mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 02:27:26 -07:00
CHG: command name changes..
old "hf legic info" is now "hf legic reader" old "hf legic read" is now "hf legic rdmem" old "hf legic decode" is now "hf legic info" ADD: new command "hf legic dump", which will autodetect tagtype and dump all mem to a binary file.
This commit is contained in:
parent
b9e8854a8b
commit
633d068682
5 changed files with 104 additions and 71 deletions
|
@ -140,14 +140,13 @@ static void frame_clean(struct legic_frame * const f) {
|
|||
|
||||
/* Generate Keystream */
|
||||
uint32_t get_key_stream(int skip, int count) {
|
||||
uint32_t key = 0;
|
||||
|
||||
int i;
|
||||
|
||||
// Use int to enlarge timer tc to 32bit
|
||||
legic_prng_bc += prng_timer->TC_CV;
|
||||
|
||||
// reset the prng timer.
|
||||
ResetTimer(prng_timer);
|
||||
|
||||
/* If skip == -1, forward prng time based */
|
||||
if(skip == -1) {
|
||||
|
@ -161,55 +160,41 @@ uint32_t get_key_stream(int skip, int count) {
|
|||
|
||||
i = (count == 6) ? -1 : legic_read_count;
|
||||
|
||||
/* Write Time Data into LOG */
|
||||
// uint8_t *BigBuf = BigBuf_get_addr();
|
||||
// BigBuf[OFFSET_LOG+128+i] = legic_prng_count();
|
||||
// BigBuf[OFFSET_LOG+256+i*4] = (legic_prng_bc >> 0) & 0xff;
|
||||
// BigBuf[OFFSET_LOG+256+i*4+1] = (legic_prng_bc >> 8) & 0xff;
|
||||
// BigBuf[OFFSET_LOG+256+i*4+2] = (legic_prng_bc >>16) & 0xff;
|
||||
// BigBuf[OFFSET_LOG+256+i*4+3] = (legic_prng_bc >>24) & 0xff;
|
||||
// BigBuf[OFFSET_LOG+384+i] = count;
|
||||
// log
|
||||
//uint8_t cmdbytes[] = {bits, BYTEx(data, 0), BYTEx(data, 1), BYTEx(send, 0), BYTEx(send, 1), legic_prng_count()};
|
||||
//LogTrace(cmdbytes, sizeof(cmdbytes), starttime, GET_TICKS, NULL, TRUE);
|
||||
|
||||
/* Generate KeyStream */
|
||||
for(i=0; i<count; i++) {
|
||||
key |= legic_prng_get_bit() << i;
|
||||
legic_prng_forward(1);
|
||||
}
|
||||
return key;
|
||||
return legic_prng_get_bits(count);
|
||||
}
|
||||
|
||||
/* Send a frame in tag mode, the FPGA must have been set up by
|
||||
* LegicRfSimulate
|
||||
*/
|
||||
void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt) {
|
||||
void frame_send_tag(uint16_t response, uint8_t bits) {
|
||||
|
||||
uint16_t mask = 1;
|
||||
|
||||
/* Bitbang the response */
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
SHORT_COIL;
|
||||
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
|
||||
|
||||
/* Use time to crypt frame */
|
||||
if(crypt) {
|
||||
legic_prng_forward(2); /* TAG_FRAME_WAIT -> shift by 2 */
|
||||
response ^= legic_prng_get_bits(bits);
|
||||
}
|
||||
/* TAG_FRAME_WAIT -> shift by 2 */
|
||||
legic_prng_forward(2);
|
||||
response ^= legic_prng_get_bits(bits);
|
||||
|
||||
/* Wait for the frame start */
|
||||
WaitUS( TAG_FRAME_WAIT );
|
||||
WaitTicks( TAG_FRAME_WAIT );
|
||||
|
||||
uint8_t bit = 0;
|
||||
for(int i = 0; i < bits; i++) {
|
||||
|
||||
bit = response & 1;
|
||||
response >>= 1;
|
||||
|
||||
if (bit)
|
||||
HIGH(GPIO_SSC_DOUT);
|
||||
for (; mask < BITMASK(bits); mask <<= 1) {
|
||||
if (send & mask)
|
||||
OPEN_COIL;
|
||||
else
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
|
||||
WaitUS(100);
|
||||
SHORT_COIL;
|
||||
WaitTicks(TAG_BIT_PERIOD);
|
||||
}
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
SHORT_COIL;
|
||||
}
|
||||
|
||||
/* Send a frame in reader mode, the FPGA must have been set up by
|
||||
|
@ -775,26 +760,26 @@ static void frame_handle_tag(struct legic_frame const * const f)
|
|||
{
|
||||
uint8_t *BigBuf = BigBuf_get_addr();
|
||||
|
||||
/* First Part of Handshake (IV) */
|
||||
if(f->bits == 7) {
|
||||
/* First Part of Handshake (IV) */
|
||||
if(f->bits == 7) {
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
// Reset prng timer
|
||||
ResetTimer(prng_timer);
|
||||
|
||||
legic_prng_init(f->data);
|
||||
frame_send_tag(0x3d, 6, 1); /* 0x3d^0x26 = 0x1B */
|
||||
legic_state = STATE_IV;
|
||||
legic_read_count = 0;
|
||||
legic_prng_bc = 0;
|
||||
legic_prng_iv = f->data;
|
||||
|
||||
|
||||
|
||||
legic_prng_init(f->data);
|
||||
frame_send_tag(0x3d, 6); /* 0x3d^0x26 = 0x1B */
|
||||
legic_state = STATE_IV;
|
||||
legic_read_count = 0;
|
||||
legic_prng_bc = 0;
|
||||
legic_prng_iv = f->data;
|
||||
|
||||
|
||||
ResetTimer(timer);
|
||||
WaitUS(280);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* 0x19==??? */
|
||||
if(legic_state == STATE_IV) {
|
||||
|
@ -828,7 +813,7 @@ static void frame_handle_tag(struct legic_frame const * const f)
|
|||
//Dbprintf("Data:%03.3x, key:%03.3x, addr: %03.3x, read_c:%u", f->data, key, addr, read_c);
|
||||
legic_prng_forward(legic_reqresp_drift);
|
||||
|
||||
frame_send_tag(hash | data, 12, 1);
|
||||
frame_send_tag(hash | data, 12);
|
||||
|
||||
ResetTimer(timer);
|
||||
legic_prng_forward(2);
|
||||
|
|
|
@ -27,7 +27,7 @@ extern void LegicRfRawWriter(int address, int data, uint8_t iv);
|
|||
extern void LegicRfInfo(void);
|
||||
|
||||
uint32_t get_key_stream(int skip, int count);
|
||||
void frame_send_tag(uint16_t response, uint8_t bits, uint8_t crypt);
|
||||
void frame_send_tag(uint16_t response, uint8_t bits);
|
||||
void frame_sendAsReader(uint32_t data, uint8_t bits);
|
||||
|
||||
int legic_read_byte( uint16_t index, uint8_t cmd_sz);
|
||||
|
|
|
@ -882,7 +882,7 @@ int CmdHFSearch(const char *Cmd){
|
|||
PrintAndLog("\nValid Topaz Tag Found - Quiting Search\n");
|
||||
return 1;
|
||||
}
|
||||
ans = HFLegicInfo("", false);
|
||||
ans = HFLegicReader("", false);
|
||||
if ( ans == 0) {
|
||||
PrintAndLog("\nValid LEGIC Tag Found - Quiting Search\n");
|
||||
return 1;
|
||||
|
|
|
@ -88,8 +88,19 @@ int usage_legic_fill(void){
|
|||
PrintAndLog("Missing help text.");
|
||||
return 0;
|
||||
}
|
||||
int usage_legic_reader(void){
|
||||
PrintAndLog("Read UID and type information from a legic tag.");
|
||||
PrintAndLog("Usage: hf legic reader [h]");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h : this help");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Samples:");
|
||||
PrintAndLog(" hf legic reader");
|
||||
return 0;
|
||||
}
|
||||
int usage_legic_info(void){
|
||||
PrintAndLog("Read info from a legic tag.");
|
||||
PrintAndLog("Reads information from a legic prime tag.");
|
||||
PrintAndLog("Shows systemarea, user areas etc");
|
||||
PrintAndLog("Usage: hf legic info [h]");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h : this help");
|
||||
|
@ -98,12 +109,30 @@ int usage_legic_info(void){
|
|||
PrintAndLog(" hf legic info");
|
||||
return 0;
|
||||
}
|
||||
int usage_legic_dump(void){
|
||||
PrintAndLog("Reads all pages from LEGIC MIM22, MIM256, MIM1024");
|
||||
PrintAndLog("and saves binary dump into the file `filename.bin` or `cardUID.bin`");
|
||||
PrintAndLog("It autodetects card type.\n");
|
||||
PrintAndLog("Usage: hf legic dump [h] o <filename w/o .bin>");
|
||||
PrintAndLog("Options:");
|
||||
PrintAndLog(" h : this help");
|
||||
PrintAndLog(" n <FN> : filename w/o .bin to save the dump as");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Samples:");
|
||||
PrintAndLog(" hf legic dump");
|
||||
PrintAndLog(" hf legic dump o myfile");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output BigBuf and deobfuscate LEGIC RF tag data.
|
||||
* This is based on information given in the talk held
|
||||
* by Henryk Ploetz and Karsten Nohl at 26c3
|
||||
*/
|
||||
int CmdLegicDecode(const char *Cmd) {
|
||||
int CmdLegicInfo(const char *Cmd) {
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_info();
|
||||
|
||||
int i = 0, k = 0, segmentNum = 0, segment_len = 0, segment_flag = 0;
|
||||
int crc = 0, wrp = 0, wrc = 0;
|
||||
|
@ -113,6 +142,8 @@ int CmdLegicDecode(const char *Cmd) {
|
|||
int dcf = 0;
|
||||
int bIsSegmented = 0;
|
||||
|
||||
CmdLegicRFRead("0 21 55");
|
||||
|
||||
// copy data from device
|
||||
GetEMLFromBigBuf(data, sizeof(data), 0);
|
||||
if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000)){
|
||||
|
@ -834,7 +865,7 @@ int CmdLegicCalcCrc8(const char *Cmd){
|
|||
return 0;
|
||||
}
|
||||
|
||||
int HFLegicInfo(const char *Cmd, bool verbose) {
|
||||
int HFLegicReader(const char *Cmd, bool verbose) {
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_info();
|
||||
|
@ -870,22 +901,29 @@ int HFLegicInfo(const char *Cmd, bool verbose) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
int CmdLegicInfo(const char *Cmd){
|
||||
return HFLegicInfo(Cmd, TRUE);
|
||||
int CmdLegicReader(const char *Cmd){
|
||||
return HFLegicReader(Cmd, TRUE);
|
||||
}
|
||||
|
||||
int CmdLegicDump(const char *Cmd){
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_dump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"decode", CmdLegicDecode, 0, "Display deobfuscated and decoded LEGIC RF tag data (use after hf legic reader)"},
|
||||
{"read", CmdLegicRFRead, 0, "[offset][length] <iv> -- read bytes from a LEGIC card"},
|
||||
{"save", CmdLegicSave, 0, "<filename> [<length>] -- Store samples"},
|
||||
{"load", CmdLegicLoad, 0, "<filename> -- Restore samples"},
|
||||
{"sim", CmdLegicRfSim, 0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"},
|
||||
{"write", CmdLegicRfWrite,0, "<offset> <length> <iv> -- Write sample buffer (user after load or read)"},
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"reader", CmdLegicReader, 1, "LEGIC Prime Reader UID and Type tag info"},
|
||||
{"info", CmdLegicInfo, 0, "Display deobfuscated and decoded LEGIC Prime tag data"},
|
||||
{"dump", CmdLegicDump, 0, "Dump LEGIC Prime card to binary file"},
|
||||
{"rdmem", CmdLegicRFRead, 0, "[offset][length] <iv> -- read bytes from a LEGIC card"},
|
||||
{"save", CmdLegicSave, 0, "<filename> [<length>] -- Store samples"},
|
||||
{"load", CmdLegicLoad, 0, "<filename> -- Restore samples"},
|
||||
{"sim", CmdLegicRfSim, 0, "[phase drift [frame drift [req/resp drift]]] Start tag simulator (use after load or read)"},
|
||||
{"write", CmdLegicRfWrite, 0, "<offset> <length> <iv> -- Write sample buffer (user after load or read)"},
|
||||
{"writeraw",CmdLegicRfRawWrite, 0, "<address> <value> <iv> -- Write direct to address"},
|
||||
{"fill", CmdLegicRfFill, 0, "<offset> <length> <value> -- Fill/Write tag with constant value"},
|
||||
{"crc8", CmdLegicCalcCrc8, 1, "Calculate Legic CRC8 over given hexbytes"},
|
||||
{"info", CmdLegicInfo, 1, "Information"},
|
||||
{"fill", CmdLegicRfFill, 0, "<offset> <length> <value> -- Fill/Write tag with constant value"},
|
||||
{"crc8", CmdLegicCalcCrc8, 1, "Calculate Legic CRC8 over given hexbytes"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
#include "legic.h" // legic_card_select_t struct
|
||||
|
||||
int CmdHFLegic(const char *Cmd);
|
||||
int CmdLegicInfo(const char *Cmd);
|
||||
|
||||
int CmdLegicRFRead(const char *Cmd);
|
||||
int CmdLegicDecode(const char *Cmd);
|
||||
int CmdLegicLoad(const char *Cmd);
|
||||
int CmdLegicSave(const char *Cmd);
|
||||
int CmdLegicRfSim(const char *Cmd);
|
||||
|
@ -35,11 +35,21 @@ int CmdLegicRfRawWrite(const char *Cmd);
|
|||
int CmdLegicRfFill(const char *Cmd);
|
||||
|
||||
int CmdLegicCalcCrc8(const char *Cmd);
|
||||
int CmdLegicInfo(const char *Cmd);
|
||||
int HFLegicInfo(const char *Cmd, bool verbose);
|
||||
|
||||
int CmdLegicReader(const char *Cmd);
|
||||
int HFLegicReader(const char *Cmd, bool verbose);
|
||||
|
||||
int CmdLegicDump(const char *Cmd);
|
||||
|
||||
|
||||
int usage_legic_calccrc8(void);
|
||||
int usage_legic_load(void);
|
||||
int usage_legic_read(void);
|
||||
int usage_legic_sim(void);
|
||||
int usage_legic_write(void);
|
||||
int usage_legic_rawwrite(void);
|
||||
int usage_legic_fill(void);
|
||||
int usage_legic_reader(void);
|
||||
int usage_legic_info(void);
|
||||
int usage_legic_dump(void);
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue