mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-02-25 16:45:09 +08:00
added "hf jooki sim" command. Lets see if the data_available call every 8000th times doesnt interrupt with simulation process too much.
This commit is contained in:
parent
73cd4fb4ff
commit
46d9ed20e5
2 changed files with 134 additions and 20 deletions
|
@ -916,18 +916,24 @@ bool GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, int *len) {
|
||||||
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void)b;
|
(void)b;
|
||||||
|
|
||||||
uint16_t check = 0;
|
uint8_t flip = 0;
|
||||||
|
uint16_t checker = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (check == 4000) {
|
WDT_HIT();
|
||||||
// if (BUTTON_PRESS() || data_available())
|
if (flip) {
|
||||||
if (BUTTON_PRESS())
|
if (data_available())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
check = 0;
|
checker = 0;
|
||||||
WDT_HIT();
|
flip = 0;
|
||||||
}
|
}
|
||||||
++check;
|
|
||||||
|
if (checker >= 4000) {
|
||||||
|
if (BUTTON_PRESS())
|
||||||
|
return false;
|
||||||
|
flip = 1;
|
||||||
|
}
|
||||||
|
++checker;
|
||||||
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
||||||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
@ -1335,7 +1341,6 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data, uint8_t
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
|
||||||
// main loop
|
// main loop
|
||||||
//for (;;) {
|
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
bool button_pushed = BUTTON_PRESS();
|
bool button_pushed = BUTTON_PRESS();
|
||||||
while (!button_pushed && !finished) {
|
while (!button_pushed && !finished) {
|
||||||
|
|
|
@ -15,10 +15,12 @@
|
||||||
#include "generator.h"
|
#include "generator.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
#include "mifare/ndef.h" // print decode ndef
|
#include "mifare/ndef.h" // print decode ndef
|
||||||
|
#include "mifare/mifarehost.h" // mfemlsetmem_xt
|
||||||
#include "cliparser.h"
|
#include "cliparser.h"
|
||||||
#include "cmdhfmfu.h"
|
#include "cmdhfmfu.h"
|
||||||
#include "cmdmain.h"
|
#include "cmdmain.h"
|
||||||
|
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -146,12 +148,6 @@ static void jooki_print(uint8_t *b64, uint8_t *result, bool verbose) {
|
||||||
jooki_printEx(b64, iv, tt, uid, verbose);
|
jooki_printEx(b64, iv, tt, uid, verbose);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
static int jooki_write(void) {
|
|
||||||
return PM3_SUCCESS;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int jooki_selftest(void) {
|
static int jooki_selftest(void) {
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "======== " _CYAN_("selftest") " ===========================================");
|
PrintAndLogEx(INFO, "======== " _CYAN_("selftest") " ===========================================");
|
||||||
|
@ -195,7 +191,7 @@ static int jooki_selftest(void) {
|
||||||
|
|
||||||
static int CmdHF14AJookiEncode(const char *Cmd) {
|
static int CmdHF14AJookiEncode(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf jooki Encode",
|
CLIParserInit(&ctx, "hf jooki encode",
|
||||||
"Encode a Jooki token to base64 NDEF URI format",
|
"Encode a Jooki token to base64 NDEF URI format",
|
||||||
"hf jooki encode -t --> selftest\n"
|
"hf jooki encode -t --> selftest\n"
|
||||||
"hf jooki encode -r --dragon --> read uid from tag and use for encoding\n"
|
"hf jooki encode -r --dragon --> read uid from tag and use for encoding\n"
|
||||||
|
@ -219,7 +215,11 @@ static int CmdHF14AJookiEncode(const char *Cmd) {
|
||||||
int ulen = 0;
|
int ulen = 0;
|
||||||
uint8_t uid[JOOKI_UID_LEN] = {0x00};
|
uint8_t uid[JOOKI_UID_LEN] = {0x00};
|
||||||
memset(uid, 0x0, sizeof(uid));
|
memset(uid, 0x0, sizeof(uid));
|
||||||
CLIParamHexToBuf(arg_get_str(ctx, 1), uid, sizeof(uid), &ulen);
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), uid, sizeof(uid), &ulen);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
bool use_tag = arg_get_lit(ctx, 2);
|
bool use_tag = arg_get_lit(ctx, 2);
|
||||||
bool selftest = arg_get_lit(ctx, 3);
|
bool selftest = arg_get_lit(ctx, 3);
|
||||||
|
@ -251,7 +251,7 @@ static int CmdHF14AJookiEncode(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t iv[JOOKI_IV_LEN] = {0x80, 0x77, 0x51, 1};
|
uint8_t iv[JOOKI_IV_LEN] = {0x80, 0x77, 0x51, 1};
|
||||||
if (use_tag) {
|
if (use_tag) {
|
||||||
int res = ul_read_uid(uid);
|
res = ul_read_uid(uid);
|
||||||
if (res != PM3_SUCCESS) {
|
if (res != PM3_SUCCESS) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
@ -298,11 +298,118 @@ static int CmdHF14AJookiDecode(const char *Cmd) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int CmdHF14AJookiSim(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf jooki sim",
|
||||||
|
"Simulate a Jooki token. Either `hf mfu eload` before or use `-d` param",
|
||||||
|
"hf jooki sim --> using eload before\n"
|
||||||
|
"hf jooki sim -d 7WzlgEzqLgwTnWNy"
|
||||||
|
);
|
||||||
|
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str0("d", "data", "<hex>", "base64 url parameter"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
int dlen = 16;
|
||||||
|
uint8_t b64[JOOKI_B64_LEN] = {0x00};
|
||||||
|
memset(b64, 0x0, sizeof(b64));
|
||||||
|
CLIGetStrWithReturn(ctx, 1, b64, &dlen);
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
uint8_t result[JOOKI_PLAIN_LEN] = {0};
|
||||||
|
int res = jooki_decode(b64, result);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
jooki_print(b64, result, false);
|
||||||
|
|
||||||
|
// hf mfu sim...
|
||||||
|
uint8_t data[144] = {0};
|
||||||
|
|
||||||
|
// copy UID from base64 url parameter
|
||||||
|
memcpy(data, result + 5, 3);
|
||||||
|
// bbc0
|
||||||
|
data[3] = data[0] ^ data[1] ^ data[2];
|
||||||
|
|
||||||
|
memcpy(data + (1*4), result + 8, 4);
|
||||||
|
// bbc1
|
||||||
|
data[8] = data[4] ^ data[5] ^ data[6] ^ data[7];
|
||||||
|
|
||||||
|
// copy NDEF magic firs, skip BBC1
|
||||||
|
memcpy(data + (2*4) + 1, "\x48\x1f\x00\xE1\x10\x12\x00", 7);
|
||||||
|
|
||||||
|
// copy raw NDEF
|
||||||
|
jooki_create_ndef(b64, data + (4 * 4));
|
||||||
|
|
||||||
|
// upload to emulator memory
|
||||||
|
PrintAndLogEx(INFO, "Uploading to emulator memory");
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "." NOLF);
|
||||||
|
// fast push mode
|
||||||
|
conn.block_after_ACK = true;
|
||||||
|
uint8_t blockwidth = 4, counter = 0, blockno = 0, datalen = sizeof(data);
|
||||||
|
while (datalen) {
|
||||||
|
if (datalen == blockwidth) {
|
||||||
|
// Disable fast mode on last packet
|
||||||
|
conn.block_after_ACK = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mfEmlSetMem_xt(data + counter, blockno, 1, blockwidth) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockno);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "." NOLF);
|
||||||
|
fflush(stdout);
|
||||||
|
blockno++;
|
||||||
|
counter += blockwidth;
|
||||||
|
datalen -= blockwidth;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(NORMAL, "\n");
|
||||||
|
|
||||||
|
|
||||||
|
struct {
|
||||||
|
uint8_t tagtype;
|
||||||
|
uint8_t flags;
|
||||||
|
uint8_t uid[10];
|
||||||
|
uint8_t exitAfter;
|
||||||
|
} PACKED payload;
|
||||||
|
|
||||||
|
// MF Ultralight , 7 byte UID in eloaded data.
|
||||||
|
payload.tagtype = 2;
|
||||||
|
payload.flags = FLAG_7B_UID_IN_DATA;
|
||||||
|
payload.exitAfter = 0;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
SendCommandNG(CMD_HF_ISO14443A_SIMULATE, (uint8_t *)&payload, sizeof(payload));
|
||||||
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " or pm3-button to abort simulation");
|
||||||
|
for (;;) {
|
||||||
|
if (kbd_enter_pressed()) {
|
||||||
|
SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
|
||||||
|
PrintAndLogEx(DEBUG, "User aborted");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_MIFARE_SIMULATE, &resp, 1500) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (resp.status != PM3_SUCCESS)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
PrintAndLogEx(INFO, "Done");
|
||||||
|
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf 14a list") "` to view trace log" );
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHF14AJookiWrite(const char *Cmd) {
|
static int CmdHF14AJookiWrite(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf jooki write",
|
CLIParserInit(&ctx, "hf jooki write",
|
||||||
"Write a Jooki token to a Ultralight or NTAG tag",
|
"Write a Jooki token to a Ultralight or NTAG tag",
|
||||||
"hf jooki write"
|
"hf jooki write -d xxxxxxxx -> where x is raw NDEF from encode command"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -373,7 +480,9 @@ static command_t CommandTable[] = {
|
||||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||||
{"encode", CmdHF14AJookiEncode, AlwaysAvailable, "Encode Jooki token"},
|
{"encode", CmdHF14AJookiEncode, AlwaysAvailable, "Encode Jooki token"},
|
||||||
{"decode", CmdHF14AJookiDecode, AlwaysAvailable, "Decode Jooki token"},
|
{"decode", CmdHF14AJookiDecode, AlwaysAvailable, "Decode Jooki token"},
|
||||||
|
{"sim", CmdHF14AJookiSim, IfPm3Iso14443a, "Simulate Jooki token"},
|
||||||
{"write", CmdHF14AJookiWrite, IfPm3Iso14443a, "Write a Jooki token"},
|
{"write", CmdHF14AJookiWrite, IfPm3Iso14443a, "Write a Jooki token"},
|
||||||
|
|
||||||
{NULL, NULL, NULL, NULL}
|
{NULL, NULL, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue