CHG: 'mem load' - the possibility to upload default_iclass_keys.dic, default_keys.dic, default_pwd.dic to predefined flashmemory sections. These will be used in pwd / key checking algorithms on device.

CHG: 'script run read_pwd_mem.lua' - script now can print those uploaded dictionary files.

How to upload
pm3 --> mem load f default_iclass_keys i
pm3 --> mem load f default_keys m
pm3 --> mem load f default_pwd t

How to validate / view
PM3 -->scr run read_pwd_mem -o 237568 -k 8
pm3 -->scr run read_pwd_mem -o 241664 -k 6
pm3 -->scr run read_pwd_mem -o 245760 -k 4
This commit is contained in:
iceman1001 2019-01-01 18:01:40 +01:00
commit 0fb0c35308
9 changed files with 276 additions and 65 deletions

View file

@ -1286,6 +1286,16 @@ void UsbPacketReceived(uint8_t *packet, int len) {
break; break;
} }
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
if ( startidx == DEFAULT_T55XX_KEYS_OFFSET )
Flash_Erase4k(3, 0xC);
else if (startidx == DEFAULT_MF_KEYS_OFFSET )
Flash_Erase4k(3, 0xB);
else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET)
Flash_Erase4k(3, 0xA);
Flash_CheckBusy(BUSY_TIMEOUT); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();

View file

@ -50,13 +50,19 @@ int usage_flashmem_read(void){
} }
int usage_flashmem_load(void){ int usage_flashmem_load(void){
PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device");
PrintAndLogEx(NORMAL, "Usage: mem load o <offset> f <file name>"); PrintAndLogEx(NORMAL, "Usage: mem load o <offset> f <file name> m t i");
PrintAndLogEx(NORMAL, " o <offset> : offset in memory"); PrintAndLogEx(NORMAL, " o <offset> : offset in memory");
PrintAndLogEx(NORMAL, " f <filename> : file name"); PrintAndLogEx(NORMAL, " f <filename> : file name");
PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)");
PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)");
PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)");
PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "");
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0
PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024
PrintAndLogEx(NORMAL, " mem load f default_keys m");
PrintAndLogEx(NORMAL, " mem load f default_pwd t");
PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i");
return 0; return 0;
} }
int usage_flashmem_save(void){ int usage_flashmem_save(void){
@ -155,6 +161,7 @@ int CmdFlashMemLoad(const char *Cmd){
char filename[FILE_PATH_SIZE] = {0}; char filename[FILE_PATH_SIZE] = {0};
bool errors = false; bool errors = false;
uint8_t cmdp = 0; uint8_t cmdp = 0;
Dictionary_t d = DICTIONARY_NONE;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
@ -172,6 +179,18 @@ int CmdFlashMemLoad(const char *Cmd){
start_index = param_get32ex(Cmd, cmdp+1, 0, 10); start_index = param_get32ex(Cmd, cmdp+1, 0, 10);
cmdp += 2; cmdp += 2;
break; break;
case 'm':
d = DICTIONARY_MIFARE;
cmdp++;
break;
case 't':
d = DICTIONARY_T55XX;
cmdp++;
break;
case 'i':
d = DICTIONARY_ICLASS;
cmdp++;
break;
default: default:
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
errors = true; errors = true;
@ -182,9 +201,48 @@ int CmdFlashMemLoad(const char *Cmd){
//Validations //Validations
if (errors || cmdp == 0 ) return usage_flashmem_load(); if (errors || cmdp == 0 ) return usage_flashmem_load();
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t));
size_t datalen = 0; size_t datalen = 0;
int res = loadFile(filename, "bin", data, &datalen); uint16_t keycount = 0;
int res = 0;
uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t));
switch (d) {
case DICTIONARY_MIFARE:
start_index = DEFAULT_MF_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount );
if ( res || !keycount) {
free(data);
return 1;
}
data[0] = (keycount >> 0) & 0xFF;
data[1] = (keycount >> 8) & 0xFF;
datalen += 2;
break;
case DICTIONARY_T55XX:
start_index = DEFAULT_T55XX_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount );
if ( res || !keycount) {
free(data);
return 1;
}
data[0] = (keycount >> 0) & 0xFF;
data[1] = (keycount >> 8) & 0xFF;
datalen += 2;
break;
case DICTIONARY_ICLASS:
start_index = DEFAULT_ICLASS_KEYS_OFFSET;
res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount );
if ( res || !keycount) {
free(data);
return 1;
}
data[0] = (keycount >> 0) & 0xFF;
data[1] = (keycount >> 8) & 0xFF;
datalen += 2;
break;
default:
res = loadFile(filename, "bin", data, &datalen);
//int res = loadFileEML( filename, "eml", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen);
if ( res ) { if ( res ) {
free(data); free(data);
@ -196,6 +254,8 @@ int CmdFlashMemLoad(const char *Cmd){
free(data); free(data);
return 1; return 1;
} }
break;
}
data = realloc(data, datalen); data = realloc(data, datalen);

View file

