Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.
ndh2k12_public:crackme:bukakke [2012/07/02 13:08] TheLizardKing [WhatisIt function] |
ndh2k12_public:crackme:bukakke [2017/04/09 15:33] (Version actuelle) |
||
---|---|---|---|
Ligne 109: | Ligne 109: | ||
</code> | </code> | ||
- | Bon, on voit un certains nombre de ''mov [ebp-xx],0xyy'', je décide de ne pas y prêter attention pour le moment. On remarque surtout l'appel à la fonction ''WhatisIt'' avec laquelle notre serial est passé en argument, ainsi que l'appel à ''ccc'' qui passe en argument quelque chose stocké en ''ebp-0x28'' ainsi que ''ebp-0x48''. Ceci parait louche, d'autant qu'il y a un certain nombre de ''mov'' sur l'''ebp''. La suite du programme dépend de ce que renvois ''ccc'' dans ''eax''. Si c'est un 0, le serial n'est pas le bon, si c'est autre chose, le mot de passe est le bon. | + | Bon, on voit un certain nombre de ''mov [ebp-xx],0xyy'', je décide de ne pas y prêter attention pour le moment. On remarque surtout l'appel à la fonction ''WhatisIt'' avec laquelle notre serial est passé en argument, ainsi que l'appel à ''ccc'' qui passe en argument quelque chose stocké en ''ebp-0x28'' ainsi que ''ebp-0x48''. Ceci parait louche, d'autant qu'il y a un certain nombre de ''mov'' sur l'''ebp''. La suite du programme dépend de ce que renvoie ''ccc'' dans ''eax''. Si c'est un 0, le serial n'est pas le bon, si c'est autre chose, le mot de passe est le bon. |
Il ne nous reste plus qu'à regarder ce que font ''WhatisIt'' et ''ccc''. | Il ne nous reste plus qu'à regarder ce que font ''WhatisIt'' et ''ccc''. | ||
- | ===== WhatisIt function ===== | + | Il est probable que la fonction ''WhatisIt'' soit là pour chiffrer notre serial et calculer celui d'origine. Je décide d'essayer de résoudre le challenge en regardant uniquement la fonction ''ccc''. |
+ | |||
+ | ===== ccc function ===== | ||
<code asm> | <code asm> | ||
- | gdb$ disas WhatisIt | + | gdb$ disas 0x8048cb4 |
- | Dump of assembler code for function WhatisIt: | + | Dump of assembler code for function ccc: |
- | 0x08048cf5 <+0>: push ebp | + | 0x08048cb4 <+0>: push ebp |
- | 0x08048cf6 <+1>: mov ebp,esp | + | 0x08048cb5 <+1>: mov ebp,esp |
- | 0x08048cf8 <+3>: sub esp,0x60 | + | 0x08048cb7 <+3>: sub esp,0x10 |
- | 0x08048cfb <+6>: mov BYTE PTR [ebp-0x34],0x5a | + | 0x08048cba <+6>: mov DWORD PTR [ebp-0x4],0x0 ; ebp-0x4 <- 0 (initialisation) |
- | 0x08048cff <+10>: mov BYTE PTR [ebp-0x33],0x43 | + | 0x08048cc1 <+13>: jmp 0x8048ce8 <ccc+52> ; début d'une boucle |
- | 0x08048d03 <+14>: mov BYTE PTR [ebp-0x32],0x58 | + | 0x08048cc3 <+15>: mov eax,DWORD PTR [ebp-0x4] ; eax <- ebp-0x4 (compteur) |
- | 0x08048d07 <+18>: mov BYTE PTR [ebp-0x31],0x4a | + | 0x08048cc6 <+18>: mov edx,DWORD PTR [ebp+0x8] ; edx <- une chaine bizarre |
- | 0x08048d0b <+22>: mov BYTE PTR [ebp-0x30],0x59 | + | 0x08048cc9 <+21>: add eax,edx |
- | ; ..........................etc....................... | + | 0x08048ccb <+23>: movzx edx,BYTE PTR [eax] ; prend le char N°eax de la chaine bizarre |
- | 0x08048dff <+266>: mov BYTE PTR [ebp-0x3c],0x1d | + | 0x08048cce <+26>: mov eax,DWORD PTR [ebp-0x4] ; eax <- ebp-0x4 (compteur) |
- | 0x08048e03 <+270>: mov BYTE PTR [ebp-0x3b],0x1e | + | 0x08048cd1 <+29>: mov ecx,DWORD PTR [ebp+0xc] ; ecx <- une seconde chaine bizarre |
- | 0x08048e07 <+274>: mov BYTE PTR [ebp-0x3a],0x1f | + | 0x08048cd4 <+32>: add eax,ecx |
- | 0x08048e0b <+278>: mov BYTE PTR [ebp-0x39],0x20 | + | 0x08048cd6 <+34>: movzx eax,BYTE PTR [eax] ; prend le char N°eax de la seconde chaine bizarre |
- | 0x08048e0f <+282>: mov BYTE PTR [ebp-0x38],0x21 | + | 0x08048cd9 <+37>: cmp dl,al ; compare les deux chars |
- | 0x08048e13 <+286>: mov BYTE PTR [ebp-0x37],0x22 | + | 0x08048cdb <+39>: je 0x8048ce4 <ccc+48> ; ils sont égaux |
- | 0x08048e17 <+290>: mov BYTE PTR [ebp-0x36],0x23 | + | 0x08048cdd <+41>: mov eax,0x0 ; si non, eax <- 0 |
- | 0x08048e1b <+294>: mov BYTE PTR [ebp-0x35],0x24 | + | 0x08048ce2 <+46>: jmp 0x8048cf3 <ccc+63> ; on sort de la fonction ! (return 0) <=> le serial n'est pas le bon |
- | 0x08048e1f <+298>: mov DWORD PTR [ebp-0x10],0x0 | + | 0x08048ce4 <+48>: add DWORD PTR [ebp-0x4],0x1 ; si les deux chars sont égaux, on incrémente de 1 le compteur |
- | 0x08048e26 <+305>: mov DWORD PTR [ebp-0x4],0x0 | + | 0x08048ce8 <+52>: cmp DWORD PTR [ebp-0x4],0x1f ; |
- | 0x08048e2d <+312>: jmp 0x8048e9a <WhatisIt+421> ; jump en bas --> début d'une boucle | + | 0x08048cec <+56>: jbe 0x8048cc3 <ccc+15> ; la boucle tourne 32 fois (ça fait tilt?) |
- | 0x08048e2f <+314>: mov DWORD PTR [ebp-0x8],0x0 ; début de la boucle | + | 0x08048cee <+58>: mov eax,0x1 |
- | 0x08048e36 <+321>: jmp 0x8048e90 <WhatisIt+411> | + | 0x08048cf3 <+63>: leave |
- | 0x08048e38 <+323>: mov edx,DWORD PTR [ebp-0x4] ; compteur de boucle | + | 0x08048cf4 <+64>: ret |
- | 0x08048e3b <+326>: mov eax,DWORD PTR [ebp+0xc] ; eax <- serial | + | |
- | 0x08048e3e <+329>: add eax,edx ; | + | |
- | 0x08048e40 <+331>: movzx edx,BYTE PTR [eax] ; récup le char N°edx du serial | + | |
- | 0x08048e43 <+334>: lea ecx,[ebp-0x34] | + | |
- | 0x08048e46 <+337>: mov eax,DWORD PTR [ebp-0x8] | + | |
- | 0x08048e49 <+340>: add eax,ecx | + | |
- | 0x08048e4b <+342>: movzx eax,BYTE PTR [eax] | + | |
- | 0x08048e4e <+345>: cmp dl,al | + | |
- | 0x08048e50 <+347>: jne 0x8048e8c <WhatisIt+407> | + | |
- | 0x08048e52 <+349>: mov DWORD PTR [ebp-0xc],0x0 | + | |
- | 0x08048e59 <+356>: jmp 0x8048e86 <WhatisIt+401> | + | |
- | 0x08048e5b <+358>: lea edx,[ebp-0x59] | + | |
- | 0x08048e5e <+361>: mov eax,DWORD PTR [ebp-0xc] | + | |
- | 0x08048e61 <+364>: add eax,edx | + | |
- | 0x08048e63 <+366>: movzx eax,BYTE PTR [eax] | + | |
- | 0x08048e66 <+369>: movzx eax,al | + | |
- | 0x08048e69 <+372>: cmp eax,DWORD PTR [ebp-0x8] | + | |
- | 0x08048e6c <+375>: jne 0x8048e82 <WhatisIt+397> | + | |
- | 0x08048e6e <+377>: mov edx,DWORD PTR [ebp-0x10] | + | |
- | 0x08048e71 <+380>: mov eax,DWORD PTR [ebp+0x8] | + | |
- | 0x08048e74 <+383>: add eax,edx | + | |
- | 0x08048e76 <+385>: mov edx,DWORD PTR [ebp-0xc] | + | |
- | 0x08048e79 <+388>: add edx,0x3 | + | |
- | 0x08048e7c <+391>: mov BYTE PTR [eax],dl | + | |
- | 0x08048e7e <+393>: add DWORD PTR [ebp-0x10],0x1 | + | |
- | 0x08048e82 <+397>: add DWORD PTR [ebp-0xc],0x1 | + | |
- | 0x08048e86 <+401>: cmp DWORD PTR [ebp-0xc],0x23 | + | |
- | 0x08048e8a <+405>: jle 0x8048e5b <WhatisIt+358> | + | |
- | 0x08048e8c <+407>: add DWORD PTR [ebp-0x8],0x1 | + | |
- | 0x08048e90 <+411>: cmp DWORD PTR [ebp-0x8],0x23 ; le début jump ici | + | |
- | 0x08048e94 <+415>: jle 0x8048e38 <WhatisIt+323> ; jmp si ebp-0x8 <= 0x23 | + | |
- | 0x08048e96 <+417>: add DWORD PTR [ebp-0x4],0x1 | + | |
- | 0x08048e9a <+421>: cmp DWORD PTR [ebp-0x4],0x1f ; ebp-0x4 == 0x1f ? | + | |
- | 0x08048e9e <+425>: jle 0x8048e2f <WhatisIt+314> ; jmp si ebp-0x4 <= 0x1f ebp-0x4 vaut 0 au début, 0x1f=31, la boucle tournerais donc 32 fois (ça fait tilt ?) | + | |
- | 0x08048ea0 <+427>: leave | + | |
- | 0x08048ea1 <+428>: ret | + | |
End of assembler dump. | End of assembler dump. | ||
+ | </code> | ||
+ | Bon, on remarque très facilement que c'est une boucle qui vérifie si deux chaines sont les mêmes. A partir de la première différence, on sort de la boucle. Il ne nous reste plus qu'à savoir à quoi correspondent les deux chaines. L'une doit probablement correspondre à notre serial et l'autre au serial à trouver. Elles ont certainement été calculées par la fonction ''WhatisIt'' que nous avons choisi de ne pas regarder. | ||
+ | |||
+ | Pour arriver à trouver quelle chaine correspond à quoi, il suffit de lancer le programme deux fois, avec deux serials différent et de regarder laquelle des deux valeurs a changé ! | ||
+ | |||
+ | <code> | ||
+ | gdb$ b *0x08048cd9 | ||
+ | Breakpoint 1 at 0x8048cd9 | ||
+ | gdb$ r 1337 | ||
+ | Breakpoint 1, 0x08048cd9 in ccc () | ||
+ | gdb$ i r $eax | ||
+ | eax 0x3 0x3 | ||
+ | gdb$ i r $edx | ||
+ | edx 0x1e 0x1e | ||
+ | gdb$ r BBBB | ||
+ | Breakpoint 1, 0x08048cd9 in ccc () | ||
+ | gdb$ i r $eax | ||
+ | eax 0x3 0x3 | ||
+ | gdb$ i r $edx | ||
+ | edx 0x4 0x4 | ||
</code> | </code> | ||
- | // J'ai raccourci un peu le code ;-) // | + | ''ebp+0x8'' correspond donc au serial que nous avons entré et ''ebp+0xc'' au serial que nous devons entrer. |
- | Bon, on remarque une boucle avec beaucoup de conditions. On a surtout l'impression que ceci est fait pour nous embrouiller. On fait ça méthodiquement pour ne pas se faire berner ;-) | + | On remarque aussi que la valeur de ''eax'' n'a pas changé dans les deux cas. On sait aussi qu'il faut que l'on trouve un hash de 32 caractères. Très vite, on suppose qu'il est juste question d'une substitution, il ne nous reste qu'à recréer la table. Rien de plus simple! |
- | ===== ccc function ===== | + | <code> |
+ | gdb$ b *0x08048cc9 | ||
+ | Breakpoint 1 at 0x8048cc9 | ||
+ | gdb$ r 0123456789ABCDEF | ||
+ | --------------------------------------------------------------------------[regs] | ||
+ | EAX: 0x00000000 EBX: 0x080E605C ECX: 0xBFFFF6A4 EDX: 0xBFFFF6F0 o d I t S z A P C | ||
+ | ESI: 0x08049580 EDI: 0x08049620 EBP: 0xBFFFF6D8 ESP: 0xBFFFF6C8 EIP: 0x08048CC9 | ||
+ | CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B | ||
+ | --------------------------------------------------------------------------[code] | ||
+ | => 0x8048cc9 <ccc+21>: add eax,edx | ||
+ | 0x8048ccb <ccc+23>: movzx edx,BYTE PTR [eax] | ||
+ | 0x8048cce <ccc+26>: mov eax,DWORD PTR [ebp-0x4] | ||
+ | 0x8048cd1 <ccc+29>: mov ecx,DWORD PTR [ebp+0xc] | ||
+ | 0x8048cd4 <ccc+32>: add eax,ecx | ||
+ | 0x8048cd6 <ccc+34>: movzx eax,BYTE PTR [eax] | ||
+ | 0x8048cd9 <ccc+37>: cmp dl,al | ||
+ | 0x8048cdb <ccc+39>: je 0x8048ce4 <ccc+48> | ||
+ | -------------------------------------------------------------------------------- | ||
+ | Breakpoint 1, 0x08048cc9 in ccc () | ||
+ | gdb$ x/s $edx | ||
+ | 0xbffff6f0: "\035\036\037 !\"#$%&\003\004\005\006\a\b\025\n\a\016\016m\016\b" | ||
+ | gdb$ si 4 | ||
+ | --------------------------------------------------------------------------[regs] | ||
+ | EAX: 0x00000000 EBX: 0x080E605C ECX: 0xBFFFF710 EDX: 0x0000001D o d I t S z a P c | ||
+ | ESI: 0x08049580 EDI: 0x08049620 EBP: 0xBFFFF6D8 ESP: 0xBFFFF6C8 EIP: 0x08048CD4 | ||
+ | CS: 0073 DS: 007B ES: 007B FS: 0000 GS: 0033 SS: 007B | ||
+ | --------------------------------------------------------------------------[code] | ||
+ | => 0x8048cd4 <ccc+32>: add eax,ecx | ||
+ | 0x8048cd6 <ccc+34>: movzx eax,BYTE PTR [eax] | ||
+ | 0x8048cd9 <ccc+37>: cmp dl,al | ||
+ | 0x8048cdb <ccc+39>: je 0x8048ce4 <ccc+48> | ||
+ | 0x8048cdd <ccc+41>: mov eax,0x0 | ||
+ | 0x8048ce2 <ccc+46>: jmp 0x8048cf3 <ccc+63> | ||
+ | 0x8048ce4 <ccc+48>: add DWORD PTR [ebp-0x4],0x1 | ||
+ | 0x8048ce8 <ccc+52>: cmp DWORD PTR [ebp-0x4],0x1f | ||
+ | -------------------------------------------------------------------------------- | ||
+ | 0x08048cd4 in ccc () | ||
+ | gdb$ x/s $ecx | ||
+ | 0xbffff710: "\003#\037#\005\003\b\a\037\004\005 !\a\037\005!\005\004\035\"\036\037&%\037\036!$\006$%\200\225\004\b" | ||
+ | </code> | ||
+ | |||
+ | // Note: il faut prendre uniquement les 16 premiers chars de la chaine ;-)// | ||
+ | |||
+ | On récupère aussi au passage le vrai hash stocké dans ''ecx''. (uniquement les 32 premiers chars sont à prendre en compte) | ||
+ | |||
+ | ^ CHAR ^ code (décimal) ^ | ||
+ | | 0 | 29 | | ||
+ | | 1 | 30 | | ||
+ | | 2 | 31 | | ||
+ | | 3 | 32 | | ||
+ | | 4 | 33 | | ||
+ | | 5 | 34 | | ||
+ | | 6 | 35 | | ||
+ | | 7 | 36 | | ||
+ | | 8 | 37 | | ||
+ | | 9 | 38 | | ||
+ | | A | 3 | | ||
+ | | B | 4 | | ||
+ | | C | 5 | | ||
+ | | D | 6 | | ||
+ | | E | 7 | | ||
+ | | F | 8 | | ||
+ | |||
+ | On code un petit truc en python, et le tour est joué ! | ||
+ | |||
+ | <code python> | ||
+ | #!/usr/bin/env python | ||
+ | # encoding: utf-8 | ||
+ | |||
+ | def main(): | ||
+ | |||
+ | table = {"29":"0", | ||
+ | "30":"1", | ||
+ | "31":"2", | ||
+ | "32":"3", | ||
+ | "33":"4", | ||
+ | "34":"5", | ||
+ | "35":"6", | ||
+ | "36":"7", | ||
+ | "37":"8", | ||
+ | "38":"9", | ||
+ | "3":"A", | ||
+ | "4":"B", | ||
+ | "5":"C", | ||
+ | "6":"D", | ||
+ | "7":"E", | ||
+ | "8":"F"}; | ||
+ | |||
+ | serial = "\003#\037#\005\003\b\a\037\004\005 !\a\037\005!\005\004\035\"\036\037&%\037\036!$\006$%" | ||
+ | decrypt = "" | ||
+ | for char in serial: | ||
+ | decrypt += table[str(ord(char))] | ||
+ | |||
+ | print decrypt | ||
+ | |||
+ | if __name__ == '__main__': | ||
+ | main() | ||
+ | </code> | ||
+ | |||
+ | <code> | ||
+ | $ ./crackme $(./bukkake.py) | ||
+ | The hash is A626CAFE2BC34E2C4CB0512982147D78 | ||
+ | </code> | ||
+ | On valide avec **A626CAFE2BC34E2C4CB0512982147D78** :-) |