0x00400186 push rbp
0x00400187 mov rbp, rsp
0x0040018a mov eax, 1
0x0040018f mov edi, 1
0x00400194 movabs rsi, str.____x64_NASM_Keygen_Me_n_A__root_me____n____Login_:_____Key_:__n_o___Yeah__good_jwrite_a_keygen_:__n_n_...__THE_GAME_n.m.key ; section..data:
; 0x4000b0 ; "[!] x64 NASM Keygen-Me\n[A] root-me \n[?] Login : [\o/] Yeah, good job bro, now write a keygen \n\n[.|..] THE GAME\n.m.key"
0x0040019e mov edx, 0x32 ; '2' ; 50
0x004001a3 syscall
;eax uguale a 1, la syscall chiamata è la write che stampa la stringa
;"[!] x64 NASM Keygen-Me\n[A] root-me \n[?] Login : [\o/] Yeah, good job bro, now write a keygen \n\n[.|..] THE GAME\n.m.key".
0x004001a5 mov eax, 0
0x004001aa mov edi, 0
0x004001af movabs rsi, segment.LOAD1 ; 0x600260
0x004001b9 mov edx, 0x20 ; 32
0x004001be syscall
;in questo caso la syscall chiamata è la read, che legge dallo standard input 32 caratteri e li va a memorizzare nel segmento di memoria puntato da rsi, segment.LOAD1 che si trova all'indirizzo 0x600260; movabs carica una costante arbitraria a 64 bit nel registro.
0x004001c0 mov eax, 2
0x004001c5 movabs rdi, 0x40012e
0x004001cf mov esi, 0
0x004001d4 syscall
;eax uguale a 2, la syscall chiamata è la open che cerca di aprire il file .m.key nella directory dove è stato lanciato l'eseguibile.
0x004001d6 cmp rax, 0xfffffffffffffffe
0x004001da je 0x400215
;se in rax abbiamo un valore negativo (il valore di ritorno della open), vuol dire che il file .m.key non è stato trovato, quindi c'è un'istruzione di jump alla funzione di uscita.
;open(".m.key", O_RDONLY) = -1 ENOENT (File o directory non esistente)
;in questo codice, confrontare con -2 (0xfffffffffffffffe in complemento a due) potrebbe essere un modo per gestire l'errore in modo più esplicito o identificare in modo univoco l'errore specifico di "No such file or directory" utilizzando il suo valore errno corrispondente, anziché fare affidamento su -1.
0x004001dc push rax
0x004001dd mov rdi, rax
0x004001e0 mov eax, 0
0x004001e5 movabs rsi, 0x600280
0x004001ef mov edx, 0x20 ; 32
0x004001f4 syscall
;qui legge la keygen dal file .m.key, se lo trova nella directory dove è stato lanciato l'eseguibile.
0x004001f6 movabs rdi, segment.LOAD1 ; 0x600260 ; int64_t arg1
0x00400200 movabs rsi, 0x600280
0x0040020a call fcn.00400146
;passa alla funzione fcn.00400146, attraverso i registri rdi e rsi, le due stringhe, quella inserita in input e quella letta dal file .m.key; funzione che farà il check della keygen.
0x0040020f cmp rax, 0
0x00400213 je 0x400232
;se il valore di ritorno di questa funzione è 0, la keygen ha superato il controllo e otteniamo un messaggio di successo.
0x00400215 mov eax, 1
0x0040021a mov edi, 1
0x0040021f movabs rsi, 0x40011d ; "\n[.|..] THE GAME\n.m.key"
0x00400229 mov edx, 0x11 ; 17
0x0040022e syscall
0x00400230 jmp 0x40024d
;altrimenti verrà stampata la stringa "\n[.|..] THE GAME\n.m.key" e salterà alla exit.
0x00400232 mov eax, 1
0x00400237 mov edi, 1
0x0040023c movabs rsi, 0x4000ec ; "\n[\o/] Yeah, good job bro, now write a keygen \n\n[.|..] THE GAME\n.m.key"
0x00400246 mov edx, 0x31 ; '1' ; 49
0x0040024b syscall
0x0040024d mov rsp, rbp
0x00400250 pop rbp
0x00400251 mov eax, 0x3c ; '<' ; 60
0x00400256 mov edi, 0
0x0040025b syscall
;stampa la stringa "\n[\o/] Yeah, good job bro, now write a keygen \n\n[.|..] THE GAME\n.m.key" in caso di successo ed esce, o esce soltanto, in caso di insuccesso.
fcn.00400146
0x00400146 call fcn.00400135
0x0040014b cmp rax, 1 ; 1
0x0040014f je 0x40017b
;qui controlla se abbia solo un carattere in ingresso; questo perchè nel menù fake che viene stampato dall'eseguibile ci sono 3 opzioni relative ad un solo carattere, per creare confusione; se trova un solo carattere salta in un punto in cui rax viene valorizzato con il valore 0x1337 e poi esce; questo perchè per validare la keygen, la funzione chiamante ha bisogno del valore 0.
0x00400151 mov rbx, rax
;rbx viene valorizzata con la lunghezza della stringa.
0x00400154 xor rdx, rdx
0x00400157 xor rcx, rcx
0x0040015a xor rax, rax
;inizializza un po' di roba a 0.
0x0040015d sub rbx, 1
;sottrae alla lunghezza della stringa 1 per non considerare il carattere null.
0x00400161 cmp rcx, rbx
0x00400164 je 0x400182
;confronta il contatore con la lunghezza della stringa e salta se non è uguale; quindi rcx verrà man mano incrementato.
0x00400166 mov dl, byte [rdi + rcx]
0x00400169 mov dh, byte [rsi + rcx]
;eax 32 bit
;ax 16 bit
;al 8 bit (un carattere)
;ah 8 bit (un carattere)
;quindi in dx, nelle due parti che lo costituiscono, abbiamo due caratteri.
;i due caratteri iesimi delle due stringhe, quella in input e quella letta dal file .m.key, nei registri a 8 bit, dl e dh.
0x0040016c mov al, dl
0x0040016e sub al, cl
0x00400170 add al, 0x14 ; 20
0x00400172 cmp al, dh
;valorizza al con il carattere iesimo della stringa inserita in input, a cui sottrae il valore dell'indice cl e aggiunge 0x14 in esadecimale (20 in decimale); se avessimo il carattere 'a' nella prima posizione della stringa in input, il carattere giusto da trovare nella prima posizione della keygen sarebbe 'u'; perchè il carattere 'a' in decimale è 97, meno 0 che è l'indice della prima posizione, è sempre 97, +20 è 117 che è la rappresentazione decimale del carattere ASCII 'u'
;se avessimo come stringa in ingresso la stringa "abcd", la keygen giusta che passerebbe il controllo sarebbe "uuuu", come è facile verificare con dei semplici calcoli.
;la keygen giusta per superare la challenge è la keygen relativa alla stringa di ingresso "root-me.org"
;valori decimali della stringa "root-me.org"
;114 111 111 116 45 109 101 46 111 114 103
;valori decimali della stringa keygen giusta
;134 130 129 133 61 124 115 59 123 125 113
;attravero il sito CyberChef
https://gchq.github.io/CyberChef/, mettiamo nel box di input i valori decimali della stringa keygen giusta e salviamo l'output prodotto nel file download.dat; per verificare la correttezza della keygen, facciamo una mv del file download.dat in .m.key, il file della keygen e immettiamo come stringa di input "root-me.org"; a questo punto per superare la challange facciamo l'hashing sha256 del file .m.key e inseriamo questo hashing come password della challenge del sito root-me.org.
0x00400174 jne 0x40017b
0x00400176 inc rcx
0x00400179 jmp 0x400161
;se i due caratteri non sono uguali salta, valorizza rax con il valore esadecimale 0x1337 e salta all'exit; in caso contrario incrementa rcx e torna indietro.
0x0040017b mov eax, 0x1337 ; '7\x13'
0x00400180 jmp 0x400185
;imposta eax con il valore esadecimale 0x1337 e salta alla ret in modo da non avere 0 in rax come valore di ritorno della funzione.
0x00400182 xor rax, rax
0x00400185 ret
;xor rax, rax equivale all'istruzione mov rax, 0.