From debf4e3327fd701ba54bf14885ffffb565ebee3d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 4 Feb 2018 17:19:08 +0100 Subject: [PATCH] chg: 'analyse hid' moved to 'hf iclass permute' un/permute function is moved. --- client/cmdanalyse.c | 253 ++++++++++++++++++++----------------------- client/cmdhficlass.c | 117 ++++++++++++++++++++ client/cmdhficlass.h | 4 +- 3 files changed, 235 insertions(+), 139 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 0f9eb4420..320833c3e 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -53,20 +53,7 @@ int usage_analyse_crc(void){ PrintAndLog(" analyse crc 137AF00A0A0D"); return 0; } -int usage_analyse_hid(void){ - PrintAndLog("Permute function from 'heart of darkness' paper."); - PrintAndLog(""); - PrintAndLog("Usage: analyse hid [h] "); - PrintAndLog("Options:"); - PrintAndLog(" h This help"); - PrintAndLog(" r reverse permuted key"); - PrintAndLog(" f permute key"); - PrintAndLog(" input bytes"); - PrintAndLog(""); - PrintAndLog("Samples:"); - PrintAndLog(" analyse hid r 0123456789abcdef"); - return 0; -} + int usage_analyse_nuid(void){ PrintAndLog("Generate 4byte NUID from 7byte UID"); PrintAndLog(""); @@ -452,9 +439,29 @@ int CmdAnalyseTEASelfTest(const char *Cmd){ return 0; } +char* pb(uint32_t b) { + static char buf1[33] = {0}; + static char buf2[33] = {0}; + static char *s; + + if (s != buf1) + s = buf1; + else + s = buf2; + + memset(s, 0, sizeof(buf1)); + + uint32_t mask = 0x80000000; + for (uint8_t i=0; i<32;i++) { + s[i] = (mask & b)?'1':'0'; + mask >>= 1; + } + return s; +} + int CmdAnalyseA(const char *Cmd){ - uint8_t syncBit = 99; + //uint8_t syncBit = 99; // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern @@ -462,29 +469,102 @@ int CmdAnalyseA(const char *Cmd){ # define SYNC_16BIT 0x4DB2 #define FELICA_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000 - uint32_t shiftReg = SYNC_16BIT; - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 0))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 1))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 2))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 3))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 4))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 5))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 6))); - printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 7))); + // uint32_t shiftReg = SYNC_16BIT; + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 0))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 1))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 2))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 3))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 4))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 5))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 6))); + // printf("reg %04x \n",(shiftReg & (SYNC_16BIT >> 7))); - for ( uint8_t i=0; i<32; i++){ - if ((shiftReg & (SYNC_16BIT >> 0)) == SYNC_16BIT >> 0) syncBit = 7; - else if ((shiftReg & (SYNC_16BIT >> 1)) == SYNC_16BIT >> 1) syncBit = 6; - else if ((shiftReg & (SYNC_16BIT >> 2)) == SYNC_16BIT >> 2) syncBit = 5; - else if ((shiftReg & (SYNC_16BIT >> 3)) == SYNC_16BIT >> 3) syncBit = 4; - else if ((shiftReg & (SYNC_16BIT >> 4)) == SYNC_16BIT >> 4) syncBit = 3; - else if ((shiftReg & (SYNC_16BIT >> 5)) == SYNC_16BIT >> 5) syncBit = 2; - else if ((shiftReg & (SYNC_16BIT >> 6)) == SYNC_16BIT >> 6) syncBit = 1; - else if ((shiftReg & (SYNC_16BIT >> 7)) == SYNC_16BIT >> 7) syncBit = 0; + // for ( uint8_t i=0; i<32; i++){ + // if ((shiftReg & (SYNC_16BIT >> 0)) == SYNC_16BIT >> 0) syncBit = 7; + // else if ((shiftReg & (SYNC_16BIT >> 1)) == SYNC_16BIT >> 1) syncBit = 6; + // else if ((shiftReg & (SYNC_16BIT >> 2)) == SYNC_16BIT >> 2) syncBit = 5; + // else if ((shiftReg & (SYNC_16BIT >> 3)) == SYNC_16BIT >> 3) syncBit = 4; + // else if ((shiftReg & (SYNC_16BIT >> 4)) == SYNC_16BIT >> 4) syncBit = 3; + // else if ((shiftReg & (SYNC_16BIT >> 5)) == SYNC_16BIT >> 5) syncBit = 2; + // else if ((shiftReg & (SYNC_16BIT >> 6)) == SYNC_16BIT >> 6) syncBit = 1; + // else if ((shiftReg & (SYNC_16BIT >> 7)) == SYNC_16BIT >> 7) syncBit = 0; - printf("ShiftReg is [%04x] | SyncBit is [%u]\n", shiftReg, syncBit); - shiftReg = shiftReg << 1 | ( shiftReg & 0x8000 ) >> 15; + // printf("ShiftReg is [%04x] | SyncBit is [%u]\n", shiftReg, syncBit); + // shiftReg = shiftReg << 1 | ( shiftReg & 0x8000 ) >> 15; + // } + uint8_t a = 0x4D, b = 0; + printf("%X \n", (0xFF >> 2)); + + //shift in remaining byte, slowly... + // this reverses the input... + for (uint8_t i=0; i<8; i++) { + printf("%u | %02X %s| %02X %s |\n", i, a, pb(a), b, pb(b)); + b = (b << 1) | (a & 1); + a >>= 1; } + + uint16_t sync = 0x4DB2; + uint32_t shift = 0x1FFF4D; // typical start pattern. + + uint8_t bt = 0x4D; //incoming byte ( b10110010) reflected = b 01001101 == 4D.. So, 4DB2 is opposite.. hm. + + // shift in byte. + shift = shift << 8 | reflect8(bt); + + // sync position + uint8_t sync_pos = 0; + + // finding sync_pos + for ( uint8_t i=0; i<32; i++) { + if ((shift & (sync >> 0)) == sync >> 0) sync_pos = 7; + else if ((shift & (sync >> 1)) == sync >> 1) sync_pos = 6; + else if ((shift & (sync >> 2)) == sync >> 2) sync_pos = 5; + else if ((shift & (sync >> 3)) == sync >> 3) sync_pos = 4; + else if ((shift & (sync >> 4)) == sync >> 4) sync_pos = 3; + else if ((shift & (sync >> 5)) == sync >> 5) sync_pos = 2; + else if ((shift & (sync >> 6)) == sync >> 6) sync_pos = 1; + else if ((shift & (sync >> 7)) == sync >> 7) sync_pos = 0; + + printf("shift [%04x] | sync_pos [%u]\n", shift, sync_pos); + shift <<= 1; + } + + // shift = 0x1FF4DB; + // shift = 0x3FE9B6; + // printf("%s | %s %c\n", pb((shift & (sync >> 0))), pb(sync >> 0), ((shift & (sync >> 0)) == sync >> 0) ?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 1))), pb(sync >> 1), ((shift & (sync >> 1)) == sync >> 1) ?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 2))), pb(sync >> 2), ((shift & (sync >> 2)) == sync >> 2) ?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 3))), pb(sync >> 3), ((shift & (sync >> 3)) == sync >> 3) ?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 4))), pb(sync >> 4), ((shift & (sync >> 4)) == sync >> 4) ?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 5))), pb(sync >> 5), ((shift & (sync >> 5)) == sync >> 5)?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 6))), pb(sync >> 6), ((shift & (sync >> 6)) == sync >> 6) ?'Y':'N' ); + // printf("%s | %s %c\n", pb((shift & (sync >> 7))), pb(sync >> 7), ((shift & (sync >> 7)) == sync >> 7) ?'Y':'N'); + + // split byte into two parts. + uint8_t offset = 3, n0 = 0, n1 = 0; + uint8_t rev = reflect8(bt); + rev = 0xB2; + for (uint8_t m=0; m<8; m++) { + offset = m; + n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset; + n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset))); + + printf("rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); + n0 = 0, n1 = 0; + // printf(" (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) ); + //printf("~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) ); + //printf(" rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) )); + } +return 0; + // from A -- x bits into B and the rest into C. + + for ( uint8_t i=0; i<8; i++){ + printf("%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) ); + b = a & (a & (0xFF >> (8-i))); + a >>=1; + } + + /* pm3 --> da hex2bin 4db2 0100110110110010 pm3 --> da hex2bin 926d9 10010010011011011001 @@ -717,108 +797,6 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; return 0; } -static void permute(uint8_t *data, uint8_t len, uint8_t *output){ -#define KEY_SIZE 8 - - if ( len > KEY_SIZE ) { - for(uint8_t m = 0; m < len; m += KEY_SIZE){ - permute(data+m, KEY_SIZE, output+m); - } - return; - } - if ( len != KEY_SIZE ) { - printf("wrong key size\n"); - return; - } - uint8_t i,j,p, mask; - for( i=0; i < KEY_SIZE; ++i){ - p = 0; - mask = 0x80 >> i; - for( j=0; j < KEY_SIZE; ++j){ - p >>= 1; - if (data[j] & mask) - p |= 0x80; - } - output[i] = p; - } -} -static void permute_rev(uint8_t *data, uint8_t len, uint8_t *output){ - permute(data, len, output); - permute(output, len, data); - permute(data, len, output); -} -static void simple_crc(uint8_t *data, uint8_t len, uint8_t *output){ - uint8_t crc = 0; - for( uint8_t i=0; i < len; ++i){ - // seventh byte contains the crc. - if ( (i & 0x7) == 0x7 ) { - output[i] = crc ^ 0xFF; - crc = 0; - } else { - output[i] = data[i]; - crc ^= data[i]; - } - } -} -// DES doesn't use the MSB. -static void shave(uint8_t *data, uint8_t len){ - for (uint8_t i=0; i>= 1; - - memcpy(key, data, 8); - - if ( isReverse ) { - generate_rev(data, len); - permutekey_rev(key, key_std_format); - printf(" holiman iclass key | %s \n", sprint_hex(key_std_format, 8)); - } - else { - generate(data, len); - permutekey(key, key_iclass_format); - printf(" holiman std key | %s \n", sprint_hex(key_iclass_format, 8)); - } - return 0; -} - void generate4bNUID(uint8_t *uid, uint8_t *nuid){ uint16_t crc; uint8_t b1, b2; @@ -875,7 +853,6 @@ static command_t CommandTable[] = { {"tea", CmdAnalyseTEASelfTest, 1, "Crypto TEA test"}, {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"}, {"a", CmdAnalyseA, 1, "num bits test"}, - {"hid", CmdAnalyseHid, 1, "Permute function from 'heart of darkness' paper"}, {"nuid", CmdAnalyseNuid, 1, "create NUID from 7byte UID"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index dd71f7a2b..51f05518b 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -245,6 +245,20 @@ int usage_hf_iclass_lookup(void) { PrintAndLog(" hf iclass lookup u 9655a400f8ff12e0 p f0ffffffffffffff m 0000000089cb984b f default_iclass_keys.dic e"); return 0; } +int usage_hf_iclass_permutekey(void){ + PrintAndLog("Permute function from 'heart of darkness' paper."); + PrintAndLog(""); + PrintAndLog("Usage: hf iclass permute [h] "); + PrintAndLog("Options:"); + PrintAndLog(" h This help"); + PrintAndLog(" r reverse permuted key"); + PrintAndLog(" f permute key"); + PrintAndLog(" input bytes"); + PrintAndLog(""); + PrintAndLog("Samples:"); + PrintAndLog(" hf iclass permute r 0123456789abcdef"); + return 0; +} int xorbits_8(uint8_t val) { uint8_t res = val ^ (val >> 1); //1st pass @@ -2334,6 +2348,108 @@ void PrintPreCalc(iclass_prekey_t* list, int itemcnt) { } } +static void permute(uint8_t *data, uint8_t len, uint8_t *output){ +#define KEY_SIZE 8 + + if ( len > KEY_SIZE ) { + for(uint8_t m = 0; m < len; m += KEY_SIZE){ + permute(data+m, KEY_SIZE, output+m); + } + return; + } + if ( len != KEY_SIZE ) { + printf("[!] wrong key size\n"); + return; + } + uint8_t i,j,p, mask; + for( i=0; i < KEY_SIZE; ++i){ + p = 0; + mask = 0x80 >> i; + for( j=0; j < KEY_SIZE; ++j){ + p >>= 1; + if (data[j] & mask) + p |= 0x80; + } + output[i] = p; + } +} +static void permute_rev(uint8_t *data, uint8_t len, uint8_t *output){ + permute(data, len, output); + permute(output, len, data); + permute(data, len, output); +} +static void simple_crc(uint8_t *data, uint8_t len, uint8_t *output){ + uint8_t crc = 0; + for( uint8_t i=0; i < len; ++i){ + // seventh byte contains the crc. + if ( (i & 0x7) == 0x7 ) { + output[i] = crc ^ 0xFF; + crc = 0; + } else { + output[i] = data[i]; + crc ^= data[i]; + } + } +} +// DES doesn't use the MSB. +static void shave(uint8_t *data, uint8_t len){ + for (uint8_t i=0; i>= 1; + + memcpy(key, data, 8); + + if ( isReverse ) { + generate_rev(data, len); + permutekey_rev(key, key_std_format); + printf("[+] holiman iclass key | %s \n", sprint_hex(key_std_format, 8)); + } + else { + generate(data, len); + permutekey(key, key_iclass_format); + printf("[+] holiman std key | %s \n", sprint_hex(key_iclass_format, 8)); + } + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"}, @@ -2347,6 +2463,7 @@ static command_t CommandTable[] = { {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"}, {"lookup", CmdHFiClassLookUp, 0, "[options..] Uses authentication trace to check for key in dictionary file"}, {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"}, + {"permutekey", CmdHFiClassPermuteKey, 0, " Permute function from 'heart of darkness' paper"}, {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"}, {"reader", CmdHFiClassReader, 0, " Act like an iClass reader"}, {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"}, diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index ca7b4a154..7aaa30a5e 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -73,7 +73,9 @@ extern int CmdHFiClassSniff(const char *Cmd); extern int CmdHFiClassSim(const char *Cmd); extern int CmdHFiClassWriteKeyFile(const char *Cmd); extern int CmdHFiClass_WriteBlock(const char *Cmd); -extern int CmdHF14AMfChk(const char *Cmd); +extern int CmdHFiClassCheckKeys(const char *Cmd); +extern int CmdHFiClassLookUp(const char *Cmd); +extern int CmdHFiClassPermuteKey(const char *Cmd); void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite);