Merge branch 'master' of https://github.com/RfidResearchGroup/proxmark3 into autopwn_restyle

This commit is contained in:
Matthias Konrath 2019-08-29 06:17:27 +02:00
commit a69fbdd3af
18 changed files with 451 additions and 186 deletions

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Chg history and logfile are now saved into $HOME/.proxmark3/ (@doegox)
- Chg optimization of iclass mac calculations on deviceside (@pwpiwi)
- Add 'hf mf autopwn' - Autopwn function for Mifare Classic, extract all keys and dump card memory (@matthiaskonrath)
- Add Lua paths: look for scripts also in ~/.proxmark/lua{scripts,libs} and /usr/local/share/proxmark3/lua{scripts,libs} (@doegox)

View file

@ -77,9 +77,63 @@ clone_script:
$env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
Function ExecUpdate($Name, $Cmd, $ErrorLine) {
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
#--- begin Job
$Job = Start-Job -Name "$Name" -ScriptBlock {
$env:Path = "C:\ProxSpace\msys\bin;$env:Path"
Set-Location $using:PWD
$sb=[scriptblock]::Create("$using:Cmd")
#execute scriptblock
$Cond=&$sb
return $Cond
}
#--- end Job
$JobTime=[System.Environment]::TickCount
while($true) {
Receive-Job -Job $Job -Keep -OutVariable Res 2>&1 6>&1 | Out-Null
if ($Res -is "String" -and $Res -like "*$ErrorLine*"){
Write-host "Exit by stop phrase"
break
}
if ($Res -is [Object]){
[bool]$needexit = $false
ForEach($line in $Res){
if ($line -like "*$ErrorLine*"){
Write-host "Exit by stop phrase [obj]"
$needexit = $true
break
}
}
if ($needexit) {
break
}
}
if(Wait-Job $Job -Timeout 5){
Write-host "Exit by end job"
break
}
if ([System.Environment]::TickCount-$JobTime -gt 600000) {
Write-host "Exit by timeout"
break
}
}
Remove-Job -Force $Job
}
ExecUpdate "update1" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
ExecUpdate "update2" "C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null" "terminate?MSYS2"
Write-Host "[ OK ]" -ForegroundColor Green
install:

View file

@ -1134,7 +1134,8 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_MIFARE_EML_LOAD: {
MifareECardLoad(packet->oldarg[0], packet->oldarg[1]);
mfc_eload_t *payload = (mfc_eload_t *) packet->data.asBytes;
MifareECardLoadExt(payload->sectorcnt, payload->keytype);
break;
}
// Work with "magic Chinese" card

View file

@ -55,7 +55,13 @@
#include "protocols.h"
#include "ticks.h"
static int timeout = 4096;
static int g_wait = 300;
static int timeout = 2900;
static uint32_t time_rdr = 0;
static uint32_t time_delta = 0;
static uint32_t time_delta_wait = 0;
static uint32_t time_response = 0;
static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay);
int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf);
@ -151,7 +157,7 @@ typedef struct {
static tUartIc Uart;
static void OnError(uint8_t reason) {
reply_old(CMD_ACK, 0, reason, 0, 0, 0);
reply_mix(CMD_ACK, 0, reason, 0, 0, 0);
switch_off();
}
@ -160,10 +166,12 @@ static void uart_reset(void) {
Uart.synced = false;
Uart.frame = false;
}
static void uart_init(uint8_t *data) {
Uart.buf = data;
uart_reset();
}
static void uart_bit(uint8_t bit) {
static uint8_t buf = 0xff;
static uint8_t n_buf;
@ -1427,7 +1435,6 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
uint32_t time_0 = GetCountSspClk();
uint32_t t2r_stime = 0, t2r_etime = 0;
uint32_t r2t_stime, r2t_etime = 0;
LED_A_ON();
bool buttonPressed = false;
@ -1717,6 +1724,8 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
bool firstpart = true;
uint8_t sendbyte;
time_rdr = 0;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
AT91C_BASE_SSC->SSC_THR = 0x00;
@ -1755,6 +1764,8 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
}
}
time_rdr = GetCountSspClk();
if (samples) {
if (wait)
*samples = (c + *wait) << 3;
@ -1827,7 +1838,7 @@ void ReaderTransmitIClass(uint8_t *frame, int len) {
// If a response is captured return TRUE
// If it takes too long return FALSE
//-----------------------------------------------------------------------------
static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *elapsed) {
static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples, int *wait) {
// buffer needs to be 512 bytes
// maxLen is not used...
@ -1837,13 +1848,16 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
// Setup UART/DEMOD to receive
DemodIcInit(receivedResponse);
if (elapsed) *elapsed = 0;
// Set FPGA mode to "reader listen mode", no modulation (listen
// only, since we are receiving, not transmitting).
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN);
SpinDelayUs(320); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments.
time_delta = GetCountSspClk() - time_rdr;
SpinDelayUs(g_wait); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments.
time_delta_wait = GetCountSspClk() - time_rdr - time_delta;
uint32_t foo = GetCountSspClk();
// clear RXRDY:
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
@ -1861,15 +1875,16 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
}
// keep tx buffer in a defined state anyway.
/*
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00;
// To make use of exact timing of next command from reader!!
if (elapsed)(*elapsed)++;
}
*/
// Wait for byte be become available in rx holding register
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
if (c >= timeout) return false;
if ( GetCountSspClk() - foo > timeout) return false;
// if (c >= timeout) return false;
c++;
@ -1881,25 +1896,28 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
if (ManchesterDecoding_iclass(b & 0x0f)) {
if (samples)
*samples = c << 3;
time_response = GetCountSspClk() - foo;
return true;
}
}
}
return false;
}
int ReaderReceiveIClass(uint8_t *receivedAnswer) {
int samples = 0;
if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL))
return false;
if (GetIClassAnswer(receivedAnswer, 0, &samples, NULL) == false)
return 0;
rsamples += samples;
LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false);
if (samples == 0)
return false;
return 0;
return Demod.len;
}
@ -1924,7 +1942,7 @@ void setupIclassReader() {
// Now give it time to spin up.
// Signal field is on with the appropriate LED
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
SpinDelay(300);
SpinDelay(500);
StartCountSspClk();
@ -1936,13 +1954,20 @@ bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *re
ReaderTransmitIClass(command, cmdsize);
//iceman - if received size is bigger than expected, we smash the stack here
// since its called with fixed sized arrays
// update/write commadn takes 4ms to 15ms before responding
if ( command[0] == ICLASS_CMD_UPDATE )
g_wait = 15000;
uint8_t got_n = ReaderReceiveIClass(resp);
// 0xBB is the internal debug separator byte..
if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) {
//try again
SpinDelayUs(400);
continue;
}
@ -2396,8 +2421,6 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
if (isOK)
goto out;
SpinDelayUs(400); //iClass (iso15693-2) should timeout after 330us.
// Auth Sequence MUST begin with reading e-purse. (block2)
// Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC)
ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));

