Files
nfc-pn532-warlord/web/src/pages/Brute.tsx
drjones 8968560565 Add PN532 toolkit firmware, web UI, and embedded SPIFFS assets
Includes ESP-IDF NFC stack (deep capture, 4K Classic geometry, UL write API,
open SoftAP), React dashboard with live tag diagnostics, and docs. README
updated for APIs and lab Wi-Fi defaults.

Made-with: Cursor
2026-03-29 09:32:55 -07:00

114 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from "react";
import { apiUrl } from "../api";
import { useToast } from "../toast";
export default function Brute() {
const toast = useToast();
const [reader, setReader] = useState<"classic1k" | "classic4k">("classic1k");
const [variations, setVariations] = useState(true);
const [extraKeys, setExtraKeys] = useState(
"FFFFFFFFFFFF\nA0A1A2A3A4A5\nD3F7D3F7D3F7",
);
const [busy, setBusy] = useState(false);
const [result, setResult] = useState<string>("");
const run = async () => {
setBusy(true);
setResult("");
try {
const keysHex = extraKeys
.split(/\r?\n/)
.map((l) => l.replace(/\s/g, "").toUpperCase())
.filter((l) => l.length === 12);
const body = {
readerType: reader,
variations,
keysHex,
};
const r = await fetch(apiUrl("/api/mifare/dictionary-attack"), {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
});
const text = await r.text();
if (!r.ok) {
throw new Error(text);
}
try {
const j = JSON.parse(text) as object;
setResult(JSON.stringify(j, null, 2));
} catch {
setResult(text);
}
toast("Dictionary pass finished");
} catch (e) {
toast(String(e), "err");
} finally {
setBusy(false);
}
};
return (
<div className="glass space-y-6 p-6">
<h1 className="font-display text-2xl font-bold">Dictionary attack</h1>
<p className="text-sm text-slate-400">
Select card family, optionally enable <strong>bounded variations</strong> (XOR / low-nibble tweaks per
key). Firmware tries a <strong>built-in community list</strong> (Proxmark3 / MCT-style defaults) plus
your lines below. This is <strong>not</strong> a full 2 exhaustive search only keys you and the
community already know. Hold a <strong>MIFARE Classic</strong> on the coil.{" "}
<a
className="text-bubble-mint underline"
href="https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_default_keys.dic"
target="_blank"
rel="noreferrer"
>
More keys online
</a>
.
</p>
<label className="block text-sm">
Reader / map
<select
value={reader}
onChange={(e) => setReader(e.target.value as "classic1k" | "classic4k")}
className="mt-1 w-full rounded-2xl border border-white/10 bg-black/25 px-4 py-2"
>
<option value="classic1k">MIFARE Classic 1K (sectors 015)</option>
<option value="classic4k">MIFARE Classic 4K (sectors 039, proper 4/16-block geometry)</option>
</select>
</label>
<label className="flex items-center gap-2 text-sm">
<input type="checkbox" checked={variations} onChange={(e) => setVariations(e.target.checked)} />
Variations (extra tries per key slower, wider net)
</label>
<label className="block text-sm">
Extra keys (one 12-hex key per line, merged after built-in list)
<textarea
value={extraKeys}
onChange={(e) => setExtraKeys(e.target.value)}
rows={6}
className="mt-1 w-full rounded-2xl border border-white/10 bg-black/25 p-3 font-mono text-xs"
/>
</label>
<button
type="button"
disabled={busy}
onClick={run}
className="rounded-2xl bg-gradient-to-r from-bubble-rose to-orange-500 px-6 py-3 font-bold text-white disabled:opacity-50"
>
{busy ? "Running…" : "Run dictionary attack"}
</button>
{result && (
<pre className="max-h-96 overflow-auto rounded-2xl border border-white/10 bg-black/40 p-4 text-xs text-bubble-mint">
{result}
</pre>
)}
</div>
);
}