`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`' ` MaX's cracking tutor for da poor ' ` ' `'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`'`' part 1 - registering PCXDUMP (9.20) intr0 :::::::::::: hia there.. this is a first part of my cracking tutor.. any decent cracker should *STOP* reading now, cos the info here is for the _real_ begginers.. i'll mainly concetrate on DOS stuff, since i don't crack under windoze ;) i've been told that it's much easier but i haven't tried it myself, probably cos i hate windoze.. well, what will ya need? - a debugger : the best choice is soft-ice, but since this is tutor for da poor, i'll use debug.exe from DOS (what a joke, you say..:) - a hexeditor : for me hiew works the best.. - a unpacking tool: cup386 is a good generic one... but we'll use here a one called dumpexe.. þ all this stuff is included in this package:) + unp v4.12á (useful unpacker) now, i suppose you have a basic asm knowledge cos i don't want this to be a asm tutor.. :) so, just a quick info (talking about 16bit!) there are some general registers (=variables).. you can see them in debug by typing 'r' AX - accumulator.. general usage.. BX - base.. CX - count.. mainly for loops.. DX - displacement.. they can hold values from 0 to 65535 (word).. they are split up to 2 pairs: low / high (byte) .. so there's: AL, AH, BL, BH, ... now we have segments.. these are 64 kb blocks full of data :) CS - code segment.. where the instructions are.. DS - data segment.. for data.. ES - extra segment.. SS - stack.. for addresses.. now there are some indexing registers.. SI - source index.. used in DS:SI combination.. DI - destination index.. for ES:DI .. BP - base pointer... for stack.. SP - stack pointer.. now flags.. something like boolean type in pascal :) zero flag - ZR/NZ .. zero/not zero.. carry flag - CY/NC .. you can change flags by typing 'rf' in debug.. now for some instructions... very quick here... get a instruction list yourself :) JMP - JMP FFF0 .. unconditional.. conditional: JNZ - jump if not zero.. JZ - jump if zero.. JE - jump if equal.. JC - jump if carry.. MOV - MOV AX, DX .. moves the value from dx to ax CALL - CALL 1234 .. calls a subroutine.. INT - INT 21 ... generates a interrupt (a function..) so... that's for refreshing memory only, since you really need some kind of asm knowledge.. get a book.. or study examples :) starT :::::::::::: oh yes, the program is old.. you must set the date to year 1995 :) don't ask me why i chosen it .. i don't have the new version and i find this program easy to crack.. :) so we have this nice program pcxdump.. and what we see when we run it is the nagging scroll line at the bottom and when we try to install it we cat another nag asking either for some F1-F10 key or registering.. since the authors were so nice and gave us the choice of registering it by entering our name and a number, why don't we try to find out or crack the checking routine of the registration procedure ? :) so we load the program to debug.. debug pcxdump.exe you'll get something like this.. AX=0000 BX=0000 CX=E7E0 DX=0000 SP=00FE BP=0000 SI=0000 DI=0000 DS=1E59 ES=1E59 SS=2CE7 CS=1EBC IP=E02F NV UP EI PL NZ NA PO NC 1EBC:E02F 8CC8 MOV AX,CS - so at the top are the registers.. at the right are the flags, you can see there NZ for example.. and at the left is 1EBC:E02F - that's the current address of the instruction (btw: it's CS:IP) and 8CC8 is a hexadecimal value for the instruction MOV AX,CS.. now you can type '?' in debug to see help.. for us the most important keys are P - proceed, T - trace, G - go, Q - quit :) P and T are similar.. they 'trace' through the code instruction by instruction.. the difference is that when you encounter CALL or LOOP the P will run the *whole* call or loop, whereas T will trace into the call or the loop.. when you simply type G, the whole program will run.. but you can also specify the breakpoint (the address where to stop) like: G 1000:2000 .. so for now, let's trace through the code by P (you don't want to trace all the long calls..).. so you step the instructions and you see some XOR stuff and loops.. this is the part where the program decodes the data .. you have *surely* viewed the program itself in a hexeditor and found out there's NO visible text there.. that means the program is either compressed by pklite, wwpack, lzexe, diet, or some other exe-compressor (which is not the case) _or_ it is encrypted (which is the case..).. usually, you can get rid of the compressors using UNP (unpacking util included in this package:).. so let's happily trace through these decoding parts until you encounter something like this: AX=1EBC BX=1573 CX=0000 DX=0000 SP=00E8 BP=0000 SI=0000 DI=E02B DS=1EBC ES=1EBC SS=2CE7 CS=1EBC IP=E0A7 NV UP EI NG NZ NA PE NC 1EBC:E0A7 07 POP ES - AX=1EBC BX=1573 CX=0000 DX=0000 SP=00EA BP=0000 SI=0000 DI=E02B DS=1EBC ES=1E69 SS=2CE7 CS=1EBC IP=E0A8 NV UP EI NG NZ NA PE NC 1EBC:E0A8 1F POP DS - AX=1EBC BX=1573 CX=0000 DX=0000 SP=00EC BP=0000 SI=0000 DI=E02B DS=1EBC ES=1E69 SS=2CE7 CS=1EBC IP=E0A9 NV UP EI NG NZ NA PE NC 1EBC:E0A9 61 POPA - AX=0000 BX=0000 CX=E7E0 DX=0000 SP=00FC BP=0000 SI=0000 DI=0000 DS=1EBC ES=1E69 SS=2CE7 CS=1EBC IP=E0AA NV UP EI NG NZ NA PE NC 1EBC:E0AA 07 POP ES - AX=0000 BX=0000 CX=E7E0 DX=0000 SP=00FE BP=0000 SI=0000 DI=0000 DS=1EBC ES=1E59 SS=2CE7 CS=1EBC IP=E0AB NV UP EI NG NZ NA PE NC 1EBC:E0AB E9C5FD JMP DE73 - this is the end of decrypting and after you step over the last jump, you'll find yourself at the beggining of the _real_ program.. wow :) so we trace on and on.. and i'll give you another nice function in the debug which is 'v' - view user screen.. sometimes you want to watch the changes happening on the screen :) .. hopefully you'll be in the part with many calls.. use P on them, unless you really want to study _every_ line the program does.. now the 15th CALL does something.. it clears the screen (remember the V key?:).. finally something happened.. but don't get overexcited and proceed on :) the 20th call draws the screen and let you move through the menu.. guess what we choose? yes ! install.. :) and wow! we're back in our debugger.. so we proceed on and on and then.. we get this awful screen where the choice of registering or installing is.. we choose register... so we type in the name and some number.. and hell what! since we used the P key on the call, which contained the whole checking routine, we get the message that we entered wrong number (unless you're a very good guess:).. hopefully you wrote down the address of that call.. as you should do before Proceeding every suspicious call! so now you just have to press the F1-F10 keys, which will get you back to debug and there you can press 'q' and start anew :) so let's load debug again (cracking is a work of patience:).. normally, you'd just type G xxxx:yyyy (where xxxx:yyyy was the last written address) but since we can't, we just had to trace it all again.. (of course, this all is not needed in the _best_ debugger Soft-Ice, but it's better to get started on debug, since you get the experience and it's not very easy for the begginers to quickly master soft-ice..) so we get to the point where we can move through the menu and we again select install.. and then we trace through the code and then there are 3 calls, then mov si, ???? and then again 3 calls and wait! the 3rd call is our checking routine, so we now must use T to get in.. now you again use P .. select register.. and now write down the calls more often.. and then there's somewhere: cmp bl,1c jnz ??? CALL ???? <--- this is our routine, use 'T' on it! and now we are almost in the core :) .. now you again use 'P' for proceed and there's one call - and you enter your name .. there's a second call - and you enter a number.. then there's a compare like: cmp al,11 jnz ??? this compares if the input registration code is 11h(=17 in dec) bytes long.. if you entered 17 bytes then go on tracing.. if not, then.. the cmp instruction enable the zero flag (remember? ZR/NZ) if the compare is true.. now we are comparing al to 11.. and if you didn't entered 17 bytes then the flag is off.. but you can _fool_ the program, to THINK, that the compare _was true_ when you change the flag like this: type: rf zr now you have turned on the zero flag.. wow :) and now there's something like this: mov byte ptr cs:[????],00 call ???? cmp byte ptr cs:[????],00 jz ???? !!! watch this !!! this is a _typical_ comparison check .. the program has a variable, let's call it correct_code of type boolean (pascal).. and this sequence of asm instructions looks something like this: correct_code:=false; check_if_correct_code_was_entered; if correct_code = true then registration_is_ok else incorrect_code; well.. all we have to do is _again_ fool the program to think the compare was true.. and how do we do it?? of course, with our favourite ZR/NZ flag! ;) so, after pressing P on the 'cmp byte ptr...' instruction we see, that the zero flaf is NZ .. so we must turn it on.. so, again -- type: rf nz .. and now, you can just press 'g' and let the program finish its work.. the file writes to itself the info about registering.. nice attitude :) ..and when you run it again the program is registrated to your name!! ;) you can see this result on the file 'pcxmax.exe' :) cracK :::::::::::: this way, you can registrate it to any name.. but how to crack it permanently so that you don't have to trace through the whole code again.. ? well.. in normal case you'd do this: find the hexadecimal value (see the begging of section start) of the instruction cmp byte ptr cs:[????],01 and then you would run hiew (hacker's view.. great hexeditor) and pres enter 2x to enter code view.. and then you'd search for '803EC2D101' which is the hexadecimal value for the instruction.. the very next instruction is the conditional jump and you'd have to change the : jz ???? to jmp ???? (where ???? is the address) .. because you remember that when you entered the reg. code it would not jump .. until you changed the zero flag :) but! .. as you remember, this program is encrypted, so your search for the sequence is unsuccessful.. right now it's too late, so i don't have any idea how to break this problem.. but i think it's enough to have it registrating once.. :) the decryption is described in the next chapter.. decryptioN :::::::::::: well.. the decryption itself is _very_ easy.. all you have to do is to use the program in this package called dumpexe.. so, very quickly.. run dumpexe.exe load debug on pcxdump.exe debug through the early xor's until: pop es pop ds popa pop es jmp ???? .. now use P on the last jump and then press: left-shift + right-shift to activate dumpexe.. type the values from the debugger to file '1' .. that means fill CS, IP, SS, SP, PSP = ES .. then autodetect filename #1, autodetect filesize #1 by stack [s].. then choose dump exe-code of file #1.. now type g in debug.. and then again activate dumpexe and choose allocate 4kb.. reload the file in debug and again trace to the same point right after the jump.. activate dumpexe.. type the values from debugger for file #2, autodet. name of #2, autodet. size #2 by stack.. and dump exe-code to file #2.. then again type 'g' in debug.. activate dumpexe.. release 4 kb.. quit from debug.. and type: makeexe pcxdump mycrack.exe .. and you have decrypted the program :) you can see the result of this in the file 'pcxcrack.exe' :) now you can view it normally and see the text inside.. you'll find out the undocumented switches such as /show_status, /no_scroll_line, /lets_register.. etc.. ..you may ask that now when the program is uncrypted we can make the crack in hiew, can't we? ... well, pcxdump checks the filesize of the file, so you'd have to add some 00's to the end of the file to fit the size.. you can play with that -- i'm too tired of writing this document now.. :) outrO ::::::::::::: soooo... i have written this stuff in one evening.. wow.. tired of it really.. so if you have some questions or comments you can write me: e-mail: maxmp@geocities.com ..and if you want to get the new parts of this tutor, then visit: http://www.geocities.com/Paris/9733/cracking.htm See you next time :) (c) 1997 by MaX, Prague