//**cracking tut by alpine**// //*****and******// //**the immortal descendants**// #6 06.1999 Hello Today,we will deal with a topic,which people claim it is hard to understand,but i will show you that there is always a way to unpack a packed file using the dump function of procdump and the pe-editor. First i have to thank MIZ,Hobgoblin and acab, without the help of them i wouldn't write this tutor...:) What we are going to do: First "manually" unpack our target and then we will crack the protection routine,to enter every dummy serial you want. We need: softice wdasm procdump //get the latest versions from: protools.cjb.net (best site to find the tools of the trade). Our target: autoinsult.zip // http://www.JumpingArmadillo.co.uk/AutoInsult/ Lets start with unpacking: First you will ask,or maybe not if you are familiar to this: what is packing ? A lot of programmers compress there programs with a packer,like aspack,shrinker,petite,....,to make them smaller and to add some more security.Why do we have to unpack?Well first i explain how a packer works: -take the program ,compress it, add an unpacking routine. I compare it to zipping a program.The difference is that the unpacking routine is allready included to the main exe,whereelse you need pkunzip to decompress the zipped exe...;) The problem with those packers is,that they decrypt their data(real program)into memory and then the real program starts.So, you will be able to bp at common bpx's like hmemcpy,getwindowtext(a)...,but you will not be able to patch a certain adress like 00401345 jne.., because if you look at the main exe file using a hexeditor,you will only find compressed and packed data.What you could do is,to use a process patcher which patches your data after it is located in memory. Disadvantage is,that you have to use the process patcher every time you start the program.Therefore we will wait till the data is written to the memory and then we will dump it to an exe file. Load your program(autoinsult.exe) into your symbol loader,but softice doesn't break!Why? Softice will only work correctly if the exe file is an executeable file and if it contains data and if it is read- and writeable.So use pe-editor,which is included in procdump;open your file;click on sections and look what the section characteristics are: C0000040.So we change the characteristics of the first line (.text) into E0000020.Try to load it into your symbol loader and wow! it breaks.Trace through the program using f10 till you are at something like this: mov eax, //something// <--eax contains the entry point without the image base;!!write it down!! add eax, //something//<--adds the imagebase popad <-- sets the registeres back jmp eax <--jump to the real entry point of the program (push ebp) BTW before you reached this code-snippet,you traced through the unpacking routine.This is the end of the unpacking routine. What we are going to do now?When we reach the jmp eax, the whole code of the "real program" is uncompressed and is written to the memory. What we have to do,is to freeze the program at that point and to dump the data in the memory to a file. So do the following:!!!Thanks to MIZ again!!!,when you reach jmp eax: 'a eip' 'jmp eip' '' 'g' or f5 or crtl-d What we have done?Look a eip:it contains an adress,and we changed it in a way to stay at the adress.By jmp to eip,we always jump to the current adress. So after you have typed g or pressed f5,go back to procdump.You will see a list of the current tasks.Scroll down,till you find your program (autoinsult),and right click on it and select dump (full).Now save it as unpacked or whatever you want.Now you have made an executable file,without packed data and without the unpacking routine. One thing is missing: If you try to start your file,it will crash.Why?Since we use the same entry point which the packed file used.Take the numbers you wrote down at mov eax, //something// and start procdump and open the pe-editor.Now select your new file and look at the entry point!It is still 20EA5.So replace this with the numbers you wrote down.I think the where: 12f31 . Now exit and try to run your target. It works!!!!! Now you are able to disassemble it,what we have to do,for cracking the protection scheme. But before: I will answer something:I think you don't know why i didn't simply used the procdump with its unpack function,which would be easier.Well, i must admit,it works using aspack as unpacker, but only because it is a version of aspack which procdump knows how to unpack.But what will you do if procdump's unpack function doesn't work? And believe me,that happens very often.I showed you a way, on how to unpack *any* kind of packer.So i will sum up what you will have to do and on what you should have an eye: -change the section characteristics if symbol loader doesn't work. -trace till you find a popad and a jump to the real entrypoint afterwards.this can also be a call too. -Before the popad the entry point is given to an adress.Write it down. -At the jump to the real program,place a loop to freeze the program. -Use procdump to dump it to a executable file. -Replace the entry point from the packer-routine with the entry point -you wrote down. I have to admit,that i didn't explained something:If you disassemble your program,you won't find the import-functions.I won't explain this, because this would make the tut too long.We only need the dead-listening for getting the hex-values to patch our program. Defeating the name/serial protection routine: Well start your program,and you will get a messagebox,which claims,that this program has been tampered...Extra security??Not really,open your disassebly and search for the string in the string-data-references. You will find it,note down the hex offset and nop it out using your hex-editor.Now it should work "fine". Well go through the whole program(of course you use your unpacked file...;))a few times and you will discover a time-trial protection,some functions are disabled and there is a serial/name protection to reg our program.So put in a dummy name and serial,i used alpine and 1234565 of course.Press register or okay (i can't remember), and you will get a messagebox telling you the name and code don't match.Have a look at the string data reference and you will find it, but wait there is a much better string: "autoinsult sucsessfully unlocked",or something like that.Double-click on it and you will find yourself at here: :00404342 B990774500 mov ecx, 00457790 :00404347 E8D9150000 call 00405925<--hmmm..... :0040434C 84C0 test al, al :0040434E 741A je 0040436A<--jump to bad boy :00404350 6A00 push 00000000 :00404352 6A40 push 00000040 :00404354 687C0B4500 push 00450B7C<--sucsessfully... :00404359 E8EF1B0300 call 00435F4D<--messagebox :0040435E 8BCB mov ecx, ebx :00404360 E8488C0200 call 0042CFAD :00404365 E98D000000 jmp 004043F7 Do you see the cond. jump at 0040434e?In our case we jumped to 0040436a,which triggered our code/name don't match messagebox. If we could change this je to two nops,we would be able to register our program.I know,you can easely nop it out,but it still says unregistered.So we have to change the data which is stored in al.Here al works as a flag.So if we want to change that,we have trace into the call at 00404347.Once in,trace till you get to the following point: :00405964 E857480000 call 0040A1C0 :00405969 83F801 cmp eax, 00000001 :0040596C 7528 jne 00405996 :0040596E 3945EC cmp dword ptr [ebp-14], eax :00405971 7523 jne 00405996 <--*1 :00405973 FF750C push [ebp+0C] :00405976 8D4E1C lea ecx, dword ptr [esi+1C] :00405979 E8395B0200 call 0042B4B7 :0040597E FF7508 push [ebp+08] :00405981 8D4E18 lea ecx, dword ptr [esi+18] :00405984 E82E5B0200 call 0042B4B7 :00405989 8B06 mov eax, dword ptr [esi] :0040598B 8BCE mov ecx, esi :0040598D C6461001 mov [esi+10], 01 <--*2 :00405991 FF500C call [eax+0C] :00405994 EB04 jmp 0040599A :00405996 80661000 and byte ptr [esi+10], 00 :0040599A 8A5E10 mov bl, byte ptr [esi+10] <--*3 :0040599D 834DFCFF or dword ptr [ebp-04], FFFFFFFF :004059A1 8D4DF0 lea ecx, dword ptr [ebp-10] :004059A4 E885590200 call 0042B32E :004059A9 8B4DF4 mov ecx, dword ptr [ebp-0C] :004059AC 5F pop edi :004059AD 8AC3 mov al, bl <--*4 :004059AF 5E pop esi :004059B0 5B pop ebx :004059B1 64890D00000000 mov dword ptr fs:[00000000], ecx :004059B8 C9 leave :004059B9 C20800 ret 0008 So,what happens here? When you reach: :00405971 jne 00405996 ,the program wants to jump. So look down,what happens if the program jumps: :00405996 and byte ptr [esi+10], 00 00 is added to esi+10;and then... :0040599A mov bl, byte ptr [esi+10] the data stored in esi+10 is moved to bl... and finally: :004059AD mov al, bl the data moves to al;and we know after the ret,our al is compared to itself.So al contains 00 as the first byte and that is bad! So look at the cond.jump at 00405971.If we patch the program in that way,that it will never jump at this adress the following happens: 01 is moved to esi+10 at adress 0040598D....and so on till at the end al contains 02 as the first byte.Good!!If you only patch it in memory using softice for example typing 'r fl z' at the adress 00405971,the program will be only registered for this run.Since the program checks if it is registered using this routine at the beginning too. I hope it teached you a bit..... That's it! alpine alpine@gmx.at or at www.immortaldescendants.com Special thanks to Miz,Hobgoblin,acab and of course to the immortal descendants.