Skip to content

Commit ef9ff6d

Browse files
committed
2.3.0 - Fix key false positives and invalid nonces
1 parent 5868f6f commit ef9ff6d

File tree

4 files changed

+120
-99
lines changed

4 files changed

+120
-99
lines changed

HardNestedSolver/cmdhfmfhard.c

Lines changed: 111 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,7 @@ static int simulate_acquire_nonces(uint32_t uid, char* path) {
11741174
uint32_t total_num_nonces = 0;
11751175
float brute_force_depth;
11761176
bool reported_suma8 = false;
1177+
bool got_invalid = false;
11771178

11781179
cuid = uid;
11791180

@@ -1238,6 +1239,29 @@ static int simulate_acquire_nonces(uint32_t uid, char* path) {
12381239
} else {
12391240
update_nonce_data(true);
12401241
acquisition_completed = shrink_key_space(&brute_force_depth);
1242+
if (brute_force_depth == 0) {
1243+
// something went wrong, wipe nonce memory and skip this nonce
1244+
if (got_invalid) {
1245+
hardnested_print_progress(num_acquired_nonces, "Too many invalid nonces", brute_force_depth, 0);
1246+
return -1;
1247+
}
1248+
hardnested_print_progress(num_acquired_nonces, "Found invalid nonce! Trying without it...", brute_force_depth, 0);
1249+
got_invalid = true;
1250+
fclose(fp);
1251+
fp = fopen(path, "r");
1252+
init_nonce_memory();
1253+
uint32_t to = total_num_nonces - 1;
1254+
num_acquired_nonces = 0;
1255+
total_num_nonces = 0;
1256+
for (uint32_t i = 0; i < to; i++) {
1257+
if (fgets(line, sizeof(line), fp) != NULL) {
1258+
sscanf(line, "%u|%hhu", &nt_enc, &par_enc);
1259+
num_acquired_nonces += add_nonce(nt_enc, par_enc);
1260+
total_num_nonces++;
1261+
}
1262+
}
1263+
fgets(line, sizeof(line), fp); // skip line
1264+
}
12411265
}
12421266
} while (!acquisition_completed);
12431267

