ADD: @pwpiwi 's latest changes to 'hf mf hardnested'

This commit is contained in:
iceman1001 2016-01-13 09:31:13 +01:00
parent d16b33feb5
commit 0d5ee8e245
5 changed files with 207 additions and 28 deletions

2
.gitignore vendored
View file

@ -15,6 +15,7 @@
*.moc.cpp
*.z
*.exe
hardnested_stats.txt
proxmark
proxmark3
flasher
@ -35,5 +36,4 @@ fpga/*
!fpga/go.bat
!fpga/sim.tcl
client/*

View file

@ -717,15 +717,16 @@ void SamyRun()
// wait for button to be released
while(BUTTON_PRESS())
WDT_HIT();
Dbprintf("%x %x %x", selected, high[selected], low[selected]);
CmdHIDsimTAG(high[selected], low[selected], 0);
CmdHIDsimTAG(high[selected], low[selected], 0);
DbpString("Done playing");
if (BUTTON_HELD(1000) > 0)
{
if (BUTTON_HELD(1000) > 0) {
DbpString("Exiting");
LEDsoff();
return;
}
}
/* We pressed a button so ignore it here with a delay */
SpinDelay(300);

View file

@ -804,7 +804,7 @@ int CmdHF14AMfNestedHard(const char *Cmd)
char ctmp;
ctmp = param_getchar(Cmd, 0);
if (ctmp != 'R' && ctmp != 'r' && strlen(Cmd) < 20) {
if (ctmp != 'R' && ctmp != 'r' && ctmp != 'T' && ctmp != 't' && strlen(Cmd) < 20) {
PrintAndLog("Usage:");
PrintAndLog(" hf mf hardnested <block number> <key A|B> <key (12 hex symbols)>");
PrintAndLog(" <target block number> <target key A|B> [known target key (12 hex symbols)] [w] [s]");
@ -829,15 +829,17 @@ int CmdHF14AMfNestedHard(const char *Cmd)
bool nonce_file_read = false;
bool nonce_file_write = false;
bool slow = false;
int tests = 0;
if (ctmp == 'R' || ctmp == 'r') {
nonce_file_read = true;
if (!param_gethex(Cmd, 1, trgkey, 12)) {
know_target_key = true;
}
} else if (ctmp == 'T' || ctmp == 't') {
tests = param_get32ex(Cmd, 1, 100, 10);
} else {
blockNo = param_get8(Cmd, 0);
ctmp = param_getchar(Cmd, 1);
if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') {
@ -883,13 +885,14 @@ int CmdHF14AMfNestedHard(const char *Cmd)
}
}
PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s ",
PrintAndLog("--target block no:%3d, target key type:%c, known target key: 0x%02x%02x%02x%02x%02x%02x%s, file action: %s, Slow: %s, Tests: %d ",
trgBlockNo,
trgKeyType?'B':'A',
trgkey[0], trgkey[1], trgkey[2], trgkey[3], trgkey[4], trgkey[5],
know_target_key?"":" (not set)",
nonce_file_write?"write":nonce_file_read?"read":"none",
slow?"Yes":"No");
slow?"Yes":"No",
tests);
int16_t isOK = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, know_target_key?trgkey:NULL, nonce_file_read, nonce_file_write, slow);

View file

@ -18,6 +18,7 @@
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <locale.h>
#include <math.h>
#include "proxmark3.h"
#include "cmdmain.h"
@ -95,7 +96,8 @@ static uint16_t first_byte_num = 0;
static uint16_t num_good_first_bytes = 0;
static uint64_t maximum_states = 0;
static uint64_t known_target_key;
static bool write_stats = false;
static FILE *fstats = NULL;
typedef enum {
@ -175,6 +177,41 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc)
}
static void init_nonce_memory(void)
{
for (uint16_t i = 0; i < 256; i++) {
nonces[i].num = 0;
nonces[i].Sum = 0;
nonces[i].Sum8_guess = 0;
nonces[i].Sum8_prob = 0.0;
nonces[i].updated = true;
nonces[i].first = NULL;
}
first_byte_num = 0;
first_byte_Sum = 0;
num_good_first_bytes = 0;
}
static void free_nonce_list(noncelistentry_t *p)
{
if (p == NULL) {
return;
} else {
free_nonce_list(p->next);
free(p);
}
}
static void free_nonces_memory(void)
{
for (uint16_t i = 0; i < 256; i++) {
free_nonce_list(nonces[i].first);
}
}
static uint16_t PartialSumProperty(uint32_t state, odd_even_t odd_even)
{
uint16_t sum = 0;
@ -621,6 +658,8 @@ static void Check_for_FilterFlipProperties(void)
{
printf("Checking for Filter Flip Properties...\n");
uint16_t num_bitflips = 0;
for (uint16_t i = 0; i < 256; i++) {
nonces[i].BitFlip[ODD_STATE] = false;
nonces[i].BitFlip[EVEN_STATE] = false;
@ -633,10 +672,92 @@ static void Check_for_FilterFlipProperties(void)
if (parity1 == parity2_odd) { // has Bit Flip Property for odd bits
nonces[i].BitFlip[ODD_STATE] = true;
num_bitflips++;
} else if (parity1 == parity2_even) { // has Bit Flip Property for even bits
nonces[i].BitFlip[EVEN_STATE] = true;
num_bitflips++;
}
}
if (write_stats) {
fprintf(fstats, "%d;", num_bitflips);
}
}
static void simulate_MFplus_RNG(uint32_t test_cuid, uint64_t test_key, uint32_t *nt_enc, uint8_t *par_enc)
{
struct Crypto1State sim_cs;
// init cryptostate with key:
for(int8_t i = 47; i > 0; i -= 2) {
sim_cs.odd = sim_cs.odd << 1 | BIT(test_key, (i - 1) ^ 7);
sim_cs.even = sim_cs.even << 1 | BIT(test_key, i ^ 7);
}
*par_enc = 0;
uint32_t nt = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff);
for (int8_t byte_pos = 3; byte_pos >= 0; byte_pos--) {
uint8_t nt_byte_dec = (nt >> (8*byte_pos)) & 0xff;
uint8_t nt_byte_enc = crypto1_byte(&sim_cs, nt_byte_dec ^ (test_cuid >> (8*byte_pos)), false) ^ nt_byte_dec; // encode the nonce byte
*nt_enc = (*nt_enc << 8) | nt_byte_enc;
uint8_t ks_par = filter(sim_cs.odd); // the keystream bit to encode/decode the parity bit
uint8_t nt_byte_par_enc = ks_par ^ oddparity8(nt_byte_dec); // determine the nt byte's parity and encode it
*par_enc = (*par_enc << 1) | nt_byte_par_enc;
}
}
static void simulate_acquire_nonces()
{
clock_t time1 = clock();
bool filter_flip_checked = false;
uint32_t total_num_nonces = 0;
uint32_t next_fivehundred = 500;
uint32_t total_added_nonces = 0;
cuid = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff);
known_target_key = ((uint64_t)rand() & 0xfff) << 36 | ((uint64_t)rand() & 0xfff) << 24 | ((uint64_t)rand() & 0xfff) << 12 | ((uint64_t)rand() & 0xfff);
printf("Simulating nonce acquisition for target key %012"llx", cuid %08x ...\n", known_target_key, cuid);
fprintf(fstats, "%012"llx";%08x;", known_target_key, cuid);
do {
uint32_t nt_enc = 0;
uint8_t par_enc = 0;
simulate_MFplus_RNG(cuid, known_target_key, &nt_enc, &par_enc);
//printf("Simulated RNG: nt_enc1: %08x, nt_enc2: %08x, par_enc: %02x\n", nt_enc1, nt_enc2, par_enc);
total_added_nonces += add_nonce(nt_enc, par_enc);
total_num_nonces++;
if (first_byte_num == 256 ) {
// printf("first_byte_num = %d, first_byte_Sum = %d\n", first_byte_num, first_byte_Sum);
if (!filter_flip_checked) {
Check_for_FilterFlipProperties();
filter_flip_checked = true;
}
num_good_first_bytes = estimate_second_byte_sum();
if (total_num_nonces > next_fivehundred) {
next_fivehundred = (total_num_nonces/500+1) * 500;
printf("Acquired %5d nonces (%5d with distinct bytes 0 and 1). Number of bytes with probability for correctly guessed Sum(a8) > %1.1f%%: %d\n",
total_num_nonces,
total_added_nonces,
CONFIDENCE_THRESHOLD * 100.0,
num_good_first_bytes);
}
}
} while (num_good_first_bytes < GOOD_BYTES_REQUIRED);
PrintAndLog("Acquired a total of %d nonces in %1.1f seconds (%0.0f nonces/minute)",
total_num_nonces,
((float)clock()-time1)/CLOCKS_PER_SEC,
total_num_nonces*60.0*CLOCKS_PER_SEC/((float)clock()-time1));
fprintf(fstats, "%d;%d;%d;%1.2f;", total_num_nonces, total_added_nonces, num_good_first_bytes, CONFIDENCE_THRESHOLD);
}
@ -1029,7 +1150,6 @@ static struct sl_cache_entry {
static void init_statelist_cache(void)
{
for (uint16_t i = 0; i < 17; i+=2) {
for (uint16_t j = 0; j < 17; j+=2) {
for (uint16_t k = 0; k < 2; k++) {
@ -1144,12 +1264,18 @@ static void TestIfKeyExists(uint64_t key)
count, log(count)/log(2),
maximum_states, log(maximum_states)/log(2),
(count>>23)/60);
if (write_stats) {
fprintf(fstats, "1\n");
}
crypto1_destroy(pcs);
return;
}
}
printf("Key NOT found!\n");
if (write_stats) {
fprintf(fstats, "0\n");
}
crypto1_destroy(pcs);
}
@ -1218,7 +1344,36 @@ static void generate_candidates(uint16_t sum_a0, uint16_t sum_a8)
maximum_states += (uint64_t)sl->len[ODD_STATE] * sl->len[EVEN_STATE];
}
printf("Number of remaining possible keys: %lld (2^%1.1f)\n", maximum_states, log(maximum_states)/log(2.0));
if (write_stats) {
if (maximum_states != 0) {
fprintf(fstats, "%1.1f;", log(maximum_states)/log(2.0));
} else {
fprintf(fstats, "%1.1f;", 0.0);
}
}
}
static void free_candidates_memory(statelist_t *sl)
{
if (sl == NULL) {
return;
} else {
free_candidates_memory(sl->next);
free(sl);
}
}
static void free_statelist_cache(void)
{
for (uint16_t i = 0; i < 17; i+=2) {
for (uint16_t j = 0; j < 17; j+=2) {
for (uint16_t k = 0; k < 2; k++) {
free(sl_cache[i][j][k].sl);
}
}
}
}
@ -1234,30 +1389,46 @@ static void brute_force(void)
}
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow)
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests)
{
// initialize Random number generator
time_t t;
srand((unsigned) time(&t));
if (trgkey != NULL) {
known_target_key = bytes_to_num(trgkey, 6);
} else {
known_target_key = -1;
}
// initialize the list of nonces
for (uint16_t i = 0; i < 256; i++) {
nonces[i].num = 0;
nonces[i].Sum = 0;
nonces[i].Sum8_guess = 0;
nonces[i].Sum8_prob = 0.0;
nonces[i].updated = true;
nonces[i].first = NULL;
}
first_byte_num = 0;
first_byte_Sum = 0;
num_good_first_bytes = 0;
init_partial_statelists();
init_BitFlip_statelist();
write_stats = false;
if (tests) {
// set the correct locale for the stats printing
setlocale(LC_ALL, "");
write_stats = true;
if ((fstats = fopen("hardnested_stats.txt","a")) == NULL) {
PrintAndLog("Could not create/open file hardnested_stats.txt");
return 3;
}
for (uint32_t i = 0; i < tests; i++) {
init_nonce_memory();
simulate_acquire_nonces();
Tests();
printf("Sum(a0) = %d\n", first_byte_Sum);
fprintf(fstats, "%d;", first_byte_Sum);
generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].Sum8_guess);
brute_force();
free_nonces_memory();
free_statelist_cache();
free_candidates_memory(candidates);
candidates = NULL;
}
fclose(fstats);
} else {
init_nonce_memory();
if (nonce_file_read) { // use pre-acquired data from file nonces.bin
if (read_nonce_file() != 0) {
return 3;
@ -1271,7 +1442,6 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
}
}
Tests();
PrintAndLog("");
@ -1294,6 +1464,11 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc
PrintAndLog("Time for generating key candidates list: %1.0f seconds", (float)(clock() - start_time)/CLOCKS_PER_SEC);
brute_force();
free_nonces_memory();
free_statelist_cache();
free_candidates_memory(candidates);
candidates = NULL;
}
return 0;
}

View file

@ -8,4 +8,4 @@
// hf mf hardnested command
//-----------------------------------------------------------------------------
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow);
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests);