Merge pull request #2741 from Donny-Guo/hidbrute
[RRG-proxmark3.git] / armsrc / Standalone / lf_em4100rswb.c
blobc5fd61475204078d79b4dd317e4eb86919270a71
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2020 Dmitriy Loginoov
3 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // See LICENSE.txt for the text of the license.
16 //-----------------------------------------------------------------------------
17 // LF rswb - This mode can simulate ID from selected slot, read ID to
18 // selected slot, write from selected slot to T5555/T55x7 tag and store
19 // read ID to flash (only RDV4).
20 // Predefining it is not recommended because you can incidentally rewrite your MANDATORY tag data.
22 // To recall stored ID from flash execute:
23 // mem spifss dump o emdump p
24 // or:
25 // mem spifss dump o emdump f emdump
26 // then from shell:
27 // hexdump emdump -e '5/1 "%02X" /0 "\n"'
29 // Mode list (switched by single click):
31 // 0 - READ Read source card ID and store it to current slot
32 // Will switch to SIM mode automatically.
34 // 1 - SIM Simulate read ID
36 // 2 - WRITE(CLONE) Write read ID to T55x7 card
37 // !!! Warning, card id WILL BE OVERWRITTEN
39 // 3 - BRUTE Brute upper or down from read card)
40 // You can PRESS SINGLE to exit brute mode OR
41 // PRESS DOUBLE to save bruted ID to current slot (will automatically switch to SIM mode) AND
42 // Also You can HOLD button to change brute speeds.
44 // Slots are switched by HOLD (LONG PRESS)
45 //-----------------------------------------------------------------------------
46 #include "standalone.h"
47 #include "proxmark3_arm.h"
48 #include "appmain.h"
49 #include "fpgaloader.h"
50 #include "util.h"
51 #include "dbprint.h"
52 #include "ticks.h"
53 #include "string.h"
54 #include "BigBuf.h"
55 #include "spiffs.h"
56 #include "inttypes.h"
57 #include "parity.h"
58 #include "lfops.h"
60 #ifdef WITH_FLASH
61 #include "flashmem.h"
62 #endif
64 #define LF_CLOCK 64 // for 125kHz
65 #define LF_RWSB_T55XX_TYPE 1 // Tag type: 0 - T5555, 1-T55x7, 2-EM4x05
67 #define LF_RWSB_UNKNOWN_RESULT 0
68 #define LF_RWSB_BRUTE_STOPED 1
69 #define LF_RWSB_BRUTE_SAVED 2
71 //modes
72 #define LF_RWSB_MODE_READ 0
73 #define LF_RWSB_MODE_SIM 1
74 #define LF_RWSB_MODE_WRITE 2
75 #define LF_RWSB_MODE_BRUTE 3
77 // Predefined bruteforce speed
78 // avg: 1s, 1.2s, 1.5s, 2s
79 static int em4100rswb_bruteforceSpeedCurrent = 1;
80 static int em4100rswb_bruteforceSpeed[] = {10, 12, 14, 16};
82 // em4100rswb_low & em4100rswb_high - array for storage IDs. Its length must be equal.
83 // Predefined IDs must be stored in em4100rswb_low[].
84 // In em4100rswb_high[] must be nulls
85 static uint64_t em4100rswb_low[] = {0, 0, 0, 0};
86 static uint32_t em4100rswb_high[] = {0, 0, 0, 0};
87 static int em4100rswb_buflen;
89 void ModInfo(void) {
90 DbpString(" LF EM4100 read/sim/write/brute mode");
93 static uint64_t rev_quads(uint64_t bits) {
94 uint64_t result = 0;
95 for (int i = 0; i < 16; i++) {
96 result += ((bits >> (60 - 4 * i)) & 0xf) << (4 * i);
98 return result >> 24;
101 static void fill_buff(uint8_t bit) {
102 uint8_t *bba = BigBuf_get_addr();
103 memset(bba + em4100rswb_buflen, bit, LF_CLOCK / 2);
104 em4100rswb_buflen += (LF_CLOCK / 2);
105 memset(bba + em4100rswb_buflen, bit ^ 1, LF_CLOCK / 2);
106 em4100rswb_buflen += (LF_CLOCK / 2);
109 static void construct_EM410x_emul(uint64_t id) {
110 int i, j;
111 int binary[4] = {0, 0, 0, 0};
112 int parity[4] = {0, 0, 0, 0};
113 em4100rswb_buflen = 0;
115 for (i = 0; i < 9; i++)
116 fill_buff(1);
118 for (i = 0; i < 10; i++) {
119 for (j = 3; j >= 0; j--, id /= 2)
120 binary[j] = id % 2;
122 for (j = 0; j < 4; j++)
123 fill_buff(binary[j]);
125 fill_buff(binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
126 for (j = 0; j < 4; j++)
127 parity[j] ^= binary[j];
130 for (j = 0; j < 4; j++)
131 fill_buff(parity[j]);
133 fill_buff(0);
136 static void LED_Update(int mode, int slot) {
137 LEDsoff();
138 switch (mode) {
139 case 0:
140 break;
141 case 1:
142 LED_A_ON();
143 break;
144 case 2:
145 LED_B_ON();
146 break;
147 case 3:
148 LED_A_ON();
149 LED_B_ON();
150 break;
152 switch (slot) {
153 case 0:
154 break;
155 case 1:
156 LED_C_ON();
157 break;
158 case 2:
159 LED_D_ON();
160 break;
161 case 3:
162 LED_C_ON();
163 LED_D_ON();
164 break;
168 static void FlashLEDs(uint32_t speed, uint8_t times) {
169 for (int i = 0; i < times * 2; i++) {
170 LED_A_INV();
171 LED_B_INV();
172 LED_C_INV();
173 LED_D_INV();
174 SpinDelay(speed);
178 #ifdef WITH_FLASH
179 static void SaveIDtoFlash(int addr, uint64_t id) {
180 uint8_t bt[5];
181 char *filename = "emdump";
182 rdv40_spiffs_mount();
183 for (int i = 0; i < 5; i++) {
184 bt[4 - i] = (uint8_t)(id >> 8 * i & 0xff);
186 if (exists_in_spiffs(filename) == false) {
187 rdv40_spiffs_write(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
188 } else {
189 rdv40_spiffs_append(filename, &bt[0], 5, RDV40_SPIFFS_SAFETY_NORMAL);
192 #endif
194 static uint64_t PackEmID(uint64_t original, int newCardNum) {
195 uint64_t buf = original;
196 //clear pairity bits
197 buf &= ~(1 << 0);
198 buf &= ~(1 << 25);
199 //clear card number
200 for (int i = 1; i <= 16; i++) {
201 buf &= ~(1 << i);
203 buf |= (newCardNum & 0xFFFF) << 1;
204 buf |= oddparity32((buf >> 1) & 0xFFF);
205 buf |= (evenparity32((buf >> 13) & 0xFFF)) << 25;
207 uint32_t cardnumNew = (buf >> 1) & 0xFFFF;
208 uint32_t fcNew = (buf >> 17) & 0xFF;
209 Dbprintf("[=] RECONSTRUCT TAG ID: %"PRIx64" - FC: %u - Card: %u\n", buf, fcNew, cardnumNew);
210 return buf;
213 static void PrintFcAndCardNum(uint64_t lowData) {
214 // Calculate Facility Code and Card Number from high and low
215 uint32_t fc = (lowData >> 17) & 0xFF;
216 uint32_t cardnum = (lowData >> 1) & 0xFFFF;
217 Dbprintf("[=] READ TAG ID: %"PRIx64" - FC: %u - Card: %u", lowData, fc, cardnum);
220 static int BruteEMTag(uint64_t originalCard, int slot) {
221 int speed_count = 4;
223 int direction = 1;
225 uint32_t cardnum = (originalCard >> 1) & 0xFFFF;
226 if (cardnum > 32767) {
227 direction = -1;
230 while (cardnum > 1 && cardnum < 65535) {
231 WDT_HIT();
232 if (data_available()) break;
234 cardnum = cardnum + direction;
235 uint64_t currentCard = PackEmID(originalCard, cardnum);
236 Dbprintf("[=] >> Simulating card id %"PRIx64" <<", currentCard);
237 construct_EM410x_emul(rev_quads(currentCard));
238 SimulateTagLowFrequencyEx(em4100rswb_buflen, 0, 1, em4100rswb_bruteforceSpeed[em4100rswb_bruteforceSpeedCurrent] * 10000);
240 int button_pressed = BUTTON_CLICKED(1000);
241 if (button_pressed == BUTTON_SINGLE_CLICK) {
242 Dbprintf("[=] >> Exit bruteforce mode without saving. <<");
243 return LF_RWSB_BRUTE_STOPED;
244 } else if (button_pressed == BUTTON_DOUBLE_CLICK) {
245 FlashLEDs(100, 10);
246 Dbprintf("[=] >> Saving bruteforced card to current slot <<");
247 em4100rswb_low[slot] = currentCard;
248 #ifdef WITH_FLASH
249 SaveIDtoFlash(slot, em4100rswb_low[slot]);
250 #endif
251 return LF_RWSB_BRUTE_SAVED;
252 } else if (button_pressed == BUTTON_HOLD) {
253 FlashLEDs(100, 1);
254 WAIT_BUTTON_RELEASED();
255 em4100rswb_bruteforceSpeedCurrent = (em4100rswb_bruteforceSpeedCurrent + 1) % speed_count;
256 FlashLEDs(100, em4100rswb_bruteforceSpeedCurrent + 1);
257 Dbprintf("[=] >> Setting speed to %d (%d) <<", em4100rswb_bruteforceSpeedCurrent, em4100rswb_bruteforceSpeed[em4100rswb_bruteforceSpeedCurrent]);
260 return LF_RWSB_BRUTE_STOPED;
263 static int ExecuteMode(int mode, int slot) {
264 LED_Update(mode, slot);
265 WDT_HIT();
267 switch (mode) {
268 //default first mode is simulate
269 case LF_RWSB_MODE_READ:
270 Dbprintf("[=] >> Read mode started <<");
271 lf_em410x_watch(1, &em4100rswb_high[slot], &em4100rswb_low[slot], true);
272 LED_Update(mode, slot);
273 Dbprintf("[=] >> Tag found. Saving. <<");
274 FlashLEDs(100, 5);
275 PrintFcAndCardNum(em4100rswb_low[slot]);
276 #ifdef WITH_FLASH
277 SaveIDtoFlash(slot, em4100rswb_low[slot]);
278 #endif
279 return LF_RWSB_UNKNOWN_RESULT;
280 case LF_RWSB_MODE_SIM:
281 Dbprintf("[=] >> Sim mode started <<");
282 construct_EM410x_emul(rev_quads(em4100rswb_low[slot]));
283 SimulateTagLowFrequency(em4100rswb_buflen, 0, true);
284 return LF_RWSB_UNKNOWN_RESULT;
285 case LF_RWSB_MODE_WRITE:
286 Dbprintf("[!!] >> Write mode started <<");
287 copy_em410x_to_t55xx(LF_RWSB_T55XX_TYPE
288 , LF_CLOCK
289 , (uint32_t)(em4100rswb_low[slot] >> 32)
290 , (uint32_t)(em4100rswb_low[slot] & 0xffffffff)
291 , false
292 , true
294 return LF_RWSB_UNKNOWN_RESULT;
295 case LF_RWSB_MODE_BRUTE:
296 Dbprintf("[=] >> Bruteforce mode started <<");
297 return BruteEMTag(em4100rswb_low[slot], slot);
299 return LF_RWSB_UNKNOWN_RESULT;
302 static int SwitchMode(int mode, int slot) {
303 WDT_HIT();
304 ExecuteMode(mode, slot);
306 if (mode == LF_RWSB_MODE_READ) {
307 //After read mode we need to switch to sim mode automatically
308 Dbprintf("[=] >> automatically switch to sim mode after read <<");
310 return SwitchMode(LF_RWSB_MODE_SIM, slot);
311 } else if (mode == LF_RWSB_MODE_BRUTE) {
312 //We have already have a click inside brute mode. Lets switch next mode
313 Dbprintf("[=] >> automatically switch to read mode after brute <<");
315 return SwitchMode(LF_RWSB_MODE_READ, slot);
317 return mode;
320 void RunMod() {
321 StandAloneMode();
322 FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
323 Dbprintf("[=] >> LF EM4100 read/write/clone/brute started <<");
324 int slots_count = 4;
325 int mode_count = 4;
327 int mode = 0;
328 int slot = 0;
329 mode = SwitchMode(mode, slot);
331 for (;;) {
332 WDT_HIT();
333 if (data_available()) break;
335 int button_pressed = BUTTON_CLICKED(1000);
336 LED_Update(mode, slot);
338 //press button - switch mode
339 //hold button - switch slot
340 if (button_pressed == BUTTON_SINGLE_CLICK) {
341 Dbprintf("[=] >> Single click <<");
342 mode = (mode + 1) % mode_count;
343 SpinDown(100);
345 mode = SwitchMode(mode, slot);
346 } else if (button_pressed == BUTTON_HOLD) {
347 Dbprintf("[=] >> Button hold <<");
348 slot = (slot + 1) % slots_count;
349 SpinUp(100);
350 SpinDelay(300);
352 //automatically switch to SIM mode on slot selection
353 mode = LF_RWSB_MODE_SIM;
354 mode = SwitchMode(mode, slot);