@@ -1835,7 +1859,7 @@ static void init_it_all(void) {
18351859

18361860
int
18371861
mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey,
1838-
bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename, uint32_t uid, char* path) {
1862+
bool nonce_file_read, bool nonce_file_write, bool slow, uint64_t *foundkey, char *filename, uint32_t uid, char* path) {
18391863
char progress_text[80];
18401864
char instr_set[12] = {0};
18411865

@@ -1847,106 +1871,99 @@ mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo,
18471871

18481872
srand((unsigned) time(NULL));
18491873
brute_force_per_second = brute_force_benchmark();
1850-
write_stats = false;
1874+
// set the correct locale for the stats printing
1875+
write_stats = true;
1876+
setlocale(LC_NUMERIC, "");
1877+
1878+
start_time = msclock();
1879+
print_progress_header();
1880+
snprintf(progress_text, sizeof(progress_text), "Brute force benchmark: %1.0f million (2^%1.1f) keys/s",
1881+
brute_force_per_second / 1000000, log(brute_force_per_second) / log(2.0));
1882+
hardnested_print_progress(0, progress_text, (float) (1LL << 47), 0);
18511883

1852-
if (tests) {
1853-
// set the correct locale for the stats printing
1854-
write_stats = true;
1855-
setlocale(LC_NUMERIC, "");
1856-
1857-
for (uint32_t i = 0; i < tests; i++) {
1858-
start_time = msclock();
1859-
print_progress_header();
1860-
snprintf(progress_text, sizeof(progress_text), "Brute force benchmark: %1.0f million (2^%1.1f) keys/s",
1861-
brute_force_per_second / 1000000, log(brute_force_per_second) / log(2.0));
1862-
hardnested_print_progress(0, progress_text, (float) (1LL << 47), 0);
1863-
snprintf(progress_text, sizeof(progress_text), "Starting Test #%" PRIu32 " ...", i + 1);
1864-
hardnested_print_progress(0, progress_text, (float) (1LL << 47), 0);
1865-
1866-
if (trgkey != NULL) {
1867-
known_target_key = bytes_to_num(trgkey, 6);
1868-
} else {
1869-
known_target_key = -1;
1870-
}
1884+
if (trgkey != NULL) {
1885+
known_target_key = bytes_to_num(trgkey, 6);
1886+
} else {
1887+
known_target_key = -1;
1888+
}
18711889

1872-
init_bitflip_bitarrays();
1873-
init_part_sum_bitarrays();
1874-
init_sum_bitarrays();
1875-
init_allbitflips_array();
1876-
init_nonce_memory();
1877-
update_reduction_rate(0.0, true);
1890+
init_bitflip_bitarrays();
1891+
init_part_sum_bitarrays();
1892+
init_sum_bitarrays();
1893+
init_allbitflips_array();
1894+
init_nonce_memory();
1895+
update_reduction_rate(0.0, true);
18781896

1879-
int res = simulate_acquire_nonces(uid, path);
1880-
if (res != 0) {
1881-
return res;
1882-
}
1897+
int res = simulate_acquire_nonces(uid, path);
1898+
if (res != 0) {
1899+
return -1;
1900+
}
18831901

1884-
set_test_state(best_first_bytes[0]);
1885-
1886-
free_bitflip_bitarrays();
1887-
1888-
bool key_found = false;
1889-
num_keys_tested = 0;
1890-
uint32_t num_odd = nonces[best_first_byte_smallest_bitarray].num_states_bitarray[ODD_STATE];
1891-
uint32_t num_even = nonces[best_first_byte_smallest_bitarray].num_states_bitarray[EVEN_STATE];
1892-
float expected_brute_force1 = (float) num_odd * num_even / 2.0;
1893-
float expected_brute_force2 = nonces[best_first_bytes[0]].expected_num_brute_force;
1894-
1895-
if (expected_brute_force1 < expected_brute_force2) {
1896-
hardnested_print_progress(num_acquired_nonces, "(Ignoring Sum(a8) properties)", expected_brute_force1,
1897-
0);
1898-
set_test_state(best_first_byte_smallest_bitarray);
1899-
add_bitflip_candidates(best_first_byte_smallest_bitarray);
1900-
maximum_states = 0;
1901-
for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) {
1902-
maximum_states += (uint64_t) sl->len[ODD_STATE] * sl->len[EVEN_STATE];
1903-
}
1902+
set_test_state(best_first_bytes[0]);
19041903

1905-
best_first_bytes[0] = best_first_byte_smallest_bitarray;
1906-
pre_XOR_nonces();
1907-
prepare_bf_test_nonces(nonces, best_first_bytes[0]);
1904+
free_bitflip_bitarrays();
19081905

1909-
key_found = brute_force(foundkey);
1910-
free(candidates->states[ODD_STATE]);
1911-
free(candidates->states[EVEN_STATE]);
1912-
free_candidates_memory(candidates);
1913-
candidates = NULL;
1914-
} else {
1915-
pre_XOR_nonces();
1916-
prepare_bf_test_nonces(nonces, best_first_bytes[0]);
1917-
for (uint8_t j = 0; j < NUM_SUMS && !key_found; j++) {
1918-
float expected_brute_force = nonces[best_first_bytes[0]].expected_num_brute_force;
1919-
snprintf(progress_text, sizeof(progress_text), "(%d. guess: Sum(a8) = %" PRIu16 ")", j + 1,
1920-
sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx]);
1921-
hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0);
1922-
if (sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx] != real_sum_a8) {
1923-
snprintf(progress_text, sizeof(progress_text),
1924-
"(Estimated Sum(a8) is WRONG! Correct Sum(a8) = %" PRIu16 ")", real_sum_a8);
1925-
hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0);
1926-
}
1927-
generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx);
1928-
1929-
key_found = brute_force(foundkey);
1930-
free_statelist_cache();
1931-
free_candidates_memory(candidates);
1932-
candidates = NULL;
1933-
if (key_found == false) {
1934-
// update the statistics
1935-
nonces[best_first_bytes[0]].sum_a8_guess[j].prob = 0;
1936-
nonces[best_first_bytes[0]].sum_a8_guess[j].num_states = 0;
1937-
// and calculate new expected number of brute forces
1938-
update_expected_brute_force(best_first_bytes[0]);
1939-
}
1940-
}
1941-
}
1906+
bool key_found = false;
1907+
num_keys_tested = 0;
1908+
uint32_t num_odd = nonces[best_first_byte_smallest_bitarray].num_states_bitarray[ODD_STATE];
1909+
uint32_t num_even = nonces[best_first_byte_smallest_bitarray].num_states_bitarray[EVEN_STATE];
1910+
float expected_brute_force1 = (float) num_odd * num_even / 2.0;
1911+
float expected_brute_force2 = nonces[best_first_bytes[0]].expected_num_brute_force;
1912+
1913+
if (expected_brute_force1 < expected_brute_force2) {
1914+
hardnested_print_progress(num_acquired_nonces, "(Ignoring Sum(a8) properties)", expected_brute_force1,
1915+
0);
1916+
set_test_state(best_first_byte_smallest_bitarray);
1917+
add_bitflip_candidates(best_first_byte_smallest_bitarray);
1918+
maximum_states = 0;
1919+
for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) {
1920+
maximum_states += (uint64_t) sl->len[ODD_STATE] * sl->len[EVEN_STATE];
1921+
}
19421922

1943-
free_nonces_memory();
1944-
free_bitarray(all_bitflips_bitarray[ODD_STATE]);
1945-
free_bitarray(all_bitflips_bitarray[EVEN_STATE]);
1946-
free_sum_bitarrays();
1947-
free_part_sum_bitarrays();
1923+
best_first_bytes[0] = best_first_byte_smallest_bitarray;
1924+
pre_XOR_nonces();
1925+
prepare_bf_test_nonces(nonces, best_first_bytes[0]);
1926+
1927+
key_found = brute_force(foundkey);
1928+
free(candidates->states[ODD_STATE]);
1929+
free(candidates->states[EVEN_STATE]);
1930+
free_candidates_memory(candidates);
1931+
candidates = NULL;
1932+
} else {
1933+
pre_XOR_nonces();
1934+
prepare_bf_test_nonces(nonces, best_first_bytes[0]);
1935+
for (uint8_t j = 0; j < NUM_SUMS && !key_found; j++) {
1936+
float expected_brute_force = nonces[best_first_bytes[0]].expected_num_brute_force;
1937+
snprintf(progress_text, sizeof(progress_text), "(%d. guess: Sum(a8) = %" PRIu16 ")", j + 1,
1938+
sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx]);
1939+
hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0);
1940+
if (sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx] != real_sum_a8) {
1941+
snprintf(progress_text, sizeof(progress_text),
1942+
"(Estimated Sum(a8) is WRONG! Correct Sum(a8) = %" PRIu16 ")", real_sum_a8);
1943+
hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0);
1944+
}
1945+
generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx);
1946+
1947+
key_found = brute_force(foundkey);
1948+
free_statelist_cache();
1949+
free_candidates_memory(candidates);
1950+
candidates = NULL;
1951+
if (key_found == false) {
1952+
// update the statistics
1953+
nonces[best_first_bytes[0]].sum_a8_guess[j].prob = 0;
1954+
nonces[best_first_bytes[0]].sum_a8_guess[j].num_states = 0;
1955+
// and calculate new expected number of brute forces
1956+
update_expected_brute_force(best_first_bytes[0]);
1957+
}
19481958
}
19491959
}
1950-
1951-
return 0;
1960+
1961+
free_nonces_memory();
1962+
free_bitarray(all_bitflips_bitarray[ODD_STATE]);
1963+
free_bitarray(all_bitflips_bitarray[EVEN_STATE]);
1964+
free_sum_bitarrays();
1965+
free_part_sum_bitarrays();
1966+
1967+
return key_found;
19521968
}
1969+

HardNestedSolver/cmdhfmfhard.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@
2121

2222
#include "pm3/common.h"
2323

24-
int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey,
25-
bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename, uint32_t uid, char* path);
24+
int
25+
mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey,
26+
bool nonce_file_read, bool nonce_file_write, bool slow, uint64_t *foundkey, char *filename, uint32_t uid, char* path);
2627
void hardnested_print_progress(uint32_t nonces, const char *activity, float brute_force, uint64_t min_diff_print_time);
2728

2829
#endif

HardNestedSolver/library.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
char* run_hardnested(uint32_t uid, char* path) {
77
uint64_t foundkey = 0;
8-
if (mfnestedhard(0, 0, NULL, 0, 0, NULL, false, false, false, 1, &foundkey, NULL, uid, path) == 0) {
8+
if (mfnestedhard(0, 0, NULL, 0, 0, NULL, false, false, false, &foundkey, NULL, uid, path) == 1) {
99
char* keystr = malloc(14);
1010
snprintf(keystr, 14, "%012" PRIx64 ";", foundkey);
1111
return keystr;

setup.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
with open("README.md", "r") as fh:
3434
long_description = fh.read()
3535

36-
setuptools.setup(name="FlipperNested", version="2.2.2", author="AloneLiberty",
36+
setuptools.setup(name="FlipperNested", version="2.3.0", author="AloneLiberty",
3737
description="Recover keys from collected nonces", long_description=long_description,
3838
long_description_content_type="text/markdown",
3939
url="https://github.com/AloneLiberty/FlipperNestedRecovery",
@@ -45,7 +45,10 @@
4545
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
4646
"Operating System :: MacOS", "Operating System :: POSIX :: Linux",
4747
"Operating System :: Microsoft :: Windows"],
48-
headers=["HardNestedSolver/pm3/util.h", "HardNestedSolver/pm3/ui.h", "HardNestedSolver/pm3/common.h",
48+
headers=["NestedSolver/library.h", "NestedSolver/parity.h",
49+
"NestedSolver/crapto1.h", "NestedSolver/bucketsort.h",
50+
"NestedSolver/progress.h", "HardNestedSolver/pm3/util.h", "HardNestedSolver/pm3/ui.h",
51+
"HardNestedSolver/pm3/common.h",
4952
"HardNestedSolver/pm3/util_posix.h", "HardNestedSolver/pm3/ansi.h",
5053
"HardNestedSolver/pm3/commonutil.h", "HardNestedSolver/pm3/emojis_alt.h",
5154
"HardNestedSolver/pm3/emojis.h", "HardNestedSolver/bucketsort.h",

0 commit comments

Comments
 (0)