Packer sans ta mère level II prerequis II le PEB

Il y a 5 mois que je vous ai laissé tomber au milieu de cette série de post. Je me rend compte qu’il faut y avancer un peu car sinon tenter d’expliquer le dernier packer au plus grand nombre sans perdre quelques personne ne sera pas aisé.

On avait précédemment regardé comment était emmanché un exécutable dans la mémoire d’un Windows et survolé le concept d’EAT et IAT. Aujourd’hui on va voir une structure rigolote et indispensable le PEB.

Le PEB alias Process Environnement Bloc est une structure dite opaque (en clair peu documenté officiellement, voir documentée sur le tard, où normalement un programme normal est pas supposé s’y pointer).

C’est un pan de mémoire maintenu par windows pour chacun des process et qui va donner des informations vaste et variées. On peut par exemple trouver l’offset qui nous dira où est mappé en mémoire notre exécutable. On peut aussi savoir si le processe est débuggé ou pas. etc…

L’offset de la PEB  est toujours disponible en regardant dans FS[0x30]  en 32 bits ou GS[0x60] en 64 bits. A chaque instant il suffit de lire ce dword/qword et on connait l’adresse du PEB. Généralement en 32bits vers 7FFDxxxx tachez d’arriver à repérer un offset de cette trempe.

Microsoft documente un peu le PEB dans son MSDN mais c’est assez minable. Heureusement en 32 bits Ollydbg connait cette structure à fond. Elle est directement visible dans Olly depuis la fenêtre de memory map (Alt+M).

Screen Shot 2014-05-24 at 0.16.11

Et il sait aussi décoder cette structure ce qui est TRÈS pratique.

Screen Shot 2014-05-24 at 0.19.31

Donc que peut t’on faire concrètement avec cet structure ? Premièrement de l’anti-debug avec l’info qui traine dans ce PEB. Il y a deux grand classique;

mov ebx,fs[0x30] ; PEB offset dans EBX
cmp byte ptr [ebx+2], 0 ; Beingdebugged = False ? 
jne .processisdebugged  ; Sinon débuggé !!!

C’est pareil que d’appeler la fonction de kernel32 IsDebuggerPresent, sauf que là, pas besoin de la déclarer une fonction et pas besoin non plus d’appeler une fonction ! tout n’est qu’access mémoire.

Le second anti-débug possible est plus étrange;

mov ebx,fs[0x30] ; PEB offset dans EBX
cmp byte ptr [ebx+0x68], 0x70 ; les Debug Flags sont là ? 
je .processisdebugged  ; Sinon débuggé !!!

Celui la se base sur le fait qu’un process débuggé à normalement 3 flags de mis dans le PEB

  • 0x10 pour HEAP_ENABLE_TAIL_CHECK
  • 0x20 pour HEAP_ENABLE_FREE_CHECK
  • 0x40 pour HEAP_VALIDATE_PARAMETERS

Pour être au top sur ces anti debug, je vous invite a lire le chapitre 2.1 et 2.2 de “The Art of Unpacking” de Mark Vincent Yason;

Bien sur généralement l’accès à fs[0x30] est caché de toutes les façons du monde, petit exemple :

push ss
mov eax, 6  
push fs
shl eax, 3   ; EAX = 6*8 = 0x30
pop ss
mov ebx,ss[eax] ; ebx = PEB
pop ss

On peut trouver aussi l’offset du PEB par une autre méthode, il est laissé par windows dans le registre EBX à l’entry point d’un programme x32.

Mais le PEB ne sert pas qu’a tester de debugging;

Il contient des infos sur le nombre de CPU (si c’est 1.. en 2014, c’est probablement une VM !). Il peut servir pour déterminer la version de windows(+0xA4 et +0xA8), il contient l’adresse de base de l’exécutable (+0x8) et enfin l’adresse d’une structure nommée LoaderData ou PPEB_LDR_DATA (en +0xC)

Cette dernière structure va nous permettre de retrouver l’offset où est mappé en mémoire les DLL nécessaire à notre exécutable. (A minima kernel32 et ntdll).

Vous l’aurez compris grâce à cela, on va pouvoir parser l’EAT de ces DLL et retrouver les offset des fonctions en mémoire afin de pourvoir les appeller sans avoir à les déclarer dans l’IAT de notre programme, bref un GetProcAddresseA mais totalement discret.

On verra cela la prochaine fois. mais retenez, si vous voyez passer un FS[0x30] ou un GS[0x60] Inquiétez vous !

Posted in Reverse, Windows | Tagged , , | 2 Comments

IDAPYTHON pour nommer les appels indirects aux fonctions

Après avoir recherché partout et fatigué tout le monde via IRC, je n’ai pas trouvé de solution sympa pour résoudre automatiquement les noms de fonction dans IDA quand les appels à celles-ci ne sont pas déclarées dans l’IAT.

Bon, j’ai perdu un lecteur ou deux, Je m’explique;

Par exemple, si je veux faire un programme windows qui pond une messagebox, cet appel de fonctions sera déclarée dans l’IAT et la DLL responsable de la fonction pour ce popup sera elle aussi déclarée et chargée à l’initialisation de l’executable. Cette publicité inattendue est peu souhaité par l’écrivain de malware. Celui-ci préfère éviter de déclarer les fonctions qu’il utilise. Et c’est du travail de se cacher.

J’ai pondu un petit exemple dans le github : https://github.com/Th4nat0s/Chall_Tools/tree/master/asm/hellostealth

Ce n’est pas le but aujourd’hui d’expliquer comment retrouver l’offset d’une fonctions en parsant la table d’EAT d’une dll; Mais en deux mots;  Ici je retrouve les adresse des fonctions à partir d’un hash de leur nom grâce à une petite procédure qui parse l’EAT de la dll chargée en mémoire (un grand classique).

Grosso modo dans tous les cas il faut passer par les étapes suivantes :

 ; Récupère la base addresse de Kernel32 
    invokel _getdll,HASH_KERNEL32.DLL
 ; Récupère l'offset de la fonctions LoadLibraryA
    invokel _getfunction, eax, HASH_LOADLIBRARYA
    mov [FN_LOADLIBRARY], EAX
 ; Charge user32.dll
    invokel [FN_LOADLIBRARY],str_user32
 ; Récupère l'addresse de base de user32.dll  
    invokel _getdll,HASH_USER32.DLL
 ; Récupère l'offset le la fonctions
    invokel _getfunction, eax, HASH_MESSAGEBOXA
    mov [FN_MSGBOX], EAX
  ; Appelle la popup discretos
    invokel [FN_MSGBOX], 0, txt1, txt1, 0
  ; Appel de fonction "Traditionnel" pour quitter  
  invoke _ExitProcess@4, NULL

Une fois compilé, notre appel à MSGBOX est totalement incognito dans la table d’import

$ rabin2 -i nop.exe 
[Imports]
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=kernel32.dll_ExitProcess

1 imports

Et dans ida, rien n’est résolu et nous on ne sait pas trop ce qu’il se passe.

public start
start proc near
push    1C9513FBh
call    sub_40205A
push    0BF89D44Eh
push    eax
call    sub_4020AE
mov     dword_40301A, eax
push    offset aUser32_dll ; "user32.dll"
call    dword_40301A
push    1015679Ah
call    sub_40205A
push    2181CB52h
push    eax
call    sub_4020AE
mov     dword_40301E, eax
push    0
push    offset aHelloDeclared ; "Hello Declared"
push    offset aHelloDeclared ; "Hello Declared"
push    0
call    dword_40301E
push    0               ; uExitCode
call    ExitProcess
start endp

Et pour cause… Rien n’est initialisé, les appels sont cachés.

.data:00403000 aHelloDeclared  db 'Hello Declared',0   ; DATA XREF: start+41o
.data:00403000                                         ; start+46o
.data:0040300F aUser32_dll     db 'user32.dll',0       ; DATA XREF: start + 1Ao
.data:0040301A dword_40301A    dd 0                    ; DATA XREF: start+15w
.data:0040301A                                         ; start+1Fr
.data:0040301E dword_40301E    dd 0                    ; DATA XREF: start+3Aw
.data:0040301E                                         ; start+4Dr

La solution facile dans ce cas là, si l’auteur du malware est sympas et charge tous les offset de fonctions dans une procédure pas loin du démarrage, c’est de dumper le process dans olly après résolution. A partir de là les offsets sont remplis.

.data:00403000 aHelloDeclared  db 'Hello Declared',0   ; DATA XREF: start+41o
.data:00403000                                         ; start+46o
.data:0040300F aUser32_dll     db 'user32.dll',0       ; DATA XREF: start+1Ao
.data:0040301A dword_40301A    dd 7C801D7Bh            ; DATA XREF: start+15w
.data:0040301A                                         ; start+1Fr
.data:0040301E dword_40301E    dd 7E4507EAh            ; DATA XREF: start+3Aw
.data:0040301E                                         ; start+4Dr

Si on utilise olly on peut connaitre l’offset de la dite fonction et se transformer en Champollion. (View > Executable Modules > Bouton Droit > Show File in all module)

Screen Shot 2014-05-22 at 1.11.32

Bon là ca va il y en a que deux fonctions à trouver, mais avec un petit droppeur ou un malware, au bout de la 50eme c’est assez pénible. D’ou le script du jour.

Etape 1, sauver la liste de “All Names”  dans c:\temp\export.txt.

Etape 2, Se rendre ensuite dans IDA avec Python d’actif , mettre le curseur dans une fonction et faire Shift + F7 puis sélectionner ce script magique :  https://github.com/Th4nat0s/Chall_Tools/blob/master/ollylink.py

Etape 3, hurler de joie, ce qui était non renommé et inconnu en Dword_ et qui a trouvé correspondance dans une table d’export est enfin nommé. IDA fait le reste pour mettre les commentaires adaptés.

[+] Loaded 8071 DLL functions
[+] IDA Got 4 Data Ref in 3 Subfunctions in Seg 402000
[+] Find 2 Api call out of 2 unknown ref
public start
start proc near
push    1C9513FBh
call    sub_40205A
push    0BF89D44Eh
push    eax
call    sub_4020AE
mov     LoadLibraryA, eax
push    offset aUser32_dll ; "user32.dll"
call    LoadLibraryA
push    1015679Ah
call    sub_40205A
push    2181CB52h
push    eax
call    sub_4020AE
mov     MessageBoxA, eax
push    0
push    offset aHelloDeclared ; "Hello Declared"
push    offset aHelloDeclared ; "Hello Declared"
push    0
call    MessageBoxA
push    0               ; uExitCode
call    ExitProcess
start endp
.data:00403000 aHelloDeclared  db 'Hello Declared',0   ; DATA XREF: start+41o
.data:00403000                                         ; start+46o
.data:0040300F aUser32_dll     db 'user32.dll',0       ; DATA XREF: start+1Ao
.data:0040301A ; HMODULE __stdcall LoadLibraryA(LPCSTR lpLibFileName)
.data:0040301A LoadLibraryA    dd 7C801D7Bh            ; DATA XREF: start+1w
.data:0040301A                                         ; start+1Fr
.data:0040301E ; int __stdcall MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
.data:0040301E MessageBoxA     dd 7E4507EAh            ; DATA XREF: start+3Aw
.data:0040301E                                         ; start+4Dr

Voila qui est mieux.

Posted in Asm, Reverse | Tagged , , | 2 Comments

Le Droppeur du jour, label231486.pdf – Part 2

Suite de l’analyse de la facture de chez DHL :) On le dépacke !

Le dit sample est dispo dans AvCaesar chez Malware.lu mais on n’y apprend pas grand chose de plus. A première vue, on n’arrivera pas a dépacker en statique. (Enfin pas moi quoi). Que ce soit radare ou Ida c’est mal partis.

[0x00408340]> pdf@0x00408340
Do you want to print 191849 chars? (y/N)

Screen Shot 2014-05-17 at 6.20.04 Voyons comment on peut louvoyer pour dépacker le bignou avec OllyDbg dans une VM sous Fusion. Si quelqu’un a des TIPs pour aller encore plus vite, je suis preneur ! En analysant la table d’import on tombe sur une ou deux fonctions chelou. C’est d’ailleurs étonnant qu’il y ait autant de fonctions déclarées pour un truc packé.

$ rabin2 -i 1.exe 
[Imports]
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=COMDLG32.dll_PageSetupDlgW
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=AVIFIL32.dll_AVISaveOptionsFree
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=SHELL32.dll_DragFinish
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_TerminateProcess
ordinal=002 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_GetUserDefaultLCID
ordinal=003 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_ReadFile
ordinal=004 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_GetFileInformationByHandle
ordinal=005 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_GetFileAttributesW
ordinal=006 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_WriteFile
ordinal=007 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_lstrcpynW
ordinal=008 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_SetEndOfFile
ordinal=009 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_GetCurrentProcess
ordinal=010 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_GetLocaleInfoW
ordinal=011 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_CreateFileW
ordinal=012 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_IsDebuggerPresent
ordinal=013 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_lstrcpyW
ordinal=014 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_UnhandledExceptionFilter
ordinal=015 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_SetUnhandledExceptionFilter
ordinal=016 plt=0x00000000 bind=NONE type=FUNC name=KERNEL32.dll_IsProcessorFeaturePresent
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=WINSPOOL.DRV_ClosePrinter
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_UnhookWinEvent
ordinal=002 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetWindowTextW
ordinal=003 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetSystemMetrics
ordinal=004 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_LoadImageW
ordinal=005 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_CharLowerW
ordinal=006 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_SetWinEventHook
ordinal=007 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_TranslateMessage
ordinal=008 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_MessageBeep
ordinal=009 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_CreateWindowExW
ordinal=010 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_EnableWindow
ordinal=011 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetDlgItem
ordinal=012 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_IsDialogMessageW
ordinal=013 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_ShowWindow
ordinal=014 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetParent
ordinal=015 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetDesktopWindow
ordinal=016 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_SetActiveWindow
ordinal=017 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_LoadStringW
ordinal=018 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_IsClipboardFormatAvailable
ordinal=019 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_UpdateWindow
ordinal=020 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetWindowLongW
ordinal=021 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetCursorPos
ordinal=022 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_GetDlgCtrlID
ordinal=023 plt=0x00000000 bind=NONE type=FUNC name=USER32.dll_SetCursor
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=ADVAPI32.dll_RegOpenKeyExW
ordinal=002 plt=0x00000000 bind=NONE type=FUNC name=ADVAPI32.dll_RegOpenKeyExA
ordinal=003 plt=0x00000000 bind=NONE type=FUNC name=ADVAPI32.dll_RegQueryValueExA
ordinal=004 plt=0x00000000 bind=NONE type=FUNC name=ADVAPI32.dll_RegCreateKeyW
ordinal=001 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_StartPage
ordinal=002 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_GetObjectW
ordinal=003 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_CreateDCW
ordinal=004 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_GetTextFaceW
ordinal=005 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_GetDeviceCaps
ordinal=006 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_StartDocW
ordinal=007 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_EnumFontsW
ordinal=008 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_TextOutW
ordinal=009 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_CreatePalette
ordinal=010 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_GetWindowOrgEx
ordinal=011 plt=0x00000000 bind=NONE type=FUNC name=GDI32.dll_GetTextExtentPoint32W

58 imports

Donc je le renomme en 2.exe comme le veut le précédent batch au cas ou et  je le charge dans Olly. Là on met un breakpoint dans kernel32.dll sur les fonctions habituelles.

(Pour breaker on se rappelle, View > Executable Modules > Mickey Bouton Droit > Show Name > F2 pour breaker) Screen Shot 2014-05-17 at 6.44.34 En plus de cela à coté un Russinovich Process monitor afin de récolter les potentielles lectures/écriture dans la registry et/ou fichiers. Et c’est partis. Screen Shot 2014-05-17 at 7.04.23 Cela break en 0x422477 à l’appel à VirtualAlloc et un nouveau segment en 0x33000 est alloué en Read Write Execute. Coté registry de l’étrange, 200 clef de cet acabit on été testée. pas une n’a de sens.

07:05:56,6524924	2.exe	2412	RegQueryKey	HKCU\Software\Classes	SUCCESS	Query: Name
07:05:56,6525133	2.exe	2412	RegOpenKey	HKCU\Software\Classes\m7VBct	NAME NOT FOUND	
07:05:56,6525442	2.exe	2412	RegOpenKey	HKCR\m7VBct	NAME NOT FOUND	
07:05:56,6525969	2.exe	2412	RegQueryKey	HKCU\Software\Classes	SUCCESS	Query: Name
07:05:56,6526179	2.exe	2412	RegOpenKey	HKCU\Software\Classes\eF5dl	NAME NOT FOUND	
07:05:56,6526496	2.exe	2412	RegOpenKey	HKCR\eF5dl	NAME NOT FOUND	

A partir de là, (Snapshot vmware !!)  et je vais lancer le mode trace de demander en plus à Olly de breaker quand il devra executer quelque chose dans le range nouvellement alloué. (ctrl-T puis hit trace dans «Trace») Screen Shot 2014-05-17 at 7.12.53   Quand enfin olly break, dans ce nouveau segment, on se dit qu’on est pas sortis du bois. nous voici dans le stage2 du packeur, une succession de “une a deux instructions, jump” bref du code spaghetti. Petit example remis dans l’ordre :

Address   Hex dump          Command                                  Comments
003309A7    C0CE 18          ROR DH,18                               ; Shift out of range
003309AA    0F9AC6           SETPE DH
003309AD    D2E8             SHR AL,CL
003309AF    55               PUSH EBP
003309B0  ^ E9 71F6FFFF      JMP 00330026

00330026    8BEC             MOV EBP,ESP
00330028    E9 CE050000      JMP 003305FB

003305FB    81C4 F8DBFFFF    ADD ESP,-2408
00330601    E9 F6190000      JMP 00331FFC

00331FFC    8B45 04          MOV EAX,DWORD PTR SS:[EBP+4]
00331FFF    E9 72120000      JMP 00333276

Bref… c’est pas humain a suivre. Donc on fait le contraire, je trace et je demande à Olly de s’arrêter si on sort du segment avec le code spaghetti. Screen Shot 2014-05-17 at 7.32.07 Et je relance le hit trace. Et là PAF… on sombre dans l’étrange… Packer/Thanat0s 1-0 !… Screen Shot 2014-05-17 at 7.34.23 Là on apprend plein de chose; Premièrement Olly se plain qu’on lui à changé un breakpoint par un 0x00. Normalement le breakpoint software alias l’instruction Int3 , c’est 0xCC en hexa et il est posé en lieu et place de l’instruction que l’on veut arrêter. Ca c’est le signe que notre stage2 chipote dans le code. Amis polymorphes bonjour. Donc il va falloir faire gaffe avec les breakpoint software.

En plus le code tripoté est pas dans le segment que nous suivons mais dans le segment 0x400000 bref là ou il y avait le code loadé initialement. Cela veut dire que le code original de l’executable est remplacé.

Ensuite, l’EIP est arrivé en 0x7FFDE000 qui l’addresse notre PEB, le process environnement bloc, c’est un bout de mémoire avec  une structure certes essentielle mais qui n’est absolument pas supposé être exécutée. Ca n’a pas de sens !

Coté registry cela comment à devenir compréhensible. Il semblerai que l’on soit dans les tests offensifs. Le packer cherche NOD32. Etonnant de la part d’un fichier issus d’un spam qui dit être déjà passé par cet antivirus, n’en doutons pas c’est surement pour nous éviter un second et inutile test :)

07:33:08,2232110	2.exe	2412	RegOpenKey	HKLM\SOFTWARE\ESET	NAME NOT FOUND	Desired Access: Read

Quoi qu’il en soit.. Il a gagné, l’exe va au crash. Déjà, voyons ou s’est passé cet read dans la registry à la recherche de l’antivirus. Pour cela bonne nouvelle Russinovich sauve l’état de la stack à l’appel de la fonction le lecture de la clef de registre. Screen Shot 2014-05-17 at 8.09.54 Après l’appel à ADVAPI32 pour lire la registry le programme est supposé retourner en 0x33b5b il y a donc fort à parier que l’instruction de devant c’est notre fameux call. Et effectivement si on regarde le code, on tombe sur un call EAX

Address   Hex dump          Command                                  Comments
00332B53      9BDAFFFF    JMP 003305F3
00332B58      46             INC ESI
00332B59      FFD0           CALL EAX
00332B5B      E9 A50A0000    JMP 00333605

On reprend donc notre snapshot vmware, . Dans la mesure ou le code se modifie de partout et qu’étonnamment 0x33B59 tombe en plein milieu de deux instructions on va utiliser un break point hardware ce coup ci (Shift+F5). Screen Shot 2014-05-17 at 8.26.08 Et on lance, cela confirme que c’est bien là qu’il faut breaker si on veut éviter le test avec node 32. Petit truc, en examinant un peut plus haut la stack on retrouve l’adresse de base de la DLL ADVAPI32. (Struct IMAGE_DOS_HEADER) cela est un bon indicateur que le packer parse lui meme les dll à la recherche des adresse des fonctions et que la table d’import originale n’est qu’un leurre. Screen Shot 2014-05-17 at 8.37.17 Bon, ca c’était pour le fun.. J’ai pas NOD32.

Maintenant gérons notre crash quand il nous a envoyé nous balader sur le PEB. On reprend le snapshot vmware au moment du crash et on va analyser la pile.

Address   Value      ASCII Comments
0012FFBC   00401235  5@   ; RETURN from 2.00401239 to 2.00401235
0012FFC0   7FFDE000   àý
0012FFC4   7C81776F  ow|  ; RETURN to kernel32.7C81776F
0012FFC8   0012ADB0  °­
0012FFCC   00140000    
0012FFD0   7FFDE000   àý
0012FFD4   8054B6ED  í¶T€  ; RETURN from 8054626C to 8054B6ED

Au dessus de 7FFDE00 on retrouve l’offset de retour d’une fonction en 0x401235 et on est passé par la juste avant le crash. Et oui vu qu’il modifie le code, il a réussis son coup le packeur, mais le breakpoint du trace n’a pas fonctionné.  Pas grave on sait où regarder… Regardons la fonction autour de cette adresse.

CPU Disasm
Address   Hex dump          Command                                  Comments
00401235      BA DCEE0059    MOV EDX,5900EEDC
0040123A      8B09          .MOV ECX,DWORD PTR DS:[ECX]
0040123C      58            .POP EAX
0040123D      8B00          .MOV EAX,DWORD PTR DS:[EAX]
0040123F      29C8          .SUB EAX,ECX
00401241      C1E0 08       .SHL EAX,8
00401244      6A 03         .PUSH 3
00401246      0FC8          .BSWAP EAX
00401248      89C1          .MOV ECX,EAX
0040124A      58            .POP EAX
0040124B      F7E1          .MUL ECX
0040124D      64:8B18       .MOV EBX,DWORD PTR FS:[EAX]
00401250      807B 02 00    .CMP BYTE PTR DS:[EBX+2],0
00401254      74 02         .JE SHORT 00401258
00401256      53            .PUSH EBX
00401257      C3            .RETN
00401258      BE 05124000    MOV ESI,00401205

On reprend notre snapshot, et comme le code se modifie, on break en hardware en 0x401235. Arrivé en 0x40124D tout s’explique. Toute la mamaille entre 0x401235 et 0x40124B sert uniquement à mettre 0x30 dans EAX. Et FS:[0x30] c’est à retenir, cela pointe le PEB. Du coup ce qu’il se passe en fait. C’est un test d’anti debugging. le fameux PEB!BEINGDEBUGGED C’est cela en clair:

.MOV EBX,DWORD PTR FS:[30]    EBX = @PEB
.CMP BYTE PTR DS:[EBX+2],0    @PEB+2 == 0 ?
.JE SHORT 00401258            SAUTE si pas débuggé

Dump - Process Environment Block
Address   Hex dump      Decoded data             Comments
7FFDE000   .  00        DB 00                    ; InheritedAddressSpace = 0
7FFDE001   .  00        DB 00                    ; ReadImageFileExecOptions = 0
7FFDE002   .  01        DB 01                    ; BeingDebugged = TRUE
7FFDE003   .  00        DB 00                    ; SpareBool = FALSE
7FFDE004   .  FFFFFFFF  DD FFFFFFFF              ; Mutant = INVALID_HANDLE_VALUE
7FFDE008   .  00004000  DD OFFSET 2.<STRUCT IMAG ; ImageBaseAddress = 00400000

Donc si je débugge, il le sent,il pousse l’offset du PEB et jumpe dessus ce qui conduit à mon crash. Il faut donc sauter en 0x401258 pour passer outre l’antidebug. On recommence, snapshot, hdw breakpoint sur 0x401254 et on rebranche avec «bouton droit > New origin here »quand on à la main. 401245 Si on step un peu, on passe par une petite procédure qu’on va retrouver plusieurs fois encore et qui xor un énième pan de mémoire dans le bloc mémoire 0x40000 avec des 0x5E.

Address   Hex dump          Command                                  Comments
0040125F      6A 22         PUSH 22
00401261      59            POP ECX
00401262      AC            LODS BYTE PTR DS:[ESI]
00401263      34 5E         XOR AL,5E
00401265      AA            STOS BYTE PTR ES:[EDI]
00401266      E2 FA         LOOP SHORT 00401262

