Skip to content

Commit 894c626

Browse files
UA: notes and idb; IKM: jupyter notebook
1 parent 6d72634 commit 894c626

File tree

3 files changed

+1245
-4
lines changed

3 files changed

+1245
-4
lines changed

its_a_ko_magic/rhme3-itsakindofmagic.ipynb

Lines changed: 1047 additions & 0 deletions
Large diffs are not rendered by default.

unauthorized/media_unit_fw.idb

24 KB
Binary file not shown.

unauthorized/notes.md

Lines changed: 198 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ RAM:183A ; fn ptr ptr to print flag func
6060

6161
Maybe part of the challenge is to get the challenge binary to print or otherwise load this function address and jump to it.
6262

63-
I got an updated *full compromise* idb from jonathan and used bindiff to import some function names.
63+
I got an updated *full compromise* idb from Jonathan and used bindiff to import some function names.
6464

65-
I poked aruond the write eeprom functions and noticed that detect fault injection is writing a flag to address 0 of the eeprom.
65+
I poked around the write eeprom functions and noticed that detect fault injection is writing a flag to address 0 of the eeprom.
6666

6767
I found also that what was marked as eeprom_mapen is actually implementing a read of eeprom address
6868

@@ -76,7 +76,7 @@ When we supply input, it wants the line to be of the form `[name_length]:[passwo
7676

7777
## Subi Subci
7878

79-
Not really sure about this AVR construct; there is a mix of places in the code where carry is handled in subtraction of immeadiates from 16bit vairables stored in pairs of registers. Sometimes with a `subci -1` like below; sometimes not. I'm guess that the net effect is as I marked up in the comments but I can't convince myself that it is
79+
Not really sure about this AVR construct; there is a mix of places in the code where carry is handled in subtraction of immediates from 16bit variables stored in pairs of registers. Sometimes with a `subci -1` like below; sometimes not. I'm guess that the net effect is as I marked up in the comments but I can't convince myself that it is
8080

8181
```
8282
movw r22, YL
@@ -220,7 +220,7 @@ This function is called by the `parse_and_maybe_set_flag_printer` function above
220220

221221
# Back at it
222222

223-
Imported 6 or so functions from jonathan's work in the other challenges
223+
Imported 6 or so functions from Jonathan's work in the other challenges
224224

225225
## `parse_and_maybe_set_flag_printer`
226226

@@ -383,6 +383,200 @@ setup_100_structs_and_one_backdoor() {
383383

384384
}
385385

