Reverse engineering di un semplice crackme

Jan 13 2023
Introduzione Salve a tutti, oggi illustrerò il mio processo mentale di reverse engineering di un semplice crackme e recupero di un flag crittografato. Il file a cui daremo un'occhiata è "f0rizen's find a real key" crackme.

introduzione

Ciao a tutti, oggi passerò attraverso il mio processo di pensiero di reverse engineering di un semplice crackme e recupero di un flag crittografato. Il file a cui daremo un'occhiata è "f0rizen's find a real key" crackme.

https://crackmes.one/crackme/629e1e5833c5d4251e72375f

Formato del file

La prima cosa che dovremmo fare prima di tentare di eseguire il file è identificare il tipo di file con cui stiamo lavorando.

$ file crackme
crackme: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped```

stringhe

Dopo aver identificato il tipo di file, mi piace eseguire le stringhe sull'applicazione data per vedere se riesco a trovare stringhe utili leggibili dall'uomo.

Dopo aver esaminato le stringhe all'interno dell'applicazione, ce ne sono alcune che mi colpiscono, principalmente "sup3r_s3cr3t_k3y_1337".

Siamo anche in grado di identificare l'utilizzo dell'applicazione, sembra accettare un solo argomento, il flag.

Vediamo se "sup3r_s3cr3t_k3y_1337" è la bandiera.

Sfortunatamente, "sup3r_s3cr3t_k3y_1337" non sembra essere la bandiera che stiamo cercando, sono necessarie ulteriori analisi per ottenere la bandiera.

Analisi statica

Apriamo questa cosa con il rizin-cutter e diamo un'occhiata a come funziona.

Dopo aver identificato la funzione principale all'offset 0x00001165, la prima cosa che mi colpisce è un array di 21 elementi che viene creato.

Possiamo anche vedere un puntatore all'indirizzo di "sup3r_s3cr3t_k3y_1337" a 0x000011dd, dove la stringa viene manipolata.

In poche parole, questo frammento di codice scorre "sup3r_s3cr3t_k3y_1337" e sposta ogni carattere della stringa di 0x22.

Un'altra scoperta interessante è un ciclo a 0x0010132c che itera attraverso ogni carattere della nostra chiave codificata e XOR lo fa con il nostro array di 21 elementi. Ho ripulito il codice decompilato qui:

// Loop through 21 elements
for (i = 0; i < 0x15; i = i + 1) {
  
   // XOR the hard-coded key with array elements
   if ((int)(char)(key[i] ^ *(byte *)((long)i + *(long *)(param_2 + 8))) != array[i]) {
      
      // If the flag is incorrect, the program ends     
      puts("Wrong flag");
      uVar1 = 1;
      goto 0x00101355;
   }
 }

Ora che abbiamo identificato lo schema di crittografia e la chiave codificata, vediamo se riusciamo a decifrare questa cosa con Python.

Per prima cosa, sappiamo che la chiave codificata è spostata di 0x22, quindi scriviamo uno script per fare proprio questo.

# Hard-coded key
key = "sup3r_s3cr3t_k3y_1337"

# Shift each character to the left by 0x22
for i in key:
  print(chr(ord(i) - 0x22), end = '')

Output: QSNP=QAPR=IW=

Prendiamo questa nuova chiave e vediamo se possiamo XOR con l'array di caratteri di prima.

# Hard-coded key
key = "sup3r_s3cr3t_k3y_1337"
new_key = ''

# Shift each character to the left by 0x22 and store in new_key
for i in key:
  new_key += chr(ord(i) - 0x22)

# Initialize array of characters
array = [ 0x37, 0x3f, 0x2f, 0x76,
          0x2b, 0x62, 0x28, 0x21,
          0x34, 0xf, 0x77, 0x62,
          0x48, 0x27, 0x75, 0x8,
          0x56, 0x6a, 0x68, 0x4e,
          0x68 ]

# XOR new_key with array of characters
for i, c in enumerate(array):
  print(chr(ord(new_key[i]) ^ c), end = '')

Output: flag{_y0u_f0und_key_}

Dopo aver eseguito lo script python, otteniamo l'output "flag{_y0u_f0und_key_}"! Possiamo quindi passarlo come argomento alla nostra applicazione e confermare che questa è, in effetti, la chiave corretta.