Et enfin on retombe sur un peu le même soucis qui conduit au crash, la faute à ce bout de code :

Address   Hex dump          Command                                  Comments
00401205      6A 70         PUSH 70
00401207      59            POP ECX
00401208      394B 68       CMP DWORD PTR DS:[EBX+68],ECX
0040120B      75 02         JNE SHORT 0040120F
0040120D      57            PUSH EDI
0040120E      C3            RETN
0040120F      BE 00104000   MOV ESI,00401000
00401214      89F7          MOV EDI,ESI

C’est un autre test d’anti debugging. le fameux PEB!NTGLOBALFLAG . arrivé en 0x401208, EBX pointe sur le PEB et  quand on débuggue, les flags HEAP_ENABLE_TAIL_CHECK, HEAP_ENABLE_FREE_CHECK et HEAP_VALIDATE_PARAMETERS sont mis. Du coup on se fait gauler. Il faut jumper en 0x40120F pour bypasser ce test. Petite aparté non primordiale mais classique, quand juste après après avoir re xoré encore un coup un pan de code avec 0x5E  on tombe sur ce genre de code, c’est intéressant.

Ce genre de code est un classique, Voici un exemple typique d’un parseur de EAT qui va s’occuper de chercher l’addresse d’une fonction dans une DLL. cette fonction est appelée avec un hash, ce hash est le nom de la fonction ou chaque lettre est décalée d’un octet et xorée avec ce qu’il y a avant (voir 0x401115 et 0x40118).  Bref c’est une fonction obfusquée qui fait le même travail que GetProcAddress

Address   Hex dump          Command                                  Comments
004010F1      60            PUSHAD
004010F2      89C5          MOV EBP,EAX
004010F4      89D3          MOV EBX,EDX
004010F6      8B7B 3C       MOV EDI,DWORD PTR DS:[EBX+3C]
004010F9      8B7C1F 78     MOV EDI,DWORD PTR DS:[EBX+EDI+78]
004010FD      01DF          ADD EDI,EBX
004010FF      57            PUSH EDI
00401100      8B4F 18       MOV ECX,DWORD PTR DS:[EDI+18]
00401103      8B57 20       MOV EDX,DWORD PTR DS:[EDI+20]
00401106      01DA          ADD EDX,EBX
00401108      49            DEC ECX
00401109      51            PUSH ECX
0040110A      8B348A        MOV ESI,DWORD PTR DS:[ECX*4+EDX]
0040110D      01DE          ADD ESI,EBX
0040110F      89F0          MOV EAX,ESI
00401111      31C9          XOR ECX,ECX
00401113      3228          XOR CH,BYTE PTR DS:[EAX]
00401115      C1C1 08       ROL ECX,8
00401118      30E9          XOR CL,CH
0040111A      40            INC EAX
0040111B      8038 00       CMP BYTE PTR DS:[EAX],0
0040111E    ^ 75 F3         JNE SHORT 00401113
00401120      39E9          CMP ECX,EBP
00401122      59            POP ECX
00401123    ^ 75 E3         JNE SHORT 00401108
00401125      5F            POP EDI
00401126      8B47 24       MOV EAX,DWORD PTR DS:[EDI+24]
00401129      01D8          ADD EAX,EBX
0040112B      0FB70C48      MOVZX ECX,WORD PTR DS:[ECX*2+EAX]
0040112F      8B47 1C       MOV EAX,DWORD PTR DS:[EDI+1C]
00401132      01D8          ADD EAX,EBX
00401134      8B0488        MOV EAX,DWORD PTR DS:[ECX*4+EAX]
00401137      01D8          ADD EAX,EBX
00401139      894424 1C     MOV DWORD PTR SS:[ESP+1C],EAX
0040113D      61            POPAD

Il est toujours juteux de breaker sur cette fonction car on peut y apprendre quel sont les fonctions que le packers souhaite utiliser sans oser les déclarer. En breakant sur le mov avant le popad on découvre donc les fonctions :

  • ntdll.NtAllocateVirtualMemory
  • ntdll.NtTerminateProcess

Et maintenant on sait avec quoi il alloue ses pans de mémoire. Le debug continue et on s’arrête désormais (merci olly) au chargement de la DLL msasn1.dll qui est en fait appelée par le chargement de crypt32.dll. Si on prend les calltrace (View > CallStack) dans olly, on découvre que notre loadlibrary est appelé depuis 0x36343d. Fichtre encore un nouveau segment avec du code. Stage 3 ! Screen Shot 2014-05-17 at 16.10.00 Et là on est très heureux, il semblerai que le segment 0x360000 soit enfin le bon. En 0x361000 plein de strings bien claires et du code pile poil en 0x36500. Screen Shot 2014-05-17 at 16.17.02 Bon, on est presque au bout, mais il nous faut juste un entry point propre. Bref s’arrêter au plus tôt dans le code exécuté dans le segment 0x36000. On reprend le dernier snapshot et on ajoute un breakpoint sur le NTAllocateVirtualmemory découvert plus tot. Au terme d’un peu de steeping on arrive enfin au Graal

Address   Hex dump          Command                                  Comments
004010DB      01DA          ADD EDX,EBX
004010DD      6A 00         PUSH 0
004010DF      55            PUSH EBP
004010E0      68 3E4A4000   PUSH 00404A3E                            ; ASCII "00002"
004010E5      FFD2          CALL EDX
004010E7      6A 00         PUSH 0
004010E9      6A FF         PUSH -1
004010EB      FF15 09104000 CALL DWORD PTR DS:[401009]

EDX contient 0x364A00 notre EntryPoint ! Le call Dword[0x401009] d’après contient NTTerminateProcess.

VICTORY !   Au final on sais le dépacker avec ces 3 steps.

  • Mettre 3 hardware Breakpoints en execution qui ne semblent pas n’avoir de sens en 0x401254 et  0x40120b et 0x4010E5
  • On aide à passer les deux anti-debug
  • Au break sur 0x4010E5 on dump le segment pointé par EDX et dont l’entry point est EDX.

Donc je repart depuis le début et je suis ces 3 steps.. ce coup-ci c’est le segment 0x9C0000 qui est alloué pour notre stage 3 (précédemment 0x360000)

Arrivé là on tape un peut dans le code et on assemble un mov edx pour aider a faire marcher le call EDX

Address   Hex dump          Command                                  Comments
004010D2      90            NOP
004010D3      90            NOP
004010D4      BA 004A9C00   MOV EDX,9C4A00
004010D9      90            NOP
004010DA      90            NOP
004010DB      90            NOP
004010DC      90            NOP
004010DD      6A 00         PUSH 0
004010DF      55            PUSH EBP
004010E0      68 3E4A4000   PUSH 00404A3E                            ; ASCII "00002"
004010E5      FFD2          CALL EDX
004010E7      6A 00         PUSH 0
004010E9      6A FF         PUSH -1
004010EB      FF15 09104000 CALL DWORD PTR DS:[401009]
004010F1      60            PUSHAD

Et on dump avec le plugin OllyDumpEX le segment 40000 et 9C4A00 (ici celui pointé par EDX) Dépacké enfin ! On set l’entry point sur notre bidouille.

Screen Shot 2014-05-20 at 1.54.31

Bingo on l’a dépacké le bignou

$ strings final.exe  | egrep "th|he|in|an|re|nd|at|on|nt|ha|es|http"
shell32
urlmon
HelpLink
dbghelp
vmware
:Zone.Identifier
cmd=getload&login=
http://www.msn.com/
User-Agent: %s
Connection: close
User-Agent: %s
Connection: close
Content-Length: %d
Content-Type: application/x-www-form-urlencoded
&doubles=1
&personal=ok
&removed=ok
&admin=
&hash=
Software
Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run
Software\Microsoft\Windows\CurrentVersion\Run
Software\Microsoft\Windows\CurrentVersion\Uninstall
Location:
http://
Shell_TrayWnd
Location:
plugin_size
System\CurrentControlSet\Services\Disk\Enum
AutoItv3CCleanerWIC

Allez bientôt on dépècera cet executable.

 

Posted in Malware, Reverse | Tagged , , , | Leave a comment

Le Droppeur du jour, label231486.pdf – Part 1

Quel ne fut pas ma joie d’ouvrir ma boite aux lettres et de tomber sur une facture envoyée par “sales@meyda.com”. Une sombre histoire de facturation.

