Patching a target packed by UPX by Phrozen Crew (PC)
1 of 1 file
azzyrian
text or ascii
- Browsers may flag this download as unwanted or malicious. If unsure, scan it with VirusTotal.
-
Last modified Dec 28, 2018 8:41:51 PM
MD5 checksum 401ebcf813406e76e39e22081a05e201
Mime type Zip archive data
Download Patching_a_target_packed_by_UPX.zip
Size 10 kB
1999 November 23
- Text / Guides and how-tos
- AzzYRiAN, program credits
7 items in the archive
- UpxTestProgram(upx-patched).EXE
- UpxTestProgram.asm
- AzN-UpxRunTimePatching.txt
- make.bat
- pc.nfo
- UpxTestProgram(org).EXE
- UpxTestProgram(upx).EXE
▀ ▄▄▄ ▀▀▀ ▀▄▄▄▀▄ ▄▄▄▄ ▄ ▄ ▄▄▄▄▄ █
█▄▄▀▀▄▄▄████▄▓▄ ▄█▄▄▄▄▄▄▀▀▀▀▄▀▄ ▄▄▀▀▄▄▄▄▄▀▀▄▄▀▄▄ ▄
▀ ▀▀▄▓▄██████████▓▌ ▓██████████▓▀▄▄ ░ ▄█████████▄▄▀
▀ ▐▓█▓▌ ▀▀▓██▓▌ ▐▓▓███▀▀██▓▌▀ ▄█▄██▀ ▀▀▀▓███▓▌▀
█ ▓███ ▄█▄▐▓███▓ ▀ ▄▄████▌ ▄ ▓██▓▌ ░ ▐▓████▓ █
▀▐▓███ ▀ ▓▓███▓▌ ░ ▓████▀▄▄▄█▌ ▐▓██▓ ░ ▓████▓▌▀
█ ▓▓▓██ ▀█▀▓██▓ ░ ▐▓▓██▄████▓ ▐▓▓██▓ ▄▓████▓ █
▄▐▒▒▓██▄ ░ ▀▓▌ ▄▒▒▓█▀▀▀▀█▓▌ ▒░▒▓██▓ ▀███▓ █
▄ ▄▄▀░▀▀▀▀ ▄ ▀▀▄▀▄▀▄▀▄▄▄▀▀▀▄▄ ▀ ▀░▀▀ ▄▄▄▀ ▀█▓▌▀▄ '99
█▀▄▀▀▀▀ ▀ ▀ ▀ ▀ ▄ ▀▀srT▀▀▀▄ ▀▄▀▄▄▄ ▄
. [ AzzYRiAN ] .
+*---*+ +*--------------------------------------------------------*+ +*---*+
CRACKER ........: AzzYRiAN
TARGET .........: Just my TestProgram
TYPE OF CRACK ..: Patching an Upx compressed target
TOOLS NEEDED ...: SOFTICE, HiEW
+*----- +*--------------------------------------------------------*+ +*---*+
Some days ago, a friend of mine asked me, to crack him a program, he had
never seen released before. I grabbed it from the web, took a short look
at the registration routine and thought, damn, I'm too lazy to solve that. :)
It looks easy to crack and I isolated the required flag very quickly. BUT,
the program was packed with UPX and my PROCDUMP ( nice tool, but never worked
on my maschine ) crashed as allways. :) So I rememberd the tut's from R!SC
about patching packed targets and decided to find out, how to do this technic
on a target packed with UPX. Btw.: Go get all tut's from R!SC, they are very
good and you can learn a lot from it.
You should find the listed files in the archiv ( azn-upxruntimepatching.zip )
UpxTestProgram.asm <- the sourcecode of my exampleprogram
make.bat <- well, just the makefile
UpxTestProgram(org).exe <- the compiled exampleprogram
UpxTestProgram(upx).exe <- the compiled exampleprogram ( packed with upx )
UpxTestProgram(upx).exe <- the same as above, but patched :)
AzN-UpxRunTimePatching.txt <- this tut
1 -] I here we go! I hope, you read the tut's I pointed out above, 'couz
I wont go into details here.
First, fire up my testprogram ( the one packed with UPX ). You see a
MessageBoxA with some text, saying I'm a nag followed by another, which
is the mainwindow :)
Kewl, we will make this damn nagscreen, never appear again. Set your
bpx on the messagebox and run the testprogram again. okay, SiCE breaks
and after we stepped out of the api call, we see the following code.
(dumped from sice)
...
0137:0040100x mov eax,01 <- fake flag
0137:00401005 xor eax,eax <- settings,
0137:00401007 cmp eax,00 <- to make it more
0137:0040100a jnz 0040101f <- easy ... for me :)
0137:0040100c push 00
0137:0040100e push 00402000
0137:00401013 push 0040200b
0137:00401018 push 00
0137:0040101a call USER32!MessageBoxA <- the nag
0137:0040101f push 00 <- we are here now
0137:00401021 push 00402061
0137:00401026 push 0040206c
0137:0040102b push 00
0137:0040102d call USER32!MessageBoxA <- the mainwindow
0137:00401032 call KERNEL32!ExitProcess
...
*G*, looks realy easy to patch, I decided to nope the xor eax,eax
in line 401005 so we have 1 in eax and we will jump at line 40100a
to 40101f directly to the mainwindow.
2 -] Now, we have to work! run hiew and load the testprogram, press f8,
then f5 and you are at the entrypoint of the program.
Press f3 and type cc ( int 3 ) f9. But remember the original data,
it was 60 ( pushad ).
Set a breakpoint on int 3 and run the program. SiCE pop's up type in
eb eip 60 <return> to restore the original code.
Run the program, with the int3 set in SiCE.
Code snipped ....
...
0137:00405160 pushad <- we will brek here, then follow the unpacking
0137:00405161 mov esi,00405000 <- routine untill 0040522d
0137:00405166 lea edi,[esi+ffffc000]
0137:0040516c push edi
0137:0040516d or ebp,-01
0137:00405170 jmp 00405182
0137:00405172 nop
0137:00405173 nop
0137:00405174 nop
0137:00405175 nop
0137:00405176 nop
0137:00405177 nop
0137:00405178 mov al,[esi]
0137:0040517a inc esi
0137:0040517b mov [edi],al
0137:0040517d inc edi
0137:0040517e add ebx,ebx
0137:00405180 jnz 00405189
0137:00405182 mov ebx,[esi]
0137:00405184 sub esi,-04
0137:00405187 adc ebx,ebx
0137:00405189 jb 00405178
0137:0040518b mov eax,00000001
0137:00405190 add ebx,ebx
0137:00405192 jnz 0040519b
0137:00405194 mov ebx,[esi]
0137:00405196 sub esi,-04
0137:00405199 adc ebx,ebx
0137:0040519b adc eax,eax
0137:0040519d add ebx,ebx
0137:0040519f ja 00405190
0137:004051a1 jnz 004051ac
0137:004051a3 mov ebx,[esi]
0137:004051a5 sub esi,-04
0137:004051a8 adc ebx,ebx
0137:004051aa jae 00405190
0137:004051ac xor ecx,ecx
0137:004051ae sub eax,03
0137:004051b1 jb 004051c0
0137:004051b3 shl eax,08
0137:004051b6 mov al,[esi]
0137:004051b8 inc esi
0137:004051b9 xor eax,-01
0137:004051bc jz 00405232 <- if eax == 0, all data is unpacked
0137:004051be mov ebp,eax if you like to break here,
0137:004051c0 add ebx,ebx do: bpx eip if eax == 0
0137:004051c2 jnz 004051cb
0137:004051c4 mov ebx,[esi]
0137:004051c6 sub esi,-04
0137:004051c9 adc ebx,ebx
0137:004051cb adc ecx,ecx
0137:004051cd add ebx,ebx
0137:004051cf jnz 004051d8
0137:004051d1 mov ebx,[esi]
0137:004051d3 sub esi,-04
0137:004051d6 adc ebx,ebx
0137:004051d8 adc ecx,ecx
0137:004051da jnz 004051fc
0137:004051dc inc ecx
0137:004051dd add ebx,ebx
0137:004051df jnz 004051e8
0137:004051e1 mov ebx,[esi]
0137:004051e3 sub esi,-04
0137:004051e6 adc ebx,ebx
0137:004051e8 adc ecx,ecx
0137:004051ea add ebx,ebx
0137:004051ec ja 004051dd
0137:004051ee jnz 004051f9
0137:004051f0 mov ebx,[esi]
0137:004051f2 sub esi,-04
0137:004051f5 adc ebx,ebx
0137:004051f7 jae 004051dd
0137:004051f9 add ecx,02
0137:004051fc cmp ebp,fffff300
0137:00405202 adc ecx,01
0137:00405205 lea edx,[ebp+edi]
0137:00405208 cmp ebp,-04
0137:0040520b jle 0040521c
0137:0040520d mov al,[edx]
0137:0040520f inc edx
0137:00405210 mov [edi],al
0137:00405212 inc edi
0137:00405213 dec ecx
0137:00405214 jnz 0040520d
0137:00405216 jmp 0040517e
0137:0040521b nop
0137:0040521c mov eax,[edx]
0137:0040521e add edx,04
0137:00405221 mov [edi],eax
0137:00405223 add edi,04
0137:00405226 sub ecx,04
0137:00405229 ja 0040521c
0137:0040522b add edi,ecx
0137:0040522d jmp 0040517e <-End of unpacking code
0137:00405232 pop esi
0137:00405233 sub edi,[edi-04]
0137:00405236 push edi
0137:00405237 mov edi,esi
0137:00405239 mov ecx,00000003
...
How we knows, that all data is unpacked if we reach 405232 ??? easy:)
If we break on our int3, we first restore the original data with that
eb eip 60 then we do: u 0040101a. Remember? It's the offset of the
messagebox, the nagscreen we like to patch. Okay, we see something
like invalid data ... If we are at 405232, we get typing the same
command the original code, that we know allreay.
...
0137:00401018 push 00
0137:0040101a call USER32!MessageBoxA
0137:0040101f push 00
...
Valid proof eh ? (btw: with: u eip you go back to our current position )
3 -] Great, now we need a place to put our jump to our runtime patching code.
One thing is sure, we need a place after the unpacking code, well if
possible directly after, so lets have a look at the code short behind
405232.
...
0137:0040522d jmp 0040517e <- loop of unpacking code,jumps up
0137:00405232 pop esi <- End of unpacking code
0137:00405233 sub edi,[edi-04] <- not good
0137:00405236 push edi <- not good
0137:00405237 mov edi,esi <- not good
0137:00405239 mov ecx,00000003 <- kewl
...
The mov ecx, 3 is the best choice 'couz we have exactly 5 bytes and our
jump will have 5 bytes too.
Next we have to find a place to put our code. The best position is at
the end of the whole program. Startup hiew, go to the end of the file
and you see a big field of zeros. I decided to put the code directly
after the imports, would be 4060b0.
Run HiEW, go to 04060b0 and change the codeview to local (alt+f1),
note down the offset 8b0 and go back to 00405239. Press (f3), (return)
and type jmp <local offset> + c00 = jmp 14b0.
Then jump to 14b0 and type your patch. Must be if we like to nop the
xor eax, eax at 00401005 -> mov dword ptr [401005],9090 then restore
the value in ecx, where we put our jump obove, mov ecx, 3 and finally
jump back to local <offset>-c00 = 63e-c00 = continue fffffa3e
the program normaly.
Summary:
mov word ptr [401005],9090
mov ecx,3
jmp fffffa3e
Thats all i cracked much more complex stuff this way and it works great!
4- ] Usefull hint:
*You cant type stuff like mov dword ptr [ destination ], code in HiEW,
so just do in SiCE a eip type you code and note down the hexcodes and
type them in HiEW.
*Think of the reverse byteorder, if you have to do more complex
patching e.g.: you need to write to an offset: test eax, eax = 85c0
then you have to write your patch the following way:
mov word ptr [ destination ], c085.
*If you don't like to type on every startup eb eip 60 to restore the
original entrypoint, you can use an easy macro which gets called on
every int3 break. Type in SiCE:
onint3 = "eb eip 60;" <- the macro
bpint 3 do "onint3" <- the modified breakpoint
*The c00 you have to add or sub, are linker depending, and show us the
difference between the static offsets and the memory mapped code.
If you have any good idear, or whatever to make it more easy, drop me a note!
Greetings goes to: All members of ODDiTY and Phrozen Crew, Phropecy, Iceman,
and the guy *im waiting for him* who will do me some gfxwork.
[ AzzYRiAN of ODDiTY and Phrozen Crew in late 1999 ]
[ eMail: [email protected] eFnet: #odt #phrozencrew ]