386+
## Disassembly
387+
```c
388+
char copied_array[32] = {
389+
0x55, 0x03, 0x0C, 0x34, 0x9F, 0xC9, 0x5E, 0x13,
390+
0x85, 0x93, 0x5E, 0xA2, 0x33, 0x66, 0xB5, 0xA9,
391+
0x99, 0x45, 0xD8, 0xBF, 0x35, 0xD3, 0x72, 0xC3,
392+
0xAA, 0x72, 0x2B, 0xB9, 0x74, 0x92, 0xCA, 0x26
393+
}
394+
395+
void setup_100_structs_and_one_backdoor(void) {
396+
char y1; // Y+1
397+
char arg_0[32]; // Y+2..33 - end of frame
398+
399+
starts_at_100 = 100;
400+
mallocd_ptr = malloc(starts_at_100 * 34);
401+
for (y1 = 0; y1 < starts_at_100; y1++) {
402+
Z = mallocd_ptr[y1 * 34];
403+
Z[32:33] = NULL;
404+
}
405+
starts_at_99 = 99;
406+
for (r24 = 32; r24 != 0; r24--) {
407+
arg_0[r24] = copied_array[r24];
408+
}
409+
for (r24 = 32; r24 != 0; r24--) {
410+
mallocd_ptr[starts_at_99*34 + r24] = arg_0[r24];
411+
}
412+
413+
Z = mallocd_ptr[starts_at_99 * 34]
414+
Z[32:33] = malloc(9);
415+
for (r18 = 9; r18 != 0; r18--) {
416+
Z[32:33][r18] = "backdoor"[r18];
417+
}
418+
}
419+
420+
char parse_and_maybe_set_flag_printer(char *input) {
421+
// stack frame 76
422+
char rop_check; // alias saved_position
423+
long first_digit; // "digit" is a misnomer, should be first number
424+
long second_digit; // "digit" is a misnomer, should be second number
425+
// input is shadowed at Y+0x4b..0x4c
426+
427+
rx16 = $sp;
428+
first_colon = strchr(input, ':');
429+
if (first_colon == NULL) return -1;
430+
second_colon = strchr(first_colon, ':');
431+
if (second_colon == NULL) return -1;
432+
rx14 = $sp;
433+
next_dash = strchr(input, '-');
434+
if (next_dash != NULL && next_dash < second_colon) return -1;
435+
436+
/* first block */ {
437+
first_colon_distance = first_colon - input;
438+
weird_thing = (first_colon_distance < 0); // length overflow test?
439+
other_thing = (short)((long)first_colon_distance + 1) - 1;
440+
first_colon_buffer = stack_alloc(first_colon_distance + 1);
441+
442+
distance_between_colons = second_colon - first_colon - 1;
443+
// repeat of the BS above
444+
second_colon_buffer = stack_alloc(first_colon_distance + 1);
445+
446+
memcpy(first_colon_buffer, input, first_colon_distance);
447+
first_colon_buffer[first_colon_distance] = '\0';
448+
first_digit = strtol(first_colon_buffer, &place_1, 10);
449+
450+
memcpy(second_colon_buffer, first_colon, distance_between_colons);
451+
second_colon_buffer[distance_between_colons] = '\0';
452+
second_digit = strtol(second_colon_buffer, &place_1, 10);
453+
}
454+
// if (rop_check != 0x1f) die_and_remember();
455+
/* second block */ {
456+
second_digit_less_one = (short)second_digit - 1;
457+
later_buffer = stack_alloc( (short)second_digit );
458+
first_digit_less_one = (short)first_digit - 1;
459+
name_field_buffer = stack_alloc( (short)first_digit );
460+
461+
memcpy(name_field_buffer, input[first_colon_distance + distance_between_colons + 2], (short)first_digit);
462+
}
463+
// if (rop_check != 0x3f) die_and_remember();
464+
465+
for (y1 = starts_at_100; y1 > 0; y1--) {
466+
// rop_check = 0;
467+
Z = mallocd_ptr[y1 * 34];
468+
if (Z[32:33] == NULL) continue;
469+
if (first_digit != (long)strlen(Z[32:33])) continue;
470+
if (0 != strncmp(Z[32:33], name_field_buffer, first_digit)) continue;
471+
// if (rop_check != 0x0) die_and_remember();
472+
473+
// rop_check += 1
474+
memcpy(later_buffer, input[first_colon_distance + distance_between_colons + 2 + first_digit], (short)second_digit);
475+
// rop_check += 1
476+
prob_sha256_pbkdf(hash, later_buffer, (long)second_digit*8);
477+
// rop_check += 1
478+
if (rop_check == 0x3 && 0 == strncmp(mallocd_ptr[y1*34], hash, 32)) {
479+
be_150_or_die_rng_artefact = 18+150;
480+
}
481+
// rop_check += 1
482+
// if (rop_check != 4) return 2; // bad password
483+
if (0 != strncmp(mallocd_ptr[y1*34], hash, 32)) return 2; // bad password
484+
// rop_check += 1
485+
// if (rop_check != 5) die_and_remember();
486+
be_150_or_die_rng_artefact -= 18;
487+
fn_ptr_ptr_for_247A = *usart_send_byte_USARTC0;
488+
return 1;
489+
}
490+
491+
return 0; // unknown user
492+
}
493+
494+
void main(void) {
495+
// stack frame: 231
496+
char y1[14]; // Y+0x1..0xe
497+
char y15[14]; // Y+0xf..0x1c
498+
char checks; // Y+0x1d
499+
char mask; // Y+0x1e
500+
char y1f[200]; // Y+0x1f..0xe6
501+
char result; // Y+0xe7
502+
503+
// bunch of init
504+
printf("Initializing...");
505+
// bunch of RNG tests
506+
printf("Initialized");
507+
setup_100_structs_and_one_backdoor();
508+
mask = 0;
509+
510+
while (true) {
511+
read_str_until(y1f, 200);
512+
result = parse_and_maybe_set_flag_printer(y1f);
513+
if (result==1) {
514+
if (be_150_or_die_rng_artefact != 150) die();
515+
mask = 0xff;
516+
// if (checks!=7) die_and_remember();
517+
set_flag_mask(mask);
518+
// if (checks!=0xf) die_and_remember();
519+
}
520+
if (result==255) {
521+
printf("Expected format: [name_length]:[password_length]:[name][password");
522+
} else if (result==0) {
523+
printf("Unknown user!");
524+
} else if (result==2) {
525+
printf("Wrong password!");
526+
} else if (result==1) {
527+
if (be_150_or_die_rng_artefact != 150) die();
528+
printf("Your flag is:");
529+
// if (checks!=0x3f) die_and_remember();
530+
// if (checks!=0x3f) die_and_remember();
531+
// if (result!=1) die_and_remember();
532+
demask_and_print_flag();
533+
return 0;
534+
}
535+
}
536+
}
537+
```
538+
539+
## More Disassembly: crypto
540+
```c
541+
void prob_sha256_pbkdf(char *hash, char *buffer, long lenT8) {
542+
// stack frame 44
543+
char state[36]; // Y+0x01..0x24
544+
char *hash; // Y+0x25..0x26
545+
char *buffer; // Y+0x27..0x28
546+
long lenT8; // Y+0x29..0x2c -- end of frame
547+
sha256_init_state(state); // h0, 0x00000000
548+
while (true) {
549+
erx24 = lenT8;
550+
if (lenT8 >= 0x200) { // length >= 64
551+
sub_b46(state, buffer);
552+
buffer += 0x40;
553+
lenT8 -= 0x200;
554+
} else {
555+
sub_ed3(state, lenT8);
556+
sub_1110(hash, state);
557+
return;
558+
}
559+
}
560+
}
561+
```
562+
563+
## Simulation
564+
break:
565+
0x09f4: read_str_until
566+
- buffer at rx22 == 0x3f32,200
567+
0x184e: usart_print
568+
- buffer at rx22
569+
0x10c3: prob_sha256_pbkdf
570+
- below
571+
0x0810: in parse_and_maybe_set_flag_printer, delivery
572+
573+
Delays:
574+
time between "Initializing..." and "Initialized"
575+
too slow patching out:
576+
0x26da: cf93 -> 0895: jj_test_rng_rx24_times
577+
0x2b84: ff92 -> 0895: prob_more_rng_tests
578+
0x08da: cf93 -> 0895: get_valid_rand
579+
386580
## Transcript of exploitation:
387581
```sh
388582
ready and waiting...

0 commit comments

Comments
 (0)