Se nos entrega el siguiente ELF:
/* This file was generated by the Hex-Rays decompiler version 8.4.0.240320. Copyright (c) 2007-2021 Hex-Rays <info@hex-rays.com> Detected compiler: GNU C++ */ #include <defs.h> //------------------------------------------------------------------------- // Function declarations __int64 (**init_proc())(void); void sub_1020(); // int printf(const char *format, ...); // int getchar(void); // int fflush(FILE *stream); // __int64 __isoc99_scanf(const char *, ...); weak // void __noreturn exit(int status); // int __fastcall _cxa_finalize(void *); void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void)); FILE **deregister_tm_clones(); __int64 register_tm_clones(); // weak FILE **_do_global_dtors_aux(); __int64 __fastcall frame_dummy(_QWORD, _QWORD, _QWORD); // weak int __fastcall main(int argc, const char **argv, const char **envp); _BOOL8 __fastcall comprobacion(char a1, char a2, int a3); void _libc_csu_fini(void); // idb void term_proc(); // int __fastcall _libc_start_main(int (__fastcall *main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void *stack_end); // int __fastcall __cxa_finalize(void *); // __int64 _gmon_start__(void); weak //------------------------------------------------------------------------- // Data declarations _UNKNOWN _libc_csu_init; __int64 (__fastcall *_frame_dummy_init_array_entry)() = &frame_dummy; // weak __int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)() = &_do_global_dtors_aux; // weak void *_dso_handle = &_dso_handle; // idb char *a = "MdfnJk"; // weak char *b = "jYx}"; // weak char *c = "gWmfk"; // weak char *d = "mlvpc"; // weak char *f = "neU++w"; // weak FILE *_bss_start; // idb char completed_0; // weak //----- (0000000000001000) ---------------------------------------------------- __int64 (**init_proc())(void) { __int64 (**result)(void); // rax result = &_gmon_start__; if ( &_gmon_start__ ) return (__int64 (**)(void))_gmon_start__(); return result; } // 40D0: using guessed type __int64 _gmon_start__(void); //----- (0000000000001020) ---------------------------------------------------- void sub_1020() { JUMPOUT(0LL); } // 1026: control flows out of bounds to 0 //----- (0000000000001090) ---------------------------------------------------- // positive sp value has been detected, the output may be wrong! void __fastcall __noreturn start(__int64 a1, __int64 a2, void (*a3)(void)) { __int64 v3; // rax int v4; // esi __int64 v5; // [rsp-8h] [rbp-8h] BYREF char *retaddr; // [rsp+0h] [rbp+0h] BYREF v4 = v5; v5 = v3; _libc_start_main( (int (__fastcall *)(int, char **, char **))main, v4, &retaddr, (void (*)(void))_libc_csu_init, _libc_csu_fini, a3, &v5); __halt(); } // 1096: positive sp value 8 has been found // 109D: variable 'v3' is possibly undefined //----- (00000000000010C0) ---------------------------------------------------- FILE **deregister_tm_clones() { return &_bss_start; } //----- (00000000000010F0) ---------------------------------------------------- __int64 register_tm_clones() { return 0LL; } // 10F0: using guessed type __int64 register_tm_clones(); //----- (0000000000001130) ---------------------------------------------------- FILE **_do_global_dtors_aux() { FILE **result; // rax if ( !completed_0 ) { if ( &__cxa_finalize ) _cxa_finalize(_dso_handle); result = deregister_tm_clones(); completed_0 = 1; } return result; } // 4080: using guessed type char completed_0; //----- (0000000000001175) ---------------------------------------------------- int __fastcall main(int argc, const char **argv, const char **envp) { char v4; // [rsp+7h] [rbp-9h] BYREF int v5; // [rsp+8h] [rbp-8h] bool v6; // [rsp+Fh] [rbp-1h] v6 = 1; v5 = 0; while ( v6 ) { fflush(_bss_start); printf("\nIntroduce la letra correcta:\t"); __isoc99_scanf("%c", &v4); getchar(); if ( v5 > 5 ) { if ( v5 > 9 ) { if ( v5 > 14 ) { if ( v5 > 19 ) v6 = comprobacion(v4, f[v5 - 20], 10); else v6 = comprobacion(v4, d[v5 - 15], 2); } else { v6 = comprobacion(v4, c[v5 - 10], 8); } } else { v6 = comprobacion(v4, b[v5 - 6], 17); } } else { v6 = comprobacion(v4, a[v5], 5); } if ( !v6 ) { printf("Incorrecta"); exit(1); } printf("\n%c\n", (unsigned int)v4); if ( v5 == 25 ) { printf("Ya tienes la flag!!"); exit(1); } ++v5; } return 0; } // 1060: using guessed type __int64 __isoc99_scanf(const char *, ...); // 4050: using guessed type char *a; // 4058: using guessed type char *b; // 4060: using guessed type char *c; // 4068: using guessed type char *d; // 4070: using guessed type char *f; //----- (0000000000001352) ---------------------------------------------------- _BOOL8 __fastcall comprobacion(char a1, char a2, int a3) { return a1 == (a3 ^ a2); } //----- (0000000000001390) ---------------------------------------------------- void __fastcall _libc_csu_init(unsigned int a1, __int64 a2, __int64 a3) { signed __int64 v4; // rbp __int64 i; // rbx init_proc(); v4 = &_do_global_dtors_aux_fini_array_entry - &_frame_dummy_init_array_entry; if ( v4 ) { for ( i = 0LL; i != v4; ++i ) ((void (__fastcall *)(_QWORD, __int64, __int64))*(&_frame_dummy_init_array_entry + i))(a1, a2, a3); } } // 1170: using guessed type __int64 __fastcall frame_dummy(_QWORD, _QWORD, _QWORD); // 3DE8: using guessed type __int64 (__fastcall *_frame_dummy_init_array_entry)(); // 3DF0: using guessed type __int64 (__fastcall *_do_global_dtors_aux_fini_array_entry)(); //----- (00000000000013F4) ---------------------------------------------------- void term_proc() { ; }
Extracción de la Flag
Si nos fijamos en las líneas 41 a la 45 vemos las siguientes cadenas:
a = «MdfnJk»
b = «jYx}»
c = «gWmfk»
d = «mlvpc»
f = «neU++w»
Usaremos las cadenas y los valores XOR especificados para cada rango de v5 en el main (líneas 123 a 182) para determinar los caracteres correctos.
Para v5 de 0 a 5: v6 = comprobacion(v4, a[v5], 5);
Significa que: v4 debe ser igual a a[v5] ^ 5
Para v5 de 6 a 9: v6 = comprobacion(v4, b[v5 – 6], 17);
Significa que: v4 debe ser igual a b[v5 – 6] ^ 17
Para v5 de 10 a 14: v6 = comprobacion(v4, c[v5 – 10], 8);
Significa que: v4 debe ser igual a c[v5 – 10] ^ 8
Para v5 de 15 a 19: v6 = comprobacion(v4, d[v5 – 15], 2);
Significa que: v4 debe ser igual a d[v5 – 15] ^ 2
Para v5 de 20 a 25: v6 = comprobacion(v4, f[v5 – 20], 10);
Significa que: v4 debe ser igual a f[v5 – 20] ^ 10
Cálculo de los caracteres correctos:
Para v5 de 0 a 5:
a[0] = ‘M’, M ^ 5 = 0x4D ^ 0x05 = 0x48 -> ‘H’
a[1] = ‘d’, d ^ 5 = 0x64 ^ 0x05 = 0x61 -> ‘a’
a[2] = ‘f’, f ^ 5 = 0x66 ^ 0x05 = 0x63 -> ‘c’
a[3] = ‘n’, n ^ 5 = 0x6E ^ 0x05 = 0x6B -> ‘k’
a[4] = ‘J’, J ^ 5 = 0x4A ^ 0x05 = 0x4F -> ‘O’
a[5] = ‘k’, k ^ 5 = 0x6B ^ 0x05 = 0x6E -> ‘n’
Resulta en la cadena: HackOn
Para v5 de 6 a 9:
b[0] = ‘j’, j ^ 17 = 0x6A ^ 0x11 = 0x7B -> ‘{‘
b[1] = ‘Y’, Y ^ 17 = 0x59 ^ 0x11 = 0x48 -> ‘H’
b[2] = ‘x’, x ^ 17 = 0x78 ^ 0x11 = 0x69 -> ‘i’
b[3] = ‘}’, } ^ 17 = 0x7D ^ 0x11 = 0x6C -> ‘l’
Resulta en la cadena: {Hil
Para v5 de 10 a 14:
c[0] = ‘g’, g ^ 8 = 0x67 ^ 0x08 = 0x6F -> ‘o’
c[1] = ‘W’, W ^ 8 = 0x57 ^ 0x08 = 0x5F -> ‘_’
c[2] = ‘m’, m ^ 8 = 0x6D ^ 0x08 = 0x65 -> ‘e’
c[3] = ‘f’, f ^ 8 = 0x66 ^ 0x08 = 0x6E -> ‘n’
c[4] = ‘k’, k ^ 8 = 0x6B ^ 0x08 = 0x63 -> ‘c’
Resulta en la cadena: o_enc
Para v5 de 15 a 19:
d[0] = ‘m’, m ^ 2 = 0x6D ^ 0x02 = 0x6F -> ‘o’
d[1] = ‘l’, l ^ 2 = 0x6C ^ 0x02 = 0x6E -> ‘n’
d[2] = ‘v’, v ^ 2 = 0x76 ^ 0x02 = 0x74 -> ‘t’
d[3] = ‘p’, p ^ 2 = 0x70 ^ 0x02 = 0x72 -> ‘r’
d[4] = ‘c’, c ^ 2 = 0x63 ^ 0x02 = 0x61 -> ‘a’
Resulta en la cadena: ontra
Para v5 de 20 a 25:
f[0] = ‘n’, n ^ 10 = 0x6E ^ 0x0A = 0x64 -> ‘d’
f[1] = ‘e’, e ^ 10 = 0x65 ^ 0x0A = 0x6F -> ‘o’
f[2] = ‘U’, U ^ 10 = 0x55 ^ 0x0A = 0x5F -> ‘_‘
f[3] = ‘+’, + ^ 10 = 0x2B ^ 0x0A = 0x21 -> ‘!’
f[4] = ‘+’, + ^ 10 = 0x2B ^ 0x0A = 0x21 -> ‘!’
f[5] = ‘w’, w ^ 10 = 0x77 ^ 0x0A = 0x7D -> ‘}’
Resulta en la cadena: do_!!}
Uniendo todas las partes, obtenemos la flag completa: HackOn{Hilo_enc_ontrado_!!}