Dear customer,
              In your adress received parcel weight 6,5 lb.
              Our company’s courier couldn’t make the delivery of parcel.
              REASON: Postal code contains an error
                  DELIVERY STATUS: sort order
                  SERVICE: One-day Shipping
                  NUMBER OF YOUR PARCEL: in label
                  FEATURES: No
              

              Label is enclosed to the letter. To get it you need to print a label231486.pdf and go to the address specified in the notice. Password to arhive - g4E6A8qu7aPTdm8X3*NGPTwv7.
		
              An additional information:
		If the parcel isn’t received within 10 working days our company will have the right to claim compensation from you for it’s keeping in the amount of $9.12 for each day of keeping of it.
		
               Thank you for using our services.
               The best regard DHL.com.
	    
	    
__________ Information from ESET NOD32 Antivirus, version of virus signature database 9729 (20140427) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com/us/

Fichtre, un problème de facturation… Heureusement je ne risque rien, le fichier semble passé à l’antivirus :).

Bref j’ouvre l’«arhive» avec le mot de passe indiqué (sans le «.») et je me retrouve avec un fichier .pdf ……….exe :) Bon jusque là… pas trop impressionné. Même la transparence sur l’icone est dégueulasse. On le renomme en .bin et on avance.

pdfexe

Au détour d’un strings on découvre que cela semble être un RAR self extractible.

$ strings label231486.bin | grep SFX
WINRAR.SFX
d:\Projects\WinRAR\SFX\build\sfxrar32\Release\sfxrar.pdb
  name="WinRAR SFX"
<description>WinRAR SFX module</description>

Une fois ce SFX décompressé bêtement avec 7Zip on tombe enfin sur quelque chose qui peut nous amuser. 4 fichiers;

$ ls -l
total 360
-rw-r--r-- 1 thanat0s thanat0s 198144 May 15 04:30 1.exe
-rw-r--r-- 1 thanat0s thanat0s 158601 May 15 04:30 1.pdf
-rw-r--r-- 1 thanat0s thanat0s    229 May 15 04:30 run.bat
-rw-r--r-- 1 thanat0s thanat0s    152 May 15 04:30 run.vbs
$ md5sum *
d9f2513d33d35e707100a9ebe08df445  1.exe
3f865974f9efc56e905068b5d78ad93f  1.pdf
99903069929fed9cc742954b54bd67a3  run.bat
2942209f00520bcf05591df05880e9fb  run.vbs

Bon, on au vu des scripts, on se doute que le SFX doit pouvoir lancer le script visual basic .vbs. Le seul but dans la vie de ce vbs étant de lancer le .bat

On error Resume Next
dim oShell
set oShell = WScript.CreateObject("Wscript.Shell")
oShell.Run "run.bat", 0, false
set oShell = Nothing

Le .bat s’occupe de virer ce qui pourrait être existant, de renommer le pdf et l’exe et ensuite, d’une part de lancer le pdf, histoire de satisfaire le bon père de famille qui a cliqué sur ce malware en affichant quelque chose. Et d’autre part de lancer le fameux exe afin d’aller dropper le malin.

$ cat run.bat 
del label231486.pdf /q
del 2.exe /q
copy 1.pdf label231486.pdf
copy 1.exe 2.exe
del 1.pdf /q
del 1.exe /q
start label231486.pdf
start 2.exe
attrib +h +s label231486.pdf
attrib +h +s 2.exe
del run.vbs /q
del %0 /q

Le pdf et l’exe sont enfin «caché» au mieux en prenant l’attribut fichier «system» et «hidden» et on se débarrasse du vbs et du .bat (le %0).

Aucuns doutes à avoir l’executable sent le packing au vue de l’entropie et de la taille du segment de data par rapport a celle du code.

$ peentro.py 1.exe 
Section Entropy Bytes   Size    MD5                                     Remark
.text   6.12    7       151873  d1c4be93ec1c3acdbff8215b120ed235
.rdata  5.39    6       3072    51a9ebbdbfb136f59f7fba6434f29124
.data   7.80    8       840904  f5412cd2ef512ff317af7a8a7cacb342        High Entropy
.rsrc   6.90    7       25128   04e8378117ba7cdd3003a3c787c7c216

Un coup de rabin2 permet de confirmer que sur 270 strings, il n’y a pas une string potable là dedans.

$ rabin2 -z 1.exe 
…
addr=0x000fbdbf off=0x0002ffbf ordinal=258 sz=51 len=102 section=.rsrc type=W string=1Yle IdLe43 Rp19I2P7 exls b33x17 s1267 L92 BQ2OKi1
addr=0x000fbe28 off=0x00030028 ordinal=259 sz=34 len=68 section=.rsrc type=W string= Tu280n5 g18a LHd u3bf57 TOU4322x
addr=0x000fbe7a off=0x0003007a ordinal=260 sz=20 len=40 section=.rsrc type=W string=T0rD w5697krr laBwQ
addr=0x000fbec3 off=0x000300c3 ordinal=261 sz=35 len=70 section=.rsrc type=W string=!U98P4 j1h190 b26i0 q5aY03 NtD3003
addr=0x000fbf21 off=0x00030121 ordinal=262 sz=21 len=42 section=.rsrc type=W string=Gs7528 Q4jNbhF6 qtWy
addr=0x000fbf7b off=0x0003017b ordinal=263 sz=17 len=34 section=.rsrc type=W string=eyY k1k0m90G lLs
addr=0x000fbfbb off=0x000301bb ordinal=264 sz=41 len=82 section=.rsrc type=W string='V0MDzu7 AU5 FKY r4eK647p Qg6Ih1B c49306
addr=0x000fc001 off=0x00030201 ordinal=265 sz=25 len=50 section=.rsrc type=W string=Mu9X6Y ur76s5 ezrc9 uao2
addr=0x000fc069 off=0x00030269 ordinal=266 sz=29 len=58 section=.rsrc type=W string=FFjr M73x H58 y0N7X7J KJ0279
addr=0x000fc0ac off=0x000302ac ordinal=267 sz=34 len=68 section=.rsrc type=W string= U2Fx0PC S2A16 i9F3 jO11H42 h1w56
addr=0x000fc120 off=0x00030320 ordinal=268 sz=36 len=72 section=.rsrc type=W string="e3B tZMYb0a d4F1f1 W58 Q8s D0IR3k7
addr=0x000fc176 off=0x00030376 ordinal=269 sz=22 len=44 section=.rsrc type=W string=wUqpx3J eqQrD6 f0tnD2
addr=0x000fc1d7 off=0x000303d7 ordinal=270 sz=53 len=106 section=.rsrc type=W string=3ret6 B9FOMm XPC5 O847opt I151Lq ZQ0P tyb50 a2y71494

La suite ca sera donc olly :)

Posted in Malware, Reverse | Tagged , , , | 1 Comment

SQLi, ce n’est pas assez SELECT.

Un petit article sympas d’un certain Osanda Malith Jayathissa. Sri lankais de son état et qui documente bien les injections MySQL possible avec les méthodes update, delete et insert into. Il revient en détail et par l’exemple sur les injections possibles avec les fonctions :

Pour sur, il va y avoir de la DB bien cochonnée…

SQL Injections without SELECT

Posted in WebSecurity | Tagged , , | Leave a comment

Marty va chercher la DELOREAN.

Oui vous ne rêvez pas… Un CVE de 2014 pour le vénérable Mosaic, alias le père de tous les browsers pour les plus jeunes d’entre vous qui l’ignorez. Browser dont la dernière version date de 1997. Je parie qu’on aura pas de patch !.

http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-3425

Au moins avec ce browser la, <blink> fonctionne encore.

Tout cela en fait pour dédoiner un Emacs de ses responsabilités… Le VIM user est mort de rire. C’est ridicule.

CVE IDs for Mosaic are presumably not too useful at this point, but it
seems best to assign the most obvious ones, so that we are not blaming
Emacs for the entirety of the problem.
Posted in BlaBla, WebSecurity | Tagged | Leave a comment

RadaRE2 Tuto [Basic] Apprendre l’assembleur.

Avec radaRE2 finis les excuses “Je comprend rien en assembleur”.  Ce petit ustensoire contient un mode d’affichage qui ne décontenancera plus le néophyte (sous certaines réserves.)

Reprenons une fois de plus notre chall vu dans le premier tutorial. Si on désassemble le programme principal… C’est bien de l’assembleur qui est proposé.

$ radare2 crackkids
 -- Setup dbg.fpregs to true to visualize the fpu registers in the debugger view.
[0x004004c0]> aa
[0x004004c0]> pdf@main
|          ; DATA XREF from 0x004004dd (entry0)
/ (fcn) main 105
|          0x004005cc    55           push rbp
|          0x004005cd    4889e5       mov rbp, rsp
|          0x004005d0    4883ec30     sub rsp, 0x30
|          0x004005d4    c745f070617. mov dword [rbp-0x10], 0x73736170 ; "pass" ;  0x73736170 
|          0x004005db    66c745f42100 mov word [rbp-0xc], 0x21 ; "!" ;  0x00000021 
|          0x004005e1    bff0064000   mov edi, str.ChalleasyforRadaredissection ;  0x004006f0 
|          0x004005e6    e895feffff   call sym.imp.puts
|             sym.imp.puts(unk)
|          0x004005eb    488d45d0     lea rax, [rbp-0x30]
|          0x004005ef    4889c6       mov rsi, rax
|          0x004005f2    bf11074000   mov edi, str._16s ;  0x00400711 
|          0x004005f7    b800000000   mov eax, 0x0
|          0x004005fc    e8affeffff   call sym.imp.__isoc99_scanf
|             sym.imp.__isoc99_scanf()
|          0x00400601    488d55d0     lea rdx, [rbp-0x30]
|          0x00400605    488d45f0     lea rax, [rbp-0x10]
|          0x00400609    4889d6       mov rsi, rdx
|          0x0040060c    4889c7       mov rdi, rax
|          0x0040060f    e88cfeffff   call sym.imp.strcmp
|             sym.imp.strcmp()
|          0x00400614    85c0         test eax, eax
|      ,=< 0x00400616    eb00         jmp loc.00400618
|      |   ; JMP XREF from 0x00400616 (fcn.0040059c)
|- loc.00400618 29
|      `-> 0x00400618    bf16074000   mov edi, str.YouWin ;  0x00400716 
|          0x0040061d    e85efeffff   call sym.imp.puts
|             sym.imp.puts()
|     ,==< 0x00400622    eb0a         jmp loc.0040062e
|     |    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
\          0x00400634    c3           ret

Il existe cependant des autres mode. Est-ce plus clair avec le mode asm.pseudo ?

[0x004004c0]> e asm.pseudo = true
[0x004004c0]> pdf@main
|          ; DATA XREF from 0x004004dd (entry0)
/ (fcn) main 105
|          0x004005cc    55           push rbp
|          0x004005cd    4889e5       rbp = rsp
|          0x004005d0    4883ec30     rsp -= 0x30
|          0x004005d4    c745f070617. dword [rbp-0x10] = 0x73736170 ; "pass" ;  0x73736170 
|          0x004005db    66c745f42100 word [rbp-0xc] = 0x21 ; "!" ;  0x00000021 
|          0x004005e1    bff0064000   edi = str.ChalleasyforRadaredissection ;  0x004006f0 
|          0x004005e6    e895feffff   call sym.imp.puts
|             sym.imp.puts(unk)
|          0x004005eb    488d45d0     rax = [rbp-0x30]
|          0x004005ef    4889c6       rsi = rax
|          0x004005f2    bf11074000   edi = str._16s ;  0x00400711 
|          0x004005f7    b800000000   eax = 0x0
|          0x004005fc    e8affeffff   call sym.imp.__isoc99_scanf
|             sym.imp.__isoc99_scanf()
|          0x00400601    488d55d0     rdx = [rbp-0x30]
|          0x00400605    488d45f0     rax = [rbp-0x10]
|          0x00400609    4889d6       rsi = rdx
|          0x0040060c    4889c7       rdi = rax
|          0x0040060f    e88cfeffff   call sym.imp.strcmp
|             sym.imp.strcmp()
|          0x00400614    85c0         cmp eax, eax
|      ,=< 0x00400616    eb00         goto loc.00400618
|      |   ; JMP XREF from 0x00400616 (fcn.0040059c)
|- loc.00400618 29
|      `-> 0x00400618    bf16074000   edi = str.YouWin ;  0x00400716 
|          0x0040061d    e85efeffff   call sym.imp.puts
|             sym.imp.puts()
|     ,==< 0x00400622    eb0a         goto loc.0040062e
|     |    0x00400624    bf1e074000   edi = str.YouFailed ;  0x0040071e 
|     |    0x00400629    e852feffff   call sym.imp.puts
|     |       sym.imp.puts()
|     |    ; JMP XREF from 0x00400622 (fcn.0040059c)
|- loc.0040062e 7
|     `--> 0x0040062e    b800000000   eax = 0x0
|          0x00400633    c9           
\          0x00400634    c3           

Il y a aussi un mode “esil” mais je ne vous cache pas qu’il est trop … étrange .. pour moi, ( mais si vous êtes motivés : e asm.esil = true). Vous l’aurez compris «e» permet de changer les paramètres. «|grep» est utilisable et «e?monparam» vous dit ce qu’il est supposé faire. Par exemple si vous êtes amis avec la syntaxe At&T (Je n’en connais pas personnellement mais bon…).

[0x004004c0]> e | grep asm
asm.os = linux
asm.bytes = true
asm.cmtflgrefs = true
asm.cmtright = false
asm.comments = false
asm.decode = false
asm.dwarf = false
asm.esil = false
asm.filter = true
asm.flags = true
asm.lbytes = true
asm.lines = true
asm.linescall = false
asm.linesout = false
asm.linesright = false
asm.linesstyle = false
asm.lineswide = false
asm.middle = false
asm.offset = true
asm.pseudo = false
asm.size = false
asm.stackptr = false
asm.cycles = true
asm.tabs = 0
asm.trace = false
asm.ucase = false
asm.varsub = true
asm.arch = x86
asm.parser = x86.pseudo
asm.segoff = false
asm.cpu = x86
asm.profile = default
asm.xrefs = true
asm.functions = true
asm.syntax = intel
asm.nbytes = 6
asm.bytespace = false
asm.bits = 64
asm.lineswidth = 7
[0x004004c0]> e?asm.syntax
          asm.syntax: Select assembly syntax
[0x004004c0]> e asm.syntax  = att
[0x004004c0]> pdf@main
|          ; DATA XREF from 0x004004dd (entry0)
/ (fcn) main 105
|          0x004005cc   0        55           push %rbp
|          0x004005cd   0        4889e5       mov %rsp, %rbp
|          0x004005d0   0        4883ec30     sub $0x30, %rsp
|          0x004005d4   0        c745f070617. mov $0x73736170, -0x10(%rbp) ; "pass" ;  0x73736170 
|          0x004005db   0        66c745f42100 mov $0x21, -0xc(%rbp) ; "!" ;  0x00000021 
|          0x004005e1   0        bff0064000   mov $str.ChalleasyforRadaredissection, %edi ;  0x004006f0 
|          0x004005e6   0        e895feffff   call sym.imp.puts
|             sym.imp.puts(unk)
|          0x004005eb   0        488d45d0     lea -0x30(%rbp), %rax
|          0x004005ef   0        4889c6       mov %rax, %rsi
|          0x004005f2   0        bf11074000   mov $str._16s, %edi ;  0x00400711 
|          0x004005f7   0        b800000000   mov $0x0, %eax
|          0x004005fc   0        e8affeffff   call sym.imp.__isoc99_scanf
|             sym.imp.__isoc99_scanf()
|          0x00400601   0        488d55d0     lea -0x30(%rbp), %rdx
|          0x00400605   0        488d45f0     lea -0x10(%rbp), %rax
|          0x00400609   0        4889d6       mov %rdx, %rsi
|          0x0040060c   0        4889c7       mov %rax, %rdi
|          0x0040060f   0        e88cfeffff   call sym.imp.strcmp
|             sym.imp.strcmp()
|          0x00400614   0        85c0         test %eax, %eax
|      ,=< 0x00400616   0        eb00         jmp loc.00400618
|      |   ; JMP XREF from 0x00400616 (fcn.0040059c)
|- loc.00400618 29
|      `-> 0x00400618   0        bf16074000   mov $str.YouWin, %edi ;  0x00400716 
|          0x0040061d   0        e85efeffff   call sym.imp.puts
|             sym.imp.puts()
|     ,==< 0x00400622   0        eb0a         jmp loc.0040062e
|     |    0x00400624   0        bf1e074000   mov $str.YouFailed, %edi ;  0x0040071e 
|     |    0x00400629   0        e852feffff   call sym.imp.puts
|     |       sym.imp.puts()
|     |    ; JMP XREF from 0x00400622 (fcn.0040059c)
|- loc.0040062e 7
|     `--> 0x0040062e   0        b800000000   mov $0x0, %eax
|          0x00400633   0        c9           leave 
\          0x00400634   0        c3           ret 

Et voila…

 

 

 

 

 

Posted in Asm, Reverse | Tagged , | 1 Comment

RadaRE2 Tuto [Basic] Patcher un binaire.

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)

 

Posted in Reverse | Tagged , , | 4 Comments

RadaRE2 Tuto [Basic] Première approche.

Allez on y va. Voici un petit guide pour mettre le pied à l’étrier et donner sa chance à RadaRE2. C’est affolant de voir qu’il soit si avancé sans avoir plus de doc/tutos que cela. A se demander si ce n’est pas juste utilisé par ses développeurs. Tentons d’y remédier.

On va voir comment reverser avec RadaRE2 un tout petit Chall dont, en plus, on a les sources. On part sur du x64 ELF. Le chall est le suivant :

$ cat crackkids.c 
#include <stdio.h>
#include <string.h>

int main () {
  char password[]="pass!";
  char input[16+1];
  
  printf("Chall easy for Radare dissection\n");
  scanf("%16s", &input);
  if (strcmp(password,input)==0) { 
    printf("You Win\n");
  } else {
    printf("You Failed\n");
  }
        return(0);
}

Compilons ce petit chall et strippons le;

$ gcc crackkids.c -o crackkids && strip crackkids

Bon, on ne va pas faire un «strings crackkids» pour gagner on va voir ce que l’on peut faire avec radaRE2. A partir de maintenant oubliez ce qu’il y a dans ce source, et même ce qu’on a pondu comme exécutable.

Premièrement demandons au Rabin2 ce qu’il pense de ce fichier. Rabin2 est mix de objdump et readelf sous stéroides. Il comprend de base les formats d’exécutables JAVA, ELF et PE (et les MZ).

$ rabin2 -I crackkids
file    /home/thanat0s/code/helloworld/crackkids
type    EXEC (Executable file)
pic     false
canary  false
has_va  true
root    elf
class   ELF64
lang    c
arch    x86
bits    64
machine AMD x86-64 architecture
os      linux
subsys  linux
endian  little
strip   true
static  false
linenum false
lsyms   false
relocs  false
rpath   NONE

Ok… on est devant un ELF 64 bits strippé. Demandons au Rabin les fonctions importées (i) et les strings déclarées (z).

$ rabin2 -iz crackkids
[Imports]
ordinal=001 plt=0x00000480 bind=GLOBAL type=FUNC name=puts
ordinal=002 plt=0x00000490 bind=GLOBAL type=FUNC name=__libc_start_main
ordinal=003 plt=0x000004a0 bind=GLOBAL type=FUNC name=strcmp
ordinal=004 plt=0x00000000 bind=UNKNOWN type=NOTYPE name=__gmon_start__
ordinal=005 plt=0x000004b0 bind=GLOBAL type=FUNC name=__isoc99_scanf

5 imports
addr=0x000006f0 off=0x000006f0 ordinal=000 sz=33 len=33 section=.rodata type=A string=Chall easy for Radare dissection
addr=0x00000711 off=0x00000711 ordinal=001 sz=5 len=5 section=.rodata type=A string=%16s
addr=0x00000716 off=0x00000716 ordinal=002 sz=8 len=8 section=.rodata type=A string=You Win
addr=0x0000071e off=0x0000071e ordinal=003 sz=11 len=11 section=.rodata type=A string=You Failed

Masel Tov Rabin !!!  je vois un STRCMP, et le You Win/You Failed !… Ça a l’air pas mal. Ouvrons ceci dans RadaRE2.

$ radare2 crackkids
 -- This page intentionally left blank.
[0x004004c0]>

Nous voila donc avec un shell à l’entry point. Et c’est là qu’il faut introduire un concept important ; les Flagspaces. L’addresse d’une string, d’une fonction, d’une référence est un “Flag”. Et vu que cela fait beaucoup d’objets, il sont rangés par “FlagSpaces”.  «fs» permet d’afficher ou de sélectionner le Flagspace dans lequel on travaille et «f» affiche les flags.

[0x004004c0]> fs
00   strings
02   symbols
04   relocs
06 * sections
[0x004004c0]> fs strings
[0x004004c0]> f
0x0040071e 11 str.YouFailed
0x00400716 8 str.YouWin
0x00400711 5 str._16s
0x004006f0 33 str.ChalleasyforRadaredissection

Devant nous donc, 4 strings, ce qu’avait trouvé avec le rabin précédemment. On peut afficher les strings avec «ps» (Print String), et plus précisément «psz» pour une stringZ (Zero terminated).

[0x004004c0]> psz@str.YouWin 
You Win

Voir meme en hexa avec px (print hexa) dans ce cas, je précise combien de byte j’en veux et le mode d’affichage.

[0x004007c0]> pxs 16 @str.YouWin 
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x00400716  596f 7520 5769 6e00 596f 7520 4661 696c  You Win.You Fail
[0x004007c0]> pxw 16 @str.YouWin 
0x00400716  0x20756f59 0x006e6957 0x20756f59 0x6c696146  You Win.You Fail

Et il y a bien d’autre print mode hexa. Pour l’aide c’est «?» donc print hexa help c’est «px?». Je vous laisse découvrir tout seul pxe.

[0x004007c0]> px?
|Usage: px[afoswqWqQ][f]
| px     show hexdump
| px/    same as x/ in gdb (help x)
| pxa    show annotated hexdump
| pxe    emoji hexdump! :)
| pxf    show hexdump of current function
| pxo    show octal dump
| pxq    show hexadecimal quad-words dump (64bit)
| pxs    show hexadecimal in sparse mode
| pxQ    same as above, but one per line
| pxw    show hexadecimal words dump (32bit)
| pxW    same as above, but one per line

Bon, avançons, allons voir le FlagSpace avec les fonctions, mais avant cela il faut le populer. Si le code n’a pas été analysé, il n’y a pas de flagspace “fonctions”.

[0x004004c0]> fs  // Pas de flagspace «functions»
00   strings
02   symbols
04   relocs
06 * sections
[0x004004c0]> aa  // On lance l'analyse
[0x004004c0]> fs   // le Flagspace functions est apparu et sélectionné
00   strings
02   symbols
04   relocs
06   sections
08 * functions
[0x004004c0]> f    // quels sont les flags.
0x0040062e 7 loc.0040062e
0x004006e5 13 fcn.004006e5
0x004006d9 12 fcn.004006d9
0x00400635 13 fcn.00400635
0x0040057f 29 fcn.0040057f
0x0040056c 19 fcn.0040056c
0x00400532 7 fcn.00400532
0x004004b6 52 fcn.004004b6
0x004004a6 16 fcn.004004a6
0x00400486 16 fcn.00400486
0x0040047c 10 fcn.0040047c
0x00400470 12 loc.00400470
0x00400496 16 fcn.00400496

Bon maintenant trouvons où est appelé notre STRCMP.  (Analyse Reference Flag)

[0x004004c0]> fs symbols    // os sélectionne le flagspace symbol avec les appel aux libs
[0x004004c0]> f         // Liste les flags
0x004004b0 16 sym.imp.__isoc99_scanf
0x00400000 16 sym.imp.__gmon_start__
0x004004a0 16 sym.imp.strcmp
0x00400490 16 sym.imp.__libc_start_main
0x00400480 16 sym.imp.puts
0x004004c0 256 entry0
0x004005cc 256 main
[0x004004c0]> arf sym.imp.strcmp  // Donne moi les références. 
Finding references of flags matching 'sym.imp.strcmp'...
ar 0x004004a0 0x0040060f
Macro 'findstref' removed.

Et voila STRCMP est appelé en 0x0040060F. Désassemblons désormais la fonction autour de cette adresse. (Print Disassembled Function)

[0x00400bc0]> pdf@0x0040060F
/ (fcn) fcn.0040059c 149
|          0x004005a0    48833d68022. cmp qword [rip+0x200268], 0x0
|      ,=< 0x004005a8    741b         je 0x4005c5
|      |   0x004005aa    b800000000   mov eax, 0x0
|      |   0x004005af    4885c0       test rax, rax
|     ,==< 0x004005b2    7411         je 0x4005c5
|     ||   0x004005b4    55           push rbp
|     ||   0x004005b5    bf10086000   mov edi, 0x600810 ;  0x00600810 
|     ||   0x004005ba    4889e5       mov rbp, rsp
|     ||   0x004005bd    ffd0         call rax
|     ||      0x00000000(unk)
|     ||   0x004005bf    5d           pop rbp
|     ||   0x004005c0    e97bffffff   jmp fcn.00400539
|     ``-> 0x004005c5    e976ffffff   jmp fcn.00400539
|          0x004005ca    90           nop
|          0x004005cb    90           nop
|          ; DATA XREF from 0x004004dd (entry0)
/ (fcn) main 105
|          0x004005cc    55           push rbp
|          0x004005cd    4889e5       mov rbp, rsp
|          0x004005d0    4883ec30     sub rsp, 0x30
|          0x004005d4    c745f070617. mov dword [rbp-0x10], 0x73736170 ;  0x73736170 
|          0x004005db    66c745f42100 mov word [rbp-0xc], 0x21 ;  0x00000021 
|          0x004005e1    bff0064000   mov edi, str.ChalleasyforRadaredissection ;  0x004006f0 
|          ; CODE (CALL) XREF from 0x00400480 (fcn.0040047c)
|          0x004005e6    e895feffff   call sym.imp.puts
|             sym.imp.puts(unk)
|          0x004005eb    488d45d0     lea rax, [rbp-0x30]
|          0x004005ef    4889c6       mov rsi, rax
|          0x004005f2    bf11074000   mov edi, str._16s ;  0x00400711 
|          0x004005f7    b800000000   mov eax, 0x0
|          0x004005fc    e8affeffff   call sym.imp.__isoc99_scanf
|             sym.imp.__isoc99_scanf()
|          0x00400601    488d55d0     lea rdx, [rbp-0x30]
|          0x00400605    488d45f0     lea rax, [rbp-0x10]
|          0x00400609    4889d6       mov rsi, rdx
|          0x0040060c    4889c7       mov rdi, rax
|          0x0040060f    e88cfeffff   call sym.imp.strcmp
|             sym.imp.strcmp()
|          0x00400614    85c0         test eax, eax
|    ,===< 0x00400616    750c         jne 0x400624
|    |     0x00400618    bf16074000   mov edi, str.YouWin ;  0x00400716 
|    |     0x0040061d    e85efeffff   call sym.imp.puts
|    |        sym.imp.puts()
|   ,====< 0x00400622    eb0a         jmp loc.0040062e
|   |`---> 0x00400624    bf1e074000   mov edi, str.YouFailed ;  0x0040071e 
|   |      0x00400629    e852feffff   call sym.imp.puts
|   |         sym.imp.puts()
|   |      ; CODE (CALL) XREF from 0x00400622 (fcn.0040059c)
|- loc.0040062e 7
|   `----> 0x0040062e    b800000000   mov eax, 0x0
|          0x00400633    c9           leave
\          0x00400634    c3           ret
[

C’est un peu large, car il n’a pas détecté la fin inexistante de la fonction fcn.0x0040059c, mais ca passe,  on y est ! On peut constater, comme dans un IDA, les petites flèches d’embranchement qui confirment que le STRCMP est la clef de ce chall. Celui ci compare ce qu’il y aura sur le stack en rbp-0x30 avec ce qu’il y a en rbp-0x10. Le 0x30 sera remplis par un scanf en 0X4005fc. Quand rbp-0x10 il est remplis par deux mov en 0X4005d4 et 0x4005db. Mais comment convertir ceci en string. Et bien on peut utiliser «rax2» un autre tools de la suite RadaRE2 qui convertit tout en tout. Et il est aussi possible de l’apeller directement depuis notre RadaRE2 avec un «!».

[0x00400cc0]> !rax2 -h
Usage: rax2 [options] [expr ...]
  int   ->  hex           ;  rax2 10
  hex   ->  int           ;  rax2 0xa
  -int  ->  hex           ;  rax2 -77
  -hex  ->  int           ;  rax2 0xffffffb3
  int   ->  bin           ;  rax2 b30
  bin   ->  int           ;  rax2 1010d
  float ->  hex           ;  rax2 3.33f
  hex   ->  float         ;  rax2 Fx40551ed8
  oct   ->  hex           ;  rax2 35o
  hex   ->  oct           ;  rax2 Ox12 (O is a letter)
  bin   ->  hex           ;  rax2 1100011b
  hex   ->  bin           ;  rax2 Bx63
  raw   ->  hex           ;  rax2 -S < /binfile
  hex   ->  raw           ;  rax2 -s 414141
  -b    binstr -> bin     ;  rax2 -b 01000101 01110110
  -B    keep base         ;  rax2 -B 33+3 -> 36
  -d    force integer     ;  rax2 -d 3 -> 3 instead of 0x3
  -e    swap endianness   ;  rax2 -e 0x33
  -f    floating point    ;  rax2 -f 6.3+2.1
  -h    help              ;  rax2 -h
  -k    randomart         ;  rax2 -k 0x34 1020304050
  -n    binary number     ;  rax2 -e 0x1234   # 34120000
  -s    hexstr -> raw     ;  rax2 -s 43 4a 50
  -S    raw -> hexstr     ;  rax2 -S < /bin/ls > ls.hex
  -t    tstamp -> str     ;  rax2 -t 1234567890
  -x    hash string       ;  rax2 -x linux osx
  -u    units             ;  rax2 -u 389289238 # 317.0M
  -v    version           ;  rax2 -V
[0x004004c0]> !rax2 -s 0x2173736170  | rev
pass!

Une autre solution capilo-tractée assez violente qui ne servira d’exemple que pour montrer ce que l’on peut faire avec les calculs d’offset de RadaRE2;

[0x00400adb]> 0x4005d4
[0x004005d4]> ps 4 @+$l-4
pass
[0x004005d4]> 0x4005db
[0x004005db]> ps 2 @+$l-2
!\x00

Ok, je traduis. Je me place en 0x4005d4 et j’affiche une string d’une longueur de 4 depuis (l’offset courant + taille de l’opcode – 4). (4 car c’est la longueur du dword).

Et oui la commande permet de faire des opérations de dingue sur les offsets. Et nombre de substitutions sont disponibles.

[0x004005db]> ?$?
|RNum $variables usable in math expressions:
| $$     here (current virtual seek)
| $o     here (current disk io offset)
| $s     file size
| $b     block size
| $w     get word size, 4 if asm.bits=32, 8 if 64, ...
| $c,$r  get width and height of terminal
| $S     section offset
| $SS    section size
| $j     jump address (e.g. jmp 0x10, jz 0x10 => 0x10)
| $f     jump fail address (e.g. jz 0x10 => next instruction)
| $I     number of instructions of current function
| $F     current function size 
| $Jn    get nth jump of function
| $Cn    get nth call of function
| $Dn    get nth data reference in function
| $Xn    get nth xref of function
| $m     opcode memory reference (e.g. mov eax,[0x10] => 0x10)
| $l     opcode length
| $e     1 if end of block, else 0
| ${ev}  get value of eval config variable # TODO: use ?k too
| $?     last comparision value

Voila pour une première approche, et on est loin de loin d’avoir tout vu encore. Je n’ai même pas parlé du mode “Visual”.

Retenons, aa, pdf, psz, f, fs et arf. Cela sera déja très bien.

Posted in Reverse | Tagged , | 7 Comments

Radare2 Guide de survie.

On m’a récemment dit du bien de Radare2 (http://radare.org/y) ce projet est un framework de reversing. Grosso modo de ma très courte expérience avec le bitonio. C’est à mettre entre GDB et IDA. même s’il faut avouer qu’on est plus proche du second que du premier. D’un autre coté, c’est pas IDA mais il est GNU… et pour ce prix la il supporte :

Les architectures:
6502, 8051, arm, arc, avr, bf, tms320 (c54x, c55x, c55+), gameboy csr, dcpu16, dalvik, i8080, mips, m68k, mips, msil, snes, nios II, sh, sparc, rar, powerpc, i386, x86-64, H8/300, malbolge, T8200

Les fichiers:
bios, dex, elf, elf64, filesystem, java, fatmach0, mach0, mach0-64, MZ, PE, PE+, TE, COFF, plan9, bios, dyldcache, Gameboy ROMs

Les Operating Systems:
Android, GNU/Linux, [Net|Free|Open]BSD, iOS, OSX, QNX, w32, w64, Solaris, Haiku, FirefoxOS

C’est exceptionnel, il faut bien l’avouer.

Mais voila, c’est pas friendly et on devient vite dingue à essayer de le faire marcher avec le peu de doc encore disponible. J’ai donc démarré une petite refcard qui suffit amplement pour désosser un petit crackme.

la chose est là :

ERRATUM du 2 mai : C’est directement chez Maijin qui se tape la documentation désormais que vous trouverez la Cheat Sheet.

REFCARD Radare2

Et si j’ai la gnack, on fera un petit tuto.

Posted in Reverse | Tagged , , | Leave a comment