You are on page 1of 10

==================================================================================

=============
====================================== patching Shrinker
======================================
==================================================================================
=============

Tutorial #2 on patching a packed file :-)nothing is impossible(-:

Written by R!SC - risc_1@hotmail.com

Knowledge is Power!

====================================== introduction!
======================================
==================================================================================
=============

I am going to try to teach you how to patch a file packed with Shrinker 3.x. How
many times
have you come across a program that you NEEDED to patch, only to find out it has
been packed
with 'Shrinker'? Its not nice asking people to 'Unpack the target with DeShrink,
and then run
our patch...'. Why bother when we can use Shrinkers own unpacking code, use the
jump to the
start of the original code to jump to our patch, patch the code in memory, then
return
execution to the original program.

tHE IDEA OF THIS TUTORIAL IS NOT TO TEACH CRACKING, BUT PATCHING A PACKED FILE

====================================== things you need


======================================
==================================================================================
=============

Xceed Absolute Packager 1.1 (Target Program, Packed with Shrinker 3.4?)
(Free trial version)
Get it at: http://www.xceedsoft.com/absolute

Soft Ice 3.22/3.23


ICEDUMP (i'm using beta 4 of this excellent addon)
ProcDump v1.3
WDasm32
A Hex Editor & Calculator..
!!!PEN AND PAPER!!! (oLD sKOOL :-)

Right then, i assume knowledge of softice, with this comes knowledge of asm, and
knowledge of
cracking

====================================== whats our target?


======================================
==================================================================================
=============

Absolute Packager has a NAG Screen every time it is loaded, stating 'X Days left
for evaluation
, I understand that I may use the program for evaluation purposes only', with
Agree/Help/Quit
buttons. Every package you create has a Nag aswell, stating it was 'Created with
the Free Trial
Version, and all packages created with the Free Trial Version will display this
Nag', and
theres several text reminders that its a 'Free Trial Version'. The 30 day trial
doesn't work,
i.e. it still works after the trial has ended, but were gonna kill this Nag & the
Nag in the
packages we create anyway.

====================================== lets begin...


======================================
==================================================================================
=============

Before we do begin, get your pen & paper ready and lets write down some variables.
We need two
file offsets, one for the DEP (Depacker Exit Point) & the other for our iMP
(Inline Memory
Patch) do it like this (this is VERY important if you want to follow along)

OFFSET#1 ; FILE OFFSET-DEP


OFFSET#2 ; FILE OFFSET-iMP

PATCH#1 ; 5 BYTES (OUR CALL TO OUR PATCH)

We want to find the exit point of the unpacker code, which will give us the
original entry
point of the program, before it was compressed with Shrinker. Loading absolute.exe
into
softice's symbol loader, doesn't work, instead of it soft ice breaking on the
first
instruction, the damn thing just runs.

Heh, get ProcDump loaded, select the PE-Editor Function, load absolute.exe. We can
see that the
Entry Point is '0015654B', select sections, and lOOk for the nearest Virtual
Offset to the
Entry Point, you will find it to be the '.load' section, starting at RVA
'00155000', '.load' +
154B = Entry Point! The file Offset of this section is '00002800', add 154B =
3D4B, the file
offset of the Program Entry Point. (did you follow that??)

Hex Edit absolute.exe, goto offset 3D4B, and change the '83' to a 'CC' (int 03).
Enter softice, type in 'bpint 03', hit F5
Run Absolute.exe
Softice will break here

0055654B CC int 03 (This address is the Entry Point


+ the ImageBase (00400000) )
Hmm, unpacking code normally locates itself far above the original code, so we
trace through
the code until it executes a jump or call to a location away from this address
space, say
somewhere between 00401000 & 00540000...

type in 'e eip 83' to replace the 'int 03' with the proper instruction code

0055654B 833DB411550000 cmp dword ptr [005511B4], 00000

Start tracing the code with F10, trying to remember what calls do what :) (you'll
see)
When you execute this call, the programs runs...

005565D3 E806000000 call 5565DE

so run the program again, replace the 'CC' with '83', start tracing again, F10
until you get to
the call where the program ran, then step into it with F8.
Carry on tracing with F10.

After tracing for a while, the program runs again, after trying to step over a
call [ebp-24]:-

