I) MANUAL DUMPING
On commence par desassembler PESniff avec
WinDasm et on s'apercoit tout de suite que le programme est compacte ( car RVA > Size )
et que l'on obtient pas de listing. On a cependant ceci:
Number of Objects = 0009 (dec), Imagebase = 00400000h
Object01: CODE RVA: 00001000 Offset: 00000400 Size: 0001D000 Flags: C0000040
Object02: DATA RVA: 00046000 Offset: 0001D400 Size: 00000600 Flags: C0000040
Object03: BSS RVA: 00047000 Offset: 0001DA00 Size: 00000000 Flags:
C0000040
Object04: .idata RVA: 00048000 Offset: 0001DA00 Size: 00000E00 Flags: C0000040
Object05: .tls RVA: 0004A000 Offset: 0001E800 Size: 00000000 Flags: C0000040
Object06: .rdata RVA: 0004B000 Offset: 0001E800 Size: 00000200 Flags: C0000040
Object07: .reloc RVA: 0004C000 Offset: 0001EA00 Size: 00000000 Flags: C0000040
Object08: .rsrc RVA: 00051000 Offset: 0001EA00 Size: 00002C00 Flags: C0000040
Object09: .Sky-M RVA: 00059000 Offset: 00021600 Size: 00001200 Flags: C0000040
Program Entry Point = 0041DDFB (pesnif106.exe File Offset:0001DDFB)
D'ailleurs si on utilise PESniff sur notre copie de PESniff on apprend qu'il est packe
avec ASPack.. Donc premiere chose a faire si on veut avoir un listing de l'exe ou si
on veut utiliser le symbol loader, il faut un peu corriger le pe header et apres avoir
constate que [Program_Entry_Point - ImageBase] etait compris entre l'Offset de la section
CODE et celui de la section DATA, on peut se dire que l'EntryPoint du programme se situe
dans la section CODE, on va donc changer le flag de cette section par E0000020 avec
ProcDump (ce flag contrairement a C0000040 signifie qu'il y a du code). Ce qui donne ceci:
Object01: CODE RVA: 00001000 Offset: 00000400 Size: 0001D000 Flags: E0000020
on peut maintenant utiliser symbol loader, et on peut tracer le programme, c'est tres
simple:
start proc near
nop
; Entry Point
jnz short [eip+2]
jmp loc_459000 ; vers
decompression
start endp
loc_459000:
pusha
; on s'attend a voir un popa en fin de decompression
call [eip+5]
pop ebp
sub ebp, 43D93Eh
mov eax, 43D938h
add eax, ebp
sub eax, [ebp+43DE0Bh]
mov [ebp+43DE17h], eax
cmp byte ptr [ebp+43DE01h], 0
jnz short loc_45903E
inc byte ptr [ebp+43DE01h]
call sub_459051
call sub_4592B2
call sub_459350
loc_45903E:
mov eax, [ebp+43DE03h]
add eax, [ebp+43DE17h]
mov [esp+1Ch], eax
popa
; restauration des registres: la decompression est terminee
jmp eax
; donne la main
au programme depacke
donc arrive au jmp eax on fait ? eax et SICE nous donne ceci:
00445348 0004477768 "DSH"
L'entry point de notre futur dump est donc 45348 (445348-ImageBase), maintenant on tape r
eax eip (equivalent a un mov eax, eip) et on appuie sur F5 pour lancer le programme. Rien
ne se passe et c'est normal car on la glace juste avant que le programme depacke ne
s'execute, on lance donc ProcDump, on choisit PESniff.exe et Dump (full), on oublie pas de
killer PESniff (car il est bloque) ensuite on fait edit pe avec notre dump et on change
l'entry point avec celle que l'on a calculee, et voila on a un beau dump! Enfin pas si
beau que ca car le probleme avec ASPack c'est qu'il detruit l'Import Table donc sous
WinDasm on n'a aucune references aux apis utilisee. Mais ce n'est pas si grave que ca car
on toujours les Strings Reference et puis on peut mettre en parallele les informations de
SICE avec celles de WinDasm.
II) VIRER LA CONFIRMATION
donc la premiere chose qu'on va modifier c'est la confirmation de sortie, on va voir les
strings data references et finalement on a ceci:
* Possible StringData Ref from Code Obj ->"Would you really want to quit "
|
->"PE-Sniffer ?"
|
:0043D81B B848D84300 mov eax, 0043D848
:0043D820 E8175AFFFF call 0043323C ; Affiche message
:0043D825 48 dec eax
:0043D826 750D jne 0043D835
; jmp annuler if eax=1
et ca aussi:
* Possible StringData Ref from Code Obj ->"Would you really want to quit "
|
->"PE-Sniffer ?"
|
:0044415F B89C414400 mov eax, 0044419C
:00444164 E8D3F0FEFF call 0043323C ; Affiche message
:00444169 48 dec eax
:0044416A 750E jne 0044417A
; jmp annuler if eax=1
on a donc deux fois la meme routine, (la premiere etant celle qui correspond au bouton
Exit) pour cracker ca il suffit de modifier les 'call 0043323C' par des 'mov eax, 1' et
ainsi les branchements ne se feront pas donc on quitteras directement et pas de
confirmation..
III) VIRER LA GESTION DU FICHIER 'output.log'
on va encore une fois faire appel aux strings data references, on recherche cette fois les
dernieres lignes que le programme est succeptible d'ecrire dans le output.txt et on trouve
facilement ca:
"Encryptor : NONE"
"Encryptor : PE-Crypt v1.02"
"Encryptor : PESHiELD"
"Encryptor : Phrozen Crew PE enCryptor "
on va donc aller voir par exemple ce qu'il fait avec "Encryptor : NONE" :
* Possible StringData Ref from Code Obj ->"Compressor : Shrinker v3.4"
|
:0043E57B BAC4E84300 mov edx, 0043E8C4
:0043E580 B888774400 mov eax, 00447788
:0043E585 E8C656FCFF call 00403C50
:0043E58A E8E467FCFF call 00404D73
:0043E58F E89841FCFF call 0040272C
* Possible StringData Ref from Code Obj ->"Encryptor : NONE"
|
:0043E594 BAE8E84300 mov edx, 0043E8E8
:0043E599 B888774400 mov eax, 00447788
:0043E59E E8AD56FCFF call 00403C50
:0043E5A3 E8CB67FCFF call 00404D73
:0043E5A8 E87F41FCFF call 0040272C
vous avez bien remarque les trois call, comme d'habitude : vive le copier coller (dans ce
cas c'est plutot vive les languages merdiques!)
explications: pour chaques lignes de texte succeptible d'etre ecrite dans
output.txt on appelle 3 routines, et si on met un break sur la seconde (avec WinDasm), on
remarque que le output.txt a ete ecrit...
donc la routine qui ecrit dans l'output.txt est en 403C50.
on va voir:
* Referenced by a CALL at Addresses:
|:0043DB8A , :0043DBA3 , :0043DBB9 , :0043DBFD , :0043DC16
|:0043DC2C , :0043DC70 , :0043DC89 , :0043DC9F , :0043DCB8
|:0043DCD1 , :0043DCEA , :0043DD00 , :0043DD19 , :0043DD32
|:0043DD4B , :0043DD61 , :0043E3F6 , :0043E40F , :0043E425
|:0043E469 , :0043E482 , :0043E498 , :0043E4DC , :0043E4F5
...snip...snip...snip...snip...snip...snip...snip...snip..
|:004429CD , :004429E3 , :004429FC , :00442A15 , :00442A2E
|:00442A44 , :00442A5D , :00442A76 , :00442A8F , :00442AA5
|:00443316 , :0044332F , :00443345 , :00443389 , :004433A2
|:004433B8 , :004433FC , :00443415 , :0044342B , :00443444
|:0044345D , :00443476 , :0044348C , :004434A5 , :004434BE
|:004434D7 , :004434ED
|
:00403C50 31C9 xor ecx, ecx
:00403C52 E901000000 jmp 00403C58
:00403C57 C3 ret
bon alors la, ma solution c'est de remplacer le xor ecx, ecx par un ret et a partir de
maintenant on peut vraiment dire que ce satane fichier ne sert VRAIMENT a rien!
il n'empeche que ce fichier est tout de meme cree au demarage du prog, on va fixer ca et
avec un bpx CreateFileA, on arrive ici:
:0040488B 6A00 push 00000000
:0040488D 6880000000 push 00000080
:00404892 51 push ecx
; OPEN_ALWAYS
:00404893 6A00 push 00000000
:00404895 52 push edx
:00404896 50 push eax
:00404897 8D4648 lea eax, dword ptr [esi+48]
:0040489A 50 push eax
; output.txt
:0040489B E83CC9FFFF Call kernel32.CreateFileA
etant donne que quand le fichier n'existe pas alors il est cree, on en deduit le sixieme
parametre: OPEN_ALWAYS (voir win32 Programmer's Ref) nous on va preferer
OPEN_EXISTING qui ne cree pas de fichier s'il n'en existe pas.
on sait egalement que OPEN_ALWAYS=02h or quelques lignes plus haut dans le listing on
trouve :
:00404856 B902000000 mov ecx, 00000002
on ne peut pas faire plus explicite et puisque OPEN_EXISTING=03h on va mettre mov ecx, 3 a
la place...
il y a juste un tout petit probleme: quand on lance l'exe une message box nous informe:
'fichier introuvable' donc en une seconde (apres avoir pris le temps de faire un bpx sous
sice) on se retrouve ici:
:0042C569 E8EE94FDFF Call user32.MessageBoxA
on va voir plus haut dans le listing et on trouve ca:
* Referenced by a CALL at Addresses:
|:0042C639 , :00436FB7
|
:0042C530 55 push ebp
encore une fois on remplace le push ebp par un ret et tout est ok!
IV) HARD PATCHING
on va donc maintenant patcher le fichier original avec nos modifications, pour cela on va
modifier le loader d'aspack pour qu'une fois sa tache terminee (fin de decompression) il
ne branche pas vers l'entry point mais vers notre routine qui va patcher le programme puis
lui passer la main.. on s'amuse quoi!
a ce moment on a un probleme car il sagit de trouver de la place dans l'exe et ce n'est
pas evident car les endroits seins sont ecrasees en cours de decompressions..
la solution que j'ai retenue est donc: puisqu'on ne trouve pas de place on en fait, on
s'interesse a la section .Sky-M qui a une RawSize de 1200h on peut grapiller un peu de
place par exemple en changeant la valeur de la RawSize de 1200h a 1264h (avec ProcDump) on
a alors un gain de 100 octets ce qui est largement suffisant dans notre cas. Pour
finaliser cette operation il faut utiliser un editeur hexa sur notre cible et ajouter 100
octets a la fin. voila on a donc de la place a partir de l'addresse 45A1F7 pour implanter
tranquillement notre patch.
revoyons la fin du loader (OFFSET 21634h):
459034: E879020000 call 0004592B2
459039: E812030000 call 000459350
45903E: 8B8503DE4300 mov eax,[ebp+00043DE03] ;\
459044: 038517DE4300 add eax,[ebp+00043DE17] ; -calcul de l'ep
45904A: 8944241C mov [esp+0001C],eax
;/
45904E: 61 popad
;
restauration des registres
45904F: FFE0 jmp eax
a partir de 45903E on peut passer la main a notre routine qui va patcher le programme et
on pourra ensuite passer la main au programme, puisque de toute facons on connait l'EP, on
modifie donc comme ca:
459034: E879020000 call 0004592B2
459039: E812030000 call 000459350
45903E: 61 popad
; restauration des registres..
45903F: E9B3110000 jmp 00045A1F7
; vers notre patch
459044: 038517DE4300 add eax,[ebp+00043DE17]
45904A: 8944241C mov [esp+0001C],eax
45904E: 61 popad
45904F: FFE0 jmp eax
il ne nous reste plus qu'a implanter notre patch en 45A1F7 (OFFSET 227F7h)
45A1F7: C70520D84300B8010000 mov dword ptr [0043D820],000001B8 ;\--place mov eax,1
en 43D820
45A201: 66C70524D843000048 mov word ptr
[0043D824],4800 ;/
45A20A: C70564414400B8010000 mov dword ptr [00444164],000001B8 ;\--place mov eax,1
en 444164
45A214: 66C705684144000048 mov word ptr
[00444168],4800 ;/
45A21D: 66C705503C4000C300 mov word ptr [00403C50],00C3
;place un ret en 403C50
45A226: C70556484000B9030000 mov dword ptr [00404856],000003B9 ;\--place mov ecx,3
en 404856
45A230: 66C7056048400000EB mov word ptr
[00404860],EB00 ;/
45A239: 66C70530C54200C300 mov word ptr [0042C530],00C3
;place un ret en 42C530
45A242: E901B1FEFF jmp
00445348
;saut vers EP
remarque: les instructions mov eax,1 et mov ecx,3 ont ete patche dans le fichier
en deux fois car ce sont des instructions codees sur 5 octets or un dword est egal a 4
octets.. vous devriez egalement etre familie au fait d'ecrire a l'envers en asm car pour
information mov eax,1 se traduit en fait par B801000000 quand au 48 qui est ecrit en
45A201, c'est un octet qui etait deja present dans le prog d'origine mais comme il falait
encore que j'ecrive 00 et que je devais ecrire deux octets alors j'ai ecris 0048..
|