====== pacman ====== ===== Analysis ===== on a un binaire sans info de debug avec addresses statiques {{:screenshot_2025-07-13_002444.png?nolink|}} strings nous retourne rien d'interessant ltrace montre un appel a memcmp{{:screenshot_2025-07-13_002610.png?nolink|}} ===== Reversing ===== la premiere chose qu'on peut faire c'est ouvrir dans gdb et chopper la valeur attendue {{:screenshot_2025-07-13_003101.png?nolink|}} la signature de memcmp c'est int memcmp(const void *s1, const void *s2, size_t n); et en gros sur x86_64 les registres deviennent rdi = s1 rsi = s2 rdx = n donc on va garder nos deux valeurs au cas ou {{:screenshot_2025-07-13_003426.png?nolink|}} ==== Ghidra ==== ok maintenant on va ouvrir dans ghidra voir ce qui se passe vu qu'on a pas les infos de debug on va se fier au entry trouve par ghidra apres renomage d'un peu de fonctions (avec GhidraMCP on va pas mentir) on a un truc du genre /* WARNING: Restarted to delay deadcode elimination for space: stack */ void entry(undefined8 param_1,undefined8 param_2,undefined8 param_3) { transform_and_check(exit_or_abort,0x2f4,&DAT_004041db); exit_or_abort(param_1,param_2,param_3); return; } dans transform and check on a void transform_and_check(void) { encrypt_loop(); bit_rotate_buffer(); xor_and_subtract_buffer(); return; } dans encrypt loop void encrypt_loop(int *data_buffer,ulong buffer_length) { undefined1 auVar1 [16]; int round_result; long lVar2; ulong uVar3; buffer_length = buffer_length / 4; auVar1._8_8_ = 0; auVar1._0_8_ = buffer_length; lVar2 = SUB168((ZEXT816(0) << 0x40 | ZEXT816(0x34)) / auVar1,0) + 6; uVar3 = buffer_length; do { while (uVar3 = uVar3 - 1, uVar3 != 0) { round_result = encrypt(); data_buffer[uVar3] = data_buffer[uVar3] - round_result; } round_result = encrypt(); *data_buffer = *data_buffer - round_result; lVar2 = lVar2 + -1; uVar3 = buffer_length; } while (lVar2 != 0); return; } encrypt ulong encrypt(undefined8 param_1,undefined8 param_2,long key_ptr,undefined8 param_4,ulong v0, ulong v1) { ulong in_R10; ulong in_R11; ulong unaff_R13; return (v0 << 2 ^ v1 >> 5) + (v0 >> 3 ^ v1 << 4) ^ (in_R10 ^ v0) + (*(uint *)(key_ptr + (in_R11 & 3 ^ unaff_R13) * 4) ^ v1); } bit rotate void bit_rotate_buffer(byte *byte_buffer,long buffer_length) { byte *pbVar1; pbVar1 = byte_buffer + buffer_length; do { *byte_buffer = *byte_buffer >> 3 | *byte_buffer << 5; byte_buffer = byte_buffer + 1; } while (byte_buffer != pbVar1); return; } xor and sub void xor_and_subtract_buffer(byte *byte_buffer,long buffer_length) { byte *pbVar1; pbVar1 = byte_buffer + buffer_length; do { *byte_buffer = *byte_buffer - 0x37; *byte_buffer = *byte_buffer ^ 0xaa; byte_buffer = byte_buffer + 1; } while (byte_buffer != pbVar1); return; } du coup a ce stade l'idee c'est de reimplementer ca de notre cote, voir si quand on passe notre input de 11111[...] on obtient la meme valeur que la reference et si c'est le cas, implementer l'algo d'encryption en reverse...