@ -24,6 +24,13 @@
#include "loclass/fileutils.h" //saveFile #include "loclass/fileutils.h" //saveFile
#include "comms.h" //getfromdevice #include "comms.h" //getfromdevice
typedef enum {
DICTIONARY_NONE = 0,
DICTIONARY_MIFARE,
DICTIONARY_T55XX,
DICTIONARY_ICLASS
} Dictionary_t;
extern int CmdFlashMem(const char *Cmd); extern int CmdFlashMem(const char *Cmd);
extern int CmdFlashMemRead(const char* cmd); extern int CmdFlashMemRead(const char* cmd);

View file

@ -2316,7 +2316,8 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
while (fgetc(f) != '\n' && !feof(f)) {}; while (fgetc(f) != '\n' && !feof(f)) {};
//The line start with # is comment, skip //The line start with # is comment, skip
if( buf[0]=='#' ) continue; if( buf[0]=='#' )
continue;
// doesn't this only test first char only? // doesn't this only test first char only?
if (!isxdigit(buf[0])){ if (!isxdigit(buf[0])){
@ -2329,7 +2330,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
p = realloc(*keys, 8 * (keyitems += 64)); p = realloc(*keys, 8 * (keyitems += 64));
if (!p) { if (!p) {
PrintAndLogEx(NORMAL, _RED_([!])" cannot allocate memory for default keys"); PrintAndLogEx(ERR, "cannot allocate memory for default keys");
fclose(f); fclose(f);
return 2; return 2;
} }
@ -2341,7 +2342,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) {
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
} }
fclose(f); fclose(f);
PrintAndLogEx(NORMAL, _BLUE_([+]) "Loaded " _GREEN_(%2d) " keys from %s", *keycnt, filename); PrintAndLogEx(SUCCESS, "Loaded " _GREEN_(%2d) " keys from %s", *keycnt, filename);
return 0; return 0;
} }

View file

@ -453,6 +453,72 @@ out:
return retval; return retval;
} }
int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt ) {
if ( preferredName == NULL ) return 1;
if ( suffix == NULL ) return 1;
// t5577 == 4bytes
// mifare == 6 bytes
// iclass == 8 bytes
// default to 6 bytes.
if (keylen != 4 && keylen != 6 && keylen != 8) {
keylen = 6;
}
// double up since its chars
keylen <<= 1;
char line[255];
size_t counter = 0;
int retval = 0;
int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10);
char * fileName = calloc(size, sizeof(char));
sprintf(fileName,"%s.%s", preferredName, suffix);
FILE *f = fopen(fileName, "r");
if ( !f ) {
PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName);
retval = 1;
goto out;
}
// read file
while ( fgets(line, sizeof(line), f) ) {
// add null terminator
line[keylen] = 0;
// smaller keys than expected is skipped
if (strlen(line) < keylen)
continue;
// The line start with # is comment, skip
if( line[0] == '#' )
continue;
if (!isxdigit(line[0])){
PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_(%2d) "HEX symbols", line, keylen);
continue;
}
uint64_t key = strtoull(line, NULL, 16);
num_to_bytes(key, keylen >> 1, data + counter);
(*keycnt)++;
memset(line, 0, sizeof(line));
counter += (keylen >> 1);
}
fclose(f);
PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file %s", *keycnt, fileName);
*datalen = counter;
out:
free(fileName);
return retval;
}
#else //if we're on ARM #else //if we're on ARM
#endif #endif

View file

@ -124,7 +124,7 @@ extern int loadFile(const char *preferredName, const char *suffix, void* data, s
*/ */
extern int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen); extern int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen);
/** STUB /**
* @brief Utility function to load data from a JSON textfile. This method takes a preferred name. * @brief Utility function to load data from a JSON textfile. This method takes a preferred name.
* E.g. dumpdata-15.json * E.g. dumpdata-15.json
* *
@ -137,6 +137,21 @@ extern int loadFileEML(const char *preferredName, const char *suffix, void* data
*/ */
extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen); extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen);
/**
* @brief Utility function to load data from a DICTIONARY textfile. This method takes a preferred name.
* E.g. default_keys.dic
*
* @param preferredName
* @param suffix the file suffix. Leave out the ".".
* @param data The data array to store the loaded bytes from file
* @param maxdatalen maximum size of data array in bytes
* @param datalen the number of bytes loaded from file
* @param keylen the number of bytes a key per row is
* @return 0 for ok, 1 for failz
*/
extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt );
#define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args)
#else #else

View file