0055664A A114365500 mov eax, dword ptr [00553614] (0006C31C)


0055664F 030528375500 add eax, dword ptr [00553728] (00400000)
00556655 8945DC mov dword ptr [ebp-24], eax (Original Program Entry
point)
00556658 FF7510 push [ebp+10]
0055665B FF750C push [ebp+0C]
0055665E FF7508 push [ebp+08]
00556661 FF55DC call [ebp-24] (call 0046C31C)

So there you go, a lesson in tracing through decompressor code, to find the
Depacker Exit Point
'DEP', and the Program Entry Point 'PEP'. With these addresses, were set to patch
this mother!

Hex Edit Absolute.exe again, goto offset 3D4B, and change the 'CC' back to the
original '83',
search for the 'push [ebp+08],call [ebp-24]', 'FF7508FF55DC', it turns up at
Offset 3E5E (write
this down, OFFSET#1) change the first 'FF' to a 'CC'. We need to change this code
to jump to
our own code, instead of running the program, a jump takes up 5 bytes, so we have
to overwrite
both these instructions, don't worry though, because after patching the memory
with our inline
code, we can execute the two instructions we replaced.

Whilst you have absolute.exe loaded in your hex editor, just look through the
file, for some
space around the unpacker code, to place our own patch code. There are plenty of
places.. I
choose offset 26C0 (write this down, OFFSET#2), just after the imports. Enter
'some text' here
that we can search for in softice, after it has unpacked the program. Save the
file, and run it
again..

Softice breaks here

0055665E CC int 03

K, now search for the text you entered into the exe, type in s 0 l ffffffff 'some
text', you
should get 'Pattern found at 01xx:005548C0' and the text displayed in the data
window, type in
'a eip', to assemble instructions at the current Eip. type in 'jmp 5548C0', then
hit escape.

Copy the instruction codes down for the jump you just wrote 'E95DE2FFFF' HIT F5,
shrinker traps
an exception, well, we haven't wrote the rest of our code yet, have we? we still
have to crack
the program, then we can finish off our patch..

======================================data we have so
far======================================
==================================================================================
=============

OFFSET#1 = 3E5E (DepackerExitPoint)


OFFSET#2 = 26C0 (Where our Inline Memory Patch will go)
PATCH#1 = E95DE2FFFF (jump to our iMP)

====================================== lets crack!


======================================
==================================================================================
=============

My way might be wrong, but it worked, so i'll tell you anyway...Basically, i keep
tracing
through the code with F10, until the Nag's popped up, remember the caller, run the
prog again,
then kill that call, test it to see if it still runs? If it doesn't, trace into
it, and try
again, i find the right place eventually..

run absolute.exe (with the int 03 still embedded at the DEP)


type in 'e eip FF', then trace with F8
when you have executed the call [ebp-24], trace with F10, until the Nag pops up...

its here:-
0046C3FB E8B09BFFFF call 00465FB0 (call Nag)

well, this calls the Nag, then after clicking agree, returns you to softice, so
put a
breakpoint on the call, and run the program again..

Softice breaks on the call, type in 'e eip b8' which will change it to a 'mov
eax,xxxxxxxx',
hit F5 to run the program, GodDamn!, it works! heh, too easy.
Our patch only has to change the byte at RVA 46C3FB to a 'b8', so lets do it..

Run the proggie again, this time, putting in the jmp at the DEP, and stepping into
it with F8.

when softice breaks, type in 'a eip', to assemble code at the current Eip.
type in 'jmp 5548C0', then hit escape.
Hit F8, were at location 5548C0 now?
type in 'a eip'
type in 'mov byte ptr [46C3FB], B8' (our iMP, Inline Memory Patch)
then replace the Packer Exit Point.
type in 'push dword ptr [ebp+08]'
type in 'call [ebp-24]', then hit escape..
dump the memory, by typing in 'pagein 5548C0 10 c:\imp.dat'
or write down all the instruction codes you just created..
'C605FBC34600B8FF7508FF55DC'

Hexedit absolute.exe again, then either copy & paste imp.dat into absolute.exe at
OFFSET#2
26C0, or write in all the codes by hand.
goto OFFSET#1 3E5E, and write in the jump instruction codes, save it and run!

Cool, it works... now for killing the Nag in the Packages we create with it..

====================================== removing NAG #2


======================================
==================================================================================
=============

oki, now for a bit of ZEN cracking, as this is tutorial is really to teach
patching packed
files, and not cracking as such...

Absolute Packager creates the self-extracting zips using a separate 'dll,


'xcdzip32.dll' (The
Xceed Zip Compression Library:File Version 3, 5, 0, 4). Lucky for us, they use the
same library
in the full version as in the trial version, and just check some flag in memory,
to see what
sort of 'exe to create.

well, upon disassembly of this dll, you can soon find this part of code...

Disassembly of File: xcdzip32.dll

:1000B1AF A1B08E0210 mov eax, dword ptr [10028EB0] <-- some version
flag
:1000B1B4 85C0 test eax, eax <-- check for zero
:1000B1B6 741C je 1000B1D4 <-- JumpifEqual to
'no NAG'
:1000B1B8 83F802 cmp eax, 00000002 <-- check for two
:1000B1BB 7417 je 1000B1D4 <-- JumpifEqual to
'no NAG'
:1000B1BD 83F803 cmp eax, 00000003 <-- check if three
:1000B1C0 7417 je 1000B1D9 <-- JumpifEqual to
NAG #2

* Possible StringData Ref from Data Obj ->"This self-extracting zip file "
->"was created with the free trial "
->"version of the Xceed Zip Self-
Extractor. "
->" It will only unzip itself on "
->"the same machine that it was created "
->"on. Registering your Xceed Zip "
->"Self-Extractor will remove this "
->"limitation."
|
:1000B1C2 BE10480110 mov esi, 10014810 <-- NAG #1 (not
ours)
:1000B1C7 8BFB mov edi, ebx
:1000B1C9 B93D000000 mov ecx, 0000003D
:1000B1CE F3 repz
:1000B1CF A5 movsd
:1000B1D0 66A5 movsw
:1000B1D2 EB13 jmp 1000B1E7

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:


|:1000B1B6(C), :1000B1BB(C)
|
:1000B1D4 C60300 mov byte ptr [ebx], 00 <-- Set a version
flag.
:1000B1D7 EB0E jmp 1000B1E7 <-- ha! done...

* Referenced by a (U)nconditional or (C)onditional Jump at Address:


|:1000B1C0(C)
|

* Possible StringData Ref from Data Obj ->"This self-extracting zip file "
->"was created with the free trial "
->"version of the Xceed Absolute "
->"Packager - the software that makes "
->"it easy to create powerful, fully "
->"customizable self-extracting zip "
->"files."
|
:1000B1D9 BE08490110 mov esi, 10014908 <-- NAG #2 (the
one we got :)

