Merge branch 'master' of github.com:RfidResearchGroup/proxmark3
[RRG-proxmark3.git] / armsrc / Standalone / lf_icehid.c
blob0b1e6cbfeabdc7fbc3d8c61c41e8e9a1fcda33c2
1 //-----------------------------------------------------------------------------
2 // Christian Herrmann, 2020
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // main code for HID collector aka IceHID by Iceman
9 //-----------------------------------------------------------------------------
10 #include <inttypes.h>
11 #include "standalone.h" // standalone definitions
12 #include "proxmark3_arm.h"
13 #include "appmain.h"
14 #include "lfops.h"
15 #include "lfsampling.h"
16 #include "BigBuf.h"
17 #include "fpgaloader.h"
18 #include "util.h"
19 #include "dbprint.h"
20 #include "printf.h"
21 #include "spiffs.h"
22 #include "ticks.h"
23 #include "lfdemod.h"
25 * `lf_hidcollect` sniffs after LF HID credentials, and stores them in internal
26 * flash. It requires RDV4 hardware (for flash and battery).
28 * On entering stand-alone mode, this module will start reading/record HID credentials.
29 * Every found / collected credential will be written/appended to the logfile in flash
30 * as a text string.
32 * LEDs:
33 * - LED A: reading / record
34 * - LED B: writing to flash
35 * - LED C: unmounting/sync'ing flash (normally < 100ms)
37 * To retrieve log file from flash:
39 * 1. mem spiffs dump -s lf_hidcollect.log -d lf_hidcollect.log
40 * Copies log file from flash to your client.
42 * 2. exit the Proxmark3 client
44 * 3. more lf_hidcollect.log
46 * This module emits debug strings during normal operation -- so try it out in
47 * the lab connected to PM3 client before taking it into the field.
49 * To delete the log file from flash:
51 * 1. mem spiffs remove -f lf_hidcollect.log
54 #define LF_HIDCOLLECT_LOGFILE "lf_hidcollect.log"
57 static void DownloadLogInstructions(void) {
58 Dbprintf("");
59 Dbprintf("[=] To get the logfile from flash and display it:");
60 Dbprintf("[=] " _YELLOW_("1.") " mem spiffs dump -s "LF_HIDCOLLECT_LOGFILE" -d "LF_HIDCOLLECT_LOGFILE);
61 Dbprintf("[=] " _YELLOW_("2.") " exit proxmark3 client");
62 Dbprintf("[=] " _YELLOW_("3.") " cat "LF_HIDCOLLECT_LOGFILE);
65 bool log_exists;
67 static void append(uint8_t *entry, size_t entry_len) {
69 LED_B_ON();
70 if (log_exists == false) {
71 rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
72 log_exists = true;
73 } else {
74 rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE, entry, entry_len, RDV40_SPIFFS_SAFETY_SAFE);
76 LED_B_OFF();
79 static uint32_t IceEM410xdemod(void) {
81 uint8_t *dest = BigBuf_get_addr();
82 size_t idx = 0;
83 int clk = 0, invert = 0, maxErr = 20;
84 uint32_t hi = 0;
85 uint64_t lo = 0;
87 size_t size = MIN(16385, BigBuf_max_traceLen());
89 //askdemod and manchester decode
90 int errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1);
92 WDT_HIT();
94 if (errCnt > 50) {
95 BigBuf_free();
96 return PM3_ESOFT;
99 errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
100 if (errCnt != 1) {
101 BigBuf_free();
102 return PM3_ESOFT;
105 uint8_t entry[81];
106 memset(entry, 0, sizeof(entry));
108 if (size == 128) {
109 sprintf((char *)entry, "EM XL TAG ID: %06"PRIx32"%08"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n",
111 (uint32_t)(lo >> 32),
112 (uint32_t)lo,
113 (uint32_t)(lo & 0xFFFF),
114 (uint32_t)((lo >> 16LL) & 0xFF),
115 (uint32_t)(lo & 0xFFFFFF));
116 } else {
117 sprintf((char *)entry, "EM TAG ID: %02"PRIx32"%08"PRIx32" - (%05"PRIu32"_%03"PRIu32"_%08"PRIu32")\n",
118 (uint32_t)(lo >> 32),
119 (uint32_t)lo,
120 (uint32_t)(lo & 0xFFFF),
121 (uint32_t)((lo >> 16LL) & 0xFF),
122 (uint32_t)(lo & 0xFFFFFF));
125 append(entry, strlen((char *)entry));
126 Dbprintf("%s", entry);
127 BigBuf_free();
128 return PM3_SUCCESS;
131 static uint32_t IceAWIDdemod(void) {
133 uint8_t *dest = BigBuf_get_addr();
134 size_t size = MIN(12800, BigBuf_max_traceLen());
135 int dummyIdx = 0;
137 //askdemod and manchester decode
138 int idx = detectAWID(dest, &size, &dummyIdx);
140 if (idx <= 0 || size != 96) {
141 BigBuf_free();
142 return PM3_ESOFT;
145 //get raw ID before removing parities
146 uint32_t rawLo = bytebits_to_byte(dest + idx + 64, 32);
147 uint32_t rawHi = bytebits_to_byte(dest + idx + 32, 32);
148 uint32_t rawHi2 = bytebits_to_byte(dest + idx, 32);
150 size = removeParity(dest, idx + 8, 4, 1, 88);
151 if (size != 66) {
152 BigBuf_free();
153 return PM3_ESOFT;
156 uint8_t entry[110];
157 memset(entry, 0, sizeof(entry));
159 uint8_t fmtLen = bytebits_to_byte(dest, 8);
160 if (fmtLen == 26) {
161 uint8_t fac = bytebits_to_byte(dest + 9, 8);
162 uint32_t cardnum = bytebits_to_byte(dest + 17, 16);
163 uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
164 sprintf((char *)entry, "AWID bit len: %d, FC: %d, Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo);
165 } else {
166 uint32_t cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16);
167 if (fmtLen > 32) {
168 uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen - 32);
169 uint32_t code2 = bytebits_to_byte(dest + 8 + (fmtLen - 32), 32);
170 sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32"%08"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo);
171 } else {
172 uint32_t code1 = bytebits_to_byte(dest + 8, fmtLen);
173 sprintf((char *)entry, "AWID bit len: %d -unk bit len - Card: %"PRIu32" - Wiegand: %"PRIx32", Raw: %08"PRIx32"%08"PRIx32"%08"PRIx32"\n", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo);
177 append(entry, strlen((char *)entry));
178 Dbprintf("%s", entry);
179 BigBuf_free();
180 return PM3_SUCCESS;
183 static uint32_t IceIOdemod(void) {
185 int dummyIdx = 0;
186 uint8_t version = 0, facilitycode = 0;
187 uint16_t number = 0;
188 uint32_t hi = 0, lo = 0;
190 size_t size = MIN(12000, BigBuf_max_traceLen());
192 // uint8_t *dest = BigBuf_malloc(size);
193 uint8_t *dest = BigBuf_get_addr();
195 //fskdemod and get start index
196 int idx = detectIOProx(dest, &size, &dummyIdx);
198 if (idx < 0) {
199 BigBuf_free();
200 return PM3_ESOFT;
203 hi = bytebits_to_byte(dest + idx, 32);
204 lo = bytebits_to_byte(dest + idx + 32, 32);
206 version = bytebits_to_byte(dest + idx + 27, 8); //14,4
207 facilitycode = bytebits_to_byte(dest + idx + 18, 8);
208 number = (bytebits_to_byte(dest + idx + 36, 8) << 8) | (bytebits_to_byte(dest + idx + 45, 8)); //36,9
210 uint8_t entry[64];
211 memset(entry, 0, sizeof(entry));
213 sprintf((char *)entry, "IO Prox XSF(%02u)%02x:%05u (%08"PRIx32"%08"PRIx32")\n"
214 , version
215 , facilitycode
216 , number
217 , hi
218 , lo
221 append(entry, strlen((char *)entry));
222 Dbprintf("%s", entry);
223 BigBuf_free();
224 return PM3_SUCCESS;
227 static uint32_t IceHIDDemod(void) {
229 int dummyIdx = 0;
231 uint32_t hi2 = 0, hi = 0, lo = 0;
233 // large enough to catch 2 sequences of largest format
234 // size_t size = 50 * 128 * 2; // 12800 bytes
235 size_t size = MIN(12800, BigBuf_max_traceLen());
236 //uint8_t *dest = BigBuf_malloc(size);
237 uint8_t *dest = BigBuf_get_addr();
239 // FSK demodulator
240 int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx);
241 if (idx < 0) {
242 BigBuf_free();
243 return PM3_ESOFT;
246 if ((size == 96 || size == 192)) {
248 uint8_t entry[80];
249 memset(entry, 0, sizeof(entry));
251 // go over previously decoded manchester data and decode into usable tag ID
252 if (hi2 != 0) { //extra large HID tags 88/192 bits
254 sprintf((char *)entry, "HID large: %"PRIx32"%08"PRIx32"%08"PRIx32" (%"PRIu32")\n",
255 hi2,
258 (lo >> 1) & 0xFFFF
261 append(entry, strlen((char *)entry));
263 } else { //standard HID tags 44/96 bits
264 uint8_t bitlen = 0;
265 uint32_t fac = 0;
266 uint32_t cardnum = 0;
268 if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used
269 uint32_t lo2 = 0;
270 lo2 = (((hi & 31) << 12) | (lo >> 20)); //get bits 21-37 to check for format len bit
271 uint8_t idx3 = 1;
272 while (lo2 > 1) { //find last bit set to 1 (format len bit)
273 lo2 >>= 1;
274 idx3++;
276 bitlen = idx3 + 19;
277 fac = 0;
278 cardnum = 0;
279 if (bitlen == 26) {
280 cardnum = (lo >> 1) & 0xFFFF;
281 fac = (lo >> 17) & 0xFF;
283 if (bitlen == 37) {
284 cardnum = (lo >> 1) & 0x7FFFF;
285 fac = ((hi & 0xF) << 12) | (lo >> 20);
287 if (bitlen == 34) {
288 cardnum = (lo >> 1) & 0xFFFF;
289 fac = ((hi & 1) << 15) | (lo >> 17);
291 if (bitlen == 35) {
292 cardnum = (lo >> 1) & 0xFFFFF;
293 fac = ((hi & 1) << 11) | (lo >> 21);
295 } else { //if bit 38 is not set then 37 bit format is used
296 bitlen = 37;
297 cardnum = (lo >> 1) & 0x7FFFF;
298 fac = ((hi & 0xF) << 12) | (lo >> 20);
301 sprintf((char *)entry, "HID: %"PRIx32"%08"PRIx32" (%"PRIu32") Format: %d bit FC: %"PRIu32" Card: %"PRIu32"\n",
304 (lo >> 1) & 0xFFFF,
305 bitlen,
306 fac,
307 cardnum
310 append(entry, strlen((char *)entry));
313 Dbprintf("%s", entry);
316 BigBuf_free();
317 return PM3_SUCCESS;
320 void ModInfo(void) {
321 DbpString(_YELLOW_(" LF HID / IOprox / AWID / EM4100 collector mode") " - a.k.a IceHID (Iceman)");
324 void RunMod(void) {
326 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
327 LFSetupFPGAForADC(LF_DIVISOR_125, true);
328 BigBuf_Clear();
330 StandAloneMode();
332 Dbprintf(_YELLOW_("[=] Standalone mode IceHID started"));
334 rdv40_spiffs_lazy_mount();
336 log_exists = exists_in_spiffs(LF_HIDCOLLECT_LOGFILE);
338 // the main loop for your standalone mode
339 for (;;) {
340 WDT_HIT();
342 // exit from IceHID, send a usbcommand.
343 if (data_available()) break;
345 // Was our button held down or pressed?
346 int button_pressed = BUTTON_HELD(280);
347 if (button_pressed == BUTTON_HOLD)
348 break;
350 LED_A_ON();
352 uint32_t res;
354 // since we steal 12800 from bigbuffer, no need to sample it.
355 size_t size = MIN(28000, BigBuf_max_traceLen());
356 DoAcquisition_config(false, size);
357 res = IceHIDDemod();
358 if (res == PM3_SUCCESS) {
359 LED_A_OFF();
360 continue;
363 DoAcquisition_config(false, size);
364 res = IceAWIDdemod();
365 if (res == PM3_SUCCESS) {
366 LED_A_OFF();
367 continue;
370 DoAcquisition_config(false, size);
371 res = IceIOdemod();
372 if (res == PM3_SUCCESS) {
373 LED_A_OFF();
374 continue;
377 size = MIN(20000, BigBuf_max_traceLen());
378 DoAcquisition_config(false, size);
379 res = IceEM410xdemod();
380 if (res == PM3_SUCCESS) {
381 LED_A_OFF();
382 continue;
386 LED_C_ON();
387 rdv40_spiffs_lazy_unmount();
388 LED_C_OFF();
390 LEDsoff();
391 DownloadLogInstructions();
392 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);