14/06/2011

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 :

unpack_esc

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.

14/06/2011

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.

14/06/2011

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.

11/06/2011

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

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.

unpack_bad_dos

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.

unpack_winhex

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 :

unpack_peheader

Ca a l'air de plutot bien marcher. Bon il faut le savoir que si on conf bien ollydbg, on peut arriver à breaker dessus :

unpack_conf

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 :

unpack_ida

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 :

unpack_upx

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