mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 13:00:42 -07:00
commit
398da9eb0b
3 changed files with 226 additions and 0 deletions
|
@ -646,6 +646,7 @@ static command_t CommandTable[] = {
|
||||||
{"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"},
|
{"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"},
|
||||||
{"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"},
|
{"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"},
|
||||||
{"4x05_unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"},
|
{"4x05_unlock", CmdEM4x05Unlock, IfPm3Lf, "execute tear off against EM4x05/EM4x69"},
|
||||||
|
{"4x05_sniff", CmdEM4x05Sniff, IfPm3Lf, "Attempt to recover em4x05 commands from sample buffer"},
|
||||||
{"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"},
|
{"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"},
|
||||||
{"4x50_dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"},
|
{"4x50_dump", CmdEM4x50Dump, IfPm3EM4x50, "dump EM4x50 tag"},
|
||||||
{"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"},
|
{"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "tag information EM4x50"},
|
||||||
|
|
|
@ -1597,3 +1597,227 @@ int CmdEM4x05Unlock(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
return exit_code;
|
return exit_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t em4x05_Sniff_GetNextBitStart (size_t idx, size_t sc, int *data, size_t *pulsesamples)
|
||||||
|
{
|
||||||
|
while ((idx < sc) && (data[idx] <= 10)) // find a going high
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
while ((idx < sc) && (data[idx] > -10)) // find going low may need to add something here it SHOULD be a small clk around 0, but white seems to extend a bit.
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
(*pulsesamples) = 0;
|
||||||
|
while ((idx < sc) && ((data[idx+1] - data[idx]) < 10 )) { // find "sharp rise"
|
||||||
|
(*pulsesamples)++;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t static em4x05_Sniff_GetBlock (char *bits, bool fwd) {
|
||||||
|
uint32_t value = 0;
|
||||||
|
uint8_t idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < 8; idx++) {
|
||||||
|
value <<= 1;
|
||||||
|
value += (bits[idx] - '0');
|
||||||
|
}
|
||||||
|
for (idx = 9; idx < 17; idx++) {
|
||||||
|
value <<= 1;
|
||||||
|
value += (bits[idx] - '0');
|
||||||
|
}
|
||||||
|
for (idx = 18; idx < 26; idx++) {
|
||||||
|
value <<= 1;
|
||||||
|
value += (bits[idx] - '0');
|
||||||
|
}
|
||||||
|
for (idx = 27; idx < 35; idx++) {
|
||||||
|
value <<= 1;
|
||||||
|
value += (bits[idx] - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fwd) {
|
||||||
|
uint32_t t1 = value;
|
||||||
|
value = 0;
|
||||||
|
for (idx = 0; idx < 32; idx++)
|
||||||
|
value |= (((t1 >> idx) & 1) << (31 - idx));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CmdEM4x05Sniff(const char *Cmd) {
|
||||||
|
|
||||||
|
bool sampleData = true;
|
||||||
|
bool haveData = false;
|
||||||
|
size_t idx = 0;
|
||||||
|
char cmdText [100];
|
||||||
|
char dataText [100];
|
||||||
|
char blkAddr[4];
|
||||||
|
char bits[80];
|
||||||
|
int bitidx;
|
||||||
|
int ZeroWidth; // 32-42 "1" is 32
|
||||||
|
int CycleWidth;
|
||||||
|
size_t pulseSamples;
|
||||||
|
size_t pktOffset;
|
||||||
|
int i;
|
||||||
|
bool eop = false;
|
||||||
|
uint32_t tmpValue;
|
||||||
|
bool pwd = false;
|
||||||
|
bool fwd = false;
|
||||||
|
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "lf em 4x05_sniff",
|
||||||
|
"Sniff EM4x05 commands sent from a programmer",
|
||||||
|
"lf em 4x05_sniff -> sniff via lf sniff\n"
|
||||||
|
"lf em 4x05_sniff -1 -> sniff from data loaded into the buffer\n"
|
||||||
|
"lf em 4x05_sniff -r -> reverse the bit order when showing block data"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_lit0("1", "buf","Use the data in the buffer"),
|
||||||
|
arg_lit0("r", "rev", "Reverse the bit order for data blocks"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
|
sampleData = !arg_get_lit(ctx,1);
|
||||||
|
fwd = arg_get_lit(ctx,2);
|
||||||
|
|
||||||
|
// setup and sample data from Proxmark
|
||||||
|
// if not directed to existing sample/graphbuffer
|
||||||
|
if (sampleData) {
|
||||||
|
CmdLFSniff("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Headings
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
PrintAndLogEx(INFO, _CYAN_("EM4x05 command detection"));
|
||||||
|
PrintAndLogEx(SUCCESS, "offset | Command | Data | blk | raw");
|
||||||
|
PrintAndLogEx(SUCCESS, "-------+-------------+----------+-----+------------------------------------------------------------");
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
// loop though sample buffer
|
||||||
|
while (idx < GraphTraceLen) {
|
||||||
|
eop = false;
|
||||||
|
haveData = false;
|
||||||
|
pwd = false;
|
||||||
|
|
||||||
|
idx = em4x05_Sniff_GetNextBitStart (idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||||
|
pktOffset = idx;
|
||||||
|
if (pulseSamples >= 10) { // Should be 18 so a bit less to allow for processing
|
||||||
|
|
||||||
|
// Use first bit to get "0" bit samples as a reference
|
||||||
|
ZeroWidth = idx;
|
||||||
|
idx = em4x05_Sniff_GetNextBitStart (idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||||
|
ZeroWidth = idx - ZeroWidth;
|
||||||
|
|
||||||
|
// printf ("Zero width after 2 0 bits : %llu 0 Zero width %d\n",idx,ZeroWidth);
|
||||||
|
|
||||||
|
if (ZeroWidth <= 50) {
|
||||||
|
pktOffset -= ZeroWidth;
|
||||||
|
// ZeroSamples = 0;
|
||||||
|
memset(bits,0x00,sizeof(bits));
|
||||||
|
bitidx = 0;
|
||||||
|
|
||||||
|
while ((idx < GraphTraceLen) && !eop) {
|
||||||
|
CycleWidth = idx;
|
||||||
|
idx = em4x05_Sniff_GetNextBitStart (idx, GraphTraceLen, GraphBuffer, &pulseSamples);
|
||||||
|
|
||||||
|
CycleWidth = idx - CycleWidth;
|
||||||
|
if ((CycleWidth > 300) || (CycleWidth < (ZeroWidth-5))) { // to long or too short
|
||||||
|
eop = true;
|
||||||
|
bits[bitidx++] = '0'; // Append last zero from the last bit find
|
||||||
|
cmdText[0] = 0;
|
||||||
|
// Memo6->Lines->Add("Bit widths... : "+T1);
|
||||||
|
// EM4305 command lengths
|
||||||
|
// Login 0011 <pwd> => 4 + 45 => 49
|
||||||
|
// Write Word 0101 <adr> <data> => 4 + 7 + 45 => 56
|
||||||
|
// Read Word 1001 <adr> => 4 + 7 => 11
|
||||||
|
// Protect 1100 <data> => 4 + 45 => 49
|
||||||
|
// Disable 1010 <data> => 4 + 45 => 49
|
||||||
|
// -> disaable 1010 11111111 0 11111111 0 11111111 0 11111111 0 00000000 0
|
||||||
|
|
||||||
|
// logon
|
||||||
|
if ((strncmp (bits,"0011",4) == 0) && (bitidx == 49)) {
|
||||||
|
haveData = true;
|
||||||
|
pwd = true;
|
||||||
|
sprintf (cmdText,"Logon");
|
||||||
|
sprintf (blkAddr," ");
|
||||||
|
tmpValue = em4x05_Sniff_GetBlock (&bits[4], fwd);
|
||||||
|
sprintf (dataText,"%08X",tmpValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write
|
||||||
|
if ((strncmp (bits,"0101",4) == 0) && (bitidx == 56)) {
|
||||||
|
haveData = true;
|
||||||
|
sprintf (cmdText,"Write");
|
||||||
|
tmpValue = 0;
|
||||||
|
tmpValue = (bits[4] - '0') + ((bits[5] - '0') << 1) + ((bits[6] - '0') << 2) + ((bits[7] - '0') << 3);
|
||||||
|
sprintf (blkAddr,"%d",tmpValue);
|
||||||
|
if (tmpValue == 2)
|
||||||
|
pwd = true;
|
||||||
|
tmpValue = em4x05_Sniff_GetBlock (&bits[11], fwd);
|
||||||
|
sprintf (dataText,"%08X",tmpValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write 2 test
|
||||||
|
if ((strncmp (bits,"00101",5) == 0) && (bitidx == 57)) {
|
||||||
|
haveData = true;
|
||||||
|
sprintf (cmdText,"Write");
|
||||||
|
tmpValue = 0;
|
||||||
|
tmpValue = (bits[5] - '0') + ((bits[6] - '0') << 1) + ((bits[7] - '0') << 2) + ((bits[8] - '0') << 3);
|
||||||
|
sprintf (blkAddr,"%d",tmpValue);
|
||||||
|
if (tmpValue == 2)
|
||||||
|
pwd = true;
|
||||||
|
tmpValue = em4x05_Sniff_GetBlock (&bits[12], fwd);
|
||||||
|
sprintf (dataText,"%08X",tmpValue);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
if ((Bits.SubString(1,4) == "1001") && (Bits.Length() == 11)) {
|
||||||
|
Addr = Bits.SubString(5,7);
|
||||||
|
Data = "";
|
||||||
|
Memo6->Lines->Add("Read : "+Addr+" "+Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Bits.SubString(1,4) == "1100") && (Bits.Length() == 49)) {
|
||||||
|
Addr = "";
|
||||||
|
Data = Bits.SubString(5,45);
|
||||||
|
Memo6->Lines->Add("Protect : "+Addr+" "+Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((Bits.SubString(1,4) == "1010") && (Bits.Length() == 49)) {
|
||||||
|
Addr = "";
|
||||||
|
Data = Bits.SubString(5,45);
|
||||||
|
Memo6->Lines->Add("Disable : "+Addr+" "+Data);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// Memo6->Lines->Add("Raw : "+Bits);
|
||||||
|
bits[bitidx] = 0;
|
||||||
|
// printf ("%s\n",bits);
|
||||||
|
} else {
|
||||||
|
i = (CycleWidth - ZeroWidth) / 30;
|
||||||
|
bits[bitidx++] = '0';
|
||||||
|
for (int ii = 0; ii < i; ii++)
|
||||||
|
bits[bitidx++] = '1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
// Print results
|
||||||
|
if (haveData) { //&& (minWidth > 1) && (maxWidth > minWidth)){
|
||||||
|
if (pwd)
|
||||||
|
PrintAndLogEx(SUCCESS, "%6llu | %-10s | "_YELLOW_("%8s")" | "_YELLOW_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
|
||||||
|
else
|
||||||
|
PrintAndLogEx(SUCCESS, "%6llu | %-10s | "_GREEN_("%8s")" | "_GREEN_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// footer
|
||||||
|
PrintAndLogEx(SUCCESS, "---------------------------------------------------------------------------------------------------");
|
||||||
|
PrintAndLogEx(NORMAL, "");
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -27,5 +27,6 @@ int CmdEM4x05Wipe(const char *Cmd);
|
||||||
int CmdEM4x05Info(const char *Cmd);
|
int CmdEM4x05Info(const char *Cmd);
|
||||||
int CmdEM4x05Chk(const char *Cmd);
|
int CmdEM4x05Chk(const char *Cmd);
|
||||||
int CmdEM4x05Unlock(const char *Cmd);
|
int CmdEM4x05Unlock(const char *Cmd);
|
||||||
|
int CmdEM4x05Sniff(const char *Cmd);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue