Merge branch 'master' into topaz

Conflicts:
	client/Makefile
	client/cmdhf.c
	client/cmdhf14a.c
This commit is contained in:
pwpiwi 2015-07-01 08:17:00 +02:00
commit db2b81ba11
119 changed files with 20403 additions and 4640 deletions

View file

@ -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 $@ $<

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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)

View file

@ -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
}

View file

@ -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}
};

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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

View file

@ -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);

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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[] =

View file

@ -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... }"},

View file

@ -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);

View file

@ -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;
}

View file

@ -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

View file

@ -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)"},

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;
}

View file

@ -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 );

View file

@ -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);

View file

@ -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
View 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);
}
}

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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,
}

View file

@ -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
View 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

View file

@ -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.

View 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

View file

@ -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 = {}

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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
View 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)

View file

@ -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)

View file

@ -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

View file

@ -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]

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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

View 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)

View file

@ -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)

View file

@ -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)

View file

@ -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];
}

View file

@ -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]);