Un OEP Finder pour escargot en C
Introduction
Je voulais m'amuser avec l'API de debug sous windows ( voir autre chose que ptrace() ).
J'ai donc décidé d'écrire un OEP finder pour le packer escargot.
Voici le cheminement de mon programme :
- Bypass IsDebuggerPresent()
- Hadware Breakpoint à l'éxécution sur l'OEP
- Step Over de 3. L'état de tous les registres seront sauvés sur la pile (PUSHAD)
- Hardware Breakpoint à l'accés de l'un de ses états
- Step Over de 3. On arrive à l'OEP original
- Il suffit de fix le dump crée avec ImportRec à partir de l'OEP trouvé par le programme et le tour est joué
Source
Voici les sources : main.c, main.h
Conclusion
Ce programme peut vous apprendre les subtilités des debug register, comment utiliser l'API de debug de Windows, et jouer avec le format PE.
Have fun.
PECompact2 unpacking
Introduction
Dans la même lignée, il y avait du PECompact pendant la defcon.
Alors j'enchaine les vidéos :
Vidéo
Binaire
Voici le binaire en question pour pouvoir vous entrainer : calender.exe.
tElock v0.98 unpacking
Introduction
C'est aprè la defcon 19 que je suis retombé, sur le packer tElock.
Mais cette fois j'ai décidé d'unpack la bête ( qui est toute bidon ).
Donc voici une vidéo que j'ai faite exprès pour vous présenter la chose :
Vidéo
Binaire
Voici le binaire en question pour pouvoir vous entrainer : calender.exe.
Unpacking or not unpacking that is the question
Introduction
C'est en regardant l'analyse faite par Nicolas Brulez du Kaspersky Lab de gpcode, que je vois une technique de détéction d'unpacking d'UPX. Je décide de regarder de plus près et recréer le meme comportement ainsi qu'ajouter une autre technique en utilisant les TLS callback.
UPX
Avant de sauter sur le réel OEP, upx fait la chose suivante :
00418DBD . 61 POPAD
00418DBE . 8D4424 80 LEA EAX,DWORD PTR SS:[ESP-80]
00418DC2 > 6A 00 PUSH 0
00418DC4 . 39C4 CMP ESP,EAX
00418DC6 .^ 75 FA JNZ SHORT test.00418DC2
00418DC8 . 83EC 80 SUB ESP,-80
00418DCB .- E9 3082FEFF JMP test.00401000
- Restauration des registres
- Met dans eax l'adresse de esp - 80h
- Push 0 sur la stack
- Compare eax et esp
- Saut conditionnel tant que eax != esp
- Soustrait 80h à esp
- Saute sur le real entry point
Du fait que eax soit égale à une valeur proche de la stack, on peut écrire le bout de code suivant pour détecter l'unpacking UPX :
.code
start:
call DetectUnpack
...
DetectUnpack:
push ebp
mov ebp, esp
mov ecx, esp
sub ecx, 078h ; 80h - saved ebp (4 octets) - saved eip (4 octets)
jnz quit
leave
ret
A partir de ce snippet de code, la détection de ce check d'anti unpack est trè facilement bypassable, en changeant simplement le saut conditionnel.
Avec un peu d'obfuscation, on peut arriver à quelque chose de plus funky. Mais ce n'est pas le but de cette article.
Ce que font majoritairement le genre de personnes qui unpack du UPX, ils dumpent et reconstruisent l'IAT avec ImportRec ( ou à la main ).
C'est en jouant avec les TLS Callback que je me suis dit y'a moyen de faire retarder ce processus en venant écraser le PeHeader, ProcDump ( un plugin d'ollydbg ) se sert des sections tables pour fonctionner correctement. En lui enlevant ces informations il perd la boule.
TLS
Quand on lit la doc de Microsft, le Thread Local Storage (TLS) est un mécanisme qui permet à Windows de défininir des objets qui ne sont pas des objets sur la stack, des variables propres à chaque thread qui éxécute le code. Chaque thread pourra tenir à jour une variable qui lui sera propre. Ces informations sont dans le PEHeader.
Un développeur, si il le souhaite peut définir des TLS Callback fonctions, qui seront désignés à initialiser / nettoyer les objets.
En gros ces fonctions seront appelés avant l'entry point du programme.
Voici la structure :
;0x00 Raw Data Start VA Starting address of the TLS template
;0x04 Raw Data End VA Address of last byte of TLS template
;0x08 Address of Index Location to receive the TLS index
;0x0C Address of Callbacks Pointer to array of TLS callbacks
;0x10 Size of Zero Fill Size of unused data in TLS template
;0x14 Characteristics (reserved but not checked)
A partir de là on peut commencer à coder un exemple de code masm :
TLS_CALLBACK PROTO :PVOID,:DWORD, :PVOID
TLS_DIRECTORY STRUCT
lpTLS_Template_RDS LPVOID ?
lpTLS_Template_RDE LPVOID ?
lpTLS_Index LPVOID ?
lpTLS_Callbacks_Array LPVOID ?
dwTLS_Filler_Size DWORD ?
dwCharacteristics DWORD ?
TLS_DIRECTORY ENDS
.data
TLS_Directory TLS_DIRECTORY <NULL,NULL,OFFSET TLSIndex,OFFSET CallBacksArray, NULL,NULL>
CallBacksArray DD TLS_CALLBACK, NULL
TLSIndex DWORD NULL
MsgBoxCaption db "...", 0
GoodText db "MAIN", 0
TLSText db "CALLBACK", 0
.code
start:
invoke MessageBox, NULL, addr GoodText, addr MsgBoxCaption, MB_OK
invoke ExitProcess, NULL
start:
;call DetectUnpack
invoke MessageBox, NULL, addr GoodText, addr MsgBoxCaption, MB_OK
invoke ExitProcess, NULL
TLS_CALLBACK PROC DllHandle :PVOID, Reason :DWORD, dwReserved :PVOID
invoke MessageBox, NULL, addr TLSText, addr MsgBoxCaption, MB_OK
RET
TLS_CALLBACK ENDP
end start
Et le make.bat qui va avec :
@echo off
if exist "first.obj" del "test.obj"
if exist "first.exe" del "test.exe"
\masm32\bin\ml /c /coff "test.asm"
if errorlevel 1 goto end
\masm32\bin\Link /SUBSYSTEM:WINDOWS "test.obj"
if errorlevel 1 goto end
:end
pause
Le problème que j'ai rencontré c'est que je ne savais pas quoi comment option passer au linker pour mettre en place dans le peheader la TLSTable.
De ce fait j'y suis allé à la main avec un éditeur Hexadécimal.
Ce qui est facile c'est qu'avec ce code la TLS Table se trouve juste à l'entrée de la section data.
On teste et ca marche, ca nous affiche bien 2 messages box d'affilé.
On va faire évoluer notre code pour eraser le pe header au moment de la TLS :
TLS_CALLBACK PROC DllHandle :PVOID, Reason :DWORD, dwReserved :PVOID
push 0
call GetModuleHandleA
push eax
push esp
push 4
push 1
push eax
xchg edi, eax
call VirtualProtect
xor ecx, ecx
mov ch, 10h
rep stosb
leave
ret
TLS_CALLBACK ENDP
On reéedite à la main notre binaire avec notre éditeur Héxadécimal. Et en breakant sur l'entry point, on va regarder que notre PeHeader s'est bien fait écraser :
Ca a l'air de plutot bien marcher. Bon il faut le savoir que si on conf bien ollydbg, on peut arriver à breaker dessus :
Ou dans IDA, une fois le binaire chargé, pressez CTRL + E, en voyant l'adresse de l'entry point, les tls callback devrait etre juste avant :
Bon maitenant la tache qui reste c'est essayer de refaire passer UPX par dessus le tout, quand on lit les changelog :
Changes in 3.06 (04 Sep 2010):
* win32/pe: TLS callback support contributed by Stefan Widmann. Thanks!
On décide donc de tester, mais :( WTF, on se mange une vieille erreur :
A partir de là j'étaits bloqué, je me demandais si j'essayais de patcher upx ou trouver un autre moyen. C'est en continuant de regarder mon binaire avec WinHex que me vient une idée, à cause du FileAlignement ( champ dans le PeHeader ), il y a un peu de place entre les sections et la premiere section du binaire ( dans notre exemple section .text ). Malheuresement il faudrait pour cela faire du call à LoadLibrary, GetProcAdress. Pour ca faudrait résousdre à la main toutes les entrées mais je ne l'ai pas encore fait pour l'instant par manque de temps : saison des partiels.
Toute facon prochainement, je vais me lancer dans l'écriture d'un packer je reprendrais surement de là pour expliquer ma démarche.
Sur ceux have fun.
Pages : 1