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