Voyons aujourd’hui comment patcher un binaire directement avec RadaRE2. On reprend le même crackme que dans le premier tuto. Deux objectifs, marquer “Prout” dans la banner, et faire en sorte de gagner à tous les coups.
Chargeons le binaire en read-write, et affichons la string que l’on veut corrompre.
$ radare2 -w crackkids -- radare2 is for lulzhat [0x004004c0]> fs strings [0x004004c0]> f 0x0040071e 11 str.YouFailed 0x00400716 8 str.YouWin 0x00400711 5 str._16s 0x004006f0 33 str.ChalleasyforRadaredissection [0x004004c0]> psz@str.ChalleasyforRadaredissection Chall easy for Radare dissection
Maintenant on va changer cette chaine (write) puis l’afficher et afficher là où elle est en hexa
[0x004004c0]> w Prout @str.ChalleasyforRadaredissection [0x004004c0]> psz@str.easyforRadaredissection Prout for Radare dissection [0x004004c0]> px 64 @str.ChalleasyforRadaredissection - offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x004006f0 5072 6f75 7420 6561 7379 2066 6f72 2052 Prout easy for R 0x00400700 6164 6172 6520 6469 7373 6563 7469 6f6e adare dissection 0x00400710 0025 3136 7300 596f 7520 5769 6e00 596f .%16s.You Win.Yo 0x00400720 7520 4661 696c 6564 0000 0000 011b 033b u Failed.......;
Zut… Prout n’est pas une stringZ. Il faut ajouter un 0 à la fin du Prout si on veut que la chaine s’arrête. Heureusement cet oublis est rapidement corrigible grâce aux offsets.
[0x004004c0]> w \x00 @str.ChalleasyforRadaredissection+5 [0x004004c0]> px 64 @str.ChalleasyforRadaredissection - offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x004006f0 5072 6f75 7400 6561 7379 2066 6f72 2052 Prout.easy for R 0x00400700 6164 6172 6520 6469 7373 6563 7469 6f6e adare dissection 0x00400710 0025 3136 7300 596f 7520 5769 6e00 596f .%16s.You Win.Yo 0x00400720 7520 4661 696c 6564 0000 0000 011b 033b u Failed.......; [0x004004c0]> psz @str.ChalleasyforRadaredissection Prout
Fastoche non… Maintenant du code. On se rappelle le test STRCMP conditionne la victoire. c’était par là ; (Print dissasemble 10 instructions à partir de l’adresse mentionnée)
[0x004008c0]> pd 10 @0x0040060f | 0x0040060f e88cfeffff call sym.imp.strcmp | sym.imp.strcmp() | 0x00400614 85c0 test eax, eax | ,=< 0x00400616 750c jne loc.00400624 | | 0x00400618 bf16074000 mov edi, str.YouWin ; 0x00400716 | | 0x0040061d e85efeffff call sym.imp.puts | | sym.imp.puts() | ,==< 0x00400622 eb0a jmp loc.0040062e | || ; JMP XREF from 0x00400616 (fcn.0040059c) |- loc.00400624 17 | |`-> 0x00400624 bf1e074000 mov edi, str.YouFailed ; 0x0040071e | | 0x00400629 e852feffff call sym.imp.puts | | sym.imp.puts() | | ; JMP XREF from 0x00400622 (fcn.0040059c) |- loc.0040062e 7 | `--> 0x0040062e b800000000 mov eax, 0x0 | 0x00400633 c9 leave
Et on va faire sauter le saut après le test en 0x400616. On se fait plaisir, pas de Nop, trop facile, trop commun, tous le monde connait le code hexa à bourrer. Non, on va faire un saut super classe. (Write Assemble mon_code_asm @oujewrite)
[0x00400616]> wa jmp 0x00400618 @0x00400616 Written 2 bytes (jmp 0x00400618) = wx eb00 [0x00400616]> pd 10 @0x0040060f | 0x0040060f e88cfeffff call sym.imp.strcmp | sym.imp.strcmp() | 0x00400614 85c0 test eax, eax | ,=< 0x00400616 eb00 jmp 0x400618 ; (fcn.0040059c) | `-> 0x00400618 bf16074000 mov edi, str.YouWin ; 0x00400716 | 0x0040061d e85efeffff call sym.imp.puts | sym.imp.puts() | ,==< 0x00400622 eb0a jmp loc.0040062e | | ; JMP XREF from 0x00400616 (fcn.0040059c) |- loc.00400624 17 | | 0x00400624 bf1e074000 mov edi, str.YouFailed ; 0x0040071e | | 0x00400629 e852feffff call sym.imp.puts | | sym.imp.puts() | | ; JMP XREF from 0x00400622 (fcn.0040059c) |- loc.0040062e 7 | `--> 0x0040062e b800000000 mov eax, 0x0 | 0x00400633 c9 leave
Rien à sauver c’est déja fait en live. on quitte ..
Et c’est gagné !
$ ./crackkids Prout Yesssssss!!!anypass... You Win
Ce n’est qu’un petit exemple de ce que l’on peut faire avec les writes. Je pourrais tout aussi ajouter un “bout de code” repompé d’un fichier binaire.
[0x004004c0]> w? |Usage: w[x] [str] [<file] [<<EOF] [@addr] | w foobar write string 'foobar' | wh r2 whereis/which shell command | wr 10 write 10 random bytes | ww foobar write wide string 'f\x00o\x00o\x00b\x00a\x00r\x00' | wa push ebp write opcode, separated by ';' (use '"' around the command) | waf file assemble file and write bytes | wA r 0 alter/modify opcode at current seek (see wA?) | wb 010203 fill current block with cyclic hexpairs | wc[ir*?] write cache undo/commit/reset/list (io.cache) | wx 9090 write two intel nops | wv eip+34 write 32-64 bit value | wo? hex write in block with operation. 'wo?' fmi | wm f0ff set binary mask hexpair to be used as cyclic write mask | ws pstring write 1 byte for length and then the string | wf -|file write contents of file at current offset | wF -|file write contents of hexpairs file here | wp -|file apply radare patch file. See wp? fmi | wt file [sz] write to file (from current seek, blocksize or sz bytes)
bien joué tu m’as pas mal appris de truc sur radare2, je fouille un peu sur le net pour savoir à peu près comment l’utiliser. Si tu as deux trois tips , je suis la tu as cas voir mon blog
http://sakiir.fr
bonne soirée
Salut, merci à toi pour ces petits tutos qui sont parfaits pour une première approche. Ça permet de se mettre dans le bain de manière pratique. C’est très bien fait, bonne courbe de progression.
Ça me donne envie de m’investir dans RadaRE2 qui semble extrêmement prometteur !
Hackndo.
Faut surtout que je m’y remette, le Rarare a beaucoup évolué
I\’ll come back later then !