===============================================================================================
====================================== 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   ======================================
===============================================================================================