oki, the way i crack this is change this line...

:1000B1B4 85C0 test eax, eax <-- check for zero


:1000B1B6 741C je 1000B1D4 <-- JumpifEqual to 'no NAG'

to this

:1000B1B4 33C0 xor eax, eax <-- zero eax (to force the
jump)
:1000B1B6 741C je 1000B1D4 <-- JumpifEqual to 'no NAG'

So, change the byte at offset A5B4 to a '33', job done!

Another lame protection bytes the dust...


====================================== end of tutorial
======================================
==================================================================================
=============

comments, suggestions, questions welcome, write in the subject 'i love you :)'

risc_1@hotmail.com

R!SC -- March 1999

(I will survive without you.


Don't tell me that you wanna leave.

If you wanna leave, I wont beg you to stay,


and if you gotta go darling, maybe its better that way.

I'm gonna be strong, i'm gonna be fine,


don't worry about this heart of mine.)

risc@notme.com
risc_1@hotmail.com

love me, hate me, u don't no me...

Patch source code, if you like this sort of thing..

;---------------------start of risc_abs.asm---------------------
; to build risc_abs.com
;
; tasm risc_abs
; tlink /t risc_abs

.MODEL TINY
.CODE
.286
ORG 100h

start: jmp main

;_______________________________________________________________

intro db 0dh,0ah," Hi, guess who patched Shrinker?",0dh,0ah


db " It was Patched by -R!SC- ",0dh,0ah,0ah
db "Patch for Absolute Packager 1.1...",0dh,0ah,0ah,"$"

done db " Groovy! Patch Successful",0Dh,0Ah,"$"

error db " cant find file ? ",0Dh,0Ah,"$"


error2 db " file wrong size, should be 673,347 bytes ",0Dh,0Ah,"$"

filename db "absolute.exe",0
filename2 db "xcdzip32.dll",0
PATCH1 db 0E9h,05Dh,0E2h,0FFh,0FFh ; jmp 5548c0

PATCH2 db 0C6h,05h,0FBh,0C3h,46h,00,0B8h ; mov byte ptr [46C3FB], B8


db 0FFh,75h,08 ; push dword ptr [ebp+08]
db 0FFh,55h,0DCh ; call [ebp-24]

PATCH3 db 033h ; for the dll

; 13 bytes of code to apply to the file + another 5 for the jump to our code...
; then 1 more for the dll.
;_______________________________________________________________

main:
mov ah, 9 ; print title
lea dx, intro ; dx with offset of text
int 21h

mov ax, 3D02h ; Open File


lea dx, filename
int 21h
jnb Ok ; jump if everything ok
fileerror:
mov ah, 9 ; error with file
lea dx, error
int 21h
mov ax, 4C01h ; Exit with error
int 21h
;_______________________________________________________________
Ok:

mov bx, ax
mov ax, 4202h ; seek eof
xor cx, cx
xor dx, dx
int 21h
; int 03 : aw! our friend (cc)
cmp ax, 04643h
jne badsize
cmp dx, 0ah
jne badsize

sizepassed:

mov ax, 4200h ; file seek


mov cx, 0 ; hi order word of offset
mov dx, 03e5eh ; lo order word of offset OFFSET#1
int 21h

mov ax, 4000h ; Write to file


mov cx, 5 ; number of bytes to write
lea dx, PATCH1
int 21h

mov ax, 4200h ; file seek


mov cx, 0
mov dx, 026c0h ; OFFSET#2
int 21h
mov ax, 4000h
mov cx, 21
lea dx, PATCH2
int 21h

mov ax, 3E00h ; Close file


int 21h
;do the dll
mov ax, 3D02h ; Open File
lea dx, filename2
int 21h
jnb stillOk ; jump if everything ok

jmp fileerror
stillOk:

mov ax, 4200h ; file seek


mov cx, 0 ; hi order word of offset
mov dx, 0A5B4h ; lo order word of offset
int 21h

mov ax, 4000h ; Write to file


mov cx, 1 ; number of bytes to write
lea dx, PATCH3
int 21h

mov ax, 3E00h ; Close file


int 21h
;_______________________________________________________________
finished:

mov ah, 9 ; Show msg


lea dx, done
int 21h

mov ax, 4C00h ; All Done And Exit


int 21h

badsize:
mov ah, 9 ; print to screen
lea dx, error2 ; message
int 21h
mov ax, 4C01h ; Exit with error
int 21h

end start

;-----------------------end of risc_abs.asm---------------------

====================================== blah blaah blah


======================================
==================================================================================
=============
Heh, with every packed file you attack, it always gets easier, and you always get
quicker.
Packing files is a poor way to protect them, people sell there packers with this
as one reason
to use them, another being faster loading times, and another being the compressed
file is
smaller?? heehee, if you really want small, program in a real language, Machine
Language, if
you really don't want it cracked, don't program it at all :(

Some packers restrict patching memory directly somehow, probably by making the
process read
only (i'm not really very clued up on Win95 memory handling), so you can trace
through the
(un)packer code to find the exit point, but if you try patching the memory like i
showed you
here, you can get a fatal exception (one of those horrible blue screens, or a
regular GPF).
these packers need handling in a different way, you have to import some of your
own functions,
then open the process with read&write access, then use writeprocessmemory to apply
your patch.
its not as hard as it sounds.. lOOk oUT for my next tutorial on packed files,
"Patching
Neolite", as this is one of those packers that annoys me, and has a hidden catch
for the
cracker, but, said somewhere before "We always get what we want!"

Get my fULL cRACK for Xceed Absolute Packager, use astalavista to search for it..
http://astalavista.box.sk

hope this tutorial will benefit some of you


-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-

p.s.
take a look at the procdump script if you want to learn about shrinker 3.2 or 3.3
exit points,
i think there right(you really should trace through them yourself though, its good
experience
for you..)

==================================================================================
=============
====================================== (c) R!SC 1999
======================================
==================================================================================
=============