]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdlfindala.c
Improve 'Magic' Mifare tags generation detection & hf mf c* commands magic 4k compati...
[proxmark3-svn] / client / cmdlfindala.c
CommitLineData
0fb65a26 1//-----------------------------------------------------------------------------
2//
3// This code is licensed to you under the terms of the GNU GPL, version 2 or,
4// at your option, any later version. See the LICENSE.txt file for the text of
5// the license.
6//-----------------------------------------------------------------------------
7// Low frequency Indala commands
b9957414 8// PSK1, rf/32, 64 or 224 bits (known)
0fb65a26 9//-----------------------------------------------------------------------------
10
11#include <stdio.h>
12#include <string.h>
13#include "cmdlfindala.h"
14#include "proxmark3.h"
15#include "ui.h"
16#include "graph.h"
17#include "cmdparser.h"
18#include "cmddata.h" //for g_debugMode, demodbuff cmds
19#include "lfdemod.h" //for indala26decode
20#include "util.h" //for sprint_bin_break
21#include "cmdlf.h" //for CmdLFRead
22#include "cmdmain.h" //for clearCommandBuffer
23
24static int CmdHelp(const char *Cmd);
25
26// Indala 26 bit decode
27// by marshmellow
28// optional arguments - same as PSKDemod (clock & invert & maxerr)
29int CmdIndalaDecode(const char *Cmd) {
30 int ans;
31 if (strlen(Cmd)>0) {
32 ans = PSKDemod(Cmd, 0);
33 } else { //default to RF/32
34 ans = PSKDemod("32", 0);
35 }
36
37 if (!ans) {
488d3098 38 if (g_debugMode) PrintAndLog("Error1: %i",ans);
0fb65a26 39 return 0;
40 }
41 uint8_t invert=0;
42 size_t size = DemodBufferLen;
43 int startIdx = indala26decode(DemodBuffer, &size, &invert);
44 if (startIdx < 0 || size > 224) {
488d3098 45 if (g_debugMode) PrintAndLog("Error2: %i",startIdx);
0fb65a26 46 return -1;
47 }
48 setDemodBuf(DemodBuffer, size, (size_t)startIdx);
9fe4507c 49 setClockGrid(g_DemodClock, g_DemodStartIdx + (startIdx*g_DemodClock));
0fb65a26 50 if (invert)
51 if (g_debugMode)
52 PrintAndLog("Had to invert bits");
53
54 PrintAndLog("BitLen: %d",DemodBufferLen);
55 //convert UID to HEX
56 uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
57 uid1=bytebits_to_byte(DemodBuffer,32);
58 uid2=bytebits_to_byte(DemodBuffer+32,32);
59 if (DemodBufferLen==64) {
60 PrintAndLog("Indala UID=%s (%x%08x)", sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2);
61 } else if (DemodBufferLen==224) {
62 uid3=bytebits_to_byte(DemodBuffer+64,32);
63 uid4=bytebits_to_byte(DemodBuffer+96,32);
64 uid5=bytebits_to_byte(DemodBuffer+128,32);
65 uid6=bytebits_to_byte(DemodBuffer+160,32);
66 uid7=bytebits_to_byte(DemodBuffer+192,32);
67 PrintAndLog("Indala UID=%s (%x%08x%08x%08x%08x%08x%08x)",
68 sprint_bin_break(DemodBuffer,DemodBufferLen,16), uid1, uid2, uid3, uid4, uid5, uid6, uid7);
69 }
70 if (g_debugMode) {
71 PrintAndLog("DEBUG: printing demodbuffer:");
72 printDemodBuff();
73 }
74 return 1;
75}
76
77int CmdIndalaRead(const char *Cmd) {
b9957414 78 lf_read(true, 30000);
0fb65a26 79 return CmdIndalaDecode("");
80}
81
82// older alternative indala demodulate (has some positives and negatives)
83// returns false positives more often - but runs against more sets of samples
84// poor psk signal can be difficult to demod this approach might succeed when the other fails
85// but the other appears to currently be more accurate than this approach most of the time.
86int CmdIndalaDemod(const char *Cmd) {
87 // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
88
89 int state = -1;
90 int count = 0;
91 int i, j;
92
93 // worst case with GraphTraceLen=64000 is < 4096
94 // under normal conditions it's < 2048
95
96 uint8_t rawbits[4096];
97 int rawbit = 0;
98 int worst = 0, worstPos = 0;
0e2ddb41 99
100 //clear clock grid and demod plot
101 setClockGrid(0, 0);
102 DemodBufferLen = 0;
0fb65a26 103
0e2ddb41 104 // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
0fb65a26 105 // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2)
106 for (i = 0; i < GraphTraceLen-1; i += 2) {
107 count += 1;
108 if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
109 // appears redundant - marshmellow
110 if (state == 0) {
111 for (j = 0; j < count - 8; j += 16) {
112 rawbits[rawbit++] = 0;
113 }
114 if ((abs(count - j)) > worst) {
115 worst = abs(count - j);
116 worstPos = i;
117 }
118 }
119 state = 1;
120 count = 0;
121 } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
122 //appears redundant
123 if (state == 1) {
124 for (j = 0; j < count - 8; j += 16) {
125 rawbits[rawbit++] = 1;
126 }
127 if ((abs(count - j)) > worst) {
128 worst = abs(count - j);
129 worstPos = i;
130 }
131 }
132 state = 0;
133 count = 0;
134 }
135 }
136
137 if (rawbit>0){
138 PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
139 PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
140 } else {
141 return 0;
142 }
143
144 // Finding the start of a UID
145 int uidlen, long_wait;
146 if (strcmp(Cmd, "224") == 0) {
147 uidlen = 224;
148 long_wait = 30;
149 } else {
150 uidlen = 64;
151 long_wait = 29;
152 }
153
154 int start;
155 int first = 0;
156 for (start = 0; start <= rawbit - uidlen; start++) {
157 first = rawbits[start];
158 for (i = start; i < start + long_wait; i++) {
159 if (rawbits[i] != first) {
160 break;
161 }
162 }
163 if (i == (start + long_wait)) {
164 break;
165 }
166 }
167
168 if (start == rawbit - uidlen + 1) {
169 PrintAndLog("nothing to wait for");
170 return 0;
171 }
172
173 // Inverting signal if needed
174 if (first == 1) {
175 for (i = start; i < rawbit; i++) {
176 rawbits[i] = !rawbits[i];
177 }
178 }
179
180 // Dumping UID
181 uint8_t bits[224] = {0x00};
182 char showbits[225] = {0x00};
183 int bit;
184 i = start;
185 int times = 0;
186
187 if (uidlen > rawbit) {
188 PrintAndLog("Warning: not enough raw bits to get a full UID");
189 for (bit = 0; bit < rawbit; bit++) {
190 bits[bit] = rawbits[i++];
191 // As we cannot know the parity, let's use "." and "/"
192 showbits[bit] = '.' + bits[bit];
193 }
194 showbits[bit+1]='\0';
195 PrintAndLog("Partial UID=%s", showbits);
196 return 0;
197 } else {
198 for (bit = 0; bit < uidlen; bit++) {
199 bits[bit] = rawbits[i++];
200 showbits[bit] = '0' + bits[bit];
201 }
202 times = 1;
203 }
204
205 //convert UID to HEX
206 uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
207 int idx;
208 uid1 = uid2 = 0;
209
210 if (uidlen==64){
211 for( idx=0; idx<64; idx++) {
212 if (showbits[idx] == '0') {
213 uid1=(uid1<<1)|(uid2>>31);
214 uid2=(uid2<<1)|0;
215 } else {
216 uid1=(uid1<<1)|(uid2>>31);
217 uid2=(uid2<<1)|1;
218 }
219 }
220 PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
221 }
222 else {
223 uid3 = uid4 = uid5 = uid6 = uid7 = 0;
224
225 for( idx=0; idx<224; idx++) {
226 uid1=(uid1<<1)|(uid2>>31);
227 uid2=(uid2<<1)|(uid3>>31);
228 uid3=(uid3<<1)|(uid4>>31);
229 uid4=(uid4<<1)|(uid5>>31);
230 uid5=(uid5<<1)|(uid6>>31);
231 uid6=(uid6<<1)|(uid7>>31);
232
233 if (showbits[idx] == '0')
234 uid7 = (uid7<<1) | 0;
235 else
236 uid7 = (uid7<<1) | 1;
237 }
238 PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
239 }
240
241 // Checking UID against next occurrences
242 int failed = 0;
243 for (; i + uidlen <= rawbit;) {
244 failed = 0;
245 for (bit = 0; bit < uidlen; bit++) {
246 if (bits[bit] != rawbits[i++]) {
247 failed = 1;
248 break;
249 }
250 }
251 if (failed == 1) {
252 break;
253 }
254 times += 1;
255 }
256
257 PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
258
259 // Remodulating for tag cloning
260 // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod)
261 // since this changes graphbuffer data.
262 GraphTraceLen = 32*uidlen;
263 i = 0;
264 int phase = 0;
265 for (bit = 0; bit < uidlen; bit++) {
266 if (bits[bit] == 0) {
267 phase = 0;
268 } else {
269 phase = 1;
270 }
271 int j;
272 for (j = 0; j < 32; j++) {
273 GraphBuffer[i++] = phase;
274 phase = !phase;
275 }
276 }
277
278 RepaintGraphWindow();
279 return 1;
280}
281
282int CmdIndalaClone(const char *Cmd) {
283 UsbCommand c;
284 unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
285
286 uid1 = uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
287 int n = 0, i = 0;
288
289 if (strchr(Cmd,'l') != 0) {
290 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
291 uid1 = (uid1 << 4) | (uid2 >> 28);
292 uid2 = (uid2 << 4) | (uid3 >> 28);
293 uid3 = (uid3 << 4) | (uid4 >> 28);
294 uid4 = (uid4 << 4) | (uid5 >> 28);
295 uid5 = (uid5 << 4) | (uid6 >> 28);
296 uid6 = (uid6 << 4) | (uid7 >> 28);
297 uid7 = (uid7 << 4) | (n & 0xf);
298 }
299 PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
300 c.cmd = CMD_INDALA_CLONE_TAG_L;
301 c.d.asDwords[0] = uid1;
302 c.d.asDwords[1] = uid2;
303 c.d.asDwords[2] = uid3;
304 c.d.asDwords[3] = uid4;
305 c.d.asDwords[4] = uid5;
306 c.d.asDwords[5] = uid6;
307 c.d.asDwords[6] = uid7;
308 } else {
309 while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
310 uid1 = (uid1 << 4) | (uid2 >> 28);
311 uid2 = (uid2 << 4) | (n & 0xf);
312 }
313 PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
314 c.cmd = CMD_INDALA_CLONE_TAG;
315 c.arg[0] = uid1;
316 c.arg[1] = uid2;
317 }
318
319 clearCommandBuffer();
320 SendCommand(&c);
321 return 0;
322}
323
324static command_t CommandTable[] = {
325 {"help", CmdHelp, 1, "This help"},
326 {"demod", CmdIndalaDecode, 1, "[clock] [invert<0|1>] -- Demodulate an indala tag (PSK1) from GraphBuffer (args optional)"},
327 {"read", CmdIndalaRead, 0, "Read an Indala Prox tag from the antenna"},
328 {"clone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be on antenna)(UID in HEX)(option 'l' for 224 UID"},
329 {"altdemod", CmdIndalaDemod, 1, "['224'] -- Alternative method to Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
330 //{"sim", CmdIndalaSim, 0, "<ID> -- indala tag simulator"},
331 {NULL, NULL, 0, NULL}
332};
333
334int CmdLFINDALA(const char *Cmd) {
335 CmdsParse(CommandTable, Cmd);
336 return 0;
337}
338
339int CmdHelp(const char *Cmd) {
340 CmdsHelp(CommandTable);
341 return 0;
342}
Impressum, Datenschutz