1 //-----------------------------------------------------------------------------
2 // Christian Herrmann, 2020
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
7 //-----------------------------------------------------------------------------
8 // main code for HID collector aka IceHID by Iceman
9 //-----------------------------------------------------------------------------
11 #include "standalone.h" // standalone definitions
12 #include "proxmark3_arm.h"
15 #include "lfsampling.h"
17 #include "fpgaloader.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
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) {
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
);
67 static void append(uint8_t *entry
, size_t entry_len
) {
70 if (log_exists
== false) {
71 rdv40_spiffs_write(LF_HIDCOLLECT_LOGFILE
, entry
, entry_len
, RDV40_SPIFFS_SAFETY_SAFE
);
74 rdv40_spiffs_append(LF_HIDCOLLECT_LOGFILE
, entry
, entry_len
, RDV40_SPIFFS_SAFETY_SAFE
);
79 static uint32_t IceEM410xdemod(void) {
81 uint8_t *dest
= BigBuf_get_addr();
83 int clk
= 0, invert
= 0, maxErr
= 20;
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);
99 errCnt
= Em410xDecode(dest
, &size
, &idx
, &hi
, &lo
);
106 memset(entry
, 0, sizeof(entry
));
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),
113 (uint32_t)(lo
& 0xFFFF),
114 (uint32_t)((lo
>> 16LL) & 0xFF),
115 (uint32_t)(lo
& 0xFFFFFF));
117 sprintf((char *)entry
, "EM TAG ID: %02"PRIx32
"%08"PRIx32
" - (%05"PRIu32
"_%03"PRIu32
"_%08"PRIu32
")\n",
118 (uint32_t)(lo
>> 32),
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
);
131 static uint32_t IceAWIDdemod(void) {
133 uint8_t *dest
= BigBuf_get_addr();
134 size_t size
= MIN(12800, BigBuf_max_traceLen());
137 //askdemod and manchester decode
138 int idx
= detectAWID(dest
, &size
, &dummyIdx
);
140 if (idx
<= 0 || size
!= 96) {
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);
157 memset(entry
, 0, sizeof(entry
));
159 uint8_t fmtLen
= bytebits_to_byte(dest
, 8);
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
);
166 uint32_t cardnum
= bytebits_to_byte(dest
+ 8 + (fmtLen
- 17), 16);
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
);
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
);
183 static uint32_t IceIOdemod(void) {
186 uint8_t version
= 0, facilitycode
= 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
);
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
211 memset(entry
, 0, sizeof(entry
));
213 sprintf((char *)entry
, "IO Prox XSF(%02u)%02x:%05u (%08"PRIx32
"%08"PRIx32
")\n"
221 append(entry
, strlen((char *)entry
));
222 Dbprintf("%s", entry
);
227 static uint32_t IceHIDDemod(void) {
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();
240 int idx
= HIDdemodFSK(dest
, &size
, &hi2
, &hi
, &lo
, &dummyIdx
);
246 if ((size
== 96 || size
== 192)) {
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",
261 append(entry
, strlen((char *)entry
));
263 } else { //standard HID tags 44/96 bits
266 uint32_t cardnum
= 0;
268 if (((hi
>> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used
270 lo2
= (((hi
& 31) << 12) | (lo
>> 20)); //get bits 21-37 to check for format len bit
272 while (lo2
> 1) { //find last bit set to 1 (format len bit)
280 cardnum
= (lo
>> 1) & 0xFFFF;
281 fac
= (lo
>> 17) & 0xFF;
284 cardnum
= (lo
>> 1) & 0x7FFFF;
285 fac
= ((hi
& 0xF) << 12) | (lo
>> 20);
288 cardnum
= (lo
>> 1) & 0xFFFF;
289 fac
= ((hi
& 1) << 15) | (lo
>> 17);
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
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",
310 append(entry
, strlen((char *)entry
));
313 Dbprintf("%s", entry
);
321 DbpString(_YELLOW_(" LF HID / IOprox / AWID / EM4100 collector mode") " - a.k.a IceHID (Iceman)");
326 FpgaDownloadAndGo(FPGA_BITSTREAM_LF
);
327 LFSetupFPGAForADC(LF_DIVISOR_125
, true);
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
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
)
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
);
358 if (res
== PM3_SUCCESS
) {
363 DoAcquisition_config(false, size
);
364 res
= IceAWIDdemod();
365 if (res
== PM3_SUCCESS
) {
370 DoAcquisition_config(false, size
);
372 if (res
== PM3_SUCCESS
) {
377 size
= MIN(20000, BigBuf_max_traceLen());
378 DoAcquisition_config(false, size
);
379 res
= IceEM410xdemod();
380 if (res
== PM3_SUCCESS
) {
387 rdv40_spiffs_lazy_unmount();
391 DownloadLogInstructions();
392 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);