@ -1,23 +1,29 @@
local getopt = require('getopt') local getopt = require('getopt')
local bin = require('bin') local bin = require('bin')
copyright = 'Copyright (c) 2018 Bogito. All rights reserved.'
author = "Bogito" author = "Bogito"
version = 'v1.0.0' version = 'v1.0.1'
desc =[[ desc =
[[
This script will read the flash memory of RDV4 and print the stored passwords. This script will read the flash memory of RDV4 and print the stored passwords.
It was meant to be used as a help tool after using the BogRun standalone mode. It was meant to be used as a help tool after using the BogRun standalone mode.
(Iceman) script adapted to read and print keys in the default dictionary flashmemory sections.
]] ]]
usage = [[ usage =
[[
Usage: Usage:
script run read_pwd_mem -h -o <offset> -l <length> script run read_pwd_mem -h -o <offset> -l <length> -k <keylength>
Arguments: Arguments:
-h : this help -h : this help
-o <OFFSET> : Memory offset. Default is 0. -o <offset> : memory offset, default is 0
-l <LENGTH> : Length in bytes. Default is 256. -l <length> : length in bytes, default is 256
-k <keylen> : key length in bytes <4|6|8> , default is 4
]] ]]
example =[[ example =
Examples: [[
-- This will scan the first 256 bytes of flash memory for stored passwords -- This will scan the first 256 bytes of flash memory for stored passwords
script run read_pwd_mem script run read_pwd_mem
@ -26,61 +32,103 @@ Examples:
-- This will scan 32 bytes of flash memory at offset 64 for stored passwords -- This will scan 32 bytes of flash memory at offset 64 for stored passwords
script run read_pwd_mem -o 64 -l 32 script run read_pwd_mem -o 64 -l 32
]]
-- This will print found
script run read_pwd_mem -o 241664 -k 6
]]
---
-- This is only meant to be used when errors occur
local function oops(err)
print("ERROR: ", err)
return nil, err
end
---
-- Usage help -- Usage help
local function help() local function help()
print(copyright)
print(version)
print(desc) print(desc)
print(usage) print(usage)
print('Example usage:')
print(example) print(example)
end end
---
-- The main entry point
local function main(args) local function main(args)
local data, err, quadlet, pwdcnt print( string.rep('--',20) )
print( string.rep('--',20) )
print()
local data, err, quadlet
local cnt = 0
local offset = 0 local offset = 0
local length = 256 local length = 256
local keylength = 4
local usedkey = false
-- Read the parameters for o, a in getopt.getopt(args, 'ho:l:k:') do
for o, a in getopt.getopt(args, 'ho:l:') do
-- help
if o == "h" then return help() end if o == "h" then return help() end
-- offset
if o == "o" then offset = tonumber(a) end if o == "o" then offset = tonumber(a) end
-- num of bytes to read
if o == "l" then length = tonumber(a) end if o == "l" then length = tonumber(a) end
-- keylength
if o == "k" then keylength = tonumber(a); usedkey = true end
end end
if length < 0 or length > 256 then if length < 0 or length > 256 then
return print('Error: Length is not valid. Must be less than 256') return oops('Error: Length is not valid. Must be less than 256')
end end
if ((offset < 0) or (offset % 4 ~= 0)) then if (offset < 0) or (offset % 4 ~= 0) then
return print('Error: Offset is not valid. Mod-4 values are only allowed.') return oops('Error: Offset is not valid. Mod-4 values are only allowed.')
end end
print('Offset: ' .. offset) print('Memory offset', offset)
print('Length: ' .. length) print('Length ', length)
print() print('Key length ', keylength)
print( string.rep('--',20) )
if usedkey then length = 4096 end
data, err = core.GetFromFlashMem(offset, length) data, err = core.GetFromFlashMem(offset, length)
if err then return oops(err) end
if err then if usedkey then
print(err)
return _, keys, s = bin.unpack('SH'..length-2, data)
if keys == 0xFFFF then return "No keys found in section" end
local kl = keylength * 2
for i = 1, keys do
key = string.sub(s, (i - 1) * kl + 1, i * kl )
print(string.format("[%02d] %s",i, key))
end end
print( string.rep('--',20) )
print( ('[+] found %d passwords'):format(keys))
else
local count, s = bin.unpack('H'..length, data) _, s = bin.unpack('H'..length, data)
pwdcnt = 0 local cnt = 0, i
for i = 1,(length/4),1 for i = 1, (length/keylength) do
do
quadlet = string.sub(s, (i-1)*8+1, i*8)
if quadlet == "FFFFFFFF" then break end
print(string.format("[%02d]",i) .. ' ' .. quadlet)
pwdcnt = pwdcnt + 1
key = string.sub(s, (i-1)*8+1, i*8)
if key == "FFFFFFFF" then break end
print(string.format("[%02d] %s",i, key))
cnt = cnt + 1
end end
print() print( string.rep('--',20) )
print('Found passwords: ' .. pwdcnt) print( ('[+] found %d passwords'):format(cnt))
end
print( string.rep('--',20) )
end end
main(args) main(args)

View file

@ -91,12 +91,16 @@ extern uint32_t FLASHMEM_SPIBAUDRATE;
# define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x2000) # define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x2000)
#endif #endif
#ifndef DEFAULT_MF_KEYS_OFFSET #ifndef DEFAULT_T55XX_KEYS_OFFSET
# define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) # define DEFAULT_T55XX_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000)
#endif #endif
#ifndef DEFAULT_LF_KEYS_OFFSET #ifndef DEFAULT_MF_KEYS_OFFSET
# define DEFAULT_LF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000)
#endif
#ifndef DEFAULT_ICLASS_KEYS_OFFSET
# define DEFAULT_ICLASS_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x5000)
#endif #endif
#endif #endif