View file

@ -1342,8 +1342,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
for (uint16_t i = s_point; i < keyCount; ++i) {
//if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point);
// Allow button press / usb cmd to interrupt device
if (BUTTON_PRESS() && !data_available()) {
goto OUT;
@ -1525,6 +1523,33 @@ OUT:
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
BigBuf_free();
BigBuf_Clear_ext(false);
// special trick ecfill
if (use_flashmem && foundkeys == allkeys) {
uint8_t block[16] = {0};
for (int i = 0; i < sectorcnt; i++) {
uint8_t blockno;
if (i < 32) {
blockno = (i * 4) ^ 0x3;
} else {
blockno = (32 * 4 + (i - 32) * 16) ^ 0xF;
}
// get ST
emlGetMem(block, blockno, 1);
memcpy(block, k_sector[i].keyA, 6);
memcpy(block + 10, k_sector[i].keyB, 6);
emlSetMem_xt(block, blockno, 1, sizeof(block));
}
int oldbg = DBGLEVEL;
DBGLEVEL = DBG_NONE;
MifareECardLoad(sectorcnt, 0);
MifareECardLoad(sectorcnt, 1);
DBGLEVEL = oldbg;
}
} else {
// partial/none keys found
reply_mix(CMD_ACK, foundkeys, 0, 0, 0, 0);
@ -1669,10 +1694,15 @@ void MifareEMemGet(uint8_t blockno, uint8_t blockcnt) {
// Load a card into the emulator memory
//
//-----------------------------------------------------------------------------
int MifareECardLoad(uint32_t arg0, uint32_t arg1) {
int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType) {
int retval = MifareECardLoad(numSectors, keyType);
reply_ng(CMD_HF_MIFARE_EML_LOAD, retval, NULL, 0);
return retval;
}
int MifareECardLoad(uint8_t numSectors, uint8_t keyType) {
uint32_t cuid = 0;
uint8_t numSectors = arg0;
uint8_t keyType = arg1;
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
@ -1683,42 +1713,40 @@ int MifareECardLoad(uint32_t arg0, uint32_t arg1) {
uint8_t uid[10] = {0x00};
LED_A_ON();
LED_B_OFF();
LED_C_OFF();
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
clear_trace();
set_tracing(true);
bool isOK = true;
int retval;
if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
isOK = false;
if (DBGLEVEL >= 1) Dbprintf("Can't select card");
retval = PM3_ESOFT;
if (DBGLEVEL > DBG_ERROR) Dbprintf("Can't select card");
goto out;
}
for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) {
for (uint8_t sectorNo = 0; sectorNo < numSectors; sectorNo++) {
uint64_t ui64Key = emlGetKey(sectorNo, keyType);
if (sectorNo == 0) {
if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
if (DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo);
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {
if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth error", sectorNo);
break;
}
} else {
if (isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
isOK = false;
if (DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
break;
if (mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) {
retval = PM3_ESOFT;
if (DBGLEVEL > DBG_ERROR) Dbprintf("Sector[%2d]. Auth nested error", sectorNo);
goto out;
}
}
for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
if (isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
isOK = false;
if (DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
for (uint8_t blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) {
if (mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) {
retval = PM3_ESOFT;
if (DBGLEVEL > DBG_ERROR) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo);
break;
}
if (isOK) {
if (blockNo < NumBlocksPerSector(sectorNo) - 1) {
emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1);
} else { // sector trailer, keep the keys, set only the AC
@ -1729,22 +1757,19 @@ int MifareECardLoad(uint32_t arg0, uint32_t arg1) {
}
}
}
if (mifare_classic_halt(pcs, cuid))
if (DBGLEVEL >= 1)
if (mifare_classic_halt(pcs, cuid)) {
if (DBGLEVEL > DBG_ERROR)
Dbprintf("Halt error");
}
// ----------------------------- crypto1 destroy
if (DBGLEVEL >= DBG_INFO) DbpString("Emulator fill sectors finished");
out:
crypto1_destroy(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
if (DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED");
set_tracing(false);
return (isOK) ? PM3_SUCCESS : PM3_EUNDEF;
return retval;
}

View file

@ -31,7 +31,8 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da
void MifareEMemClr(void);
void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
int MifareECardLoad(uint32_t arg0, uint32_t arg1);
int MifareECardLoad(uint8_t sectorcnt, uint8_t keytype);
int MifareECardLoadExt(uint8_t numSectors, uint8_t keyType);
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);

View file

@ -73,7 +73,7 @@ ifneq (,$(PM3_SHARE_PATH))
PM3CFLAGS += -DPM3_SHARE_PATH=\"$(PM3_SHARE_PATH)\"
endif
ifneq (,$(findstring MINGW,$(platform)))
PM3CFLAGS += -mno-ms-bitfields
PM3CFLAGS += -mno-ms-bitfields -fexec-charset=cp850
endif
CXXFLAGS ?= -Wall -Werror -O3
PM3CXXFLAGS = $(CXXFLAGS) -I../include

View file

@ -751,12 +751,56 @@ static uint8_t NumBlocksPerSector(uint8_t sectorNo) {
return 16;
}
}
static uint8_t GetSectorFromBlockNo(uint8_t blockNo) {
if (blockNo < 128)
return blockNo / 4;
else
return 32 + ((128 - blockNo) / 16);
}
static char GetFormatFromSector(uint8_t sectorNo) {
switch (sectorNo) {
case MIFARE_MINI_MAXSECTOR:
return '0';
case MIFARE_1K_MAXSECTOR:
return '1';
case MIFARE_2K_MAXSECTOR:
return '2';
case MIFARE_4K_MAXSECTOR:
return '4';
default :
return ' ';
}
}
static int FastDumpWithEcFill(uint8_t numsectors){
PacketResponseNG resp;
mfc_eload_t payload;
payload.sectorcnt = numsectors;
payload.keytype = 0;
// ecfill key A
clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
int res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2000);
if ( res != PM3_SUCCESS) {
}
// ecfill key B
payload.keytype = 1;
clearCommandBuffer();
SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
res = WaitForResponseTimeout(CMD_HF_MIFARE_EML_LOAD, &resp, 2000);
if ( res != PM3_SUCCESS) {
}
return PM3_SUCCESS;
}
static int CmdHF14AMfDump(const char *Cmd) {
uint64_t t1 = msclock();
@ -1242,7 +1286,12 @@ static int CmdHF14AMfNested(const char *Cmd) {
}
PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt);
mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false);
int res = mfCheckKeys_fast(SectorsCnt, true, true, 1, ARRAYLEN(g_mifare_default_keys) + 1, keyBlock, e_sector, false);
if ( res == PM3_SUCCESS ) {
// all keys found
PrintAndLogEx(SUCCESS, "Fast check found all keys");
goto jumptoend;
}
uint64_t t2 = msclock() - t1;
PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", ARRAYLEN(g_mifare_default_keys), (float)t2 / 1000.0);
@ -1329,6 +1378,7 @@ static int CmdHF14AMfNested(const char *Cmd) {
}
}
jumptoend:
//print them
printKeyTable(SectorsCnt, e_sector);
@ -1612,56 +1662,69 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
bool legacy_mfchk = false;
bool prng_type = false;
bool verbose = false;
bool has_filename = false;
bool errors = false;
// Parse the options given by the user
ctmp = tolower(param_getchar(Cmd, 0));
while ((ctmp = param_getchar(Cmd, cmdp))) {
while ( (ctmp = param_getchar(Cmd, cmdp)) && !errors ) {
switch (tolower(ctmp)) {
case 'h':
return usage_hf14_autopwn();
case 'f':
if (param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE) {
PrintAndLogEx(FAILED, "Filename too long");
errors = true;
} else {
has_filename = true;
}
cmdp ++;
cmdp += 2;
break;
case 'l':
legacy_mfchk = true;
cmdp++;
break;
case 'v':
verbose = true;
cmdp++;
break;
case '*':
// Get the number of sectors
sectors_cnt = NumOfSectors(param_getchar(Cmd, cmdp + 1));
block_cnt = NumOfBlocks(param_getchar(Cmd, cmdp + 1));
cmdp ++;
cmdp += 2;
break;
case 'k':
// Get the known block number
if (param_getchar(Cmd, cmdp + 1) == 0x00) {
PrintAndLogEx(WARNING, "Sector number is missing");
return PM3_EINVARG;
errors = true;
break;
}
blockNo = param_get8(Cmd, cmdp + 1);
// Get the knonwn block type
ctmp = tolower(param_getchar(Cmd, cmdp + 2));
if (ctmp != 'a' && ctmp != 'b') {
PrintAndLogEx(WARNING, "Key type must be A or B");
return PM3_EINVARG;
errors = true;
break;
}
if (ctmp != 'a') {
keyType = 1;
}
// Get the known block key
if (param_gethex(Cmd, cmdp + 3, key, 12)) {
PrintAndLogEx(WARNING, "Key must include 12 HEX symbols");
errors = true;
return PM3_EINVARG;
}
know_target_key = true;
cmdp += 3;
case 's':
slow = true;
cmdp++;
break;
case 'i':
SetSIMDInstr(SIMD_AUTO);
@ -1695,7 +1758,10 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp);
return usage_hf14_autopwn();
}
cmdp++;
}
if ( errors ) {
return usage_hf14_autopwn();
}
// Create the key storage stucture
@ -1732,19 +1798,20 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
// check the user supplied key
if (know_target_key == false)
PrintAndLogEx(WARNING, "No known key was supplied, key recovery might fail");
PrintAndLogEx(WARNING, "no known key was supplied, key recovery might fail");
else {
if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= START KNOWN KEY ATTACK ======================="));
if (verbose) {
PrintAndLogEx(INFO, _YELLOW_("======================= START KNOWN KEY ATTACK ======================="));
}
if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) == PM3_SUCCESS) {
PrintAndLogEx(INFO, "Using valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)",
PrintAndLogEx(INFO, "target sector:%3u key type: %c -- using valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)",
blockNo,
keyType ? 'B' : 'A',
sprint_hex(key, sizeof(key))
);
// Store the key for the nested / hardnested attack (if supplied by the user)
e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6);
e_sector[blockNo].foundKey[keyType] = 'U';
e_sector[blockNo].Key[keyType] = key64;
} else {
know_target_key = false;
PrintAndLogEx(FAILED, "Key is wrong. Can't authenticate to sector:"_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"),
@ -1752,8 +1819,9 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
keyType ? 'B' : 'A',
sprint_hex(key, sizeof(key))
);
PrintAndLogEx(WARNING, "Falling back to dictionary");
PrintAndLogEx(WARNING, "falling back to dictionary");
}
// Check if the user supplied key is used by other sectors
for (int i = 0; i < sectors_cnt; i++) {
for (int j = 0; j < 2; j++) {
@ -1768,13 +1836,13 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
know_target_key = true;
blockNo = i;
keyType = j;
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)",
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)",
i,
j ? 'B' : 'A',
sprint_hex(key, sizeof(key))
);
} else {
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
i,
j ? 'B' : 'A',
sprint_hex(key, sizeof(key))
@ -1787,16 +1855,21 @@ static int CmdHF14AMfAutoPWN(const char *Cmd) {
if (verbose) PrintAndLogEx(INFO, _YELLOW_("======================= STOP KNOWN KEY ATTACK ======================="));
}
bool load_success = true;
// Load the dictionary
if (strlen(filename) != 0) {
if (has_filename) {
int res = loadFileDICTIONARY_safe(filename, (void**) &keyBlock, 6, &key_cnt);
if (res != PM3_SUCCESS || key_cnt <= 0 || keyBlock == NULL) {
if (res != PM3_SUCCESS || key_cnt == 0 || keyBlock == NULL) {
PrintAndLogEx(FAILED, "An error occurred while loading the dictionary! (we will use the default keys now)");
if (keyBlock != NULL) free(keyBlock);
goto useDefaultKeys;
if (keyBlock != NULL)
free(keyBlock);
load_success = false;
}
} else {
useDefaultKeys:
}
if ( has_filename == false || load_success == false ) {
keyBlock = calloc(ARRAYLEN(g_mifare_default_keys), 6);
if (keyBlock == NULL) {
free(e_sector);
@ -1807,6 +1880,7 @@ useDefaultKeys:
num_to_bytes(g_mifare_default_keys[cnt], 6, keyBlock + cnt * 6);
}
key_cnt = ARRAYLEN(g_mifare_default_keys);
PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from hardcoded default array", key_cnt);
}
// Use the dictionary to find sector keys on the card
@ -1833,10 +1907,12 @@ useDefaultKeys:
printf("\n");
fflush(stdout);
} else {
int chunksize = key_cnt > (PM3_CMD_DATA_SIZE / 6) ? (PM3_CMD_DATA_SIZE / 6) : key_cnt;
bool firstChunk = true, lastChunk = false;
for (uint8_t strategy = 1; strategy < 3; strategy++) {
PrintAndLogEx(INFO, "Running strategy %u", strategy);
PrintAndLogEx(INFO, "running strategy %u", strategy);
// main keychunk loop
for (int i = 0; i < key_cnt; i += chunksize) {
@ -1855,7 +1931,7 @@ useDefaultKeys:
if (firstChunk)
firstChunk = false;
// all keys, aborted
if (res == 0 || res == 2) {
if (res == PM3_SUCCESS) {
i = key_cnt;
strategy = 3;
break; // Exit the loop
@ -1875,20 +1951,19 @@ useDefaultKeys:
e_sector[i].foundKey[j] = 'D';
num_to_bytes(e_sector[i].Key[j], 6, tmp_key);
// Store valid credentials for the nested / hardnested attack if none exist
if (know_target_key == false) {
num_to_bytes(e_sector[i].Key[j], 6, key);
know_target_key = true;
blockNo = i;
keyType = j;
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)",
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)",
i,
j ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key))
);
} else {
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
i,
j ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key))
@ -1926,21 +2001,11 @@ useDefaultKeys:
PrintAndLogEx(SUCCESS, "\nFound valid key: %012" PRIx64 "\n", key64);
break;
}
num_to_bytes(key64, 6, key);
// Check if the darkside key is valid
if (mfCheckKeys(FirstBlockOfSector(blockNo), keyType, true, 1, key, &key64) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "The key generated by the darkside attack is not valid!"
_RED_("%3d") " key type: "_RED_("%c") " key: " _RED_("%s"),
blockNo,
keyType ? 'B' : 'A',
sprint_hex(key, sizeof(key))
);
goto noValidKeyFound;
}
// Store the keys
e_sector[blockNo].Key[keyType] = bytes_to_num(key, 6);
e_sector[blockNo].Key[keyType] = key64;
e_sector[blockNo].foundKey[keyType] = 'S';
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s") "(used for nested / hardnested attack)",
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "] (used for nested / hardnested attack)",
blockNo,
keyType ? 'B' : 'A',
sprint_hex(key, sizeof(key))
@ -1953,6 +2018,7 @@ noValidKeyFound:
return PM3_ESOFT;
}
}
free(keyBlock);
// Clear the needed variables
num_to_bytes(0, 6, tmp_key);
@ -1979,7 +2045,7 @@ noValidKeyFound:
if (mfCheckKeys(FirstBlockOfSector(i), j, true, 1, tmp_key, &key64) == PM3_SUCCESS) {
e_sector[i].Key[j] = bytes_to_num(tmp_key, 6);
e_sector[i].foundKey[j] = 'R';
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
i,
j ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key))
@ -1995,7 +2061,7 @@ noValidKeyFound:
if (e_sector[current_sector_i].foundKey[0] && !e_sector[current_sector_i].foundKey[1]) {
if (verbose) {
PrintAndLogEx(INFO, _YELLOW_("======================= START READ B KEY ATTACK ======================="));
PrintAndLogEx(INFO, "Reading B key: sector: %3d key type: %c",
PrintAndLogEx(INFO, "reading B key: sector: %3d key type: %c",
current_sector_i,
current_key_type_i ? 'B' : 'A');
}
@ -2021,13 +2087,13 @@ noValidKeyFound:
e_sector[current_sector_i].foundKey[current_key_type_i] = 'A';
e_sector[current_sector_i].Key[current_key_type_i] = key64;
num_to_bytes(key64, 6, tmp_key);
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
current_sector_i,
current_key_type_i ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key))
);
} else {
if (verbose) PrintAndLogEx(WARNING, "Unknown B key: sector: %3d key type: %c (reading the B key was not possible, maybe due to insufficient access rights) ",
if (verbose) PrintAndLogEx(WARNING, "unknown B key: sector: %3d key type: %c (reading the B key was not possible, maybe due to insufficient access rights) ",
current_sector_i,
current_key_type_i ? 'B' : 'A'
);
@ -2043,7 +2109,7 @@ skipReadBKey:
uint8_t retries = 0;
if (verbose) {
PrintAndLogEx(INFO, _YELLOW_("======================= START NESTED ATTACK ======================="));
PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c",
PrintAndLogEx(INFO, "sector no: %3d, target key type: %c",
current_sector_i,
current_key_type_i ? 'B' : 'A');
}
@ -2089,7 +2155,7 @@ tryNested:
tryHardnested: // If the nested attack fails then we try the hardnested attack
if (verbose) {
PrintAndLogEx(INFO, _YELLOW_("======================= START HARDNESTED ATTACK ======================="));
PrintAndLogEx(INFO, "Sector no: %3d, target key type: %c, Slow: %s",
PrintAndLogEx(INFO, "sector no: %3d, target key type: %c, Slow: %s",
current_sector_i,
current_key_type_i ? 'B' : 'A',
slow ? "Yes" : "No");
@ -2121,7 +2187,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
}
// Check if the key was found
if (e_sector[current_sector_i].foundKey[current_key_type_i]) {
PrintAndLogEx(SUCCESS, "Found valid key: sector: %3d key type: %c key: " _YELLOW_("%s"),
PrintAndLogEx(SUCCESS, "target sector:%3u key type: %c -- found valid key [ " _YELLOW_("%s") "]",
current_sector_i,
current_key_type_i ? 'B' : 'A',
sprint_hex(tmp_key, sizeof(tmp_key))
@ -2134,7 +2200,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
// Show the results to the user
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Found Keys:");
PrintAndLogEx(INFO, "found Keys:");
char strA[12 + 1] = {0};
char strB[12 + 1] = {0};
@ -2172,10 +2238,11 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
);
// Dump the keys
PrintAndLogEx(INFO, "\nSaving keys");
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "saving keys");
createMfcKeyDump(sectors_cnt, e_sector, GenerateFilename("hf-mf-", "-key.bin"));
PrintAndLogEx(SUCCESS, "Transferring keys to simulator memory (Cmd Error: 04 can occur)");
PrintAndLogEx(SUCCESS, "transferring keys to simulator memory (Cmd Error: 04 can occur)");
for (current_sector_i = 0; current_sector_i < sectors_cnt; current_sector_i++) {
mfEmlGetMem(block, current_sector_i, 1);
@ -2187,13 +2254,8 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
mfEmlSetMem(block, FirstBlockOfSector(current_sector_i) + NumBlocksPerSector(current_sector_i) - 1, 1);
}
// using ecfill trick, keys already in emulator mem, load data using Key A
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, sectors_cnt, 0, 0, NULL, 0);
// using ecfill trick, keys already in emulator mem, load data using Key B
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, sectors_cnt, 1, 0, NULL, 0);
// use ecfill trick
FastDumpWithEcFill(sectors_cnt);
bytes = block_cnt * MFBLOCK_SIZE;
dump = calloc(bytes, sizeof(uint8_t));
@ -2204,7 +2266,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
}
memset(dump, 0, bytes);
PrintAndLogEx(INFO, "Downloading the card content from emulator memory");
PrintAndLogEx(INFO, "downloading the card content from emulator memory");
if (!GetFromDevice(BIG_BUF_EML, dump, bytes, 0, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(ERR, "Fail, transfer from device time-out");
free(e_sector);
@ -2226,7 +2288,7 @@ tryHardnested: // If the nested attack fails then we try the hardnested attack
// Generate and show statistics
t1 = msclock() - t1;
PrintAndLogEx(INFO, "Autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0);
PrintAndLogEx(INFO, "autopwn execution time: " _YELLOW_("%.0f") " seconds", (float)t1 / 1000.0);
free(dump);
free(e_sector);
@ -2436,7 +2498,7 @@ static int CmdHF14AMfChk_fast(const char *Cmd) {
firstChunk = false;
// all keys, aborted
if (res == 0 || res == 2)
if (res == PM3_SUCCESS || res == 2)
goto out;
} // end chunks of keys
firstChunk = true;
@ -2464,6 +2526,13 @@ out:
printKeyTable(sectorsCnt, e_sector);
if ( use_flashmemory && found_keys == (sectorsCnt << 1) ) {
PrintAndLogEx(SUCCESS, "Card dumped aswell. run " _YELLOW_("`%s %c`"),
"hf mf esave",
GetFormatFromSector(sectorsCnt)
);
}
if (transferToEml) {
// fast push mode
conn.block_after_ACK = true;
@ -2482,6 +2551,10 @@ out:
mfEmlSetMem(block, blockno, 1);
}
PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory");
if ( found_keys == (sectorsCnt << 1) ) {
FastDumpWithEcFill(sectorsCnt);
}
}
if (createDumpFile) {
@ -3459,8 +3532,12 @@ static int CmdHF14AMfECFill(const char *Cmd) {
}
PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B');
mfc_eload_t payload;
payload.sectorcnt = numSectors;
payload.keytype = keyType;
clearCommandBuffer();
SendCommandMIX(CMD_HF_MIFARE_EML_LOAD, numSectors, keyType, 0, NULL, 0);
SendCommandNG(CMD_HF_MIFARE_EML_LOAD, (uint8_t *)&payload, sizeof(payload));
return PM3_SUCCESS;
}

View file

@ -619,16 +619,14 @@ int CmdHW(const char *Cmd) {
void pm3_version(bool verbose, bool oneliner) {
if (oneliner) {
char msg[70];
memset(msg, 0x00, sizeof(msg));
strcat(msg, "Client: RRG/Iceman compiled with ");
#if defined(__clang__)
strcat(msg + strlen(msg), _YELLOW_("Clang/LLVM "__VERSION__));
# define PM3CLIENTCOMPILER "Clang/LLVM "
#elif defined(__GNUC__) || defined(__GNUG__)
strcat(msg + strlen(msg), _YELLOW_("GCC "__VERSION__));
# define PM3CLIENTCOMPILER "GCC "
#endif
PrintAndLogEx(NORMAL, "%s", msg);
if (oneliner) {
PrintAndLogEx(NORMAL, "Client: RRG/Iceman compiled with " _YELLOW_(PM3CLIENTCOMPILER __VERSION__));
return;
}
@ -644,12 +642,7 @@ void pm3_version(bool verbose, bool oneliner) {
PrintAndLogEx(NORMAL, "\n" _BLUE_(" [ Proxmark3 RFID instrument ]") "\n");
PrintAndLogEx(NORMAL, "\n [ CLIENT ]");
PrintAndLogEx(NORMAL, " client: RRG/Iceman"); // TODO version info?
#if defined(__clang__)
PrintAndLogEx(NORMAL, " compiled with Clang/LLVM "__VERSION__);
#elif defined(__GNUC__) || defined(__GNUG__)
PrintAndLogEx(NORMAL, " compiled with GCC "__VERSION__);
#endif
PrintAndLogEx(NORMAL, " compiled with " PM3CLIENTCOMPILER __VERSION__);
PrintAndLogEx(NORMAL, "\n [ PROXMARK RDV4 ]");
PrintAndLogEx(NORMAL, " external flash: %s", IfPm3Flash() ? _GREEN_("present") : _YELLOW_("absent"));
PrintAndLogEx(NORMAL, " smartcard reader: %s", IfPm3Smartcard() ? _GREEN_("present") : _YELLOW_("absent"));

View file

@ -2129,9 +2129,11 @@ static int CmdT55xxChkPwds(const char *Cmd) {
uint16_t keycount = 0;
int res = loadFileDICTIONARY_safe(filename, (void**) &keyBlock, 4, &keycount);
if (res != PM3_SUCCESS || keycount <= 0 || keyBlock == NULL) {
if (res != PM3_SUCCESS || keycount == 0 || keyBlock == NULL) {
PrintAndLogEx(WARNING, "No keys found in file");
if (keyBlock != NULL) free(keyBlock);
if (keyBlock != NULL)
free(keyBlock);
return PM3_ESOFT;
}

View file

@ -283,9 +283,9 @@ int saveFileJSON(const char *preferredName, JSONFileType ftype, uint8_t *data, s
}
case jsfIclass: {
JsonSaveStr(root, "FileType", "iclass");
uint8_t uid[8] = {0};
memcpy(uid, data, 8);
JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid));
uint8_t csn[8] = {0};
memcpy(csn, data, 8);
JsonSaveBufAsHexCompact(root, "$.Card.CSN", csn, sizeof(csn));
for (size_t i = 0; i < (datalen / 8); i++) {
char path[PATH_MAX_LENGTH] = {0};
@ -316,13 +316,13 @@ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) {
int i;
if (fptr == NULL) {
return 1;
return PM3_EINVARG;
}
FILE *fkeys = fopen(fptr, "wb");
if (fkeys == NULL) {
PrintAndLogEx(WARNING, "Could not create file " _YELLOW_("%s"), fptr);
return 1;
return PM3_EFILE;
}
PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_("%s")"...", fptr);
@ -338,14 +338,14 @@ int createMfcKeyDump(uint8_t sectorsCnt, sector_t *e_sector, char *fptr) {
fclose(fkeys);
PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_("%s")" --> 0xffffffffffff has been inserted for unknown keys.", fptr);
return 0;
return PM3_SUCCESS;
}
int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) {
if (data == NULL) return 1;
char *fileName = filenamemcopy(preferredName, suffix);
if (fileName == NULL) return 1;
if (fileName == NULL) return PM3_EINVARG;
int retval = PM3_SUCCESS;
@ -363,23 +363,24 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m
if (fsize <= 0) {
PrintAndLogEx(FAILED, "error, when getting filesize");
retval = 1;
retval = PM3_EFILE;
goto out;
}
uint8_t *dump = calloc(fsize, sizeof(uint8_t));
if (!dump) {
PrintAndLogEx(FAILED, "error, cannot allocate memory");
retval = 2;
retval = PM3_EMALLOC;
goto out;
}
size_t bytes_read = fread(dump, 1, fsize, f);
fclose(f);
if (bytes_read != fsize) {
PrintAndLogEx(FAILED, "error, bytes read mismatch file size");
free(dump);
retval = 3;
retval = PM3_EFILE;
goto out;
}
@ -396,9 +397,7 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m
*datalen = bytes_read;
out:
fclose(f);
free(fileName);
return retval;
}
@ -432,7 +431,7 @@ int loadFileEML(const char *preferredName, void *data, size_t *datalen) {
break;
fclose(f);
PrintAndLogEx(FAILED, "File reading error.");
retval = 2;
retval = PM3_EFILE;
goto out;
}
@ -471,13 +470,13 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_
root = json_load_file(fileName, 0, &error);
if (!root) {
PrintAndLogEx(ERR, "ERROR: json " _YELLOW_("%s") " error on line %d: %s", fileName, error.line, error.text);
retval = 2;
retval = PM3_ESOFT;
goto out;
}
if (!json_is_object(root)) {
PrintAndLogEx(ERR, "ERROR: Invalid json " _YELLOW_("%s") " format. root must be an object.", fileName);
retval = 3;
retval = PM3_ESOFT;
goto out;
}
@ -493,7 +492,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_
size_t sptr = 0;
for (int i = 0; i < 256; i++) {
if (sptr + 16 > maxdatalen) {
retval = 5;
retval = PM3_EMALLOC;
goto out;
}
@ -515,7 +514,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_
size_t sptr = 0;
for (int i = 0; i < 256; i++) {
if (sptr + 4 > maxdatalen) {
retval = 5;
retval = PM3_EMALLOC;
goto out;
}
@ -537,7 +536,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_
size_t sptr = 0;
for (size_t i = 0; i < (maxdatalen / 4); i++) {
if (sptr + 4 > maxdatalen) {
retval = 5;
retval = PM3_EMALLOC;
goto out;
}
@ -559,7 +558,7 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_
size_t sptr = 0;
for (size_t i = 0; i < (maxdatalen / 8); i++) {
if (sptr + 8 > maxdatalen) {
retval = 5;
retval = PM3_EMALLOC;
goto out;
}
@ -651,10 +650,8 @@ out:
int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t keylen, uint16_t *keycnt) {
int block_size = 512;
int allocation_size = block_size;
size_t counter = 0;
int retval = PM3_SUCCESS;
char *path;
if (searchFile(&path, DICTIONARIES_SUBDIR, preferredName, ".dic") != PM3_SUCCESS)
return PM3_EFILE;
@ -667,14 +664,20 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key
keylen = 6;
}
size_t mem_size;
size_t block_size = 10 * keylen;
// double up since its chars
keylen <<= 1;
char line[255];
// allocate some space for the dictionary
*pdata = calloc(keylen * allocation_size, sizeof(uint8_t));
if (*pdata == NULL) return PM3_EFILE;
*pdata = calloc( block_size , sizeof(uint8_t));
if (*pdata == NULL)
return PM3_EFILE;
mem_size = block_size;
FILE *f = fopen(path, "r");
if (!f) {
@ -684,15 +687,17 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key
// read file
while (fgets(line, sizeof(line), f)) {
// check if we have enough space (if not allocate more)
if ((*keycnt) >= allocation_size) {
allocation_size += block_size;
*pdata = realloc(*pdata, keylen * allocation_size * sizeof(uint8_t));
if ( (*keycnt * (keylen >> 1) ) >= mem_size ) {
mem_size += block_size;
*pdata = realloc(*pdata, mem_size);
if (*pdata == NULL) {
return PM3_EFILE;
} else {
// zero the new memory (safety first)
memset(*pdata + allocation_size - block_size, 0, block_size);
memset(*pdata + (mem_size - block_size), 0, block_size);
}
}
@ -714,10 +719,11 @@ int loadFileDICTIONARY_safe(const char *preferredName, void **pdata, uint8_t key
uint64_t key = strtoull(line, NULL, 16);
num_to_bytes(key, keylen >> 1, *pdata + counter);
num_to_bytes(key, keylen >> 1, *pdata + (*keycnt * (keylen >> 1)) );
(*keycnt)++;
memset(line, 0, sizeof(line));
counter += (keylen >> 1);
}
fclose(f);
PrintAndLogEx(SUCCESS, "loaded " _GREEN_("%2d") "keys from dictionary file " _YELLOW_("%s"), *keycnt, path);
@ -759,13 +765,14 @@ int convertOldMfuDump(uint8_t **dump, size_t *dumplen) {
return PM3_SUCCESS;
}
static int filelist(const char *path, const char *ext, bool last) {
static int filelist(const char *path, const char *ext, bool last, bool tentative) {
struct dirent **namelist;
int n;
n = scandir(path, &namelist, NULL, alphasort);
if (n == -1) {
PrintAndLogEx(NORMAL, "%s── %s => NOT FOUND", last ? "" : "", path);
if (!tentative)
PrintAndLogEx(NORMAL, "%s── %s", last ? "" : "", path);
return PM3_EFILE;
}
@ -781,25 +788,29 @@ static int filelist(const char *path, const char *ext, bool last) {
}
int searchAndList(const char *pm3dir, const char *ext) {
// display in same order as searched by searchFile
// try pm3 dirs in current workdir (dev mode)
if (get_my_executable_directory() != NULL) {
char script_directory_path[strlen(get_my_executable_directory()) + strlen(pm3dir) + 1];
strcpy(script_directory_path, get_my_executable_directory());
strcat(script_directory_path, pm3dir);
filelist(script_directory_path, ext, false);
filelist(script_directory_path, ext, false, true);
}
// try pm3 dirs in user .proxmark3 (user mode)
char *userpath = getenv("HOME");
if (userpath != NULL) {
char script_directory_path[strlen(userpath) + strlen(PM3_USER_DIRECTORY) + strlen(pm3dir) + 1];
strcpy(script_directory_path, userpath);
strcat(script_directory_path, PM3_USER_DIRECTORY);
strcat(script_directory_path, pm3dir);
filelist(script_directory_path, ext, false);
filelist(script_directory_path, ext, false, false);
}
// try pm3 dirs in pm3 installation dir (install mode)
{
char script_directory_path[strlen(PM3_SHARE_PATH) + strlen(pm3dir) + 1];
strcpy(script_directory_path, PM3_SHARE_PATH);
strcat(script_directory_path, pm3dir);
filelist(script_directory_path, ext, true);
filelist(script_directory_path, ext, true, false);
}
return PM3_SUCCESS;
}
@ -885,6 +896,8 @@ out:
}
int searchFile(char **foundpath, const char *pm3dir, const char *searchname, const char *suffix) {
if (foundpath == NULL)
return PM3_EINVARG;
char *filename = filenamemcopy(searchname, suffix);
if (filename == NULL) return PM3_EMALLOC;
int res = searchFinalFile(foundpath, pm3dir, filename);

View file

@ -62,6 +62,13 @@ typedef enum {
// jsfT55xx,
} JSONFileType;
typedef enum {
BIN = 0,
EML,
JSON,
DICTIONARY,
} DumpFileType_t;
int fileExists(const char *filename);
/**

View file

@ -209,7 +209,8 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
// initialize storage for found keys
icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t));
if (tmp == NULL)
return 1;
return PM3_EMALLOC;
memcpy(tmp, resp.data.asBytes, sectorsCnt * sizeof(icesector_t));
for (int i = 0; i < sectorsCnt; i++) {
@ -227,11 +228,11 @@ int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk,
free(tmp);
if (curr_keys == sectorsCnt * 2)
return 0;
return PM3_SUCCESS;
if (lastChunk)
return 1;
return PM3_ESOFT;
}
return 1;
return PM3_ESOFT;
}
// PM3 imp of J-Run mf_key_brute (part 2)

View file

@ -31,7 +31,7 @@
static void showBanner(void) {
PrintAndLogEx(NORMAL, "\n");
#if defined(__linux__) || (__APPLE__)
#if defined(__linux__) || (__APPLE__) || (_WIN32)
PrintAndLogEx(NORMAL, _BLUE_("██████╗ ███╗ ███╗ ████╗ ") " ...iceman fork");
PrintAndLogEx(NORMAL, _BLUE_("██╔══██╗████╗ ████║ ══█║") " ...dedicated to " _BLUE_("RDV40"));
PrintAndLogEx(NORMAL, _BLUE_("██████╔╝██╔████╔██║ ████╔╝"));
@ -102,8 +102,13 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
PrintAndLogEx(ERR, "could not open " _YELLOW_("%s") "...", script_cmds_file);
}
read_history(".history");
char *my_history_path = NULL;
if (searchHomeFilePath(&my_history_path, PROXHISTORY, true) != PM3_SUCCESS) {
PrintAndLogEx(ERR, "could not create $HOME/" PROXHISTORY ", no history will be recorded");
my_history_path = NULL;
} else {
read_history(my_history_path);
}
// loops every time enter is pressed...
while (1) {
bool printprompt = false;
@ -220,8 +225,10 @@ main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop) {
if (sf)
fclose(sf);
write_history(".history");
if (my_history_path) {
write_history(my_history_path);
free(my_history_path);
}
if (cmd) {
free(cmd);
cmd = NULL;

View file

@ -18,6 +18,8 @@
#define PROXPROMPT_USB "[usb] pm3 --> "
#define PROXPROMPT_FPC "[fpc] pm3 --> "
#define PROXPROMPT_OFFLINE "[offline] pm3 --> "
#define PROXHISTORY "history.txt"
#define PROXLOG "log_%Y%m%d.txt"
#ifdef __cplusplus
extern "C" {

View file

@ -24,7 +24,13 @@
#include <readline/readline.h>
#include <complex.h>
#include "util.h"
#include "proxmark3.h" // PROXLOG
#include "fileutils.h"
#include "pm3_cmd.h"
#ifdef _WIN32
# include <direct.h> // _mkdir
#endif
#include <time.h>
session_arg_t session;
double CursorScaleFactor = 1;
@ -36,9 +42,46 @@ bool GridLocked = false;
bool showDemod = true;
pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER;
static const char *logfilename = "proxmark3.log";
static void fPrintAndLog(FILE *stream, const char *fmt, ...);
// needed by flasher, so let's put it here instead of fileutils.c
int searchHomeFilePath(char **foundpath, const char *filename, bool create_home) {
if (foundpath == NULL)
return PM3_EINVARG;
char *user_path = getenv("HOME");
if (user_path == NULL)
return PM3_EFILE;
char *path = calloc(strlen(user_path) + strlen(PM3_USER_DIRECTORY) + 1, sizeof(char));
if (path == NULL)
return PM3_EMALLOC;
strcpy(path, user_path);
strcat(path, PM3_USER_DIRECTORY);
// Mingw: _stat fails on mangled HOME path /pm3 => C:\ProxSpace\pm3, while stat works fine
struct stat st;
int result = stat(path, &st);
if ((result != 0) && create_home) {
#ifdef _WIN32
if (_mkdir(path)) {
#else
if (mkdir(path, 0700)) {
#endif
free(path);
return PM3_EFILE;
}
}
if (filename == NULL) {
*foundpath = path;
return PM3_SUCCESS;
}
path = realloc(path, (strlen(user_path) + strlen(PM3_USER_DIRECTORY) + strlen(filename) + 1) * sizeof(char));
strcat(path, filename);
*foundpath = path;
return PM3_SUCCESS;
}
void PrintAndLogOptions(const char *str[][2], size_t size, size_t space) {
char buff[2000] = "Options:\n";
char format[2000] = "";
@ -166,10 +209,24 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
pthread_mutex_lock(&print_lock);
if (logging && !logfile) {
logfile = fopen(logfilename, "a");
if (!logfile) {
fprintf(stderr, "Can't open logfile, logging disabled!\n");
char *my_logfile_path = NULL;
char filename[40];
struct tm *timenow;
time_t now = time(NULL);
timenow = gmtime(&now);
strftime(filename, sizeof(filename), PROXLOG, timenow);
if (searchHomeFilePath(&my_logfile_path, filename, true) != PM3_SUCCESS) {
fprintf(stderr, "Could not create $HOME/.proxmark3/%s, no log will be recorded\n", filename);
my_logfile_path = NULL;
logging = 0;
} else {
logfile = fopen(my_logfile_path, "a");
if (logfile == NULL) {
fprintf(stderr, "Can't open logfile %s, logging disabled!\n", my_logfile_path);
logging = 0;
}
printf("Session is logged into %s\n", my_logfile_path);
free(my_logfile_path);
}
}
@ -228,10 +285,6 @@ static void fPrintAndLog(FILE *stream, const char *fmt, ...) {
pthread_mutex_unlock(&print_lock);
}
void SetLogFilename(char *fn) {
logfilename = fn;
}
void SetFlushAfterWrite(bool value) {
flushAfterWrite = value;
}

View file

@ -39,7 +39,6 @@ void ShowGraphWindow(void);
void RepaintGraphWindow(void);
void PrintAndLogOptions(const char *str[][2], size_t size, size_t space);
void PrintAndLogEx(logLevel_t level, const char *fmt, ...);
void SetLogFilename(char *fn);
void SetFlushAfterWrite(bool value);
void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter);
@ -49,6 +48,8 @@ extern uint32_t CursorCPos, CursorDPos;
extern bool GridLocked;
extern bool showDemod;
int searchHomeFilePath(char **foundpath, const char *filename, bool create_home);
extern pthread_mutex_t print_lock;
void iceIIR_Butterworth(int *data, const size_t len);

View file

@ -229,6 +229,10 @@ typedef struct {
uint8_t key[6];
} PACKED mf_readblock_t;
typedef struct {
uint8_t sectorcnt;
uint8_t keytype;
} PACKED mfc_eload_t;
// For the bootloader
#define CMD_DEVICE_INFO 0x0000