Outils d'utilisateurs

Outils du Site


ndh2k12_public:crackme:bukakke

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

ndh2k12_public:crackme:bukakke [2012/07/02 12:13]
TheLizardKing créée
ndh2k12_public:crackme:bukakke [2017/04/09 15:33] (Version actuelle)
Ligne 11: Ligne 11:
 Pour une raison que je ne sais pas expliquer, il est impossible de l'ouvrir avec IDA. C'est parti pour du full gdb ;-) ! Pour une raison que je ne sais pas expliquer, il est impossible de l'ouvrir avec IDA. C'est parti pour du full gdb ;-) !
  
-===== Main function =====+===== main function =====
  
 <code asm> <code asm>
Ligne 38: Ligne 38:
 De façon basique, le programme regarde s'il a au moins un argument en entrée. Si ce n'est pas le cas, il retourne un message d'erreur. Dans le cas contraire, il appel la fonction ''check'' avec ''argv[1]'' en argument. De façon basique, le programme regarde s'il a au moins un argument en entrée. Si ce n'est pas le cas, il retourne un message d'erreur. Dans le cas contraire, il appel la fonction ''check'' avec ''argv[1]'' en argument.
  
-===== Check function =====+===== check function =====
  
 +<code asm>
 +gdb$ disas check
 +Dump of assembler code for function check:
 +   0x08048ea2 <+0>: push   ebp
 +   0x08048ea3 <+1>: mov    ebp,esp
 +   0x08048ea5 <+3>: push   ebx
 +   0x08048ea6 <+4>: sub    esp,0x54
 +   0x08048ea9 <+7>: call   0x8048bcc <__x86.get_pc_thunk.bx>
 +   0x08048eae <+12>: add    ebx,0x9d1ae
 +   0x08048eb4 <+18>: mov    BYTE PTR [ebp-0x28],0x3
 +   0x08048eb8 <+22>: mov    BYTE PTR [ebp-0x27],0x23
 +   0x08048ebc <+26>: mov    BYTE PTR [ebp-0x26],0x1f
 +   0x08048ec0 <+30>: mov    BYTE PTR [ebp-0x25],0x23
 +   0x08048ec4 <+34>: mov    BYTE PTR [ebp-0x24],0x5
 +   0x08048ec8 <+38>: mov    BYTE PTR [ebp-0x23],0x3
 +   0x08048ecc <+42>: mov    BYTE PTR [ebp-0x22],0x8
 +   0x08048ed0 <+46>: mov    BYTE PTR [ebp-0x21],0x7
 +   0x08048ed4 <+50>: mov    BYTE PTR [ebp-0x20],0x1f
 +   0x08048ed8 <+54>: mov    BYTE PTR [ebp-0x1f],0x4
 +   0x08048edc <+58>: mov    BYTE PTR [ebp-0x1e],0x5
 +   0x08048ee0 <+62>: mov    BYTE PTR [ebp-0x1d],0x20
 +   0x08048ee4 <+66>: mov    BYTE PTR [ebp-0x1c],0x21
 +   0x08048ee8 <+70>: mov    BYTE PTR [ebp-0x1b],0x7
 +   0x08048eec <+74>: mov    BYTE PTR [ebp-0x1a],0x1f
 +   0x08048ef0 <+78>: mov    BYTE PTR [ebp-0x19],0x5
 +   0x08048ef4 <+82>: mov    BYTE PTR [ebp-0x18],0x21
 +   0x08048ef8 <+86>: mov    BYTE PTR [ebp-0x17],0x5
 +   0x08048efc <+90>: mov    BYTE PTR [ebp-0x16],0x4
 +   0x08048f00 <+94>: mov    BYTE PTR [ebp-0x15],0x1d
 +   0x08048f04 <+98>: mov    BYTE PTR [ebp-0x14],0x22
 +   0x08048f08 <+102>: mov    BYTE PTR [ebp-0x13],0x1e
 +   0x08048f0c <+106>: mov    BYTE PTR [ebp-0x12],0x1f
 +   0x08048f10 <+110>: mov    BYTE PTR [ebp-0x11],0x26
 +   0x08048f14 <+114>: mov    BYTE PTR [ebp-0x10],0x25
 +   0x08048f18 <+118>: mov    BYTE PTR [ebp-0xf],0x1f
 +   0x08048f1c <+122>: mov    BYTE PTR [ebp-0xe],0x1e
 +   0x08048f20 <+126>: mov    BYTE PTR [ebp-0xd],0x21
 +   0x08048f24 <+130>: mov    BYTE PTR [ebp-0xc],0x24
 +   0x08048f28 <+134>: mov    BYTE PTR [ebp-0xb],0x6
 +   0x08048f2c <+138>: mov    BYTE PTR [ebp-0xa],0x24
 +   0x08048f30 <+142>: mov    BYTE PTR [ebp-0x9],0x25
 +   0x08048f34 <+146>: mov    DWORD PTR [esp+0x8],0x20
 +   0x08048f3c <+154>: mov    eax,DWORD PTR [ebp+0x8]
 +   0x08048f3f <+157>: mov    DWORD PTR [esp+0x4],eax     ; push notre serial passé en argument
 +   0x08048f43 <+161>: lea    eax,[ebp-0x48]
 +   0x08048f46 <+164>: mov    DWORD PTR [esp],eax         ; push l'adresse de ebp-0x48
 +   0x08048f49 <+167>: call   0x8048cf5 <WhatisIt>        ; WhatisIt([ebp-0x48], argv[1]);
 +   0x08048f4e <+172>: lea    eax,[ebp-0x28]
 +   0x08048f51 <+175>: mov    DWORD PTR [esp+0x4],eax     ; push l'adresse de ebp-0x28
 +   0x08048f55 <+179>: lea    eax,[ebp-0x48]
 +   0x08048f58 <+182>: mov    DWORD PTR [esp],eax         ; psuh l'adresse de ebp-0x48
 +   0x08048f5b <+185>: call   0x8048cb4 <ccc>             ; ccc([ebp-0x48], [ebp-0x28]);
 +   0x08048f60 <+190>: test   eax,eax                     ; eax = 0 ?
 +   0x08048f62 <+192>: je     0x8048f7b <check+217>       ; si oui, jmp en check+217
 +   0x08048f64 <+194>: mov    eax,DWORD PTR [ebp+0x8]
 +   0x08048f67 <+197>: mov    DWORD PTR [esp+0x4],eax     ; push argv[1]
 +   0x08048f6b <+201>: lea    eax,[ebx-0x23b30]      
 +   0x08048f71 <+207>: mov    DWORD PTR [esp],eax         ; push "The hash is %s\n"
 +   0x08048f74 <+210>: call   0x8049960 <printf>          ; printf("The hash is %s\n",argv[1]);
 +   0x08048f79 <+215>: jmp    0x8048f89 <check+231>       ; jmp après le "Wrong password"
 +   0x08048f7b <+217>: lea    eax,[ebx-0x23b20]           ; jmp ici si ccc renvois 0
 +   0x08048f81 <+223>: mov    DWORD PTR [esp],eax         
 +   0x08048f84 <+226>: call   0x8049990 <puts>            ; printf("Wrong password !\n")
 +   0x08048f89 <+231>: mov    DWORD PTR [esp],0x1 
 +   0x08048f90 <+238>: call   0x8049770 <exit>            ; exit(1);
 +End of assembler dump.
 +
 +</code>
 +
 +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 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>
 +gdb$ disas 0x8048cb4
 +Dump of assembler code for function ccc:
 +   0x08048cb4 <+0>: push   ebp
 +   0x08048cb5 <+1>: mov    ebp,esp
 +   0x08048cb7 <+3>: sub    esp,0x10
 +   0x08048cba <+6>: mov    DWORD PTR [ebp-0x4],0x0       ; ebp-0x4 <- 0 (initialisation)
 +   0x08048cc1 <+13>: jmp    0x8048ce8 <ccc+52>            ; début d'une boucle
 +   0x08048cc3 <+15>: mov    eax,DWORD PTR [ebp-0x4]       ; eax <- ebp-0x4 (compteur)
 +   0x08048cc6 <+18>: mov    edx,DWORD PTR [ebp+0x8]       ; edx <- une chaine bizarre 
 +   0x08048cc9 <+21>: add    eax,edx
 +   0x08048ccb <+23>: movzx  edx,BYTE PTR [eax]            ; prend le char N°eax de la chaine bizarre
 +   0x08048cce <+26>: mov    eax,DWORD PTR [ebp-0x4]       ; eax <- ebp-0x4 (compteur)
 +   0x08048cd1 <+29>: mov    ecx,DWORD PTR [ebp+0xc]       ; ecx <- une seconde chaine bizarre
 +   0x08048cd4 <+32>: add    eax,ecx
 +   0x08048cd6 <+34>: movzx  eax,BYTE PTR [eax]            ; prend le char N°eax de la seconde chaine bizarre
 +   0x08048cd9 <+37>: cmp    dl,al                         ; compare les deux chars
 +   0x08048cdb <+39>: je     0x8048ce4 <ccc+48>            ; ils sont égaux
 +   0x08048cdd <+41>: mov    eax,0x0                       ; si non, eax <- 0
 +   0x08048ce2 <+46>: jmp    0x8048cf3 <ccc+63>            ; on sort de la fonction ! (return 0) <=> le serial n'est pas le bon
 +   0x08048ce4 <+48>: add    DWORD PTR [ebp-0x4],0x1       ; si les deux chars sont égaux, on incrémente de 1 le compteur
 +   0x08048ce8 <+52>: cmp    DWORD PTR [ebp-0x4],0x1f      ;
 +   0x08048cec <+56>: jbe    0x8048cc3 <ccc+15>            ; la boucle tourne 32 fois (ça fait tilt?)
 +   0x08048cee <+58>: mov    eax,0x1
 +   0x08048cf3 <+63>: leave  
 +   0x08048cf4 <+64>: ret    
 +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>
 +
 +''ebp+0x8'' correspond donc au serial que nous avons entré et ''ebp+0xc'' au serial que nous devons entrer.
 +
 +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!
 +
 +<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** :-)
ndh2k12_public/crackme/bukakke.1341223985.txt.gz · Dernière modification: 2017/04/09 15:33 (modification externe)