mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-21 05:43:23 -07:00
Merge branch 'master' into GenericTracing
Conflicts: armsrc/iso14443.c armsrc/iso14443a.c client/cmdhf.c client/cmdhf14b.c
This commit is contained in:
commit
7d5ebac993
98 changed files with 444131 additions and 2207 deletions
|
@ -1,30 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd ">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key> <string>English</string>
|
||||
<key>CFBundleIdentifier</key> <string>org.proxmark</string>
|
||||
<key>CFBundleIconFile</key> <string></string>
|
||||
<key>CFBundleInfoDictionaryVersion</key> <string>6.0</string>
|
||||
<key>CFBundlePackageType</key> <string>KEXT</string>
|
||||
<key>CFBundleSignature</key> <string>????</string>
|
||||
<key>CFBundleVersion</key> <string>1.0.0</string>
|
||||
<key>IOKitPersonalities</key>
|
||||
<dict>
|
||||
<key>Proxmark3</key>
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key><string>com.apple.kernel.iokit</string>
|
||||
<key>IOClass</key><string>IOService</string>
|
||||
<key>IOProviderClass</key><string>IOUSBInterface</string>
|
||||
<key>bConfigurationValue</key> <integer>1</integer>
|
||||
<key>bInterfaceNumber</key> <integer>0</integer>
|
||||
<key>idProduct</key><integer>19343</integer>
|
||||
<key>idVendor</key><integer>39620</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>OSBundleLibraries</key>
|
||||
<dict>
|
||||
<key>com.apple.iokit.IOUSBFamily</key><string>1.8</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -9,15 +9,13 @@ include ../common/Makefile.common
|
|||
CC=gcc
|
||||
CXX=g++
|
||||
#COMMON_FLAGS = -m32
|
||||
|
||||
VPATH = ../common
|
||||
OBJDIR = obj
|
||||
|
||||
LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
|
||||
LDFLAGS = $(COMMON_FLAGS)
|
||||
CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
|
||||
CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
|
||||
LUAPLATFORM = generic
|
||||
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
|
||||
QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
|
||||
|
@ -79,6 +77,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
|||
cmdhflegic.c \
|
||||
cmdhficlass.c \
|
||||
cmdhfmf.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
cmdlfio.c \
|
||||
|
@ -138,17 +137,6 @@ clean:
|
|||
tarbin: $(BINS)
|
||||
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%)
|
||||
|
||||
# must be run as root
|
||||
install_kext: Info.plist
|
||||
mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
|
||||
cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
|
||||
chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
|
||||
chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
|
||||
chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
|
||||
rm -rf /System/Library/Caches/com.apple.kext.caches
|
||||
touch /System/Library/Extensions
|
||||
@echo "*** You may need to reboot for the kext to take effect."
|
||||
|
||||
lua_build:
|
||||
@echo Compiling liblua, using platform $(LUAPLATFORM)
|
||||
cd ../liblua && make $(LUAPLATFORM)
|
||||
|
|
817
client/cmddata.c
817
client/cmddata.c
File diff suppressed because it is too large
Load diff
|
@ -26,9 +26,12 @@ int CmdBitstream(const char *Cmd);
|
|||
int CmdBuffClear(const char *Cmd);
|
||||
int CmdDec(const char *Cmd);
|
||||
int CmdDetectClockRate(const char *Cmd);
|
||||
int CmdFSKdemodAWID(const char *Cmd);
|
||||
int CmdFSKdemod(const char *Cmd);
|
||||
int CmdFSKdemodHID(const char *Cmd);
|
||||
int CmdFSKdemodIO(const char *Cmd);
|
||||
int CmdFSKdemodParadox(const char *Cmd);
|
||||
int CmdFSKdemodPyramid(const char *Cmd);
|
||||
int CmdFSKrawdemod(const char *Cmd);
|
||||
int CmdDetectNRZpskClockRate(const char *Cmd);
|
||||
int CmdpskNRZrawDemod(const char *Cmd);
|
||||
|
@ -57,4 +60,6 @@ int CmdIndalaDecode(const char *Cmd);
|
|||
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||
extern int DemodBufferLen;
|
||||
|
||||
#define BIGBUF_SIZE 40000
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "cmdhflegic.h"
|
||||
#include "cmdhficlass.h"
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhfmfu.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -31,8 +32,6 @@ int CmdHFTune(const char *Cmd)
|
|||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
// for the time being. Need better Bigbuf handling.
|
||||
#define TRACE_SIZE 3000
|
||||
|
||||
//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501
|
||||
/*
|
||||
|
@ -212,7 +211,7 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
case ISO14443A_CMD_ANTICOLL_OR_SELECT:{
|
||||
// 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor)
|
||||
// 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK)
|
||||
if(cmd[2] == 0x70)
|
||||
if(cmd[1] == 0x70)
|
||||
{
|
||||
snprintf(exp,size,"SELECT_UID"); break;
|
||||
}else
|
||||
|
@ -240,8 +239,8 @@ void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
|
|||
case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break;
|
||||
case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break;
|
||||
case MIFARE_CMD_TRANSFER: snprintf(exp,size,"TRANSFER(%d)",cmd[1]); break;
|
||||
case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A"); break;
|
||||
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B"); break;
|
||||
case MIFARE_AUTH_KEYA: snprintf(exp,size,"AUTH-A(%d)",cmd[1]); break;
|
||||
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
|
||||
case MIFARE_MAGICMODE: snprintf(exp,size,"MAGIC"); break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
}
|
||||
|
@ -422,18 +421,18 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
|
|||
}
|
||||
}
|
||||
|
||||
uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, bool showWaitCycles)
|
||||
uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
|
||||
{
|
||||
bool isResponse;
|
||||
uint16_t duration, data_len,parity_len;
|
||||
uint16_t duration, data_len, parity_len;
|
||||
|
||||
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
|
||||
char explanation[30] = {0};
|
||||
|
||||
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||
|
||||
first_timestamp = *((uint32_t *)(trace));
|
||||
timestamp = *((uint32_t *)(trace + tracepos));
|
||||
// Break and stick with current result if buffer was not completely full
|
||||
if (timestamp == 0x44444444) return TRACE_SIZE;
|
||||
|
||||
tracepos += 4;
|
||||
duration = *((uint16_t *)(trace + tracepos));
|
||||
|
@ -449,8 +448,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
|
|||
}
|
||||
parity_len = (data_len-1)/8 + 1;
|
||||
|
||||
if (tracepos + data_len + parity_len >= TRACE_SIZE) {
|
||||
return TRACE_SIZE;
|
||||
if (tracepos + data_len + parity_len > traceLen) {
|
||||
return traceLen;
|
||||
}
|
||||
uint8_t *frame = trace + tracepos;
|
||||
tracepos += data_len;
|
||||
|
@ -545,6 +544,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
|
|||
}
|
||||
}
|
||||
|
||||
if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
|
||||
|
||||
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
|
||||
|
||||
if (showWaitCycles && !isResponse && next_isResponse) {
|
||||
|
@ -557,9 +558,11 @@ uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, boo
|
|||
(next_timestamp - EndOfTransmissionTimestamp));
|
||||
}
|
||||
}
|
||||
|
||||
return tracepos;
|
||||
}
|
||||
|
||||
|
||||
int CmdHFList(const char *Cmd)
|
||||
{
|
||||
bool showWaitCycles = false;
|
||||
|
@ -599,12 +602,13 @@ int CmdHFList(const char *Cmd)
|
|||
|
||||
if (errors) {
|
||||
PrintAndLog("List protocol data in trace buffer.");
|
||||
PrintAndLog("Usage: hf list [14a|14b|iclass] [f]");
|
||||
PrintAndLog("Usage: hf list <protocol> [f]");
|
||||
PrintAndLog(" f - show frame delay times as well");
|
||||
PrintAndLog("Supported <protocol> values:");
|
||||
PrintAndLog(" raw - just show raw data without annotations");
|
||||
PrintAndLog(" 14a - interpret data as iso14443a communications");
|
||||
PrintAndLog(" 14b - interpret data as iso14443b communications");
|
||||
PrintAndLog(" iclass - interpret data as iclass communications");
|
||||
PrintAndLog(" raw - just show raw data");
|
||||
PrintAndLog(" f - show frame delay times as well");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("example: hf list 14a f");
|
||||
PrintAndLog("example: hf list iclass");
|
||||
|
@ -617,11 +621,28 @@ int CmdHFList(const char *Cmd)
|
|||
}
|
||||
|
||||
|
||||
uint8_t trace[TRACE_SIZE];
|
||||
uint8_t *trace;
|
||||
uint16_t tracepos = 0;
|
||||
GetFromBigBuf(trace, TRACE_SIZE, 0);
|
||||
WaitForResponse(CMD_ACK, NULL);
|
||||
PrintAndLog("Recorded Activity");
|
||||
trace = malloc(USB_CMD_DATA_SIZE);
|
||||
|
||||
// Query for the size of the trace
|
||||
UsbCommand response;
|
||||
GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
|
||||
WaitForResponse(CMD_ACK, &response);
|
||||
uint16_t traceLen = response.arg[2];
|
||||
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||
uint8_t *p = realloc(trace, traceLen);
|
||||
if (p == NULL) {
|
||||
PrintAndLog("Cannot allocate memory for trace");
|
||||
free(trace);
|
||||
return 2;
|
||||
}
|
||||
trace = p;
|
||||
GetFromBigBuf(trace, traceLen, 0);
|
||||
WaitForResponse(CMD_ACK, NULL);
|
||||
}
|
||||
|
||||
PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
|
||||
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
|
||||
|
@ -630,10 +651,12 @@ int CmdHFList(const char *Cmd)
|
|||
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
|
||||
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
|
||||
|
||||
while(tracepos < TRACE_SIZE)
|
||||
while(tracepos < traceLen)
|
||||
{
|
||||
tracepos = printTraceLine(tracepos, trace, protocol, showWaitCycles);
|
||||
tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
|
||||
}
|
||||
|
||||
free(trace);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -648,6 +671,7 @@ static command_t CommandTable[] =
|
|||
{"legic", CmdHFLegic, 0, "{ LEGIC RFIDs... }"},
|
||||
{"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"},
|
||||
{"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"},
|
||||
{"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"},
|
||||
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
|
||||
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
|
|
|
@ -412,9 +412,9 @@ int CmdHF14ASim(const char *Cmd)
|
|||
PrintAndLog(" syntax: hf 14a sim <type> <uid>");
|
||||
PrintAndLog(" types: 1 = MIFARE Classic");
|
||||
PrintAndLog(" 2 = MIFARE Ultralight");
|
||||
PrintAndLog(" 3 = MIFARE DESFIRE");
|
||||
PrintAndLog(" 3 = MIFARE Desfire");
|
||||
PrintAndLog(" 4 = ISO/IEC 14443-4");
|
||||
PrintAndLog(" 5 = MIFARE TNP3XXX");
|
||||
PrintAndLog(" 5 = MIFARE Tnp3xxx");
|
||||
PrintAndLog("");
|
||||
return 1;
|
||||
}
|
||||
|
@ -480,7 +480,8 @@ int CmdHF14ASim(const char *Cmd)
|
|||
int CmdHF14ASnoop(const char *Cmd) {
|
||||
int param = 0;
|
||||
|
||||
if (param_getchar(Cmd, 0) == 'h') {
|
||||
uint8_t ctmp = param_getchar(Cmd, 0) ;
|
||||
if (ctmp == 'h' || ctmp == 'H') {
|
||||
PrintAndLog("It get data from the field and saves it into command buffer.");
|
||||
PrintAndLog("Buffer accessible from command hf list 14a.");
|
||||
PrintAndLog("Usage: hf 14a snoop [c][r]");
|
||||
|
@ -491,7 +492,7 @@ int CmdHF14ASnoop(const char *Cmd) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
char ctmp = param_getchar(Cmd, i);
|
||||
ctmp = param_getchar(Cmd, i);
|
||||
if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
|
||||
if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
|
||||
}
|
||||
|
@ -670,7 +671,7 @@ static command_t CommandTable[] =
|
|||
{"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443a history"},
|
||||
{"reader", CmdHF14AReader, 0, "Act like an ISO14443 Type A reader"},
|
||||
{"cuids", CmdHF14ACUIDs, 0, "<n> Collect n>0 ISO14443 Type A UIDs in one go"},
|
||||
{"sim", CmdHF14ASim, 0, "<UID> -- Fake ISO 14443a tag"},
|
||||
{"sim", CmdHF14ASim, 0, "<UID> -- Simulate ISO 14443a tag"},
|
||||
{"snoop", CmdHF14ASnoop, 0, "Eavesdrop ISO 14443 Type A"},
|
||||
{"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
|
|
|
@ -146,6 +146,7 @@ demodError:
|
|||
int CmdHF14BList(const char *Cmd)
|
||||
{
|
||||
PrintAndLog("Deprecated command, use 'hf list 14b' instead");
|
||||
|
||||
return 0;
|
||||
}
|
||||
int CmdHF14BRead(const char *Cmd)
|
||||
|
@ -207,7 +208,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
|||
uint8_t power=0;
|
||||
char buf[5]="";
|
||||
int i=0;
|
||||
uint8_t data[100];
|
||||
uint8_t data[100] = {0x00};
|
||||
unsigned int datalen=0, temp;
|
||||
char *hexout;
|
||||
|
||||
|
@ -261,7 +262,7 @@ int CmdHF14BCmdRaw (const char *cmd) {
|
|||
continue;
|
||||
}
|
||||
PrintAndLog("Invalid char on input");
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
if (datalen == 0)
|
||||
{
|
||||
|
@ -375,7 +376,7 @@ int CmdHF14BWrite( const char *Cmd){
|
|||
else
|
||||
PrintAndLog("[%s] Write block %02X [ %s ]", (isSrix4k)?"SRIX4K":"SRI512", blockno, sprint_hex(data,4) );
|
||||
|
||||
sprintf(str, "-c -p 09 %02x %02x%02x%02x%02x", blockno, data[0], data[1], data[2], data[3]);
|
||||
sprintf(str, "-c 09 %02x %02x%02x%02x%02x", blockno, data[0], data[1], data[2], data[3]);
|
||||
|
||||
CmdHF14BCmdRaw(str);
|
||||
return 0;
|
||||
|
|
300
client/cmdhfmf.c
300
client/cmdhfmf.c
|
@ -140,117 +140,6 @@ int CmdHF14AMfWrBl(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfUWrBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
bool chinese_card=0;
|
||||
uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
UsbCommand resp;
|
||||
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: hf mf uwrbl <block number> <block data (8 hex symbols)> <w>");
|
||||
PrintAndLog(" sample: hf mf uwrbl 0 01020304");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
if (param_gethex(Cmd, 1, bldata, 8)) {
|
||||
PrintAndLog("Block data must include 8 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strchr(Cmd,'w') != 0) {
|
||||
chinese_card=1;
|
||||
}
|
||||
|
||||
switch(blockNo){
|
||||
case 0:
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
}else{
|
||||
PrintAndLog("--specialblock no:%d", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(d.d.asBytes,bldata, 4);
|
||||
SendCommand(&d);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
}else{
|
||||
PrintAndLog("--specialblock no:%d", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(d.d.asBytes,bldata, 4);
|
||||
SendCommand(&d);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
}else{
|
||||
PrintAndLog("--specialblock no:%d", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(c.d.asBytes, bldata, 4);
|
||||
SendCommand(&c);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
PrintAndLog("--specialblock no:%d", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(d.d.asBytes,bldata, 4);
|
||||
SendCommand(&d);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("--block no:%d", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(e.d.asBytes,bldata, 4);
|
||||
SendCommand(&e);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfRdBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
|
@ -299,87 +188,6 @@ int CmdHF14AMfRdBl(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfURdBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
|
||||
if (strlen(Cmd)<1) {
|
||||
PrintAndLog("Usage: hf mf urdbl <block number>");
|
||||
PrintAndLog(" sample: hf mf urdbl 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
PrintAndLog("--block no:%d", blockNo);
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
uint8_t *data = resp.d.asBytes;
|
||||
|
||||
if (isOK)
|
||||
PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
|
||||
else
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfURdCard(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
uint8_t sectorNo = 0;
|
||||
uint8_t *lockbytes_t=NULL;
|
||||
uint8_t lockbytes[2]={0,0};
|
||||
bool bit[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
|
||||
uint8_t isOK = 0;
|
||||
uint8_t * data = NULL;
|
||||
|
||||
PrintAndLog("Attempting to Read Ultralight... ");
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READCARD, {sectorNo}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
data = resp.d.asBytes;
|
||||
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
if (isOK)
|
||||
{ // bit 0 and 1
|
||||
PrintAndLog("Block %3d:%s ", 0,sprint_hex(data + 0 * 4, 4));
|
||||
PrintAndLog("Block %3d:%s ", 1,sprint_hex(data + 1 * 4, 4));
|
||||
// bit 2
|
||||
//process lock bytes
|
||||
lockbytes_t=data+(2*4);
|
||||
lockbytes[0]=lockbytes_t[2];
|
||||
lockbytes[1]=lockbytes_t[3];
|
||||
for(int j=0; j<16; j++){
|
||||
bit[j]=lockbytes[j/8] & ( 1 <<(7-j%8));
|
||||
}
|
||||
//remaining
|
||||
for (i = 3; i < 16; i++) {
|
||||
int bitnum = (23-i) % 16;
|
||||
PrintAndLog("Block %3d:%s [%d]", i,sprint_hex(data + i * 4, 4),bit[bitnum]);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdHF14AMfRdSc(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
|
@ -970,12 +778,14 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
int CmdHF14AMfChk(const char *Cmd)
|
||||
{
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t] [<key (12 hex symbols)>] [<dic (*.dic)>]");
|
||||
PrintAndLog("Usage: hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]");
|
||||
PrintAndLog(" * - all sectors");
|
||||
PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");
|
||||
PrintAndLog("d - write keys to binary file\n");
|
||||
PrintAndLog("t - write keys to emulator memory");
|
||||
PrintAndLog(" sample: hf mf chk 0 A 1234567890ab keys.dic");
|
||||
PrintAndLog(" hf mf chk *1 ? t");
|
||||
PrintAndLog(" hf mf chk *1 ? d");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1202,12 +1012,16 @@ int CmdHF14AMf1kSim(const char *Cmd)
|
|||
uint8_t exitAfterNReads = 0;
|
||||
uint8_t flags = 0;
|
||||
|
||||
if (param_getchar(Cmd, 0) == 'h') {
|
||||
uint8_t cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mf sim u <uid (8 hex symbols)> n <numreads> i x");
|
||||
PrintAndLog(" h this help");
|
||||
PrintAndLog(" u (Optional) UID. If not specified, the UID from emulator memory will be used");
|
||||
PrintAndLog(" n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
|
||||
PrintAndLog(" i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
|
||||
PrintAndLog(" x (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" sample: hf mf sim u 0a0a0a0a ");
|
||||
return 0;
|
||||
}
|
||||
|
@ -1288,7 +1102,7 @@ int CmdHF14AMfDbg(const char *Cmd)
|
|||
int CmdHF14AMfEGet(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = 0;
|
||||
uint8_t data[16];
|
||||
uint8_t data[16] = {0x00};
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf eget <block number>");
|
||||
|
@ -1355,14 +1169,11 @@ int CmdHF14AMfELoad(const char *Cmd)
|
|||
FILE * f;
|
||||
char filename[FILE_PATH_SIZE];
|
||||
char *fnameptr = filename;
|
||||
char buf[64];
|
||||
uint8_t buf8[64];
|
||||
char buf[64] = {0x00};
|
||||
uint8_t buf8[64] = {0x00};
|
||||
int i, len, blockNum, numBlocks;
|
||||
int nameParamNo = 1;
|
||||
|
||||
memset(filename, 0, sizeof(filename));
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
char ctmp = param_getchar(Cmd, 0);
|
||||
|
||||
if ( ctmp == 'h' || ctmp == 0x00) {
|
||||
|
@ -1432,11 +1243,13 @@ int CmdHF14AMfELoad(const char *Cmd)
|
|||
fclose(f);
|
||||
return 3;
|
||||
}
|
||||
printf(".");
|
||||
blockNum++;
|
||||
|
||||
if (blockNum >= numBlocks) break;
|
||||
}
|
||||
fclose(f);
|
||||
printf("\n");
|
||||
|
||||
if ((blockNum != numBlocks)) {
|
||||
PrintAndLog("File content error. Got %d must be %d blocks.",blockNum, numBlocks);
|
||||
|
@ -1638,7 +1451,7 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
char ctmp = param_getchar(Cmd, 1);
|
||||
if (ctmp == 'w' || ctmp == 'W') wipeCard = 1;
|
||||
|
||||
PrintAndLog("--wipe card:%02x uid:%s", wipeCard, sprint_hex(uid, 4));
|
||||
PrintAndLog("--wipe card:%s uid:%s", (wipeCard)?"YES":"NO", sprint_hex(uid, 4));
|
||||
|
||||
res = mfCSetUID(uid, oldUid, wipeCard);
|
||||
if (res) {
|
||||
|
@ -1653,11 +1466,10 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
|
||||
int CmdHF14AMfCSetBlk(const char *Cmd)
|
||||
{
|
||||
uint8_t uid[8];
|
||||
uint8_t memBlock[16];
|
||||
uint8_t uid[8] = {0x00};
|
||||
uint8_t memBlock[16] = {0x00};
|
||||
uint8_t blockNo = 0;
|
||||
int res;
|
||||
memset(memBlock, 0x00, sizeof(memBlock));
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)>");
|
||||
|
@ -1682,7 +1494,6 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("UID:%s", sprint_hex(uid, 4));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1697,11 +1508,8 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
uint8_t fillFromEmulator = 0;
|
||||
int i, len, blockNum, flags;
|
||||
|
||||
// memset(filename, 0, sizeof(filename));
|
||||
// memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (param_getchar(Cmd, 0) == 'h' || param_getchar(Cmd, 0)== 0x00) {
|
||||
PrintAndLog("It loads magic Chinese card (only works with!!!) from the file `filename.eml`");
|
||||
PrintAndLog("It loads magic Chinese card from the file `filename.eml`");
|
||||
PrintAndLog("or from emulator memory (option `e`)");
|
||||
PrintAndLog("Usage: hf mf cload <file name w/o `.eml`>");
|
||||
PrintAndLog(" or: hf mf cload e ");
|
||||
|
@ -1748,7 +1556,9 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
blockNum = 0;
|
||||
flags = CSETBLOCK_INIT_FIELD + CSETBLOCK_WUPC;
|
||||
while(!feof(f)){
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||
PrintAndLog("File reading error.");
|
||||
return 2;
|
||||
|
@ -1783,6 +1593,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
PrintAndLog("Loaded from file: %s", filename);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14AMfCGetBlk(const char *Cmd) {
|
||||
|
@ -1814,10 +1625,9 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
|
|||
|
||||
|
||||
int CmdHF14AMfCGetSc(const char *Cmd) {
|
||||
uint8_t memBlock[16];
|
||||
uint8_t memBlock[16] = {0x00};
|
||||
uint8_t sectorNo = 0;
|
||||
int i, res, flags;
|
||||
memset(memBlock, 0x00, sizeof(memBlock));
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf cgetsc <sector number>");
|
||||
|
@ -1955,18 +1765,19 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
int res = 0;
|
||||
int len = 0;
|
||||
int blockLen = 0;
|
||||
int num = 0;
|
||||
int pckNum = 0;
|
||||
int num = 0;
|
||||
uint8_t uid[7];
|
||||
uint8_t uid_len;
|
||||
uint8_t atqa[2];
|
||||
uint8_t atqa[2] = {0x00};
|
||||
uint8_t sak;
|
||||
bool isTag;
|
||||
uint8_t buf[3000];
|
||||
uint8_t * bufPtr = buf;
|
||||
memset(buf, 0x00, 3000);
|
||||
uint8_t *buf = NULL;
|
||||
uint16_t bufsize = 0;
|
||||
uint8_t *bufPtr = NULL;
|
||||
|
||||
if (param_getchar(Cmd, 0) == 'h') {
|
||||
char ctmp = param_getchar(Cmd, 0);
|
||||
if ( ctmp == 'h' || ctmp == 'H' ) {
|
||||
PrintAndLog("It continuously gets data from the field and saves it to: log, emulator, emulator file.");
|
||||
PrintAndLog("You can specify:");
|
||||
PrintAndLog(" l - save encrypted sequence to logfile `uid.log`");
|
||||
|
@ -1979,7 +1790,7 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
}
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
char ctmp = param_getchar(Cmd, i);
|
||||
ctmp = param_getchar(Cmd, i);
|
||||
if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true;
|
||||
if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true;
|
||||
//if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO
|
||||
|
@ -2006,32 +1817,47 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
break;
|
||||
}
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {
|
||||
res = resp.arg[0] & 0xff;
|
||||
len = resp.arg[1];
|
||||
num = resp.arg[2];
|
||||
|
||||
if (res == 0) return 0;
|
||||
if (res == 1) {
|
||||
if (num ==0) {
|
||||
uint16_t traceLen = resp.arg[1];
|
||||
len = resp.arg[2];
|
||||
|
||||
if (res == 0) return 0; // we are done
|
||||
|
||||
if (res == 1) { // there is (more) data to be transferred
|
||||
if (pckNum == 0) { // first packet, (re)allocate necessary buffer
|
||||
if (traceLen > bufsize) {
|
||||
uint8_t *p;
|
||||
if (buf == NULL) { // not yet allocated
|
||||
p = malloc(traceLen);
|
||||
} else { // need more memory
|
||||
p = realloc(buf, traceLen);
|
||||
}
|
||||
if (p == NULL) {
|
||||
PrintAndLog("Cannot allocate memory for trace");
|
||||
free(buf);
|
||||
return 2;
|
||||
}
|
||||
buf = p;
|
||||
}
|
||||
bufPtr = buf;
|
||||
memset(buf, 0x00, 3000);
|
||||
bufsize = traceLen;
|
||||
memset(buf, 0x00, traceLen);
|
||||
}
|
||||
memcpy(bufPtr, resp.d.asBytes, len);
|
||||
bufPtr += len;
|
||||
pckNum++;
|
||||
}
|
||||
if (res == 2) {
|
||||
|
||||
if (res == 2) { // received all data, start displaying
|
||||
blockLen = bufPtr - buf;
|
||||
bufPtr = buf;
|
||||
printf(">\n");
|
||||
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);
|
||||
num = 0;
|
||||
while (bufPtr - buf < blockLen) {
|
||||
bufPtr += 6;
|
||||
bufPtr += 6; // skip (void) timing information
|
||||
len = *((uint16_t *)bufPtr);
|
||||
|
||||
if(len & 0x8000) {
|
||||
isTag = true;
|
||||
len &= 0x7fff;
|
||||
|
@ -2040,12 +1866,10 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
}
|
||||
bufPtr += 2;
|
||||
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {
|
||||
|
||||
memcpy(uid, bufPtr + 2, 7);
|
||||
memcpy(atqa, bufPtr + 2 + 7, 2);
|
||||
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;
|
||||
sak = bufPtr[11];
|
||||
|
||||
PrintAndLog("tag select uid:%s atqa:0x%02x%02x sak:0x%02x",
|
||||
sprint_hex(uid + (7 - uid_len), uid_len),
|
||||
atqa[1],
|
||||
|
@ -2063,26 +1887,26 @@ int CmdHF14AMfSniff(const char *Cmd){
|
|||
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);
|
||||
if (wantDecrypt)
|
||||
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);
|
||||
num++;
|
||||
}
|
||||
bufPtr += len;
|
||||
bufPtr += ((len-1)/8+1); // ignore parity
|
||||
num++;
|
||||
}
|
||||
pckNum = 0;
|
||||
}
|
||||
} // resp not NULL
|
||||
} // while (true)
|
||||
|
||||
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"},
|
||||
{"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"},
|
||||
{"urdbl", CmdHF14AMfURdBl, 0, "Read MIFARE Ultralight block"},
|
||||
{"urdcard", CmdHF14AMfURdCard, 0,"Read MIFARE Ultralight Card"},
|
||||
{"uwrbl", CmdHF14AMfUWrBl, 0,"Write MIFARE Ultralight block"},
|
||||
{"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"},
|
||||
{"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"},
|
||||
{"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"},
|
||||
|
|
741
client/cmdhfmfu.c
Normal file
741
client/cmdhfmfu.c
Normal file
|
@ -0,0 +1,741 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Ultralight Code (c) 2013,2014 Midnitesnake & Andy Davies of Pentura
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// High frequency MIFARE ULTRALIGHT (C) commands
|
||||
//-----------------------------------------------------------------------------
|
||||
//#include <openssl/des.h>
|
||||
#include "loclass/des.h"
|
||||
#include "cmdhfmfu.h"
|
||||
#include "cmdhfmf.h"
|
||||
#include "cmdhf14a.h"
|
||||
|
||||
|
||||
#define MAX_ULTRA_BLOCKS 0x0f
|
||||
#define MAX_ULTRAC_BLOCKS 0x2f
|
||||
//#define MAX_ULTRAC_BLOCKS 0x2c
|
||||
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
int CmdHF14AMfUInfo(const char *Cmd){
|
||||
|
||||
uint8_t datatemp[7] = {0x00};
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READCARD, {0, 4}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
data = resp.d.asBytes;
|
||||
|
||||
if (!isOK) {
|
||||
PrintAndLog("Error reading from tag");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Command execute timed out");
|
||||
return -1;
|
||||
}
|
||||
|
||||
PrintAndLog("");
|
||||
PrintAndLog("-- Mifare Ultralight / Ultralight-C Tag Information ---------");
|
||||
PrintAndLog("-------------------------------------------------------------");
|
||||
|
||||
// UID
|
||||
memcpy( datatemp, data, 3);
|
||||
memcpy( datatemp+3, data+4, 4);
|
||||
|
||||
PrintAndLog("MANUFACTURER : %s", getTagInfo(datatemp[0]));
|
||||
PrintAndLog(" UID : %s ", sprint_hex(datatemp, 7));
|
||||
// BBC
|
||||
// CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2
|
||||
int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2];
|
||||
if ( data[3] == crc0 )
|
||||
PrintAndLog(" BCC0 : %02x - Ok", data[3]);
|
||||
else
|
||||
PrintAndLog(" BCC0 : %02x - crc should be %02x", data[3], crc0);
|
||||
|
||||
int crc1 = data[4] ^ data[5] ^ data[6] ^data[7];
|
||||
if ( data[8] == crc1 )
|
||||
PrintAndLog(" BCC1 : %02x - Ok", data[8]);
|
||||
else
|
||||
PrintAndLog(" BCC1 : %02x - crc should be %02x", data[8], crc1 );
|
||||
|
||||
PrintAndLog(" Internal : %s ", sprint_hex(data + 9, 1));
|
||||
|
||||
memcpy(datatemp, data+10, 2);
|
||||
PrintAndLog(" Lock : %s - %s", sprint_hex(datatemp, 2),printBits( 2, &datatemp) );
|
||||
PrintAndLog(" OneTimePad : %s ", sprint_hex(data + 3*4, 4));
|
||||
PrintAndLog("");
|
||||
|
||||
int len = CmdHF14AMfucAuth("K 0");
|
||||
// PrintAndLog("CODE: %d",len);
|
||||
|
||||
PrintAndLog("Seems to be a Ultralight %s", (len==0) ? "-C" :"");
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Mifare Ultralight Write Single Block
|
||||
//
|
||||
int CmdHF14AMfUWrBl(const char *Cmd){
|
||||
uint8_t blockNo = -1;
|
||||
bool chinese_card = FALSE;
|
||||
uint8_t bldata[16] = {0x00};
|
||||
UsbCommand resp;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
|
||||
PrintAndLog(" [block number]");
|
||||
PrintAndLog(" [block data] - (8 hex symbols)");
|
||||
PrintAndLog(" [w] - Chinese magic ultralight tag");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" sample: hf mfu wrbl 0 01020304");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
|
||||
if (blockNo > MAX_ULTRA_BLOCKS){
|
||||
PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 1, bldata, 8)) {
|
||||
PrintAndLog("Block data must include 8 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
|
||||
chinese_card = TRUE;
|
||||
}
|
||||
|
||||
if ( blockNo <= 3) {
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
} else {
|
||||
PrintAndLog("--specialblock no:%02x", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(d.d.asBytes,bldata, 4);
|
||||
SendCommand(&d);
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("--block no:%02x", blockNo);
|
||||
PrintAndLog("--data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(e.d.asBytes,bldata, 4);
|
||||
SendCommand(&e);
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Mifare Ultralight Read Single Block
|
||||
//
|
||||
int CmdHF14AMfURdBl(const char *Cmd){
|
||||
|
||||
uint8_t blockNo = -1;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mfu rdbl <block number>");
|
||||
PrintAndLog(" sample: hfu mfu rdbl 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
|
||||
if (blockNo > MAX_ULTRA_BLOCKS){
|
||||
PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("--block no:0x%02X (%d)", (int)blockNo, blockNo);
|
||||
UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
uint8_t * data = resp.d.asBytes;
|
||||
|
||||
PrintAndLog("isOk: %02x", isOK);
|
||||
|
||||
if (isOK)
|
||||
PrintAndLog("Data: %s", sprint_hex(data, 4));
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Mifare Ultralight / Ultralight-C; Read and Dump Card Contents
|
||||
//
|
||||
int CmdHF14AMfUDump(const char *Cmd){
|
||||
|
||||
FILE *fout;
|
||||
char filename[FILE_PATH_SIZE] = {0x00};
|
||||
char * fnameptr = filename;
|
||||
|
||||
uint8_t *lockbytes_t = NULL;
|
||||
uint8_t lockbytes[2] = {0x00};
|
||||
|
||||
uint8_t *lockbytes_t2 = NULL;
|
||||
uint8_t lockbytes2[2] = {0x00};
|
||||
|
||||
bool bit[16] = {0x00};
|
||||
bool bit2[16] = {0x00};
|
||||
|
||||
int i;
|
||||
uint8_t BlockNo = 0;
|
||||
int Pages = 16;
|
||||
|
||||
bool tmplockbit = false;
|
||||
uint8_t isOK = 0;
|
||||
uint8_t *data = NULL;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
|
||||
PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`");
|
||||
PrintAndLog("Usage: hf mfu dump <c> <filename w/o .bin>");
|
||||
PrintAndLog(" <c> optional cardtype c == Ultralight-C, if not defaults to Ultralight");
|
||||
PrintAndLog(" sample: hf mfu dump");
|
||||
PrintAndLog(" : hf mfu dump myfile");
|
||||
PrintAndLog(" : hf mfu dump c myfile");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// UL or UL-C?
|
||||
Pages = (cmdp == 'c' || cmdp == 'C') ? 44 : 16;
|
||||
|
||||
PrintAndLog("Dumping Ultralight%s Card Data...", (Pages ==16)?"":"-C");
|
||||
|
||||
UsbCommand c = {CMD_MIFAREU_READCARD, {BlockNo,Pages}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
if (!isOK) {
|
||||
PrintAndLog("Command error");
|
||||
return 0;
|
||||
}
|
||||
data = resp.d.asBytes;
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load lock bytes.
|
||||
int j = 0;
|
||||
|
||||
lockbytes_t = data + 8;
|
||||
lockbytes[0] = lockbytes_t[2];
|
||||
lockbytes[1] = lockbytes_t[3];
|
||||
for(j = 0; j < 16; j++){
|
||||
bit[j] = lockbytes[j/8] & ( 1 <<(7-j%8));
|
||||
}
|
||||
|
||||
// Load bottom lockbytes if available
|
||||
if ( Pages == 44 ) {
|
||||
|
||||
lockbytes_t2 = data + (40*4);
|
||||
lockbytes2[0] = lockbytes_t2[2];
|
||||
lockbytes2[1] = lockbytes_t2[3];
|
||||
for (j = 0; j < 16; j++) {
|
||||
bit2[j] = lockbytes2[j/8] & ( 1 <<(7-j%8));
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < Pages; ++i) {
|
||||
|
||||
if ( i < 3 ) {
|
||||
PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch(i){
|
||||
case 3: tmplockbit = bit[4]; break;
|
||||
case 4: tmplockbit = bit[3]; break;
|
||||
case 5: tmplockbit = bit[2]; break;
|
||||
case 6: tmplockbit = bit[1]; break;
|
||||
case 7: tmplockbit = bit[0]; break;
|
||||
case 8: tmplockbit = bit[15]; break;
|
||||
case 9: tmplockbit = bit[14]; break;
|
||||
case 10: tmplockbit = bit[13]; break;
|
||||
case 11: tmplockbit = bit[12]; break;
|
||||
case 12: tmplockbit = bit[11]; break;
|
||||
case 13: tmplockbit = bit[10]; break;
|
||||
case 14: tmplockbit = bit[9]; break;
|
||||
case 15: tmplockbit = bit[8]; break;
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19: tmplockbit = bit2[6]; break;
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23: tmplockbit = bit2[5]; break;
|
||||
case 24:
|
||||
case 25:
|
||||
case 26:
|
||||
case 27: tmplockbit = bit2[4]; break;
|
||||
case 28:
|
||||
case 29:
|
||||
case 30:
|
||||
case 31: tmplockbit = bit2[2]; break;
|
||||
case 32:
|
||||
case 33:
|
||||
case 34:
|
||||
case 35: tmplockbit = bit2[1]; break;
|
||||
case 36:
|
||||
case 37:
|
||||
case 38:
|
||||
case 39: tmplockbit = bit2[0]; break;
|
||||
case 40: tmplockbit = bit2[12]; break;
|
||||
case 41: tmplockbit = bit2[11]; break;
|
||||
case 42: tmplockbit = bit2[10]; break; //auth0
|
||||
case 43: tmplockbit = bit2[9]; break; //auth1
|
||||
default: break;
|
||||
}
|
||||
PrintAndLog("Block %02x:%s [%d]", i,sprint_hex(data + i * 4, 4),tmplockbit);
|
||||
}
|
||||
|
||||
int len = 0;
|
||||
if ( Pages == 16 )
|
||||
len = param_getstr(Cmd,0,filename);
|
||||
else
|
||||
len = param_getstr(Cmd,1,filename);
|
||||
|
||||
if (len > FILE_PATH_SIZE-5) len = FILE_PATH_SIZE-5;
|
||||
|
||||
// user supplied filename?
|
||||
if (len < 1) {
|
||||
|
||||
// UID = data 0-1-2 4-5-6-7 (skips a beat)
|
||||
sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin",
|
||||
data[0],data[1], data[2], data[4],data[5],data[6], data[7]);
|
||||
|
||||
} else {
|
||||
sprintf(fnameptr + len," .bin");
|
||||
}
|
||||
|
||||
|
||||
if ((fout = fopen(filename,"wb")) == NULL) {
|
||||
PrintAndLog("Could not create file name %s", filename);
|
||||
return 1;
|
||||
}
|
||||
fwrite( data, 1, Pages*4, fout );
|
||||
fclose(fout);
|
||||
|
||||
PrintAndLog("Dumped %d pages, wrote %d bytes to %s", Pages, Pages*4, filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Needed to Authenticate to Ultralight C tags
|
||||
void rol (uint8_t *data, const size_t len){
|
||||
uint8_t first = data[0];
|
||||
for (size_t i = 0; i < len-1; i++) {
|
||||
data[i] = data[i+1];
|
||||
}
|
||||
data[len-1] = first;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// Ultralight C Methods
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// Ultralight C Authentication Demo {currently uses hard-coded key}
|
||||
//
|
||||
int CmdHF14AMfucAuth(const char *Cmd){
|
||||
|
||||
uint8_t default_keys[5][16] = {
|
||||
{ 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key
|
||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes
|
||||
{ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F
|
||||
{ 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key
|
||||
{ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 } // all ones
|
||||
};
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
uint8_t keyNo = 0;
|
||||
bool errors = false;
|
||||
//Change key to user defined one
|
||||
if (cmdp == 'k' || cmdp == 'K'){
|
||||
keyNo = param_get8(Cmd, 1);
|
||||
if(keyNo >= 4) errors = true;
|
||||
}
|
||||
|
||||
if (cmdp == 'h' || cmdp == 'H') {
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
PrintAndLog("Usage: hf mfu cauth k <key number>");
|
||||
PrintAndLog(" 0 (default): 3DES standard key");
|
||||
PrintAndLog(" 1 : all zeros key");
|
||||
PrintAndLog(" 2 : 0x00-0x0F key");
|
||||
PrintAndLog(" 3 : nfc key");
|
||||
PrintAndLog(" 4 : all ones key");
|
||||
PrintAndLog(" sample : hf mfu cauth k");
|
||||
PrintAndLog(" : hf mfu cauth k 3");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t random_a[8] = { 1,1,1,1,1,1,1,1 };
|
||||
//uint8_t enc_random_a[8] = { 0 };
|
||||
uint8_t random_b[8] = { 0 };
|
||||
uint8_t enc_random_b[8] = { 0 };
|
||||
uint8_t random_a_and_b[16] = { 0 };
|
||||
des3_context ctx = { 0 };
|
||||
uint8_t *key = default_keys[keyNo];
|
||||
uint8_t blockNo = 0;
|
||||
uint32_t cuid = 0;
|
||||
|
||||
//Auth1
|
||||
UsbCommand c = {CMD_MIFAREUC_AUTH1, {blockNo}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
cuid = resp.arg[1];
|
||||
uint8_t * data= resp.d.asBytes;
|
||||
|
||||
if (isOK){
|
||||
PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8));
|
||||
memcpy(enc_random_b,data+1,8);
|
||||
} else {
|
||||
PrintAndLog("Auth failed");
|
||||
return 2; // auth failed.
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t iv[8] = { 0 };
|
||||
// Do we need random ? Right now we use all ones, is that random enough ?
|
||||
// DES_random_key(&RndA);
|
||||
|
||||
PrintAndLog(" RndA :%s",sprint_hex(random_a, 8));
|
||||
PrintAndLog(" e_RndB:%s",sprint_hex(enc_random_b, 8));
|
||||
|
||||
des3_set2key_dec(&ctx, key);
|
||||
|
||||
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||
, DES_DECRYPT // int mode
|
||||
, sizeof(random_b) // size_t length
|
||||
, iv // unsigned char iv[8]
|
||||
, enc_random_b // const unsigned char *input
|
||||
, random_b // unsigned char *output
|
||||
);
|
||||
|
||||
PrintAndLog(" RndB:%s",sprint_hex(random_b, 8));
|
||||
|
||||
rol(random_b,8);
|
||||
memcpy(random_a_and_b ,random_a,8);
|
||||
memcpy(random_a_and_b+8,random_b,8);
|
||||
|
||||
PrintAndLog(" RA+B:%s",sprint_hex(random_a_and_b, 16));
|
||||
|
||||
des3_set2key_enc(&ctx, key);
|
||||
|
||||
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||
, DES_ENCRYPT // int mode
|
||||
, sizeof(random_a_and_b) // size_t length
|
||||
, enc_random_b // unsigned char iv[8]
|
||||
, random_a_and_b // const unsigned char *input
|
||||
, random_a_and_b // unsigned char *output
|
||||
);
|
||||
|
||||
PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
|
||||
|
||||
//Auth2
|
||||
UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}};
|
||||
memcpy(d.d.asBytes,random_a_and_b, 16);
|
||||
SendCommand(&d);
|
||||
|
||||
UsbCommand respb;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
|
||||
uint8_t isOK = respb.arg[0] & 0xff;
|
||||
uint8_t * data2= respb.d.asBytes;
|
||||
|
||||
if (isOK){
|
||||
PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8));
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
A test function to validate that the polarssl-function works the same
|
||||
was as the openssl-implementation.
|
||||
Commented out, since it requires openssl
|
||||
|
||||
int CmdTestDES(const char * cmd)
|
||||
{
|
||||
uint8_t key[16] = {0x00};
|
||||
|
||||
memcpy(key,key3_3des_data,16);
|
||||
DES_cblock RndA, RndB;
|
||||
|
||||
PrintAndLog("----------OpenSSL DES implementation----------");
|
||||
{
|
||||
uint8_t e_RndB[8] = {0x00};
|
||||
unsigned char RndARndB[16] = {0x00};
|
||||
|
||||
DES_cblock iv = { 0 };
|
||||
DES_key_schedule ks1,ks2;
|
||||
DES_cblock key1,key2;
|
||||
|
||||
memcpy(key,key3_3des_data,16);
|
||||
memcpy(key1,key,8);
|
||||
memcpy(key2,key+8,8);
|
||||
|
||||
|
||||
DES_set_key((DES_cblock *)key1,&ks1);
|
||||
DES_set_key((DES_cblock *)key2,&ks2);
|
||||
|
||||
DES_random_key(&RndA);
|
||||
PrintAndLog(" RndA:%s",sprint_hex(RndA, 8));
|
||||
PrintAndLog(" e_RndB:%s",sprint_hex(e_RndB, 8));
|
||||
//void DES_ede2_cbc_encrypt(const unsigned char *input,
|
||||
// unsigned char *output, long length, DES_key_schedule *ks1,
|
||||
// DES_key_schedule *ks2, DES_cblock *ivec, int enc);
|
||||
DES_ede2_cbc_encrypt(e_RndB,RndB,sizeof(e_RndB),&ks1,&ks2,&iv,0);
|
||||
|
||||
PrintAndLog(" RndB:%s",sprint_hex(RndB, 8));
|
||||
rol(RndB,8);
|
||||
memcpy(RndARndB,RndA,8);
|
||||
memcpy(RndARndB+8,RndB,8);
|
||||
PrintAndLog(" RA+B:%s",sprint_hex(RndARndB, 16));
|
||||
DES_ede2_cbc_encrypt(RndARndB,RndARndB,sizeof(RndARndB),&ks1,&ks2,&e_RndB,1);
|
||||
PrintAndLog("enc(RA+B):%s",sprint_hex(RndARndB, 16));
|
||||
|
||||
}
|
||||
PrintAndLog("----------PolarSSL implementation----------");
|
||||
{
|
||||
uint8_t random_a[8] = { 0 };
|
||||
uint8_t enc_random_a[8] = { 0 };
|
||||
uint8_t random_b[8] = { 0 };
|
||||
uint8_t enc_random_b[8] = { 0 };
|
||||
uint8_t random_a_and_b[16] = { 0 };
|
||||
des3_context ctx = { 0 };
|
||||
|
||||
memcpy(random_a, RndA,8);
|
||||
|
||||
uint8_t output[8] = { 0 };
|
||||
uint8_t iv[8] = { 0 };
|
||||
|
||||
PrintAndLog(" RndA :%s",sprint_hex(random_a, 8));
|
||||
PrintAndLog(" e_RndB:%s",sprint_hex(enc_random_b, 8));
|
||||
|
||||
des3_set2key_dec(&ctx, key);
|
||||
|
||||
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||
, DES_DECRYPT // int mode
|
||||
, sizeof(random_b) // size_t length
|
||||
, iv // unsigned char iv[8]
|
||||
, enc_random_b // const unsigned char *input
|
||||
, random_b // unsigned char *output
|
||||
);
|
||||
|
||||
PrintAndLog(" RndB:%s",sprint_hex(random_b, 8));
|
||||
|
||||
rol(random_b,8);
|
||||
memcpy(random_a_and_b ,random_a,8);
|
||||
memcpy(random_a_and_b+8,random_b,8);
|
||||
|
||||
PrintAndLog(" RA+B:%s",sprint_hex(random_a_and_b, 16));
|
||||
|
||||
des3_set2key_enc(&ctx, key);
|
||||
|
||||
des3_crypt_cbc(&ctx // des3_context *ctx
|
||||
, DES_ENCRYPT // int mode
|
||||
, sizeof(random_a_and_b) // size_t length
|
||||
, enc_random_b // unsigned char iv[8]
|
||||
, random_a_and_b // const unsigned char *input
|
||||
, random_a_and_b // unsigned char *output
|
||||
);
|
||||
|
||||
PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
**/
|
||||
//
|
||||
// Ultralight C Read Single Block
|
||||
//
|
||||
int CmdHF14AMfUCRdBl(const char *Cmd)
|
||||
{
|
||||
uint8_t blockNo = -1;
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mfu crdbl <block number>");
|
||||
PrintAndLog(" sample: hf mfu crdbl 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
if (blockNo < 0) {
|
||||
PrintAndLog("Wrong block number");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (blockNo > MAX_ULTRAC_BLOCKS ){
|
||||
PrintAndLog("Error: Maximum number of readable blocks is 47 for Ultralight-C Cards!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo, blockNo);
|
||||
|
||||
//Read Block
|
||||
UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}};
|
||||
SendCommand(&e);
|
||||
UsbCommand resp_c;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) {
|
||||
uint8_t isOK = resp_c.arg[0] & 0xff;
|
||||
uint8_t *data = resp_c.d.asBytes;
|
||||
|
||||
PrintAndLog("isOk: %02x", isOK);
|
||||
if (isOK)
|
||||
PrintAndLog("Data: %s", sprint_hex(data, 4));
|
||||
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Mifare Ultralight C Write Single Block
|
||||
//
|
||||
int CmdHF14AMfUCWrBl(const char *Cmd){
|
||||
|
||||
uint8_t blockNo = -1;
|
||||
bool chinese_card = FALSE;
|
||||
uint8_t bldata[16] = {0x00};
|
||||
UsbCommand resp;
|
||||
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
|
||||
if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
|
||||
PrintAndLog("Usage: hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
|
||||
PrintAndLog(" [block number]");
|
||||
PrintAndLog(" [block data] - (8 hex symbols)");
|
||||
PrintAndLog(" [w] - Chinese magic ultralight tag");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" sample: hf mfu cwrbl 0 01020304");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
blockNo = param_get8(Cmd, 0);
|
||||
if (blockNo > MAX_ULTRAC_BLOCKS ){
|
||||
PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (param_gethex(Cmd, 1, bldata, 8)) {
|
||||
PrintAndLog("Block data must include 8 HEX symbols");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strchr(Cmd,'w') != 0 || strchr(Cmd,'W') != 0 ) {
|
||||
chinese_card = TRUE;
|
||||
}
|
||||
|
||||
if ( blockNo <= 3 ) {
|
||||
if (!chinese_card){
|
||||
PrintAndLog("Access Denied");
|
||||
} else {
|
||||
PrintAndLog("--Special block no: 0x%02x", blockNo);
|
||||
PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(d.d.asBytes,bldata, 4);
|
||||
SendCommand(&d);
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk:%02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("--Block no : 0x%02x", blockNo);
|
||||
PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
|
||||
UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
|
||||
memcpy(e.d.asBytes,bldata, 4);
|
||||
SendCommand(&e);
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
uint8_t isOK = resp.arg[0] & 0xff;
|
||||
PrintAndLog("isOk : %02x", isOK);
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------
|
||||
// Menu Stuff
|
||||
//------------------------------------
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1,"This help"},
|
||||
{"dbg", CmdHF14AMfDbg, 0,"Set default debug mode"},
|
||||
{"info", CmdHF14AMfUInfo, 0,"Taginfo"},
|
||||
{"dump", CmdHF14AMfUDump, 0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"},
|
||||
{"rdbl", CmdHF14AMfURdBl, 0,"Read block - MIFARE Ultralight"},
|
||||
{"wrbl", CmdHF14AMfUWrBl, 0,"Write block - MIFARE Ultralight"},
|
||||
{"crdbl", CmdHF14AMfUCRdBl, 0,"Read block - MIFARE Ultralight C"},
|
||||
{"cwrbl", CmdHF14AMfUCWrBl, 0,"Write MIFARE Ultralight C block"},
|
||||
{"cauth", CmdHF14AMfucAuth, 0,"try a Ultralight C Authentication"},
|
||||
//{"testdes", CmdTestDES , 1, "Test DES"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdHFMFUltra(const char *Cmd){
|
||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHelp(const char *Cmd){
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
19
client/cmdhfmfu.h
Normal file
19
client/cmdhfmfu.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "cmdhfmf.h"
|
||||
#include "cmdhf14a.h"
|
||||
|
||||
//standard ultralight
|
||||
int CmdHF14AMfUWrBl(const char *Cmd);
|
||||
int CmdHF14AMfURdBl(const char *Cmd);
|
||||
|
||||
//Crypto Cards
|
||||
int CmdHF14AMfUCRdBl(const char *Cmd);
|
||||
int CmdHF14AMfUCRdCard(const char *Cmd);
|
||||
int CmdHF14AMfucAuth(const char *Cmd);
|
||||
|
||||
//general stuff
|
||||
int CmdHF14AMfUDump(const char *Cmd);
|
||||
void rol (uint8_t *data, const size_t len);
|
||||
|
||||
|
||||
int CmdHFMFUltra(const char *Cmd);
|
||||
int CmdHF14AMfUInfo(const char *Cmd);
|
217
client/cmdlf.c
217
client/cmdlf.c
|
@ -356,24 +356,155 @@ int CmdIndalaClone(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int usage_lf_read()
|
||||
{
|
||||
PrintAndLog("Usage: lf read");
|
||||
PrintAndLog("Options: ");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog("This function takes no arguments. ");
|
||||
PrintAndLog("Use 'lf config' to set parameters.");
|
||||
return 0;
|
||||
}
|
||||
int usage_lf_snoop()
|
||||
{
|
||||
PrintAndLog("Usage: lf snoop");
|
||||
PrintAndLog("Options: ");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog("This function takes no arguments. ");
|
||||
PrintAndLog("Use 'lf config' to set parameters.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usage_lf_config()
|
||||
{
|
||||
PrintAndLog("Usage: lf config [H|<divisor>] [b <bps>] [d <decim>] [a 0|1]");
|
||||
PrintAndLog("Options: ");
|
||||
PrintAndLog(" h This help");
|
||||
PrintAndLog(" L Low frequency (125 KHz)");
|
||||
PrintAndLog(" H High frequency (134 KHz)");
|
||||
PrintAndLog(" q <divisor> Manually set divisor. 88-> 134KHz, 95-> 125 Hz");
|
||||
PrintAndLog(" b <bps> Sets resolution of bits per sample. Default (max): 8");
|
||||
PrintAndLog(" d <decim> Sets decimation. A value of N saves only 1 in N samples. Default: 1");
|
||||
PrintAndLog(" a [0|1] Averaging - if set, will average the stored sample value when decimating. Default: 1");
|
||||
PrintAndLog(" t <threshold> Sets trigger threshold. 0 means no threshold");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf config b 8 L");
|
||||
PrintAndLog(" Samples at 125KHz, 8bps.");
|
||||
PrintAndLog(" lf config H b 4 d 3");
|
||||
PrintAndLog(" Samples at 134KHz, averages three samples into one, stored with ");
|
||||
PrintAndLog(" a resolution of 4 bits per sample.");
|
||||
PrintAndLog(" lf read");
|
||||
PrintAndLog(" Performs a read (active field)");
|
||||
PrintAndLog(" lf snoop");
|
||||
PrintAndLog(" Performs a snoop (no active field)");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFSetConfig(const char *Cmd)
|
||||
{
|
||||
|
||||
uint8_t divisor = 0;//Frequency divisor
|
||||
uint8_t bps = 0; // Bits per sample
|
||||
uint8_t decimation = 0; //How many to keep
|
||||
bool averaging = 1; // Defaults to true
|
||||
bool errors = FALSE;
|
||||
int trigger_threshold =-1;//Means no change
|
||||
uint8_t unsigned_trigg = 0;
|
||||
|
||||
uint8_t cmdp =0;
|
||||
while(param_getchar(Cmd, cmdp) != 0x00)
|
||||
{
|
||||
PrintAndLog("working %c", param_getchar(Cmd, cmdp));
|
||||
switch(param_getchar(Cmd, cmdp))
|
||||
{
|
||||
case 'h':
|
||||
return usage_lf_config();
|
||||
case 'H':
|
||||
divisor = 88;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'L':
|
||||
divisor = 95;
|
||||
cmdp++;
|
||||
break;
|
||||
case 'q':
|
||||
errors |= param_getdec(Cmd,cmdp+1,&divisor);
|
||||
cmdp+=2;
|
||||
break;
|
||||
case 't':
|
||||
errors |= param_getdec(Cmd,cmdp+1,&unsigned_trigg);
|
||||
cmdp+=2;
|
||||
if(!errors) trigger_threshold = unsigned_trigg;
|
||||
break;
|
||||
case 'b':
|
||||
errors |= param_getdec(Cmd,cmdp+1,&bps);
|
||||
cmdp+=2;
|
||||
break;
|
||||
case 'd':
|
||||
errors |= param_getdec(Cmd,cmdp+1,&decimation);
|
||||
cmdp+=2;
|
||||
break;
|
||||
case 'a':
|
||||
averaging = param_getchar(Cmd,cmdp+1) == '1';
|
||||
cmdp+=2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
if(errors) break;
|
||||
}
|
||||
if(cmdp == 0)
|
||||
{
|
||||
errors = 1;// No args
|
||||
}
|
||||
|
||||
//Validations
|
||||
if(errors)
|
||||
{
|
||||
return usage_lf_config();
|
||||
}
|
||||
//Bps is limited to 8, so fits in lower half of arg1
|
||||
if(bps >> 8) bps = 8;
|
||||
|
||||
sample_config config = {
|
||||
decimation,bps,averaging,divisor,trigger_threshold
|
||||
};
|
||||
//Averaging is a flag on high-bit of arg[1]
|
||||
UsbCommand c = {CMD_SET_LF_SAMPLING_CONFIG};
|
||||
memcpy(c.d.asBytes,&config,sizeof(sample_config));
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFRead(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||
|
||||
// 'h' means higher-low-frequency, 134 kHz
|
||||
if(*Cmd == 'h') {
|
||||
c.arg[0] = 1;
|
||||
} else if (*Cmd == '\0') {
|
||||
c.arg[0] = 0;
|
||||
} else if (sscanf(Cmd, "%"lli, &c.arg[0]) != 1) {
|
||||
PrintAndLog("Samples 1: 'lf read'");
|
||||
PrintAndLog(" 2: 'lf read h'");
|
||||
PrintAndLog(" 3: 'lf read <divisor>'");
|
||||
return 0;
|
||||
}
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
return 0;
|
||||
uint8_t cmdp =0;
|
||||
if(param_getchar(Cmd, cmdp) == 'h')
|
||||
{
|
||||
return usage_lf_read();
|
||||
}
|
||||
//And ship it to device
|
||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFSnoop(const char *Cmd)
|
||||
{
|
||||
uint8_t cmdp =0;
|
||||
if(param_getchar(Cmd, cmdp) == 'h')
|
||||
{
|
||||
return usage_lf_snoop();
|
||||
}
|
||||
|
||||
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ChkBitstream(const char *str)
|
||||
|
@ -388,7 +519,7 @@ static void ChkBitstream(const char *str)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//appears to attempt to simulate manchester
|
||||
int CmdLFSim(const char *Cmd)
|
||||
{
|
||||
int i,j;
|
||||
|
@ -450,30 +581,6 @@ int CmdLFSimManchester(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFSnoop(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES};
|
||||
|
||||
// 'h' means higher-low-frequency, 134 kHz
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = -1;
|
||||
|
||||
if (*Cmd == 'l') {
|
||||
sscanf(Cmd, "l %"lli, &c.arg[1]);
|
||||
} else if(*Cmd == 'h') {
|
||||
c.arg[0] = 1;
|
||||
sscanf(Cmd, "h %"lli, &c.arg[1]);
|
||||
} else if (sscanf(Cmd, "%"lli" %"lli, &c.arg[0], &c.arg[1]) < 1) {
|
||||
PrintAndLog("usage 1: snoop");
|
||||
PrintAndLog(" 2: snoop {l,h} [trigger threshold]");
|
||||
PrintAndLog(" 3: snoop <divisor> [trigger threshold]");
|
||||
return 0;
|
||||
}
|
||||
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdVchDemod(const char *Cmd)
|
||||
{
|
||||
|
@ -575,26 +682,41 @@ int CmdLFfind(const char *Cmd)
|
|||
}
|
||||
|
||||
PrintAndLog("NOTE: some demods output possible binary\n if it finds something that looks like a tag");
|
||||
PrintAndLog("Checking for known tags:");
|
||||
PrintAndLog("\nChecking for known tags:\n");
|
||||
ans=CmdFSKdemodIO("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("Valid IO Prox ID Found!");
|
||||
PrintAndLog("\nValid IO Prox ID Found!");
|
||||
return 1;
|
||||
}
|
||||
ans=CmdFSKdemodPyramid("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid Pyramid ID Found!");
|
||||
return 1;
|
||||
}
|
||||
ans=CmdFSKdemodParadox("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid Paradox ID Found!");
|
||||
return 1;
|
||||
}
|
||||
ans=CmdFSKdemodAWID("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid AWID ID Found!");
|
||||
return 1;
|
||||
}
|
||||
ans=CmdFSKdemodHID("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("Valid HID Prox ID Found!");
|
||||
PrintAndLog("\nValid HID Prox ID Found!");
|
||||
return 1;
|
||||
}
|
||||
//add psk and indala
|
||||
ans=CmdIndalaDecode("0");
|
||||
ans=CmdIndalaDecode("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("Valid Indala ID Found!");
|
||||
PrintAndLog("\nValid Indala ID Found!");
|
||||
return 1;
|
||||
}
|
||||
ans=Cmdaskmandemod("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("Valid EM410x ID Found!");
|
||||
PrintAndLog("\nValid EM410x ID Found!");
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("No Known Tags Found!\n");
|
||||
|
@ -606,12 +728,13 @@ static command_t CommandTable[] =
|
|||
{"help", CmdHelp, 1, "This help"},
|
||||
{"cmdread", CmdLFCommandRead, 0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
|
||||
{"em4x", CmdLFEM4X, 1, "{ EM4X RFIDs... }"},
|
||||
{"config", CmdLFSetConfig, 0, "Set config for LF sampling, bit/sample, decimation, frequency"},
|
||||
{"flexdemod", CmdFlexdemod, 1, "Demodulate samples for FlexPass"},
|
||||
{"hid", CmdLFHID, 1, "{ HID RFIDs... }"},
|
||||
{"io", CmdLFIO, 1, "{ ioProx tags... }"},
|
||||
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
||||
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
|
||||
{"read", CmdLFRead, 0, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
|
||||
{"read", CmdLFRead, 0, "Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
|
||||
{"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
|
||||
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
|
||||
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
|
||||
|
|
|
@ -29,110 +29,125 @@ size_t nbytes(size_t nbits) {
|
|||
|
||||
int CmdLFHitagList(const char *Cmd)
|
||||
{
|
||||
uint8_t got[TRACE_BUFFER_SIZE];
|
||||
GetFromBigBuf(got,sizeof(got),0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
uint8_t *got = malloc(USB_CMD_DATA_SIZE);
|
||||
|
||||
PrintAndLog("recorded activity:");
|
||||
PrintAndLog(" ETU :nbits: who bytes");
|
||||
PrintAndLog("---------+-----+----+-----------");
|
||||
|
||||
int i = 0;
|
||||
int prev = -1;
|
||||
int len = strlen(Cmd);
|
||||
|
||||
char filename[FILE_PATH_SIZE] = { 0x00 };
|
||||
FILE* pf = NULL;
|
||||
|
||||
if (len > FILE_PATH_SIZE)
|
||||
len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd, len);
|
||||
|
||||
if (strlen(filename) > 0) {
|
||||
if ((pf = fopen(filename,"wb")) == NULL) {
|
||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||
return 1;
|
||||
// Query for the actual size of the trace
|
||||
UsbCommand response;
|
||||
GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0);
|
||||
WaitForResponse(CMD_ACK, &response);
|
||||
uint16_t traceLen = response.arg[2];
|
||||
if (traceLen > USB_CMD_DATA_SIZE) {
|
||||
uint8_t *p = realloc(got, traceLen);
|
||||
if (p == NULL) {
|
||||
PrintAndLog("Cannot allocate memory for trace");
|
||||
free(got);
|
||||
return 2;
|
||||
}
|
||||
got = p;
|
||||
GetFromBigBuf(got, traceLen, 0);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
if(i >= TRACE_BUFFER_SIZE) { break; }
|
||||
|
||||
bool isResponse;
|
||||
int timestamp = *((uint32_t *)(got+i));
|
||||
if (timestamp & 0x80000000) {
|
||||
timestamp &= 0x7fffffff;
|
||||
isResponse = 1;
|
||||
} else {
|
||||
isResponse = 0;
|
||||
}
|
||||
|
||||
int parityBits = *((uint32_t *)(got+i+4));
|
||||
// 4 bytes of additional information...
|
||||
// maximum of 32 additional parity bit information
|
||||
//
|
||||
// TODO:
|
||||
// at each quarter bit period we can send power level (16 levels)
|
||||
// or each half bit period in 256 levels.
|
||||
|
||||
int bits = got[i+8];
|
||||
int len = nbytes(got[i+8]);
|
||||
|
||||
if (len > 100) {
|
||||
break;
|
||||
}
|
||||
if (i + len >= TRACE_BUFFER_SIZE) { break;}
|
||||
|
||||
uint8_t *frame = (got+i+9);
|
||||
|
||||
// Break and stick with current result if buffer was not completely full
|
||||
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
|
||||
|
||||
char line[1000] = "";
|
||||
int j;
|
||||
for (j = 0; j < len; j++) {
|
||||
int oddparity = 0x01;
|
||||
int k;
|
||||
|
||||
for (k=0;k<8;k++) {
|
||||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||
}
|
||||
|
||||
//if((parityBits >> (len - j - 1)) & 0x01) {
|
||||
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
||||
sprintf(line+(j*4), "%02x! ", frame[j]);
|
||||
}
|
||||
else {
|
||||
sprintf(line+(j*4), "%02x ", frame[j]);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog(" +%7d: %3d: %s %s",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
|
||||
|
||||
if (pf) {
|
||||
fprintf(pf," +%7d: %3d: %s %s\n",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
}
|
||||
|
||||
prev = timestamp;
|
||||
i += (len + 9);
|
||||
}
|
||||
|
||||
if (pf) {
|
||||
fclose(pf);
|
||||
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
|
||||
}
|
||||
PrintAndLog("recorded activity (TraceLen = %d bytes):");
|
||||
PrintAndLog(" ETU :nbits: who bytes");
|
||||
PrintAndLog("---------+-----+----+-----------");
|
||||
|
||||
return 0;
|
||||
int i = 0;
|
||||
int prev = -1;
|
||||
int len = strlen(Cmd);
|
||||
|
||||
char filename[FILE_PATH_SIZE] = { 0x00 };
|
||||
FILE* pf = NULL;
|
||||
|
||||
if (len > FILE_PATH_SIZE)
|
||||
len = FILE_PATH_SIZE;
|
||||
memcpy(filename, Cmd, len);
|
||||
|
||||
if (strlen(filename) > 0) {
|
||||
if ((pf = fopen(filename,"wb")) == NULL) {
|
||||
PrintAndLog("Error: Could not open file [%s]",filename);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
|
||||
if(i > traceLen) { break; }
|
||||
|
||||
bool isResponse;
|
||||
int timestamp = *((uint32_t *)(got+i));
|
||||
if (timestamp & 0x80000000) {
|
||||
timestamp &= 0x7fffffff;
|
||||
isResponse = 1;
|
||||
} else {
|
||||
isResponse = 0;
|
||||
}
|
||||
|
||||
int parityBits = *((uint32_t *)(got+i+4));
|
||||
// 4 bytes of additional information...
|
||||
// maximum of 32 additional parity bit information
|
||||
//
|
||||
// TODO:
|
||||
// at each quarter bit period we can send power level (16 levels)
|
||||
// or each half bit period in 256 levels.
|
||||
|
||||
int bits = got[i+8];
|
||||
int len = nbytes(got[i+8]);
|
||||
|
||||
if (len > 100) {
|
||||
break;
|
||||
}
|
||||
if (i + len > traceLen) { break;}
|
||||
|
||||
uint8_t *frame = (got+i+9);
|
||||
|
||||
// Break and stick with current result if buffer was not completely full
|
||||
if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
|
||||
|
||||
char line[1000] = "";
|
||||
int j;
|
||||
for (j = 0; j < len; j++) {
|
||||
int oddparity = 0x01;
|
||||
int k;
|
||||
|
||||
for (k=0;k<8;k++) {
|
||||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||
}
|
||||
|
||||
//if((parityBits >> (len - j - 1)) & 0x01) {
|
||||
if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
|
||||
sprintf(line+(j*4), "%02x! ", frame[j]);
|
||||
}
|
||||
else {
|
||||
sprintf(line+(j*4), "%02x ", frame[j]);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLog(" +%7d: %3d: %s %s",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
|
||||
if (pf) {
|
||||
fprintf(pf," +%7d: %3d: %s %s\n",
|
||||
(prev < 0 ? 0 : (timestamp - prev)),
|
||||
bits,
|
||||
(isResponse ? "TAG" : " "),
|
||||
line);
|
||||
}
|
||||
|
||||
prev = timestamp;
|
||||
i += (len + 9);
|
||||
}
|
||||
|
||||
if (pf) {
|
||||
fclose(pf);
|
||||
PrintAndLog("Recorded activity succesfully written to file: %s", filename);
|
||||
}
|
||||
|
||||
free(got);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLFHitagSnoop(const char *Cmd) {
|
||||
|
|
|
@ -273,7 +273,8 @@ int CmdTIWrite(const char *Cmd)
|
|||
UsbCommand c = {CMD_WRITE_TI_TYPE};
|
||||
int res = 0;
|
||||
|
||||
res = sscanf(Cmd, "0x%"PRIu64"x 0x%"PRIu64"x 0x%"PRIu64"x ", &c.arg[0], &c.arg[1], &c.arg[2]);
|
||||
res = sscanf(Cmd, "%012"llx" %012"llx" %012"llx"", &c.arg[0], &c.arg[1], &c.arg[2]);
|
||||
|
||||
if (res == 2) c.arg[2]=0;
|
||||
if (res < 2)
|
||||
PrintAndLog("Please specify the data as two hex strings, optionally the CRC as a third");
|
||||
|
|
|
@ -188,7 +188,6 @@ void UsbCommandReceived(UsbCommand *UC)
|
|||
} break;
|
||||
|
||||
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
|
||||
sample_buf_len += UC->arg[1];
|
||||
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
|
||||
} break;
|
||||
|
||||
|
|
|
@ -16,11 +16,9 @@
|
|||
#include "cmdmain.h"
|
||||
|
||||
uint8_t* sample_buf;
|
||||
size_t sample_buf_len;
|
||||
|
||||
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index)
|
||||
{
|
||||
sample_buf_len = 0;
|
||||
sample_buf = dest;
|
||||
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
|
||||
SendCommand(&c);
|
||||
|
|
|
@ -13,13 +13,9 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
//trace buffer size as defined in armsrc/apps.h TRACE_SIZE
|
||||
#define TRACE_BUFFER_SIZE 4096
|
||||
#define FILE_PATH_SIZE 1000
|
||||
#define SAMPLE_BUFFER_SIZE 64
|
||||
|
||||
extern uint8_t* sample_buf;
|
||||
extern size_t sample_buf_len;
|
||||
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
|
||||
|
||||
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "ui.h"
|
||||
#include "graph.h"
|
||||
|
@ -50,7 +51,11 @@ int ClearGraph(int redraw)
|
|||
|
||||
void setGraphBuf(uint8_t *buff, size_t size)
|
||||
{
|
||||
int i=0;
|
||||
if ( buff == NULL ) return;
|
||||
|
||||
uint16_t i = 0;
|
||||
if ( size > MAX_GRAPH_TRACE_LEN )
|
||||
size = MAX_GRAPH_TRACE_LEN;
|
||||
ClearGraph(0);
|
||||
for (; i < size; ++i){
|
||||
GraphBuffer[i]=buff[i]-128;
|
||||
|
@ -61,6 +66,8 @@ void setGraphBuf(uint8_t *buff, size_t size)
|
|||
}
|
||||
size_t getFromGraphBuf(uint8_t *buff)
|
||||
{
|
||||
if ( buff == NULL ) return 0;
|
||||
|
||||
uint32_t i;
|
||||
for (i=0;i<GraphTraceLen;++i){
|
||||
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
|
||||
|
@ -69,27 +76,64 @@ size_t getFromGraphBuf(uint8_t *buff)
|
|||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
// Get or auto-detect clock rate
|
||||
int GetClock(const char *str, int peak, int verbose)
|
||||
{
|
||||
int clock;
|
||||
sscanf(str, "%i", &clock);
|
||||
if (!strcmp(str, ""))
|
||||
clock = 0;
|
||||
int clock;
|
||||
sscanf(str, "%i", &clock);
|
||||
if (!strcmp(str, ""))
|
||||
clock = 0;
|
||||
|
||||
// Auto-detect clock
|
||||
if (!clock)
|
||||
{
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||
if (!clock)
|
||||
{
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t size = getFromGraphBuf(grph);
|
||||
clock = DetectASKClock(grph,size,0);
|
||||
if ( size == 0 ) {
|
||||
PrintAndLog("Failed to copy from graphbuffer");
|
||||
return -1;
|
||||
}
|
||||
clock = DetectASKClock(grph,size,0);
|
||||
// Only print this message if we're not looping something
|
||||
if (!verbose){
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
}
|
||||
}
|
||||
if (!verbose){
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
}
|
||||
}
|
||||
return clock;
|
||||
}
|
||||
|
||||
return clock;
|
||||
// A simple test to see if there is any data inside Graphbuffer.
|
||||
bool HasGraphData(){
|
||||
|
||||
if ( GraphTraceLen <= 0) {
|
||||
PrintAndLog("No data available, try reading something first");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Detect high and lows in Grapbuffer.
|
||||
// Only loops the first 256 values.
|
||||
void DetectHighLowInGraph(int *high, int *low, bool addFuzz) {
|
||||
|
||||
uint8_t loopMax = 255;
|
||||
if ( loopMax > GraphTraceLen)
|
||||
loopMax = GraphTraceLen;
|
||||
|
||||
for (uint8_t i = 0; i < loopMax; ++i) {
|
||||
if (GraphBuffer[i] > *high)
|
||||
*high = GraphBuffer[i];
|
||||
else if (GraphBuffer[i] < *low)
|
||||
*low = GraphBuffer[i];
|
||||
}
|
||||
|
||||
//12% fuzz in case highs and lows aren't clipped
|
||||
if (addFuzz) {
|
||||
*high = (int)(*high * .88);
|
||||
*low = (int)(*low * .88);
|
||||
}
|
||||
}
|
||||
|
||||
int GetNRZpskClock(const char *str, int peak, int verbose)
|
||||
|
@ -104,6 +148,10 @@ int GetNRZpskClock(const char *str, int peak, int verbose)
|
|||
{
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||
size_t size = getFromGraphBuf(grph);
|
||||
if ( size == 0 ) {
|
||||
PrintAndLog("Failed to copy from graphbuffer");
|
||||
return -1;
|
||||
}
|
||||
clock = DetectpskNRZClock(grph,size,0);
|
||||
// Only print this message if we're not looping something
|
||||
if (!verbose){
|
||||
|
|
|
@ -20,8 +20,12 @@ int GetClock(const char *str, int peak, int verbose);
|
|||
int GetNRZpskClock(const char *str, int peak, int verbose);
|
||||
void setGraphBuf(uint8_t *buff, size_t size);
|
||||
|
||||
#define MAX_GRAPH_TRACE_LEN (1024*128)
|
||||
bool HasGraphData();
|
||||
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);
|
||||
|
||||
// Max graph trace len: 40000 (bigbuf) * 8 (at 1 bit per sample)
|
||||
#define MAX_GRAPH_TRACE_LEN (40000 * 8 )
|
||||
|
||||
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
extern int GraphTraceLen;
|
||||
|
||||
#endif
|
||||
|
|
50
client/hid-flasher/Info.plist
Normal file
50
client/hid-flasher/Info.plist
Normal file
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<!-- This is a dummy driver which binds to Proxmark. It -->
|
||||
<!-- contains no actual code; its only purpose is to -->
|
||||
<!-- prevent Apple's USBHID driver from exclusively -->
|
||||
<!-- opening the device. -->
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string></string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.proxmark.driver.dummy</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>KEXT</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0d2</string>
|
||||
<key>IOKitPersonalities</key>
|
||||
<dict>
|
||||
<!-- The Proxmark3 USB interface -->
|
||||
<key>Proxmark3</key>
|
||||
<dict>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.apple.kpi.iokit</string>
|
||||
<key>IOClass</key>
|
||||
<string>IOService</string>
|
||||
<key>IOProviderClass</key>
|
||||
<string>IOUSBInterface</string>
|
||||
<key>bConfigurationValue</key>
|
||||
<integer>1</integer>
|
||||
<key>bInterfaceNumber</key>
|
||||
<integer>0</integer>
|
||||
<key>idProduct</key>
|
||||
<integer>19343</integer>
|
||||
<key>idVendor</key>
|
||||
<integer>39620</integer>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>OSBundleLibraries</key>
|
||||
<dict>
|
||||
<key>com.apple.iokit.IOUSBFamily</key>
|
||||
<string>1.8</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
48
client/hid-flasher/Makefile
Normal file
48
client/hid-flasher/Makefile
Normal file
|
@ -0,0 +1,48 @@
|
|||
#-----------------------------------------------------------------------------
|
||||
# This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
# at your option, any later version. See the LICENSE.txt file for the text of
|
||||
# the license.
|
||||
#-----------------------------------------------------------------------------
|
||||
include ../../common/Makefile.common
|
||||
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
#COMMON_FLAGS = -m32
|
||||
|
||||
VPATH = ../../common
|
||||
OBJDIR = obj
|
||||
|
||||
LDLIBS = -L/opt/local/lib -L/usr/local/lib -lusb -lreadline -lpthread
|
||||
LDFLAGS = $(COMMON_FLAGS)
|
||||
CFLAGS = -std=gnu99 -I. -I../include -I../common -I/opt/local/include -Wall -Wno-unused-function $(COMMON_FLAGS) -g -O3
|
||||
|
||||
CXXFLAGS =
|
||||
QTLDLIBS =
|
||||
|
||||
RM = rm -f
|
||||
BINS = flasher
|
||||
CLEAN = flasher flasher.exe $(OBJDIR)/*.o *.o
|
||||
|
||||
all: $(BINS)
|
||||
|
||||
flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(OBJDIR)/proxusb.o
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) $(CLEAN)
|
||||
|
||||
# must be run as root
|
||||
install_kext: Info.plist
|
||||
mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
|
||||
cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
|
||||
chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
|
||||
chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
|
||||
chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
|
||||
rm -rf /System/Library/Caches/com.apple.kext.caches
|
||||
touch /System/Library/Extensions
|
||||
@echo "*** You may need to reboot for the kext to take effect."
|
||||
|
||||
.PHONY: all clean
|
71
client/hid-flasher/elf.h
Normal file
71
client/hid-flasher/elf.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// ELF header
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __ELF_H__
|
||||
#define __ELF_H__
|
||||
|
||||
typedef struct {
|
||||
uint32_t p_type;
|
||||
uint32_t p_offset;
|
||||
uint32_t p_vaddr;
|
||||
uint32_t p_paddr;
|
||||
uint32_t p_filesz;
|
||||
uint32_t p_memsz;
|
||||
uint32_t p_flags;
|
||||
uint32_t p_align;
|
||||
} __attribute__((__packed__)) Elf32_Phdr;
|
||||
|
||||
#define EI_NIDENT 16
|
||||
|
||||
typedef struct {
|
||||
unsigned char e_ident[EI_NIDENT];
|
||||
uint16_t e_type;
|
||||
uint16_t e_machine;
|
||||
uint32_t e_version;
|
||||
uint32_t e_entry;
|
||||
uint32_t e_phoff;
|
||||
uint32_t e_shoff;
|
||||
uint32_t e_flags;
|
||||
uint16_t e_ehsize;
|
||||
uint16_t e_phentsize;
|
||||
uint16_t e_phnum;
|
||||
uint16_t e_shentsize;
|
||||
uint16_t e_shnum;
|
||||
uint16_t e_shtrndx;
|
||||
} __attribute__((__packed__)) Elf32_Ehdr;
|
||||
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
#define EV_CURRENT 1
|
||||
|
||||
#define ET_NONE 0
|
||||
#define ET_REL 1
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define ET_CORE 4
|
||||
|
||||
#define EM_ARM 0x28
|
||||
|
||||
#define PF_R 4
|
||||
#define PF_W 2
|
||||
#define PF_X 1
|
||||
|
||||
#endif
|
||||
|
478
client/hid-flasher/flash.c
Normal file
478
client/hid-flasher/flash.c
Normal file
|
@ -0,0 +1,478 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// ELF file flasher
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sleep.h"
|
||||
#include "proxusb.h"
|
||||
#include "flash.h"
|
||||
#include "elf.h"
|
||||
#include "proxendian.h"
|
||||
|
||||
// FIXME: what the fuckity fuck
|
||||
unsigned int current_command = CMD_UNKNOWN;
|
||||
|
||||
#define FLASH_START 0x100000
|
||||
#define FLASH_SIZE (256*1024)
|
||||
#define FLASH_END (FLASH_START + FLASH_SIZE)
|
||||
#define BOOTLOADER_SIZE 0x2000
|
||||
#define BOOTLOADER_END (FLASH_START + BOOTLOADER_SIZE)
|
||||
|
||||
#define BLOCK_SIZE 0x100
|
||||
|
||||
static const uint8_t elf_ident[] = {
|
||||
0x7f, 'E', 'L', 'F',
|
||||
ELFCLASS32,
|
||||
ELFDATA2LSB,
|
||||
EV_CURRENT
|
||||
};
|
||||
|
||||
// Turn PHDRs into flasher segments, checking for PHDR sanity and merging adjacent
|
||||
// unaligned segments if needed
|
||||
static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, int num_phdrs)
|
||||
{
|
||||
Elf32_Phdr *phdr = phdrs;
|
||||
flash_seg_t *seg;
|
||||
uint32_t last_end = 0;
|
||||
|
||||
ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs);
|
||||
if (!ctx->segments) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
ctx->num_segs = 0;
|
||||
seg = ctx->segments;
|
||||
|
||||
fprintf(stderr, "Loading usable ELF segments:\n");
|
||||
for (int i = 0; i < num_phdrs; i++) {
|
||||
if (le32(phdr->p_type) != PT_LOAD) {
|
||||
phdr++;
|
||||
continue;
|
||||
}
|
||||
uint32_t vaddr = le32(phdr->p_vaddr);
|
||||
uint32_t paddr = le32(phdr->p_paddr);
|
||||
uint32_t filesz = le32(phdr->p_filesz);
|
||||
uint32_t memsz = le32(phdr->p_memsz);
|
||||
uint32_t offset = le32(phdr->p_offset);
|
||||
uint32_t flags = le32(phdr->p_flags);
|
||||
if (!filesz) {
|
||||
phdr++;
|
||||
continue;
|
||||
}
|
||||
fprintf(stderr, "%d: V 0x%08x P 0x%08x (0x%08x->0x%08x) [%c%c%c] @0x%x\n",
|
||||
i, vaddr, paddr, filesz, memsz,
|
||||
flags & PF_R ? 'R' : ' ',
|
||||
flags & PF_W ? 'W' : ' ',
|
||||
flags & PF_X ? 'X' : ' ',
|
||||
offset);
|
||||
if (filesz != memsz) {
|
||||
fprintf(stderr, "Error: PHDR file size does not equal memory size\n"
|
||||
"(DATA+BSS PHDRs do not make sense on ROM platforms!)\n");
|
||||
return -1;
|
||||
}
|
||||
if (paddr < last_end) {
|
||||
fprintf(stderr, "Error: PHDRs not sorted or overlap\n");
|
||||
return -1;
|
||||
}
|
||||
if (paddr < FLASH_START || (paddr+filesz) > FLASH_END) {
|
||||
fprintf(stderr, "Error: PHDR is not contained in Flash\n");
|
||||
return -1;
|
||||
}
|
||||
if (vaddr >= FLASH_START && vaddr < FLASH_END && (flags & PF_W)) {
|
||||
fprintf(stderr, "Error: Flash VMA segment is writable\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
// make extra space if we need to move the data forward
|
||||
data = malloc(filesz + BLOCK_SIZE);
|
||||
if (!data) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
return -1;
|
||||
}
|
||||
if (fseek(fd, offset, SEEK_SET) < 0 || fread(data, 1, filesz, fd) != filesz) {
|
||||
fprintf(stderr, "Error while reading PHDR payload\n");
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t block_offset = paddr & (BLOCK_SIZE-1);
|
||||
if (block_offset) {
|
||||
if (ctx->num_segs) {
|
||||
flash_seg_t *prev_seg = seg - 1;
|
||||
uint32_t this_end = paddr + filesz;
|
||||
uint32_t this_firstblock = paddr & ~(BLOCK_SIZE-1);
|
||||
uint32_t prev_lastblock = (last_end - 1) & ~(BLOCK_SIZE-1);
|
||||
|
||||
if (this_firstblock == prev_lastblock) {
|
||||
uint32_t new_length = this_end - prev_seg->start;
|
||||
uint32_t this_offset = paddr - prev_seg->start;
|
||||
uint32_t hole = this_offset - prev_seg->length;
|
||||
uint8_t *new_data = malloc(new_length);
|
||||
if (!new_data) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
free(data);
|
||||
return -1;
|
||||
}
|
||||
memset(new_data, 0xff, new_length);
|
||||
memcpy(new_data, prev_seg->data, prev_seg->length);
|
||||
memcpy(new_data + this_offset, data, filesz);
|
||||
fprintf(stderr, "Note: Extending previous segment from 0x%x to 0x%x bytes\n",
|
||||
prev_seg->length, new_length);
|
||||
if (hole)
|
||||
fprintf(stderr, "Note: 0x%x-byte hole created\n", hole);
|
||||
free(data);
|
||||
free(prev_seg->data);
|
||||
prev_seg->data = new_data;
|
||||
prev_seg->length = new_length;
|
||||
last_end = this_end;
|
||||
phdr++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Warning: segment does not begin on a block boundary, will pad\n");
|
||||
memmove(data + block_offset, data, filesz);
|
||||
memset(data, 0xFF, block_offset);
|
||||
filesz += block_offset;
|
||||
paddr -= block_offset;
|
||||
}
|
||||
|
||||
seg->data = data;
|
||||
seg->start = paddr;
|
||||
seg->length = filesz;
|
||||
seg++;
|
||||
ctx->num_segs++;
|
||||
|
||||
last_end = paddr + filesz;
|
||||
phdr++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Sanity check segments and check for bootloader writes
|
||||
static int check_segs(flash_file_t *ctx, int can_write_bl) {
|
||||
for (int i = 0; i < ctx->num_segs; i++) {
|
||||
flash_seg_t *seg = &ctx->segments[i];
|
||||
|
||||
if (seg->start & (BLOCK_SIZE-1)) {
|
||||
fprintf(stderr, "Error: Segment is not aligned\n");
|
||||
return -1;
|
||||
}
|
||||
if (seg->start < FLASH_START) {
|
||||
fprintf(stderr, "Error: Segment is outside of flash bounds\n");
|
||||
return -1;
|
||||
}
|
||||
if (seg->start + seg->length > FLASH_END) {
|
||||
fprintf(stderr, "Error: Segment is outside of flash bounds\n");
|
||||
return -1;
|
||||
}
|
||||
if (!can_write_bl && seg->start < BOOTLOADER_END) {
|
||||
fprintf(stderr, "Attempted to write bootloader but bootloader writes are not enabled\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Load an ELF file and prepare it for flashing
|
||||
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl)
|
||||
{
|
||||
FILE *fd = NULL;
|
||||
Elf32_Ehdr ehdr;
|
||||
Elf32_Phdr *phdrs = NULL;
|
||||
int num_phdrs;
|
||||
int res;
|
||||
|
||||
fd = fopen(name, "rb");
|
||||
if (!fd) {
|
||||
fprintf(stderr, "Could not open file '%s': ", name);
|
||||
perror(NULL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Loading ELF file '%s'...\n", name);
|
||||
|
||||
if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) {
|
||||
fprintf(stderr, "Error while reading ELF file header\n");
|
||||
goto fail;
|
||||
}
|
||||
if (memcmp(ehdr.e_ident, elf_ident, sizeof(elf_ident))
|
||||
|| le32(ehdr.e_version) != 1)
|
||||
{
|
||||
fprintf(stderr, "Not an ELF file or wrong ELF type\n");
|
||||
goto fail;
|
||||
}
|
||||
if (le16(ehdr.e_type) != ET_EXEC) {
|
||||
fprintf(stderr, "ELF is not executable\n");
|
||||
goto fail;
|
||||
}
|
||||
if (le16(ehdr.e_machine) != EM_ARM) {
|
||||
fprintf(stderr, "Wrong ELF architecture\n");
|
||||
goto fail;
|
||||
}
|
||||
if (!ehdr.e_phnum || !ehdr.e_phoff) {
|
||||
fprintf(stderr, "ELF has no PHDRs\n");
|
||||
goto fail;
|
||||
}
|
||||
if (le16(ehdr.e_phentsize) != sizeof(Elf32_Phdr)) {
|
||||
// could be a structure padding issue...
|
||||
fprintf(stderr, "Either the ELF file or this code is made of fail\n");
|
||||
goto fail;
|
||||
}
|
||||
num_phdrs = le16(ehdr.e_phnum);
|
||||
|
||||
phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr));
|
||||
if (!phdrs) {
|
||||
fprintf(stderr, "Out of memory\n");
|
||||
goto fail;
|
||||
}
|
||||
if (fseek(fd, le32(ehdr.e_phoff), SEEK_SET) < 0) {
|
||||
fprintf(stderr, "Error while reading ELF PHDRs\n");
|
||||
goto fail;
|
||||
}
|
||||
if (fread(phdrs, sizeof(Elf32_Phdr), num_phdrs, fd) != num_phdrs) {
|
||||
fprintf(stderr, "Error while reading ELF PHDRs\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
res = build_segs_from_phdrs(ctx, fd, phdrs, num_phdrs);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
res = check_segs(ctx, can_write_bl);
|
||||
if (res < 0)
|
||||
goto fail;
|
||||
|
||||
free(phdrs);
|
||||
fclose(fd);
|
||||
ctx->filename = name;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
if (phdrs)
|
||||
free(phdrs);
|
||||
if (fd)
|
||||
fclose(fd);
|
||||
flash_free(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get the state of the proxmark, backwards compatible
|
||||
static int get_proxmark_state(uint32_t *state)
|
||||
{
|
||||
UsbCommand c;
|
||||
c.cmd = CMD_DEVICE_INFO;
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
ReceiveCommand(&resp);
|
||||
|
||||
// Three outcomes:
|
||||
// 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK
|
||||
// 2. The old os code will respond with CMD_DEBUG_PRINT_STRING and "unknown command"
|
||||
// 3. The new bootrom and os codes will respond with CMD_DEVICE_INFO and flags
|
||||
|
||||
switch (resp.cmd) {
|
||||
case CMD_ACK:
|
||||
*state = DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM;
|
||||
break;
|
||||
case CMD_DEBUG_PRINT_STRING:
|
||||
*state = DEVICE_INFO_FLAG_CURRENT_MODE_OS;
|
||||
break;
|
||||
case CMD_DEVICE_INFO:
|
||||
*state = resp.arg[0];
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: Couldn't get proxmark state, bad response type: 0x%04x\n", resp.cmd);
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Enter the bootloader to be able to start flashing
|
||||
static int enter_bootloader(void)
|
||||
{
|
||||
uint32_t state;
|
||||
|
||||
if (get_proxmark_state(&state) < 0)
|
||||
return -1;
|
||||
|
||||
if (state & DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM) {
|
||||
/* Already in flash state, we're done. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) {
|
||||
fprintf(stderr,"Entering bootloader...\n");
|
||||
UsbCommand c;
|
||||
memset(&c, 0, sizeof (c));
|
||||
|
||||
if ((state & DEVICE_INFO_FLAG_BOOTROM_PRESENT)
|
||||
&& (state & DEVICE_INFO_FLAG_OSIMAGE_PRESENT))
|
||||
{
|
||||
// New style handover: Send CMD_START_FLASH, which will reset the board
|
||||
// and enter the bootrom on the next boot.
|
||||
c.cmd = CMD_START_FLASH;
|
||||
SendCommand(&c);
|
||||
fprintf(stderr,"(Press and release the button only to abort)\n");
|
||||
} else {
|
||||
// Old style handover: Ask the user to press the button, then reset the board
|
||||
c.cmd = CMD_HARDWARE_RESET;
|
||||
SendCommand(&c);
|
||||
fprintf(stderr,"Press and hold down button NOW if your bootloader requires it.\n");
|
||||
}
|
||||
fprintf(stderr,"Waiting for Proxmark to reappear on USB...");
|
||||
|
||||
CloseProxmark();
|
||||
sleep(1);
|
||||
while (!OpenProxmark(0)) {
|
||||
sleep(1);
|
||||
fprintf(stderr, ".");
|
||||
}
|
||||
fprintf(stderr," Found.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Error: Unknown Proxmark mode\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int wait_for_ack(void)
|
||||
{
|
||||
UsbCommand ack;
|
||||
ReceiveCommand(&ack);
|
||||
if (ack.cmd != CMD_ACK) {
|
||||
printf("Error: Unexpected reply 0x%04x (expected ACK)\n", ack.cmd);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Go into flashing mode
|
||||
int flash_start_flashing(int enable_bl_writes)
|
||||
{
|
||||
uint32_t state;
|
||||
|
||||
if (enter_bootloader() < 0)
|
||||
return -1;
|
||||
|
||||
if (get_proxmark_state(&state) < 0)
|
||||
return -1;
|
||||
|
||||
if (state & DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH) {
|
||||
// This command is stupid. Why the heck does it care which area we're
|
||||
// flashing, as long as it's not the bootloader area? The mind boggles.
|
||||
UsbCommand c = {CMD_START_FLASH};
|
||||
|
||||
if (enable_bl_writes) {
|
||||
c.arg[0] = FLASH_START;
|
||||
c.arg[1] = FLASH_END;
|
||||
c.arg[2] = START_FLASH_MAGIC;
|
||||
} else {
|
||||
c.arg[0] = BOOTLOADER_END;
|
||||
c.arg[1] = FLASH_END;
|
||||
c.arg[2] = 0;
|
||||
}
|
||||
SendCommand(&c);
|
||||
return wait_for_ack();
|
||||
} else {
|
||||
fprintf(stderr, "Note: Your bootloader does not understand the new START_FLASH command\n");
|
||||
fprintf(stderr, " It is recommended that you update your bootloader\n\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_block(uint32_t address, uint8_t *data, uint32_t length)
|
||||
{
|
||||
uint8_t block_buf[BLOCK_SIZE];
|
||||
|
||||
memset(block_buf, 0xFF, BLOCK_SIZE);
|
||||
memcpy(block_buf, data, length);
|
||||
|
||||
UsbCommand c = {CMD_SETUP_WRITE};
|
||||
for (int i = 0; i < 240; i += 48) {
|
||||
memcpy(c.d.asBytes, block_buf + i, 48);
|
||||
c.arg[0] = i / 4;
|
||||
SendCommand(&c);
|
||||
if (wait_for_ack() < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
c.cmd = CMD_FINISH_WRITE;
|
||||
c.arg[0] = address;
|
||||
memcpy(c.d.asBytes, block_buf+240, 16);
|
||||
SendCommand(&c);
|
||||
return wait_for_ack();
|
||||
}
|
||||
|
||||
// Write a file's segments to Flash
|
||||
int flash_write(flash_file_t *ctx)
|
||||
{
|
||||
fprintf(stderr, "Writing segments for file: %s\n", ctx->filename);
|
||||
for (int i = 0; i < ctx->num_segs; i++) {
|
||||
flash_seg_t *seg = &ctx->segments[i];
|
||||
|
||||
uint32_t length = seg->length;
|
||||
uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE;
|
||||
uint32_t end = seg->start + length;
|
||||
|
||||
fprintf(stderr, " 0x%08x..0x%08x [0x%x / %d blocks]",
|
||||
seg->start, end - 1, length, blocks);
|
||||
|
||||
int block = 0;
|
||||
uint8_t *data = seg->data;
|
||||
uint32_t baddr = seg->start;
|
||||
|
||||
while (length) {
|
||||
uint32_t block_size = length;
|
||||
if (block_size > BLOCK_SIZE)
|
||||
block_size = BLOCK_SIZE;
|
||||
|
||||
if (write_block(baddr, data, block_size) < 0) {
|
||||
fprintf(stderr, " ERROR\n");
|
||||
fprintf(stderr, "Error writing block %d of %d\n", block, blocks);
|
||||
return -1;
|
||||
}
|
||||
|
||||
data += block_size;
|
||||
baddr += block_size;
|
||||
length -= block_size;
|
||||
block++;
|
||||
fprintf(stderr, ".");
|
||||
}
|
||||
fprintf(stderr, " OK\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// free a file context
|
||||
void flash_free(flash_file_t *ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
if (ctx->segments) {
|
||||
for (int i = 0; i < ctx->num_segs; i++)
|
||||
free(ctx->segments[i].data);
|
||||
free(ctx->segments);
|
||||
ctx->segments = NULL;
|
||||
ctx->num_segs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// just reset the unit
|
||||
int flash_stop_flashing(void) {
|
||||
UsbCommand c = {CMD_HARDWARE_RESET};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
35
client/hid-flasher/flash.h
Normal file
35
client/hid-flasher/flash.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flashing utility functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __FLASH_H__
|
||||
#define __FLASH_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "elf.h"
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
uint32_t start;
|
||||
uint32_t length;
|
||||
} flash_seg_t;
|
||||
|
||||
typedef struct {
|
||||
const char *filename;
|
||||
int can_write_bl;
|
||||
int num_segs;
|
||||
flash_seg_t *segments;
|
||||
} flash_file_t;
|
||||
|
||||
int flash_load(flash_file_t *ctx, const char *name, int can_write_bl);
|
||||
int flash_start_flashing(int enable_bl_writes);
|
||||
int flash_write(flash_file_t *ctx);
|
||||
void flash_free(flash_file_t *ctx);
|
||||
int flash_stop_flashing(void);
|
||||
|
||||
#endif
|
||||
|
93
client/hid-flasher/flasher.c
Normal file
93
client/hid-flasher/flasher.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Flasher frontend tool
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "sleep.h"
|
||||
#include "proxusb.h"
|
||||
#include "flash.h"
|
||||
|
||||
static void usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0);
|
||||
fprintf(stderr, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n");
|
||||
fprintf(stderr, "Example: %s path/to/osimage.elf path/to/fpgaimage.elf\n", argv0);
|
||||
}
|
||||
|
||||
#define MAX_FILES 4
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int can_write_bl = 0;
|
||||
int num_files = 0;
|
||||
int res;
|
||||
flash_file_t files[MAX_FILES];
|
||||
|
||||
memset(files, 0, sizeof(files));
|
||||
|
||||
if (argc < 2) {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
if (!strcmp(argv[i], "-b")) {
|
||||
can_write_bl = 1;
|
||||
} else {
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
res = flash_load(&files[num_files], argv[i], can_write_bl);
|
||||
if (res < 0) {
|
||||
fprintf(stderr, "Error while loading %s\n", argv[i]);
|
||||
return -1;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
num_files++;
|
||||
}
|
||||
}
|
||||
|
||||
usb_init();
|
||||
|
||||
fprintf(stderr, "Waiting for Proxmark to appear on USB...");
|
||||
while (!OpenProxmark(1)) {
|
||||
sleep(1);
|
||||
fprintf(stderr, ".");
|
||||
}
|
||||
fprintf(stderr, " Found.\n");
|
||||
|
||||
res = flash_start_flashing(can_write_bl);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
|
||||
fprintf(stderr, "\nFlashing...\n");
|
||||
|
||||
for (int i = 0; i < num_files; i++) {
|
||||
res = flash_write(&files[i]);
|
||||
if (res < 0)
|
||||
return -1;
|
||||
flash_free(&files[i]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
fprintf(stderr, "Resetting hardware...\n");
|
||||
|
||||
res = flash_stop_flashing();
|
||||
if (res < 0)
|
||||
return -1;
|
||||
|
||||
CloseProxmark();
|
||||
|
||||
fprintf(stderr, "All done.\n\n");
|
||||
fprintf(stderr, "Have a nice day!\n");
|
||||
|
||||
return 0;
|
||||
}
|
0
client/hid-flasher/obj/.dummy
Normal file
0
client/hid-flasher/obj/.dummy
Normal file
46
client/hid-flasher/proxendian.h
Normal file
46
client/hid-flasher/proxendian.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Endianness convenience functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PROXENDIAN_H__
|
||||
#define PROXENDIAN_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef WIN32
|
||||
# define HOST_LITTLE_ENDIAN
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
|
||||
# if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
|
||||
# error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
|
||||
# endif
|
||||
|
||||
# if BYTE_ORDER == LITTLE_ENDIAN
|
||||
# define HOST_LITTLE_ENDIAN
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef HOST_LITTLE_ENDIAN
|
||||
# define le16(x) (x)
|
||||
# define le32(x) (x)
|
||||
#else
|
||||
|
||||
static inline uint16_t le16(uint16_t v)
|
||||
{
|
||||
return (v>>8) | (v<<8);
|
||||
}
|
||||
|
||||
static inline uint32_t le32(uint32_t v)
|
||||
{
|
||||
return (le16(v)<<16) | (le16(v>>16));
|
||||
}
|
||||
#endif // HOST_LITTLE_ENDIAN
|
||||
|
||||
#endif // PROXENDIAN_H__
|
17
client/hid-flasher/proxmark3.h
Normal file
17
client/hid-flasher/proxmark3.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main binary
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PROXMARK3_H__
|
||||
#define PROXMARK3_H__
|
||||
|
||||
#define PROXPROMPT "proxmark3> "
|
||||
|
||||
#endif
|
222
client/hid-flasher/proxusb.c
Normal file
222
client/hid-flasher/proxusb.c
Normal file
|
@ -0,0 +1,222 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// USB utilities
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <usb.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sleep.h"
|
||||
#include "proxusb.h"
|
||||
#include "proxmark3.h"
|
||||
#include "usb_cmd.h"
|
||||
|
||||
// It seems to be missing for mingw
|
||||
#ifndef ETIMEDOUT
|
||||
#define ETIMEDOUT 116
|
||||
#endif
|
||||
|
||||
usb_dev_handle *devh = NULL;
|
||||
static unsigned int claimed_iface = 0;
|
||||
unsigned char return_on_error = 0;
|
||||
unsigned char error_occured = 0;
|
||||
extern unsigned int current_command;
|
||||
|
||||
void SendCommand(UsbCommand *c)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if 0
|
||||
printf("Sending %d bytes\n", sizeof(UsbCommand));
|
||||
#endif
|
||||
current_command = c->cmd;
|
||||
ret = usb_bulk_write(devh, 0x01, (char*)c, sizeof(UsbCommand), 1000);
|
||||
if (ret<0) {
|
||||
error_occured = 1;
|
||||
if (return_on_error)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "write failed: %s!\nTrying to reopen device...\n",
|
||||
usb_strerror());
|
||||
|
||||
if (devh) {
|
||||
usb_close(devh);
|
||||
devh = NULL;
|
||||
}
|
||||
while(!OpenProxmark(0)) { sleep(1); }
|
||||
printf(PROXPROMPT);
|
||||
fflush(NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool ReceiveCommandPoll(UsbCommand *c)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(c, 0, sizeof (UsbCommand));
|
||||
ret = usb_bulk_read(devh, 0x82, (char*)c, sizeof(UsbCommand), 500);
|
||||
if (ret<0) {
|
||||
if (ret != -ETIMEDOUT) {
|
||||
error_occured = 1;
|
||||
if (return_on_error)
|
||||
return false;
|
||||
|
||||
fprintf(stderr, "read failed: %s(%d)!\nTrying to reopen device...\n",
|
||||
usb_strerror(), ret);
|
||||
|
||||
if (devh) {
|
||||
usb_close(devh);
|
||||
devh = NULL;
|
||||
}
|
||||
while(!OpenProxmark(0)) { sleep(1); }
|
||||
printf(PROXPROMPT);
|
||||
fflush(NULL);
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ret && (ret < sizeof(UsbCommand))) {
|
||||
fprintf(stderr, "Read only %d instead of requested %d bytes!\n",
|
||||
ret, (int)sizeof(UsbCommand));
|
||||
}
|
||||
}
|
||||
|
||||
return ret > 0;
|
||||
}
|
||||
|
||||
void ReceiveCommand(UsbCommand *c)
|
||||
{
|
||||
// printf("%s()\n", __FUNCTION__);
|
||||
int retval = 0;
|
||||
do {
|
||||
retval = ReceiveCommandPoll(c);
|
||||
if (retval != 1) printf("ReceiveCommandPoll returned %d\n", retval);
|
||||
} while(retval<0);
|
||||
// printf("recv %x\n", c->cmd);
|
||||
}
|
||||
|
||||
usb_dev_handle* findProxmark(int verbose, unsigned int *iface)
|
||||
{
|
||||
struct usb_bus *busses, *bus;
|
||||
usb_dev_handle *handle = NULL;
|
||||
struct prox_unit units[50];
|
||||
int iUnit = 0;
|
||||
|
||||
usb_find_busses();
|
||||
usb_find_devices();
|
||||
|
||||
busses = usb_get_busses();
|
||||
|
||||
for (bus = busses; bus; bus = bus->next) {
|
||||
struct usb_device *dev;
|
||||
|
||||
for (dev = bus->devices; dev; dev = dev->next) {
|
||||
struct usb_device_descriptor *desc = &(dev->descriptor);
|
||||
|
||||
if ((desc->idProduct == 0x4b8f) && (desc->idVendor == 0x9ac4)) {
|
||||
handle = usb_open(dev);
|
||||
if (!handle) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "open fabiled: %s!\n", usb_strerror());
|
||||
//return NULL;
|
||||
continue;
|
||||
}
|
||||
*iface = dev->config[0].interface[0].altsetting[0].bInterfaceNumber;
|
||||
|
||||
struct prox_unit unit = {handle, {0}};
|
||||
usb_get_string_simple(handle, desc->iSerialNumber, unit.serial_number, sizeof(unit.serial_number));
|
||||
units[iUnit++] = unit;
|
||||
|
||||
//return handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iUnit > 0) {
|
||||
int iSelection = 0;
|
||||
|
||||
fprintf(stdout, "\nConnected units:\n");
|
||||
|
||||
for (int i = 0; i < iUnit; i++) {
|
||||
struct usb_device * dev = usb_device(units[i].handle);
|
||||
fprintf(stdout, "\t%d. SN: %s [%s/%s]\n", i+1, units[i].serial_number, dev->bus->dirname, dev->filename);
|
||||
}
|
||||
if (iUnit > 1) {
|
||||
while (iSelection < 1 || iSelection > iUnit) {
|
||||
fprintf(stdout, "Which unit do you want to connect to? ");
|
||||
fscanf(stdin, "%d", &iSelection);
|
||||
}
|
||||
}
|
||||
else
|
||||
iSelection = 1;
|
||||
iSelection --;
|
||||
|
||||
for (int i = 0; i < iUnit; i++) {
|
||||
if (iSelection == i) continue;
|
||||
usb_close(units[i].handle);
|
||||
units[i].handle = NULL;
|
||||
}
|
||||
|
||||
return units[iSelection].handle;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
usb_dev_handle* OpenProxmark(int verbose)
|
||||
{
|
||||
int ret;
|
||||
usb_dev_handle *handle = NULL;
|
||||
unsigned int iface;
|
||||
|
||||
handle = findProxmark(verbose, &iface);
|
||||
if (!handle)
|
||||
return NULL;
|
||||
|
||||
#ifdef __linux__
|
||||
/* detach kernel driver first */
|
||||
ret = usb_detach_kernel_driver_np(handle, iface);
|
||||
/* don't complain if no driver attached */
|
||||
if (ret<0 && ret != -61 && verbose)
|
||||
fprintf(stderr, "detach kernel driver failed: (%d) %s!\n", ret, usb_strerror());
|
||||
#endif
|
||||
|
||||
// Needed for Windows. Optional for Mac OS and Linux
|
||||
ret = usb_set_configuration(handle, 1);
|
||||
if (ret < 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "configuration set failed: %s!\n", usb_strerror());
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = usb_claim_interface(handle, iface);
|
||||
if (ret < 0) {
|
||||
if (verbose)
|
||||
fprintf(stderr, "claim failed: %s!\n", usb_strerror());
|
||||
return NULL;
|
||||
}
|
||||
claimed_iface = iface;
|
||||
devh = handle;
|
||||
return handle;
|
||||
}
|
||||
|
||||
void CloseProxmark(void)
|
||||
{
|
||||
usb_release_interface(devh, claimed_iface);
|
||||
usb_close(devh);
|
||||
devh = NULL;
|
||||
}
|
34
client/hid-flasher/proxusb.h
Normal file
34
client/hid-flasher/proxusb.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// USB utilities
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef PROXUSB_H__
|
||||
#define PROXUSB_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <usb.h>
|
||||
#include "usb_cmd.h"
|
||||
|
||||
extern unsigned char return_on_error;
|
||||
extern unsigned char error_occured;
|
||||
|
||||
void SendCommand(UsbCommand *c);
|
||||
bool ReceiveCommandPoll(UsbCommand *c);
|
||||
void ReceiveCommand(UsbCommand *c);
|
||||
struct usb_dev_handle* FindProxmark(int verbose, unsigned int *iface);
|
||||
struct usb_dev_handle* OpenProxmark(int verbose);
|
||||
void CloseProxmark(void);
|
||||
|
||||
struct prox_unit {
|
||||
usb_dev_handle *handle;
|
||||
char serial_number[256];
|
||||
};
|
||||
|
||||
#endif
|
24
client/hid-flasher/sleep.h
Normal file
24
client/hid-flasher/sleep.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// platform-independant sleep macros
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef SLEEP_H__
|
||||
#define SLEEP_H__
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#define sleep(n) Sleep(1000 * n)
|
||||
#define msleep(n) Sleep(n)
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#define msleep(n) usleep(1000 * n)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
165
client/hid-flasher/usb_cmd.h
Normal file
165
client/hid-flasher/usb_cmd.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Jonathan Westhues, Mar 2006
|
||||
// Edits by Gerhard de Koning Gans, Sep 2007
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Definitions for all the types of commands that may be sent over USB; our
|
||||
// own protocol.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __USB_CMD_H
|
||||
#define __USB_CMD_H
|
||||
#ifdef _MSC_VER
|
||||
typedef DWORD uint32_t;
|
||||
typedef BYTE uint8_t;
|
||||
#define PACKED
|
||||
// stuff
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#define PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t cmd;
|
||||
uint32_t arg[3];
|
||||
union {
|
||||
uint8_t asBytes[48];
|
||||
uint32_t asDwords[12];
|
||||
} d;
|
||||
} PACKED UsbCommand;
|
||||
|
||||
// For the bootloader
|
||||
#define CMD_DEVICE_INFO 0x0000
|
||||
#define CMD_SETUP_WRITE 0x0001
|
||||
#define CMD_FINISH_WRITE 0x0003
|
||||
#define CMD_HARDWARE_RESET 0x0004
|
||||
#define CMD_START_FLASH 0x0005
|
||||
#define CMD_NACK 0x00fe
|
||||
#define CMD_ACK 0x00ff
|
||||
|
||||
// For general mucking around
|
||||
#define CMD_DEBUG_PRINT_STRING 0x0100
|
||||
#define CMD_DEBUG_PRINT_INTEGERS 0x0101
|
||||
#define CMD_DEBUG_PRINT_BYTES 0x0102
|
||||
#define CMD_LCD_RESET 0x0103
|
||||
#define CMD_LCD 0x0104
|
||||
#define CMD_BUFF_CLEAR 0x0105
|
||||
#define CMD_READ_MEM 0x0106
|
||||
#define CMD_VERSION 0x0107
|
||||
|
||||
// For low-frequency tags
|
||||
#define CMD_READ_TI_TYPE 0x0202
|
||||
#define CMD_WRITE_TI_TYPE 0x0203
|
||||
#define CMD_DOWNLOADED_RAW_BITS_TI_TYPE 0x0204
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0205
|
||||
#define CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K 0x0206
|
||||
#define CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K 0x0207
|
||||
#define CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K 0x0208
|
||||
#define CMD_DOWNLOADED_SIM_SAMPLES_125K 0x0209
|
||||
#define CMD_SIMULATE_TAG_125K 0x020A
|
||||
#define CMD_HID_DEMOD_FSK 0x020B
|
||||
#define CMD_HID_SIM_TAG 0x020C
|
||||
#define CMD_SET_LF_DIVISOR 0x020D
|
||||
#define CMD_LF_SIMULATE_BIDIR 0x020E
|
||||
#define CMD_SET_ADC_MUX 0x020F
|
||||
#define CMD_HID_CLONE_TAG 0x0210
|
||||
#define CMD_EM410X_WRITE_TAG 0x0211
|
||||
#define CMD_INDALA_CLONE_TAG 0x0212
|
||||
// for 224 bits UID
|
||||
#define CMD_INDALA_CLONE_TAG_L 0x0213
|
||||
|
||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
// For the 13.56 MHz tags
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300
|
||||
#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301
|
||||
#define CMD_READ_SRI512_TAG 0x0303
|
||||
#define CMD_READ_SRIX4K_TAG 0x0304
|
||||
#define CMD_READER_ISO_15693 0x0310
|
||||
#define CMD_SIMTAG_ISO_15693 0x0311
|
||||
#define CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693 0x0312
|
||||
#define CMD_ISO_15693_COMMAND 0x0313
|
||||
#define CMD_ISO_15693_COMMAND_DONE 0x0314
|
||||
#define CMD_ISO_15693_FIND_AFI 0x0315
|
||||
#define CMD_ISO_15693_DEBUG 0x0316
|
||||
|
||||
// For Hitag2 transponders
|
||||
#define CMD_SNOOP_HITAG 0x0370
|
||||
#define CMD_SIMULATE_HITAG 0x0371
|
||||
#define CMD_READER_HITAG 0x0372
|
||||
|
||||
#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380
|
||||
#define CMD_SIMULATE_TAG_ISO_14443 0x0381
|
||||
#define CMD_SNOOP_ISO_14443 0x0382
|
||||
#define CMD_SNOOP_ISO_14443a 0x0383
|
||||
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384
|
||||
#define CMD_READER_ISO_14443a 0x0385
|
||||
#define CMD_SIMULATE_TAG_LEGIC_RF 0x0387
|
||||
#define CMD_READER_LEGIC_RF 0x0388
|
||||
#define CMD_WRITER_LEGIC_RF 0x0389
|
||||
#define CMD_EPA_PACE_COLLECT_NONCE 0x038A
|
||||
|
||||
#define CMD_SNOOP_ICLASS 0x0392
|
||||
#define CMD_SIMULATE_TAG_ICLASS 0x0393
|
||||
#define CMD_READER_ICLASS 0x0394
|
||||
|
||||
// For measurements of the antenna tuning
|
||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||
#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401
|
||||
#define CMD_MEASURED_ANTENNA_TUNING 0x0410
|
||||
#define CMD_LISTEN_READER_FIELD 0x0420
|
||||
|
||||
// For direct FPGA control
|
||||
#define CMD_FPGA_MAJOR_MODE_OFF 0x0500
|
||||
|
||||
// For mifare commands
|
||||
#define CMD_MIFARE_SET_DBGMODE 0x0600
|
||||
#define CMD_MIFARE_EML_MEMCLR 0x0601
|
||||
#define CMD_MIFARE_EML_MEMSET 0x0602
|
||||
#define CMD_MIFARE_EML_MEMGET 0x0603
|
||||
#define CMD_MIFARE_EML_CARDLOAD 0x0604
|
||||
#define CMD_MIFARE_EML_CSETBLOCK 0x0605
|
||||
#define CMD_MIFARE_EML_CGETBLOCK 0x0606
|
||||
|
||||
#define CMD_SIMULATE_MIFARE_CARD 0x0610
|
||||
|
||||
#define CMD_READER_MIFARE 0x0611
|
||||
#define CMD_MIFARE_NESTED 0x0612
|
||||
|
||||
#define CMD_MIFARE_READBL 0x0620
|
||||
#define CMD_MIFARE_READSC 0x0621
|
||||
#define CMD_MIFARE_WRITEBL 0x0622
|
||||
#define CMD_MIFARE_CHKKEYS 0x0623
|
||||
|
||||
#define CMD_MIFARE_SNIFFER 0x0630
|
||||
|
||||
#define CMD_UNKNOWN 0xFFFF
|
||||
|
||||
// CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
|
||||
/* Whether a bootloader that understands the common_area is present */
|
||||
#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0)
|
||||
|
||||
/* Whether a osimage that understands the common_area is present */
|
||||
#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1)
|
||||
|
||||
/* Set if the bootloader is currently executing */
|
||||
#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2)
|
||||
|
||||
/* Set if the OS is currently executing */
|
||||
#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3)
|
||||
|
||||
/* Set if this device understands the extend start flash command */
|
||||
#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4)
|
||||
|
||||
/* CMD_START_FLASH may have three arguments: start of area to flash,
|
||||
end of area to flash, optional magic.
|
||||
The bootrom will not allow to overwrite itself unless this magic
|
||||
is given as third parameter */
|
||||
|
||||
#define START_FLASH_MAGIC 0x54494f44 // 'DOIT'
|
||||
|
||||
#endif
|
|
@ -28,7 +28,13 @@
|
|||
#define POLARSSL_DES_H
|
||||
|
||||
//#include "config.h"
|
||||
|
||||
/**
|
||||
* \def POLARSSL_CIPHER_MODE_CBC
|
||||
*
|
||||
* Enable Cipher Block Chaining mode (CBC) for symmetric ciphers.
|
||||
*/
|
||||
#define POLARSSL_CIPHER_MODE_CBC
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32)
|
||||
|
|
|
@ -49,7 +49,7 @@ local _commands = {
|
|||
CMD_EM4X_WRITE_WORD = 0x0219,
|
||||
CMD_IO_DEMOD_FSK = 0x021A,
|
||||
CMD_IO_CLONE_TAG = 0x021B,
|
||||
CMD_EM410X_DEMOD = 0x021C,
|
||||
CMD_EM410X_DEMOD = 0x021c,
|
||||
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
--// For the 13.56 MHz tags
|
||||
|
|
|
@ -1,63 +1,195 @@
|
|||
local _names = {
|
||||
--[[
|
||||
--]]
|
||||
["0400"]="BASH",
|
||||
["1600"]="BOOMER" ,
|
||||
["1800"]="CAMO",
|
||||
["3000"]="CHOPCHOP" ,
|
||||
["2000"]="CYNDER",
|
||||
["6400"]="JET-VAC",
|
||||
["6700"]="FLASHWING",
|
||||
["7000"]="TREE REX",
|
||||
["7100"]="LIGHTCORE SHROOMBOOM",
|
||||
["1C00"]="DARK SPYRO",
|
||||
["0600"]="DINORANG" ,
|
||||
["1200"]="DOUBLE TROUBLE" ,
|
||||
["1500"]="DRILLSERGEANT" ,
|
||||
["1400"]="DROBOT",
|
||||
["0900"]="LIGHTCORE ERUPTOR" ,
|
||||
["0B00"]="FLAMESLINGER" ,
|
||||
["1F00"]="GHOST ROASTER",
|
||||
["0E00"]="GILL GRUNT" ,
|
||||
["1D00"]="HEX",
|
||||
["0A00"]="IGNITOR",
|
||||
["0300"]="LIGHTNINGROD",
|
||||
["0700"]="LIGHTCORE PRISM BREAK",
|
||||
["1500"]="SLAMBAM",
|
||||
["0000"]="WHIRLWIND",
|
||||
["0100"]="SONIC BOOM",
|
||||
["0200"]="WARNADO",
|
||||
["0300"]="LIGHTNINGROD",
|
||||
["0400"]="BASH",
|
||||
["0500"]="TERRAFIN",
|
||||
["0600"]="DINORANG" ,
|
||||
["0700"]="LIGHTCORE PRISM BREAK",
|
||||
["0800"]="SUNBURN",
|
||||
["0900"]="LIGHTCORE ERUPTOR",
|
||||
["0A00"]="IGNITOR",
|
||||
["0B00"]="FLAMESLINGER",
|
||||
["0C00"]="ZAP",
|
||||
["0D00"]="WHAM SHELL",
|
||||
["0E00"]="GILL GRUNT",
|
||||
["0F00"]="SLAMBAM",
|
||||
["1000"]="SPYRO",
|
||||
["1100"]="VOODOOD",
|
||||
["1200"]="DOUBLE TROUBLE",
|
||||
["1300"]="TRIGGER HAPPY",
|
||||
["1400"]="DROBOT",
|
||||
["1500"]="DRILLSERGEANT",
|
||||
["1600"]="BOOMER",
|
||||
["1700"]="WRECKING BALL",
|
||||
["1800"]="CAMO",
|
||||
["1900"]="ZOOK",
|
||||
["1A00"]="STEALTH ELF",
|
||||
["1B00"]="STUMP SMASH",
|
||||
["0800"]="SUNBURN",
|
||||
["0500"]="TERRAFIN",
|
||||
["1300"]="TRIGGER HAPPY",
|
||||
["1100"]="VOODOOD",
|
||||
["0200"]="WARNADO",
|
||||
["0D00"]="WHAM SHELL",
|
||||
["0000"]="WHIRLWIND",
|
||||
["1700"]="WRECKING BALL",
|
||||
["0C00"]="ZAP",
|
||||
["1900"]="ZOOK",
|
||||
["0300"]="DRAGON",
|
||||
["012D"]="ICE",
|
||||
["012E"]="PIRATE",
|
||||
["0130"]="PVPUNLOCK",
|
||||
["012F"]="UNDEAD",
|
||||
["0200"]="ANVIL" ,
|
||||
["1D00"]="HEX",
|
||||
["1C00"]="DARK SPYRO",
|
||||
["1E00"]="CHOPCHOP",
|
||||
["1F00"]="GHOST ROASTER",
|
||||
["2000"]="CYNDER",
|
||||
--[[
|
||||
GIANTS
|
||||
--]]
|
||||
["6400"]="GIANT JET-VAC",
|
||||
["6500"]="GIANT SWARM",
|
||||
["6600"]="GIANT CRUSHER",
|
||||
["6700"]="GIANT FLASHWING",
|
||||
["6800"]="GIANT HOTHEAD",
|
||||
["6900"]="GIANT HOTDOG",
|
||||
["6A00"]="GIANT CHILL",
|
||||
["6B00"]="GIANT THUMPBACK",
|
||||
["6C00"]="GIANT POPFIZZ",
|
||||
["6D00"]="GIANT NINJINI",
|
||||
["6E00"]="GIANT BOUNCER",
|
||||
["6F00"]="GIANT SPROCKET",
|
||||
["7000"]="GIANT TREE REX",
|
||||
["7100"]="LIGHTCORE SHROOMBOOM",
|
||||
["7200"]="GIANT EYEBROAWL",
|
||||
["7300"]="GIANT FRIGHTRIDER",
|
||||
|
||||
--[[
|
||||
ITEM
|
||||
--]]
|
||||
["C800"]="ANVIL",
|
||||
["C900"]="SECRET STASH",
|
||||
["CA00"]="REGENERATION",
|
||||
["CD00"]="SHIELD",
|
||||
["CB00"]="CROSSED SWORDS",
|
||||
["CC00"]="HOURGLASS",
|
||||
["CA00"]="REGENERATION",
|
||||
["C900"]="SECRET STASH",
|
||||
["CD00"]="SHIELD",
|
||||
["CF00"]="SPARX",
|
||||
["CE00"]="SPEED BOOTS",
|
||||
["CF00"]="SPARX",
|
||||
["D000"]="CANNON",
|
||||
["D100"]="SCORPIONSTRIKER",
|
||||
|
||||
--[[
|
||||
ITEM TRAPS
|
||||
--]]
|
||||
["D200"]="MAGIC TRAP",
|
||||
["D300"]="WATER TRAP",
|
||||
["D400"]="AIR TRAP",
|
||||
["D600"]="TECH TRAP",
|
||||
["D700"]="FIRE TRAP",
|
||||
["D800"]="EARTH TRAP",
|
||||
["D900"]="LIFE TRAP",
|
||||
["DA00"]="DARK TRAP",
|
||||
["DB00"]="LIGHT TRAP",
|
||||
["DC00"]="KAOS TRAP",
|
||||
|
||||
--[[
|
||||
ITEM
|
||||
--]]
|
||||
["E600"]="HAND OF FATE",
|
||||
["E700"]="PIGGYBANK",
|
||||
["E800"]="ROCKET RAM",
|
||||
["E900"]="TIKI SPEAKY",
|
||||
|
||||
|
||||
--[[
|
||||
EXPANSION
|
||||
--]]
|
||||
["012C"]="DRAGON",
|
||||
["012D"]="ICE",
|
||||
["012E"]="PIRATE",
|
||||
["012F"]="UNDEAD",
|
||||
["0130"]="PVPUNLOCK",
|
||||
["0131"]="MIRROR OF MYSTERY",
|
||||
["0132"]="NIGHTMARE EXPRESS",
|
||||
["0133"]="SUNSCRAPER SPIRE",
|
||||
["0134"]="MIDNIGHT MUSEUM",
|
||||
|
||||
--[[
|
||||
LEGENDARY
|
||||
--]]
|
||||
["0194"]="LEGENDARY BASH",
|
||||
["0430"]="LEGENDARY CHOPCHOP",
|
||||
["01A0"]="LEGENDARY SPYRO",
|
||||
["01A3"]="LEGENDARY TRIGGER HAPPY",
|
||||
["0202"]="PET GILL GRUNT",
|
||||
["020E"]="PET STEALTH ELF",
|
||||
["01AE"]="LEGENDARY CHOPCHOP",
|
||||
|
||||
--[[
|
||||
TRAPTEAM
|
||||
--]]
|
||||
["01C2"]="TRAPTEAM GUSTO",
|
||||
["01C3"]="TRAPTEAM THUNDERBOLT",
|
||||
["01C4"]="TRAPTEAM FLINGKONG",
|
||||
["01C5"]="TRAPTEAM BLADES",
|
||||
["01C6"]="TRAPTEAM WALLOP",
|
||||
["01C7"]="TRAPTEAM HEADRUSH",
|
||||
["01C8"]="TRAPTEAM FISTBUMP",
|
||||
["01C9"]="TRAPTEAM ROCKYROLL",
|
||||
["01CA"]="TRAPTEAM WILDFIRE",
|
||||
["01CB"]="TRAPTEAM KABOOM",
|
||||
["01CC"]="TRAPTEAM TRAILBLAZER",
|
||||
["01CD"]="TRAPTEAM TORCH",
|
||||
["01CE"]="TRAPTEAM SNAPSHOT",
|
||||
["01CF"]="TRAPTEAM LOBSTAR",
|
||||
["01D0"]="TRAPTEAM FLIPWRECK",
|
||||
["01D1"]="TRAPTEAM ECHO",
|
||||
["01D2"]="TRAPTEAM BLASTERMIND",
|
||||
["01D3"]="TRAPTEAM ENIGMA",
|
||||
["01D4"]="TRAPTEAM DEJAVU",
|
||||
["01D5"]="TRAPTEAM COBRA CADABRA",
|
||||
["01D6"]="TRAPTEAM JAWBREAKER",
|
||||
["01D7"]="TRAPTEAM GEARSHIFT",
|
||||
["01D8"]="TRAPTEAM CHOPPER",
|
||||
["01D9"]="TRAPTEAM TREADHEAD",
|
||||
["01DA"]="TRAPTEAM BUSHWHACK",
|
||||
["01DB"]="TRAPTEAM TUFF LUCK",
|
||||
["01DC"]="TRAPTEAM FOODFIGHT",
|
||||
["01DD"]="TRAPTEAM HIGHFIVE",
|
||||
["01DE"]="TRAPTEAM KRYPTKING",
|
||||
["01DF"]="TRAPTEAM SHORTCUT",
|
||||
["01E0"]="TRAPTEAM BATSPIN",
|
||||
["01E1"]="TRAPTEAM FUNNYBONE",
|
||||
["01E2"]="TRAPTEAM KNIGHTLIGHT",
|
||||
["01E3"]="TRAPTEAM SPOTLIGHT",
|
||||
["01E4"]="TRAPTEAM KNIGHTMARE",
|
||||
["01E5"]="TRAPTEAM BLACKOUT",
|
||||
|
||||
--[[
|
||||
PET
|
||||
--]]
|
||||
["01F6"]="PET BOP",
|
||||
["01F7"]="PET SPRY",
|
||||
["01F8"]="PET HIJINX",
|
||||
["01F9"]="PET TERRAFIN",
|
||||
["01FA"]="PET BREEZE",
|
||||
["01FB"]="PET WEERUPTOR",
|
||||
["01FC"]="PET PETVAC",
|
||||
["01FD"]="PET SMALLFRY",
|
||||
["01FE"]="PET DROBIT",
|
||||
["0202"]="PET GILL GRUNT",
|
||||
["0207"]="PET TRIGGER HAPPY",
|
||||
["020E"]="PET STEALTH ELF",
|
||||
["021C"]="PET BARKLEY",
|
||||
["021D"]="PET THUMPLING",
|
||||
["021E"]="PET MINI JINI",
|
||||
["021F"]="PET EYE SMALL",
|
||||
|
||||
--[[
|
||||
SWAP FORCE
|
||||
--]]
|
||||
["0BB8"]="SWAPFORCE SCRATCH",
|
||||
["0BB9"]="SWAPFORCE POPTHORN",
|
||||
["0BBA"]="SWAPFORCE SLOBBER TOOTH",
|
||||
["0BBB"]="SWAPFORCE SCORP",
|
||||
["0BBC"]="SWAPFORCE HOG WILD FRYNO",
|
||||
["0BBD"]="SWAPFORCE SMOLDER DASH",
|
||||
["0BBE"]="SWAPFORCE BUMBLE BLAST",
|
||||
["0BBF"]="SWAPFORCE ZOOLOU",
|
||||
["0BC0"]="SWAPFORCE DUNE BUG",
|
||||
["0BC1"]="SWAPFORCE STAR STRIKE",
|
||||
["0BC2"]="SWAPFORCE COUNTDOWN",
|
||||
["0BC3"]="SWAPFORCE WINDUP",
|
||||
["0BC4"]="SWAPFORCE ROLLER BRAWL",
|
||||
["0BC5"]="SWAPFORCE GRIM CREEPER",
|
||||
["0BC6"]="SWAPFORCE RIPTIDE",
|
||||
["0BC7"]="SWAPFORCE PUNKSHOCK",
|
||||
}
|
||||
return _names
|
||||
|
|
|
@ -108,6 +108,24 @@ local Utils =
|
|||
return retval
|
||||
end,
|
||||
|
||||
-- input parameter is a string
|
||||
-- Swaps the endianess and returns a string,
|
||||
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||
SwapEndiannessStr = function(s, len)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return '' end
|
||||
if type(s) ~= 'string' then return nil end
|
||||
|
||||
local retval
|
||||
if len == 16 then
|
||||
retval = s:sub(3,4)..s:sub(1,2)
|
||||
elseif len == 24 then
|
||||
retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
elseif len == 32 then
|
||||
retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2)
|
||||
end
|
||||
return retval
|
||||
end,
|
||||
------------ CONVERSIONS
|
||||
|
||||
--
|
||||
|
@ -116,7 +134,7 @@ local Utils =
|
|||
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
|
||||
while IN>0 do
|
||||
I=I+1
|
||||
IN,D=math.floor(IN/B),math.mod(IN,B)+1
|
||||
IN , D = math.floor(IN/B), math.modf(IN,B)+1
|
||||
OUT=string.sub(K,D,D)..OUT
|
||||
end
|
||||
return OUT
|
||||
|
|
|
@ -232,14 +232,27 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
|||
// "MAGIC" CARD
|
||||
|
||||
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
||||
|
||||
uint8_t oldblock0[16] = {0x00};
|
||||
uint8_t block0[16] = {0x00};
|
||||
memcpy(block0, uid, 4);
|
||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // Mifare UID BCC
|
||||
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7)
|
||||
block0[5] = 0x08;
|
||||
block0[6] = 0x04;
|
||||
block0[7] = 0x00;
|
||||
//block0[5] = 0x08;
|
||||
//block0[6] = 0x04;
|
||||
//block0[7] = 0x00;
|
||||
|
||||
block0[5] = 0x01; //sak
|
||||
block0[6] = 0x01;
|
||||
block0[7] = 0x0f;
|
||||
|
||||
int old = mfCGetBlock(0, oldblock0, CSETBLOCK_SINGLE_OPER);
|
||||
if ( old == 0) {
|
||||
memcpy(block0+8, oldblock0+8, 8);
|
||||
PrintAndLog("block 0: %s", sprint_hex(block0,16));
|
||||
} else {
|
||||
PrintAndLog("Couldn't get olddata. Will write over the last bytes of Block 0.");
|
||||
}
|
||||
return mfCSetBlock(0, block0, oldUID, wantWipe, CSETBLOCK_SINGLE_OPER);
|
||||
}
|
||||
|
||||
|
@ -253,8 +266,10 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
|
|||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
if (uid != NULL) memcpy(uid, resp.d.asBytes, 4);
|
||||
if (!isOK) return 2;
|
||||
if (uid != NULL)
|
||||
memcpy(uid, resp.d.asBytes, 4);
|
||||
if (!isOK)
|
||||
return 2;
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
return 1;
|
||||
|
@ -286,9 +301,9 @@ int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) {
|
|||
static uint8_t trailerAccessBytes[4] = {0x08, 0x77, 0x8F, 0x00};
|
||||
|
||||
// variables
|
||||
char logHexFileName[200] = {0x00};
|
||||
char logHexFileName[FILE_PATH_SIZE] = {0x00};
|
||||
static uint8_t traceCard[4096] = {0x00};
|
||||
static char traceFileName[200] = {0x00};
|
||||
static char traceFileName[FILE_PATH_SIZE] = {0x00};
|
||||
static int traceState = TRACE_IDLE;
|
||||
static uint8_t traceCurBlock = 0;
|
||||
static uint8_t traceCurKey = 0;
|
||||
|
@ -323,20 +338,28 @@ int isBlockTrailer(int blockN) {
|
|||
|
||||
int loadTraceCard(uint8_t *tuid) {
|
||||
FILE * f;
|
||||
char buf[64];
|
||||
uint8_t buf8[64];
|
||||
char buf[64] = {0x00};
|
||||
uint8_t buf8[64] = {0x00};
|
||||
int i, blockNum;
|
||||
|
||||
if (!isTraceCardEmpty()) saveTraceCard();
|
||||
if (!isTraceCardEmpty())
|
||||
saveTraceCard();
|
||||
|
||||
memset(traceCard, 0x00, 4096);
|
||||
memcpy(traceCard, tuid + 3, 4);
|
||||
|
||||
FillFileNameByUID(traceFileName, tuid, ".eml", 7);
|
||||
|
||||
f = fopen(traceFileName, "r");
|
||||
if (!f) return 1;
|
||||
if (!f) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
blockNum = 0;
|
||||
|
||||
while(!feof(f)){
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||
PrintAndLog("File reading error.");
|
||||
|
@ -368,22 +391,30 @@ int saveTraceCard(void) {
|
|||
if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0;
|
||||
|
||||
f = fopen(traceFileName, "w+");
|
||||
if ( !f ) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++) { // blocks
|
||||
for (int j = 0; j < 16; j++) // bytes
|
||||
fprintf(f, "%02x", *(traceCard + i * 16 + j));
|
||||
fprintf(f,"\n");
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mfTraceInit(uint8_t *tuid, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) {
|
||||
|
||||
if (traceCrypto1) crypto1_destroy(traceCrypto1);
|
||||
if (traceCrypto1)
|
||||
crypto1_destroy(traceCrypto1);
|
||||
|
||||
traceCrypto1 = NULL;
|
||||
|
||||
if (wantSaveToEmlFile) loadTraceCard(tuid);
|
||||
if (wantSaveToEmlFile)
|
||||
loadTraceCard(tuid);
|
||||
|
||||
traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3];
|
||||
traceCard[5] = sak;
|
||||
memcpy(&traceCard[6], atqa, 2);
|
||||
|
|
|
@ -47,7 +47,7 @@ typedef struct {
|
|||
int foundKey[2];
|
||||
} sector;
|
||||
|
||||
extern char logHexFileName[200];
|
||||
extern char logHexFileName[FILE_PATH_SIZE];
|
||||
|
||||
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate);
|
||||
int mfCheckKeys (uint8_t blockNo, uint8_t keyType, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key);
|
||||
|
|
63
client/scripts/remagic.lua
Normal file
63
client/scripts/remagic.lua
Normal file
|
@ -0,0 +1,63 @@
|
|||
local getopt = require('getopt')
|
||||
|
||||
example = "script run remagic"
|
||||
author = "Iceman"
|
||||
|
||||
desc =
|
||||
[[
|
||||
This is a script that tries to bring back a chinese magic card (1k generation1)
|
||||
from the dead when it's block 0 has been written with bad values.
|
||||
|
||||
Arguments:
|
||||
-h this help
|
||||
]]
|
||||
---
|
||||
-- A debug printout-function
|
||||
function dbg(args)
|
||||
if DEBUG then
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
function oops(err)
|
||||
print("ERROR: ",err)
|
||||
end
|
||||
|
||||
---
|
||||
-- Usage help
|
||||
function help()
|
||||
print(desc)
|
||||
print("Example usage")
|
||||
print(example)
|
||||
end
|
||||
|
||||
---
|
||||
-- The main entry point
|
||||
function main(args)
|
||||
|
||||
|
||||
-- Read the parameters
|
||||
for o, a in getopt.getopt(args, 'h') do
|
||||
if o == "h" then help() return end
|
||||
end
|
||||
|
||||
local _cmds = {
|
||||
--[[
|
||||
--]]
|
||||
[0] = "hf 14a raw -p -a -b 7 40",
|
||||
[1] = "hf 14a raw -p -a 43",
|
||||
[2] = "hf 14a raw -c -p -a A000",
|
||||
[3] = "hf 14a raw -c -p -a 01 02 03 04 04 98 02 00 00 00 00 00 00 00 10 01",
|
||||
}
|
||||
core.clearCommandBuffer()
|
||||
|
||||
local i
|
||||
--for _,c in pairs(_cmds) do
|
||||
for i = 0, 3 do
|
||||
print ( _cmds[i] )
|
||||
core.console( _cmds[i] )
|
||||
end
|
||||
end
|
||||
|
||||
main(args)
|
173
client/scripts/test_t55x7_psk.lua
Normal file
173
client/scripts/test_t55x7_psk.lua
Normal file
|
@ -0,0 +1,173 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local bin = require('bin')
|
||||
local utils = require('utils')
|
||||
local dumplib = require('html_dumplib')
|
||||
|
||||
example =[[
|
||||
1. script run tracetest
|
||||
2. script run tracetest -o
|
||||
|
||||
]]
|
||||
author = "Iceman"
|
||||
usage = "script run test_t55x7_psk -o <filename>"
|
||||
desc =[[
|
||||
This script will program a T55x7 TAG with the configuration: block 0x00 data 0x00088040
|
||||
The outlined procedure is as following:
|
||||
|
||||
"lf t55xx write 0 00088040"
|
||||
"lf read"
|
||||
"data samples"
|
||||
"data pskdet"
|
||||
"data psknrz"
|
||||
"data pskindala"
|
||||
"data psknrzraw"
|
||||
|
||||
Loop OUTER:
|
||||
change the configuretion block 0 with:
|
||||
-xxxx8xxx = PSK RF/2 with Manchester modulation
|
||||
-xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes)
|
||||
-xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high)
|
||||
-xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
|
||||
Loop INNER
|
||||
for each outer configuration, also do
|
||||
XXXXX0XX = PSK RF/2
|
||||
XXXXX4XX = PSK RF/4
|
||||
XXXXX8XX = PSK RF/8
|
||||
|
||||
In all 12 individual test for the PSK demod
|
||||
|
||||
Arguments:
|
||||
-h : this help
|
||||
-o : logfile name
|
||||
]]
|
||||
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
local DEBUG = true -- the debug flag
|
||||
|
||||
--BLOCK 0 = 00088040
|
||||
local config1 = '0008'
|
||||
local config2 = '40'
|
||||
|
||||
local procedurecmds = {
|
||||
[1] = '%s%s%s%s',
|
||||
[2] = 'lf read',
|
||||
--[3] = '',
|
||||
[3] = 'data samples',
|
||||
[4] = 'data pskdetectclock',
|
||||
[5] = 'data psknrzrawdemod',
|
||||
[6] = 'data pskindalademod',
|
||||
}
|
||||
|
||||
---
|
||||
-- A debug printout-function
|
||||
function dbg(args)
|
||||
if not DEBUG then
|
||||
return
|
||||
end
|
||||
|
||||
if type(args) == "table" then
|
||||
local i = 1
|
||||
while args[i] do
|
||||
dbg(args[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
function oops(err)
|
||||
print("ERROR: ",err)
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
function help()
|
||||
print(desc)
|
||||
print("Example usage")
|
||||
print(example)
|
||||
end
|
||||
--
|
||||
-- Exit message
|
||||
function ExitMsg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print(msg)
|
||||
print()
|
||||
end
|
||||
|
||||
function pskTest(modulation)
|
||||
local y
|
||||
for y = 0, 8, 4 do
|
||||
for _ = 1, #procedurecmds do
|
||||
local cmd = procedurecmds[_]
|
||||
|
||||
if #cmd == 0 then
|
||||
|
||||
elseif _ == 1 then
|
||||
|
||||
dbg("Writing to T55x7 TAG")
|
||||
|
||||
local configdata = cmd:format( config1, modulation , y, config2)
|
||||
|
||||
dbg( configdata)
|
||||
|
||||
local writecommand = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = configdata ,arg2 = 0, arg3 = 0}
|
||||
local err = core.SendCommand(writecommand:getBytes())
|
||||
if err then return oops(err) end
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
|
||||
if response then
|
||||
local count,cmd,arg0 = bin.unpack('LL',response)
|
||||
if(arg0==1) then
|
||||
dbg("Writing success")
|
||||
else
|
||||
return nil, "Couldn't read block.."
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
dbg(cmd)
|
||||
core.console( cmd )
|
||||
end
|
||||
end
|
||||
core.clearCommandBuffer()
|
||||
end
|
||||
print( string.rep('--',20) )
|
||||
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local outputTemplate = os.date("testpsk_%Y-%m-%d_%H%M%S")
|
||||
|
||||
-- Arguments for the script
|
||||
for o, arg in getopt.getopt(args, 'ho:') do
|
||||
if o == "h" then return help() end
|
||||
if o == "o" then outputTemplate = arg end
|
||||
end
|
||||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
pskTest(1)
|
||||
pskTest(2)
|
||||
pskTest(3)
|
||||
pskTest(8)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
end
|
||||
main(args)
|
||||
|
||||
-- Where it iterates over
|
||||
-- xxxx8xxx = PSK RF/2 with Manchester modulation
|
||||
-- xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes)
|
||||
-- xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high)
|
||||
-- xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input)
|
||||
|
||||
-- XXXXX0XX = PSK RF/2
|
||||
-- XXXXX4XX = PSK RF/4
|
||||
-- XXXXX8XX = PSK RF/8
|
|
@ -249,23 +249,27 @@ local function main(args)
|
|||
end
|
||||
end
|
||||
|
||||
-- Write dump to files
|
||||
if not DEBUG then
|
||||
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'.bin')
|
||||
print(("Wrote a BIN dump to the file %s"):format(foo))
|
||||
local bar = dumplib.SaveAsText(emldata, outputTemplate..'.eml')
|
||||
print(("Wrote a EML dump to the file %s"):format(bar))
|
||||
end
|
||||
|
||||
local uid = block0:sub(1,8)
|
||||
local itemtype = block1:sub(1,4)
|
||||
local cardid = block1:sub(9,24)
|
||||
local traptype = block1:sub(25,28)
|
||||
|
||||
-- Write dump to files
|
||||
if not DEBUG then
|
||||
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin')
|
||||
print(("Wrote a BIN dump to the file %s"):format(foo))
|
||||
local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml')
|
||||
print(("Wrote a EML dump to the file %s"):format(bar))
|
||||
end
|
||||
|
||||
-- Show info
|
||||
print( string.rep('--',20) )
|
||||
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
|
||||
print( (' UID : 0x%s'):format(uid) )
|
||||
print( (' CARDID : 0x%s'):format(cardid ) )
|
||||
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
|
||||
print( (' Alter ego / traptype : 0x%s'):format(traptype) )
|
||||
print( (' UID : 0x%s'):format(uid) )
|
||||
print( (' CARDID : 0x%s'):format(cardid ) )
|
||||
|
||||
print( string.rep('--',20) )
|
||||
|
||||
end
|
||||
|
|
|
@ -241,18 +241,20 @@ local function main(args)
|
|||
local cmdSetDbgOff = "hf mf dbg 0"
|
||||
core.console( cmdSetDbgOff)
|
||||
|
||||
-- Look for tag present on reader,
|
||||
result, err = lib14a.read1443a(false)
|
||||
if not result then return oops(err) end
|
||||
-- if not loadFromDump then
|
||||
-- -- Look for tag present on reader,
|
||||
-- result, err = lib14a.read1443a(false)
|
||||
-- if not result then return oops(err) end
|
||||
|
||||
core.clearCommandBuffer()
|
||||
-- core.clearCommandBuffer()
|
||||
|
||||
if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
||||
return oops('This is not a TNP3xxx tag. aborting.')
|
||||
end
|
||||
-- if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
|
||||
-- return oops('This is not a TNP3xxx tag. aborting.')
|
||||
-- end
|
||||
|
||||
-- Show tag info
|
||||
print((' Found tag : %s'):format(result.name))
|
||||
-- -- Show tag info
|
||||
-- print((' Found tag : %s'):format(result.name))
|
||||
-- end
|
||||
|
||||
-- Load dump.bin file
|
||||
print( (' Load data from %s'):format(inputTemplate))
|
||||
|
@ -349,7 +351,7 @@ local function main(args)
|
|||
err = LoadEmulator(blocks)
|
||||
if err then return oops(err) end
|
||||
core.clearCommandBuffer()
|
||||
print('The simulation is now prepared.\n --> run \"hf mf sim 5 '..uid..'\" <--')
|
||||
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..' x\" <--')
|
||||
end
|
||||
end
|
||||
main(args)
|
132
client/scripts/tracetest.lua
Normal file
132
client/scripts/tracetest.lua
Normal file
|
@ -0,0 +1,132 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local bin = require('bin')
|
||||
local utils = require('utils')
|
||||
local dumplib = require('html_dumplib')
|
||||
|
||||
example =[[
|
||||
1. script run tracetest
|
||||
2. script run tracetest -o
|
||||
|
||||
]]
|
||||
author = "Iceman"
|
||||
usage = "script run tracetest -o <filename>"
|
||||
desc =[[
|
||||
This script will load several traces files in ../traces/ folder and do
|
||||
"data load"
|
||||
"lf search"
|
||||
|
||||
Arguments:
|
||||
-h : this help
|
||||
-o : logfile name
|
||||
]]
|
||||
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
local DEBUG = true -- the debug flag
|
||||
---
|
||||
-- A debug printout-function
|
||||
function dbg(args)
|
||||
if not DEBUG then
|
||||
return
|
||||
end
|
||||
|
||||
if type(args) == "table" then
|
||||
local i = 1
|
||||
while result[i] do
|
||||
dbg(result[i])
|
||||
i = i+1
|
||||
end
|
||||
else
|
||||
print("###", args)
|
||||
end
|
||||
end
|
||||
---
|
||||
-- This is only meant to be used when errors occur
|
||||
function oops(err)
|
||||
print("ERROR: ",err)
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
function help()
|
||||
print(desc)
|
||||
print("Example usage")
|
||||
print(example)
|
||||
end
|
||||
--
|
||||
-- Exit message
|
||||
function ExitMsg(msg)
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
print(msg)
|
||||
print()
|
||||
end
|
||||
|
||||
|
||||
local function main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local cmdDataLoad = 'data load %s';
|
||||
local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f"
|
||||
local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f"
|
||||
|
||||
local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S")
|
||||
|
||||
-- Arguments for the script
|
||||
for o, arg in getopt.getopt(args, 'ho:') do
|
||||
if o == "h" then return help() end
|
||||
if o == "o" then outputTemplate = arg end
|
||||
end
|
||||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
local files = {}
|
||||
|
||||
-- Find a set of traces staring with EM
|
||||
local p = assert( io.popen(tracesEM))
|
||||
for file in p:lines() do
|
||||
table.insert(files, file)
|
||||
end
|
||||
p.close();
|
||||
|
||||
-- Find a set of traces staring with MOD
|
||||
p = assert( io.popen(tracesMOD) )
|
||||
for file in p:lines() do
|
||||
table.insert(files, file)
|
||||
end
|
||||
p.close();
|
||||
|
||||
local cmdLFSEARCH = "lf search 1"
|
||||
|
||||
-- main loop
|
||||
io.write('Starting to test traces > ')
|
||||
for _,file in pairs(files) do
|
||||
|
||||
local x = "data load "..file
|
||||
dbg(x)
|
||||
core.console(x)
|
||||
|
||||
dbg(cmdLFSEARCH)
|
||||
core.console(cmdLFSEARCH)
|
||||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
if core.ukbhit() then
|
||||
print("aborted by user")
|
||||
break
|
||||
end
|
||||
end
|
||||
io.write('\n')
|
||||
|
||||
-- Write dump to files
|
||||
if not DEBUG then
|
||||
local bar = dumplib.SaveAsText(emldata, outputTemplate..'.txt')
|
||||
print(("Wrote output to: %s"):format(bar))
|
||||
end
|
||||
|
||||
-- Show info
|
||||
print( string.rep('--',20) )
|
||||
|
||||
end
|
||||
main(args)
|
|
@ -213,6 +213,7 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
char param_getchar(const char *line, int paramnum)
|
||||
{
|
||||
int bg, en;
|
||||
|
@ -227,6 +228,36 @@ uint8_t param_get8(const char *line, int paramnum)
|
|||
return param_get8ex(line, paramnum, 10, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a decimal integer (actually, 0-254, not 255)
|
||||
* @param line
|
||||
* @param paramnum
|
||||
* @return -1 if error
|
||||
*/
|
||||
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination)
|
||||
{
|
||||
uint8_t val = param_get8ex(line, paramnum, 255, 10);
|
||||
printf("read %i", (int8_t ) val);
|
||||
if( (int8_t) val == -1) return 1;
|
||||
(*destination) = val;
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @brief Checks if param is decimal
|
||||
* @param line
|
||||
* @param paramnum
|
||||
* @return
|
||||
*/
|
||||
uint8_t param_isdec(const char *line, int paramnum)
|
||||
{
|
||||
int bg, en;
|
||||
//TODO, check more thorougly
|
||||
if (!param_getptr(line, &bg, &en, paramnum)) return 1;
|
||||
// return strtoul(&line[bg], NULL, 10) & 0xff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base)
|
||||
{
|
||||
int bg, en;
|
||||
|
|
|
@ -49,6 +49,8 @@ uint8_t param_get8(const char *line, int paramnum);
|
|||
uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base);
|
||||
uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base);
|
||||
uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
|
||||
uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
|
||||
uint8_t param_isdec(const char *line, int paramnum);
|
||||
int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
|
||||
int param_getstr(const char *line, int paramnum, char * str);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue