mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-20 21:33:19 -07:00
Merge branch 'master' into topaz
Conflicts: client/Makefile client/cmdhf.c client/cmdhf14a.c
This commit is contained in:
commit
db2b81ba11
119 changed files with 20403 additions and 4640 deletions
123
client/Makefile
123
client/Makefile
|
@ -9,12 +9,13 @@ include ../common/Makefile.common
|
|||
CC=gcc
|
||||
CXX=g++
|
||||
#COMMON_FLAGS = -m32
|
||||
VPATH = ../common
|
||||
VPATH = ../common ../zlib
|
||||
OBJDIR = obj
|
||||
|
||||
LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
|
||||
LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm
|
||||
LUALIB = ../liblua/liblua.a
|
||||
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../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
|
||||
LUAPLATFORM = generic
|
||||
|
||||
ifneq (,$(findstring MINGW,$(platform)))
|
||||
|
@ -35,14 +36,13 @@ else ifeq ($(platform),Darwin)
|
|||
else
|
||||
CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4
|
||||
QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
|
||||
LUALIB += -ldl
|
||||
MOC = $(shell pkg-config --variable=moc_location QtCore)
|
||||
LDLIBS += -ldl
|
||||
# Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info.
|
||||
#MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc
|
||||
LUAPLATFORM = linux
|
||||
endif
|
||||
|
||||
|
||||
ifneq ($(QTLDLIBS),)
|
||||
QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
|
||||
CFLAGS += -DHAVE_GUI
|
||||
|
@ -57,65 +57,73 @@ CORESRCS = uart.c \
|
|||
|
||||
|
||||
CMDSRCS = nonce2key/crapto1.c\
|
||||
nonce2key/crypto1.c\
|
||||
nonce2key/nonce2key.c\
|
||||
loclass/cipher.c \
|
||||
loclass/cipherutils.c \
|
||||
loclass/des.c \
|
||||
loclass/ikeys.c \
|
||||
loclass/elite_crack.c\
|
||||
loclass/fileutils.c\
|
||||
mifarehost.c\
|
||||
crc.c \
|
||||
crc16.c \
|
||||
iso14443crc.c \
|
||||
iso15693tools.c \
|
||||
data.c \
|
||||
graph.c \
|
||||
ui.c \
|
||||
cmddata.c \
|
||||
lfdemod.c \
|
||||
cmdhf.c \
|
||||
cmdhf14a.c \
|
||||
cmdhf14b.c \
|
||||
cmdhf15.c \
|
||||
cmdhfepa.c \
|
||||
cmdhflegic.c \
|
||||
cmdhficlass.c \
|
||||
cmdhfmf.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhftopaz.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
cmdlfio.c \
|
||||
cmdlfhid.c \
|
||||
cmdlfem4x.c \
|
||||
cmdlfhitag.c \
|
||||
cmdlfti.c \
|
||||
cmdparser.c \
|
||||
cmdmain.c \
|
||||
cmdlft55xx.c \
|
||||
cmdlfpcf7931.c\
|
||||
pm3_binlib.c\
|
||||
scripting.c\
|
||||
cmdscript.c\
|
||||
pm3_bitlib.c\
|
||||
aes.c\
|
||||
protocols.c
|
||||
nonce2key/crypto1.c\
|
||||
nonce2key/nonce2key.c\
|
||||
loclass/cipher.c \
|
||||
loclass/cipherutils.c \
|
||||
loclass/des.c \
|
||||
loclass/ikeys.c \
|
||||
loclass/elite_crack.c\
|
||||
loclass/fileutils.c\
|
||||
mifarehost.c\
|
||||
crc.c \
|
||||
crc16.c \
|
||||
crc64.c \
|
||||
iso14443crc.c \
|
||||
iso15693tools.c \
|
||||
data.c \
|
||||
graph.c \
|
||||
ui.c \
|
||||
cmddata.c \
|
||||
lfdemod.c \
|
||||
cmdhf.c \
|
||||
cmdhf14a.c \
|
||||
cmdhf14b.c \
|
||||
cmdhf15.c \
|
||||
cmdhfepa.c \
|
||||
cmdhflegic.c \
|
||||
cmdhficlass.c \
|
||||
cmdhfmf.c \
|
||||
cmdhfmfu.c \
|
||||
cmdhftopaz.c \
|
||||
cmdhw.c \
|
||||
cmdlf.c \
|
||||
cmdlfio.c \
|
||||
cmdlfhid.c \
|
||||
cmdlfem4x.c \
|
||||
cmdlfhitag.c \
|
||||
cmdlfti.c \
|
||||
cmdparser.c \
|
||||
cmdmain.c \
|
||||
cmdlft55xx.c \
|
||||
cmdlfpcf7931.c\
|
||||
pm3_binlib.c\
|
||||
scripting.c\
|
||||
cmdscript.c\
|
||||
pm3_bitlib.c\
|
||||
aes.c\
|
||||
protocols.c\
|
||||
sha1.c\
|
||||
|
||||
ZLIBSRCS = deflate.c adler32.c trees.c zutil.c inflate.c inffast.c inftrees.c
|
||||
ZLIB_FLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED
|
||||
#-DDEBUG -Dverbose=1
|
||||
|
||||
|
||||
COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
|
||||
CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
|
||||
ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o)
|
||||
|
||||
RM = rm -f
|
||||
BINS = proxmark3 flasher #snooper cli
|
||||
CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp
|
||||
BINS = proxmark3 flasher fpga_compress #snooper cli
|
||||
CLEAN = cli cli.exe flasher flasher.exe proxmark3 proxmark3.exe fpga_compress fpga_compress.exe snooper snooper.exe $(CMDOBJS) $(OBJDIR)/*.o *.o *.moc.cpp
|
||||
|
||||
all: lua_build $(BINS)
|
||||
|
||||
all-static: LDLIBS:=-static $(LDLIBS)
|
||||
all-static: snooper cli flasher
|
||||
|
||||
proxmark3: LDLIBS+=$(QTLDLIBS)
|
||||
all-static: snooper cli flasher fpga_compress
|
||||
|
||||
proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS)
|
||||
proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUI)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
|
@ -128,8 +136,11 @@ cli: $(OBJDIR)/cli.o $(COREOBJS) $(CMDOBJS) $(OBJDIR)/guidummy.o
|
|||
flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS)
|
||||
$(CXX) $(CXXFLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS)
|
||||
$(CXX) $(CXXFLAGS) $(ZLIB_FLAGS) $^ $(LDLIBS) -o $@
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
$(CC) $(CFLAGS) $(ZLIB_FLAGS) -c -o $@ $<
|
||||
|
||||
$(OBJDIR)/%.o: %.cpp
|
||||
$(CXX) $(CXXFLAGS) -c -o $@ $<
|
||||
|
|
1178
client/cmddata.c
1178
client/cmddata.c
File diff suppressed because it is too large
Load diff
|
@ -15,10 +15,7 @@ command_t * CmdDataCommands();
|
|||
|
||||
int CmdData(const char *Cmd);
|
||||
void printDemodBuff(void);
|
||||
void printBitStream(uint8_t BitStream[], uint32_t bitLen);
|
||||
void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
|
||||
int CmdAmp(const char *Cmd);
|
||||
int Cmdaskdemod(const char *Cmd);
|
||||
int CmdAskEM410xDemod(const char *Cmd);
|
||||
int CmdG_Prox_II_Demod(const char *Cmd);
|
||||
int Cmdaskrawdemod(const char *Cmd);
|
||||
|
@ -27,12 +24,11 @@ int AutoCorrelate(int window, bool SaveGrph, bool verbose);
|
|||
int CmdAutoCorr(const char *Cmd);
|
||||
int CmdBiphaseDecodeRaw(const char *Cmd);
|
||||
int CmdBitsamples(const char *Cmd);
|
||||
int CmdBitstream(const char *Cmd);
|
||||
int CmdBuffClear(const char *Cmd);
|
||||
int CmdDec(const char *Cmd);
|
||||
int CmdDetectClockRate(const char *Cmd);
|
||||
int CmdFDXBdemodBI(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);
|
||||
|
@ -40,6 +36,7 @@ int CmdFSKdemodPyramid(const char *Cmd);
|
|||
int CmdFSKrawdemod(const char *Cmd);
|
||||
int CmdPSK1rawDemod(const char *Cmd);
|
||||
int CmdPSK2rawDemod(const char *Cmd);
|
||||
int CmdPSKNexWatch(const char *Cmd);
|
||||
int CmdGrid(const char *Cmd);
|
||||
int CmdGetBitStream(const char *Cmd);
|
||||
int CmdHexsamples(const char *Cmd);
|
||||
|
@ -49,24 +46,22 @@ int CmdLoad(const char *Cmd);
|
|||
int CmdLtrim(const char *Cmd);
|
||||
int CmdRtrim(const char *Cmd);
|
||||
int Cmdmandecoderaw(const char *Cmd);
|
||||
int CmdManchesterDemod(const char *Cmd);
|
||||
int CmdManchesterMod(const char *Cmd);
|
||||
int CmdNorm(const char *Cmd);
|
||||
int CmdNRZrawDemod(const char *Cmd);
|
||||
int CmdPlot(const char *Cmd);
|
||||
int CmdPrintDemodBuff(const char *Cmd);
|
||||
int CmdRawDemod(const char *Cmd);
|
||||
int CmdSamples(const char *Cmd);
|
||||
int CmdTuneSamples(const char *Cmd);
|
||||
int CmdSave(const char *Cmd);
|
||||
int CmdScale(const char *Cmd);
|
||||
int CmdThreshold(const char *Cmd);
|
||||
int CmdDirectionalThreshold(const char *Cmd);
|
||||
int CmdZerocrossings(const char *Cmd);
|
||||
int CmdIndalaDecode(const char *Cmd);
|
||||
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo);
|
||||
int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo );
|
||||
int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
|
||||
int ASKbiphaseDemod(const char *Cmd, bool verbose);
|
||||
int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch);
|
||||
int ASKrawDemod(const char *Cmd, bool verbose);
|
||||
int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType);
|
||||
int FSKrawDemod(const char *Cmd, bool verbose);
|
||||
int PSKDemod(const char *Cmd, bool verbose);
|
||||
int NRZrawDemod(const char *Cmd, bool verbose);
|
||||
|
@ -76,8 +71,8 @@ int getSamples(const char *Cmd, bool silent);
|
|||
|
||||
#define MAX_DEMOD_BUF_LEN (1024*128)
|
||||
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
|
||||
extern int DemodBufferLen;
|
||||
|
||||
extern size_t DemodBufferLen;
|
||||
extern uint8_t g_debugMode;
|
||||
#define BIGBUF_SIZE 40000
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,11 +72,57 @@ 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(%d)",cmd[1]); break;
|
||||
case MIFARE_AUTH_KEYA:{
|
||||
if ( cmdsize > 3)
|
||||
snprintf(exp,size,"AUTH-A(%d)",cmd[1]);
|
||||
else
|
||||
// case MIFARE_ULEV1_VERSION : both 0x60.
|
||||
snprintf(exp,size,"EV1 VERSION");
|
||||
break;
|
||||
}
|
||||
case MIFARE_AUTH_KEYB: snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break;
|
||||
case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break;
|
||||
case MIFARE_MAGICWUPC2: snprintf(exp,size,"MAGIC WUPC2"); break;
|
||||
case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break;
|
||||
case MIFARE_ULC_AUTH_1: snprintf(exp,size,"AUTH "); break;
|
||||
case MIFARE_ULC_AUTH_2: snprintf(exp,size,"AUTH_ANSW"); break;
|
||||
case MIFARE_ULEV1_AUTH:
|
||||
if ( cmdsize == 7 )
|
||||
snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
|
||||
else
|
||||
snprintf(exp,size,"PWD-AUTH");
|
||||
break;
|
||||
case MIFARE_ULEV1_FASTREAD:{
|
||||
if ( cmdsize >=3 && cmd[2] <= 0xE6)
|
||||
snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]);
|
||||
else
|
||||
snprintf(exp,size,"?");
|
||||
break;
|
||||
}
|
||||
case MIFARE_ULC_WRITE:{
|
||||
if ( cmd[1] < 0x21 )
|
||||
snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]);
|
||||
else
|
||||
snprintf(exp,size,"?");
|
||||
break;
|
||||
}
|
||||
case MIFARE_ULEV1_READ_CNT:{
|
||||
if ( cmd[1] < 5 )
|
||||
snprintf(exp,size,"READ CNT(%d)",cmd[1]);
|
||||
else
|
||||
snprintf(exp,size,"?");
|
||||
break;
|
||||
}
|
||||
case MIFARE_ULEV1_INCR_CNT:{
|
||||
if ( cmd[1] < 5 )
|
||||
snprintf(exp,size,"INCR(%d)",cmd[1]);
|
||||
else
|
||||
snprintf(exp,size,"?");
|
||||
break;
|
||||
}
|
||||
case MIFARE_ULEV1_READSIG: snprintf(exp,size,"READ_SIG"); break;
|
||||
case MIFARE_ULEV1_CHECKTEAR: snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
|
||||
case MIFARE_ULEV1_VCSL: snprintf(exp,size,"VCSL"); break;
|
||||
default: snprintf(exp,size,"?"); break;
|
||||
}
|
||||
return;
|
||||
|
@ -438,8 +484,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
|
|||
oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
|
||||
}
|
||||
uint8_t parityBits = parityBytes[j>>3];
|
||||
if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
|
||||
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x!", frame[j]);
|
||||
if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
|
||||
snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
|
||||
} else {
|
||||
snprintf(line[j/16]+(( j % 16) * 4), 110, " %02x ", frame[j]);
|
||||
}
|
||||
|
@ -615,9 +661,36 @@ int CmdHFList(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdHFSearch(const char *Cmd){
|
||||
int ans = 0;
|
||||
PrintAndLog("");
|
||||
ans = CmdHF14AReader("s");
|
||||
if (ans > 0) {
|
||||
PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HF14BInfo(false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HFiClassReader("", false, false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
ans = HF15Reader("", false);
|
||||
if (ans) {
|
||||
PrintAndLog("\nValid ISO15693 Tag Found - Quiting Search\n");
|
||||
return ans;
|
||||
}
|
||||
PrintAndLog("\nno known/supported 13.56 MHz tags found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
<<<<<<< HEAD
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
|
||||
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
|
||||
|
@ -631,6 +704,21 @@ static command_t CommandTable[] =
|
|||
{"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"},
|
||||
{"list", CmdHFList, 1, "List protocol data in trace buffer"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
=======
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"},
|
||||
{"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"},
|
||||
{"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"},
|
||||
{"epa", CmdHFEPA, 1, "{ German Identification Card... }"},
|
||||
{"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"},
|
||||
{"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
>>>>>>> master
|
||||
};
|
||||
|
||||
int CmdHF(const char *Cmd)
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "common.h"
|
||||
#include "cmdmain.h"
|
||||
#include "mifare.h"
|
||||
#include "cmdhfmfu.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
static void waitCmd(uint8_t iLen);
|
||||
|
@ -143,7 +144,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
|
||||
|
||||
if(select_status == 0) {
|
||||
PrintAndLog("iso14443a card select failed");
|
||||
if (Cmd[0] != 's') PrintAndLog("iso14443a card select failed");
|
||||
// disconnect
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
|
@ -163,19 +164,68 @@ int CmdHF14AReader(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
|
||||
PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
|
||||
PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
|
||||
|
||||
// Double & triple sized UID, can be mapped to a manufacturer.
|
||||
// HACK: does this apply for Ultralight cards?
|
||||
if ( card.uidlen > 4 ) {
|
||||
PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
|
||||
}
|
||||
|
||||
switch (card.sak) {
|
||||
case 0x00: PrintAndLog("TYPE : NXP MIFARE Ultralight | Ultralight C"); break;
|
||||
case 0x00:
|
||||
|
||||
//***************************************test****************
|
||||
// disconnect
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
|
||||
uint32_t tagT = GetHF14AMfU_Type();
|
||||
ul_print_type(tagT, 0);
|
||||
|
||||
//reconnect for further tests
|
||||
c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
|
||||
|
||||
select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
|
||||
|
||||
if(select_status == 0) {
|
||||
//PrintAndLog("iso14443a card select failed");
|
||||
// disconnect
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = 0;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* orig
|
||||
// check if the tag answers to GETVERSION (0x60)
|
||||
c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
|
||||
c.arg[1] = 1;
|
||||
c.arg[2] = 0;
|
||||
c.d.asBytes[0] = 0x60;
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
uint8_t version[10] = {0};
|
||||
memcpy(version, resp.d.asBytes, resp.arg[0] < sizeof(version) ? resp.arg[0] : sizeof(version));
|
||||
uint8_t len = resp.arg[0] & 0xff;
|
||||
switch ( len ){
|
||||
// todo, identify "Magic UL-C tags". // they usually have a static nonce response to 0x1A command.
|
||||
// UL-EV1, size, check version[6] == 0x0b (smaller) 0x0b * 4 == 48
|
||||
case 0x0A:PrintAndLog("TYPE : NXP MIFARE Ultralight EV1 %d bytes", (version[6] == 0xB) ? 48 : 128);break;
|
||||
case 0x01:PrintAndLog("TYPE : NXP MIFARE Ultralight C");break;
|
||||
case 0x00:PrintAndLog("TYPE : NXP MIFARE Ultralight");break;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
case 0x01: PrintAndLog("TYPE : NXP TNP3xxx Activision Game Appliance"); break;
|
||||
case 0x04: PrintAndLog("TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); break;
|
||||
case 0x08: PrintAndLog("TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1"); break;
|
||||
|
@ -192,6 +242,12 @@ int CmdHF14AReader(const char *Cmd)
|
|||
default: ;
|
||||
}
|
||||
|
||||
// Double & triple sized UID, can be mapped to a manufacturer.
|
||||
// HACK: does this apply for Ultralight cards?
|
||||
if ( card.uidlen > 4 ) {
|
||||
PrintAndLog("MANUFACTURER : %s", getTagInfo(card.uid[0]));
|
||||
}
|
||||
|
||||
// try to request ATS even if tag claims not to support it
|
||||
if (select_status == 2) {
|
||||
uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
|
||||
|
@ -202,7 +258,7 @@ int CmdHF14AReader(const char *Cmd)
|
|||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
memcpy(&card.ats, resp.d.asBytes, resp.arg[0]);
|
||||
memcpy(card.ats, resp.d.asBytes, resp.arg[0]);
|
||||
card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes
|
||||
}
|
||||
|
||||
|
|
|
@ -22,157 +22,29 @@
|
|||
#include "cmdparser.h"
|
||||
#include "cmdhf14b.h"
|
||||
#include "cmdmain.h"
|
||||
#include "cmdhf14a.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
int CmdHF14BDemod(const char *Cmd)
|
||||
{
|
||||
int i, j, iold;
|
||||
int isum, qsum;
|
||||
int outOfWeakAt;
|
||||
bool negateI, negateQ;
|
||||
|
||||
uint8_t data[256];
|
||||
int dataLen = 0;
|
||||
|
||||
// As received, the samples are pairs, correlations against I and Q
|
||||
// square waves. So estimate angle of initial carrier (or just
|
||||
// quadrant, actually), and then do the demod.
|
||||
|
||||
// First, estimate where the tag starts modulating.
|
||||
for (i = 0; i < GraphTraceLen; i += 2) {
|
||||
if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= GraphTraceLen) {
|
||||
PrintAndLog("too weak to sync");
|
||||
return 0;
|
||||
}
|
||||
PrintAndLog("out of weak at %d", i);
|
||||
outOfWeakAt = i;
|
||||
|
||||
// Now, estimate the phase in the initial modulation of the tag
|
||||
isum = 0;
|
||||
qsum = 0;
|
||||
for (; i < (outOfWeakAt + 16); i += 2) {
|
||||
isum += GraphBuffer[i + 0];
|
||||
qsum += GraphBuffer[i + 1];
|
||||
}
|
||||
negateI = (isum < 0);
|
||||
negateQ = (qsum < 0);
|
||||
|
||||
// Turn the correlation pairs into soft decisions on the bit.
|
||||
j = 0;
|
||||
for (i = 0; i < GraphTraceLen / 2; i++) {
|
||||
int si = GraphBuffer[j];
|
||||
int sq = GraphBuffer[j + 1];
|
||||
if (negateI) si = -si;
|
||||
if (negateQ) sq = -sq;
|
||||
GraphBuffer[i] = si + sq;
|
||||
j += 2;
|
||||
}
|
||||
GraphTraceLen = i;
|
||||
|
||||
i = outOfWeakAt / 2;
|
||||
while (GraphBuffer[i] > 0 && i < GraphTraceLen)
|
||||
i++;
|
||||
if (i >= GraphTraceLen) goto demodError;
|
||||
|
||||
iold = i;
|
||||
while (GraphBuffer[i] < 0 && i < GraphTraceLen)
|
||||
i++;
|
||||
if (i >= GraphTraceLen) goto demodError;
|
||||
if ((i - iold) > 23) goto demodError;
|
||||
|
||||
PrintAndLog("make it to demod loop");
|
||||
|
||||
for (;;) {
|
||||
iold = i;
|
||||
while (GraphBuffer[i] >= 0 && i < GraphTraceLen)
|
||||
i++;
|
||||
if (i >= GraphTraceLen) goto demodError;
|
||||
if ((i - iold) > 6) goto demodError;
|
||||
|
||||
uint16_t shiftReg = 0;
|
||||
if (i + 20 >= GraphTraceLen) goto demodError;
|
||||
|
||||
for (j = 0; j < 10; j++) {
|
||||
int soft = GraphBuffer[i] + GraphBuffer[i + 1];
|
||||
|
||||
if (abs(soft) < (abs(isum) + abs(qsum)) / 20) {
|
||||
PrintAndLog("weak bit");
|
||||
}
|
||||
|
||||
shiftReg >>= 1;
|
||||
if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) {
|
||||
shiftReg |= 0x200;
|
||||
}
|
||||
|
||||
i+= 2;
|
||||
}
|
||||
|
||||
if ((shiftReg & 0x200) && !(shiftReg & 0x001))
|
||||
{
|
||||
// valid data byte, start and stop bits okay
|
||||
PrintAndLog(" %02x", (shiftReg >> 1) & 0xff);
|
||||
data[dataLen++] = (shiftReg >> 1) & 0xff;
|
||||
if (dataLen >= sizeof(data)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (shiftReg == 0x000) {
|
||||
// this is EOF
|
||||
break;
|
||||
} else {
|
||||
goto demodError;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second);
|
||||
PrintAndLog("CRC: %02x %02x (%s)\n", first, second,
|
||||
(first == data[dataLen-2] && second == data[dataLen-1]) ?
|
||||
"ok" : "****FAIL****");
|
||||
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
|
||||
demodError:
|
||||
PrintAndLog("demod error");
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14BList(const char *Cmd)
|
||||
{
|
||||
PrintAndLog("Deprecated command, use 'hf list 14b' instead");
|
||||
|
||||
return 0;
|
||||
}
|
||||
int CmdHF14BRead(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14Sim(const char *Cmd)
|
||||
int CmdHF14BSim(const char *Cmd)
|
||||
{
|
||||
UsbCommand c={CMD_SIMULATE_TAG_ISO_14443};
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHFSimlisten(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN};
|
||||
UsbCommand c={CMD_SIMULATE_TAG_ISO_14443B};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14BSnoop(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_SNOOP_ISO_14443};
|
||||
UsbCommand c = {CMD_SNOOP_ISO_14443B};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -184,6 +56,7 @@ int CmdHF14BSnoop(const char *Cmd)
|
|||
int CmdSri512Read(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_READ_SRI512_TAG, {strtol(Cmd, NULL, 0), 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
@ -195,127 +68,356 @@ int CmdSri512Read(const char *Cmd)
|
|||
int CmdSrix4kRead(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_READ_SRIX4K_TAG, {strtol(Cmd, NULL, 0), 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14BCmdRaw (const char *cmd) {
|
||||
UsbCommand resp;
|
||||
uint8_t *recv;
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv?
|
||||
uint8_t reply=1;
|
||||
uint8_t crc=0;
|
||||
uint8_t power=0;
|
||||
char buf[5]="";
|
||||
int i=0;
|
||||
uint8_t data[100] = {0x00};
|
||||
unsigned int datalen=0, temp;
|
||||
char *hexout;
|
||||
|
||||
if (strlen(cmd)<3) {
|
||||
PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>");
|
||||
PrintAndLog(" -r do not read response");
|
||||
PrintAndLog(" -c calculate and append CRC");
|
||||
PrintAndLog(" -p leave the field on after receive");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// strip
|
||||
while (*cmd==' ' || *cmd=='\t') cmd++;
|
||||
|
||||
while (cmd[i]!='\0') {
|
||||
if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; }
|
||||
if (cmd[i]=='-') {
|
||||
switch (cmd[i+1]) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
reply=0;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
crc=1;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
power=1;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Invalid option");
|
||||
return 0;
|
||||
}
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ((cmd[i]>='0' && cmd[i]<='9') ||
|
||||
(cmd[i]>='a' && cmd[i]<='f') ||
|
||||
(cmd[i]>='A' && cmd[i]<='F') ) {
|
||||
buf[strlen(buf)+1]=0;
|
||||
buf[strlen(buf)]=cmd[i];
|
||||
i++;
|
||||
|
||||
if (strlen(buf)>=2) {
|
||||
sscanf(buf,"%x",&temp);
|
||||
data[datalen]=(uint8_t)(temp & 0xff);
|
||||
datalen++;
|
||||
*buf=0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
PrintAndLog("Invalid char on input");
|
||||
return 1;
|
||||
}
|
||||
if (datalen == 0)
|
||||
{
|
||||
PrintAndLog("Missing data input");
|
||||
return 0;
|
||||
}
|
||||
if(crc)
|
||||
{
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
|
||||
data[datalen++] = first;
|
||||
data[datalen++] = second;
|
||||
}
|
||||
|
||||
c.arg[0] = datalen;
|
||||
c.arg[1] = reply;
|
||||
c.arg[2] = power;
|
||||
memcpy(c.d.asBytes,data,datalen);
|
||||
|
||||
SendCommand(&c);
|
||||
|
||||
if (reply) {
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
||||
recv = resp.d.asBytes;
|
||||
PrintAndLog("received %i octets",resp.arg[0]);
|
||||
if(!resp.arg[0])
|
||||
return 0;
|
||||
hexout = (char *)malloc(resp.arg[0] * 3 + 1);
|
||||
if (hexout != NULL) {
|
||||
uint8_t first, second;
|
||||
for (int i = 0; i < resp.arg[0]; i++) { // data in hex
|
||||
sprintf(&hexout[i * 3], "%02X ", recv[i]);
|
||||
}
|
||||
PrintAndLog("%s", hexout);
|
||||
free(hexout);
|
||||
ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second);
|
||||
if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) {
|
||||
PrintAndLog("CRC OK");
|
||||
} else {
|
||||
PrintAndLog("CRC failed");
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("malloc failed your client has low memory?");
|
||||
}
|
||||
} else {
|
||||
PrintAndLog("timeout while waiting for reply.");
|
||||
}
|
||||
} // if reply
|
||||
return 0;
|
||||
int rawClose(void){
|
||||
UsbCommand resp;
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}};
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
if (!WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14BWrite( const char *Cmd){
|
||||
int HF14BCmdRaw(bool reply, bool *crc, bool power, uint8_t *data, uint8_t *datalen, bool verbose){
|
||||
UsbCommand resp;
|
||||
UsbCommand c = {CMD_ISO_14443B_COMMAND, {0, 0, 0}}; // len,recv,power
|
||||
if(*crc)
|
||||
{
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_B, data, *datalen, &first, &second);
|
||||
data[*datalen] = first;
|
||||
data[*datalen + 1] = second;
|
||||
*datalen += 2;
|
||||
}
|
||||
|
||||
c.arg[0] = *datalen;
|
||||
c.arg[1] = reply;
|
||||
c.arg[2] = power;
|
||||
memcpy(c.d.asBytes,data,*datalen);
|
||||
clearCommandBuffer();
|
||||
SendCommand(&c);
|
||||
|
||||
if (!reply) return 1;
|
||||
|
||||
if (!WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
||||
if (verbose) PrintAndLog("timeout while waiting for reply.");
|
||||
return 0;
|
||||
}
|
||||
*datalen = resp.arg[0];
|
||||
if (verbose) PrintAndLog("received %u octets", *datalen);
|
||||
if(*datalen<2) return 0;
|
||||
|
||||
memcpy(data, resp.d.asBytes, *datalen);
|
||||
if (verbose) PrintAndLog("%s", sprint_hex(data, *datalen));
|
||||
|
||||
uint8_t first, second;
|
||||
ComputeCrc14443(CRC_14443_B, data, *datalen-2, &first, &second);
|
||||
if(data[*datalen-2] == first && data[*datalen-1] == second) {
|
||||
if (verbose) PrintAndLog("CRC OK");
|
||||
*crc = true;
|
||||
} else {
|
||||
if (verbose) PrintAndLog("CRC failed");
|
||||
*crc = false;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdHF14BCmdRaw (const char *Cmd) {
|
||||
bool reply = true;
|
||||
bool crc = false;
|
||||
bool power = false;
|
||||
char buf[5] = "";
|
||||
uint8_t data[100] = {0x00};
|
||||
uint8_t datalen = 0;
|
||||
unsigned int temp;
|
||||
int i = 0;
|
||||
if (strlen(Cmd)<3) {
|
||||
PrintAndLog("Usage: hf 14b raw [-r] [-c] [-p] <0A 0B 0C ... hex>");
|
||||
PrintAndLog(" -r do not read response");
|
||||
PrintAndLog(" -c calculate and append CRC");
|
||||
PrintAndLog(" -p leave the field on after receive");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// strip
|
||||
while (*Cmd==' ' || *Cmd=='\t') Cmd++;
|
||||
|
||||
while (Cmd[i]!='\0') {
|
||||
if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; }
|
||||
if (Cmd[i]=='-') {
|
||||
switch (Cmd[i+1]) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
reply = false;
|
||||
break;
|
||||
case 'c':
|
||||
case 'C':
|
||||
crc = true;
|
||||
break;
|
||||
case 'p':
|
||||
case 'P':
|
||||
power = true;
|
||||
break;
|
||||
default:
|
||||
PrintAndLog("Invalid option");
|
||||
return 0;
|
||||
}
|
||||
i+=2;
|
||||
continue;
|
||||
}
|
||||
if ((Cmd[i]>='0' && Cmd[i]<='9') ||
|
||||
(Cmd[i]>='a' && Cmd[i]<='f') ||
|
||||
(Cmd[i]>='A' && Cmd[i]<='F') ) {
|
||||
buf[strlen(buf)+1]=0;
|
||||
buf[strlen(buf)]=Cmd[i];
|
||||
i++;
|
||||
|
||||
if (strlen(buf)>=2) {
|
||||
sscanf(buf,"%x",&temp);
|
||||
data[datalen++]=(uint8_t)(temp & 0xff);
|
||||
*buf=0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
PrintAndLog("Invalid char on input");
|
||||
return 1;
|
||||
}
|
||||
if (datalen == 0)
|
||||
{
|
||||
PrintAndLog("Missing data input");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return HF14BCmdRaw(reply, &crc, power, data, &datalen, true);
|
||||
}
|
||||
|
||||
static void print_atqb_resp(uint8_t *data){
|
||||
PrintAndLog (" UID: %s", sprint_hex(data+1,4));
|
||||
PrintAndLog (" App Data: %s", sprint_hex(data+5,4));
|
||||
PrintAndLog (" Protocol: %s", sprint_hex(data+9,3));
|
||||
uint8_t BitRate = data[9];
|
||||
if (!BitRate)
|
||||
PrintAndLog (" Bit Rate: 106 kbit/s only PICC <-> PCD");
|
||||
if (BitRate & 0x10)
|
||||
PrintAndLog (" Bit Rate: 212 kbit/s PICC -> PCD supported");
|
||||
if (BitRate & 0x20)
|
||||
PrintAndLog (" Bit Rate: 424 kbit/s PICC -> PCD supported");
|
||||
if (BitRate & 0x40)
|
||||
PrintAndLog (" Bit Rate: 847 kbit/s PICC -> PCD supported");
|
||||
if (BitRate & 0x01)
|
||||
PrintAndLog (" Bit Rate: 212 kbit/s PICC <- PCD supported");
|
||||
if (BitRate & 0x02)
|
||||
PrintAndLog (" Bit Rate: 424 kbit/s PICC <- PCD supported");
|
||||
if (BitRate & 0x04)
|
||||
PrintAndLog (" Bit Rate: 847 kbit/s PICC <- PCD supported");
|
||||
if (BitRate & 0x80)
|
||||
PrintAndLog (" Same bit rate <-> required");
|
||||
|
||||
uint16_t maxFrame = data[10]>>4;
|
||||
if (maxFrame < 5)
|
||||
maxFrame = 8*maxFrame + 16;
|
||||
else if (maxFrame == 5)
|
||||
maxFrame = 64;
|
||||
else if (maxFrame == 6)
|
||||
maxFrame = 96;
|
||||
else if (maxFrame == 7)
|
||||
maxFrame = 128;
|
||||
else if (maxFrame == 8)
|
||||
maxFrame = 256;
|
||||
else
|
||||
maxFrame = 257;
|
||||
|
||||
PrintAndLog ("Max Frame Size: %d%s",maxFrame, (maxFrame == 257) ? "+ RFU" : "");
|
||||
|
||||
uint8_t protocolT = data[10] & 0xF;
|
||||
PrintAndLog (" Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " );
|
||||
PrintAndLog ("Frame Wait Int: %d", data[11]>>4);
|
||||
PrintAndLog (" App Data Code: Application is %s",(data[11]&4) ? "Standard" : "Proprietary");
|
||||
PrintAndLog (" Frame Options: NAD is %ssupported",(data[11]&2) ? "" : "not ");
|
||||
PrintAndLog (" Frame Options: CID is %ssupported",(data[11]&1) ? "" : "not ");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *get_ST_Chip_Model(uint8_t data){
|
||||
static char model[20];
|
||||
char *retStr = model;
|
||||
memset(model,0, sizeof(model));
|
||||
|
||||
switch (data) {
|
||||
case 0x0: sprintf(retStr, "SRIX4K (Special)"); break;
|
||||
case 0x2: sprintf(retStr, "SR176"); break;
|
||||
case 0x3: sprintf(retStr, "SRIX4K"); break;
|
||||
case 0x4: sprintf(retStr, "SRIX512"); break;
|
||||
case 0x6: sprintf(retStr, "SRI512"); break;
|
||||
case 0x7: sprintf(retStr, "SRI4K"); break;
|
||||
case 0xC: sprintf(retStr, "SRT512"); break;
|
||||
default : sprintf(retStr, "Unknown"); break;
|
||||
}
|
||||
return retStr;
|
||||
}
|
||||
|
||||
static void print_st_info(uint8_t *data){
|
||||
//uid = first 8 bytes in data
|
||||
PrintAndLog(" UID: %s", sprint_hex(SwapEndian64(data,8,8),8));
|
||||
PrintAndLog(" MFG: %02X, %s", data[6], getTagInfo(data[6]));
|
||||
PrintAndLog("Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2));
|
||||
return;
|
||||
}
|
||||
|
||||
int HF14BStdInfo(uint8_t *data, uint8_t *datalen){
|
||||
|
||||
//05 00 00 = find one tag in field
|
||||
//1d xx xx xx xx 20 00 08 01 00 = attrib xx=crc
|
||||
//a3 = ? (resp 03 e2 c2)
|
||||
//02 = ? (resp 02 6a d3)
|
||||
// 022b (resp 02 67 00 [29 5b])
|
||||
// 0200a40400 (resp 02 67 00 [29 5b])
|
||||
// 0200a4040c07a0000002480300 (resp 02 67 00 [29 5b])
|
||||
// 0200a4040c07a0000002480200 (resp 02 67 00 [29 5b])
|
||||
// 0200a4040006a0000000010100 (resp 02 6a 82 [4b 4c])
|
||||
// 0200a4040c09d27600002545500200 (resp 02 67 00 [29 5b])
|
||||
// 0200a404000cd2760001354b414e4d30310000 (resp 02 6a 82 [4b 4c])
|
||||
// 0200a404000ca000000063504b43532d313500 (resp 02 6a 82 [4b 4c])
|
||||
// 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c])
|
||||
//03 = ? (resp 03 [e3 c2])
|
||||
//c2 = ? (resp c2 [66 15])
|
||||
//b2 = ? (resp a3 [e9 67])
|
||||
bool crc = true;
|
||||
*datalen = 3;
|
||||
//std read cmd
|
||||
data[0] = 0x05;
|
||||
data[1] = 0x00;
|
||||
data[2] = 0x00;
|
||||
|
||||
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)==0) return 0;
|
||||
|
||||
if (data[0] != 0x50 || *datalen != 14 || !crc) return 0;
|
||||
|
||||
PrintAndLog ("\n14443-3b tag found:");
|
||||
print_atqb_resp(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int HF14B_ST_Info(uint8_t *data, uint8_t *datalen){
|
||||
bool crc = true;
|
||||
*datalen = 2;
|
||||
//wake cmd
|
||||
data[0] = 0x06;
|
||||
data[1] = 0x00;
|
||||
|
||||
//leave power on
|
||||
// verbose on for now for testing - turn off when functional
|
||||
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
|
||||
|
||||
if (*datalen != 3 || !crc) return rawClose();
|
||||
|
||||
uint8_t chipID = data[0];
|
||||
// select
|
||||
data[0] = 0x0E;
|
||||
data[1] = chipID;
|
||||
*datalen = 2;
|
||||
|
||||
//leave power on
|
||||
// verbose on for now for testing - turn off when functional
|
||||
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return rawClose();
|
||||
|
||||
if (*datalen != 3 || !crc || data[0] != chipID) return rawClose();
|
||||
|
||||
// get uid
|
||||
data[0] = 0x0B;
|
||||
*datalen = 1;
|
||||
|
||||
//power off
|
||||
// verbose on for now for testing - turn off when functional
|
||||
if (HF14BCmdRaw(true, &crc, true, data, datalen, false)==0) return 0;
|
||||
rawClose();
|
||||
if (*datalen != 10 || !crc) return 0;
|
||||
|
||||
PrintAndLog("\n14443-3b ST tag found:");
|
||||
print_st_info(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// test for other 14b type tags (mimic another reader - don't have tags to identify)
|
||||
int HF14B_Other_Info(uint8_t *data, uint8_t *datalen){
|
||||
bool crc = true;
|
||||
*datalen = 4;
|
||||
//std read cmd
|
||||
data[0] = 0x00;
|
||||
data[1] = 0x0b;
|
||||
data[2] = 0x3f;
|
||||
data[3] = 0x80;
|
||||
|
||||
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
|
||||
if (*datalen > 2 || !crc) {
|
||||
PrintAndLog ("\n14443-3b tag found:");
|
||||
PrintAndLog ("Unknown tag type answered to a 0x000b3f80 command ans:");
|
||||
PrintAndLog ("%s",sprint_hex(data,*datalen));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
crc = false;
|
||||
*datalen = 1;
|
||||
data[0] = 0x0a;
|
||||
|
||||
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
|
||||
if (*datalen > 0) {
|
||||
PrintAndLog ("\n14443-3b tag found:");
|
||||
PrintAndLog ("Unknown tag type answered to a 0x0A command ans:");
|
||||
PrintAndLog ("%s",sprint_hex(data,*datalen));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
crc = false;
|
||||
*datalen = 1;
|
||||
data[0] = 0x0c;
|
||||
|
||||
if (HF14BCmdRaw(true, &crc, false, data, datalen, false)!=0) {
|
||||
if (*datalen > 0) {
|
||||
PrintAndLog ("\n14443-3b tag found:");
|
||||
PrintAndLog ("Unknown tag type answered to a 0x0C command ans:");
|
||||
PrintAndLog ("%s",sprint_hex(data,*datalen));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int HF14BInfo(bool verbose){
|
||||
uint8_t data[100];
|
||||
uint8_t datalen = 5;
|
||||
|
||||
// try std 14b (atqb)
|
||||
if (HF14BStdInfo(data, &datalen)) return 1;
|
||||
|
||||
// try st 14b
|
||||
if (HF14B_ST_Info(data, &datalen)) return 1;
|
||||
|
||||
// try unknown 14b read commands (to be identified later)
|
||||
// could be read of calypso, CEPAS, moneo, or pico pass.
|
||||
if (HF14B_Other_Info(data, &datalen)) return 1;
|
||||
|
||||
if (verbose) PrintAndLog("no 14443B tag found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHF14Binfo(const char *Cmd){
|
||||
return HF14BInfo(true);
|
||||
}
|
||||
|
||||
int CmdSriWrite( const char *Cmd){
|
||||
/*
|
||||
* For SRIX4K blocks 00 - 7F
|
||||
* hf 14b raw -c -p 09 $srix4kwblock $srix4kwdata
|
||||
|
@ -385,16 +487,14 @@ int CmdHF14BWrite( const char *Cmd){
|
|||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"demod", CmdHF14BDemod, 1, "Demodulate ISO14443 Type B from tag"},
|
||||
{"info", CmdHF14Binfo, 0, "Find and print info about a 14b type tag (HF ISO 14443b)"},
|
||||
{"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"},
|
||||
{"read", CmdHF14BRead, 0, "Read HF tag (ISO 14443)"},
|
||||
{"sim", CmdHF14Sim, 0, "Fake ISO 14443 tag"},
|
||||
{"simlisten", CmdHFSimlisten, 0, "Get HF samples as fake tag"},
|
||||
{"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443"},
|
||||
{"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"},
|
||||
{"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"},
|
||||
{"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"},
|
||||
{"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"},
|
||||
{"sriwrite", CmdSriWrite, 0, "Write data to a SRI512 | SRIX4K tag"},
|
||||
{"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"},
|
||||
{"write", CmdHF14BWrite, 0, "Write data to a SRI512 | SRIX4K tag"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,15 +12,13 @@
|
|||
#define CMDHF14B_H__
|
||||
|
||||
int CmdHF14B(const char *Cmd);
|
||||
|
||||
int CmdHF14BDemod(const char *Cmd);
|
||||
int CmdHF14BList(const char *Cmd);
|
||||
int CmdHF14BRead(const char *Cmd);
|
||||
int CmdHF14Sim(const char *Cmd);
|
||||
int CmdHFSimlisten(const char *Cmd);
|
||||
int CmdHF14BInfo(const char *Cmd);
|
||||
int CmdHF14BSim(const char *Cmd);
|
||||
int CmdHF14BSnoop(const char *Cmd);
|
||||
int CmdSri512Read(const char *Cmd);
|
||||
int CmdSrix4kRead(const char *Cmd);
|
||||
int CmdHF14BWrite( const char *cmd);
|
||||
int HF14BInfo(bool verbose);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -374,6 +374,20 @@ int CmdHF15Record(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int HF15Reader(const char *Cmd, bool verbose)
|
||||
{
|
||||
uint8_t uid[8];
|
||||
|
||||
if (!getUID(uid)) {
|
||||
if (verbose) PrintAndLog("No Tag found.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
PrintAndLog("Tag UID : %s",sprintUID(NULL,uid));
|
||||
PrintAndLog("Tag Info: %s",getTagInfo(uid));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdHF15Reader(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_READER_ISO_15693, {strtol(Cmd, NULL, 0), 0, 0}};
|
||||
|
@ -469,7 +483,7 @@ int CmdHF15DumpMem(const char*Cmd) {
|
|||
// PrintAndLog("bn=%i",blocknum);
|
||||
} else {
|
||||
PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
} // else PrintAndLog("crc");
|
||||
} // else PrintAndLog("r null");
|
||||
|
@ -481,7 +495,7 @@ int CmdHF15DumpMem(const char*Cmd) {
|
|||
// PrintAndLog("CRC Failed");
|
||||
// else
|
||||
// PrintAndLog("Tag returned Error %i: %s",recv[1],TagErrorStr(recv[1]));
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ int CmdHF15(const char *Cmd);
|
|||
|
||||
int CmdHF15Demod(const char *Cmd);
|
||||
int CmdHF15Read(const char *Cmd);
|
||||
int HF15Reader(const char *Cmd, bool verbose);
|
||||
int CmdHF15Reader(const char *Cmd);
|
||||
int CmdHF15Sim(const char *Cmd);
|
||||
int CmdHF15Record(const char *Cmd);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "util.h"
|
||||
//#include "proxusb.h"
|
||||
|
||||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
#include "cmdparser.h"
|
||||
|
@ -29,9 +29,9 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
|
|||
unsigned int n = 0;
|
||||
// delay between requests
|
||||
unsigned int d = 0;
|
||||
|
||||
|
||||
sscanf(Cmd, "%u %u %u", &m, &n, &d);
|
||||
|
||||
|
||||
// values are expected to be > 0
|
||||
m = m > 0 ? m : 1;
|
||||
n = n > 0 ? n : 1;
|
||||
|
@ -44,7 +44,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
|
|||
UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}};
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
|
||||
|
||||
WaitForResponse(CMD_ACK,&resp);
|
||||
|
||||
// check if command failed
|
||||
|
@ -68,13 +68,123 @@ int CmdHFEPACollectPACENonces(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////The commands lie below here/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// perform the PACE protocol by replaying APDUs
|
||||
int CmdHFEPAPACEReplay(const char *Cmd)
|
||||
{
|
||||
// the 4 APDUs which are replayed + their lengths
|
||||
uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75];
|
||||
uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0};
|
||||
// pointers to the arrays to be able to iterate
|
||||
uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu};
|
||||
|
||||
// usage message
|
||||
static const char const *usage_msg =
|
||||
"Please specify 5 APDUs separated by spaces. "
|
||||
"Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D";
|
||||
|
||||
// Proxmark response
|
||||
UsbCommand resp;
|
||||
|
||||
int skip = 0, skip_add = 0, scan_return = 0;
|
||||
// for each APDU
|
||||
for (int i = 0; i < sizeof(apdu_lengths); i++) {
|
||||
// scan to next space or end of string
|
||||
while (Cmd[skip] != ' ' && Cmd[skip] != '\0') {
|
||||
// convert
|
||||
scan_return = sscanf(Cmd + skip, "%2X%n",
|
||||
(unsigned int *) (apdus[i] + apdu_lengths[i]),
|
||||
&skip_add);
|
||||
if (scan_return < 1) {
|
||||
PrintAndLog((char *)usage_msg);
|
||||
PrintAndLog("Not enough APDUs! Try again!");
|
||||
return 0;
|
||||
}
|
||||
skip += skip_add;
|
||||
apdu_lengths[i]++;
|
||||
}
|
||||
|
||||
// break on EOF
|
||||
if (Cmd[skip] == '\0') {
|
||||
if (i < sizeof(apdu_lengths) - 1) {
|
||||
|
||||
PrintAndLog((char *)usage_msg);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// skip the space
|
||||
skip++;
|
||||
}
|
||||
|
||||
// transfer the APDUs to the Proxmark
|
||||
UsbCommand usb_cmd;
|
||||
usb_cmd.cmd = CMD_EPA_PACE_REPLAY;
|
||||
for (int i = 0; i < sizeof(apdu_lengths); i++) {
|
||||
// APDU number
|
||||
usb_cmd.arg[0] = i + 1;
|
||||
// transfer the APDU in several parts if necessary
|
||||
for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) {
|
||||
// offset into the APDU
|
||||
usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes);
|
||||
// amount of data in this packet
|
||||
int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes));
|
||||
if (packet_length > sizeof(usb_cmd.d.asBytes)) {
|
||||
packet_length = sizeof(usb_cmd.d.asBytes);
|
||||
}
|
||||
usb_cmd.arg[2] = packet_length;
|
||||
|
||||
memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)),
|
||||
apdus[i] + (j * sizeof(usb_cmd.d.asBytes)),
|
||||
packet_length);
|
||||
SendCommand(&usb_cmd);
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
if (resp.arg[0] != 0) {
|
||||
PrintAndLog("Transfer of APDU #%d Part %d failed!", i, j);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now perform the replay
|
||||
usb_cmd.arg[0] = 0;
|
||||
SendCommand(&usb_cmd);
|
||||
WaitForResponse(CMD_ACK, &resp);
|
||||
if (resp.arg[0] != 0) {
|
||||
PrintAndLog("\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]);
|
||||
PrintAndLog("Measured times:");
|
||||
PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
|
||||
PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
|
||||
PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
|
||||
PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
|
||||
PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
|
||||
} else {
|
||||
PrintAndLog("PACE replay successfull!");
|
||||
PrintAndLog("MSE Set AT: %u us", resp.d.asDwords[0]);
|
||||
PrintAndLog("GA Get Nonce: %u us", resp.d.asDwords[1]);
|
||||
PrintAndLog("GA Map Nonce: %u us", resp.d.asDwords[2]);
|
||||
PrintAndLog("GA Perform Key Agreement: %u us", resp.d.asDwords[3]);
|
||||
PrintAndLog("GA Mutual Authenticate: %u us", resp.d.asDwords[4]);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////The new commands lie above here/////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// UI-related stuff
|
||||
|
||||
static const command_t CommandTable[] =
|
||||
static const command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"cnonces", CmdHFEPACollectPACENonces, 0,
|
||||
"<m> <n> <d> Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"},
|
||||
{"preplay", CmdHFEPAPACEReplay, 0,
|
||||
"<mse> <get> <map> <pka> <ma> Perform PACE protocol by replaying given APDUs"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
|
@ -92,4 +202,4 @@ int CmdHFEPA(const char *Cmd)
|
|||
// parse
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,34 +165,47 @@ int CmdHFiClassSim(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdHFiClassReader(const char *Cmd)
|
||||
int HFiClassReader(const char *Cmd, bool loop, bool verbose)
|
||||
{
|
||||
bool tagFound = false;
|
||||
UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN|
|
||||
FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}};
|
||||
if (!loop) c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
|
||||
SendCommand(&c);
|
||||
UsbCommand resp;
|
||||
while(!ukbhit()){
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
|
||||
uint8_t readStatus = resp.arg[0] & 0xff;
|
||||
uint8_t * data = resp.d.asBytes;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
|
||||
uint8_t readStatus = resp.arg[0] & 0xff;
|
||||
uint8_t *data = resp.d.asBytes;
|
||||
|
||||
PrintAndLog("Readstatus:%02x", readStatus);
|
||||
if (verbose)
|
||||
PrintAndLog("Readstatus:%02x", readStatus);
|
||||
if( readStatus == 0){
|
||||
//Aborted
|
||||
PrintAndLog("Quitting...");
|
||||
if (verbose) PrintAndLog("Quitting...");
|
||||
return 0;
|
||||
}
|
||||
if( readStatus & FLAG_ICLASS_READER_CSN) PrintAndLog("CSN: %s",sprint_hex(data,8));
|
||||
if( readStatus & FLAG_ICLASS_READER_CSN){
|
||||
PrintAndLog("CSN: %s",sprint_hex(data,8));
|
||||
tagFound = true;
|
||||
}
|
||||
if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s",sprint_hex(data+16,8));
|
||||
if( readStatus & FLAG_ICLASS_READER_CONF){
|
||||
printIclassDumpInfo(data);
|
||||
}
|
||||
if (tagFound && !loop) return 1;
|
||||
} else {
|
||||
PrintAndLog("Command execute timeout");
|
||||
if (verbose) PrintAndLog("Command execute timeout");
|
||||
}
|
||||
if (!loop) break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int CmdHFiClassReader(const char *Cmd)
|
||||
{
|
||||
return HFiClassReader(Cmd, true, true);
|
||||
}
|
||||
|
||||
int CmdHFiClassReader_Replay(const char *Cmd)
|
||||
|
@ -345,7 +358,7 @@ int CmdHFiClassReader_Dump(const char *Cmd)
|
|||
if(dataLength > 0)
|
||||
{
|
||||
PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
|
||||
memcpy(iclass_data, resp.d.asBytes,dataLength);
|
||||
memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
|
||||
iclass_datalen += dataLength;
|
||||
}else
|
||||
{//Last transfer, datalength 0 means the dump is finished
|
||||
|
|
|
@ -17,6 +17,7 @@ int CmdHFiClass(const char *Cmd);
|
|||
int CmdHFiClassSnoop(const char *Cmd);
|
||||
int CmdHFiClassSim(const char *Cmd);
|
||||
int CmdHFiClassList(const char *Cmd);
|
||||
int HFiClassReader(const char *Cmd, bool loop, bool verbose);
|
||||
int CmdHFiClassReader(const char *Cmd);
|
||||
int CmdHFiClassReader_Replay(const char *Cmd);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ int CmdHF14AMifare(const char *Cmd)
|
|||
uint32_t uid = 0;
|
||||
uint32_t nt = 0, nr = 0;
|
||||
uint64_t par_list = 0, ks_list = 0, r_key = 0;
|
||||
uint8_t isOK = 0;
|
||||
int16_t isOK = 0;
|
||||
uint8_t keyBlock[8] = {0};
|
||||
|
||||
UsbCommand c = {CMD_READER_MIFARE, {true, 0, 0}};
|
||||
|
@ -25,7 +25,7 @@ int CmdHF14AMifare(const char *Cmd)
|
|||
// message
|
||||
printf("-------------------------------------------------------------------------\n");
|
||||
printf("Executing command. Expected execution time: 25sec on average :-)\n");
|
||||
printf("Press the key on the proxmark3 device to abort both proxmark3 and client.\n");
|
||||
printf("Press button on the proxmark3 device to abort both proxmark3 and client.\n");
|
||||
printf("-------------------------------------------------------------------------\n");
|
||||
|
||||
|
||||
|
@ -47,15 +47,20 @@ start:
|
|||
}
|
||||
|
||||
UsbCommand resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
||||
isOK = resp.arg[0] & 0xff;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) {
|
||||
isOK = resp.arg[0];
|
||||
uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4);
|
||||
nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4);
|
||||
par_list = bytes_to_num(resp.d.asBytes + 8, 8);
|
||||
ks_list = bytes_to_num(resp.d.asBytes + 16, 8);
|
||||
nr = bytes_to_num(resp.d.asBytes + 24, 4);
|
||||
printf("\n\n");
|
||||
if (!isOK) PrintAndLog("Proxmark can't get statistic info. Execution aborted.\n");
|
||||
switch (isOK) {
|
||||
case -1 : PrintAndLog("Button pressed. Aborted.\n"); break;
|
||||
case -2 : PrintAndLog("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).\n"); break;
|
||||
case -3 : PrintAndLog("Card is not vulnerable to Darkside attack (its random number generator is not predictable).\n"); break;
|
||||
default: ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +439,7 @@ int CmdHF14AMfRestore(const char *Cmd)
|
|||
{
|
||||
uint8_t sectorNo,blockNo;
|
||||
uint8_t keyType = 0;
|
||||
uint8_t key[6] = {0xFF};
|
||||
uint8_t key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
|
||||
uint8_t bldata[16] = {0x00};
|
||||
uint8_t keyA[40][6];
|
||||
uint8_t keyB[40][6];
|
||||
|
@ -547,7 +552,7 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
uint8_t trgKeyType = 0;
|
||||
uint8_t SectorsCnt = 0;
|
||||
uint8_t key[6] = {0, 0, 0, 0, 0, 0};
|
||||
uint8_t keyBlock[13*6];
|
||||
uint8_t keyBlock[14*6];
|
||||
uint64_t key64 = 0;
|
||||
bool transferToEml = false;
|
||||
|
||||
|
@ -622,8 +627,14 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
|
||||
if (cmdp == 'o') {
|
||||
PrintAndLog("--target block no:%3d, target key type:%c ", trgBlockNo, trgKeyType?'B':'A');
|
||||
if (mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true)) {
|
||||
PrintAndLog("Nested error.");
|
||||
int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true);
|
||||
if (isOK) {
|
||||
switch (isOK) {
|
||||
case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
|
||||
case -2 : PrintAndLog("Button pressed. Aborted.\n"); break;
|
||||
case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break;
|
||||
default : PrintAndLog("Unknown Error.\n");
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
key64 = bytes_to_num(keyBlock, 6);
|
||||
|
@ -696,11 +707,17 @@ int CmdHF14AMfNested(const char *Cmd)
|
|||
for (trgKeyType = 0; trgKeyType < 2; trgKeyType++) {
|
||||
if (e_sector[sectorNo].foundKey[trgKeyType]) continue;
|
||||
PrintAndLog("-----------------------------------------------");
|
||||
if(mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate)) {
|
||||
PrintAndLog("Nested error.\n");
|
||||
int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate);
|
||||
if(isOK) {
|
||||
switch (isOK) {
|
||||
case -1 : PrintAndLog("Error: No response from Proxmark.\n"); break;
|
||||
case -2 : PrintAndLog("Button pressed. Aborted.\n"); break;
|
||||
case -3 : PrintAndLog("Tag isn't vulnerable to Nested Attack (random numbers are not predictable).\n"); break;
|
||||
default : PrintAndLog("Unknown Error.\n");
|
||||
}
|
||||
free(e_sector);
|
||||
return 2; }
|
||||
else {
|
||||
return 2;
|
||||
} else {
|
||||
calibrate = false;
|
||||
}
|
||||
|
||||
|
@ -1200,7 +1217,7 @@ int CmdHF14AMfELoad(const char *Cmd)
|
|||
|
||||
len = param_getstr(Cmd,nameParamNo,filename);
|
||||
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
|
||||
|
||||
fnameptr += len;
|
||||
|
||||
|
@ -1299,17 +1316,20 @@ int CmdHF14AMfESave(const char *Cmd)
|
|||
|
||||
len = param_getstr(Cmd,nameParamNo,filename);
|
||||
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
|
||||
|
||||
// user supplied filename?
|
||||
if (len < 1) {
|
||||
// get filename (UID from memory)
|
||||
if (mfEmlGetMem(buf, 0, 1)) {
|
||||
PrintAndLog("Can\'t get UID from block: %d", 0);
|
||||
sprintf(filename, "dump.eml");
|
||||
len = sprintf(fnameptr, "dump");
|
||||
fnameptr += len;
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < 7; j++, fnameptr += 2)
|
||||
sprintf(fnameptr, "%02X", buf[j]);
|
||||
}
|
||||
for (j = 0; j < 7; j++, fnameptr += 2)
|
||||
sprintf(fnameptr, "%02X", buf[j]);
|
||||
} else {
|
||||
fnameptr += len;
|
||||
}
|
||||
|
@ -1499,16 +1519,16 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
|
||||
int CmdHF14AMfCSetBlk(const char *Cmd)
|
||||
{
|
||||
uint8_t uid[8] = {0x00};
|
||||
uint8_t memBlock[16] = {0x00};
|
||||
uint8_t blockNo = 0;
|
||||
bool wipeCard = FALSE;
|
||||
int res;
|
||||
|
||||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)>");
|
||||
PrintAndLog("Usage: hf mf csetblk <block number> <block data (32 hex symbols)> [w]");
|
||||
PrintAndLog("sample: hf mf csetblk 1 01020304050607080910111213141516");
|
||||
PrintAndLog("Set block data for magic Chinese card (only works with!!!)");
|
||||
PrintAndLog("If you want wipe card then add 'w' into command line. \n");
|
||||
PrintAndLog("Set block data for magic Chinese card (only works with such cards)");
|
||||
PrintAndLog("If you also want wipe the card then add 'w' at the end of the command line");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1519,14 +1539,15 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
char ctmp = param_getchar(Cmd, 2);
|
||||
wipeCard = (ctmp == 'w' || ctmp == 'W');
|
||||
PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));
|
||||
|
||||
res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);
|
||||
res = mfCSetBlock(blockNo, memBlock, NULL, wipeCard, CSETBLOCK_SINGLE_OPER);
|
||||
if (res) {
|
||||
PrintAndLog("Can't write block. error=%d", res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Can't write block. error=%d", res);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1571,7 +1592,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
return 0;
|
||||
} else {
|
||||
len = strlen(Cmd);
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
|
||||
|
||||
memcpy(filename, Cmd, len);
|
||||
fnameptr += len;
|
||||
|
@ -1591,6 +1612,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||
fclose(f);
|
||||
PrintAndLog("File reading error.");
|
||||
return 2;
|
||||
}
|
||||
|
@ -1599,6 +1621,7 @@ int CmdHF14AMfCLoad(const char *Cmd)
|
|||
if(strlen(buf) && feof(f))
|
||||
break;
|
||||
PrintAndLog("File content error. Block data must include 32 HEX symbols");
|
||||
fclose(f);
|
||||
return 2;
|
||||
}
|
||||
for (i = 0; i < 32; i += 2)
|
||||
|
@ -1637,7 +1660,7 @@ int CmdHF14AMfCGetBlk(const char *Cmd) {
|
|||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf cgetblk <block number>");
|
||||
PrintAndLog("sample: hf mf cgetblk 1");
|
||||
PrintAndLog("Get block data from magic Chinese card (only works with!!!)\n");
|
||||
PrintAndLog("Get block data from magic Chinese card (only works with such cards)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1664,7 +1687,7 @@ int CmdHF14AMfCGetSc(const char *Cmd) {
|
|||
if (strlen(Cmd) < 1 || param_getchar(Cmd, 0) == 'h') {
|
||||
PrintAndLog("Usage: hf mf cgetsc <sector number>");
|
||||
PrintAndLog("sample: hf mf cgetsc 0");
|
||||
PrintAndLog("Get sector data from magic Chinese card (only works with!!!)\n");
|
||||
PrintAndLog("Get sector data from magic Chinese card (only works with such cards)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1738,16 +1761,19 @@ int CmdHF14AMfCSave(const char *Cmd) {
|
|||
return 0;
|
||||
} else {
|
||||
len = strlen(Cmd);
|
||||
if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
|
||||
if (len > FILE_PATH_SIZE - 4) len = FILE_PATH_SIZE - 4;
|
||||
|
||||
if (len < 1) {
|
||||
// get filename
|
||||
if (mfCGetBlock(0, buf, CSETBLOCK_SINGLE_OPER)) {
|
||||
PrintAndLog("Cant get block: %d", 0);
|
||||
return 1;
|
||||
len = sprintf(fnameptr, "dump");
|
||||
fnameptr += len;
|
||||
}
|
||||
else {
|
||||
for (j = 0; j < 7; j++, fnameptr += 2)
|
||||
sprintf(fnameptr, "%02x", buf[j]);
|
||||
}
|
||||
for (j = 0; j < 7; j++, fnameptr += 2)
|
||||
sprintf(fnameptr, "%02x", buf[j]);
|
||||
} else {
|
||||
memcpy(filename, Cmd, len);
|
||||
fnameptr += len;
|
||||
|
|
1937
client/cmdhfmfu.c
1937
client/cmdhfmfu.c
File diff suppressed because it is too large
Load diff
|
@ -1,19 +1,55 @@
|
|||
#include "cmdhfmf.h"
|
||||
#include "cmdhf14a.h"
|
||||
|
||||
//standard ultralight
|
||||
#ifndef CMDHFMFU_H__
|
||||
#define CMDHFMFU_H__
|
||||
|
||||
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 CmdHF14AMfUInfo(const char *Cmd);
|
||||
|
||||
uint32_t GetHF14AMfU_Type(void);
|
||||
int ul_print_type(uint32_t tagtype, uint8_t spacer);
|
||||
void ul_switch_off_field(void);
|
||||
|
||||
int usage_hf_mfu_dump(void);
|
||||
int usage_hf_mfu_info(void);
|
||||
int usage_hf_mfu_rdbl(void);
|
||||
int usage_hf_mfu_wrbl(void);
|
||||
|
||||
int CmdHFMFUltra(const char *Cmd);
|
||||
int CmdHF14AMfUInfo(const char *Cmd);
|
||||
|
||||
typedef enum TAGTYPE_UL {
|
||||
UNKNOWN = 0x000000,
|
||||
UL = 0x000001,
|
||||
UL_C = 0x000002,
|
||||
UL_EV1_48 = 0x000004,
|
||||
UL_EV1_128 = 0x000008,
|
||||
NTAG = 0x000010,
|
||||
NTAG_203 = 0x000020,
|
||||
NTAG_210 = 0x000040,
|
||||
NTAG_212 = 0x000080,
|
||||
NTAG_213 = 0x000100,
|
||||
NTAG_215 = 0x000200,
|
||||
NTAG_216 = 0x000400,
|
||||
MY_D = 0x000800,
|
||||
MY_D_NFC = 0x001000,
|
||||
MY_D_MOVE = 0x002000,
|
||||
MY_D_MOVE_NFC = 0x004000,
|
||||
MY_D_MOVE_LEAN= 0x008000,
|
||||
NTAG_I2C_1K = 0x010000,
|
||||
NTAG_I2C_2K = 0x020000,
|
||||
FUDAN_UL = 0x040000,
|
||||
MAGIC = 0x080000,
|
||||
UL_MAGIC = UL | MAGIC,
|
||||
UL_C_MAGIC = UL_C | MAGIC,
|
||||
UL_ERROR = 0xFFFFFF,
|
||||
} TagTypeUL_t;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,9 +23,11 @@
|
|||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static void lookupChipID(uint32_t iChipID)
|
||||
static void lookupChipID(uint32_t iChipID, uint32_t mem_used)
|
||||
{
|
||||
char asBuff[100];
|
||||
uint32_t mem_avail = 0;
|
||||
|
||||
switch(iChipID)
|
||||
{
|
||||
case 0x270B0A40:
|
||||
|
@ -103,37 +105,43 @@ static void lookupChipID(uint32_t iChipID)
|
|||
switch((iChipID&0xF00)>>8)
|
||||
{
|
||||
case 0:
|
||||
sprintf(asBuff,"None");
|
||||
mem_avail = 0;
|
||||
break;
|
||||
case 1:
|
||||
sprintf(asBuff,"8K bytes");
|
||||
mem_avail = 8;
|
||||
break;
|
||||
case 2:
|
||||
sprintf(asBuff,"16K bytes");
|
||||
mem_avail = 16;
|
||||
break;
|
||||
case 3:
|
||||
sprintf(asBuff,"32K bytes");
|
||||
mem_avail = 32;
|
||||
break;
|
||||
case 5:
|
||||
sprintf(asBuff,"64K bytes");
|
||||
mem_avail = 64;
|
||||
break;
|
||||
case 7:
|
||||
sprintf(asBuff,"128K bytes");
|
||||
mem_avail = 128;
|
||||
break;
|
||||
case 9:
|
||||
sprintf(asBuff,"256K bytes");
|
||||
mem_avail = 256;
|
||||
break;
|
||||
case 10:
|
||||
sprintf(asBuff,"512K bytes");
|
||||
mem_avail = 512;
|
||||
break;
|
||||
case 12:
|
||||
sprintf(asBuff,"1024K bytes");
|
||||
mem_avail = 1024;
|
||||
break;
|
||||
case 14:
|
||||
sprintf(asBuff,"2048K bytes");
|
||||
mem_avail = 2048;
|
||||
break;
|
||||
}
|
||||
PrintAndLog("Nonvolatile Program Memory Size: %s",asBuff);
|
||||
PrintAndLog("Nonvolatile Program Memory Size: %dK bytes. Used: %d bytes (%2.0f\%). Free: %d bytes (%2.0f\%).",
|
||||
mem_avail,
|
||||
mem_used,
|
||||
mem_avail == 0 ? 0 : (float)mem_used/(mem_avail*1024)*100,
|
||||
mem_avail*1024 - mem_used,
|
||||
mem_avail == 0 ? 0 : (float)(mem_avail*1024-mem_used)/(mem_avail*1024)*100
|
||||
);
|
||||
switch((iChipID&0xF000)>>12)
|
||||
{
|
||||
case 0:
|
||||
|
@ -396,13 +404,24 @@ int CmdTune(const char *Cmd)
|
|||
|
||||
int CmdVersion(const char *Cmd)
|
||||
{
|
||||
UsbCommand c = {CMD_VERSION};
|
||||
UsbCommand resp;
|
||||
SendCommand(&c);
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) {
|
||||
lookupChipID(resp.arg[0]);
|
||||
}
|
||||
return 0;
|
||||
|
||||
UsbCommand c = {CMD_VERSION};
|
||||
static UsbCommand resp = {0, {0, 0, 0}};
|
||||
|
||||
if (resp.arg[0] == 0 && resp.arg[1] == 0) { // no cached information available
|
||||
SendCommand(&c);
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1000) && Cmd != NULL) {
|
||||
PrintAndLog("Prox/RFID mark3 RFID instrument");
|
||||
PrintAndLog((char*)resp.d.asBytes);
|
||||
lookupChipID(resp.arg[0], resp.arg[1]);
|
||||
}
|
||||
} else if (Cmd != NULL) {
|
||||
PrintAndLog("Prox/RFID mark3 RFID instrument");
|
||||
PrintAndLog((char*)resp.d.asBytes);
|
||||
lookupChipID(resp.arg[0], resp.arg[1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
|
|
|
@ -522,7 +522,8 @@ static void ChkBitstream(const char *str)
|
|||
}
|
||||
}
|
||||
}
|
||||
//appears to attempt to simulate manchester
|
||||
//Attempt to simulate any wave in buffer (one bit per output sample)
|
||||
// converts GraphBuffer to bitstream (based on zero crossings) if needed.
|
||||
int CmdLFSim(const char *Cmd)
|
||||
{
|
||||
int i,j;
|
||||
|
@ -530,11 +531,11 @@ int CmdLFSim(const char *Cmd)
|
|||
|
||||
sscanf(Cmd, "%i", &gap);
|
||||
|
||||
/* convert to bitstream if necessary */
|
||||
// convert to bitstream if necessary
|
||||
|
||||
ChkBitstream(Cmd);
|
||||
|
||||
//can send 512 bits at a time (1 byte sent per bit...)
|
||||
//can send only 512 bits at a time (1 byte sent per bit...)
|
||||
printf("Sending [%d bytes]", GraphTraceLen);
|
||||
for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
|
||||
UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
|
||||
|
@ -606,8 +607,8 @@ int usage_lf_simpsk(void)
|
|||
// - allow pull data from DemodBuffer
|
||||
int CmdLFfskSim(const char *Cmd)
|
||||
{
|
||||
//might be able to autodetect FC and clock from Graphbuffer if using demod buffer
|
||||
//will need FChigh, FClow, Clock, and bitstream
|
||||
//might be able to autodetect FCs and clock from Graphbuffer if using demod buffer
|
||||
// otherwise will need FChigh, FClow, Clock, and bitstream
|
||||
uint8_t fcHigh=0, fcLow=0, clk=0;
|
||||
uint8_t invert=0;
|
||||
bool errors = FALSE;
|
||||
|
@ -682,6 +683,8 @@ int CmdLFfskSim(const char *Cmd)
|
|||
} else {
|
||||
setDemodBuf(data, dataLen, 0);
|
||||
}
|
||||
|
||||
//default if not found
|
||||
if (clk == 0) clk = 50;
|
||||
if (fcHigh == 0) fcHigh = 10;
|
||||
if (fcLow == 0) fcLow = 8;
|
||||
|
@ -706,9 +709,8 @@ int CmdLFfskSim(const char *Cmd)
|
|||
int CmdLFaskSim(const char *Cmd)
|
||||
{
|
||||
//autodetect clock from Graphbuffer if using demod buffer
|
||||
//will need clock, invert, manchester/raw as m or r, separator as s, and bitstream
|
||||
// needs clock, invert, manchester/raw as m or r, separator as s, and bitstream
|
||||
uint8_t encoding = 1, separator = 0;
|
||||
//char cmdp = Cmd[0], par3='m', par4=0;
|
||||
uint8_t clk=0, invert=0;
|
||||
bool errors = FALSE;
|
||||
char hexData[32] = {0x00};
|
||||
|
@ -913,30 +915,6 @@ int CmdLFSimBidir(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
|
||||
/*
|
||||
int CmdLFSimManchester(const char *Cmd)
|
||||
{
|
||||
static int clock, gap;
|
||||
static char data[1024], gapstring[8];
|
||||
|
||||
sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
|
||||
|
||||
ClearGraph(0);
|
||||
|
||||
for (int i = 0; i < strlen(data) ; ++i)
|
||||
AppendGraph(0, clock, data[i]- '0');
|
||||
|
||||
CmdManchesterMod("");
|
||||
|
||||
RepaintGraphWindow();
|
||||
|
||||
sprintf(&gapstring[0], "%i", gap);
|
||||
CmdLFSim(gapstring);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
int CmdVchDemod(const char *Cmd)
|
||||
{
|
||||
// Is this the entire sync pattern, or does this also include some
|
||||
|
@ -1033,8 +1011,8 @@ int CmdLFfind(const char *Cmd)
|
|||
}
|
||||
|
||||
if (!offline && (cmdp != '1')){
|
||||
ans=CmdLFRead("");
|
||||
ans=CmdSamples("20000");
|
||||
CmdLFRead("s");
|
||||
getSamples("30000",false);
|
||||
} else if (GraphTraceLen < 1000) {
|
||||
PrintAndLog("Data in Graphbuffer was too small.");
|
||||
return 0;
|
||||
|
@ -1094,26 +1072,42 @@ int CmdLFfind(const char *Cmd)
|
|||
return 1;
|
||||
}
|
||||
|
||||
ans=CmdFDXBdemodBI("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid FDX-B ID Found!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ans=EM4x50Read("", false);
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid EM4x50 ID Found!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
ans=CmdPSKNexWatch("");
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nValid NexWatch ID Found!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("\nNo Known Tags Found!\n");
|
||||
if (testRaw=='u' || testRaw=='U'){
|
||||
//test unknown tag formats (raw mode)
|
||||
PrintAndLog("\nChecking for Unknown tags:\n");
|
||||
ans=AutoCorrelate(4000, FALSE, FALSE);
|
||||
if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
|
||||
ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); //
|
||||
ans=GetFskClock("",FALSE,FALSE);
|
||||
if (ans != 0){ //fsk
|
||||
ans=FSKrawDemod("",FALSE);
|
||||
ans=FSKrawDemod("",TRUE);
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nUnknown FSK Modulated Tag Found!");
|
||||
printDemodBuff();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
ans=ASKmanDemod("",FALSE,FALSE);
|
||||
ans=ASKDemod("0 0 0",TRUE,FALSE,1);
|
||||
if (ans>0) {
|
||||
PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
|
||||
PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
|
||||
printDemodBuff();
|
||||
return 1;
|
||||
}
|
||||
ans=CmdPSK1rawDemod("");
|
||||
|
@ -1121,7 +1115,6 @@ int CmdLFfind(const char *Cmd)
|
|||
PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
|
||||
PrintAndLog("\nCould also be PSK3 - [currently not supported]");
|
||||
PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
|
||||
printDemodBuff();
|
||||
return 1;
|
||||
}
|
||||
PrintAndLog("\nNo Data Found!\n");
|
||||
|
@ -1147,7 +1140,6 @@ static command_t CommandTable[] =
|
|||
{"simfsk", CmdLFfskSim, 0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
|
||||
{"simpsk", CmdLFpskSim, 0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
|
||||
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
|
||||
//{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
|
||||
{"snoop", CmdLFSnoop, 0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
|
||||
{"ti", CmdLFTI, 1, "{ TI RFIDs... }"},
|
||||
{"hitag", CmdLFHitag, 1, "{ Hitag tags and transponders... }"},
|
||||
|
|
|
@ -23,7 +23,6 @@ int CmdLFaskSim(const char *Cmd);
|
|||
int CmdLFfskSim(const char *Cmd);
|
||||
int CmdLFpskSim(const char *Cmd);
|
||||
int CmdLFSimBidir(const char *Cmd);
|
||||
//int CmdLFSimManchester(const char *Cmd);
|
||||
int CmdLFSnoop(const char *Cmd);
|
||||
int CmdVchDemod(const char *Cmd);
|
||||
int CmdLFfind(const char *Cmd);
|
||||
|
|
|
@ -19,6 +19,10 @@
|
|||
#include "cmddata.h"
|
||||
#include "cmdlf.h"
|
||||
#include "cmdlfem4x.h"
|
||||
#include "lfdemod.h"
|
||||
|
||||
#define llx PRIx64
|
||||
|
||||
char *global_em410xId;
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
@ -26,11 +30,11 @@ static int CmdHelp(const char *Cmd);
|
|||
int CmdEMdemodASK(const char *Cmd)
|
||||
{
|
||||
char cmdp = param_getchar(Cmd, 0);
|
||||
int findone = (cmdp == '1') ? 1 : 0;
|
||||
UsbCommand c={CMD_EM410X_DEMOD};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
int findone = (cmdp == '1') ? 1 : 0;
|
||||
UsbCommand c={CMD_EM410X_DEMOD};
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the ID of an EM410x tag.
|
||||
|
@ -43,21 +47,21 @@ int CmdEMdemodASK(const char *Cmd)
|
|||
*/
|
||||
int CmdEM410xRead(const char *Cmd)
|
||||
{
|
||||
uint32_t hi=0;
|
||||
uint64_t lo=0;
|
||||
uint32_t hi=0;
|
||||
uint64_t lo=0;
|
||||
|
||||
if(!AskEm410xDemod("", &hi, &lo)) return 0;
|
||||
PrintAndLog("EM410x pattern found: ");
|
||||
printEM410x(hi, lo);
|
||||
if (hi){
|
||||
PrintAndLog ("EM410x XL pattern found");
|
||||
return 0;
|
||||
}
|
||||
char id[12] = {0x00};
|
||||
sprintf(id, "%010llx",lo);
|
||||
|
||||
global_em410xId = id;
|
||||
return 1;
|
||||
if(!AskEm410xDemod("", &hi, &lo, false)) return 0;
|
||||
PrintAndLog("EM410x pattern found: ");
|
||||
printEM410x(hi, lo);
|
||||
if (hi){
|
||||
PrintAndLog ("EM410x XL pattern found");
|
||||
return 0;
|
||||
}
|
||||
char id[12] = {0x00};
|
||||
sprintf(id, "%010llx",lo);
|
||||
|
||||
global_em410xId = id;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// emulate an EM410X tag
|
||||
|
@ -83,52 +87,52 @@ int CmdEM410xSim(const char *Cmd)
|
|||
PrintAndLog("Starting simulating UID %02X%02X%02X%02X%02X", uid[0],uid[1],uid[2],uid[3],uid[4]);
|
||||
PrintAndLog("Press pm3-button to about simulation");
|
||||
|
||||
/* clock is 64 in EM410x tags */
|
||||
int clock = 64;
|
||||
/* clock is 64 in EM410x tags */
|
||||
int clock = 64;
|
||||
|
||||
/* clear our graph */
|
||||
ClearGraph(0);
|
||||
/* clear our graph */
|
||||
ClearGraph(0);
|
||||
|
||||
/* write 9 start bits */
|
||||
for (i = 0; i < 9; i++)
|
||||
AppendGraph(0, clock, 1);
|
||||
/* write 9 start bits */
|
||||
for (i = 0; i < 9; i++)
|
||||
AppendGraph(0, clock, 1);
|
||||
|
||||
/* for each hex char */
|
||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
/* read each hex char */
|
||||
sscanf(&Cmd[i], "%1x", &n);
|
||||
for (j = 3; j >= 0; j--, n/= 2)
|
||||
binary[j] = n % 2;
|
||||
/* for each hex char */
|
||||
parity[0] = parity[1] = parity[2] = parity[3] = 0;
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
/* read each hex char */
|
||||
sscanf(&Cmd[i], "%1x", &n);
|
||||
for (j = 3; j >= 0; j--, n/= 2)
|
||||
binary[j] = n % 2;
|
||||
|
||||
/* append each bit */
|
||||
AppendGraph(0, clock, binary[0]);
|
||||
AppendGraph(0, clock, binary[1]);
|
||||
AppendGraph(0, clock, binary[2]);
|
||||
AppendGraph(0, clock, binary[3]);
|
||||
/* append each bit */
|
||||
AppendGraph(0, clock, binary[0]);
|
||||
AppendGraph(0, clock, binary[1]);
|
||||
AppendGraph(0, clock, binary[2]);
|
||||
AppendGraph(0, clock, binary[3]);
|
||||
|
||||
/* append parity bit */
|
||||
AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
/* append parity bit */
|
||||
AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]);
|
||||
|
||||
/* keep track of column parity */
|
||||
parity[0] ^= binary[0];
|
||||
parity[1] ^= binary[1];
|
||||
parity[2] ^= binary[2];
|
||||
parity[3] ^= binary[3];
|
||||
}
|
||||
/* keep track of column parity */
|
||||
parity[0] ^= binary[0];
|
||||
parity[1] ^= binary[1];
|
||||
parity[2] ^= binary[2];
|
||||
parity[3] ^= binary[3];
|
||||
}
|
||||
|
||||
/* parity columns */
|
||||
AppendGraph(0, clock, parity[0]);
|
||||
AppendGraph(0, clock, parity[1]);
|
||||
AppendGraph(0, clock, parity[2]);
|
||||
AppendGraph(0, clock, parity[3]);
|
||||
/* parity columns */
|
||||
AppendGraph(0, clock, parity[0]);
|
||||
AppendGraph(0, clock, parity[1]);
|
||||
AppendGraph(0, clock, parity[2]);
|
||||
AppendGraph(0, clock, parity[3]);
|
||||
|
||||
/* stop bit */
|
||||
AppendGraph(1, clock, 0);
|
||||
/* stop bit */
|
||||
AppendGraph(1, clock, 0);
|
||||
|
||||
CmdLFSim("0"); //240 start_gap.
|
||||
return 0;
|
||||
CmdLFSim("0"); //240 start_gap.
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function is equivalent of lf read + data samples + em410xread
|
||||
|
@ -139,7 +143,6 @@ int CmdEM410xSim(const char *Cmd)
|
|||
* rate gets lower, then grow the number of samples
|
||||
* Changed by martin, 4000 x 4 = 16000,
|
||||
* see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235
|
||||
|
||||
*/
|
||||
int CmdEM410xWatch(const char *Cmd)
|
||||
{
|
||||
|
@ -150,12 +153,13 @@ int CmdEM410xWatch(const char *Cmd)
|
|||
}
|
||||
|
||||
CmdLFRead("s");
|
||||
getSamples("8192",true); //capture enough to get 2 full messages
|
||||
getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)
|
||||
} while (!CmdEM410xRead(""));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//currently only supports manchester modulations
|
||||
int CmdEM410xWatchnSpoof(const char *Cmd)
|
||||
{
|
||||
CmdEM410xWatch(Cmd);
|
||||
|
@ -164,154 +168,10 @@ int CmdEM410xWatchnSpoof(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Read the transmitted data of an EM4x50 tag
|
||||
* Format:
|
||||
*
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* CCCCCCCC <- column parity bits
|
||||
* 0 <- stop bit
|
||||
* LW <- Listen Window
|
||||
*
|
||||
* This pattern repeats for every block of data being transmitted.
|
||||
* Transmission starts with two Listen Windows (LW - a modulated
|
||||
* pattern of 320 cycles each (32/32/128/64/64)).
|
||||
*
|
||||
* Note that this data may or may not be the UID. It is whatever data
|
||||
* is stored in the blocks defined in the control word First and Last
|
||||
* Word Read values. UID is stored in block 32.
|
||||
*/
|
||||
int CmdEM4x50Read(const char *Cmd)
|
||||
{
|
||||
int i, j, startblock, skip, block, start, end, low, high;
|
||||
bool complete= false;
|
||||
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
|
||||
char tmp[6];
|
||||
|
||||
high= low= 0;
|
||||
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
|
||||
|
||||
/* first get high and low values */
|
||||
for (i = 0; i < GraphTraceLen; i++)
|
||||
{
|
||||
if (GraphBuffer[i] > high)
|
||||
high = GraphBuffer[i];
|
||||
else if (GraphBuffer[i] < low)
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
|
||||
/* populate a buffer with pulse lengths */
|
||||
i= 0;
|
||||
j= 0;
|
||||
while (i < GraphTraceLen)
|
||||
{
|
||||
// measure from low to low
|
||||
while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
|
||||
++i;
|
||||
start= i;
|
||||
while ((GraphBuffer[i] < high) && (i<GraphTraceLen))
|
||||
++i;
|
||||
while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
|
||||
++i;
|
||||
if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
|
||||
break;
|
||||
}
|
||||
tmpbuff[j++]= i - start;
|
||||
}
|
||||
|
||||
/* look for data start - should be 2 pairs of LW (pulses of 192,128) */
|
||||
start= -1;
|
||||
skip= 0;
|
||||
for (i= 0; i < j - 4 ; ++i)
|
||||
{
|
||||
skip += tmpbuff[i];
|
||||
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
|
||||
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
|
||||
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
|
||||
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
|
||||
{
|
||||
start= i + 3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
startblock= i + 3;
|
||||
|
||||
/* skip over the remainder of the LW */
|
||||
skip += tmpbuff[i+1]+tmpbuff[i+2];
|
||||
while (skip < MAX_GRAPH_TRACE_LEN && GraphBuffer[skip] > low)
|
||||
++skip;
|
||||
skip += 8;
|
||||
|
||||
/* now do it again to find the end */
|
||||
end= start;
|
||||
for (i += 3; i < j - 4 ; ++i)
|
||||
{
|
||||
end += tmpbuff[i];
|
||||
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
|
||||
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
|
||||
if (tmpbuff[i+2] >= 190 && tmpbuff[i+2] <= 194)
|
||||
if (tmpbuff[i+3] >= 126 && tmpbuff[i+3] <= 130)
|
||||
{
|
||||
complete= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (start >= 0)
|
||||
PrintAndLog("Found data at sample: %i",skip);
|
||||
else
|
||||
{
|
||||
PrintAndLog("No data found!");
|
||||
PrintAndLog("Try again with more samples.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!complete)
|
||||
{
|
||||
PrintAndLog("*** Warning!");
|
||||
PrintAndLog("Partial data - no end found!");
|
||||
PrintAndLog("Try again with more samples.");
|
||||
}
|
||||
|
||||
/* get rid of leading crap */
|
||||
sprintf(tmp,"%i",skip);
|
||||
CmdLtrim(tmp);
|
||||
|
||||
/* now work through remaining buffer printing out data blocks */
|
||||
block= 0;
|
||||
i= startblock;
|
||||
while (block < 6)
|
||||
{
|
||||
PrintAndLog("Block %i:", block);
|
||||
// mandemod routine needs to be split so we can call it for data
|
||||
// just print for now for debugging
|
||||
CmdManchesterDemod("i 64");
|
||||
skip= 0;
|
||||
/* look for LW before start of next block */
|
||||
for ( ; i < j - 4 ; ++i)
|
||||
{
|
||||
skip += tmpbuff[i];
|
||||
if (tmpbuff[i] >= 190 && tmpbuff[i] <= 194)
|
||||
if (tmpbuff[i+1] >= 126 && tmpbuff[i+1] <= 130)
|
||||
break;
|
||||
}
|
||||
while (GraphBuffer[skip] > low)
|
||||
++skip;
|
||||
skip += 8;
|
||||
sprintf(tmp,"%i",skip);
|
||||
CmdLtrim(tmp);
|
||||
start += skip;
|
||||
block++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdEM410xWrite(const char *Cmd)
|
||||
{
|
||||
uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value
|
||||
int card = 0xFF; // invalid card value
|
||||
uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value
|
||||
int card = 0xFF; // invalid card value
|
||||
unsigned int clock = 0; // invalid clock value
|
||||
|
||||
sscanf(Cmd, "%" PRIx64 " %d %d", &id, &card, &clock);
|
||||
|
@ -370,133 +230,404 @@ int CmdEM410xWrite(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
|
||||
SendCommand(&c);
|
||||
UsbCommand c = {CMD_EM410X_WRITE_TAG, {card, (uint32_t)(id >> 32), (uint32_t)id}};
|
||||
SendCommand(&c);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
|
||||
{
|
||||
if (rows*cols>size) return false;
|
||||
uint8_t colP=0;
|
||||
//assume last col is a parity and do not test
|
||||
for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
|
||||
for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
|
||||
colP ^= BitStream[(rowNum*cols)+colNum];
|
||||
}
|
||||
if (colP != pType) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType)
|
||||
{
|
||||
if (rows*cols>size) return false;
|
||||
uint8_t rowP=0;
|
||||
//assume last row is a parity row and do not test
|
||||
for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) {
|
||||
for (uint8_t colNum = 0; colNum < cols; colNum++) {
|
||||
rowP ^= BitStream[(rowNum*cols)+colNum];
|
||||
}
|
||||
if (rowP != pType) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest)
|
||||
{
|
||||
if (size<45) return 0;
|
||||
uint32_t code = bytebits_to_byte(BitStream,8);
|
||||
code = code<<8 | bytebits_to_byte(BitStream+9,8);
|
||||
code = code<<8 | bytebits_to_byte(BitStream+18,8);
|
||||
code = code<<8 | bytebits_to_byte(BitStream+27,8);
|
||||
if (verbose || g_debugMode){
|
||||
for (uint8_t i = 0; i<5; i++){
|
||||
if (i == 4) PrintAndLog(""); //parity byte spacer
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x",
|
||||
BitStream[i*9],
|
||||
BitStream[i*9+1],
|
||||
BitStream[i*9+2],
|
||||
BitStream[i*9+3],
|
||||
BitStream[i*9+4],
|
||||
BitStream[i*9+5],
|
||||
BitStream[i*9+6],
|
||||
BitStream[i*9+7],
|
||||
BitStream[i*9+8],
|
||||
bytebits_to_byte(BitStream+i*9,8)
|
||||
);
|
||||
}
|
||||
if (pTest)
|
||||
PrintAndLog("Parity Passed");
|
||||
else
|
||||
PrintAndLog("Parity Failed");
|
||||
}
|
||||
return code;
|
||||
}
|
||||
/* Read the transmitted data of an EM4x50 tag
|
||||
* Format:
|
||||
*
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
|
||||
* CCCCCCCC <- column parity bits
|
||||
* 0 <- stop bit
|
||||
* LW <- Listen Window
|
||||
*
|
||||
* This pattern repeats for every block of data being transmitted.
|
||||
* Transmission starts with two Listen Windows (LW - a modulated
|
||||
* pattern of 320 cycles each (32/32/128/64/64)).
|
||||
*
|
||||
* Note that this data may or may not be the UID. It is whatever data
|
||||
* is stored in the blocks defined in the control word First and Last
|
||||
* Word Read values. UID is stored in block 32.
|
||||
*/
|
||||
//completed by Marshmellow
|
||||
int EM4x50Read(const char *Cmd, bool verbose)
|
||||
{
|
||||
uint8_t fndClk[] = {8,16,32,40,50,64,128};
|
||||
int clk = 0;
|
||||
int invert = 0;
|
||||
int tol = 0;
|
||||
int i, j, startblock, skip, block, start, end, low, high, minClk;
|
||||
bool complete = false;
|
||||
int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
|
||||
uint32_t Code[6];
|
||||
char tmp[6];
|
||||
char tmp2[20];
|
||||
int phaseoff;
|
||||
high = low = 0;
|
||||
memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
|
||||
|
||||
// get user entry if any
|
||||
sscanf(Cmd, "%i %i", &clk, &invert);
|
||||
|
||||
// save GraphBuffer - to restore it later
|
||||
save_restoreGB(1);
|
||||
|
||||
// first get high and low values
|
||||
for (i = 0; i < GraphTraceLen; i++) {
|
||||
if (GraphBuffer[i] > high)
|
||||
high = GraphBuffer[i];
|
||||
else if (GraphBuffer[i] < low)
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
|
||||
i = 0;
|
||||
j = 0;
|
||||
minClk = 255;
|
||||
// get to first full low to prime loop and skip incomplete first pulse
|
||||
while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
|
||||
++i;
|
||||
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
|
||||
++i;
|
||||
skip = i;
|
||||
|
||||
// populate tmpbuff buffer with pulse lengths
|
||||
while (i < GraphTraceLen) {
|
||||
// measure from low to low
|
||||
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
|
||||
++i;
|
||||
start= i;
|
||||
while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
|
||||
++i;
|
||||
while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
|
||||
++i;
|
||||
if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
|
||||
break;
|
||||
}
|
||||
tmpbuff[j++]= i - start;
|
||||
if (i-start < minClk && i < GraphTraceLen) {
|
||||
minClk = i - start;
|
||||
}
|
||||
}
|
||||
// set clock
|
||||
if (!clk) {
|
||||
for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
|
||||
tol = fndClk[clkCnt]/8;
|
||||
if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) {
|
||||
clk=fndClk[clkCnt];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!clk) return 0;
|
||||
} else tol = clk/8;
|
||||
|
||||
// look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
|
||||
start = -1;
|
||||
for (i= 0; i < j - 4 ; ++i) {
|
||||
skip += tmpbuff[i];
|
||||
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
|
||||
if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
|
||||
if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
|
||||
if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
|
||||
{
|
||||
start= i + 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
startblock = i + 4;
|
||||
|
||||
// skip over the remainder of LW
|
||||
skip += tmpbuff[i+1] + tmpbuff[i+2] + clk;
|
||||
if (tmpbuff[i+3]>clk)
|
||||
phaseoff = tmpbuff[i+3]-clk;
|
||||
else
|
||||
phaseoff = 0;
|
||||
// now do it again to find the end
|
||||
end = skip;
|
||||
for (i += 3; i < j - 4 ; ++i) {
|
||||
end += tmpbuff[i];
|
||||
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks
|
||||
if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks
|
||||
if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
|
||||
if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following
|
||||
{
|
||||
complete= true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
end = i;
|
||||
// report back
|
||||
if (verbose || g_debugMode) {
|
||||
if (start >= 0) {
|
||||
PrintAndLog("\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)");
|
||||
} else {
|
||||
PrintAndLog("No data found!, clock tried:%d",clk);
|
||||
PrintAndLog("Try again with more samples.");
|
||||
PrintAndLog(" or after a 'data askedge' command to clean up the read");
|
||||
return 0;
|
||||
}
|
||||
} else if (start < 0) return 0;
|
||||
start = skip;
|
||||
snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
|
||||
// get rid of leading crap
|
||||
snprintf(tmp, sizeof(tmp), "%i", skip);
|
||||
CmdLtrim(tmp);
|
||||
bool pTest;
|
||||
bool AllPTest = true;
|
||||
// now work through remaining buffer printing out data blocks
|
||||
block = 0;
|
||||
i = startblock;
|
||||
while (block < 6) {
|
||||
if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block);
|
||||
skip = phaseoff;
|
||||
|
||||
// look for LW before start of next block
|
||||
for ( ; i < j - 4 ; ++i) {
|
||||
skip += tmpbuff[i];
|
||||
if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
|
||||
if (tmpbuff[i+1] >= clk-tol)
|
||||
break;
|
||||
}
|
||||
if (i >= j-4) break; //next LW not found
|
||||
skip += clk;
|
||||
if (tmpbuff[i+1]>clk)
|
||||
phaseoff = tmpbuff[i+1]-clk;
|
||||
else
|
||||
phaseoff = 0;
|
||||
i += 2;
|
||||
if (ASKDemod(tmp2, false, false, 1) < 1) {
|
||||
save_restoreGB(0);
|
||||
return 0;
|
||||
}
|
||||
//set DemodBufferLen to just one block
|
||||
DemodBufferLen = skip/clk;
|
||||
//test parities
|
||||
pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0);
|
||||
pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0);
|
||||
AllPTest &= pTest;
|
||||
//get output
|
||||
Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
|
||||
if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d", skip, skip/clk);
|
||||
//skip to start of next block
|
||||
snprintf(tmp,sizeof(tmp),"%i",skip);
|
||||
CmdLtrim(tmp);
|
||||
block++;
|
||||
if (i >= end) break; //in case chip doesn't output 6 blocks
|
||||
}
|
||||
//print full code:
|
||||
if (verbose || g_debugMode || AllPTest){
|
||||
if (!complete) {
|
||||
PrintAndLog("*** Warning!");
|
||||
PrintAndLog("Partial data - no end found!");
|
||||
PrintAndLog("Try again with more samples.");
|
||||
}
|
||||
PrintAndLog("Found data at sample: %i - using clock: %i", start, clk);
|
||||
end = block;
|
||||
for (block=0; block < end; block++){
|
||||
PrintAndLog("Block %d: %08x",block,Code[block]);
|
||||
}
|
||||
if (AllPTest) {
|
||||
PrintAndLog("Parities Passed");
|
||||
} else {
|
||||
PrintAndLog("Parities Failed");
|
||||
PrintAndLog("Try cleaning the read samples with 'data askedge'");
|
||||
}
|
||||
}
|
||||
|
||||
//restore GraphBuffer
|
||||
save_restoreGB(0);
|
||||
return (int)AllPTest;
|
||||
}
|
||||
|
||||
int CmdEM4x50Read(const char *Cmd)
|
||||
{
|
||||
return EM4x50Read(Cmd, true);
|
||||
}
|
||||
|
||||
int CmdReadWord(const char *Cmd)
|
||||
{
|
||||
int Word = -1; //default to invalid word
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%d", &Word);
|
||||
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%d", &Word);
|
||||
|
||||
if ( (Word > 15) | (Word < 0) ) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Reading word %d", Word);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x0; //Normal mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Reading word %d", Word);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x0; //Normal mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdReadWordPWD(const char *Cmd)
|
||||
{
|
||||
int Word = -1; //default to invalid word
|
||||
int Password = 0xFFFFFFFF; //default to blank password
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%d %x", &Word, &Password);
|
||||
|
||||
int Password = 0xFFFFFFFF; //default to blank password
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%d %x", &Word, &Password);
|
||||
|
||||
if ( (Word > 15) | (Word < 0) ) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Reading word %d with password %08X", Word, Password);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x1; //Password mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = Password;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Reading word %d with password %08X", Word, Password);
|
||||
|
||||
c.cmd = CMD_EM4X_READ_WORD;
|
||||
c.d.asBytes[0] = 0x1; //Password mode
|
||||
c.arg[0] = 0;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = Password;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdWriteWord(const char *Cmd)
|
||||
{
|
||||
int Word = 16; //default to invalid block
|
||||
int Data = 0xFFFFFFFF; //default to blank data
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%x %d", &Data, &Word);
|
||||
|
||||
if (Word > 15) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Writing word %d with data %08X", Word, Data);
|
||||
|
||||
c.cmd = CMD_EM4X_WRITE_WORD;
|
||||
c.d.asBytes[0] = 0x0; //Normal mode
|
||||
c.arg[0] = Data;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
int Word = 16; //default to invalid block
|
||||
int Data = 0xFFFFFFFF; //default to blank data
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%x %d", &Data, &Word);
|
||||
|
||||
if (Word > 15) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Writing word %d with data %08X", Word, Data);
|
||||
|
||||
c.cmd = CMD_EM4X_WRITE_WORD;
|
||||
c.d.asBytes[0] = 0x0; //Normal mode
|
||||
c.arg[0] = Data;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdWriteWordPWD(const char *Cmd)
|
||||
{
|
||||
int Word = 16; //default to invalid word
|
||||
int Data = 0xFFFFFFFF; //default to blank data
|
||||
int Password = 0xFFFFFFFF; //default to blank password
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
|
||||
|
||||
if (Word > 15) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
|
||||
|
||||
c.cmd = CMD_EM4X_WRITE_WORD;
|
||||
c.d.asBytes[0] = 0x1; //Password mode
|
||||
c.arg[0] = Data;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = Password;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
int Word = 16; //default to invalid word
|
||||
int Data = 0xFFFFFFFF; //default to blank data
|
||||
int Password = 0xFFFFFFFF; //default to blank password
|
||||
UsbCommand c;
|
||||
|
||||
sscanf(Cmd, "%x %d %x", &Data, &Word, &Password);
|
||||
|
||||
if (Word > 15) {
|
||||
PrintAndLog("Word must be between 0 and 15");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("Writing word %d with data %08X and password %08X", Word, Data, Password);
|
||||
|
||||
c.cmd = CMD_EM4X_WRITE_WORD;
|
||||
c.d.asBytes[0] = 0x1; //Password mode
|
||||
c.arg[0] = Data;
|
||||
c.arg[1] = Word;
|
||||
c.arg[2] = Password;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
|
||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
||||
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
|
||||
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
|
||||
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
|
||||
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},
|
||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
|
||||
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
|
||||
{"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
|
||||
{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
|
||||
{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
|
||||
{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},
|
||||
{"writeword", CmdWriteWord, 1, "<Data> <Word> -- Write EM4xxx word data"},
|
||||
{"writewordPWD", CmdWriteWordPWD, 1, "<Data> <Word> <Password> -- Write EM4xxx word data in password mode"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
int CmdLFEM4X(const char *Cmd)
|
||||
{
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
CmdsParse(CommandTable, Cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdHelp(const char *Cmd)
|
||||
{
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#ifndef CMDLFEM4X_H__
|
||||
#define CMDLFEM4X_H__
|
||||
|
||||
int CmdLFEM4X(const char *Cmd);
|
||||
int CmdEMdemodASK(const char *Cmd);
|
||||
int CmdEM410xRead(const char *Cmd);
|
||||
int CmdEM410xSim(const char *Cmd);
|
||||
|
@ -19,9 +18,11 @@ int CmdEM410xWatch(const char *Cmd);
|
|||
int CmdEM410xWatchnSpoof(const char *Cmd);
|
||||
int CmdEM410xWrite(const char *Cmd);
|
||||
int CmdEM4x50Read(const char *Cmd);
|
||||
int CmdLFEM4X(const char *Cmd);
|
||||
int CmdReadWord(const char *Cmd);
|
||||
int CmdReadWordPWD(const char *Cmd);
|
||||
int CmdWriteWord(const char *Cmd);
|
||||
int CmdWriteWordPWD(const char *Cmd);
|
||||
int EM4x50Read(const char *Cmd, bool verbose);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "cmdlfhid.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
/*
|
||||
int CmdHIDDemod(const char *Cmd)
|
||||
{
|
||||
if (GraphTraceLen < 4800) {
|
||||
|
@ -36,7 +36,7 @@ int CmdHIDDemod(const char *Cmd)
|
|||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
int CmdHIDDemodFSK(const char *Cmd)
|
||||
{
|
||||
int findone=0;
|
||||
|
@ -106,7 +106,7 @@ int CmdHIDClone(const char *Cmd)
|
|||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"},
|
||||
//{"demod", CmdHIDDemod, 1, "Demodulate HID Prox Card II (not optimal)"},
|
||||
{"fskdemod", CmdHIDDemodFSK, 0, "['1'] Realtime HID FSK demodulator (option '1' for one tag only)"},
|
||||
{"sim", CmdHIDSim, 0, "<ID> -- HID tag simulator"},
|
||||
{"clone", CmdHIDClone, 0, "<ID> ['l'] -- Clone HID to T55x7 (tag must be in antenna)(option 'l' for 84bit ID)"},
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
#define CMDLFHID_H__
|
||||
|
||||
int CmdLFHID(const char *Cmd);
|
||||
|
||||
int CmdHIDDemod(const char *Cmd);
|
||||
//int CmdHIDDemod(const char *Cmd);
|
||||
int CmdHIDDemodFSK(const char *Cmd);
|
||||
int CmdHIDSim(const char *Cmd);
|
||||
int CmdHIDClone(const char *Cmd);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,7 +24,7 @@ int CmdIODemodFSK(const char *Cmd)
|
|||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int CmdIOProxDemod(const char *Cmd){
|
||||
if (GraphTraceLen < 4800) {
|
||||
PrintAndLog("too short; need at least 4800 samples");
|
||||
|
@ -37,7 +37,7 @@ int CmdIOProxDemod(const char *Cmd){
|
|||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*/
|
||||
int CmdIOClone(const char *Cmd)
|
||||
{
|
||||
unsigned int hi = 0, lo = 0;
|
||||
|
@ -67,7 +67,7 @@ int CmdIOClone(const char *Cmd)
|
|||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
|
||||
//{"demod", CmdIOProxDemod, 1, "Demodulate Stream"},
|
||||
{"fskdemod", CmdIODemodFSK, 0, "['1'] Realtime IO FSK demodulator (option '1' for one tag only)"},
|
||||
{"clone", CmdIOClone, 0, "Clone ioProx Tag"},
|
||||
{NULL, NULL, 0, NULL}
|
||||
|
@ -83,4 +83,4 @@ int CmdHelp(const char *Cmd)
|
|||
{
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <time.h>
|
||||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
#include "graph.h"
|
||||
|
@ -49,24 +50,24 @@ int usage_t55xx_config(){
|
|||
}
|
||||
int usage_t55xx_read(){
|
||||
PrintAndLog("Usage: lf t55xx read <block> <password>");
|
||||
PrintAndLog(" <block>, block number to read. Between 0-7");
|
||||
PrintAndLog(" <password>, OPTIONAL password (8 hex characters)");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" <block>, block number to read. Between 0-7");
|
||||
PrintAndLog(" <password>, OPTIONAL password (8 hex characters)");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx read 0 - read data from block 0");
|
||||
PrintAndLog(" lf t55xx read 0 - read data from block 0");
|
||||
PrintAndLog(" lf t55xx read 0 feedbeef - read data from block 0 password feedbeef");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
int usage_t55xx_write(){
|
||||
PrintAndLog("Usage: lf t55xx wr <block> <data> [password]");
|
||||
PrintAndLog(" <block>, block number to read. Between 0-7");
|
||||
PrintAndLog(" <block>, block number to write. Between 0-7");
|
||||
PrintAndLog(" <data>, 4 bytes of data to write (8 hex characters)");
|
||||
PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)");
|
||||
PrintAndLog("");
|
||||
PrintAndLog(" [password], OPTIONAL password 4bytes (8 hex characters)");
|
||||
PrintAndLog("");
|
||||
PrintAndLog("Examples:");
|
||||
PrintAndLog(" lf t55xx wd 3 11223344 - write 11223344 to block 3");
|
||||
PrintAndLog(" lf t55xx wd 3 11223344 feedbeef - write 11223344 to block 3 password feedbeef");
|
||||
PrintAndLog(" lf t55xx wr 3 11223344 - write 11223344 to block 3");
|
||||
PrintAndLog(" lf t55xx wr 3 11223344 feedbeef - write 11223344 to block 3 password feedbeef");
|
||||
PrintAndLog("");
|
||||
return 0;
|
||||
}
|
||||
|
@ -147,31 +148,37 @@ int CmdT55xxSetConfig(const char *Cmd) {
|
|||
param_getstr(Cmd, cmdp+1, modulation);
|
||||
cmdp += 2;
|
||||
|
||||
if ( strcmp(modulation, "FSK" ) == 0)
|
||||
if ( strcmp(modulation, "FSK" ) == 0) {
|
||||
config.modulation = DEMOD_FSK;
|
||||
else if ( strcmp(modulation, "FSK1" ) == 0)
|
||||
} else if ( strcmp(modulation, "FSK1" ) == 0) {
|
||||
config.modulation = DEMOD_FSK1;
|
||||
else if ( strcmp(modulation, "FSK1a" ) == 0)
|
||||
config.inverted=1;
|
||||
} else if ( strcmp(modulation, "FSK1a" ) == 0) {
|
||||
config.modulation = DEMOD_FSK1a;
|
||||
else if ( strcmp(modulation, "FSK2" ) == 0)
|
||||
config.inverted=0;
|
||||
} else if ( strcmp(modulation, "FSK2" ) == 0) {
|
||||
config.modulation = DEMOD_FSK2;
|
||||
else if ( strcmp(modulation, "FSK2a" ) == 0)
|
||||
config.inverted=0;
|
||||
} else if ( strcmp(modulation, "FSK2a" ) == 0) {
|
||||
config.modulation = DEMOD_FSK2a;
|
||||
else if ( strcmp(modulation, "ASK" ) == 0)
|
||||
config.inverted=1;
|
||||
} else if ( strcmp(modulation, "ASK" ) == 0) {
|
||||
config.modulation = DEMOD_ASK;
|
||||
else if ( strcmp(modulation, "NRZ" ) == 0)
|
||||
} else if ( strcmp(modulation, "NRZ" ) == 0) {
|
||||
config.modulation = DEMOD_NRZ;
|
||||
else if ( strcmp(modulation, "PSK1" ) == 0)
|
||||
} else if ( strcmp(modulation, "PSK1" ) == 0) {
|
||||
config.modulation = DEMOD_PSK1;
|
||||
else if ( strcmp(modulation, "PSK2" ) == 0)
|
||||
} else if ( strcmp(modulation, "PSK2" ) == 0) {
|
||||
config.modulation = DEMOD_PSK2;
|
||||
else if ( strcmp(modulation, "PSK3" ) == 0)
|
||||
} else if ( strcmp(modulation, "PSK3" ) == 0) {
|
||||
config.modulation = DEMOD_PSK3;
|
||||
else if ( strcmp(modulation, "BIa" ) == 0)
|
||||
} else if ( strcmp(modulation, "BIa" ) == 0) {
|
||||
config.modulation = DEMOD_BIa;
|
||||
else if ( strcmp(modulation, "BI" ) == 0)
|
||||
config.inverted=1;
|
||||
} else if ( strcmp(modulation, "BI" ) == 0) {
|
||||
config.modulation = DEMOD_BI;
|
||||
else {
|
||||
config.inverted=0;
|
||||
} else {
|
||||
PrintAndLog("Unknown modulation '%s'", modulation);
|
||||
errors = TRUE;
|
||||
}
|
||||
|
@ -255,77 +262,51 @@ int CmdT55xxReadBlock(const char *Cmd) {
|
|||
|
||||
bool DecodeT55xxBlock(){
|
||||
|
||||
char buf[8] = {0x00};
|
||||
char buf[30] = {0x00};
|
||||
char *cmdStr = buf;
|
||||
int ans = 0;
|
||||
uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};
|
||||
|
||||
DemodBufferLen = 0x00;
|
||||
|
||||
//trim 1/2 a clock from beginning
|
||||
snprintf(cmdStr, sizeof(buf),"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
switch( config.modulation ){
|
||||
case DEMOD_FSK:
|
||||
//CmdLtrim("26");
|
||||
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
sprintf(cmdStr,"%d %d", bitRate[config.bitrate], config.inverted );
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted );
|
||||
ans = FSKrawDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_FSK1:
|
||||
//CmdLtrim("26");
|
||||
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
sprintf(cmdStr,"%d 1 8 5", bitRate[config.bitrate] );
|
||||
ans = FSKrawDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_FSK1a:
|
||||
//CmdLtrim("26");
|
||||
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
sprintf(cmdStr,"%d 0 8 5", bitRate[config.bitrate] );
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d 8 5", bitRate[config.bitrate], config.inverted );
|
||||
ans = FSKrawDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_FSK2:
|
||||
//CmdLtrim("26");
|
||||
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
sprintf(cmdStr,"%d 0 10 8", bitRate[config.bitrate] );
|
||||
ans = FSKrawDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_FSK2a:
|
||||
//CmdLtrim("26");
|
||||
sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );
|
||||
CmdLtrim(cmdStr);
|
||||
sprintf(cmdStr,"%d 1 10 8", bitRate[config.bitrate] );
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d 10 8", bitRate[config.bitrate], config.inverted );
|
||||
ans = FSKrawDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_ASK:
|
||||
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
|
||||
ans = ASKmanDemod(cmdStr, FALSE, FALSE);
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted );
|
||||
ans = ASKDemod(cmdStr, FALSE, FALSE, 1);
|
||||
break;
|
||||
case DEMOD_PSK1:
|
||||
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d 0", bitRate[config.bitrate], config.inverted );
|
||||
ans = PSKDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_PSK2:
|
||||
sprintf(cmdStr,"%d 1", bitRate[config.bitrate] );
|
||||
ans = PSKDemod(cmdStr, FALSE);
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
break;
|
||||
case DEMOD_PSK3:
|
||||
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
|
||||
case DEMOD_PSK2: //inverted won't affect this
|
||||
case DEMOD_PSK3: //not fully implemented
|
||||
snprintf(cmdStr, sizeof(buf),"%d 0 1", bitRate[config.bitrate] );
|
||||
ans = PSKDemod(cmdStr, FALSE);
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
break;
|
||||
case DEMOD_NRZ:
|
||||
sprintf(cmdStr,"%d %d 1", bitRate[config.bitrate], config.inverted );
|
||||
snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );
|
||||
ans = NRZrawDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_BI:
|
||||
sprintf(cmdStr,"0 %d 0 1", bitRate[config.bitrate] );
|
||||
ans = ASKbiphaseDemod(cmdStr, FALSE);
|
||||
break;
|
||||
case DEMOD_BIa:
|
||||
sprintf(cmdStr,"0 %d 1 1", bitRate[config.bitrate] );
|
||||
snprintf(cmdStr, sizeof(buf),"0 %d %d 0", bitRate[config.bitrate], config.inverted );
|
||||
ans = ASKbiphaseDemod(cmdStr, FALSE);
|
||||
break;
|
||||
default:
|
||||
|
@ -354,114 +335,141 @@ bool tryDetectModulation(){
|
|||
char cmdStr[8] = {0};
|
||||
uint8_t hits = 0;
|
||||
t55xx_conf_block_t tests[15];
|
||||
|
||||
int bitRate=0;
|
||||
uint8_t fc1 = 0, fc2 = 0, clk=0;
|
||||
save_restoreGB(1);
|
||||
if (GetFskClock("", FALSE, FALSE)){
|
||||
uint8_t fc1 = 0, fc2 = 0, clk=0;
|
||||
fskClocks(&fc1, &fc2, &clk, FALSE);
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset)){
|
||||
if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)){
|
||||
tests[hits].modulation = DEMOD_FSK;
|
||||
if (fc1==8 && fc2 == 5)
|
||||
tests[hits].modulation = DEMOD_FSK1a;
|
||||
else if (fc1==10 && fc2 == 8)
|
||||
tests[hits].modulation = DEMOD_FSK2;
|
||||
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset)) {
|
||||
if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_FSK;
|
||||
if (fc1==8 && fc2 == 5)
|
||||
if (fc1 == 8 && fc2 == 5)
|
||||
tests[hits].modulation = DEMOD_FSK1;
|
||||
else if (fc1==10 && fc2 == 8)
|
||||
else if (fc1 == 10 && fc2 == 8)
|
||||
tests[hits].modulation = DEMOD_FSK2a;
|
||||
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
} else {
|
||||
if ( ASKmanDemod("0 0 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
if ( ASKmanDemod("0 1 1", FALSE, FALSE) && test(DEMOD_ASK, &tests[hits].offset)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
// PSK2 - needs a call to psk1TOpsk2.
|
||||
if ( PSKDemod("0 0 1", FALSE)) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (test(DEMOD_PSK2, &tests[hits].offset)){
|
||||
tests[hits].modulation = DEMOD_PSK2;
|
||||
clk = GetAskClock("", FALSE, FALSE);
|
||||
if (clk>0) {
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( ASKDemod("0 0 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
} // inverse waves does not affect this demod
|
||||
|
||||
// PSK3 - needs a call to psk1TOpsk2.
|
||||
if ( PSKDemod("0 0 1", FALSE)) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (test(DEMOD_PSK3, &tests[hits].offset)){
|
||||
tests[hits].modulation = DEMOD_PSK3;
|
||||
if ( ASKDemod("0 1 0", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_ASK;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
if ( ASKbiphaseDemod("0 0 0 0", FALSE) && test(DEMOD_BI, &tests[hits].offset, &bitRate) ) {
|
||||
tests[hits].modulation = DEMOD_BI;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
} // inverse waves does not affect this demod
|
||||
|
||||
if ( ASKbiphaseDemod("0 0 0 1", FALSE) && test(DEMOD_BI, &tests[hits].offset) ) {
|
||||
tests[hits].modulation = DEMOD_BI;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
if ( ASKbiphaseDemod("0 0 1 0", FALSE) && test(DEMOD_BIa, &tests[hits].offset, &bitRate) ) {
|
||||
tests[hits].modulation = DEMOD_BIa;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
}
|
||||
if ( ASKbiphaseDemod("0 0 1 1", FALSE) && test(DEMOD_BIa, &tests[hits].offset) ) {
|
||||
tests[hits].modulation = DEMOD_BIa;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
//undo trim from ask
|
||||
save_restoreGB(0);
|
||||
clk = GetNrzClock("", FALSE, FALSE);
|
||||
if (clk>0) {
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( NRZrawDemod("0 0 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
|
||||
if ( NRZrawDemod("0 1 1", FALSE) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_NRZ;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
}
|
||||
|
||||
//undo trim from nrz
|
||||
save_restoreGB(0);
|
||||
clk = GetPskClock("", FALSE, FALSE);
|
||||
if (clk>0) {
|
||||
PrintAndLog("clk %d",clk);
|
||||
sprintf(cmdStr,"%d", clk/2);
|
||||
CmdLtrim(cmdStr);
|
||||
if ( PSKDemod("0 0 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
if ( PSKDemod("0 1 1", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate)) {
|
||||
tests[hits].modulation = DEMOD_PSK1;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = TRUE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
// PSK2 - needs a call to psk1TOpsk2.
|
||||
if ( PSKDemod("0 0 1", FALSE)) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate)){
|
||||
tests[hits].modulation = DEMOD_PSK2;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
} // inverse waves does not affect this demod
|
||||
// PSK3 - needs a call to psk1TOpsk2.
|
||||
if ( PSKDemod("0 0 1", FALSE)) {
|
||||
psk1TOpsk2(DemodBuffer, DemodBufferLen);
|
||||
if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate)){
|
||||
tests[hits].modulation = DEMOD_PSK3;
|
||||
tests[hits].bitrate = bitRate;
|
||||
tests[hits].inverted = FALSE;
|
||||
tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);
|
||||
++hits;
|
||||
}
|
||||
} // inverse waves does not affect this demod
|
||||
}
|
||||
}
|
||||
if ( hits == 1) {
|
||||
config.modulation = tests[0].modulation;
|
||||
config.bitrate = tests[0].bitrate;
|
||||
config.inverted = tests[0].inverted;
|
||||
config.offset = tests[0].offset;
|
||||
config.block0 = tests[0].block0;
|
||||
|
@ -516,81 +524,32 @@ bool testBitRate(uint8_t readRate, uint8_t mod){
|
|||
uint8_t detRate = 0;
|
||||
switch( mod ){
|
||||
case DEMOD_FSK:
|
||||
detRate = GetFskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_FSK1:
|
||||
detRate = GetFskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_FSK1a:
|
||||
detRate = GetFskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_FSK2:
|
||||
detRate = GetFskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_FSK2a:
|
||||
detRate = GetFskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
if (expected[readRate] == detRate)
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_ASK:
|
||||
case DEMOD_BI:
|
||||
case DEMOD_BIa:
|
||||
detRate = GetAskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
if (expected[readRate] == detRate)
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_PSK1:
|
||||
detRate = GetPskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_PSK2:
|
||||
detRate = GetPskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_PSK3:
|
||||
detRate = GetPskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
if (expected[readRate] == detRate)
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_NRZ:
|
||||
detRate = GetNrzClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
if (expected[readRate] == detRate)
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
case DEMOD_BI:
|
||||
detRate = GetAskClock("",FALSE, FALSE);
|
||||
if (expected[readRate] == detRate) {
|
||||
config.bitrate = readRate;
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
|
@ -598,26 +557,27 @@ bool testBitRate(uint8_t readRate, uint8_t mod){
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
bool test(uint8_t mode, uint8_t *offset){
|
||||
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate){
|
||||
|
||||
if ( !DemodBufferLen) return FALSE;
|
||||
if ( DemodBufferLen < 64 ) return FALSE;
|
||||
uint8_t si = 0;
|
||||
for (uint8_t idx = 0; idx < 64; idx++){
|
||||
si = idx;
|
||||
if ( PackBits(si, 32, DemodBuffer) == 0x00 ) continue;
|
||||
|
||||
uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key
|
||||
uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key
|
||||
uint8_t resv = PackBits(si, 4, DemodBuffer); si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode
|
||||
// 2nibble must be zeroed.
|
||||
// moved test to here, since this gets most faults first.
|
||||
if ( resv > 0x00) continue;
|
||||
|
||||
uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //new
|
||||
uint8_t bitRate = PackBits(si, 3, DemodBuffer); si += 3; //new could check bit rate
|
||||
uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //extended mode part of rate
|
||||
int bitRate = PackBits(si, 3, DemodBuffer); si += 3; //bit rate
|
||||
if (bitRate > 7) continue;
|
||||
uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode
|
||||
uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //new
|
||||
//uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //new could check psk cr
|
||||
uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24 , 30, 31 could be tested for 0 if not extended mode
|
||||
uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1;
|
||||
//uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr
|
||||
uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode
|
||||
uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2;
|
||||
|
||||
//if extended mode
|
||||
|
@ -628,15 +588,15 @@ bool test(uint8_t mode, uint8_t *offset){
|
|||
}
|
||||
//test modulation
|
||||
if (!testModulation(mode, modread)) continue;
|
||||
|
||||
*offset = idx;
|
||||
if (!testBitRate(bitRate, mode)) continue;
|
||||
*fndBitRate = bitRate;
|
||||
*offset = idx;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void printT55xxBlock(const char *demodStr){
|
||||
void printT55xxBlock(const char *blockNum){
|
||||
|
||||
uint8_t i = config.offset;
|
||||
uint8_t endpos = 32 + i;
|
||||
|
@ -654,7 +614,7 @@ void printT55xxBlock(const char *demodStr){
|
|||
bits[i - config.offset]=DemodBuffer[i];
|
||||
|
||||
blockData = PackBits(0, 32, bits);
|
||||
PrintAndLog("0x%08X %s [%s]", blockData, sprint_bin(bits,32), demodStr);
|
||||
PrintAndLog("[%s] 0x%08X %s", blockNum, blockData, sprint_bin(bits,32));
|
||||
}
|
||||
|
||||
int special(const char *Cmd) {
|
||||
|
@ -746,16 +706,28 @@ int CmdT55xxReadTrace(const char *Cmd)
|
|||
uint32_t bl0 = PackBits(si, 32, DemodBuffer);
|
||||
uint32_t bl1 = PackBits(si+32, 32, DemodBuffer);
|
||||
|
||||
uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8;
|
||||
uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8;
|
||||
uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5;
|
||||
uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3;
|
||||
uint32_t year = PackBits(si, 4, DemodBuffer); si += 4;
|
||||
uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2;
|
||||
uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14;
|
||||
uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5;
|
||||
uint32_t acl = PackBits(si, 8, DemodBuffer); si += 8;
|
||||
uint32_t mfc = PackBits(si, 8, DemodBuffer); si += 8;
|
||||
uint32_t cid = PackBits(si, 5, DemodBuffer); si += 5;
|
||||
uint32_t icr = PackBits(si, 3, DemodBuffer); si += 3;
|
||||
uint32_t year = PackBits(si, 4, DemodBuffer); si += 4;
|
||||
uint32_t quarter = PackBits(si, 2, DemodBuffer); si += 2;
|
||||
uint32_t lotid = PackBits(si, 14, DemodBuffer); si += 14;
|
||||
uint32_t wafer = PackBits(si, 5, DemodBuffer); si += 5;
|
||||
uint32_t dw = PackBits(si, 15, DemodBuffer);
|
||||
|
||||
time_t t = time(NULL);
|
||||
struct tm tm = *localtime(&t);
|
||||
if ( year > tm.tm_year-110)
|
||||
year += 2000;
|
||||
else
|
||||
year += 2010;
|
||||
|
||||
if ( acl != 0xE0 ) {
|
||||
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
|
||||
return 1;
|
||||
}
|
||||
|
||||
PrintAndLog("");
|
||||
PrintAndLog("-- T55xx Trace Information ----------------------------------");
|
||||
PrintAndLog("-------------------------------------------------------------");
|
||||
|
@ -764,7 +736,7 @@ int CmdT55xxReadTrace(const char *Cmd)
|
|||
PrintAndLog(" CID : 0x%02X (%d) - %s", cid, cid, GetModelStrFromCID(cid));
|
||||
PrintAndLog(" ICR IC Revision : %d",icr );
|
||||
PrintAndLog(" Manufactured");
|
||||
PrintAndLog(" Year/Quarter : 20?%d/%d",year, quarter);
|
||||
PrintAndLog(" Year/Quarter : %d/%d",year, quarter);
|
||||
PrintAndLog(" Lot ID : %d", lotid );
|
||||
PrintAndLog(" Wafer number : %d", wafer);
|
||||
PrintAndLog(" Die Number : %d", dw);
|
||||
|
@ -774,8 +746,6 @@ int CmdT55xxReadTrace(const char *Cmd)
|
|||
PrintAndLog(" Block 1 : 0x%08X %s", bl1, sprint_bin(DemodBuffer+config.offset+repeat+32,32) );
|
||||
PrintAndLog("-------------------------------------------------------------");
|
||||
|
||||
if ( acl != 0xE0 )
|
||||
PrintAndLog("The modulation is most likely wrong since the ACL is not 0xE0. ");
|
||||
/*
|
||||
TRACE - BLOCK O
|
||||
Bits Definition HEX
|
||||
|
@ -809,10 +779,10 @@ int CmdT55xxInfo(const char *Cmd){
|
|||
|
||||
if (strlen(Cmd)==0)
|
||||
AquireData( CONFIGURATION_BLOCK );
|
||||
|
||||
|
||||
if (!DecodeT55xxBlock()) return 1;
|
||||
|
||||
if ( !DemodBufferLen) return 1;
|
||||
if ( DemodBufferLen < 32) return 1;
|
||||
|
||||
uint8_t si = config.offset;
|
||||
uint32_t bl0 = PackBits(si, 32, DemodBuffer);
|
||||
|
@ -922,7 +892,8 @@ int AquireData( uint8_t block ){
|
|||
}
|
||||
|
||||
char * GetBitRateStr(uint32_t id){
|
||||
static char buf[40];
|
||||
static char buf[25];
|
||||
|
||||
char *retStr = buf;
|
||||
switch (id){
|
||||
case 0:
|
||||
|
@ -957,7 +928,6 @@ char * GetBitRateStr(uint32_t id){
|
|||
return buf;
|
||||
}
|
||||
|
||||
|
||||
char * GetSaferStr(uint32_t id){
|
||||
static char buf[40];
|
||||
char *retStr = buf;
|
||||
|
@ -974,7 +944,7 @@ char * GetSaferStr(uint32_t id){
|
|||
}
|
||||
|
||||
char * GetModulationStr( uint32_t id){
|
||||
static char buf[40];
|
||||
static char buf[60];
|
||||
char *retStr = buf;
|
||||
|
||||
switch (id){
|
||||
|
@ -1003,7 +973,7 @@ char * GetModulationStr( uint32_t id){
|
|||
snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id);
|
||||
break;
|
||||
case 8:
|
||||
snprintf(retStr,sizeof(buf),"%d - Manschester",id);
|
||||
snprintf(retStr,sizeof(buf),"%d - Manchester",id);
|
||||
break;
|
||||
case 16:
|
||||
snprintf(retStr,sizeof(buf),"%d - Biphase",id);
|
||||
|
@ -1026,8 +996,8 @@ char * GetModelStrFromCID(uint32_t cid){
|
|||
static char buf[10];
|
||||
char *retStr = buf;
|
||||
|
||||
if (cid == 1) sprintf(retStr,"ATA5577M1");
|
||||
if (cid == 2) sprintf(retStr,"ATA5577M2");
|
||||
if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1");
|
||||
if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2");
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,13 +53,13 @@ char * GetSaferStr(uint32_t id);
|
|||
char * GetModulationStr( uint32_t id);
|
||||
char * GetModelStrFromCID(uint32_t cid);
|
||||
char * GetSelectedModulationStr( uint8_t id);
|
||||
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bitstream);
|
||||
uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream);
|
||||
void printT55xxBlock(const char *demodStr);
|
||||
void printConfiguration( t55xx_conf_block_t b);
|
||||
|
||||
bool DecodeT55xxBlock();
|
||||
bool tryDetectModulation();
|
||||
bool test(uint8_t mode, uint8_t *offset);
|
||||
bool test(uint8_t mode, uint8_t *offset, int *fndBitRate);
|
||||
int special(const char *Cmd);
|
||||
int AquireData( uint8_t block );
|
||||
|
||||
|
|
|
@ -83,7 +83,7 @@ int CmdList(const char *Cmd)
|
|||
{
|
||||
while ((ep = readdir (dp)) != NULL)
|
||||
{
|
||||
if(ep->d_name != NULL && str_ends_with(ep->d_name, ".lua"))
|
||||
if(str_ends_with(ep->d_name, ".lua"))
|
||||
PrintAndLog("%-16s %s", ep->d_name, "A script file");
|
||||
}
|
||||
(void) closedir (dp);
|
||||
|
|
|
@ -11,7 +11,7 @@ d3f7d3f7d3f7,
|
|||
587ee5f9350f,
|
||||
a0478cc39091,
|
||||
533cb6c723f6,
|
||||
8fd0a4f256e9
|
||||
8fd0a4f256e9,
|
||||
# more Keys from mf_default_keys.lua
|
||||
000000000001,
|
||||
000000000002,
|
||||
|
@ -42,6 +42,7 @@ a0478cc39091,
|
|||
47524f555041,--RKFJOJOGROUPKeyA
|
||||
47524f555042,--RKFJOJOGROUPKeyB
|
||||
4AF9D7ADEBE4,--DirectoryandeventlogKeyA
|
||||
4b0b20107ccb,--TNP3xxx
|
||||
505249564141,--RKFJOJOPRIVAKeyA
|
||||
505249564142,--RKFJOJOPRIVAKeyB
|
||||
505249565441,
|
||||
|
@ -49,14 +50,19 @@ a0478cc39091,
|
|||
54726176656c,--VästtrafikenKeyA
|
||||
555555555555,
|
||||
55f5a5dd38c9,
|
||||
569369c5a0e5,--kiev
|
||||
5c598c9c58b5,--RKFSLKeyB
|
||||
632193be1c3c,--kiev
|
||||
644672bd4afe,--kiev
|
||||
666666666666,
|
||||
722bfcc5375f,--RKFRejskortDanmarkKeyA
|
||||
776974687573,--VästtrafikenKeyB
|
||||
777777777777,
|
||||
888888888888,
|
||||
8fe644038790,--kiev
|
||||
999999999999,
|
||||
99c636334433,
|
||||
9de89e070277,--kiev
|
||||
a00000000000,
|
||||
a053a292a4af,
|
||||
a64598a77478,--RKFSLKeyA
|
||||
|
@ -65,6 +71,7 @@ aaaaaaaaaaaa,
|
|||
abcdef123456,--Keyfromladyada.net
|
||||
b00000000000,
|
||||
b127c6f41436,
|
||||
b5ff67cba951,--kiev
|
||||
bbbbbbbbbbbb,
|
||||
bd493a3962b6,
|
||||
c934fe34d934,
|
||||
|
@ -73,7 +80,15 @@ dddddddddddd,
|
|||
e4d2770a89be,--RKFSLKeyB
|
||||
ee0042f88840,--VästtrafikenKeyB
|
||||
eeeeeeeeeeee,
|
||||
eff603e1efe9,--kiev
|
||||
f14ee7cae863,--kiev
|
||||
f1a97341a9fc,
|
||||
f1d83f964314,--RKFRejskortDanmarkKeyB
|
||||
fc00018778f7,--VästtrafikenKeyA
|
||||
fc0001877bf7,--RKFÖstgötaTrafikenKeyA
|
||||
44ab09010845,-- hotel system
|
||||
85fed980ea5a,-- hotel system
|
||||
314B49474956,--VIGIK1KeyA
|
||||
564c505f4d41,--VIGIK1KeyB
|
||||
f4a9ef2afc6d,--BCARD KeyB
|
||||
a9f953def0a3,--
|
287
client/fpga_compress.c
Normal file
287
client/fpga_compress.c
Normal file
|
@ -0,0 +1,287 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Compression tool for FPGA config files. Compress several *.bit files at
|
||||
// compile time. Decompression is done at run time (see fpgaloader.c).
|
||||
// This uses the zlib library tuned to this specific case. The small file sizes
|
||||
// allow to use "insane" parameters for optimum compression ratio.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "zlib.h"
|
||||
|
||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||
|
||||
// zlib configuration
|
||||
#define COMPRESS_LEVEL 9 // use best possible compression
|
||||
#define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes
|
||||
#define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8.
|
||||
/* COMPRESS_STRATEGY can be
|
||||
Z_DEFAULT_STRATEGY (the default),
|
||||
Z_FILTERED (more huffmann, less string matching),
|
||||
Z_HUFFMAN_ONLY (huffman only, no string matching)
|
||||
Z_RLE (distances limited to one)
|
||||
Z_FIXED (prevents the use of dynamic Huffman codes)
|
||||
*/
|
||||
#define COMPRESS_STRATEGY Z_DEFAULT_STRATEGY
|
||||
// zlib tuning parameters:
|
||||
#define COMPRESS_GOOD_LENGTH 258
|
||||
#define COMPRESS_MAX_LAZY 258
|
||||
#define COMPRESS_MAX_NICE_LENGTH 258
|
||||
#define COMPRESS_MAX_CHAIN 8192
|
||||
|
||||
#define FPGA_INTERLEAVE_SIZE 288 // (the FPGA's internal config frame size is 288 bits. Interleaving with 288 bytes should give best compression)
|
||||
#define FPGA_CONFIG_SIZE 42336 // our current fpga_[lh]f.bit files are 42175 bytes. Rounded up to next multiple of FPGA_INTERLEAVE_SIZE
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: fpga_compress <infile1> <infile2> ... <infile_n> <outfile>\n");
|
||||
fprintf(stderr, " Combine n FPGA bitstream files and compress them into one.\n\n");
|
||||
fprintf(stderr, " fpga_compress -d <infile> <outfile>");
|
||||
fprintf(stderr, " Decompress <infile>. Write result to <outfile>");
|
||||
}
|
||||
|
||||
|
||||
static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size)
|
||||
{
|
||||
return malloc(items*size);
|
||||
}
|
||||
|
||||
|
||||
static void fpga_deflate_free(voidpf opaque, voidpf address)
|
||||
{
|
||||
return free(address);
|
||||
}
|
||||
|
||||
|
||||
static bool all_feof(FILE *infile[], uint8_t num_infiles)
|
||||
{
|
||||
for (uint16_t i = 0; i < num_infiles; i++) {
|
||||
if (!feof(infile[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile)
|
||||
{
|
||||
uint8_t *fpga_config;
|
||||
uint32_t i;
|
||||
int ret;
|
||||
uint8_t c;
|
||||
z_stream compressed_fpga_stream;
|
||||
|
||||
fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE);
|
||||
|
||||
// read the input files. Interleave them into fpga_config[]
|
||||
i = 0;
|
||||
do {
|
||||
|
||||
if (i >= num_infiles * FPGA_CONFIG_SIZE) {
|
||||
fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE);
|
||||
for(uint16_t j = 0; j < num_infiles; j++) {
|
||||
fclose(infile[j]);
|
||||
}
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for(uint16_t j = 0; j < num_infiles; j++) {
|
||||
for(uint16_t k = 0; k < FPGA_INTERLEAVE_SIZE; k++) {
|
||||
c = fgetc(infile[j]);
|
||||
if (!feof(infile[j])) {
|
||||
fpga_config[i++] = c;
|
||||
} else if (num_infiles > 1) {
|
||||
fpga_config[i++] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (!all_feof(infile, num_infiles));
|
||||
|
||||
// initialize zlib structures
|
||||
compressed_fpga_stream.next_in = fpga_config;
|
||||
compressed_fpga_stream.avail_in = i;
|
||||
compressed_fpga_stream.zalloc = fpga_deflate_malloc;
|
||||
compressed_fpga_stream.zfree = fpga_deflate_free;
|
||||
|
||||
ret = deflateInit2(&compressed_fpga_stream,
|
||||
COMPRESS_LEVEL,
|
||||
Z_DEFLATED,
|
||||
COMPRESS_WINDOW_BITS,
|
||||
COMPRESS_MEM_LEVEL,
|
||||
COMPRESS_STRATEGY);
|
||||
|
||||
// estimate the size of the compressed output
|
||||
unsigned int outsize_max = deflateBound(&compressed_fpga_stream, compressed_fpga_stream.avail_in);
|
||||
uint8_t *outbuf = malloc(outsize_max);
|
||||
compressed_fpga_stream.next_out = outbuf;
|
||||
compressed_fpga_stream.avail_out = outsize_max;
|
||||
|
||||
if (ret == Z_OK) {
|
||||
ret = deflateTune(&compressed_fpga_stream,
|
||||
COMPRESS_GOOD_LENGTH,
|
||||
COMPRESS_MAX_LAZY,
|
||||
COMPRESS_MAX_NICE_LENGTH,
|
||||
COMPRESS_MAX_CHAIN);
|
||||
}
|
||||
|
||||
if (ret == Z_OK) {
|
||||
ret = deflate(&compressed_fpga_stream, Z_FINISH);
|
||||
}
|
||||
|
||||
fprintf(stderr, "compressed %lu input bytes to %lu output bytes\n", i, compressed_fpga_stream.total_out);
|
||||
|
||||
if (ret != Z_STREAM_END) {
|
||||
fprintf(stderr, "Error in deflate(): %d %s\n", ret, compressed_fpga_stream.msg);
|
||||
free(outbuf);
|
||||
deflateEnd(&compressed_fpga_stream);
|
||||
for(uint16_t j = 0; j < num_infiles; j++) {
|
||||
fclose(infile[j]);
|
||||
}
|
||||
fclose(outfile);
|
||||
free(infile);
|
||||
free(fpga_config);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (i = 0; i < compressed_fpga_stream.total_out; i++) {
|
||||
fputc(outbuf[i], outfile);
|
||||
}
|
||||
|
||||
free(outbuf);
|
||||
deflateEnd(&compressed_fpga_stream);
|
||||
for(uint16_t j = 0; j < num_infiles; j++) {
|
||||
fclose(infile[j]);
|
||||
}
|
||||
fclose(outfile);
|
||||
free(infile);
|
||||
free(fpga_config);
|
||||
|
||||
return(EXIT_SUCCESS);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int zlib_decompress(FILE *infile, FILE *outfile)
|
||||
{
|
||||
#define DECOMPRESS_BUF_SIZE 1024
|
||||
uint8_t outbuf[DECOMPRESS_BUF_SIZE];
|
||||
uint8_t inbuf[DECOMPRESS_BUF_SIZE];
|
||||
int ret;
|
||||
|
||||
z_stream compressed_fpga_stream;
|
||||
|
||||
// initialize zlib structures
|
||||
compressed_fpga_stream.next_in = inbuf;
|
||||
compressed_fpga_stream.avail_in = 0;
|
||||
compressed_fpga_stream.next_out = outbuf;
|
||||
compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
|
||||
compressed_fpga_stream.zalloc = fpga_deflate_malloc;
|
||||
compressed_fpga_stream.zfree = fpga_deflate_free;
|
||||
|
||||
ret = inflateInit2(&compressed_fpga_stream, 0);
|
||||
|
||||
do {
|
||||
if (compressed_fpga_stream.avail_in == 0) {
|
||||
compressed_fpga_stream.next_in = inbuf;
|
||||
uint16_t i = 0;
|
||||
do {
|
||||
uint8_t c = fgetc(infile);
|
||||
if (!feof(infile)) {
|
||||
inbuf[i++] = c;
|
||||
compressed_fpga_stream.avail_in++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (i < DECOMPRESS_BUF_SIZE);
|
||||
}
|
||||
|
||||
ret = inflate(&compressed_fpga_stream, Z_SYNC_FLUSH);
|
||||
|
||||
if (ret != Z_OK && ret != Z_STREAM_END) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (compressed_fpga_stream.avail_out == 0) {
|
||||
for (uint16_t i = 0; i < DECOMPRESS_BUF_SIZE; i++) {
|
||||
fputc(outbuf[i], outfile);
|
||||
}
|
||||
compressed_fpga_stream.avail_out = DECOMPRESS_BUF_SIZE;
|
||||
compressed_fpga_stream.next_out = outbuf;
|
||||
}
|
||||
} while (ret == Z_OK);
|
||||
|
||||
if (ret == Z_STREAM_END) { // reached end of input
|
||||
uint16_t i = 0;
|
||||
while (compressed_fpga_stream.avail_out < DECOMPRESS_BUF_SIZE) {
|
||||
fputc(outbuf[i++], outfile);
|
||||
compressed_fpga_stream.avail_out++;
|
||||
}
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return(EXIT_SUCCESS);
|
||||
} else {
|
||||
fprintf(stderr, "Error. Inflate() returned error %d, %s", ret, compressed_fpga_stream.msg);
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE **infiles;
|
||||
FILE *outfile;
|
||||
|
||||
if (argc == 1 || argc == 2) {
|
||||
usage();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (!strcmp(argv[1], "-d")) { // Decompress
|
||||
infiles = calloc(1, sizeof(FILE*));
|
||||
if (argc != 4) {
|
||||
usage();
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
infiles[0] = fopen(argv[2], "rb");
|
||||
if (infiles[0] == NULL) {
|
||||
fprintf(stderr, "Error. Cannot open input file %s", argv[2]);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
outfile = fopen(argv[3], "wb");
|
||||
if (outfile == NULL) {
|
||||
fprintf(stderr, "Error. Cannot open output file %s", argv[3]);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
return zlib_decompress(infiles[0], outfile);
|
||||
|
||||
} else { // Compress
|
||||
|
||||
infiles = calloc(argc-2, sizeof(FILE*));
|
||||
for (uint16_t i = 0; i < argc-2; i++) {
|
||||
infiles[i] = fopen(argv[i+1], "rb");
|
||||
if (infiles[i] == NULL) {
|
||||
fprintf(stderr, "Error. Cannot open input file %s", argv[i+1]);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
outfile = fopen(argv[argc-1], "wb");
|
||||
if (outfile == NULL) {
|
||||
fprintf(stderr, "Error. Cannot open output file %s", argv[argc-1]);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
return zlib_compress(infiles, argc-2, outfile);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
int GraphTraceLen;
|
||||
|
||||
/* write a manchester bit to the graph */
|
||||
void AppendGraph(int redraw, int clock, int bit)
|
||||
{
|
||||
|
@ -46,6 +45,24 @@ int ClearGraph(int redraw)
|
|||
|
||||
return gtl;
|
||||
}
|
||||
// option '1' to save GraphBuffer any other to restore
|
||||
void save_restoreGB(uint8_t saveOpt)
|
||||
{
|
||||
static int SavedGB[MAX_GRAPH_TRACE_LEN];
|
||||
static int SavedGBlen;
|
||||
static bool GB_Saved = false;
|
||||
|
||||
if (saveOpt==1) { //save
|
||||
memcpy(SavedGB, GraphBuffer, sizeof(GraphBuffer));
|
||||
SavedGBlen = GraphTraceLen;
|
||||
GB_Saved=true;
|
||||
} else if (GB_Saved){ //restore
|
||||
memcpy(GraphBuffer, SavedGB, sizeof(GraphBuffer));
|
||||
GraphTraceLen = SavedGBlen;
|
||||
RepaintGraphWindow();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// DETECT CLOCK NOW IN LFDEMOD.C
|
||||
|
||||
|
@ -126,10 +143,10 @@ int GetAskClock(const char str[], bool printAns, bool verbose)
|
|||
PrintAndLog("Failed to copy from graphbuffer");
|
||||
return -1;
|
||||
}
|
||||
DetectASKClock(grph, size, &clock, 20);
|
||||
int start = DetectASKClock(grph, size, &clock, 20);
|
||||
// Only print this message if we're not looping something
|
||||
if (printAns){
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start);
|
||||
}
|
||||
return clock;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ uint8_t GetNrzClock(const char str[], bool printAns, bool verbose);
|
|||
uint8_t GetFskClock(const char str[], bool printAns, bool verbose);
|
||||
uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose);
|
||||
void setGraphBuf(uint8_t *buff, size_t size);
|
||||
void save_restoreGB(uint8_t saveOpt);
|
||||
|
||||
bool HasGraphData();
|
||||
void DetectHighLowInGraph(int *high, int *low, bool addFuzz);
|
||||
|
|
|
@ -89,7 +89,6 @@ typedef struct {
|
|||
|
||||
// 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
|
||||
|
@ -105,9 +104,8 @@ typedef struct {
|
|||
#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_SIMULATE_TAG_ISO_14443B 0x0381
|
||||
#define CMD_SNOOP_ISO_14443B 0x0382
|
||||
#define CMD_SNOOP_ISO_14443a 0x0383
|
||||
#define CMD_SIMULATE_TAG_ISO_14443a 0x0384
|
||||
#define CMD_READER_ISO_14443a 0x0385
|
||||
|
|
|
@ -59,7 +59,6 @@ local _commands = {
|
|||
|
||||
--// For the 13.56 MHz tags
|
||||
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300,
|
||||
CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 = 0x0301,
|
||||
CMD_READ_SRI512_TAG = 0x0303,
|
||||
CMD_READ_SRIX4K_TAG = 0x0304,
|
||||
CMD_READER_ISO_15693 = 0x0310,
|
||||
|
@ -76,9 +75,8 @@ local _commands = {
|
|||
CMD_SIMULATE_HITAG = 0x0371,
|
||||
CMD_READER_HITAG = 0x0372,
|
||||
|
||||
CMD_SIMULATE_TAG_HF_LISTEN = 0x0380,
|
||||
CMD_SIMULATE_TAG_ISO_14443 = 0x0381,
|
||||
CMD_SNOOP_ISO_14443 = 0x0382,
|
||||
CMD_SIMULATE_TAG_ISO_14443B = 0x0381,
|
||||
CMD_SNOOP_ISO_14443B = 0x0382,
|
||||
CMD_SNOOP_ISO_14443a = 0x0383,
|
||||
CMD_SIMULATE_TAG_ISO_14443a = 0x0384,
|
||||
CMD_READER_ISO_14443a = 0x0385,
|
||||
|
@ -135,9 +133,9 @@ local _commands = {
|
|||
CMD_MIFARE_SNIFFER = 0x0630,
|
||||
|
||||
--//ultralightC
|
||||
CMD_MIFAREUC_AUTH1 = 0x0724,
|
||||
CMD_MIFAREUC_AUTH2 = 0x0725,
|
||||
CMD_MIFAREUC_READCARD = 0x0726,
|
||||
CMD_MIFAREUC_AUTH = 0x0724,
|
||||
CMD_MIFAREUC_SETPWD = 0x0727,
|
||||
CMD_MIFAREU_SETUID = 0x0728,
|
||||
|
||||
--// mifare desfire
|
||||
CMD_MIFARE_DESFIRE_READBL = 0x0728,
|
||||
|
@ -153,10 +151,10 @@ local _commands = {
|
|||
|
||||
|
||||
local _reverse_lookup,k,v = {}
|
||||
for k, v in pairs(_commands) do
|
||||
_reverse_lookup[v] = k
|
||||
end
|
||||
_commands.tostring = function(command)
|
||||
for k, v in pairs(_commands) do
|
||||
_reverse_lookup[v] = k
|
||||
end
|
||||
_commands.tostring = function(command)
|
||||
if(type(command) == 'number') then
|
||||
return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
|
||||
end
|
||||
|
@ -217,7 +215,6 @@ function Command:getBytes()
|
|||
local data = self.data
|
||||
local cmd = self.cmd
|
||||
local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
|
||||
|
||||
return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
|
||||
return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data);
|
||||
end
|
||||
return _commands
|
||||
|
|
|
@ -1,196 +1,377 @@
|
|||
local _names = {
|
||||
--[[
|
||||
--[[ decimal, hexadecimal, ccc, elements, group, name
|
||||
--]]
|
||||
["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",
|
||||
["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",
|
||||
{"0", "0000", "0030", "air", "regular", "Whirlwind"},
|
||||
--{"0", "0000", "0030", "air", "regular", "Elite Whirlwind"},
|
||||
--{"0", "0000", "0030", "air", "regular", "Polar Whirlwind"},
|
||||
{"1", "0100", "0030", "air", "regular", "Sonic Boom"},
|
||||
{"2", "0200", "0030", "air", "regular", "Warnado"},
|
||||
{"3", "0300", "0030", "air", "regular", "Lightning Rod"},
|
||||
{"4", "0400", "0030", "earth", "regular", "Bash"},
|
||||
--{"4", "0400", "0030", "earth", "regular", "Birthday Bash"},
|
||||
{"5", "0500", "0030", "earth", "regular", "Terrafin"},
|
||||
--{"5", "0500", "0030", "earth", "regular", "Elite Terrafin"},
|
||||
{"6", "0600", "0030", "earth", "regular", "Dino Rang"},
|
||||
{"7", "0700", "0030", "earth", "regular", "Prism Break"}, --lightcore
|
||||
{"8", "0800", "0030", "fire", "regular", "Sunburn"},
|
||||
{"9", "0900", "0030", "fire", "regular", "Eruptor"}, --lightcore
|
||||
--{"9", "0900", "0030", "fire", "regular", "Elite Eruptor"},
|
||||
--{"9", "0900", "0030", "fire", "regular", "Volcanic Eruptor"},
|
||||
{"10", "0a00", "0030", "fire", "regular", "Ignitor"},
|
||||
{"11", "0b00", "0030", "fire", "regular", "Flameslinger"},
|
||||
--{"11", "0b00", "0030", "fire", "regular", "Cupid Flameslinger"},
|
||||
{"12", "0c00", "0030", "water", "regular", "Zap"},
|
||||
{"13", "0d00", "0030", "water", "regular", "Wham Shell"},
|
||||
{"14", "0e00", "0030", "water", "regular", "Gill Grunt"},
|
||||
--{"14", "0e00", "0030", "water", "regular", "Elite Gill Grunt"},
|
||||
--{"14", "0e00", "0030", "water", "regular", "Tidal Wave Gill Grunt"},
|
||||
{"15", "0f00", "0030", "water", "regular", "Slam Bam"},
|
||||
--{"15", "0f00", "0030", "water", "regular", "Surfer Slam Bam"},
|
||||
{"16", "1000", "0030", "magic", "regular", "Spyro"},
|
||||
{"17", "1100", "0030", "magic", "regular", "Voodood"},
|
||||
{"18", "1200", "0030", "magic", "regular", "Double Trouble"},
|
||||
--{"18", "1200", "0030", "magic", "regular", "Royal Double Trouble"},
|
||||
{"19", "1300", "0030", "tech", "regular", "Trigger Happy"},
|
||||
--{"19", "1300", "0030", "tech", "regular", "Elite Trigger Happy"},
|
||||
--{"19", "1300", "0030", "tech", "regular", "Springtime Trigger Happy"},
|
||||
{"20", "1400", "0030", "tech", "regular", "Drobot"},
|
||||
{"21", "1500", "0030", "tech", "regular", "Drill Sergeant"},
|
||||
{"22", "1600", "0030", "tech", "regular", "Boomer"},
|
||||
--{"22", "1600", "0030", "tech", "regular", "Lucky Boomer"},
|
||||
{"23", "1700", "0030", "magic", "regular", "Wrecking Ball"},
|
||||
--{"23", "1700", "0030", "magic", "regular", "Buddy Wrecking Ball"},
|
||||
{"24", "1800", "0030", "life", "regular", "Camo"},
|
||||
{"25", "1900", "0030", "life", "regular", "Zook"},
|
||||
{"26", "1a00", "0030", "life", "regular", "Stealth Elf"},
|
||||
--{"26", "1a00", "0030", "life", "regular", "Elite Stealth Elf"},
|
||||
--{"26", "1a00", "0528", "life", "regular", "Dark Stealth Elf"},
|
||||
{"26", "1a00", "0528", "life", "swapforce", "Ninja Stealth Elf"},
|
||||
{"27", "1b00", "0030", "life", "regular", "Stump Smash"},
|
||||
{"27", "1b00", "0118", "life", "regular", "Stump Smash"},
|
||||
--{"27", "1b00", "0030", "life", "regular", "Autumn Stump Smash"},
|
||||
{"28", "1c00", "0030", "magic", "regular", "Dark Spyro"},
|
||||
--{"28", "1c00", "0030", "magic", "regular", "Elite Spyro"},
|
||||
{"29", "1d00", "0030", "undead", "regular", "Hex"},
|
||||
--{"29", "1d00", "0030", "undead", "regular", "Hallows' Eve Hex"},
|
||||
{"30", "1e00", "0030", "undead", "regular", "Chop Chop"},
|
||||
--{"30", "1e00", "0030", "undead", "regular", "Elite Chop Chop"},
|
||||
--{"30", "1e00", "0030", "undead", "regular", "Grill Master Chop Chop"},
|
||||
{"31", "1f00", "0030", "undead", "regular", "Ghost Roaster"},
|
||||
{"32", "2000", "0030", "undead", "regular", "Cynder"},
|
||||
--{"32", "2000", "0030", "undead", "regular", "Skeletal Cynder"},
|
||||
|
||||
--[[
|
||||
ITEM
|
||||
--]]
|
||||
["C800"]="ANVIL",
|
||||
["C900"]="SECRET STASH",
|
||||
["CA00"]="REGENERATION",
|
||||
["CD00"]="SHIELD",
|
||||
["CB00"]="CROSSED SWORDS",
|
||||
["CC00"]="HOURGLASS",
|
||||
["CE00"]="SPEED BOOTS",
|
||||
["CF00"]="SPARX",
|
||||
["D000"]="CANNON",
|
||||
["D100"]="SCORPIONSTRIKER",
|
||||
{"100", "6400", "0030", "air", "giant", "Jet Vac"},
|
||||
--{"100", "6400", "0030", "air", "giant", "Full blast Jet Vac"},
|
||||
{"101", "6500", "0030", "air", "giant", "Swarm"},
|
||||
{"102", "6600", "0030", "earth", "giant", "Crusher"},
|
||||
{"103", "6700", "0030", "earth", "giant", "Flashwing"},
|
||||
--{"103", "6700", "0030", "earth", "giant", "Jade Flashwing"},
|
||||
{"104", "6800", "0030", "fire", "giant", "Hot Head"},
|
||||
{"105", "6900", "0030", "fire", "giant", "Hot Dog"},
|
||||
--{"105", "6900", "0030", "fire", "giant", "Molten Hot Dog"},
|
||||
{"106", "6a00", "0030", "water", "giant", "Chill"},
|
||||
{"107", "6b00", "0030", "water", "giant", "Thumpback"},
|
||||
--{"107", "6b00", "0030", "water", "giant", "Admiral Thumpback"},
|
||||
{"108", "6c00", "0030", "magic", "giant", "Pop Fizz"},
|
||||
--{"108", "6c00", "0030", "magic", "giant", "Hoppity Pop Fizz"},
|
||||
{"108", "6c00", "023c", "magic", "giant", "Love Potion Pop Fizz"},
|
||||
--{"108", "6c00", "0030", "magic", "giant", "Punch Pop Fizz"},
|
||||
--{"108", "6c00", "0030", "magic", "giant", "Fizzy Frenzy Pop Fizz"},
|
||||
{"109", "6d00", "0030", "magic", "giant", "Nin Jini"},
|
||||
{"110", "6e00", "0030", "tech", "giant", "Bouncer"},
|
||||
{"111", "6f00", "0030", "tech", "giant", "Sprocket"},
|
||||
{"112", "7000", "0030", "life", "giant", "Tree Rex"},
|
||||
--{"112", "7000", "0030", "life", "giant", "Gnarly Tree Rex"},
|
||||
{"113", "7100", "0030", "life", "giant", "Shroomboom"},
|
||||
--{"113", "7100", "0030", "life", "giant", "Sure shot Shroomboom"},
|
||||
{"114", "7200", "0030", "undead", "giant", "Eye Broawl"},
|
||||
{"115", "7300", "0030", "undead", "giant", "Fright Rider"},
|
||||
|
||||
--[[
|
||||
ITEM TRAPS
|
||||
--]]
|
||||
["D200"]="MAGIC TRAP",
|
||||
["D300"]="WATER TRAP",
|
||||
["D400"]="AIR TRAP",
|
||||
["D500"]="UNDEAD TRAP",
|
||||
["D600"]="TECH TRAP",
|
||||
["D700"]="FIRE TRAP",
|
||||
["D800"]="EARTH TRAP",
|
||||
["D900"]="LIFE TRAP",
|
||||
["DA00"]="DARK TRAP",
|
||||
["DB00"]="LIGHT TRAP",
|
||||
["DC00"]="KAOS TRAP",
|
||||
{"200", "c800", "0030", "", "item", "Anvil Rain"},
|
||||
{"201", "c900", "0030", "", "item", "Platinum Treasure Chest"},
|
||||
{"202", "ca00", "0030", "", "item", "Healing Elixer"},
|
||||
{"203", "cb00", "0030", "", "item", "Ghost Pirate Swords"},
|
||||
{"204", "cc00", "0030", "", "item", "Time Twist Hourglass"},
|
||||
{"205", "cd00", "0030", "", "item", "Sky Iron Shield"},
|
||||
{"206", "ce00", "0030", "", "item", "Winged Boots"},
|
||||
{"207", "cf00", "0030", "", "item", "Sparx"},
|
||||
{"208", "d000", "0030", "", "item", "Cannon"},
|
||||
{"209", "d100", "0030", "", "item", "Scorpion Striker"},
|
||||
|
||||
--[[
|
||||
ITEM
|
||||
--]]
|
||||
["E600"]="HAND OF FATE",
|
||||
["E700"]="PIGGYBANK",
|
||||
["E800"]="ROCKET RAM",
|
||||
["E900"]="TIKI SPEAKY",
|
||||
{"210", "d200", "0230", "magic", "trap", "Biter's Bane"},
|
||||
{"210", "d200", "0830", "magic", "trap", "Sorcerous Skull"},
|
||||
-- legendary Sorcerous Skull?
|
||||
{"210", "d200", "0b30", "magic", "trap", "Axe Of Illusion"},
|
||||
{"210", "d200", "0e30", "magic", "trap", "Arcane Hourglass"},
|
||||
{"210", "d200", "1230", "magic", "trap", "Spell Slapper"},
|
||||
{"210", "d200", "1430", "magic", "trap", "Rune Rocket"},
|
||||
|
||||
{"211", "d300", "0130", "water", "trap", "Tidal Tiki"},
|
||||
{"211", "d300", "0230", "water", "trap", "Wet Walter"},
|
||||
{"211", "d300", "0630", "water", "trap", "Flood Flask"},
|
||||
-- legendary flood flask?
|
||||
{"211", "d300", "0730", "water", "trap", "Soaking Staff"},
|
||||
{"211", "d300", "0b30", "water", "trap", "Aqua Axe"},
|
||||
{"211", "d300", "1630", "water", "trap", "Frost Helm"},
|
||||
|
||||
{"212", "d400", "0330", "air", "trap", "Breezy Bird"},
|
||||
{"212", "d400", "0630", "air", "trap", "Drafty Decanter"},
|
||||
{"212", "d400", "0d30", "air", "trap", "Tempest Timer"},
|
||||
{"212", "d400", "1030", "air", "trap", "Cloudy Cobra"},
|
||||
{"212", "d400", "1130", "air", "trap", "Storm Warning"},
|
||||
{"212", "d400", "1830", "air", "trap", "Cycone Saber"},
|
||||
|
||||
{"213", "d500", "0430", "undead", "trap", "Spirit Sphere"},
|
||||
{"213", "d500", "0830", "undead", "trap", "Spectral Skull"},
|
||||
{"213", "d500", "0b30", "undead", "trap", "Haunted Hatchet"},
|
||||
{"213", "d500", "0c30", "undead", "trap", "Grim Gripper"},
|
||||
{"213", "d500", "1030", "undead", "trap", "Spooky Snake"},
|
||||
{"213", "d500", "1730", "undead", "trap", "Dream Piercer"},
|
||||
|
||||
{"214", "d600", "0030", "tech", "trap", "tech Totem"},
|
||||
{"214", "d600", "0730", "tech", "trap", "Automatic Angel"},
|
||||
{"214", "d600", "0930", "tech", "trap", "Factory Flower"},
|
||||
{"214", "d600", "0c30", "tech", "trap", "Grabbing Gadget"},
|
||||
{"214", "d600", "1630", "tech", "trap", "Makers Mana"},
|
||||
{"214", "d600", "1a30", "tech", "trap", "Topsy techy"},
|
||||
|
||||
{"215", "d700", "0530", "fire", "trap", "Eternal Flame"},
|
||||
{"215", "d700", "0930", "fire", "trap", "fire Flower"},
|
||||
{"215", "d700", "1130", "fire", "trap", "Scorching Stopper"},
|
||||
{"215", "d700", "1230", "fire", "trap", "Searing Spinner"},
|
||||
{"215", "d700", "1730", "fire", "trap", "Spark Spear"},
|
||||
{"215", "d700", "1b30", "fire", "trap", "Blazing Belch"},
|
||||
|
||||
{"216", "d800", "0030", "earth", "trap", "Banded Boulder"},
|
||||
{"216", "d800", "0330", "earth", "trap", "Rock Hawk"},
|
||||
{"216", "d800", "0a30", "earth", "trap", "Slag Hammer"},
|
||||
{"216", "d800", "0e30", "earth", "trap", "Dust Of Time"},
|
||||
{"216", "d800", "1330", "earth", "trap", "Spinning Sandstorm"},
|
||||
{"216", "d800", "1a30", "earth", "trap", "Rubble Trouble"},
|
||||
|
||||
{"217", "d900", "0330", "life", "trap", "Oak Eagle"},
|
||||
{"217", "d900", "0530", "life", "trap", "Emerald Energy"},
|
||||
{"217", "d900", "0a30", "life", "trap", "Weed Whacker"},
|
||||
{"217", "d900", "1030", "life", "trap", "Seed Serpent"},
|
||||
{"217", "d900", "1830", "life", "trap", "Jade Blade"},
|
||||
{"217", "d900", "1b30", "life", "trap", "Shrub Shrieker"},
|
||||
|
||||
{"218", "da00", "0030", "dark", "trap", "dark Dagger"},
|
||||
{"218", "da00", "1430", "dark", "trap", "Shadow Spider"},
|
||||
{"218", "da00", "1a30", "dark", "trap", "Ghastly Grimace"},
|
||||
|
||||
{"219", "db00", "0030", "light", "trap", "Shining Ship"},
|
||||
{"219", "db00", "0f30", "light", "trap", "Heavenly Hawk"},
|
||||
{"219", "db00", "1b30", "light", "trap", "Beam Scream"},
|
||||
|
||||
{"220", "dc00", "3030", "kaos", "trap", "Kaos trap!"},
|
||||
--{"220", "dc00", "3130", "kaos", "trap", "Ultimate Kaos trap!"}, ?
|
||||
|
||||
|
||||
--[[
|
||||
EXPANSION
|
||||
--]]
|
||||
["012C"]="DRAGONS PEAK",
|
||||
["012D"]="EMPIRE OF ICE",
|
||||
["012E"]="PIRATE SEAS",
|
||||
["012F"]="DARKLIGHT CRYPT",
|
||||
["0130"]="VOLCANIC VAULT",
|
||||
["0131"]="MIRROR OF MYSTERY",
|
||||
["0132"]="NIGHTMARE EXPRESS",
|
||||
["0133"]="SUNSCRAPER SPIRE",
|
||||
["0134"]="MIDNIGHT MUSEUM",
|
||||
{"230", "e600", "0030", "none", "item", "Hand Of Fate"},
|
||||
{"231", "e700", "0030", "none", "item", "Piggy Bank"},
|
||||
{"232", "e800", "0030", "none", "item", "Rocket Ram"},
|
||||
{"233", "e900", "0030", "none", "item", "Tiki Speaky"},
|
||||
|
||||
{"300", "2c01", "0030", "none", "location", "Dragons Peak"},
|
||||
{"301", "2d01", "0030", "none", "location", "Empire Of Ice"},
|
||||
{"302", "2e01", "0030", "none", "location", "Pirate Seas"},
|
||||
{"303", "2f01", "0030", "none", "location", "darklight Crypt"},
|
||||
{"304", "3001", "0030", "none", "location", "Volcanic Vault"},
|
||||
{"305", "3101", "0030", "none", "location", "Mirror Of Mystery"},
|
||||
{"306", "3201", "0030", "none", "location", "Nightmare Express"},
|
||||
{"307", "3301", "0030", "light", "location", "Sunscraper Spire"},
|
||||
{"308", "3401", "0030", "dark", "location", "Midnight Museum"},
|
||||
|
||||
{"404", "9401", "0030", "earth", "legendary","Bash"},
|
||||
{"416", "a001", "0030", "magic", "legendary", "Spyro"},
|
||||
--{"", "", "0030", "magic", "legendary", "Deja Vu"},
|
||||
{"419", "a301", "0030", "tech", "legendary", "Trigger Happy"},
|
||||
--{"", "", "0030", "tech", "legendary", "bouncer"},
|
||||
--{"", "", "0030", "tech", "legendary", "jawbreaker"},
|
||||
{"430", "ae01", "0030", "undead", "legendary", "Chop Chop"},
|
||||
--{"", "", "0030", "undead", "legendary", "grim creeper"},
|
||||
--{"", "", "0030", "undead", "legendary", "night shift"},
|
||||
|
||||
--[[
|
||||
LEGENDARY
|
||||
--]]
|
||||
["0194"]="LEGENDARY BASH",
|
||||
["01A0"]="LEGENDARY SPYRO",
|
||||
["01A3"]="LEGENDARY TRIGGER HAPPY",
|
||||
["01AE"]="LEGENDARY CHOPCHOP",
|
||||
--{"", "", "0030", "air", "legendary", "blades"},
|
||||
--{"", "", "0030", "air", "legendary", "jet vac"},
|
||||
--{"", "", "0030", "air", "legendary", "Free Ranger"},
|
||||
--{"", "", "0030", "life", "legendary", "stealth elf"},
|
||||
--{"", "", "0030", "life", "legendary", "Bushwhack"},
|
||||
--{"", "", "0030", "fire", "legendary", "ignitor"},
|
||||
--{"", "", "0030", "water", "legendary", "slam bam"},
|
||||
--{"", "", "0030", "water", "legendary", "chill"},
|
||||
|
||||
--{"", "", "0030", "", "legendary", "zoo lou"},
|
||||
|
||||
--[[
|
||||
TRAPTEAM
|
||||
--]]
|
||||
["01C2"]="TRAPTEAM GUSTO",
|
||||
["01C3"]="TRAPTEAM THUNDERBOLT",
|
||||
["01C4"]="TRAPTEAM FLING KONG",
|
||||
["01C5"]="TRAPTEAM BLADES",
|
||||
["01C6"]="TRAPTEAM WALLOP",
|
||||
["01C7"]="TRAPTEAM HEAD RUSH",
|
||||
["01C8"]="TRAPTEAM FIST BUMP",
|
||||
["01C9"]="TRAPTEAM ROCKY ROLL",
|
||||
["01CA"]="TRAPTEAM WILDFIRE",
|
||||
["01CB"]="TRAPTEAM KA BOOM",
|
||||
["01CC"]="TRAPTEAM TRAIL BLAZER",
|
||||
["01CD"]="TRAPTEAM TORCH",
|
||||
["01CE"]="TRAPTEAM SNAP SHOT",
|
||||
["01CF"]="TRAPTEAM LOB STAR",
|
||||
["01D0"]="TRAPTEAM FLIP WRECK",
|
||||
["01D1"]="TRAPTEAM ECHO",
|
||||
["01D2"]="TRAPTEAM BLASTERMIND",
|
||||
["01D3"]="TRAPTEAM ENIGMA",
|
||||
["01D4"]="TRAPTEAM DEJA VU",
|
||||
["01D5"]="TRAPTEAM COBRA CADABRA",
|
||||
["01D6"]="TRAPTEAM JAWBREAKER",
|
||||
["01D7"]="TRAPTEAM GEARSHIFT",
|
||||
["01D8"]="TRAPTEAM CHOPPER",
|
||||
["01D9"]="TRAPTEAM TREAD HEAD",
|
||||
["01DA"]="TRAPTEAM BUSHWHACK",
|
||||
["01DB"]="TRAPTEAM TUFF LUCK",
|
||||
["01DC"]="TRAPTEAM FOOD FIGHT",
|
||||
["01DD"]="TRAPTEAM HIGH FIVE",
|
||||
["01DE"]="TRAPTEAM NITRO KRYPT KING",
|
||||
["01DF"]="TRAPTEAM SHORT CUT",
|
||||
["01E0"]="TRAPTEAM BAT SPIN",
|
||||
["01E1"]="TRAPTEAM FUNNY BONE",
|
||||
["01E2"]="TRAPTEAM KNIGHT LIGHT",
|
||||
["01E3"]="TRAPTEAM SPOTLIGHT",
|
||||
["01E4"]="TRAPTEAM KNIGHT MARE",
|
||||
["01E5"]="TRAPTEAM BLACKOUT",
|
||||
{"450", "c201", "0030", "air", "trapmaster", "Gusto"},
|
||||
--{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"},
|
||||
{"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"},
|
||||
--{"451", "c301", "0234", "air", "trapmaster", "Special Thunderbolt"},
|
||||
{"452", "c401", "0030", "air", "regular", "Fling Kong"},
|
||||
{"453", "c501", "0030", "air", "regular", "Blades"},
|
||||
{"454", "c601", "0030", "earth", "trapmaster", "Wallop"},
|
||||
--{"454", "c601", "0234", "earth", "trapmaster", "Special Wallop"},
|
||||
{"455", "c701", "0030", "earth", "trapmaster", "Head Rush"},
|
||||
{"455", "c701", "0234", "earth", "trapmaster", "Nitro Head Rush"},
|
||||
{"456", "c801", "0030", "earth", "regular", "Fist Bump"},
|
||||
{"457", "c901", "0030", "earth", "regular", "Rocky Roll"},
|
||||
--{"457", "c901", "0030", "earth", "regular", "Rocky Egg Roll"},
|
||||
{"458", "ca01", "0030", "fire", "trapmaster", "Wildfire"},
|
||||
{"458", "ca01", "0234", "fire", "trapmaster", "Dark Wildfire"},
|
||||
{"459", "cb01", "0030", "fire", "trapmaster", "Ka Boom"},
|
||||
--{"459", "cb01", "0234", "fire", "trapmaster", "Special Ka Boom"},
|
||||
{"460", "cc01", "0030", "fire", "regular", "Trail Blazer"},
|
||||
{"461", "cd01", "0030", "fire", "regular", "Torch"},
|
||||
{"462", "ce01", "0030", "water", "trapmaster", "Snap Shot"},
|
||||
{"462", "ce01", "0234", "water", "trapmaster", "Dark Snap Shot"},
|
||||
{"462", "6c00", "023c", "water", "trapmaster", "Instant Snap Shot"},
|
||||
--, "water", "trapmaster", "Merry Snap Shot"},
|
||||
{"463", "cf01", "0030", "water", "trapmaster", "Lob Star"},
|
||||
{"463", "cf01", "0234", "water", "trapmaster", "Winterfest Lob Star"},
|
||||
{"464", "d001", "0030", "water", "regular", "Flip Wreck"},
|
||||
{"465", "d101", "0030", "water", "regular", "Echo"},
|
||||
{"466", "d201", "0030", "magic", "trapmaster", "Blastermind"},
|
||||
--{"466", "d201", "0234", "magic", "trapmaster", "Special Blastermind"},
|
||||
{"467", "d301", "0030", "magic", "trapmaster", "Enigma"},
|
||||
--{"467", "d301", "0234", "magic", "trapmaster", "Special Enigma"},
|
||||
{"468", "d401", "0030", "magic", "regular", "Deja Vu"},
|
||||
{"469", "d501", "0030", "magic", "regular", "Cobra Cadabra"},
|
||||
--{"469", "d501", "0030", "magic", "regular", "Charming Cobra Cadabra"},
|
||||
--{"469", "d501", "0030", "magic", "regular", "King Cobra Cadabra"},
|
||||
{"470", "d601", "0030", "tech", "trapmaster", "Jawbreaker"},
|
||||
--{"470", "d601", "0234", "tech", "trapmaster", "Special Jawbreaker"},
|
||||
--{"470", "d601", "0234", "tech", "trapmaster", "Knockout Jawbreaker"},
|
||||
{"471", "d701", "0030", "tech", "trapmaster", "Gearshift"},
|
||||
--{"471", "d701", "0234", "tech", "trapmaster", "Special Gearshift"},
|
||||
{"472", "d801", "0030", "tech", "regular", "Chopper"},
|
||||
{"473", "d901", "0030", "tech", "regular", "Tread Head"},
|
||||
{"474", "da01", "0030", "life", "trapmaster", "Bushwhack"},
|
||||
--{"474", "da01", "0234", "life", "trapmaster", "Special Bushwhack"},
|
||||
{"475", "db01", "0030", "life", "trapmaster", "Tuff Luck"},
|
||||
--{"475", "db01", "0234", "life", "trapmaster", "Special Tuff Luck"},
|
||||
{"476", "dc01", "0030", "life", "regular", "Food Fight"},
|
||||
{"476", "dc01", "0612", "life", "regular", "LightCore Food Fight"},
|
||||
--{"476", "dc01", "0030", "life", "regular", "Dark Food Fight"},
|
||||
--{"476", "dc01", "0030", "life", "regular", "Frosted Food Fight"},
|
||||
--{"476", "dc01", "0030", "life", "regular", "Instant Food Fight"},
|
||||
{"477", "dd01", "0030", "life", "regular", "High Five"},
|
||||
{"478", "de01", "0030", "undead", "trapmaster", "Krypt King"},
|
||||
{"478", "de01", "0234", "undead", "trapmaster", "Nitro Krypt King"},
|
||||
{"479", "df01", "0030", "undead", "trapmaster", "Short Cut"},
|
||||
--{"479", "df01", "0234", "undead", "trapmaster", "Special Short Cut"},
|
||||
{"480", "e001", "0030", "undead", "regular", "Bat Spin"},
|
||||
{"481", "e101", "0030", "undead", "regular", "Funny Bone"},
|
||||
{"481", "e101", "0612", "undead", "regular", "LightCore Funny Bone"},
|
||||
--{"481", "e101", "0030", "undead", "regular", "Fortune Funny Bone"},
|
||||
{"482", "e201", "0030", "light", "trapmaster", "Knight light"},
|
||||
--{"482", "e201", "0234", "light", "trapmaster", "Special Knight light"},
|
||||
{"483", "e301", "0030", "light", "regular", "Spotlight"},
|
||||
--{"483", "e301", "0234", "light", "regular", "Special Spotlight"},
|
||||
{"484", "e401", "0030", "dark", "trapmaster", "Knight Mare"},
|
||||
--{"484", "e401", "0234", "dark", "trapmaster", "Special Knight Mare"},
|
||||
{"485", "e501", "0030", "dark", "regular", "Blackout"},
|
||||
--{"485", "e501", "0234", "dark", "regular", "Special Blackout"},
|
||||
|
||||
--[[
|
||||
PET
|
||||
--]]
|
||||
["01F6"]="PET BOP",
|
||||
["01F7"]="PET SPRY",
|
||||
["01F8"]="PET HIJINX",
|
||||
["01F9"]="PET TERRAFIN",
|
||||
["01FA"]="PET BREEZE",
|
||||
["01FB"]="PET WEERUPTOR",
|
||||
["01FC"]="PET PET VAC",
|
||||
["01FD"]="PET SMALL FRY",
|
||||
["01FE"]="PET DROBIT",
|
||||
["0202"]="PET GILL GRUNT",
|
||||
["0207"]="PET TRIGGER SNAPPY",
|
||||
["020E"]="PET WHISPER ELF",
|
||||
["021C"]="PET BARKLEY",
|
||||
["021D"]="PET THUMPLING",
|
||||
["021E"]="PET MINI JINI",
|
||||
["021F"]="PET EYE SMALL",
|
||||
-- MINI's
|
||||
{"502", "f601", "0030", "earth", "mini", "Bop"},
|
||||
{"505", "f901", "0030", "earth", "mini", "Terrabite"},
|
||||
|
||||
{"506", "fa01", "0030", "air", "mini", "Breeze"},
|
||||
{"508", "fc01", "0030", "air", "mini", "Pet Vac"},
|
||||
--{"508", "fc01", "0030", "air", "mini", "Power Punch Pet Vac"},
|
||||
|
||||
{"507", "fb01", "0030", "fire", "mini", "Weeruptor"},
|
||||
--{"507", "fb01", "0030", "fire", "mini", "Eggsellent Weeruptor"},
|
||||
{"509", "fd01", "0030", "fire", "mini", "Small Fry"},
|
||||
|
||||
{"510", "fe01", "0030", "tech", "mini", "Drobit"},
|
||||
{"519", "0702", "0030", "tech", "mini", "Trigger Snappy"},
|
||||
|
||||
{"526", "0e02", "0030", "life", "mini", "Whisper Elf"},
|
||||
{"540", "1c02", "0030", "life", "mini", "Barkley"},
|
||||
--{"540", "1c02", "0030", "life", "mini", "Gnarly Barkley"},
|
||||
|
||||
{"541", "1d02", "0030", "water", "mini", "Thumpling"},
|
||||
{"514", "0202", "0030", "water", "mini", "Gill Runt"},
|
||||
|
||||
{"542", "1e02", "0030", "magic", "mini", "mini Jini"},
|
||||
{"503", "f701", "0030", "magic", "mini", "Spry"},
|
||||
|
||||
{"504", "f801", "0030", "undead", "mini", "Hijinx"},
|
||||
{"543", "1f02", "0030", "undead", "mini", "Eye Small"},
|
||||
|
||||
{"3000", "b80b", "0030", "air", "mini", "Scratch", "SWAPFORCE"},
|
||||
{"3001", "b90b", "0030", "air", "SWAPFORCE", "Pop Thorn"},
|
||||
--{"3001", "b90b", "0030", "air", "SWAPFORCE", "Buttered Pop Thorn"},
|
||||
{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Slobber Tooth"},
|
||||
--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Dark Slobber Tooth"},
|
||||
--{"3002", "ba0b", "0030", "earth", "SWAPFORCE", "Sundae Slobber Tooth"},
|
||||
{"3003", "bb0b", "0030", "earth", "SWAPFORCE", "Scorp"},
|
||||
{"3004", "bc0b", "0030", "fire", "SWAPFORCE", "Fryno"},
|
||||
{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Hog Wild Fryno"},
|
||||
--{"3004", "bc0b", "0138", "fire", "SWAPFORCE", "Flip flop Fryno"},
|
||||
{"3005", "bd0b", "0030", "fire", "SWAPFORCE", "Smolderdash"},
|
||||
{"3006", "be0b", "0030", "life", "SWAPFORCE", "Bumble Blast"},
|
||||
--{"3006", "be0b", "0030", "life", "SWAPFORCE", "Jolly Bumble Blast"},
|
||||
{"3007", "bf0b", "0030", "life", "SWAPFORCE", "Zoo Lou"},
|
||||
{"3008", "c00b", "0030", "magic", "SWAPFORCE", "Dune Bug"},
|
||||
{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Star Strike"},
|
||||
--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Enchanted Star Strike"},
|
||||
--{"3009", "c10b", "0030", "magic", "SWAPFORCE", "Mystic Star Strike"},
|
||||
{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Countdown"},
|
||||
--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "Kickoff Countdown"},
|
||||
--{"3010", "c20b", "0030", "tech", "SWAPFORCE", "New Year's Countdown"},
|
||||
{"3011", "c30b", "0030", "tech", "SWAPFORCE", "Wind Up"},
|
||||
{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Roller Brawl"},
|
||||
--{"3012", "c40b", "0030", "undead", "SWAPFORCE", "Snowler Roller Brawl"},
|
||||
{"3013", "c50b", "0030", "undead", "SWAPFORCE", "Grim Creeper"},
|
||||
{"3014", "c60b", "0030", "water", "SWAPFORCE", "Rip Tide"},
|
||||
{"3015", "c70b", "0030", "water", "SWAPFORCE", "Punk Shock"},
|
||||
|
||||
--{"", "", "0030", "water", "SWAPFORCE", "Hoot Loop"},
|
||||
--{"", "", "0030", "water", "SWAPFORCE", "Trap Shadow"},
|
||||
--{"", "", "0030", "water", "SWAPFORCE", "Wash Buckler"},
|
||||
--{"", "", "0030", "water", "SWAPFORCE", "Freeze Blade"},
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Magna Charge"},
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Spy Rise"},
|
||||
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Doom Stone"},
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Rubble Rouser"},
|
||||
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Blast Zone"}
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Fire Kraken"},
|
||||
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Rattle Shake"},
|
||||
--{"", "", "0030", "fire", "SWAPFORCE", "Night Shift"},
|
||||
|
||||
--{"", "", "0030", "life", "SWAPFORCE", "Stink Bomb"},
|
||||
--{"", "", "0030", "life", "SWAPFORCE", "Grilla Drilla"},
|
||||
|
||||
--{"", "", "0030", "air", "SWAPFORCE", "Free Ranger"},
|
||||
--{"", "", "0030", "air", "SWAPFORCE", "Boom Jet"},
|
||||
|
||||
--[[
|
||||
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 ZOO LOU",
|
||||
["0BC0"]="SWAPFORCE DUNE BUG",
|
||||
["0BC1"]="SWAPFORCE STAR STRIKE",
|
||||
["0BC2"]="SWAPFORCE COUNTDOWN",
|
||||
["0BC3"]="SWAPFORCE WIND UP",
|
||||
["0BC4"]="SWAPFORCE ROLLER BRAWL",
|
||||
["0BC5"]="SWAPFORCE GRIM CREEPER",
|
||||
["0BC6"]="SWAPFORCE RIP TIDE",
|
||||
["0BC7"]="SWAPFORCE PUNK SHOCK",
|
||||
}
|
||||
return _names
|
||||
|
||||
local function find( main, sub)
|
||||
main = main:lower()
|
||||
sub = sub:lower()
|
||||
for k, v in pairs(_names) do
|
||||
if ( v[2]:lower() == main and v[3]:lower() == sub) then
|
||||
return v
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
local function list()
|
||||
print ("Type\tSub\tElement\tGame Name")
|
||||
print (string.rep('=', 54))
|
||||
for k, v in pairs(_names) do
|
||||
print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] ))
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
Find = find,
|
||||
List = list,
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ end
|
|||
return {
|
||||
convert_bin_to_html = convert_bin_to_html,
|
||||
convert_eml_to_html = convert_eml_to_html,
|
||||
convert_eml_to_bin = convert_eml_to_bin,
|
||||
SaveAsBinary = save_BIN,
|
||||
convert_eml_to_bin = convert_eml_to_bin,
|
||||
SaveAsBinary = save_BIN,
|
||||
SaveAsText = save_TEXT,
|
||||
}
|
||||
|
|
384
client/lualibs/md5.lua
Normal file
384
client/lualibs/md5.lua
Normal file
|
@ -0,0 +1,384 @@
|
|||
local md5 = {
|
||||
_VERSION = "md5.lua 0.5.0",
|
||||
_DESCRIPTION = "MD5 computation in Lua (5.1)",
|
||||
_URL = "https://github.com/kikito/md5.lua",
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
|
||||
Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
-- bit lib implementions
|
||||
|
||||
local floor, abs, max = math.floor, math.abs, math.max
|
||||
local char, byte, format, rep, sub =
|
||||
string.char, string.byte, string.format, string.rep, string.sub
|
||||
|
||||
local function check_int(n)
|
||||
-- checking not float
|
||||
if(n - floor(n) > 0) then
|
||||
error("trying to use bitwise operation on non-integer!")
|
||||
end
|
||||
end
|
||||
|
||||
local function tbl2number(tbl)
|
||||
local n = #tbl
|
||||
|
||||
local rslt = 0
|
||||
local power = 1
|
||||
for i = 1, n do
|
||||
rslt = rslt + tbl[i]*power
|
||||
power = power*2
|
||||
end
|
||||
|
||||
return rslt
|
||||
end
|
||||
|
||||
local function expand(tbl_m, tbl_n)
|
||||
local big = {}
|
||||
local small = {}
|
||||
if(#tbl_m > #tbl_n) then
|
||||
big = tbl_m
|
||||
small = tbl_n
|
||||
else
|
||||
big = tbl_n
|
||||
small = tbl_m
|
||||
end
|
||||
-- expand small
|
||||
for i = #small + 1, #big do
|
||||
small[i] = 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local to_bits -- needs to be declared before bit_not
|
||||
|
||||
local function bit_not(n)
|
||||
local tbl = to_bits(n)
|
||||
local size = max(#tbl, 32)
|
||||
for i = 1, size do
|
||||
if(tbl[i] == 1) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
-- defined as local above
|
||||
to_bits = function (n)
|
||||
check_int(n)
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
return to_bits(bit_not(abs(n)) + 1)
|
||||
end
|
||||
-- to bits table
|
||||
local tbl = {}
|
||||
local cnt = 1
|
||||
while (n > 0) do
|
||||
local last = math.fmod(n,2)
|
||||
if(last == 1) then
|
||||
tbl[cnt] = 1
|
||||
else
|
||||
tbl[cnt] = 0
|
||||
end
|
||||
n = (n-last)/2
|
||||
cnt = cnt + 1
|
||||
end
|
||||
|
||||
return tbl
|
||||
end
|
||||
|
||||
local function bit_or(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = max(#tbl_m, #tbl_n)
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i]== 0 and tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
local function bit_and(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = max(#tbl_m, #tbl_n)
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i]== 0 or tbl_n[i] == 0) then
|
||||
tbl[i] = 0
|
||||
else
|
||||
tbl[i] = 1
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
local function bit_xor(m, n)
|
||||
local tbl_m = to_bits(m)
|
||||
local tbl_n = to_bits(n)
|
||||
expand(tbl_m, tbl_n)
|
||||
|
||||
local tbl = {}
|
||||
local rslt = max(#tbl_m, #tbl_n)
|
||||
for i = 1, rslt do
|
||||
if(tbl_m[i] ~= tbl_n[i]) then
|
||||
tbl[i] = 1
|
||||
else
|
||||
tbl[i] = 0
|
||||
end
|
||||
end
|
||||
|
||||
return tbl2number(tbl)
|
||||
end
|
||||
|
||||
local function bit_rshift(n, bits)
|
||||
check_int(n)
|
||||
|
||||
local high_bit = 0
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(abs(n)) + 1
|
||||
high_bit = 2147483648 -- 0x80000000
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n/2
|
||||
n = bit_or(floor(n), high_bit)
|
||||
end
|
||||
return floor(n)
|
||||
end
|
||||
|
||||
local function bit_lshift(n, bits)
|
||||
check_int(n)
|
||||
|
||||
if(n < 0) then
|
||||
-- negative
|
||||
n = bit_not(abs(n)) + 1
|
||||
end
|
||||
|
||||
for i=1, bits do
|
||||
n = n*2
|
||||
end
|
||||
return bit_and(n, 4294967295) -- 0xFFFFFFFF
|
||||
end
|
||||
|
||||
-- convert little-endian 32-bit int to a 4-char string
|
||||
local function lei2str(i)
|
||||
local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
|
||||
return f(0)..f(8)..f(16)..f(24)
|
||||
end
|
||||
|
||||
-- convert raw string to big-endian int
|
||||
local function str2bei(s)
|
||||
local v=0
|
||||
for i=1, #s do
|
||||
v = v * 256 + byte(s, i)
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- convert raw string to little-endian int
|
||||
local function str2lei(s)
|
||||
local v=0
|
||||
for i = #s,1,-1 do
|
||||
v = v*256 + byte(s, i)
|
||||
end
|
||||
return v
|
||||
end
|
||||
|
||||
-- cut up a string in little-endian ints of given size
|
||||
local function cut_le_str(s,...)
|
||||
local o, r = 1, {}
|
||||
local args = {...}
|
||||
for i=1, #args do
|
||||
table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
|
||||
o = o + args[i]
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local swap = function (w) return str2bei(lei2str(w)) end
|
||||
|
||||
local function hex2binaryaux(hexval)
|
||||
return char(tonumber(hexval, 16))
|
||||
end
|
||||
|
||||
local function hex2binary(hex)
|
||||
local result, _ = hex:gsub('..', hex2binaryaux)
|
||||
return result
|
||||
end
|
||||
|
||||
-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
|
||||
-- 10/02/2001 jcw@equi4.com
|
||||
|
||||
local FF = 0xffffffff
|
||||
local CONSTS = {
|
||||
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
|
||||
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
|
||||
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
|
||||
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
|
||||
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
|
||||
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
|
||||
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
|
||||
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
|
||||
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
|
||||
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
|
||||
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
|
||||
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
|
||||
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
|
||||
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
|
||||
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
|
||||
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
|
||||
0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
|
||||
}
|
||||
|
||||
local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
|
||||
local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
|
||||
local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
|
||||
local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
|
||||
local z=function (f,a,b,c,d,x,s,ac)
|
||||
a=bit_and(a+f(b,c,d)+x+ac,FF)
|
||||
-- be *very* careful that left shift does not cause rounding!
|
||||
return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
|
||||
end
|
||||
|
||||
local function transform(A,B,C,D,X)
|
||||
local a,b,c,d=A,B,C,D
|
||||
local t=CONSTS
|
||||
|
||||
a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
|
||||
d=z(f,d,a,b,c,X[ 1],12,t[ 2])
|
||||
c=z(f,c,d,a,b,X[ 2],17,t[ 3])
|
||||
b=z(f,b,c,d,a,X[ 3],22,t[ 4])
|
||||
a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
|
||||
d=z(f,d,a,b,c,X[ 5],12,t[ 6])
|
||||
c=z(f,c,d,a,b,X[ 6],17,t[ 7])
|
||||
b=z(f,b,c,d,a,X[ 7],22,t[ 8])
|
||||
a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
|
||||
d=z(f,d,a,b,c,X[ 9],12,t[10])
|
||||
c=z(f,c,d,a,b,X[10],17,t[11])
|
||||
b=z(f,b,c,d,a,X[11],22,t[12])
|
||||
a=z(f,a,b,c,d,X[12], 7,t[13])
|
||||
d=z(f,d,a,b,c,X[13],12,t[14])
|
||||
c=z(f,c,d,a,b,X[14],17,t[15])
|
||||
b=z(f,b,c,d,a,X[15],22,t[16])
|
||||
|
||||
a=z(g,a,b,c,d,X[ 1], 5,t[17])
|
||||
d=z(g,d,a,b,c,X[ 6], 9,t[18])
|
||||
c=z(g,c,d,a,b,X[11],14,t[19])
|
||||
b=z(g,b,c,d,a,X[ 0],20,t[20])
|
||||
a=z(g,a,b,c,d,X[ 5], 5,t[21])
|
||||
d=z(g,d,a,b,c,X[10], 9,t[22])
|
||||
c=z(g,c,d,a,b,X[15],14,t[23])
|
||||
b=z(g,b,c,d,a,X[ 4],20,t[24])
|
||||
a=z(g,a,b,c,d,X[ 9], 5,t[25])
|
||||
d=z(g,d,a,b,c,X[14], 9,t[26])
|
||||
c=z(g,c,d,a,b,X[ 3],14,t[27])
|
||||
b=z(g,b,c,d,a,X[ 8],20,t[28])
|
||||
a=z(g,a,b,c,d,X[13], 5,t[29])
|
||||
d=z(g,d,a,b,c,X[ 2], 9,t[30])
|
||||
c=z(g,c,d,a,b,X[ 7],14,t[31])
|
||||
b=z(g,b,c,d,a,X[12],20,t[32])
|
||||
|
||||
a=z(h,a,b,c,d,X[ 5], 4,t[33])
|
||||
d=z(h,d,a,b,c,X[ 8],11,t[34])
|
||||
c=z(h,c,d,a,b,X[11],16,t[35])
|
||||
b=z(h,b,c,d,a,X[14],23,t[36])
|
||||
a=z(h,a,b,c,d,X[ 1], 4,t[37])
|
||||
d=z(h,d,a,b,c,X[ 4],11,t[38])
|
||||
c=z(h,c,d,a,b,X[ 7],16,t[39])
|
||||
b=z(h,b,c,d,a,X[10],23,t[40])
|
||||
a=z(h,a,b,c,d,X[13], 4,t[41])
|
||||
d=z(h,d,a,b,c,X[ 0],11,t[42])
|
||||
c=z(h,c,d,a,b,X[ 3],16,t[43])
|
||||
b=z(h,b,c,d,a,X[ 6],23,t[44])
|
||||
a=z(h,a,b,c,d,X[ 9], 4,t[45])
|
||||
d=z(h,d,a,b,c,X[12],11,t[46])
|
||||
c=z(h,c,d,a,b,X[15],16,t[47])
|
||||
b=z(h,b,c,d,a,X[ 2],23,t[48])
|
||||
|
||||
a=z(i,a,b,c,d,X[ 0], 6,t[49])
|
||||
d=z(i,d,a,b,c,X[ 7],10,t[50])
|
||||
c=z(i,c,d,a,b,X[14],15,t[51])
|
||||
b=z(i,b,c,d,a,X[ 5],21,t[52])
|
||||
a=z(i,a,b,c,d,X[12], 6,t[53])
|
||||
d=z(i,d,a,b,c,X[ 3],10,t[54])
|
||||
c=z(i,c,d,a,b,X[10],15,t[55])
|
||||
b=z(i,b,c,d,a,X[ 1],21,t[56])
|
||||
a=z(i,a,b,c,d,X[ 8], 6,t[57])
|
||||
d=z(i,d,a,b,c,X[15],10,t[58])
|
||||
c=z(i,c,d,a,b,X[ 6],15,t[59])
|
||||
b=z(i,b,c,d,a,X[13],21,t[60])
|
||||
a=z(i,a,b,c,d,X[ 4], 6,t[61])
|
||||
d=z(i,d,a,b,c,X[11],10,t[62])
|
||||
c=z(i,c,d,a,b,X[ 2],15,t[63])
|
||||
b=z(i,b,c,d,a,X[ 9],21,t[64])
|
||||
|
||||
return A+a,B+b,C+c,D+d
|
||||
end
|
||||
|
||||
----------------------------------------------------------------
|
||||
|
||||
function md5.sumhexa(s)
|
||||
local msgLen = #s
|
||||
local padLen = 56 - msgLen % 64
|
||||
|
||||
if msgLen % 64 > 56 then padLen = padLen + 64 end
|
||||
|
||||
if padLen == 0 then padLen = 64 end
|
||||
|
||||
s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
|
||||
|
||||
assert(#s % 64 == 0)
|
||||
|
||||
local t = CONSTS
|
||||
local a,b,c,d = t[65],t[66],t[67],t[68]
|
||||
|
||||
for i=1,#s,64 do
|
||||
local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
|
||||
assert(#X == 16)
|
||||
X[0] = table.remove(X,1) -- zero based!
|
||||
a,b,c,d = transform(a,b,c,d,X)
|
||||
end
|
||||
|
||||
return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
|
||||
end
|
||||
|
||||
function md5.sum(s)
|
||||
return hex2binary(md5.sumhexa(s))
|
||||
end
|
||||
|
||||
return md5
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
local _keys = {
|
||||
|
||||
|
||||
--[[
|
||||
|
||||
These keys are from the pm3 c-codebase.
|
||||
|
@ -157,9 +158,30 @@ local _keys = {
|
|||
'9de89e070277',
|
||||
'eff603e1efe9',
|
||||
'644672bd4afe',
|
||||
|
||||
'b5ff67cba951',
|
||||
}
|
||||
|
||||
--[[
|
||||
hotel system cards,
|
||||
http://www.proxmark.org/forum/viewtopic.php?id=2430
|
||||
--]]
|
||||
'44ab09010845',
|
||||
'85fed980ea5a',
|
||||
|
||||
--[[
|
||||
VIGIK1
|
||||
--]]
|
||||
'314B49474956',
|
||||
'564c505f4d41',
|
||||
|
||||
--[[
|
||||
BCARD keyB
|
||||
--]]
|
||||
'f4a9ef2afc6d',
|
||||
|
||||
--[[
|
||||
--]]
|
||||
'a9f953def0a3',
|
||||
}
|
||||
|
||||
---
|
||||
-- The keys above have just been pasted in, for completeness sake. They contain duplicates.
|
||||
|
|
94
client/lualibs/precalc.lua
Normal file
94
client/lualibs/precalc.lua
Normal file
|
@ -0,0 +1,94 @@
|
|||
--[[
|
||||
This is an experimental lib.
|
||||
--]]
|
||||
local utils = require('utils')
|
||||
|
||||
-- LOOKUP Tables
|
||||
local perm = {}
|
||||
perm [1]= { 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5, 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA }
|
||||
perm [2]= { 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4, 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB }
|
||||
perm [3]= { 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7, 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8 }
|
||||
perm [4]= { 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6, 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9 }
|
||||
perm [5]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
|
||||
perm [6]= { 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0, 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF }
|
||||
perm [7]= { 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3, 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC }
|
||||
perm [8]= { 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD }
|
||||
perm [9]= { 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD, 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2 }
|
||||
perm [10]= { 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC, 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3 }
|
||||
perm [11]= { 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF, 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0 }
|
||||
perm [12]= { 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE, 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1 }
|
||||
perm [13]= { 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9, 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6 }
|
||||
perm [14]= { 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8, 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7 }
|
||||
perm [15]= { 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB, 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4 }
|
||||
perm [16]= { 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA, 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5 }
|
||||
|
||||
local shifts = {}
|
||||
shifts[1]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
|
||||
shifts[2]= { 0x4, 0xB, 0xB, 0x4, 0xB, 0x4, 0x4, 0xB, 0xA, 0x5, 0x5, 0xA, 0x5, 0xA, 0xA, 0x5 }
|
||||
shifts[3]= { 0xB, 0x6, 0x0, 0xD, 0xD, 0x0, 0x6, 0xB, 0x6, 0xB, 0xD, 0x0, 0x0, 0xD, 0xB, 0x6 }
|
||||
shifts[4]= { 0xE, 0x5, 0x9, 0x2, 0x0, 0xB, 0x7, 0xC, 0x3, 0x8, 0x4, 0xF, 0xD, 0x6, 0xA, 0x1 }
|
||||
shifts[5]= { 0x4, 0xE, 0x1, 0xB, 0xF, 0x5, 0xA, 0x0, 0x3, 0x9, 0x6, 0xC, 0x8, 0x2, 0xD, 0x7 }
|
||||
shifts[6]= { 0xA, 0x4, 0x7, 0x9, 0x0, 0xE, 0xD, 0x3, 0xE, 0x0, 0x3, 0xD, 0x4, 0xA, 0x9, 0x7 }
|
||||
shifts[7]= { 0xE, 0x6, 0xE, 0x6, 0xF, 0x7, 0xF, 0x7, 0xD, 0x5, 0xD, 0x5, 0xC, 0x4, 0xC, 0x4 }
|
||||
shifts[8]= { 0x7, 0x1, 0xB, 0xD, 0xE, 0x8, 0x2, 0x4, 0x4, 0x2, 0x8, 0xE, 0xD, 0xB, 0x1, 0x7 }
|
||||
shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x7, 0xC, 0xA }
|
||||
shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe }
|
||||
|
||||
local function ApplyPermutationAndShifts( pos, value, nibble)
|
||||
local shiftbytes = shifts[pos]
|
||||
local shiftElem = shiftbytes[nibble+1] --one indexed
|
||||
local shiftOne = shiftbytes[1]
|
||||
local rs = bit32.bxor(value, bit32.bxor(shiftOne, shiftElem))
|
||||
return rs
|
||||
end
|
||||
|
||||
local function GetOne( uid, block )
|
||||
|
||||
if uid == nil then return nil, 'empty uid string' end
|
||||
if #uid == 0 then return nil, 'empty uid string' end
|
||||
if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
|
||||
if type(block) ~= 'number' then return nil, 'block is not number' end
|
||||
if block > 16 or block < 0 then return nil, 'block is out-of-range' end
|
||||
|
||||
local s = ('%s%02X'):format(uid,block)
|
||||
local nibble1 = tonumber(s:sub(1,1),16) + 1
|
||||
|
||||
local permuted = ''
|
||||
for i = 1, #s do
|
||||
local el_row = shifts[i]
|
||||
local el_value = el_row[nibble1]
|
||||
j = 1
|
||||
while j <= i do
|
||||
if i-j > 0 then
|
||||
local nibble = tonumber(s:sub(j+1,j+1),16)
|
||||
el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
|
||||
end
|
||||
j = j+1
|
||||
end
|
||||
permuted =('%s%X'):format(permuted,el_value)
|
||||
end
|
||||
|
||||
permuted = 'C2'..permuted
|
||||
local crc64numStr = utils.Crc64(permuted)
|
||||
local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
|
||||
local key = utils.ConvertBytesToHex(keybytes)
|
||||
return key:sub(1,12)
|
||||
end
|
||||
|
||||
local PreCalc =
|
||||
{
|
||||
GetAll = function(id)
|
||||
if id == nil then return nil, 'empty string' end
|
||||
if #id == 0 then return nil, 'empty string' end
|
||||
if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
|
||||
|
||||
local list = '4b0b20107ccb'
|
||||
for i = 1,15 do
|
||||
local key, err = GetOne(id,i)
|
||||
if not key then return oops(err) end
|
||||
list = list..key
|
||||
end
|
||||
return list
|
||||
end,
|
||||
}
|
||||
return PreCalc
|
|
@ -20,7 +20,9 @@ local ISO14A_COMMAND = {
|
|||
ISO14A_RAW = 8,
|
||||
ISO14A_REQUEST_TRIGGER = 0x10,
|
||||
ISO14A_APPEND_CRC = 0x20,
|
||||
ISO14A_SET_TIMEOUT = 0x40
|
||||
ISO14A_SET_TIMEOUT = 0x40,
|
||||
ISO14A_NO_SELECT = 0x80,
|
||||
ISO14A_TOPAZMODE = 0x100
|
||||
}
|
||||
|
||||
local ISO14443a_TYPES = {}
|
||||
|
|
|
@ -71,8 +71,8 @@ local Utils =
|
|||
return outResults
|
||||
end,
|
||||
|
||||
------------ CRC-16 ccitt checksums
|
||||
|
||||
------------ CRC-16 ccitt checksums
|
||||
-- Takes a hex string and calculates a crc16
|
||||
Crc16 = function(s)
|
||||
if s == nil then return nil end
|
||||
|
@ -85,7 +85,48 @@ local Utils =
|
|||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ CRC-64 ecma checksums
|
||||
-- Takes a hex string and calculates a crc64 ecma
|
||||
Crc64 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.crc64(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
------------ SHA1 hash
|
||||
-- Takes a string and calculates a SHA1 hash
|
||||
Sha1 = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
--local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.sha1(s)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
-- Takes a hex string and calculates a SHA1 hash
|
||||
Sha1Hex = function(s)
|
||||
if s == nil then return nil end
|
||||
if #s == 0 then return nil end
|
||||
if type(s) == 'string' then
|
||||
local utils = require('utils')
|
||||
local asc = utils.ConvertHexToAscii(s)
|
||||
local hash = core.sha1(asc)
|
||||
return hash
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
|
||||
|
||||
-- input parameter is a string
|
||||
-- Swaps the endianess and returns a number,
|
||||
-- IE: 'cd7a' -> '7acd' -> 0x7acd
|
||||
|
@ -135,7 +176,7 @@ local Utils =
|
|||
while IN>0 do
|
||||
I=I+1
|
||||
IN , D = math.floor(IN/B), math.modf(IN,B)+1
|
||||
OUT=string.sub(K,D,D)..OUT
|
||||
OUT = string.sub(K,D,D)..OUT
|
||||
end
|
||||
return OUT
|
||||
end,
|
||||
|
@ -147,7 +188,7 @@ local Utils =
|
|||
end
|
||||
local s={}
|
||||
for i = 1, #(bytes) do
|
||||
s[i] = string.format("%02X",bytes[i])
|
||||
s[i] = string.format("%02X",bytes[i])
|
||||
end
|
||||
return table.concat(s)
|
||||
end,
|
||||
|
@ -171,16 +212,28 @@ local Utils =
|
|||
end
|
||||
return t
|
||||
end,
|
||||
ConvertAsciiToBytes = function(s)
|
||||
local t={}
|
||||
ConvertAsciiToBytes = function(s, reverse)
|
||||
local t = {}
|
||||
if s == nil then return t end
|
||||
if #s == 0 then return t end
|
||||
|
||||
for k in s:gmatch"(.)" do
|
||||
table.insert(t, string.byte(k))
|
||||
end
|
||||
return t
|
||||
|
||||
if not reverse then
|
||||
return t
|
||||
end
|
||||
|
||||
local rev = {}
|
||||
if reverse then
|
||||
for i = #t, 1,-1 do
|
||||
table.insert(rev, t[i] )
|
||||
end
|
||||
end
|
||||
return rev
|
||||
end,
|
||||
|
||||
ConvertHexToAscii = function(s)
|
||||
local t={}
|
||||
if s == nil then return t end
|
||||
|
@ -191,6 +244,30 @@ local Utils =
|
|||
return table.concat(t)
|
||||
end,
|
||||
|
||||
Chars2num = function(s)
|
||||
return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))
|
||||
end,
|
||||
|
||||
-- use length of string to determine 8,16,32,64 bits
|
||||
bytes_to_int = function(str,endian,signed)
|
||||
local t={str:byte(1,-1)}
|
||||
if endian=="big" then --reverse bytes
|
||||
local tt={}
|
||||
for k=1,#t do
|
||||
tt[#t-k+1]=t[k]
|
||||
end
|
||||
t=tt
|
||||
end
|
||||
local n=0
|
||||
for k=1,#t do
|
||||
n=n+t[k]*2^((k-1)*8)
|
||||
end
|
||||
if signed then
|
||||
n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
|
||||
end
|
||||
return n
|
||||
end,
|
||||
|
||||
-- function convertStringToBytes(str)
|
||||
-- local bytes = {}
|
||||
-- local strLength = string.len(str)
|
||||
|
@ -237,4 +314,4 @@ local Utils =
|
|||
-- end
|
||||
|
||||
}
|
||||
return Utils
|
||||
return Utils
|
||||
|
|
|
@ -69,7 +69,7 @@ void* nested_worker_thread(void *arg)
|
|||
|
||||
int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate)
|
||||
{
|
||||
uint16_t i, len;
|
||||
uint16_t i;
|
||||
uint32_t uid;
|
||||
UsbCommand resp;
|
||||
|
||||
|
@ -77,31 +77,29 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
|
|||
struct Crypto1State *p1, *p2, *p3, *p4;
|
||||
|
||||
// flush queue
|
||||
WaitForResponseTimeout(CMD_ACK,NULL,100);
|
||||
WaitForResponseTimeout(CMD_ACK, NULL, 100);
|
||||
|
||||
UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}};
|
||||
memcpy(c.d.asBytes, key, 6);
|
||||
SendCommand(&c);
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
|
||||
len = resp.arg[1];
|
||||
if (len == 2) {
|
||||
memcpy(&uid, resp.d.asBytes, 4);
|
||||
PrintAndLog("uid:%08x len=%d trgbl=%d trgkey=%x", uid, len, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
statelists[i].blockNo = resp.arg[2] & 0xff;
|
||||
statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
|
||||
statelists[i].uid = uid;
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);
|
||||
memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PrintAndLog("Got 0 keys from proxmark.");
|
||||
return 1;
|
||||
}
|
||||
if (resp.arg[0]) {
|
||||
return resp.arg[0]; // error during nested
|
||||
}
|
||||
|
||||
memcpy(&uid, resp.d.asBytes, 4);
|
||||
PrintAndLog("uid:%08x trgbl=%d trgkey=%x", uid, (uint16_t)resp.arg[2] & 0xff, (uint16_t)resp.arg[2] >> 8);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
statelists[i].blockNo = resp.arg[2] & 0xff;
|
||||
statelists[i].keyType = (resp.arg[2] >> 8) & 0xff;
|
||||
statelists[i].uid = uid;
|
||||
memcpy(&statelists[i].nt, (void *)(resp.d.asBytes + 4 + i * 8 + 0), 4);
|
||||
memcpy(&statelists[i].ks1, (void *)(resp.d.asBytes + 4 + i * 8 + 4), 4);
|
||||
}
|
||||
|
||||
// calc keys
|
||||
|
@ -354,10 +352,7 @@ int loadTraceCard(uint8_t *tuid) {
|
|||
FillFileNameByUID(traceFileName, tuid, ".eml", 7);
|
||||
|
||||
f = fopen(traceFileName, "r");
|
||||
if (!f) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
if (!f) return 1;
|
||||
|
||||
blockNum = 0;
|
||||
|
||||
|
@ -394,10 +389,7 @@ int saveTraceCard(void) {
|
|||
if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0;
|
||||
|
||||
f = fopen(traceFileName, "w+");
|
||||
if ( !f ) {
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
if ( !f ) return 1;
|
||||
|
||||
for (int i = 0; i < 64; i++) { // blocks
|
||||
for (int j = 0; j < 16; j++) // bytes
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include "ui.h"
|
||||
#include "sleep.h"
|
||||
#include "cmdparser.h"
|
||||
#include "cmdmain.h"
|
||||
#include "cmdhw.h"
|
||||
|
||||
// a global mutex to prevent interlaced printing from different threads
|
||||
pthread_mutex_t print_lock;
|
||||
|
@ -105,6 +105,8 @@ static void *main_loop(void *targ) {
|
|||
if (arg->usb_present == 1) {
|
||||
rarg.run = 1;
|
||||
pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
|
||||
// cache Version information now:
|
||||
CmdVersion(NULL);
|
||||
}
|
||||
|
||||
FILE *script_file = NULL;
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "nonce2key/nonce2key.h"
|
||||
#include "../common/iso15693tools.h"
|
||||
#include "../common/crc16.h"
|
||||
#include "../common/crc64.h"
|
||||
#include "../common/sha1.h"
|
||||
#include "aes.h"
|
||||
/**
|
||||
* The following params expected:
|
||||
|
@ -29,34 +31,34 @@
|
|||
*/
|
||||
static int l_SendCommand(lua_State *L){
|
||||
|
||||
/*
|
||||
*
|
||||
The SendCommand (native) expects the following structure:
|
||||
/*
|
||||
*
|
||||
The SendCommand (native) expects the following structure:
|
||||
|
||||
typedef struct {
|
||||
uint64_t cmd; //8 bytes
|
||||
uint64_t arg[3]; // 8*3 bytes = 24 bytes
|
||||
union {
|
||||
uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
|
||||
uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
|
||||
} d;
|
||||
} PACKED UsbCommand;
|
||||
typedef struct {
|
||||
uint64_t cmd; //8 bytes
|
||||
uint64_t arg[3]; // 8*3 bytes = 24 bytes
|
||||
union {
|
||||
uint8_t asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
|
||||
uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
|
||||
} d;
|
||||
} PACKED UsbCommand;
|
||||
|
||||
==> A 544 byte buffer will do.
|
||||
**/
|
||||
//Pop cmd
|
||||
size_t size;
|
||||
const char *data = luaL_checklstring(L, 1, &size);
|
||||
if(size != sizeof(UsbCommand))
|
||||
{
|
||||
printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
|
||||
lua_pushstring(L,"Wrong data size");
|
||||
return 1;
|
||||
}
|
||||
==> A 544 byte buffer will do.
|
||||
**/
|
||||
//Pop cmd
|
||||
size_t size;
|
||||
const char *data = luaL_checklstring(L, 1, &size);
|
||||
if(size != sizeof(UsbCommand))
|
||||
{
|
||||
printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
|
||||
lua_pushstring(L,"Wrong data size");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// UsbCommand c = (*data);
|
||||
SendCommand((UsbCommand* )data);
|
||||
return 0; // no return values
|
||||
SendCommand((UsbCommand* )data);
|
||||
return 0; // no return values
|
||||
}
|
||||
/**
|
||||
* @brief The following params expected:
|
||||
|
@ -67,105 +69,105 @@ static int l_SendCommand(lua_State *L){
|
|||
*/
|
||||
static int l_WaitForResponseTimeout(lua_State *L){
|
||||
|
||||
uint32_t cmd = 0;
|
||||
size_t ms_timeout = -1;
|
||||
uint32_t cmd = 0;
|
||||
size_t ms_timeout = -1;
|
||||
|
||||
//Check number of arguments
|
||||
int n = lua_gettop(L);
|
||||
if(n == 0)
|
||||
{
|
||||
//signal error by returning Nil, errorstring
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L,"You need to supply at least command to wait for");
|
||||
return 2; // two return values
|
||||
}
|
||||
if(n >= 1)
|
||||
{
|
||||
//pop cmd
|
||||
cmd = luaL_checkunsigned(L,1);
|
||||
}
|
||||
if(n >= 2)
|
||||
{
|
||||
//Did the user send a timeout ?
|
||||
//Check if the current top of stack is an integer
|
||||
ms_timeout = luaL_checkunsigned(L,2);
|
||||
//printf("Timeout set to %dms\n" , (int) ms_timeout);
|
||||
}
|
||||
//Check number of arguments
|
||||
int n = lua_gettop(L);
|
||||
if(n == 0)
|
||||
{
|
||||
//signal error by returning Nil, errorstring
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L,"You need to supply at least command to wait for");
|
||||
return 2; // two return values
|
||||
}
|
||||
if(n >= 1)
|
||||
{
|
||||
//pop cmd
|
||||
cmd = luaL_checkunsigned(L,1);
|
||||
}
|
||||
if(n >= 2)
|
||||
{
|
||||
//Did the user send a timeout ?
|
||||
//Check if the current top of stack is an integer
|
||||
ms_timeout = luaL_checkunsigned(L,2);
|
||||
//printf("Timeout set to %dms\n" , (int) ms_timeout);
|
||||
}
|
||||
|
||||
UsbCommand response;
|
||||
UsbCommand response;
|
||||
|
||||
if(WaitForResponseTimeout(cmd, &response, ms_timeout))
|
||||
{
|
||||
//Push it as a string
|
||||
lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
|
||||
if(WaitForResponseTimeout(cmd, &response, ms_timeout))
|
||||
{
|
||||
//Push it as a string
|
||||
lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
|
||||
|
||||
return 1;// return 1 to signal one return value
|
||||
}else{
|
||||
//Push a Nil instead
|
||||
lua_pushnil(L);
|
||||
return 1;// one return value
|
||||
}
|
||||
return 1;// return 1 to signal one return value
|
||||
}else{
|
||||
//Push a Nil instead
|
||||
lua_pushnil(L);
|
||||
return 1;// one return value
|
||||
}
|
||||
}
|
||||
|
||||
static int returnToLuaWithError(lua_State *L, const char* fmt, ...)
|
||||
{
|
||||
char buffer[200];
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt,args);
|
||||
va_end(args);
|
||||
char buffer[200];
|
||||
va_list args;
|
||||
va_start(args,fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt,args);
|
||||
va_end(args);
|
||||
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L,buffer);
|
||||
return 2;
|
||||
lua_pushnil(L);
|
||||
lua_pushstring(L,buffer);
|
||||
return 2;
|
||||
}
|
||||
|
||||
static int l_nonce2key(lua_State *L){
|
||||
|
||||
size_t size;
|
||||
const char *p_uid = luaL_checklstring(L, 1, &size);
|
||||
if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
|
||||
size_t size;
|
||||
const char *p_uid = luaL_checklstring(L, 1, &size);
|
||||
if(size != 4) return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
|
||||
|
||||
const char *p_nt = luaL_checklstring(L, 2, &size);
|
||||
if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
|
||||
const char *p_nt = luaL_checklstring(L, 2, &size);
|
||||
if(size != 4) return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
|
||||
|
||||
const char *p_nr = luaL_checklstring(L, 3, &size);
|
||||
if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
|
||||
const char *p_nr = luaL_checklstring(L, 3, &size);
|
||||
if(size != 4) return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
|
||||
|
||||
const char *p_par_info = luaL_checklstring(L, 4, &size);
|
||||
if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
|
||||
const char *p_par_info = luaL_checklstring(L, 4, &size);
|
||||
if(size != 8) return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
|
||||
|
||||
const char *p_pks_info = luaL_checklstring(L, 5, &size);
|
||||
if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
|
||||
const char *p_pks_info = luaL_checklstring(L, 5, &size);
|
||||
if(size != 8) return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
|
||||
|
||||
|
||||
uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
|
||||
uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
|
||||
uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
|
||||
uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
|
||||
|
||||
uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
|
||||
uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
|
||||
uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
|
||||
uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
|
||||
uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
|
||||
uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
|
||||
|
||||
uint64_t key = 0;
|
||||
uint64_t key = 0;
|
||||
|
||||
int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
|
||||
int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
|
||||
|
||||
//Push the retval on the stack
|
||||
lua_pushinteger(L,retval);
|
||||
|
||||
//Push the key onto the stack
|
||||
uint8_t dest_key[8];
|
||||
num_to_bytes(key,sizeof(dest_key),dest_key);
|
||||
//Push the retval on the stack
|
||||
lua_pushinteger(L,retval);
|
||||
|
||||
//printf("Pushing to lua stack: %012"llx"\n",key);
|
||||
lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
|
||||
//Push the key onto the stack
|
||||
uint8_t dest_key[8];
|
||||
num_to_bytes(key,sizeof(dest_key),dest_key);
|
||||
|
||||
return 2; //Two return values
|
||||
//printf("Pushing to lua stack: %012"llx"\n",key);
|
||||
lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
|
||||
|
||||
return 2; //Two return values
|
||||
}
|
||||
//static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));}
|
||||
static int l_clearCommandBuffer(lua_State *L){
|
||||
clearCommandBuffer();
|
||||
return 0;
|
||||
clearCommandBuffer();
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* @brief l_foobar is a dummy function to test lua-integration with
|
||||
|
@ -174,23 +176,23 @@ static int l_clearCommandBuffer(lua_State *L){
|
|||
*/
|
||||
static int l_foobar(lua_State *L)
|
||||
{
|
||||
//Check number of arguments
|
||||
int n = lua_gettop(L);
|
||||
printf("foobar called with %d arguments" , n);
|
||||
lua_settop(L, 0);
|
||||
printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
|
||||
|
||||
// todo: this is not used, where was it intended for?
|
||||
// UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}};
|
||||
|
||||
printf("Now returning a uint64_t as a string");
|
||||
uint64_t x = 0xDEADBEEF;
|
||||
uint8_t destination[8];
|
||||
num_to_bytes(x,sizeof(x),destination);
|
||||
lua_pushlstring(L,(const char *)&x,sizeof(x));
|
||||
lua_pushlstring(L,(const char *)destination,sizeof(destination));
|
||||
//Check number of arguments
|
||||
int n = lua_gettop(L);
|
||||
printf("foobar called with %d arguments" , n);
|
||||
lua_settop(L, 0);
|
||||
printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
|
||||
|
||||
return 2;
|
||||
// todo: this is not used, where was it intended for?
|
||||
// UsbCommand response = {CMD_MIFARE_READBL, {1337, 1338, 1339}};
|
||||
|
||||
printf("Now returning a uint64_t as a string");
|
||||
uint64_t x = 0xDEADBEEF;
|
||||
uint8_t destination[8];
|
||||
num_to_bytes(x,sizeof(x),destination);
|
||||
lua_pushlstring(L,(const char *)&x,sizeof(x));
|
||||
lua_pushlstring(L,(const char *)destination,sizeof(destination));
|
||||
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,8 +203,8 @@ static int l_foobar(lua_State *L)
|
|||
*/
|
||||
static int l_ukbhit(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L,ukbhit() ? true : false);
|
||||
return 1;
|
||||
lua_pushboolean(L,ukbhit() ? true : false);
|
||||
return 1;
|
||||
}
|
||||
/**
|
||||
* @brief Calls the command line parser to deal with the command. This enables
|
||||
|
@ -212,58 +214,134 @@ static int l_ukbhit(lua_State *L)
|
|||
*/
|
||||
static int l_CmdConsole(lua_State *L)
|
||||
{
|
||||
CommandReceived((char *)luaL_checkstring(L, 1));
|
||||
return 0;
|
||||
CommandReceived((char *)luaL_checkstring(L, 1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_iso15693_crc(lua_State *L)
|
||||
{
|
||||
// uint16_t Iso15693Crc(uint8_t *v, int n);
|
||||
size_t size;
|
||||
const char *v = luaL_checklstring(L, 1, &size);
|
||||
uint16_t retval = Iso15693Crc((uint8_t *) v, size);
|
||||
lua_pushinteger(L, (int) retval);
|
||||
return 1;
|
||||
// uint16_t Iso15693Crc(uint8_t *v, int n);
|
||||
size_t size;
|
||||
const char *v = luaL_checklstring(L, 1, &size);
|
||||
uint16_t retval = Iso15693Crc((uint8_t *) v, size);
|
||||
lua_pushinteger(L, (int) retval);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Simple AES 128 cbc hook up to OpenSSL.
|
||||
params: key, input
|
||||
*/
|
||||
static int l_aes(lua_State *L)
|
||||
static int l_aes128decrypt_cbc(lua_State *L)
|
||||
{
|
||||
//Check number of arguments
|
||||
int i;
|
||||
size_t size;
|
||||
const char *p_key = luaL_checklstring(L, 1, &size);
|
||||
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
|
||||
size_t size;
|
||||
const char *p_key = luaL_checklstring(L, 1, &size);
|
||||
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
|
||||
|
||||
const char *p_encTxt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
const char *p_encTxt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
unsigned char indata[16] = {0x00};
|
||||
unsigned char outdata[16] = {0x00};
|
||||
unsigned char aes_key[16] = {0x00};
|
||||
unsigned char aes_key[16] = {0x00};
|
||||
unsigned char iv[16] = {0x00};
|
||||
|
||||
// convert key to bytearray
|
||||
|
||||
// convert key to bytearray and convert input to bytearray
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
|
||||
}
|
||||
|
||||
// convert input to bytearray
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
|
||||
}
|
||||
|
||||
//AES_KEY key;
|
||||
//AES_set_decrypt_key(aes_key, 128, &key);
|
||||
//AES_cbc_encrypt(indata, outdata, sizeof(indata), &key, iv, AES_DECRYPT);
|
||||
|
||||
aes_context ctx;
|
||||
aes_init(&ctx);
|
||||
aes_setkey_enc(&ctx,(const unsigned char *)p_key,128);
|
||||
aes_context ctx;
|
||||
aes_init(&ctx);
|
||||
aes_setkey_dec(&ctx, aes_key, 128);
|
||||
aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata );
|
||||
//Push decrypted array as a string
|
||||
//Push decrypted array as a string
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;// return 1 to signal one return value
|
||||
}
|
||||
static int l_aes128decrypt_ecb(lua_State *L)
|
||||
{
|
||||
//Check number of arguments
|
||||
int i;
|
||||
size_t size;
|
||||
const char *p_key = luaL_checklstring(L, 1, &size);
|
||||
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
|
||||
|
||||
const char *p_encTxt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
unsigned char indata[16] = {0x00};
|
||||
unsigned char outdata[16] = {0x00};
|
||||
unsigned char aes_key[16] = {0x00};
|
||||
|
||||
// convert key to bytearray and convert input to bytearray
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
|
||||
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
|
||||
}
|
||||
aes_context ctx;
|
||||
aes_init(&ctx);
|
||||
aes_setkey_dec(&ctx, aes_key, 128);
|
||||
aes_crypt_ecb(&ctx, AES_DECRYPT, indata, outdata );
|
||||
|
||||
//Push decrypted array as a string
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;// return 1 to signal one return value
|
||||
}
|
||||
|
||||
static int l_aes128encrypt_cbc(lua_State *L)
|
||||
{
|
||||
//Check number of arguments
|
||||
int i;
|
||||
size_t size;
|
||||
const char *p_key = luaL_checklstring(L, 1, &size);
|
||||
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
|
||||
|
||||
const char *p_txt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
unsigned char indata[16] = {0x00};
|
||||
unsigned char outdata[16] = {0x00};
|
||||
unsigned char aes_key[16] = {0x00};
|
||||
unsigned char iv[16] = {0x00};
|
||||
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]);
|
||||
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
|
||||
}
|
||||
|
||||
aes_context ctx;
|
||||
aes_init(&ctx);
|
||||
aes_setkey_enc(&ctx, aes_key, 128);
|
||||
aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata );
|
||||
//Push encrypted array as a string
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;// return 1 to signal one return value
|
||||
}
|
||||
|
||||
static int l_aes128encrypt_ecb(lua_State *L)
|
||||
{
|
||||
//Check number of arguments
|
||||
int i;
|
||||
size_t size;
|
||||
const char *p_key = luaL_checklstring(L, 1, &size);
|
||||
if(size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
|
||||
|
||||
const char *p_txt = luaL_checklstring(L, 2, &size);
|
||||
|
||||
unsigned char indata[16] = {0x00};
|
||||
unsigned char outdata[16] = {0x00};
|
||||
unsigned char aes_key[16] = {0x00};
|
||||
|
||||
for (i = 0; i < 32; i += 2) {
|
||||
sscanf(&p_txt[i], "%02x", (unsigned int *)&indata[i / 2]);
|
||||
sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
|
||||
}
|
||||
aes_context ctx;
|
||||
aes_init(&ctx);
|
||||
aes_setkey_enc(&ctx, aes_key, 128);
|
||||
aes_crypt_ecb(&ctx, AES_ENCRYPT, indata, outdata );
|
||||
//Push encrypted array as a string
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;// return 1 to signal one return value
|
||||
}
|
||||
|
@ -272,10 +350,42 @@ static int l_crc16(lua_State *L)
|
|||
{
|
||||
size_t size;
|
||||
const char *p_str = luaL_checklstring(L, 1, &size);
|
||||
|
||||
|
||||
uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size);
|
||||
lua_pushinteger(L, (int) retval);
|
||||
return 1;
|
||||
lua_pushinteger(L, (int) retval);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_crc64(lua_State *L)
|
||||
{
|
||||
size_t size;
|
||||
uint64_t crc = 0;
|
||||
unsigned char outdata[8] = {0x00};
|
||||
|
||||
const char *p_str = luaL_checklstring(L, 1, &size);
|
||||
|
||||
crc64( (uint8_t*) p_str, size, &crc);
|
||||
|
||||
outdata[0] = (uint8_t)(crc >> 56) & 0xff;
|
||||
outdata[1] = (uint8_t)(crc >> 48) & 0xff;
|
||||
outdata[2] = (uint8_t)(crc >> 40) & 0xff;
|
||||
outdata[3] = (uint8_t)(crc >> 32) & 0xff;
|
||||
outdata[4] = (uint8_t)(crc >> 24) & 0xff;
|
||||
outdata[5] = (uint8_t)(crc >> 16) & 0xff;
|
||||
outdata[6] = (uint8_t)(crc >> 8) & 0xff;
|
||||
outdata[7] = crc & 0xff;
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_sha1(lua_State *L)
|
||||
{
|
||||
size_t size;
|
||||
const char *p_str = luaL_checklstring(L, 1, &size);
|
||||
unsigned char outdata[20] = {0x00};
|
||||
sha1( (uint8_t*) p_str, size, outdata);
|
||||
lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -288,57 +398,63 @@ static int l_crc16(lua_State *L)
|
|||
*/
|
||||
int setLuaPath( lua_State* L, const char* path )
|
||||
{
|
||||
lua_getglobal( L, "package" );
|
||||
lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
|
||||
const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
|
||||
int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
|
||||
char * buf = malloc(requiredLength);
|
||||
snprintf(buf, requiredLength, "%s;%s", cur_path, path);
|
||||
lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
|
||||
lua_pushstring( L, buf ); // push the new one
|
||||
lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
|
||||
lua_pop( L, 1 ); // get rid of package table from top of stack
|
||||
return 0; // all done!
|
||||
lua_getglobal( L, "package" );
|
||||
lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
|
||||
const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
|
||||
int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
|
||||
char * buf = malloc(requiredLength);
|
||||
snprintf(buf, requiredLength, "%s;%s", cur_path, path);
|
||||
lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
|
||||
lua_pushstring( L, buf ); // push the new one
|
||||
lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
|
||||
lua_pop( L, 1 ); // get rid of package table from top of stack
|
||||
free(buf);
|
||||
return 0; // all done!
|
||||
}
|
||||
|
||||
|
||||
int set_pm3_libraries(lua_State *L)
|
||||
{
|
||||
|
||||
static const luaL_Reg libs[] = {
|
||||
{"SendCommand", l_SendCommand},
|
||||
{"WaitForResponseTimeout", l_WaitForResponseTimeout},
|
||||
{"nonce2key", l_nonce2key},
|
||||
//{"PrintAndLog", l_PrintAndLog},
|
||||
{"foobar", l_foobar},
|
||||
{"ukbhit", l_ukbhit},
|
||||
{"clearCommandBuffer", l_clearCommandBuffer},
|
||||
{"console", l_CmdConsole},
|
||||
{"iso15693_crc", l_iso15693_crc},
|
||||
{"aes", l_aes},
|
||||
static const luaL_Reg libs[] = {
|
||||
{"SendCommand", l_SendCommand},
|
||||
{"WaitForResponseTimeout", l_WaitForResponseTimeout},
|
||||
{"nonce2key", l_nonce2key},
|
||||
//{"PrintAndLog", l_PrintAndLog},
|
||||
{"foobar", l_foobar},
|
||||
{"ukbhit", l_ukbhit},
|
||||
{"clearCommandBuffer", l_clearCommandBuffer},
|
||||
{"console", l_CmdConsole},
|
||||
{"iso15693_crc", l_iso15693_crc},
|
||||
{"aes128_decrypt", l_aes128decrypt_cbc},
|
||||
{"aes128_decrypt_ecb", l_aes128decrypt_ecb},
|
||||
{"aes128_encrypt", l_aes128encrypt_cbc},
|
||||
{"aes128_encrypt_ecb", l_aes128encrypt_ecb},
|
||||
{"crc16", l_crc16},
|
||||
{NULL, NULL}
|
||||
};
|
||||
{"crc64", l_crc64},
|
||||
{"sha1", l_sha1},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
lua_pushglobaltable(L);
|
||||
// Core library is in this table. Contains '
|
||||
//this is 'pm3' table
|
||||
lua_newtable(L);
|
||||
lua_pushglobaltable(L);
|
||||
// Core library is in this table. Contains '
|
||||
//this is 'pm3' table
|
||||
lua_newtable(L);
|
||||
|
||||
//Put the function into the hash table.
|
||||
for (int i = 0; libs[i].name; i++) {
|
||||
lua_pushcfunction(L, libs[i].func);
|
||||
lua_setfield(L, -2, libs[i].name);//set the name, pop stack
|
||||
}
|
||||
//Name of 'core'
|
||||
lua_setfield(L, -2, "core");
|
||||
//Put the function into the hash table.
|
||||
for (int i = 0; libs[i].name; i++) {
|
||||
lua_pushcfunction(L, libs[i].func);
|
||||
lua_setfield(L, -2, libs[i].name);//set the name, pop stack
|
||||
}
|
||||
//Name of 'core'
|
||||
lua_setfield(L, -2, "core");
|
||||
|
||||
//-- remove the global environment table from the stack
|
||||
lua_pop(L, 1);
|
||||
//-- remove the global environment table from the stack
|
||||
lua_pop(L, 1);
|
||||
|
||||
//-- Last but not least, add to the LUA_PATH (package.path in lua)
|
||||
// so we can load libraries from the ./lualib/ - directory
|
||||
setLuaPath(L,"./lualibs/?.lua");
|
||||
//-- Last but not least, add to the LUA_PATH (package.path in lua)
|
||||
// so we can load libraries from the ./lualib/ - directory
|
||||
setLuaPath(L,"./lualibs/?.lua");
|
||||
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
|
473
client/scripts/didump.lua
Normal file
473
client/scripts/didump.lua
Normal file
|
@ -0,0 +1,473 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local utils = require('utils')
|
||||
local lib14a = require('read14a')
|
||||
|
||||
example =[[
|
||||
script run didump
|
||||
script run didump -k aabbccddeeff
|
||||
]]
|
||||
author = "Iceman"
|
||||
usage = "script run didump -k <key> "
|
||||
desc = [[
|
||||
This is a script to dump and decrypt the data of a specific type of Mifare Mini token.
|
||||
|
||||
Arguments:
|
||||
-h : this help
|
||||
-k <key> : Mifare Key A.
|
||||
]]
|
||||
|
||||
local band=bit32.band
|
||||
local bor=bit32.bor
|
||||
local bnot=bit32.bnot
|
||||
local bxor=bit32.bxor
|
||||
local lshift=bit32.lshift
|
||||
local rshift=bit32.rshift
|
||||
|
||||
local FOO = 'AF62D2EC0491968CC52A1A7165F865FE'
|
||||
local BAR = '286329204469736E65792032303133'
|
||||
local RANDOM = FOO..BAR
|
||||
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
|
||||
local TIMEOUT = 2000
|
||||
local DEBUG = false
|
||||
local numBlocks = 20
|
||||
local numSectors = 5
|
||||
local CHECKSUM_OFFSET = 12; -- +1???
|
||||
---
|
||||
-- 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)
|
||||
core.clearCommandBuffer()
|
||||
end
|
||||
---
|
||||
-- Usage help
|
||||
function help()
|
||||
print(desc)
|
||||
print("Example usage")
|
||||
print(example)
|
||||
end
|
||||
---
|
||||
-- Get checksum,
|
||||
-- called: data is string (32 hex digits)
|
||||
-- returns: number
|
||||
local function getChecksum(data)
|
||||
local chksum = data:sub(25,32)
|
||||
return tonumber(chksum,16)
|
||||
end
|
||||
---
|
||||
-- calculate checksum
|
||||
-- called: data is bytes (24 hex digits)
|
||||
-- returns: number
|
||||
local function calculateChecksum(data)
|
||||
|
||||
-- Generate table
|
||||
local _tbl = {}
|
||||
_tbl[0] = { 0x0 }
|
||||
_tbl[1] = { 0x77073096 }
|
||||
_tbl[2] = { 0xEE0E612C }
|
||||
_tbl[3] = { 0x990951BA }
|
||||
_tbl[4] = { 0x76DC419 }
|
||||
_tbl[5] = { 0x706AF48F }
|
||||
_tbl[6] = { 0xE963A535 }
|
||||
_tbl[7] = { 0x9E6495A3 }
|
||||
_tbl[8] = { 0xEDB8832 }
|
||||
_tbl[9] = { 0x79DCB8A4 }
|
||||
_tbl[10] = { 0xE0D5E91E }
|
||||
_tbl[11] = { 0x97D2D988 }
|
||||
_tbl[12] = { 0x9B64C2B }
|
||||
_tbl[13] = { 0x7EB17CBD }
|
||||
_tbl[14] = { 0xE7B82D07 }
|
||||
_tbl[15] = { 0x90BF1D91 }
|
||||
_tbl[16] = { 0x1DB71064 }
|
||||
_tbl[17] = { 0x6AB020F2 }
|
||||
_tbl[18] = { 0xF3B97148 }
|
||||
_tbl[19] = { 0x84BE41DE }
|
||||
_tbl[20] = { 0x1ADAD47D }
|
||||
_tbl[21] = { 0x6DDDE4EB }
|
||||
_tbl[22] = { 0xF4D4B551 }
|
||||
_tbl[23] = { 0x83D385C7 }
|
||||
_tbl[24] = { 0x136C9856 }
|
||||
_tbl[25] = { 0x646BA8C0 }
|
||||
_tbl[26] = { 0xFD62F97A }
|
||||
_tbl[27] = { 0x8A65C9EC }
|
||||
_tbl[28] = { 0x14015C4F }
|
||||
_tbl[29] = { 0x63066CD9 }
|
||||
_tbl[30] = { 0xFA0F3D63 }
|
||||
_tbl[31] = { 0x8D080DF5 }
|
||||
_tbl[32] = { 0x3B6E20C8 }
|
||||
_tbl[33] = { 0x4C69105E }
|
||||
_tbl[34] = { 0xD56041E4 }
|
||||
_tbl[35] = { 0xA2677172 }
|
||||
_tbl[36] = { 0x3C03E4D1 }
|
||||
_tbl[37] = { 0x4B04D447 }
|
||||
_tbl[38] = { 0xD20D85FD }
|
||||
_tbl[39] = { 0xA50AB56B }
|
||||
_tbl[40] = { 0x35B5A8FA }
|
||||
_tbl[41] = { 0x42B2986C }
|
||||
_tbl[42] = { 0xDBBBC9D6 }
|
||||
_tbl[43] = { 0xACBCF940 }
|
||||
_tbl[44] = { 0x32D86CE3 }
|
||||
_tbl[45] = { 0x45DF5C75 }
|
||||
_tbl[46] = { 0xDCD60DCF }
|
||||
_tbl[47] = { 0xABD13D59 }
|
||||
_tbl[48] = { 0x26D930AC }
|
||||
_tbl[49] = { 0x51DE003A }
|
||||
_tbl[50] = { 0xC8D75180 }
|
||||
_tbl[51] = { 0xBFD06116 }
|
||||
_tbl[52] = { 0x21B4F4B5 }
|
||||
_tbl[53] = { 0x56B3C423 }
|
||||
_tbl[54] = { 0xCFBA9599 }
|
||||
_tbl[55] = { 0xB8BDA50F }
|
||||
_tbl[56] = { 0x2802B89E }
|
||||
_tbl[57] = { 0x5F058808 }
|
||||
_tbl[58] = { 0xC60CD9B2 }
|
||||
_tbl[59] = { 0xB10BE924 }
|
||||
_tbl[60] = { 0x2F6F7C87 }
|
||||
_tbl[61] = { 0x58684C11 }
|
||||
_tbl[62] = { 0xC1611DAB }
|
||||
_tbl[63] = { 0xB6662D3D }
|
||||
_tbl[64] = { 0x76DC4190 }
|
||||
_tbl[65] = { 0x1DB7106 }
|
||||
_tbl[66] = { 0x98D220BC }
|
||||
_tbl[67] = { 0xEFD5102A }
|
||||
_tbl[68] = { 0x71B18589 }
|
||||
_tbl[69] = { 0x6B6B51F }
|
||||
_tbl[70] = { 0x9FBFE4A5 }
|
||||
_tbl[71] = { 0xE8B8D433 }
|
||||
_tbl[72] = { 0x7807C9A2 }
|
||||
_tbl[73] = { 0xF00F934 }
|
||||
_tbl[74] = { 0x9609A88E }
|
||||
_tbl[75] = { 0xE10E9818 }
|
||||
_tbl[76] = { 0x7F6A0DBB }
|
||||
_tbl[77] = { 0x86D3D2D }
|
||||
_tbl[78] = { 0x91646C97 }
|
||||
_tbl[79] = { 0xE6635C01 }
|
||||
_tbl[80] = { 0x6B6B51F4 }
|
||||
_tbl[81] = { 0x1C6C6162 }
|
||||
_tbl[82] = { 0x856530D8 }
|
||||
_tbl[83] = { 0xF262004E }
|
||||
_tbl[84] = { 0x6C0695ED }
|
||||
_tbl[85] = { 0x1B01A57B }
|
||||
_tbl[86] = { 0x8208F4C1 }
|
||||
_tbl[87] = { 0xF50FC457 }
|
||||
_tbl[88] = { 0x65B0D9C6 }
|
||||
_tbl[89] = { 0x12B7E950 }
|
||||
_tbl[90] = { 0x8BBEB8EA }
|
||||
_tbl[91] = { 0xFCB9887C }
|
||||
_tbl[92] = { 0x62DD1DDF }
|
||||
_tbl[93] = { 0x15DA2D49 }
|
||||
_tbl[94] = { 0x8CD37CF3 }
|
||||
_tbl[95] = { 0xFBD44C65 }
|
||||
_tbl[96] = { 0x4DB26158 }
|
||||
_tbl[97] = { 0x3AB551CE }
|
||||
_tbl[98] = { 0xA3BC0074 }
|
||||
_tbl[99] = { 0xD4BB30E2 }
|
||||
_tbl[100] = { 0x4ADFA541 }
|
||||
_tbl[101] = { 0x3DD895D7 }
|
||||
_tbl[102] = { 0xA4D1C46D }
|
||||
_tbl[103] = { 0xD3D6F4FB }
|
||||
_tbl[104] = { 0x4369E96A }
|
||||
_tbl[105] = { 0x346ED9FC }
|
||||
_tbl[106] = { 0xAD678846 }
|
||||
_tbl[107] = { 0xDA60B8D0 }
|
||||
_tbl[108] = { 0x44042D73 }
|
||||
_tbl[109] = { 0x33031DE5 }
|
||||
_tbl[110] = { 0xAA0A4C5F }
|
||||
_tbl[111] = { 0xDD0D7CC9 }
|
||||
_tbl[112] = { 0x5005713C }
|
||||
_tbl[113] = { 0x270241AA }
|
||||
_tbl[114] = { 0xBE0B1010 }
|
||||
_tbl[115] = { 0xC90C2086 }
|
||||
_tbl[116] = { 0x5768B525 }
|
||||
_tbl[117] = { 0x206F85B3 }
|
||||
_tbl[118] = { 0xB966D409 }
|
||||
_tbl[119] = { 0xCE61E49F }
|
||||
_tbl[120] = { 0x5EDEF90E }
|
||||
_tbl[121] = { 0x29D9C998 }
|
||||
_tbl[122] = { 0xB0D09822 }
|
||||
_tbl[123] = { 0xC7D7A8B4 }
|
||||
_tbl[124] = { 0x59B33D17 }
|
||||
_tbl[125] = { 0x2EB40D81 }
|
||||
_tbl[126] = { 0xB7BD5C3B }
|
||||
_tbl[127] = { 0xC0BA6CAD }
|
||||
_tbl[128] = { 0xEDB88320 }
|
||||
_tbl[129] = { 0x9ABFB3B6 }
|
||||
_tbl[130] = { 0x3B6E20C }
|
||||
_tbl[131] = { 0x74B1D29A }
|
||||
_tbl[132] = { 0xEAD54739 }
|
||||
_tbl[133] = { 0x9DD277AF }
|
||||
_tbl[134] = { 0x4DB2615 }
|
||||
_tbl[135] = { 0x73DC1683 }
|
||||
_tbl[136] = { 0xE3630B12 }
|
||||
_tbl[137] = { 0x94643B84 }
|
||||
_tbl[138] = { 0xD6D6A3E }
|
||||
_tbl[139] = { 0x7A6A5AA8 }
|
||||
_tbl[140] = { 0xE40ECF0B }
|
||||
_tbl[141] = { 0x9309FF9D }
|
||||
_tbl[142] = { 0xA00AE27 }
|
||||
_tbl[143] = { 0x7D079EB1 }
|
||||
_tbl[144] = { 0xF00F9344 }
|
||||
_tbl[145] = { 0x8708A3D2 }
|
||||
_tbl[146] = { 0x1E01F268 }
|
||||
_tbl[147] = { 0x6906C2FE }
|
||||
_tbl[148] = { 0xF762575D }
|
||||
_tbl[149] = { 0x806567CB }
|
||||
_tbl[150] = { 0x196C3671 }
|
||||
_tbl[151] = { 0x6E6B06E7 }
|
||||
_tbl[152] = { 0xFED41B76 }
|
||||
_tbl[153] = { 0x89D32BE0 }
|
||||
_tbl[154] = { 0x10DA7A5A }
|
||||
_tbl[155] = { 0x67DD4ACC }
|
||||
_tbl[156] = { 0xF9B9DF6F }
|
||||
_tbl[157] = { 0x8EBEEFF9 }
|
||||
_tbl[158] = { 0x17B7BE43 }
|
||||
_tbl[159] = { 0x60B08ED5 }
|
||||
_tbl[160] = { 0xD6D6A3E8 }
|
||||
_tbl[161] = { 0xA1D1937E }
|
||||
_tbl[162] = { 0x38D8C2C4 }
|
||||
_tbl[163] = { 0x4FDFF252 }
|
||||
_tbl[164] = { 0xD1BB67F1 }
|
||||
_tbl[165] = { 0xA6BC5767 }
|
||||
_tbl[166] = { 0x3FB506DD }
|
||||
_tbl[167] = { 0x48B2364B }
|
||||
_tbl[168] = { 0xD80D2BDA }
|
||||
_tbl[169] = { 0xAF0A1B4C }
|
||||
_tbl[170] = { 0x36034AF6 }
|
||||
_tbl[171] = { 0x41047A60 }
|
||||
_tbl[172] = { 0xDF60EFC3 }
|
||||
_tbl[173] = { 0xA867DF55 }
|
||||
_tbl[174] = { 0x316E8EEF }
|
||||
_tbl[175] = { 0x4669BE79 }
|
||||
_tbl[176] = { 0xCB61B38C }
|
||||
_tbl[177] = { 0xBC66831A }
|
||||
_tbl[178] = { 0x256FD2A0 }
|
||||
_tbl[179] = { 0x5268E236 }
|
||||
_tbl[180] = { 0xCC0C7795 }
|
||||
_tbl[181] = { 0xBB0B4703 }
|
||||
_tbl[182] = { 0x220216B9 }
|
||||
_tbl[183] = { 0x5505262F }
|
||||
_tbl[184] = { 0xC5BA3BBE }
|
||||
_tbl[185] = { 0xB2BD0B28 }
|
||||
_tbl[186] = { 0x2BB45A92 }
|
||||
_tbl[187] = { 0x5CB36A04 }
|
||||
_tbl[188] = { 0xC2D7FFA7 }
|
||||
_tbl[189] = { 0xB5D0CF31 }
|
||||
_tbl[190] = { 0x2CD99E8B }
|
||||
_tbl[191] = { 0x5BDEAE1D }
|
||||
_tbl[192] = { 0x9B64C2B0 }
|
||||
_tbl[193] = { 0xEC63F226 }
|
||||
_tbl[194] = { 0x756AA39C }
|
||||
_tbl[195] = { 0x26D930A }
|
||||
_tbl[196] = { 0x9C0906A9 }
|
||||
_tbl[197] = { 0xEB0E363F }
|
||||
_tbl[198] = { 0x72076785 }
|
||||
_tbl[199] = { 0x5005713 }
|
||||
_tbl[200] = { 0x95BF4A82 }
|
||||
_tbl[201] = { 0xE2B87A14 }
|
||||
_tbl[202] = { 0x7BB12BAE }
|
||||
_tbl[203] = { 0xCB61B38 }
|
||||
_tbl[204] = { 0x92D28E9B }
|
||||
_tbl[205] = { 0xE5D5BE0D }
|
||||
_tbl[206] = { 0x7CDCEFB7 }
|
||||
_tbl[207] = { 0xBDBDF21 }
|
||||
_tbl[208] = { 0x86D3D2D4 }
|
||||
_tbl[209] = { 0xF1D4E242 }
|
||||
_tbl[210] = { 0x68DDB3F8 }
|
||||
_tbl[211] = { 0x1FDA836E }
|
||||
_tbl[212] = { 0x81BE16CD }
|
||||
_tbl[213] = { 0xF6B9265B }
|
||||
_tbl[214] = { 0x6FB077E1 }
|
||||
_tbl[215] = { 0x18B74777 }
|
||||
_tbl[216] = { 0x88085AE6 }
|
||||
_tbl[217] = { 0xFF0F6A70 }
|
||||
_tbl[218] = { 0x66063BCA }
|
||||
_tbl[219] = { 0x11010B5C }
|
||||
_tbl[220] = { 0x8F659EFF }
|
||||
_tbl[221] = { 0xF862AE69 }
|
||||
_tbl[222] = { 0x616BFFD3 }
|
||||
_tbl[223] = { 0x166CCF45 }
|
||||
_tbl[224] = { 0xA00AE278 }
|
||||
_tbl[225] = { 0xD70DD2EE }
|
||||
_tbl[226] = { 0x4E048354 }
|
||||
_tbl[227] = { 0x3903B3C2 }
|
||||
_tbl[228] = { 0xA7672661 }
|
||||
_tbl[229] = { 0xD06016F7 }
|
||||
_tbl[230] = { 0x4969474D }
|
||||
_tbl[231] = { 0x3E6E77DB }
|
||||
_tbl[232] = { 0xAED16A4A }
|
||||
_tbl[233] = { 0xD9D65ADC }
|
||||
_tbl[234] = { 0x40DF0B66 }
|
||||
_tbl[235] = { 0x37D83BF0 }
|
||||
_tbl[236] = { 0xA9BCAE53 }
|
||||
_tbl[237] = { 0xDEBB9EC5 }
|
||||
_tbl[238] = { 0x47B2CF7F }
|
||||
_tbl[239] = { 0x30B5FFE9 }
|
||||
_tbl[240] = { 0xBDBDF21C }
|
||||
_tbl[241] = { 0xCABAC28A }
|
||||
_tbl[242] = { 0x53B39330 }
|
||||
_tbl[243] = { 0x24B4A3A6 }
|
||||
_tbl[244] = { 0xBAD03605 }
|
||||
_tbl[245] = { 0xCDD70693 }
|
||||
_tbl[246] = { 0x54DE5729 }
|
||||
_tbl[247] = { 0x23D967BF }
|
||||
_tbl[248] = { 0xB3667A2E }
|
||||
_tbl[249] = { 0xC4614AB8 }
|
||||
_tbl[250] = { 0x5D681B02 }
|
||||
_tbl[251] = { 0x2A6F2B94 }
|
||||
_tbl[252] = { 0xB40BBE37 }
|
||||
_tbl[253] = { 0xC30C8EA1 }
|
||||
_tbl[254] = { 0x5A05DF1B }
|
||||
_tbl[255] = { 0x2D02EF8D }
|
||||
|
||||
|
||||
-- Calculate it
|
||||
local ret = 0
|
||||
for i,item in pairs(data) do
|
||||
local tmp = band(ret, 0xFF)
|
||||
local index = band( bxor(tmp, item), 0xFF)
|
||||
ret = bxor(rshift(ret,8), _tbl[index][1])
|
||||
end
|
||||
return ret
|
||||
end
|
||||
---
|
||||
-- update checksum
|
||||
-- called: data is string, ( >= 24 hex digits )
|
||||
-- returns: string, (data concat new checksum)
|
||||
local function updateChecksum(data)
|
||||
local part = data:sub(1,24)
|
||||
local chksum = calculateChecksum( utils.ConvertHexToBytes(part))
|
||||
return string.format("%s%X", part, chksum)
|
||||
end
|
||||
---
|
||||
-- receives the answer from deviceside, used with a readblock command
|
||||
local function waitCmd()
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
if response then
|
||||
local count,cmd,arg0 = bin.unpack('LL',response)
|
||||
if(arg0==1) then
|
||||
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
||||
return data:sub(1,32)
|
||||
else
|
||||
return nil, "Couldn't read block.."
|
||||
end
|
||||
end
|
||||
return nil, "No response from device"
|
||||
end
|
||||
|
||||
local function selftest()
|
||||
local testdata = '000F42430D0A14000001D11F'..'5D738517'
|
||||
local chksum = getChecksum(testdata)
|
||||
local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24)))
|
||||
print ('TESTDATA :: '..testdata)
|
||||
print ('DATA :: '..testdata:sub(1,24))
|
||||
print (('CHKSUM :: %X'):format(chksum))
|
||||
print (('CHKSUM CALC :: %X'):format(calc))
|
||||
print ('UPDATE CHKSUM :: '..updateChecksum(testdata))
|
||||
|
||||
|
||||
end
|
||||
---
|
||||
-- The main entry point
|
||||
-- -d decrypt
|
||||
-- -e encrypt
|
||||
-- -v validate
|
||||
function main(args)
|
||||
|
||||
local cmd, result, err, blockNo, keyA
|
||||
local blocks = {}
|
||||
local decryptkey = ''
|
||||
|
||||
-- Read the parameters
|
||||
for o, a in getopt.getopt(args, 'hk:') do
|
||||
if o == "h" then help() return end
|
||||
if o == "k" then keyA = a end
|
||||
end
|
||||
|
||||
selftest()
|
||||
|
||||
local tst2 = '00100100030209094312356432324E34B79A349B'
|
||||
|
||||
-- validate input args.
|
||||
keyA = keyA or '6dd747e86975'
|
||||
if #(keyA) ~= 12 then
|
||||
return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA))
|
||||
end
|
||||
|
||||
-- Turn off Debug
|
||||
local cmdSetDbgOff = "hf mf dbg 0"
|
||||
core.console( cmdSetDbgOff)
|
||||
|
||||
-- GET TAG UID
|
||||
|
||||
result, err = lib14a.read1443a(false)
|
||||
if not result then
|
||||
return oops(err)
|
||||
end
|
||||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
print(result.uid, keyA)
|
||||
|
||||
local my = result.uid
|
||||
if 1 == 1 then
|
||||
return
|
||||
end
|
||||
|
||||
-- Show tag info
|
||||
print((' Found tag %s'):format(result.name))
|
||||
|
||||
local longrandom = RANDOM..result.uid
|
||||
local res = utils.Sha1Hex(longrandom)
|
||||
res = utils.ConvertBytesToHex(utils.ConvertAsciiToBytes(res:sub(1,16)))
|
||||
decryptkey = utils.SwapEndiannessStr(res:sub(1,8) , 32)
|
||||
decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(9,16),32)
|
||||
decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(17,24),32)
|
||||
decryptkey = decryptkey..utils.SwapEndiannessStr( res:sub(25,32),32)
|
||||
print('Decrypt key::',decryptkey)
|
||||
print('Reading card data')
|
||||
print('Raw','Decrypted')
|
||||
for blockNo = 0, numBlocks-1, 1 do
|
||||
|
||||
if core.ukbhit() then
|
||||
print("aborted by user")
|
||||
break
|
||||
end
|
||||
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = keyA}
|
||||
local err = core.SendCommand(cmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local blockdata, err = waitCmd()
|
||||
if err then return oops(err) end
|
||||
|
||||
if blockNo%4 ~= 3 then
|
||||
|
||||
-- blocks with zero not encrypted.
|
||||
if string.find(blockdata, '^0+$') then
|
||||
print(blockdata, blockdata)
|
||||
else
|
||||
local aes = core.aes128_decrypt_ecb(decryptkey, blockdata)
|
||||
local bytes = utils.ConvertAsciiToBytes(aes)
|
||||
local hex = utils.ConvertBytesToHex(bytes)
|
||||
print(blockdata , hex)
|
||||
end
|
||||
elseif blockNo == 0 then
|
||||
print(blockdata,blockdata)
|
||||
else
|
||||
-- Sectorblocks, not encrypted
|
||||
local sectortrailer = keyA..blockdata:sub(13,20)..keyA
|
||||
print(sectortrailer, sectortrailer, blockdata:sub(13,20))
|
||||
end
|
||||
end
|
||||
-- checksum fyra sista bytes i varje rad. (kanske inte för s0)
|
||||
-- s0b1,s1b0,s2b0,s3b0
|
||||
--
|
||||
end
|
||||
|
||||
main(args)
|
|
@ -73,7 +73,8 @@ local function convert_to_emulform(hexdata)
|
|||
for i = 1, string.len(hexdata),32 do
|
||||
ascii = ascii ..string.sub(hexdata,i,i+31).."\n"
|
||||
end
|
||||
return ascii
|
||||
|
||||
return string.sub(ascii,1,-1)
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
|
|
|
@ -80,14 +80,14 @@ function GetCardInfo()
|
|||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k
|
||||
if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k
|
||||
-- IFARE Classic 4K offers 4096 bytes split into forty sectors,
|
||||
-- of which 32 are same size as in the 1K with eight more that are quadruple size sectors.
|
||||
numSectors = 40
|
||||
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
|
||||
elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k
|
||||
-- 1K offers 1024 bytes of data storage, split into 16 sector
|
||||
numSectors = 16
|
||||
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
|
||||
elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k
|
||||
-- MIFARE Classic mini offers 320 bytes split into five sectors.
|
||||
numSectors = 5
|
||||
elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k
|
||||
|
|
|
@ -205,7 +205,7 @@ local function main( args)
|
|||
|
||||
-- NDEF compliant?
|
||||
if b3chars[1] ~= 0xE1 then
|
||||
return oops("This tag is not NDEF-Complian")
|
||||
return oops("This tag is not NDEF-Compliant")
|
||||
end
|
||||
|
||||
local ndefVersion = b3chars[2]
|
||||
|
|
|
@ -95,6 +95,7 @@ end
|
|||
|
||||
function test()
|
||||
local y
|
||||
local block = "00"
|
||||
for y = 0x0, 0x1d, 0x4 do
|
||||
for _ = 1, #procedurecmds do
|
||||
local pcmd = procedurecmds[_]
|
||||
|
@ -107,7 +108,7 @@ function test()
|
|||
dbg(('lf t55xx write 0 %s'):format(config))
|
||||
config = tonumber(config,16)
|
||||
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||
local err = core.SendCommand(writecmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
|
|
|
@ -89,6 +89,7 @@ end
|
|||
|
||||
function test()
|
||||
local y
|
||||
local block = "00"
|
||||
for y = 1, 0x1D, 4 do
|
||||
for _ = 1, #procedurecmds do
|
||||
local pcmd = procedurecmds[_]
|
||||
|
@ -98,10 +99,10 @@ function test()
|
|||
elseif _ == 1 then
|
||||
|
||||
local config = pcmd:format(config1, y, config2)
|
||||
dbg(('lf t55xx wr 0 %s'):format(config))
|
||||
|
||||
config = tonumber(config,16)
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
|
||||
dbg(('lf t55xx write 0 %s'):format(config))
|
||||
|
||||
config = tonumber(config,16)
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||
local err = core.SendCommand(writecmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
|
|
|
@ -92,6 +92,7 @@ end
|
|||
|
||||
function test(modulation)
|
||||
local y
|
||||
local block = "00"
|
||||
for y = 0x0, 0x1d, 0x4 do
|
||||
for _ = 1, #procedurecmds do
|
||||
local pcmd = procedurecmds[_]
|
||||
|
@ -104,7 +105,7 @@ function test(modulation)
|
|||
dbg(('lf t55xx write 0 %s'):format(config))
|
||||
|
||||
config = tonumber(config,16)
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||
local err = core.SendCommand(writecmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
|
|
|
@ -108,6 +108,7 @@ end
|
|||
function test(modulation)
|
||||
local bitrate
|
||||
local clockrate
|
||||
local block = "00"
|
||||
for bitrate = 0x0, 0x1d, 0x4 do
|
||||
|
||||
for clockrate = 0,8,4 do
|
||||
|
@ -125,8 +126,8 @@ function test(modulation)
|
|||
dbg(('lf t55xx write 0 %s'):format(config))
|
||||
|
||||
config = tonumber(config,16)
|
||||
local writecommand = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config ,arg2 = 0, arg3 = 0}
|
||||
local err = core.SendCommand(writecommand:getBytes())
|
||||
local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"}
|
||||
local err = core.SendCommand(writecmd:getBytes())
|
||||
if err then return oops(err) end
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
|
||||
else
|
||||
|
|
165
client/scripts/tnp3clone.lua
Normal file
165
client/scripts/tnp3clone.lua
Normal file
|
@ -0,0 +1,165 @@
|
|||
local cmds = require('commands')
|
||||
local getopt = require('getopt')
|
||||
local lib14a = require('read14a')
|
||||
local utils = require('utils')
|
||||
local pre = require('precalc')
|
||||
local toys = require('default_toys')
|
||||
|
||||
local lsh = bit32.lshift
|
||||
local rsh = bit32.rshift
|
||||
local bor = bit32.bor
|
||||
local band = bit32.band
|
||||
|
||||
example =[[
|
||||
script run tnp3clone
|
||||
script run tnp3clone -h
|
||||
script run tnp3clone -l
|
||||
script run tnp3clone -t aa00 -s 0030
|
||||
|
||||
]]
|
||||
author = "Iceman"
|
||||
usage = "script run tnp3clone -t <toytype> -s <subtype>"
|
||||
desc =[[
|
||||
This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
|
||||
|
||||
Arguments:
|
||||
-h : this help
|
||||
-l : list all known toy tokens
|
||||
-t <data> : toytype id, 4hex symbols
|
||||
-s <data> : subtype id, 4hex symbols
|
||||
|
||||
For fun, try the following subtype id:
|
||||
0612 - Lightcore
|
||||
0118 - Series 1
|
||||
0138 - Series 2
|
||||
0234 - Special
|
||||
023c - Special
|
||||
0020 - Swapforce
|
||||
]]
|
||||
|
||||
|
||||
-- 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
|
||||
|
||||
local function waitCmd()
|
||||
local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
|
||||
if response then
|
||||
local count,cmd,arg0 = bin.unpack('LL',response)
|
||||
if(arg0==1) then
|
||||
local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
|
||||
return data:sub(1,32)
|
||||
else
|
||||
return nil, "Couldn't read block."
|
||||
end
|
||||
end
|
||||
return nil, "No response from device"
|
||||
end
|
||||
|
||||
local function readblock( blocknum, keyA )
|
||||
-- Read block 0
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA}
|
||||
err = core.SendCommand(cmd:getBytes())
|
||||
if err then return nil, err end
|
||||
local block0, err = waitCmd()
|
||||
if err then return nil, err end
|
||||
return block0
|
||||
end
|
||||
local function readmagicblock( blocknum )
|
||||
-- Read block 0
|
||||
local CSETBLOCK_SINGLE_OPERATION = 0x1F
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum}
|
||||
err = core.SendCommand(cmd:getBytes())
|
||||
if err then return nil, err end
|
||||
local block0, err = waitCmd()
|
||||
if err then return nil, err end
|
||||
return block0
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local numBlocks = 64
|
||||
local cset = 'hf mf csetbl '
|
||||
local csetuid = 'hf mf csetuid '
|
||||
local cget = 'hf mf cgetbl '
|
||||
local empty = '00000000000000000000000000000000'
|
||||
local AccAndKeyB = '7F078869000000000000'
|
||||
-- Defaults to Gusto
|
||||
local toytype = 'C201'
|
||||
local subtype = '0030'
|
||||
local DEBUG = true
|
||||
|
||||
-- Arguments for the script
|
||||
for o, a in getopt.getopt(args, 'ht:s:l') do
|
||||
if o == "h" then return help() end
|
||||
if o == "t" then toytype = a end
|
||||
if o == "s" then subtype = a end
|
||||
if o == "l" then return toys.List() end
|
||||
end
|
||||
|
||||
if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end
|
||||
if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end
|
||||
|
||||
-- look up type, find & validate types
|
||||
local item = toys.Find( toytype, subtype)
|
||||
if item then
|
||||
print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
||||
else
|
||||
print('Didn\'t find item type. If you are sure about it, report it in')
|
||||
end
|
||||
--15,16
|
||||
--13-14
|
||||
|
||||
|
||||
-- find tag
|
||||
result, err = lib14a.read1443a(false)
|
||||
if not result then return oops(err) end
|
||||
|
||||
-- load keys
|
||||
local akeys = pre.GetAll(result.uid)
|
||||
local keyA = akeys:sub(1, 12 )
|
||||
|
||||
local b0 = readblock(0,keyA)
|
||||
if not b0 then
|
||||
print('failed reading block with factorydefault key. Trying chinese magic read.')
|
||||
b0, err = readmagicblock(0)
|
||||
if not b0 then
|
||||
oops(err)
|
||||
return oops('failed reading block with chinese magic command. quitting...')
|
||||
end
|
||||
end
|
||||
|
||||
-- wipe card.
|
||||
local cmd = (csetuid..'%s 0004 08 w'):format(result.uid)
|
||||
core.console(cmd)
|
||||
|
||||
local b1 = toytype..string.rep('00',10)..subtype
|
||||
|
||||
local calc = utils.Crc16(b0..b1)
|
||||
local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
|
||||
|
||||
local cmd = (cset..'1 %s%04x'):format( b1, calcEndian)
|
||||
core.console(cmd)
|
||||
|
||||
local pos, key
|
||||
for blockNo = 2, numBlocks-1, 1 do
|
||||
pos = (math.floor( blockNo / 4 ) * 12)+1
|
||||
key = akeys:sub(pos, pos + 11 )
|
||||
if blockNo%4 == 3 then
|
||||
cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB)
|
||||
core.console(cmd)
|
||||
end
|
||||
end
|
||||
core.clearCommandBuffer()
|
||||
end
|
||||
main(args)
|
|
@ -5,19 +5,21 @@ local lib14a = require('read14a')
|
|||
local utils = require('utils')
|
||||
local md5 = require('md5')
|
||||
local dumplib = require('html_dumplib')
|
||||
local toyNames = require('default_toys')
|
||||
local toys = require('default_toys')
|
||||
|
||||
example =[[
|
||||
1. script run tnp3dump
|
||||
2. script run tnp3dump -n
|
||||
3. script run tnp3dump -k aabbccddeeff
|
||||
4. script run tnp3dump -k aabbccddeeff -n
|
||||
5. script run tnp3dump -o myfile
|
||||
6. script run tnp3dump -n -o myfile
|
||||
7. script run tnp3dump -k aabbccddeeff -n -o myfile
|
||||
script run tnp3dump
|
||||
script run tnp3dump -n
|
||||
script run tnp3dump -p
|
||||
script run tnp3dump -k aabbccddeeff
|
||||
script run tnp3dump -k aabbccddeeff -n
|
||||
script run tnp3dump -o myfile
|
||||
script run tnp3dump -n -o myfile
|
||||
script run tnp3dump -p -o myfile
|
||||
script run tnp3dump -k aabbccddeeff -n -o myfile
|
||||
]]
|
||||
author = "Iceman"
|
||||
usage = "script run tnp3dump -k <key> -n -o <filename>"
|
||||
usage = "script run tnp3dump -k <key> -n -p -o <filename>"
|
||||
desc =[[
|
||||
This script will try to dump the contents of a Mifare TNP3xxx card.
|
||||
It will need a valid KeyA in order to find the other keys and decode the card.
|
||||
|
@ -25,11 +27,10 @@ Arguments:
|
|||
-h : this help
|
||||
-k <key> : Sector 0 Key A.
|
||||
-n : Use the nested cmd to find all keys
|
||||
-p : Use the precalc to find all keys
|
||||
-o : filename for the saved dumps
|
||||
]]
|
||||
|
||||
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||
|
||||
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
local DEBUG = false -- the debug flag
|
||||
local numBlocks = 64
|
||||
|
@ -93,16 +94,6 @@ local function waitCmd()
|
|||
return nil, "No response from device"
|
||||
end
|
||||
|
||||
local function computeCrc16(s)
|
||||
local hash = core.crc16(utils.ConvertHexToAscii(s))
|
||||
return hash
|
||||
end
|
||||
|
||||
local function reverseCrcBytes(crc)
|
||||
crc2 = crc:sub(3,4)..crc:sub(1,2)
|
||||
return tonumber(crc2,16)
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
|
@ -112,18 +103,20 @@ local function main(args)
|
|||
local cmd
|
||||
local err
|
||||
local useNested = false
|
||||
local usePreCalc = false
|
||||
local cmdReadBlockString = 'hf mf rdbl %d A %s'
|
||||
local input = "dumpkeys.bin"
|
||||
local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
|
||||
|
||||
-- Arguments for the script
|
||||
for o, a in getopt.getopt(args, 'hk:no:') do
|
||||
for o, a in getopt.getopt(args, 'hk:npo:') do
|
||||
if o == "h" then return help() end
|
||||
if o == "k" then keyA = a end
|
||||
if o == "n" then useNested = true end
|
||||
if o == "p" then usePreCalc = true end
|
||||
if o == "o" then outputTemplate = a end
|
||||
end
|
||||
|
||||
|
||||
-- validate input args.
|
||||
keyA = keyA or '4b0b20107ccb'
|
||||
if #(keyA) ~= 12 then
|
||||
|
@ -141,30 +134,31 @@ local function main(args)
|
|||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
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))
|
||||
print(('Using keyA : %s'):format(keyA))
|
||||
print((' Found tag %s'):format(result.name))
|
||||
|
||||
dbg(('Using keyA : %s'):format(keyA))
|
||||
|
||||
--Trying to find the other keys
|
||||
if useNested then
|
||||
core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
|
||||
end
|
||||
|
||||
|
||||
core.clearCommandBuffer()
|
||||
|
||||
-- Loading keyfile
|
||||
print('Loading dumpkeys.bin')
|
||||
local hex, err = utils.ReadDumpFile(input)
|
||||
if not hex then
|
||||
return oops(err)
|
||||
local akeys = ''
|
||||
if usePreCalc then
|
||||
local pre = require('precalc')
|
||||
akeys = pre.GetAll(result.uid)
|
||||
else
|
||||
print('Loading dumpkeys.bin')
|
||||
local hex, err = utils.ReadDumpFile(input)
|
||||
if not hex then
|
||||
return oops(err)
|
||||
end
|
||||
akeys = hex:sub(0,12*16)
|
||||
end
|
||||
|
||||
local akeys = hex:sub(0,12*16)
|
||||
|
||||
|
||||
-- Read block 0
|
||||
cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
|
||||
err = core.SendCommand(cmd:getBytes())
|
||||
|
@ -179,6 +173,8 @@ local function main(args)
|
|||
local block1, err = waitCmd()
|
||||
if err then return oops(err) end
|
||||
|
||||
local tmpHash = block0..block1..'%02x'..RANDOM
|
||||
|
||||
local key
|
||||
local pos = 0
|
||||
local blockNo
|
||||
|
@ -188,7 +184,7 @@ local function main(args)
|
|||
core.clearCommandBuffer()
|
||||
|
||||
-- main loop
|
||||
io.write('Decrypting blocks > ')
|
||||
io.write('Reading blocks > ')
|
||||
for blockNo = 0, numBlocks-1, 1 do
|
||||
|
||||
if core.ukbhit() then
|
||||
|
@ -204,25 +200,24 @@ local function main(args)
|
|||
local blockdata, err = waitCmd()
|
||||
if err then return oops(err) end
|
||||
|
||||
|
||||
if blockNo%4 ~= 3 then
|
||||
|
||||
if blockNo < 8 then
|
||||
-- Block 0-7 not encrypted
|
||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
||||
else
|
||||
local base = ('%s%s%02x%s'):format(block0, block1, blockNo, HASHCONSTANT)
|
||||
local baseStr = utils.ConvertHexToAscii(base)
|
||||
local md5hash = md5.sumhexa(baseStr)
|
||||
local aestest = core.aes(md5hash, blockdata)
|
||||
|
||||
local hex = utils.ConvertAsciiToBytes(aestest)
|
||||
hex = utils.ConvertBytesToHex(hex)
|
||||
|
||||
-- blocks with zero not encrypted.
|
||||
if string.find(blockdata, '^0+$') then
|
||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata)
|
||||
else
|
||||
local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo))
|
||||
local key = md5.sumhexa(baseStr)
|
||||
local aestest = core.aes128_decrypt(key, blockdata)
|
||||
local hex = utils.ConvertAsciiToBytes(aestest)
|
||||
hex = utils.ConvertBytesToHex(hex)
|
||||
blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex)
|
||||
io.write( blockNo..',')
|
||||
io.write(blockNo..',')
|
||||
end
|
||||
end
|
||||
else
|
||||
|
@ -246,31 +241,40 @@ local function main(args)
|
|||
emldata = emldata..slice..'\n'
|
||||
for c in (str):gmatch('.') do
|
||||
bindata[#bindata+1] = c
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
print( string.rep('--',20) )
|
||||
|
||||
local uid = block0:sub(1,8)
|
||||
local itemtype = block1:sub(1,4)
|
||||
local toytype = block1:sub(1,4)
|
||||
local cardidLsw = block1:sub(9,16)
|
||||
local cardidMsw = block1:sub(16,24)
|
||||
local cardid = block1:sub(9,24)
|
||||
local traptype = block1:sub(25,28)
|
||||
local subtype = 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))
|
||||
local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin')
|
||||
print(("Wrote a BIN dump to: %s"):format(foo))
|
||||
local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml')
|
||||
print(("Wrote a EML dump to: %s"):format(bar))
|
||||
end
|
||||
|
||||
-- Show info
|
||||
print( string.rep('--',20) )
|
||||
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) )
|
||||
-- Show info
|
||||
|
||||
local item = toys.Find(toytype, subtype)
|
||||
if item then
|
||||
print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) )
|
||||
else
|
||||
print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype))
|
||||
end
|
||||
|
||||
print( (' UID : 0x%s'):format(uid) )
|
||||
print( (' CARDID : 0x%s'):format(cardid ) )
|
||||
print( string.rep('--',20) )
|
||||
|
||||
core.clearCommandBuffer()
|
||||
end
|
||||
main(args)
|
|
@ -4,7 +4,7 @@ local bin = require('bin')
|
|||
local lib14a = require('read14a')
|
||||
local utils = require('utils')
|
||||
local md5 = require('md5')
|
||||
local toyNames = require('default_toys')
|
||||
local toys = require('default_toys')
|
||||
|
||||
example =[[
|
||||
1. script run tnp3sim
|
||||
|
@ -23,10 +23,33 @@ Arguments:
|
|||
-h : this help
|
||||
-m : Maxed out items (experimental)
|
||||
-i : filename for the datadump to read (bin)
|
||||
]]
|
||||
|
||||
]]
|
||||
|
||||
local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
|
||||
local DEBUG = true -- the debug flag
|
||||
local DEBUG = false -- the debug flag
|
||||
local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||
|
||||
local band = bit32.band
|
||||
local bor = bit32.bor
|
||||
local lshift = bit32.lshift
|
||||
local rshift = bit32.rshift
|
||||
local byte = string.byte
|
||||
local char = string.char
|
||||
local sub = string.sub
|
||||
local format = string.format
|
||||
|
||||
|
||||
|
||||
local band = bit32.band
|
||||
local bor = bit32.bor
|
||||
local lshift = bit32.lshift
|
||||
local rshift = bit32.rshift
|
||||
local byte = string.byte
|
||||
local char = string.char
|
||||
local sub = string.sub
|
||||
local format = string.format
|
||||
|
||||
---
|
||||
-- A debug printout-function
|
||||
function dbg(args)
|
||||
|
@ -65,7 +88,6 @@ function ExitMsg(msg)
|
|||
print()
|
||||
end
|
||||
|
||||
|
||||
local function writedumpfile(infile)
|
||||
t = infile:read("*all")
|
||||
len = string.len(t)
|
||||
|
@ -187,9 +209,6 @@ local function ValidateCheckSums(blocks)
|
|||
io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
|
||||
end
|
||||
|
||||
|
||||
local function LoadEmulator(blocks)
|
||||
local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
|
||||
local cmd
|
||||
local blockdata
|
||||
for _,b in pairs(blocks) do
|
||||
|
@ -198,10 +217,10 @@ local function LoadEmulator(blocks)
|
|||
|
||||
if _%4 ~= 3 then
|
||||
if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then
|
||||
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , HASHCONSTANT)
|
||||
local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM)
|
||||
local baseStr = utils.ConvertHexToAscii(base)
|
||||
local key = md5.sumhexa(baseStr)
|
||||
local enc = core.aes(key, blockdata)
|
||||
local enc = core.aes128_encrypt(key, blockdata)
|
||||
local hex = utils.ConvertAsciiToBytes(enc)
|
||||
hex = utils.ConvertBytesToHex(hex)
|
||||
|
||||
|
@ -219,6 +238,102 @@ local function LoadEmulator(blocks)
|
|||
io.write('\n')
|
||||
end
|
||||
|
||||
local function Num2Card(m, l)
|
||||
|
||||
local k = {
|
||||
0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
|
||||
0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
|
||||
}
|
||||
local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
|
||||
local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
|
||||
|
||||
if msw > 0x17ea1 then
|
||||
return "too big"
|
||||
end
|
||||
|
||||
if msw == 0x17ea1 and lsw > 0x8931fee8 then
|
||||
return "out of range"
|
||||
end
|
||||
|
||||
local s = ""
|
||||
local index
|
||||
for i = 1,10 do
|
||||
index, msw, lsw = DivideByK( msw, lsw)
|
||||
if ( index <= 1 ) then
|
||||
s = char(k[index]) .. s
|
||||
else
|
||||
s = char(k[index-1]) .. s
|
||||
end
|
||||
print (index-1, msw, lsw)
|
||||
end
|
||||
return s
|
||||
end
|
||||
--33LRT-LM9Q9
|
||||
--7, 122, 3474858630
|
||||
--20, 4, 1008436634
|
||||
--7, 0, 627182959
|
||||
--17, 0, 21626998
|
||||
--16, 0, 745758
|
||||
--23, 0, 25715
|
||||
--21, 0, 886
|
||||
--16, 0, 30
|
||||
--1, 0, 1
|
||||
--1, 0, 0
|
||||
|
||||
function DivideByK(msw, lsw)
|
||||
|
||||
local lowLSW
|
||||
local highLSW
|
||||
local remainder = 0
|
||||
local RADIX = 29
|
||||
|
||||
--local num = 0 | band( rshift(msw,16), 0xffff)
|
||||
local num = band( rshift(msw, 16), 0xffff)
|
||||
|
||||
--highLSW = 0 | lshift( (num / RADIX) , 16)
|
||||
highLSW = lshift( (num / RADIX) , 16)
|
||||
remainder = num % RADIX
|
||||
|
||||
num = bor( lshift(remainder,16), band(msw, 0xffff))
|
||||
|
||||
--highLSW |= num / RADIX
|
||||
highLSW = highLSW or (num / RADIX)
|
||||
remainder = num % RADIX
|
||||
|
||||
num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
|
||||
|
||||
--lowLSW = 0 | (num / RADIX) << 16
|
||||
lowLSW = 0 or (lshift( (num / RADIX), 16))
|
||||
remainder = num % RADIX
|
||||
|
||||
num = bor( lshift(remainder,16) , band(lsw, 0xffff) )
|
||||
|
||||
lowLSW = bor(lowLSW, (num / RADIX))
|
||||
remainder = num % RADIX
|
||||
return remainder, highLSW, lowLSW
|
||||
|
||||
-- uint num = 0 | (msw >> 16) & 0xffff;
|
||||
|
||||
-- highLSW = 0 | (num / RADIX) << 16;
|
||||
-- remainder = num % RADIX;
|
||||
|
||||
-- num = (remainder << 16) | (msw & 0xffff);
|
||||
|
||||
-- highLSW |= num / RADIX;
|
||||
-- remainder = num % RADIX;
|
||||
|
||||
-- num = (remainder << 16) | ((lsw >> 16) & 0xffff);
|
||||
|
||||
-- lowLSW = 0 | (num / RADIX) << 16;
|
||||
-- remainder = num % RADIX;
|
||||
|
||||
-- num = (remainder << 16) | (lsw & 0xffff);
|
||||
|
||||
-- lowLSW |= num / RADIX;
|
||||
-- remainder = num % RADIX;
|
||||
|
||||
end
|
||||
|
||||
local function main(args)
|
||||
|
||||
print( string.rep('--',20) )
|
||||
|
@ -241,21 +356,6 @@ local function main(args)
|
|||
local cmdSetDbgOff = "hf mf dbg 0"
|
||||
core.console( cmdSetDbgOff)
|
||||
|
||||
-- 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()
|
||||
|
||||
-- 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))
|
||||
-- end
|
||||
|
||||
-- Load dump.bin file
|
||||
print( (' Load data from %s'):format(inputTemplate))
|
||||
hex, err = utils.ReadDumpFile(inputTemplate)
|
||||
|
@ -269,7 +369,7 @@ local function main(args)
|
|||
end
|
||||
|
||||
if DEBUG then
|
||||
print('Validating checksums in the loaded datadump')
|
||||
print(' Validating checksums')
|
||||
ValidateCheckSums(blocks)
|
||||
end
|
||||
|
||||
|
@ -277,22 +377,44 @@ local function main(args)
|
|||
print( string.rep('--',20) )
|
||||
print(' Gathering info')
|
||||
local uid = blocks[0]:sub(1,8)
|
||||
local itemtype = blocks[1]:sub(1,4)
|
||||
local cardid = blocks[1]:sub(9,24)
|
||||
local toytype = blocks[1]:sub(1,4)
|
||||
local cardidLsw = blocks[1]:sub(9,16)
|
||||
local cardidMsw = blocks[1]:sub(17,24)
|
||||
local subtype = blocks[1]:sub(25,28)
|
||||
|
||||
-- Show info
|
||||
print( string.rep('--',20) )
|
||||
print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
|
||||
|
||||
local item = toys.Find( toytype, subtype)
|
||||
if item then
|
||||
local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4])
|
||||
print(' ITEM TYPE : '..itemStr )
|
||||
else
|
||||
print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) )
|
||||
end
|
||||
|
||||
print( (' UID : 0x%s'):format(uid) )
|
||||
print( (' CARDID : 0x%s'):format(cardid ) )
|
||||
print( (' CARDID : 0x%s %s [%s]'):format(
|
||||
cardidMsw,cardidLsw,
|
||||
--Num2Card(cardidMsw, cardidLsw))
|
||||
'')
|
||||
)
|
||||
print( string.rep('--',20) )
|
||||
|
||||
-- lets do something.
|
||||
--
|
||||
|
||||
-- Experience should be:
|
||||
local experience = blocks[8]:sub(1,6)
|
||||
print(('Experience : %d'):format(utils.SwapEndianness(experience,24)))
|
||||
print(('Experience : %d'):format(utils.SwapEndianness(experience,16)))
|
||||
|
||||
local money = blocks[8]:sub(7,10)
|
||||
print(('Money : %d'):format(utils.SwapEndianness(money,16)))
|
||||
|
||||
--
|
||||
|
||||
-- Sequence number
|
||||
local seqnum = blocks[8]:sub(18,19)
|
||||
print(('Sequence number : %d'):format( tonumber(seqnum,16)))
|
||||
|
||||
local fairy = blocks[9]:sub(1,8)
|
||||
--FD0F = Left, FF0F = Right
|
||||
local path = 'not choosen'
|
||||
|
@ -305,6 +427,12 @@ local function main(args)
|
|||
|
||||
local hat = blocks[9]:sub(8,11)
|
||||
print(('Hat : %d'):format(utils.SwapEndianness(hat,16)))
|
||||
|
||||
local level = blocks[13]:sub(27,28)
|
||||
print(('LEVEL : %d'):format( tonumber(level,16)))
|
||||
--hälsa: 667 029b
|
||||
--local health = blocks[]:sub();
|
||||
--print(('Health : %d'):format( tonumber(health,16))
|
||||
|
||||
--0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100.
|
||||
local heropoints = blocks[13]:sub(20,23)
|
||||
|
@ -314,6 +442,11 @@ local function main(args)
|
|||
local challenges = blocks[16]:sub(25,32)
|
||||
print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32)))
|
||||
|
||||
-- Character Name
|
||||
local name1 = blocks[10]:sub(1,32)
|
||||
local name2 = blocks[12]:sub(1,32)
|
||||
print('Custom name : '..utils.ConvertHexToAscii(name1..name2))
|
||||
|
||||
if maxed then
|
||||
print('Lets try to max out some values')
|
||||
-- max out money, experience
|
||||
|
@ -351,7 +484,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 u '..uid..' x\" <--')
|
||||
print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
|
||||
end
|
||||
end
|
||||
main(args)
|
|
@ -108,11 +108,12 @@ void print_hex(const uint8_t * data, const size_t len)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
char * sprint_hex(const uint8_t * data, const size_t len) {
|
||||
char *sprint_hex(const uint8_t *data, const size_t len) {
|
||||
|
||||
int maxLen = ( len > 1024/3) ? 1024/3 : len;
|
||||
static char buf[1024];
|
||||
char * tmp = buf;
|
||||
memset(buf, 0x00, 1024);
|
||||
char *tmp = buf;
|
||||
size_t i;
|
||||
|
||||
for (i=0; i < maxLen; ++i, tmp += 3)
|
||||
|
@ -121,19 +122,25 @@ char * sprint_hex(const uint8_t * data, const size_t len) {
|
|||
return buf;
|
||||
}
|
||||
|
||||
char * sprint_bin(const uint8_t * data, const size_t len) {
|
||||
char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) {
|
||||
|
||||
int maxLen = ( len > 1024) ? 1024 : len;
|
||||
int maxLen = ( len > 1020) ? 1020 : len;
|
||||
static char buf[1024];
|
||||
char * tmp = buf;
|
||||
size_t i;
|
||||
memset(buf, 0x00, 1024);
|
||||
char *tmp = buf;
|
||||
|
||||
for (i=0; i < maxLen; ++i, ++tmp)
|
||||
sprintf(tmp, "%u", data[i]);
|
||||
for (size_t i=0; i < maxLen; ++i){
|
||||
sprintf(tmp++, "%u", data[i]);
|
||||
if (breaks > 0 && !((i+1) % breaks))
|
||||
sprintf(tmp++, "%s","\n");
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *sprint_bin(const uint8_t *data, const size_t len) {
|
||||
return sprint_bin_break(data, len, 0);
|
||||
}
|
||||
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
|
||||
{
|
||||
while (len--) {
|
||||
|
@ -153,6 +160,22 @@ uint64_t bytes_to_num(uint8_t* src, size_t len)
|
|||
return num;
|
||||
}
|
||||
|
||||
// aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
|
||||
// to
|
||||
// hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
|
||||
// up to 64 bytes or 512 bits
|
||||
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize){
|
||||
static uint8_t buf[64];
|
||||
memset(buf, 0x00, 64);
|
||||
uint8_t *tmp = buf;
|
||||
for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){
|
||||
for (size_t i = 0; i < blockSize; i++){
|
||||
tmp[i+(blockSize*block)] = src[(blockSize-1-i)+(blockSize*block)];
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//assumes little endian
|
||||
char * printBits(size_t const size, void const * const ptr)
|
||||
{
|
||||
|
@ -371,7 +394,7 @@ int hextobinstring(char *target, char *source)
|
|||
|
||||
// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source)
|
||||
// return number of bits converted
|
||||
int binarraytohex(char *target, char *source, int length)
|
||||
int binarraytohex(char *target,char *source, int length)
|
||||
{
|
||||
unsigned char i, x;
|
||||
int j = length;
|
||||
|
@ -421,3 +444,12 @@ void wiegand_add_parity(char *target, char *source, char length)
|
|||
target += length;
|
||||
*(target)= GetParity(source + length / 2, ODD, length / 2);
|
||||
}
|
||||
|
||||
void xor(unsigned char *dst, unsigned char *src, size_t len) {
|
||||
for( ; len > 0; len--,dst++,src++)
|
||||
*dst ^= *src;
|
||||
}
|
||||
|
||||
int32_t le24toh (uint8_t data[3]) {
|
||||
return (data[2] << 16) | (data[1] << 8) | data[0];
|
||||
}
|
||||
|
|
|
@ -39,10 +39,12 @@ void FillFileNameByUID(char *fileName, uint8_t * uid, char *ext, int byteCount);
|
|||
void print_hex(const uint8_t * data, const size_t len);
|
||||
char * sprint_hex(const uint8_t * data, const size_t len);
|
||||
char * sprint_bin(const uint8_t * data, const size_t len);
|
||||
char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
|
||||
|
||||
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
|
||||
uint64_t bytes_to_num(uint8_t* src, size_t len);
|
||||
char * printBits(size_t const size, void const * const ptr);
|
||||
uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
|
||||
|
||||
char param_getchar(const char *line, int paramnum);
|
||||
uint8_t param_get8(const char *line, int paramnum);
|
||||
|
@ -61,3 +63,5 @@ void binarraytobinstring(char *target, char *source, int length);
|
|||
uint8_t GetParity( char *string, uint8_t type, int length);
|
||||
void wiegand_add_parity(char *target, char *source, char length);
|
||||
|
||||
void xor(unsigned char *dst, unsigned char *src, size_t len);
|
||||
int32_t le24toh(uint8_t data[3]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue