Welcome to Cracking Tutorial #16! Ah it's gr8 to be back in the cracking scene! If it wasn't Katrien, I won't be here (tnx for our special day, I'll always remember you..) In this tutor we'll teach you everything more about W32Dasm, SoftIce, SmartCheck, and MORE! Without knowledge, no power! ;) Warning, this tutorial is a real mother! *grin* Ok, let's rave! You'll need the following tools: (I use these tools, I assume you'll use 'em, but it doesn't mean that you'll need to use all those tools, so be sure to get them handy for the examples in this tutorial!) SoftIce 3.24 Beta W32Dasm 8.93 Hacker's View 6.02 SmartCheck 6.01 TASM 5.00 Windows Commander 3.53 (I use it coz of easier to multitask) Don't ask me where to download all these tools since you had a chance to get them when you used my older tutorials. Here are a few good cracking sites where you can grab tools from: http://cracking.home.ml.org or http://surf.to/HarvestR or ask any crackers to get you these tools! Are you ready?! OK! ;) PART 1: ~~~~~~ How to get a serial for 5 Users in Plan-It v1.02 by pIst0lS/CST http://www.mhsoftware.demon.co.uk 1) Run Plan-It and you will see a nag screen saying that "The Version of Plan-It is UNREGISTRED". Click in the "Register Button". 2) You will see a message box with "Please enter your code?". Type "147258" as serial. Don't click "OK" yet. 3) Press CTRL+D to be into SoftIce. Let's make a brakepoint, type "bpx hmemcpy", and press F5 to return into Plan-It. Click "OK" and now you're back into SoftIce. 4) Press F12, about 12 times, and you have to see: :00454D9E CALL 0042EEA0 :00454DA3 MOV EDX,[EBP-28] :00454DA6 MOV EAX,[EBP-08] :00454DA9 CALL 00403A68 <-------- Fake Code 5) Now let's press F10, until you see the code: :00496E6D LEA ECX[EBP-08] :00496E70 MOV EDX,00497210 <-------- Real Code :00496E75 MOV EAX,[EBP-0C] :00496E78 CALL 0047C2BC 6) Type "d edx" or "d 00497210" to see our real code. B00M! You got the code! Now just note the code and put the in Plan-It. Type bd *, to disabble the breakpoint, and type "F5" to return into Plan-It. Next time i gonna do it for 100 Users. Thanx for all crackers! pistols@zaz.com.br PART 2: ~~~~~~ HOW TO GET A SERIAL OF NFO-Diz viewer 1.26 Tutor by RSiP Tools to use ~~~~~~~~~~~~ SMARTCHECK 6.01 Where to get the program ~~~~~~~~~~~~~~~~~~~~~~~~ Company: CFA NFO-Diz viewer 1.26 http://pages.ripco.com:8080/~swb/ Start SmartCheck (sc) Open (crtl-O) Diz-nfo.exe Run the program by press F5 Press on all the errors the Acknowledge button untill the program starts. Press Ctrl-R (=Registration) There is a Registration window with a NAME (this is the COMPUTER NAME of your computer) and a code line (for the serial number) For my computer it says "RSIP" Enter any number and press OK (e.g. 12345) Registration says: Nope, thats not the right code... Now go back to the diz-nfo.exe - Program Results window. go to string : [+] Command1_Click en expand it. (last action) On Left the computername is displayed it is also in the Mid. Scroll down untill you see Right [this number is Too long] Look in Left you see: String .bsr=trVal = 00444AE8 =5125044160044"" Long lenght = 10 0x0000000A Take the first 10 numbers of the string of 13 numbers while the long lenght = 10 the nummer is then : 5125044160 Start Nfo-Diz and pres Ctrl-R put the number 5125044160 in, press OK *Boom* Thank you for registering ! BTW this works on ALL programs made by CFA ! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ How to change the computer name.. make a .reg file what contains: REGEDIT4 [HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ComputerName\ComputerName] "ComputerName"="RSiP" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RSiP would like to thank tKC for his tutors. PART 3: ~~~~~~ ----======oDDiTy======---- Cracking-tutor by Barnie Target:Resize Image v3.3 (http://pages.whowhere.com/internet/mudry/resizeimage.html) Tools :SoftIce Brain Computer Ok, start the program. hmmm it asks for an name and a serial. Ugly. Ok enter any name. I entered Barnie^oDDiTy. And enter any serial I entered 987654321. Press CTRL+D to enter SoftIce. Set a Breakpoint on GetWindowTextA (bpx getwindowtexta). Leave SoftIce and press on OK. There you are. Press F5 twice. Then press F10 until you reach :00406585 8B3B mov edi, dword ptr [ebx] :00406587 B9FFFFFFFF mov ecx, FFFFFFFF :0040658C 2BC0 sub eax, eax :0040658E F2 repnz :0040658F AE scasb :00406590 F7D1 not ecx :00406592 49 dec ecx :00406593 0F840B010000 je 004066A4 Here the program calculates the lenght of the name you entered and it will leave when you entered nothing. :00406599 8B7E5C mov edi, dword ptr [esi+5C] :0040659C B9FFFFFFFF mov ecx, FFFFFFFF :004065A1 2BC0 sub eax, eax :004065A3 F2 repnz :004065A4 AE scasb :004065A5 F7D1 not ecx :004065A7 49 dec ecx :004065A8 0F84F6000000 je 004066A4 Here is nearly the same routine but it will do the samething with the serial. :004065AE 6A00 push 00000000 :004065B0 8BCB mov ecx, ebx :004065B2 E899D70200 call 00433D50 :004065B7 50 push eax ;here it pushes the name :004065B8 8BCE mov ecx, esi :004065BA E821010000 call 004066E0 ;call to calculate the serial valid Just type d eax before the call and you will see your name. Now press F10 and step over the call that is calculating the serial. And what do we see right under our name in the data window?? I saw a B4421355. Hmm might be a serial we will check this. :004065BF 8B565C mov edx, dword ptr [esi+5C] here it moves our serial we entered into edx. * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004065DC(C) | :004065C2 8A08 mov cl, byte ptr [eax] ;moves 1 char of the correct # into cl :004065C4 3A0A cmp cl, byte ptr [edx] ;compares this char with the char of the wrong serial :004065C6 751A jne 004065E2 ;jump to BADBOY :004065C8 0AC9 or cl, cl ;end of the # ? :004065CA 7412 je 004065DE ;go to GOODBOY :004065CC 8A4801 mov cl, byte ptr [eax+01] ;takes the next char :004065CF 3A4A01 cmp cl, byte ptr [edx+01] ;compares again :004065D2 750E jne 004065E2 ;not equal?? BADBOY :004065D4 83C002 add eax, 00000002 ;prepares for the :004065D7 83C202 add edx, 00000002 ;cycle :004065DA 0AC9 or cl, cl ;end of the string?? :004065DC 75E4 jne 004065C2 ;no?? start again OK here it compares the correct serial with the wrong one so the number under our name IS the correct serial. So I got for the name: Barnie^oDDiTy the serial: B4421355 Thats it! If you have any questions you can find me on IRC in #odt. Barnie PART 4: ~~~~~~ CRACKING MPEGDJ ENCODER 1.24a - By IceBox Content: a) How to make it encode all tracks b) How to bypass invalid date c) Put in Regname Where to get it: http://www.xaudio.de/encoder Tools: - W32Dasm 8.9 - Hacker's View 6.01 a) The maincrack 1. Ok, insert any audio-cd in your drive and run MpegDj Encoder. Click on a track i.e. track 5. Click Copy and Encode. *boom* "You are using the unregistered Version which can only Copy Track ONE.." Damn ! 2. Quit and copy encode.exe into 1.exe. Disassemble 1.exe 3. Click the SDR button and find "You are using the unregistered 4. Doubleclick and press close in the SDR window 5. Look at this: * Referenced by a CALL at Adress |:004ABFA3 | * Possible StringData Ref from Code Obj ->"You are using the unregistered " ->"Version which can only Copy Track " ->"ONE of each CD-Audio. you have " ->"to register if you want no Limitations." | :004ABCD8 B8ECDC4A00 mov eax, 004ABCEC :004ABCDD E8E657F9FF call 004414C8 :004ABCE2 C3 ret 6. Now go to 4ABFA3. :004ABF88 648920 mov dword ptr fs:[eax], esp :004ABF8B BB01000000 mov ebx, 00000001 :004ABF90 803D131D4C0000 cmp byte ptr [004C1D13], 00 :004ABF97 7408 je 004ABFA1 <------ Yes, here it is ! :004ABF99 8B1D74D24B00 mov ebx, dword ptr [004BD274] :004ABF9F EB07 jmp 004ABFA8 * Referenced by a (U)nconditional or (C)onditional Jump at Adress: |:004ABF97(C) <----------------------------- This bring us to 4ABF97 | :004ABFA1 8BC6 mov eax, esi :004ABFA3 E830FDFFFF call 004ABCD8 <-- The message is called from here 7. If you look at 4ABF97 you see a jump If equal then jump to 4ABFA1 which will call the nasty message, we wanna get rid of Place the bar at :004ABF97 7408 je 004ABFA1 In the statusbar you will see the offset AB397 8. Run Hiew and open encoder.exe Press enter twice to go to decode-mode Press F5 and type AB397 Place the indicator on 74 and press F3 Change 74 to 75 and press F9 to update Press F10 to save and quit 9. Run MpegDj Encoder and try encode any track on the CD Yes! You did it ! b) The detailed crack 1. Set you date two month back and run MpegDj Encoder *Boom* "The clock was moved back" and the program exits 2. This is a invalid-date-protection But easy now. We can fix it Disassemble 1.exe Click the SDR button and find "The clock was moved back! 3. Look: :004ABA88 53 push ebx :004ABA89 8BD8 mov ebx, eax * Possible StringData Ref from Code Obj ->"The clock was moved back!" | :004ABA8B B8A8BS4A00 mov eax, 004ABAA8 :004ABA90 E8335AF9FF call 004414C8 <-- Look here ! :004ABA95 8BC3 mov eax, ebx :004ABA97 E9B449F8FF call 00430450 <-- And here ! :004ABA9C 5B pop ebx :004ABA9D C3 ret 4. All above the text you just forget. We can't use to anything The first call at 4ABA90 will call the messagebox The second call at 4ABA97 will close the program So we simply delete those two calls 5. We could fill a couple of NOP's in, but some program will crach if it finds three NOP's after each other and it will know it's a crack So we do another thing Place the bar at :004ABA90 E833F4F9FF call 004414C8 See the offset in the statusbar: AAE90 6. Run Hiew and open encoder.exe Press enter twice to go to decode-mode Press F5 and type AAE90 Place the indicator at E8 Press F3 and type 4149414941 Press F9 to update 7. Go down to the next call Place the indicator at E9 Press F3 and type 4941494149 Press F9 to update Press F10 to save and quit 8. Run MpegDj Encoder No NAG, cool huh ? c) The extra detailed crack 1. When running the program we see "Unregistered Version" We can change it, too ;-) 2. Run Hiew and open encoder.exe 3. Press F7 to search In the ascii field type 'unregistered' It will find the bad messagebox, but we have fixed it Press CTRL+F7 to go to the next string 4. Now you will find Unregistered Version 5. Place the indicator at U Press F3 Press TAB Type 'Cracked by IceBox ' Press F9 6. We also want to fix the aboutbox Press CTRL+HOME Press F7 Type 'unlicensed' Like before change it to 'IceBox ' 7. Press F9 Press F7 Type 'n/a' Press F3 Change 'n/a' to 'CRK' (for CRacKed) Press F9 Press F10 8. Now we are finish with MpegDj Encoder IceBox PART 5: ~~~~~~ Keygen for "a Musical Generator 1.2" by Merkuur/CiA Get it from http://www.musoft-builders.com/ Note: please register the program if you use it. Tools required: - disassembler (w32dasm or ida) - debugger (w32dasm or softice) 1. Finding where the check takes place. --------------------------------------- First run the program, you will notice it only asks for a serial (no name), and displays a ""Sorry, this is not a valid registration" box if you enter a random one. Disassemble the program, and have a look at the strings references. You will quickly find the "Sorry, this is not a valid registration" string, and get to the following place in the disassembly: :00446696 call 00440B6C :0044669B test al, al :0044669D jne 004466BE * Possible StringData Ref from Code Obj ->"Sorry, this is not a valid registration " :0044669F mov eax, 00446734 ... Allright, this looks like the check code is done in the call 00440B6C... let's quickly verify that by putting a breakpoint on the test al, al line, and running the program. Enter a random serial. Sure enough, we get a break, with al=0. Modify al so that it nows is 1, and resume execution... YES ! "Thank you for registering". I think it is usually good practice to quickly check that you are looking at the proper part of the code like that. After all, it only takes a few seconds... remember some programmers (at least the ones who know a little bit about cracking) like to put fake code in their programs... Don't be fooled by that. 2. Understanding the serial check --------------------------------- A beginner cracker would be tempted to patch the jne into a jmp... but getting a valid serial is what you must aim for... In order to do this you will have to get into the call 00440B6C. You now know we want to have al non-zero when coming back from this call. So we now breakpoint at 446696, enter a serial again, and, when the break occurs, step into the call. 2.a. Checking serial length --------------------------- You will land in this piece of code: :00440B91 call 00403D5C; get entered code length :00440B96 cmp eax, 00000008; is it 8 ? :00440B99 jne 00440D11; bad code ! ok so the code must be 8 chars long. Allright. Mine happened to be "12341234", which just fits, so let's move on: :00440B9F mov [ebp-38], 00000030 What's 30 ? it's the ASCII code for character '0'. Whenever you see this in a serial check, it's a great indication that the expected code is made of numbers... So what's next ? 2.b. converting the entered serial ---------------------------------- :00440BA6 mov eax, 00000001; character number :00440BAB mov edx, dword ptr [ebp-08]; start of serial ("12341234") :00440BAE movzx eax, byte ptr [edx+eax-01]; eax='1' :00440BB3 sub eax, dword ptr [ebp-38]; eax='1'-'0' = 1 :00440BB6 jno 00440BBD; skip call if its a number :00440BB8 call 00402EF8 :00440BBD mov dword ptr [ebp-10], eax; store eax Let's call our entered 8-numbers serial : a1 a2 a3 a4 a5 a6 a7 a8 this stores a1 at ebp-10. Similar code goes on (with a great waste of space), storing: a2 at ebp-14 a3 at ebp-18 a4 at ebp-1C a5 at ebp-20 a6 at ebp-24 a7 at ebp-28 a8 at ebp-2C 2.b. Computing K0 and K1, serial validation data ------------------------------------------------ Then the following code then performs some operations on these numbers: :00440C76 mov eax, dword ptr [ebp-10]; a1 :00440C79 add eax, dword ptr [ebp-24]; +a6 ... :00440C83 imul eax, 00000007; *7 ... :00440C8D imul edx, dword ptr [ebp-18], 00000003; 3.a3 ... :00440C98 add eax, edx; 7.(a1+a6)+3.a3 ... :00440CA1 add eax, dword ptr [ebp-14]; 7.(a1+a6)+3.a3+a2 ... :00440CAB mov ecx, 0000000A :00440CB0 cdq :00440CB1 idiv ecx :00440CB3 mov dword ptr [ebp-30], edx idiv ecx divides eax by ecx, and store the remainder in edx. So what we just did is store at ebp-30 the value: (7.(a1+a6)+3.a3+a2)%10 that I call K0 Similar code follows, storing at ebp-34 the value: (7.(a3+a6)+3.a5+a4)%10 that I call K1 2.c. Checking the serial validity --------------------------------- and finally, we get to the final part of the check: :00440CF6 mov eax, dword ptr [ebp-30]; K0 :00440CF9 cmp eax, dword ptr [ebp-28]; char 7 :00440CFC jne 00440D06; K0!=a7 -> bad code ! :00440CFE mov eax, dword ptr [ebp-34]; K1 :00440D01 cmp eax, dword ptr [ebp-2C]; char 8 :00440D04 je 00440D0A; K1=a8 -> good code ! :00440D06 xor eax, eax; bad code - return eax=0 ... So, in order to be valid, we must have K0=a7 and K1=a8. a7 and a8 were not used for computing K0 and K1, this means they act as "validation" number for the first 6 ones (a1..a6) For instance, let's say I want my serial to start with: 123456 a7 = (7.(a1+a6)+3.a3+a2)%10 = (7*7+9+2)%10 = 60 % 10 = 0 a8 = (7.(a3+a6)+3.a5+a4)%10 = 82 % 10 = 2 so the 8 chars code is: 12345602. Also note that code 00000000 is valid... Isn't that amazing ;-) 3. And now... some work for you, my friend ------------------------------------------ Well this should be fairly easy, yet a good exercise for a beginner cracker... What I suggest you now do is, write a C or asm keygenerator for this program, that will display all the valid serial numbers, from 000000xx to 999999xx. When you're done, try to make this program as small as possible... Good luck ! PART 6: ~~~~~~ Target: Anti-BO v1.5 URL: http://www.swiftp.com protection: serial number Description: Anti-BO detects people trying to access your system with the use of Trojans such as Back Orifice. Anti-BO logs the IP address and time-stamp for reporting purposes. It also has a system scanner, which will attempt to clean any infections of installed Trojans. Anti-BO has been a lot of help in the cracking down of Trojans. Some people using Anti-BO have reported attacks and had the attackers Internet accounts disabled, and even further. Tools you will need to crack this program: Soft-ice 3.0 or better (http://www.numega.com) programming knowledge (any language as long as you can code the keygen) How to make a keygen for this program: 1. Start the program, choose license and enter a name (6 chars at least) and a serial but DO NOT press OK yet, go into softice and set a breakpoint on hmemcpy (bpx hmemcpy). Now go back to the program and press the OK button, and bang, you are in softice. 2. Now press F5 to goto the next hmemcpy call, and press F11 to get out of the second call, now trace down until you are here: :0048493E mov edx, [ebp-04] <-- your entered name :00484941 lea ecx, [ebp-08] :00484944 mov eax, ebx :00484946 call 00484710 <-- code calculation :0048494B mov eax, [ebp-08] :0048494E push eax 3. So trace into the call, and step down until you come here: :0048476D mov al, [ebx+eax-01] <-- al=upcase(name[i]) :00484771 call 00402880 <-- makes al=upcase :00484776 cmp al, 41 <-- compare al, 41h='A' :00484778 jae 00484791 <-- jump if above or equal :0048477A mov eax, [ebp-04] <-- eax=name :0048477D call 00403C64 <-- makes eax=length(name) :00484782 mov edx, ebx <-- edx=i :00484784 add dl, 09 <-- dl=dl+9h :00484787 add al, dl <-- al=al+dl :00484789 add [ebp-14], al <-- ebp-14=char(ebp-14+al) :0048478C jmp 0048486D <-- jump :00484791 mov eax, [ebp-04] <-- eax=name :00484794 mov al, [ebx+eax-01] <-- al=upcase(name[i]) :00484798 call 00402880 <-- makes al=upcase :0048479D cmp al, 45 <-- compare al, 45h='E' :0048479F jae 004847B8 <-- jump if above or equal :004847A1 mov eax, [ebp-04] <-- eax=name :004847A4 call 00403C64 <-- makes eax=length(name) :004847A9 mov edx, ebx <-- edx=i :004847AB add dl, 0C <-- dl=dl+Ch :004847AE add al, dl <-- al=al+dl :004847B0 add [ebp-13], al <-- ebp-13=char(ebp-13+al) :004847B3 jmp 0048486D <-- jump :004847B8 mov eax, [ebp-04] <-- eax=name :004847BB mov al, [ebx+eax-01] <-- al=upcase(name[i]) :004847BF call 00402880 <-- makes al=upcase :004847C4 cmp al, 49 <-- compare al, 49h='I' :004847C6 jae 004847DF <-- jump if above or equal :004847C8 mov eax, [ebp-04] <-- eax=name :004847CB call 00403C64 <-- makes eax=length(name) :004847D0 mov edx, ebx <-- edx=i :004847D2 add dl, 16 <-- dl=dl+16h :004847D5 add al, dl <-- al=al+dl :004847D7 add [ebp-12], al <-- ebp-12=char(ebp-12+al) :004847DA jmp 0048486D <-- jump :004847DF mov eax, [ebp-04] <-- eax=name :004847E2 mov al, [ebx+eax-01] <-- al=upcase(name[i]) :004847E6 call 00402880 <-- makes al=upcase :004847EB cmp al, 4D <-- compare al, 4Dh='M' :004847ED jae 00484803 <-- jump if above or equal :004847EF mov eax, [ebp-04] <-- eax=name :004847F2 call 00403C64 <-- makes eax=length(name) :004847F7 mov edx, ebx <-- edx=i :004847F9 add dl, 22 <-- dl=dl+22h :004847FC add al, dl <-- al=al+dl :004847FE add [ebp-11], al <-- ebp-11=char(ebp-11+al) :00484801 jmp 0048486D <-- jump :00484803 mov eax, [ebp-04] <-- eax=name :00484806 mov al, [ebx+eax-01] <-- al=upcase(name[i]) :0048480A call 00402880 <-- makes al=upcase :0048480F cmp al, 51 <-- compare al, 51h='Q' :00484811 jae 00484827 <-- jump if above or equal :00484813 mov eax, [ebp-04] <-- eax=name :00484816 call 00403C64 <-- makes eax=length(name) :0048481B mov edx, ebx <-- edx=i :0048481D add dl, 2E <-- dl=dl+2Eh :00484820 add al, dl <-- al=al+dl :00484822 add [ebp-10], al <-- ebp-10=char(ebp-10+al) :00484825 jmp 0048486D <-- jump :00484827 mov eax, [ebp-04] <-- eax=name :0048482A mov al, [ebx+eax-01] <-- al=upcase(name[i]) :0048482E call 00402880 <-- makes al=upcase :00484833 cmp al, 55 <-- compare al, 55h='U' :00484835 jae 0048484B <-- jump if above or equal :00484837 mov eax, [ebp-04] <-- eax=name :0048483A call 00403C64 <-- makes eax=length(name) :0048483F mov edx, ebx <-- edx=i :00484841 add dl, 3A <-- dl=dl+eAh :00484844 add al, dl <-- al=al+dl :00484846 add [ebp-0F], al <-- ebp-0F=char(ebp-0F+al) :00484849 jmp 0048486D <-- jump :0048484B mov eax, [ebp-04] <-- eax=name :0048484E mov al, [ebx+eax-01] <-- al=upcase(name[i]) :00484852 call 00402880 <-- makes al=upcase :00484857 cmp al, 55 <-- compare al, 55h='U' :00484859 jbe 0048486D <-- jump if below or equal :0048485B mov eax, [ebp-04] <-- eax=name :0048485E call 00403C64 <-- makes eax=length(name) :00484863 mov edx, ebx <-- edx=i :00484865 add dl, 46 <-- dl=dl+46h :00484868 add al, dl <-- al=al+dl :0048486A add [ebp-0E], al <-- ebp-0E=char(ebp-0E+al) :0048486D mov eax, [ebp-04] <-- eax=name :00484870 call 00403C64 <-- makes eax=length(name) :00484875 mov edx, [ebp-04] <-- edx=name :00484878 movzx edx, byte ptr [edx]<-- edx=asc value of first letter of name :0048487B mov ecx, [ebp-04] <-- ecx=name :0048487E movzx ecx, byte ptr [ecx+01]<-- ecx=asc value of second letter of name :00484882 imul edx, ecx <-- edx=edx*ecx :00484885 shr edx, 1 <-- edx=edx shr 1 :00484887 add al, dl <-- length(name)=length(name)+dl :00484889 mov [ebp-0D], al <-- ebp-0D=char(al) :0048488C inc ebx <-- i=i+1 :0048488D dec esi <-- length(name)-1 :0048488E jnz 0048476A <-- jump if not zero :00484894 mov ebx, 00000008 <-- ebx=8 :00484899 lea esi, [ebp-14] <-- esi=ebp-14 (ebp-14=start of the calculated chars) :0048489C lea edx, [ebp-18] :0048489F xor eax, eax :004848A1 mov al, [esi] <-- al=asc value of ebp-xx char :004848A3 call 00408198 <-- inttostr :004848A8 mov edx, [ebp-18] <-- place the string here :004848AB lea eax, [ebp-0C] :004848AE call 00403C6C <-- place the string at the right place here :004848B3 inc esi <-- i=i+1 :004848B4 dec ebx <-- ebx=ebx-1 :004848B5 jnz 0048499C <-- jump if not zero :004848B7 mov eax, [ebp-08] :004848BA mov edx, [ebp-0C] :004848BD call 00403A80 :004848C2 xor eax, eax :004848C4 pop edx :004848C5 pop ecx :004848C6 pop ecx :004848C7 mov fs:[eax], edx :004848CA push 004848EF :004848CF lea eax, [ebp-18] :004848D2 call 004039E8 :004848D7 lea eax, [ebp-0C] :004848DA call 004039E8 :004848DF lea eax, [ebp-04] :004848E2 call 004039E8 :004848E7 ret ok, hard eh? :) here's a sample delphi keygen.. { Anti-BO v1.5 keygen by Klefz use for educational purposes only! } unit antibo; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) cancel_btn: TButton; name_ed: TEdit; msg_ed: TEdit; Label1: TLabel; Label2: TLabel; Label3: TLabel; procedure cancel_btnClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure name_edChange(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; al,dl:byte; penis,penis2,penis3,penis4,penis5,penis6,penis7,penis8,edx,ecx:longint; endsum,nisse:string; i:integer; implementation {$R *.DFM} procedure TForm1.cancel_btnClick(Sender: TObject); begin halt(0); end; procedure TForm1.FormCreate(Sender: TObject); begin Form1.Caption:='Anti-BO v1.5 keygen by Klefz / CRYSTAL'; name_ed.text:='Klefz / CRYSTAL'; end; procedure TForm1.name_edChange(Sender: TObject); { the calculation routine} label fel,ok,hah,nota,note,noti,notm,notq,notv1,notv2; begin al:=0; edx:=0; dl:=0; nisse:=chr($00)+chr($00)+chr($00)+chr($00)+chr($00)+chr($00)+chr($00)+chr($00); if length(name_ed.text)<6 then goto fel; for i := 1 to Length(name_ed.text) do begin; al:=ord(upcase(name_ed.text[i])); if (al > $41) or (al=$41) then goto nota; { cmp al, 41 jae } edx:=i; al:=length(name_ed.text); dl:=edx; { dl:byte (min 0, max 255) } dl:=dl+9; al:=al+dl; { al:byte (min 0, max 255) } nisse[8]:=chr(ord(nisse[8])+al); { add [ebp-14], al } goto hah; { jmp } nota: if (al > $45) or (al=$45) then goto note; { cmp al, 45 jae } edx:=i; al:=length(name_ed.text); dl:=edx; dl:=dl+$c; al:=al+dl; nisse[7]:=chr(ord(nisse[7])+al); { add [ebp-13], al } goto hah; note: if (al > $49) or (al=$49) then goto noti; { cmp al, 49 jae } edx:=i; al:=length(name_ed.text); dl:=edx; dl:=dl+$16; al:=al+dl; nisse[6]:=chr(ord(nisse[6])+al); { add [ebp-12], al } goto hah; noti: if (al > $4d) or (al=$4d) then goto notm; { cmp al, 4d jae } edx:=i; al:=length(name_ed.text); dl:=edx; dl:=dl+$22; al:=al+dl; nisse[5]:=chr(ord(nisse[5])+al); { add [ebp-11], al } goto hah; notm: if (al > $51) or (al=$51) then goto notq; { cmp al, 51 jae } edx:=i; al:=length(name_ed.text); dl:=edx; dl:=dl+$2e; al:=al+dl; nisse[4]:=chr(ord(nisse[4])+al); { add [ebp-10], al } goto hah; notq: if (al > $55) or (al=$55) then goto notv1; { cmp al, 55 jae } edx:=i; al:=length(name_ed.text); dl:=edx; dl:=dl+$3a; al:=al+dl; nisse[3]:=chr(ord(nisse[3])+al); { add [ebp-0F], al } goto hah; notv1: if (al < $55) or (al=$55) then goto notv2; { cmp al, 55 jbe } edx:=i; al:=length(name_ed.text); dl:=edx; dl:=dl+$46; al:=al+dl; nisse[2]:=chr(ord(nisse[2])+al); { add [ebp-0E], al } goto hah; notv2: hah: edx:=ord(upcase(name_ed.text[1])); { movzx edx, byte ptr [edx] } ecx:=ord(upcase(name_ed.text[2])); { movzx ecx, byte ptr [ecx+01] } edx:=edx*ecx; { imul edx, ecx } penis:=edx; al:=length(name_ed.text); penis:=penis shr 1; dl:=penis; al:=al+dl; nisse[1]:=chr(al); { mov [ebp-0D, al } end; penis:=ord(nisse[1]); { penis=asc value of first char in string nisse } penis2:=ord(nisse[2]); { penis2=asc value of second char in string nisse } penis3:=ord(nisse[3]); { penis3=asc value of third char in string nisse } penis4:=ord(nisse[4]); { penis4=asc value of fourth char in string nisse } penis5:=ord(nisse[5]); { penis5=asc value of fifth char in string nisse } penis6:=ord(nisse[6]); { penis6=asc value of sixth char in string nisse } penis7:=ord(nisse[7]); { penis7=asc value of seventh char in string nisse } penis8:=ord(nisse[8]); { penis8=asc value of eighth char in string nisse } endsum:=inttostr(penis8)+inttostr(penis7)+inttostr(penis6)+inttostr(penis5)+inttostr(penis4)+inttostr(penis3)+inttostr(penis2)+inttostr(penis); msg_ed.text:=endsum;goto ok; fel: msg_ed.text:='You must enter atleast 6 chars!'; ok: end; end. /Klefz - CST.FLK - klefz@cryogen.com - http://klefz.cjb.net PART 7: ~~~~~~ £ ££-ΦΦΦΦΦΦΦΦΦΦ₯ Crackers in Action presents: ·ΦΦΦΦΦΦΦΦΦΦ-££ £ ŽŽŽρ ΰŽŽŽ VERY EASY CRACKING TUTORIAL BY : BuLLeT March 2 - 1999 Heya ! Once again i'm back. Stronger and more powerfull/describing than ever :) Actually i didn't think this NEW basic tutorial would be necessary to write after the last one, cause i thought that i wrote it in a language and at such a low level that everyone would understand...but i was wrong :( Since the day i released it i have gotten many emails with questions that are so low that i almost don't know how to answer. (No offence). When writing the last basic tutorial i didn't ask ppl what they wanted, and i guess that was my mistake. Sorry. But i've learned from it and therefore i asked ppl in #CRACKS what they wanted. Actually i was a little disappointed by the number of requests cause i only got 3 (THREE) requests. I guess the ppl who wrote emails to me weren't present at that time ;) But what the hell.. i'm a nice person and i will help you anyway by, once again, trying to cover the most frequently asked questions concerning cracking. In this tutorial you will (hopefully) learn: 1) The VERY basics of cracking using Windows 32 Disassember (W32Dasm) 2) The VERY basics of cracking using SoftIce (SICE) 3) How to make a patch when you've finally found that little (damn) byte (TP) 4) Then i will try to answer these questions in the best possible way: 4.1) Basics of Visual Basic (VB) cracking (Req. by EagleWolf) 4.2) The program is not registered when i restart it?? (Req. by IceFlame) 4.3) Something about Anti-Softice (Req. by FunkyZero) 4.4) Basics of encryption (Req. by Z-Wing) 5) Source-Code for a keygen made in Delphi by BuLLeT & Nobody 6) Finally i'll tell about why it's so hard to crack...is it? To follow this tutorial in the best way you must have: * Windows 32 Disassembler (required for: 1, 3) * SoftIce (required for: 2, 3, 4.3) * HIEW (required for: 1, 2, 3) * Delphi (required for: 5) So..ready to go? I hope so cause i'm gonna start now. Or d'ya want just one minute to catch your breath and start the appz...ok...GO! 1) <---------------- W32Dasm is a disassembler which is perfect if you want to patch a program in the way that it'll accept ANY name/serial. It's also perfect for removing those annoying 30 days limit and some other stuff. Generally it's perfect! But now that you have installed it and you've tried to disassemble a program you are lost when you see the first piece of code. Don't be..i'll explain. W32Dasm works in the way that you basicly have two choices. Either you select the String Data Reference (SDR) and find a piece of text in the program, or you load the program and break at a NAG-screen. The first example is the most used, i dunno why cause they're both easy. When cracking using SDR (you'll find it in the REFS-menu) you will need a piece of text from the program. This you can find by launcing the program and watch carefully what it says. Try to enter your own name and a random serial and note the error-message the program gives you. This is usually: * Invalid serial... * Incorrect serial... * Wrong Serial... You get the idea. Note it, but don't stop looking. Take a look in the About- box which almost every program has. There it will probably say: * Unregistered Version... * Evaluation... * NOT registered... Got it? (if you don't understand what you read until now then you might as well just skip this and forget about being a cracker :P ) Note that too cause we'll need that later. Ok..so now you ave two notes messages. That should be enough to start with. So you may now quit the program and disassemble the EXE- file in W32Dasm. (select: Open File To Disassemble from the Disassembler-menu) It will probably take a while to load....wait....ZZZZzzzz..done? Good. So knowin ghte two messages you select the SDR from the REFS-menu and search for the first error-message. (Invalid Serial). Look carefully twice, but if you can't find it go get another program cause then we're talking encryption or some other kind of string-hiding, which is too hard for you so far. If you find it go on reading. Double-click the message and note the offset at the bottom of the disassembler. It should look like: Line: xxxx Pg xx and xx of xxx Code Data @:xxxxxxxx @Offset xxxxxxxxh in File xxxxxxxx.exe | | | | | | | The: line page page total Data Code Offset File Note that you will only see this if the GREEN BAR is placed correctly. If you don't see it, try scrolling up or down a bit and it should get there. Now that you have double-clicked it and you're looking at the code you know that this was the first reference of that text in the program. But there might be more references, so try to double-click it again and watch if the offset changes. If it doesn't you can close the SDR window and go on. If the line changes and you now see another offset there is more than one reference to that particular text and it's now (often) harder to crack the program. Assuming that you only got ONE reference you will now be looking at the code right after the registration process. But is this the place we wanna be? Nah! We want to be where the registration is calculated/compared. We'll get there by looking from where it's called. Trace/scroll up till you see something like this piece of code: * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:xxxxxxxx(U/C) This is the address from where the ERROR-message is called. We need to go there to envestigate a bit further. But i think it's time to explain a bit first cause this is a point where many newbies *cough* get confused. They think that the number on the left of W32Dasm is the offset. It's NOT! Note it and remember it. THe number on the left is the CODE LOCATION of the code. You can not use this for anything except to step through the file more easily. So what i mean is explained by this example: * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:00001234(C) | :00001236 8B4DF4 mov ecx, dword ptr[ebp,0C] <- Ignore this for now :00001237 5F pop edi <- Ignore this for now / GREEN BAR :00001238 5E pop esi <- Ignore this for now and the bottom line looks like: (assuming that the GREEN BAR in on 00001237) Line..... Code Data @: 00001237 @Offset 000004C3h in File.... What this means is that on Code Location 00001237, which is the same as Offset 000004C3 there is the following code: POP EDI. (Ignore the code for now and consentrade on the code location/offset). Understand??...hope so! NOTE: THe h at the end of the Offset means that it's HEX and is NOT a part of the offset itself so ignore that too). Ok..so now we're at the code just below the registration process, but we want to modify the registration process so let's trace up a bit. We need to trace to the Conditional Jump (|:00001234(C)) So scroll up and watch carefully for Jumps... JE/74 - JNE/75 - JMP/EB, and CALLS. Most likely you will see some code similar to this: CMP EAX,EBX JE XXXXXXXX or CALL XXXXXXXX TEST EAX,EAX JZ XXXXXXXX This code is the most often used but you may see something similiar too. The first example compares what is stored in EAX to EBX and jumps if the data is EQUAL. If it's NOT equal it will jump to the ERROR-message (probably the one you came from). The second example first CALLS a procedure/routine/function which will compare the info you entered to the CORRECT info and return a FLAG. This means that you, in SoftIce, would be able to trace into that call and find the CORRECT serial and register in the right way. Well it returns a FLAG which is either 0 or 1, to EAX. (ex: MOV EAX, 00000001). Then the program will TEST if EAX is 0 or 1 and depending on the FLAG it will either take you to the CORRECT or the WRONG message. This is done in the JZ (Jump Zero) line. Ok..so all of this sounds easy right? Actually it's very logical. Compare two things, and jump either to the CORRECT or the WRONG place in the code. This should be easy to understand, but if you of some reason don't, press PgUp and read from there :) So, now that you know this and you understand it it should be hard to figure what to change. Or?? In the first example it jumps if YOUR info equals the CORRECT info, which it probably won't. So now you have the option of changing in two ways. You can 1) Change it to say: CMP EAX,EAX, or 2) Reverse the JE to JNE. The most used way is to reverse the JUMP and that's what we're gonna do here as well. So what do you do? You plave the GREEN BAR on the JE-line and notes the OFFSET (at the bottom right ??). By noting this you have finished my first lesson successfully and you should now move on to either lesson 2) and learn about SoftIce, or lesson 3) and learn hw to patch that damn byte using HIEW. What you do is your choice and i won't leave ya no matter what you do :) 2) <---------------- So, time for some SoftIce basics. First of all you will need to modify the WINICE.DAT. This is a part that almost EVERYONE forgets and then they can't get their breakpoints to work. So EDIT WINICE.DAT and look for these lines: EXP=c:\windows\system\kernel32.dll EXP=c:\windows\system\user32.dll EXP=c:\windows\system\gdi32.dll EXP=c:\windows\system\msvbvm50.dll EXP=c:\windows\system\shell32.dll EXP=c:\windows\system\advapi32.dll Most likely you will have some of these lines but they might have a ; in front which is the same as disabled. So remove the ; in front of these lines. If you don't have all these lines you might wanna add them cause you'll sooner or later need them. Done? Save your work end restart! I'll wait till you get back for more action...Cya :) Back? Good. What took you so long???? Well time is relative and so am i so let's continue this little tut. Now another problem comes to mind. Cause how do i activate SoftIce? Well one thing i remember i was asked once is: "But i thought i should use the Symbol- Loader". NOT! You don't need to use it. The only thing you need to make sure is that SoftIce is loaded in your AUTOEXEC.BAT. If it IS mentioned it's loaded and you should now be ready to go crack da sucka! But before you do anything i have something to say. SoftIce is an "real-time-debugger" which means that you can trace through a program line-by-line. This is something that you'll soon be doing..trust me ;) One thing you must know is that SoftIce doesn't work like W32dasm. You can not go back one line if you press the wrong button and finding the offset can be hard too. This is, however, not something that should terrify you cause you'll soon see how powerfull and "easy" SoftIce is. Ok, so the program (the target) is running and you're placed at the REGISTER- DialogBox. What next? Well as you know SoftIce use breakpoints. We're gonna use a few of them in a second. What you should see now is something like: NAME : λλλλλλλλλλλλλλ REG NR : λλλλλλλλλλλλλλ NAME : λλλλλλλλλλλλλλ COMPANY : λλλλλλλλλλλλλλ SERIAL : λλλλλλλλλλλλλλ This should pretty much cover the often used registrations. So you enter your OWN name/nick and enter a random chosen serial. (If you have the COMPANY too then enter your company/group/whatever there). So assuming that this is NOT a Visual Basic program you now have the following choices. Well actually you have many more but these are the ones that are often used: GetWindowText / GetWindowTextA GetDlgItemText / GetDlgItemTextA HMEMCPY These are the breakpoints you'll use in about 95% of the programs you'll meet in the beginning of your cracking career. The first 4 are the "normal" break- points which you'll most likely use. The HMEMCPY is a breakpoint which is called everytime something is copied to/from memory. This breakpoint is not used THAT often. So..now all of the inputs are filled and you now need to set a breakpoint. To do that you will have to enter SoftIce. This is done by pressing CTRL+D. WOW! what is this? Looks like shit (if it worx). Well maybe not shit but at least VERY weird in the beginning :P What you need to do now is set the breakpoint. Do that by typing: BPX breakpoint. (I'm sure someone will enter EXACTLY that instead of BPX GetWindowText... :) ) But which one should you set? Well this can be hard to figure so why not set them all? I usually do this and it worx great so set them all (NOT HMEMCPY) and lemme know when you're done. K? Kay? Now you should be all set. If you got an error saying: Symbol not defined, you have forgotten to edit the WINICE.DAT. Modify it, as shown above, and read on. So, you need to return to the program to activate the breakpoints. Do that by pressing F5 (=GO). Back into the program you press the OK/REGISTER/CHECK/ WHATEVER the button might say, and you should be back in SoftIce. IF you're not back in SoftIce it means that you have chosen the wrong breakpoints and you'll have to try the HMEMCPY. Assuming that you're back in SoftIce you're now almost ready to go. But do you see a window with the REGISTERS? Or the DATA window? I doubt it, so therefore you should first type: R This should bring up (at the top) a window of registers (EAX, EBX, ECX, EDX...). Now you activated the register window but you need to press ESC to go back to the place where you are able to type normal text. Only one more thing to go. Type: DATA and once again press ESC. Now you should see 4 (FOUR) windows. Top: REGISTERS, Top-Middle: DATA, Lower-Middle: CODE-WINDOW, Bottom: PROMPT. (The place where you can type text). If you do NOT see this you can move/resize using your mouse. How you put them is your choice but the way i described makes it easier to cover. So you're ready to go again. The place where the breakpoint was activated was at the FIRST input-box (NAME). But we also need SoftIce to read the other input-boxes so press F5 again. (Assuming that you only have a NAME/SERIAL). You will have to press F5 as many times as you have input-boxes - 1. If you pressed too many times you will get back to windows and you'll have to start over. Ok, now you will have to press F11 to return from the CALL. (Remember the Unconditional/Conditional jump in W32Dasm?? This is the same as tracing up). So..you're now ready to go and the CORRECT serial will be right at your face in a matter of minutes. In SoftIce you'll need to know the meaning of these: F8 = Trace Into F10 = Trace Through/Over F11 = Return ? EAX = Show what's in EAX D EAX = The same as above S 0 L FFFFFFFF 'textstring' S 0 L FFFFFFFF FF,FF,FF,FF (FF = HEX numbers) If you understand and remember this you're well off. But now i've reached the point from which i can not really guide you. Cause what to do now warries a LOT depending on the program you have found. There is not TWO programs which will show the same in SoftIce. Therefore there is no way to tell you; do this, do that, press that. You're pretty much on your own tracing the code. Inside CALLS..outside them. I remember when i first started cracking i typed D EAX every time EAX changed to see if the serial was there. Actually this will work and you will succeed by doing it this way but it takes for ever and is NOT a good way. What you should do is watch the code carefully. Look how your inputs are read/ manipulated. This can be hard at first but you'll soon notice how it calculates the length of your name/serial etc. Just keep on tracing (F8/F10), and you'll see that the serial is hiding there somewhere. Just KEEP looking.. just like this little fella 0ω0 If you can not find the serial but you manage to find the byte to patch you have two choices. Type D XXXX:XXXXXXXX (the number left to the line). This will often be like: 017F:00001234 or something similar. Now the HEX value of the line will be shown in the DATA window. So NOTE the bytes. At least note 8 of them (= FF FF FF FF FF FF FF FF). The other choice you have is to NOTE the line itself (= JE XXXXXXXX) but this is not a good way to do it cause the program will most likely have several examples of that code elsewhere in the text. It is, however, possible. Ok, that was pretty much all i could teach you. You're on your own! 3) <---------------- So you wanna know how to patch? Sure you do cause what else are you gonna do? You could chose to manually patch the file or you could make a patch to do it automatically. It should be pretty obvious what to chose and we're of course gonna chose the easiest one..i'm too lazy :) To make this patch you'll need Turbo Pascal for DOS. You must also know the basics of TP programming, but this should lot be hard since it's easy and very logical. Below i will show you ONE way of making a patch. This if, however, an enhanced version since i added FileSize check. (This example is originally made by tKC-CiA'99..TNX!): * Beginning of Turbo Pascal patch Example * Program PATCH; <--- Program Name! Uses Crt; <--- Uses the Crt unit! Const A: Array[1..1] of Record A : Longint; B : Byte; End=((A:$FFFF;B:$FF)); <--- A = Offset, B = Byte C: Array[1..1] of Record D : Longint; E : Byte; End=((D:$FFFF;E:$FF)); <--- D = Offset, E = Byte txt:array[0..3] of byte =($FF,$FF,$FF,$FF); <--- Text (HEX) Var Ch:Char; I:Byte; F:File; Size:Longint; { GemExitProc: Pointer;} begin Assign(F,'FILENAME.EXE'); {$I-} Reset(F,1);{$I+} If IOResult <> 0 then begin writeln('Can''t find FILENAME.EXE'); halt(1); end; For I:=1 to 1 do <---| begin | Seek(F,A[I].A); |_ First Offset/Byte ch:=Char(A[I].B); | Blockwrite(F,Ch,1); | end; <---| For I:=1 to 1 do <---| begin | Seek(F,C[I].D); |_ Second Offset/Byte ch:=Char(C[I].E); | Blockwrite(F,Ch,1); | end; <---| begin <---| seek(f,$FFFF); |_ Patch the text blockwrite(f,txt,4); | end; <---| Writeln('Patching complete!'); end. * End of Turbo Pascal patch Example * So, this should pretty much cover it. But i'll give a short explanation to you who do not understand it. First we have the constants which represents the Offset/Byte to patch. (In this case Offset:FFFF / Byte:FF). So what you need to do it find the offset and put it in instead of FFFF and also instead of the FF by the byte. (Could be 74 / 75 / EB / C3). The second part of this patch gives you the option the change a string in a program. This can sometimes be usefull if you want to change a text to say: Cracked by... This is, however, not something that is used very often but i thought i'd include that too. To patch a text you'll need to get the text in HEX. Then you change the $FF,$FF to the bytes and change the numbers of the array. This can be a bit tough, but never the less you should be able to make it work after a lil' while. By doing this you'll also have to change the FFFF at the seek(f,$FFFF) to match the offset of where you cant to change the text. Note that you will also have to change the number at the end of the blockwrite command to fit the array. When everything is done correctly you can add a bit text or just compile the program and you'll have a working patch. Note that before you even think of distributing it you MUST test it so you don't spread a NOT working crack. I hope this helped you a bit on the way of making a patch. If you for some reason don't have Turbo Pascal then please don't come bugging me for it. Search the Warez sitez or something, i do NOT provide that kind of help! Once again tnx to tKC for providing me with this code in the first place. 4) <---------------- Well, this part is actually new. Usually i just write tutorials for programs that i've cracked myself, but this time i figured that if i could help people to learn by answering their own questions it would be much better. So that's why i've made this section. If i get more subject-requests i will of course continue this section in the future tutorials. 4.1) <---------------- EagleWolf old buddy old pal..finally you got the guts to ask for help :) j/k You wanted to know the basics of Visual Basic (VB) cracking. Normally i would advice you to skip VB cracking until you get better and more experienced, cause VB cracking can really be a bitch sometimes. Never the less i'm kind and wanna help an old friend - not to mention all the other ppl out there who is also interested in this subject. VB cracking can be approached in two ways. Well actually several ways, but the only ways you need to know are the following: SmartCheck (SC) / SoftIce. Cracking a VB app using SC can sometimes be VERY easy and it is just a matter of minutes before you have the correct serial right in your face. This you will some day see cause there are a lot of bad programmers out there :P In SC you will not have to set any breakpoints or anything else that might make you give up. You will only have to launch SC, load the file and RUN it. It will then pop up and a dialog will be showed to you. On this dialog there is a button called "Acknowledge", which you will, sometimes, have to click MANY times. But for now you launch the program, run the file and click that button until you're inside the program. Then you go to the REGISTER screen and like before you enter your OWN name and a random serial. Then you click the REGISTER/CHECK/WHATEVER button there might be and go back to SC. The window on the left should now have expanded a bit and you should see something like: +Register_Button_Click, or something similar. What next? Well you see the + in front of the line? I wonder what that means...why not click it? Done? Good! Now you have expanded the things that happens when you press that button. The list of actions taken after clicking REGISTER can sometimes be very long and complicated but most often it's rather small and easy to attack. What to do next is hard to tell. Well actually it's not, but i can't say that you have to do this and that and stuff, cause not TWO programs are the same. You will simply have to click the actions you expanded and look at the window on the right to see if there is a suspicious number. This number will most likely appear right after the random number YOU entered, since they'll need to be compared. Look carefully and note any suspicious number you find. If you can not find any numbers, look again VERY carefully. If you still can't find any number then the programmer thinks he's a smart ass and you'll now need a stronger and more powerfull toy of this world..... So what are you waiting for??? Launch SoftIce and let's crack that sucka! (load Softice the way i described earlier in this text). Cracking VB appz using Softice can also be hard but never the less it's possible. One reason why so many ppl give up on a VB app is that they don't respond to normal breakpoints. Then ppl don't know what to do and they delete the program instead of KEEP trying! When cracking VB you will VERY often use the breakpoint called: HMEMCPY. This breakpoint will break every time data is copied to/from memory, so thre must be an easier way. Lucky you...there IS! Almost all VB appz also use the breakpoint: MultiByteToWideChar, cause that's the way VB reads the input. It converts all input to WideChar. As an example of this: 'BuLLeT' will be 'B u L L e T'. This process is called MultiByte... So if you want to search for your name while cracking a VB app you'll not find anything unless you type: S 0 L FFFFFFFF 'B u L L e T' If you forget the spaces you will not get an answer to the search. So where do i want to go with this? Well since 99% of all VB appz do this, it may be a good idea to use it. Or am i wrong? You tell me! Since it converts ALL your input to WideChar you will be, using this, able to break right in front of where your name/serial is converted. This means that you may break almost right in front of the REAL serial! Great eh? How you find the serial after setting this breakpoint is up to you, but try to read the part about SoftIce in this text for further information. 4.2) <---------------- (In this part i assume that you have succesfully cracked a program into accepting ANY name/serial but that it's not registered when you restart it). A program not being registered is one of the most common questions, cause how do you attack such a program? This scares a lot of ppl away but why? Is it really THAT hard to crack? You'll soon learn that it's NOT! Again you need to think logical. How come the program is not regged when you restart? Well it must have some kind of check upon startup to see if the info is correct. But where is that info stored? Well, some programmers hide the info, and maybe even encrypt it, in the EXE-file itself. If you have such a program i would advice you to go on to another program since that's way above your level YET! The most commonly used place is INI-files or the Registry. The program will most likely write the info you type into one of these and check when you restart it. So what we need to do it remove that check right? Yep :) Finding this check can some times be hard, but in 90% of the cases it's pretty easy. You can not find such a check by searching for .INI / Reg in the SDR part of W32Dasm, but what you need to do is find a piece of text in the program which shows that it's IS/NOT registered. An example of this could be: * Evaluation Copy * Trial Version * 30 days period * Licensed to: * Registered to: The most used is the Lincensed to:/Registered to:. This text you'll probably find in SDR. So double-click it and trace up like before. Now you should see some references and other stuff that might not be important but somewhere in that code you'll see a CALL in which the INI/Registry is called. When/if you find that particular CALL you'll see something like: GetPrivateProfileString, RegQueryValue. You will of course not be able to find this ALWAYS but in the cases where you find it you should also see a JE / JNE / JZ / JNZ command very close. What this means is that it reads your input, calculates it and compares it to the number it SHOULD have been. So like before you will need to reverse that Jump. This is the most used way of reading registration upon startup, but of course there are many more. Unfortunately i don't have time to describe all of them but read and learn ! Luck coming at ya ! 4.3) <---------------- FunkyZero, i'm actually kinda lost here cause i don't really know what you want me to write about. How to remove a Softice check? How to code it? Well i think that you wanna know how to remove it so that's what i'm gonna try to tell ya. First of all; if you, as one of your first programs, get a program which has anti-softice code i would advice you to skip it. Removing such a check CAN be REALLY hard, and there is actually no way to describe how to remove such a check. This is because there are several ways to code such a check and programmers do not code alike. There is, however, in some cases a way to do it rather easily. This is when the program crashes and gives you a GPF (=General Protection Fault). When you get this message a Code Location/Offset will be given to you and this is exactly what you need. Cause as you see the check must have been performed right before this GPF. Therefore you will note the location and disassemble in W32Dasm. Then go to that location and look carefully. You will look for code looking like: Cmp xxxxxxxxxxxxx, 01 (note the 01) Jz xxxxxxxx or Cmp xxxxxxxxxxxxx, 00 (note the 00) Jz xxxxxxxx When checking for Softice a FLAG is set (0/1) to tell the program whether the check was successfull or a failure. This is the 00 / 01 that desides that. Then the program checks (in the lines above) and jumps if the result is Zero. This means that if you reverse the Jump the check will be removed. You can also change the 00 to 01 in the Cmp-line to make it perform a reversed check. But now you might encounter another problem, cause what if the program is encrypted/packed..... 4.4) <---------------- Tnx for leading me on to this Z-Wing! IF the program you're trying to crack is encrypted/packed you can not just disassemble in W32dasm and change the code cause that might crash the program. So what you need to do is decrypt/unpack it first. But before you do that you will have to check how it is protected. By this i mean that it's no good to decrypt a packed program nor is it any good to unpack an encrypted program. So you need to see how it is protected first. This can, in one way, be done by HIEW the file and look at the first page. There you'll see info like: .data / .text / .rsrc. If you see this the program is most likely not encrypted. Another way is to search for text in the program. Like: Registered, Unregistered etc. If you see this text the chance that the program is encrypted is rather small. There is, however, a chance that the author has used some other kind of encryption but patching should now be possible. (Note that if the program has CRC-check patching will not work). Let's assume that the program is packed we will now need to unpack it. There are many ways to unpack a program. Manually is, if you're good, the best way, but if you suck you should use an unpacker instead. Like ProcDump. For further info on using procdump read the manual included in the procdump archive. Procdump supports unpacking of several packers so the chance that yours is in there is rather big. So you run ProcDump, select Unpack, select the FILE, unpack and try to patch again. If you succeed CONGRATULATIONS! If you don't... ..well then try another program ;) This was the first part of encryption in programs. The next part i'm gonna describe is how to encrypt text in a Delphi application. Encrypting text in a program is actually a good way of confusing crackers cause they can lot, like i mentioned earlier, search for the text in SDR. They'll only find some strange things which they can not seperate. Therefore use encryption when you code. An example of such a procedure could be this: Procedure TXTCRP(Var S: String); Var X: Byte; Begin RandSeed := Length(S); FOR X := 1 TO length(s) DO S[X] := Chr(Ord(S[X]) XOR (Random(512) OR 512)); End; Var Name: String; Begin Name := edit1.text; TXTCRP(NAME); edit1.text := Name; End. This is a simply encryption procedure which will hide a text. This is, however , not ONLY an encryption procedure but also decryption. If you do the TXTCRP(NAME) again you'll get the decryption text. This is not a hard way of encrypting your text but i bet that many ppl will be confused by this. Do this to all of the text in the program, for example in the Form1.Create so that all the text is decrypted when the program starts. I hope that tought you a bit about encryption of files and text within files. 5) <---------------- Actually i didn't really plan to include this, but since Nobody agreed, and i got an email asking for some keygen source-code in Delphi4, i thought that i might as well include it. I will not provide any describtion on how to make it , nor will i help if you can't make this code work. This piece of code is for a prgoram called HotChrome ScreenSaver. This keygenerator is made by BuLLeT & Nobody. procedure TForm1.Button1Click(Sender: TObject); var i, i1 : integer; s, s1 : string; begin s := edit1.text; i1 := strtoint(s); i := ((i1 div 3 And (94917020 + 1949)) Mod 2147483647) + 1; s1 := inttostr(i); edit2.text := s1; end; Hope this will teach someone who just needed the last bit the final stuff so he'll be able to make a keygen next time himself. :P 6) <---------------- To end this text i would like to say to all the newbies out there: ???????????? WHY IS IT SO HARD TO LEARN ???????????? This is is definately not the first tutorial you've read, it might be the easiest though, but don't you learn anything from reading tutorials? I bet 80% of all of you have every single version of tKC's tutorials volume #1-#15, and that you have read them several times. But why? Don't you learn anything from them? Or do you just read them and delete them? Do you quit if you can't successfully set a breakpoint the first time you try? Don't you ever wanna become 3l33t? Talk to the vice guys? This final note is not ment as anything bad, but i just have a hard time understanding how people could STILL ask questions after they've read my last tutorial (BASIC). I really tried to go very deep into all areas but still i get questions like: "Could you take a look at this...i've spend 4 days trying to crack it but it's TOO HARD!". And then when i crack it i find that i only had to change 74 to 75 ONE place and it could be found EXACTLY like i told in the BASIC. Oh well, i guess i'll just have to drink a beer and calm down or sumfing. As a final advice i'd like to say: DON'T GIVE UP ! Even if you have a hard time, and you've tried to crack 5 programs in one day but none of them worked. Do NOT give up! Who knows..maybe the next day you'll crack 5 programs. This is not just something i say to keep you going..this is actually what I did ! * Final Words Wow..so this was the longest tutorial by me so far huh? Maybe the longest ever :) I hope you read every single line and that you understood it, cause IF you understand this text you'll see that it's not that hard to crack after all. If you think this tutorial is good and you want to contact me don't hesitate to email me. But when/if you do, please do NOT send me files without my permission. Another thing you'll need to do is, if it's a program you need help with, include the name of it. This you'll have to do in every single email you write me cause i get a LOT of emails and i can't remember which program belonged to what email. Do this and i'll answer your questions ! Oh yeah before i forget. Those of you who can easier type German, do it! I both write and understand it. This also goes for Norweigan, Swedish & Danish. * Greetings fly out to Z-Wing -> You'll make it some day dood! EagleWolf -> Keep working..on cracking i mean :) Ms_Jessca -> *huggz* ;) Nitallica -> Nice to have you back. HarvestR -> You give me greetz i give you greetz :) aCD^^^^ -> Ich bin geil auf dich..hehehehe Nobody -> Tnx for 50% of keygen source-code ------------------- i MaY Be SLoW - BuT i'M DeaDLy aS HeLL ------------------- Written by [BuLLeT-CiA'99] E-Mail: BuL_LeT@hotmail.com ------------------- i MaY Be SLoW - BuT i'M DeaDLy aS HeLL ------------------- PART 8: ~~~~~~ A DREADed Guide to Cracking Written by MisterE 13th March 1999 .----------------------------------------------------------------------------------------------. | Index | `----------------------------------------------------------------------------------------------' Introduction Serials Windows32BitDisassembler: String Fishing SoftIce: Getting Started Short Intermezzo about APIs and dlls Combining the power of Windows32BitDisassembler and SoftIce SoftIce: The 'Break on Memory Access' Approach Other Serial Protections Patching A warning before we start Finding the offset of the code you want to patch Intermediate way of finding the serial Let's Patch! Spreading the Patch Problems Nags Very Easy Nags (MessageBoxes) Universal approach to get rid of those nags Hard Nags Intermediate: String fishing using a hex-editor and W32dasm Keyfiles Arriving at the protection scheme Some common keyfile checks Visual Basic Cracking Introduction Requirements Visual Basic Programs Approaches Case1: Visual Basic 3 Programs Case2: Visual Basic 4 Programs Case3: Visual Basic 5 and Visual Basic 6 programs Using Numega's Smartcheck Using SoftICE and W32Dasm Greyed targets and CrippleWare Find out if the target is missing a feature Uncrippling CD-Checks Last Words And Greetz Tools API's that might help you breaking into SoftIce API's that are used to get text from the screen API's that protection scheme's might use API's that keyfiles protections use API's that CD protections use API's that are used to read/write from plain text files (INI, CFG) API's that programs use to access the registry API's that have something to do with time API's that put a nag-screen on the screen Visual Basic APIs Compare APIs Other APIs that are common .----------------------------------------------------------------------------------------------. | Introduction | `----------------------------------------------------------------------------------------------' Hi, Here's another essay from me and all the people that helped me by writing pieces of this guide and supporting me with info. You wouldn't be reading this essay without the help of BaneOldMan, Rhytm and {_Suby_}. I started this Guide in December 1998, quite some time back. But after some time I joined DREAD (Dutch Reverse Engineers And Deciperians), so now this is a DREADed Guide. In this Guide, I'll try to explain to you how most protections work and -moreover- how to defeat them. The protection schemes will NOT be explained in a target specific way; rather, in a general fashion, so be prepared for some theory :) I've tried to keep this Guide as readable as possible, starting from newbie level to more advanced level, sometimes you might see some intermediate cracker tips. Those tips are NOT meant for newbies, but for crackers who have some experience in cracking. I've included those tips so both newbie and more advanced crackers will have fun in reading this Guide. I've included some reference material and an index at the end of this Guide to keep it as readable as possible. Well, won't bother you with a longer Introduction, here we go :) MisterE PS: If YOU also want to write a piece for the Guide, contact me! PSS: Expect updates for this Guide, as new pieces will be added. .----------------------------------------------------------------------------------------------. | Serials | | Written by MisterE | `----------------------------------------------------------------------------------------------' Windows32bitDisassembler (W32dasm): String Fishing Most people who want to learn about cracking, start with W32dasm, because it's easy to understand. Just open the program you want to crack and go to 'Refs - String Data References'. See if you can find a string that has something to do with the registration of the target. Look for strings like: 'Thank You (for registering)', 'Wrong Serial', 'Invalid Serial', etc. You found such string? Cool! Now double-click on the string to go to the location where that string is mentioned (do another double-click on the string to go to the next location). Take a good look at the code now..........Do you see some conditonal jump to the string? Go to the location of the jump that points at the string. It is very likely that this jump determines if the serial number you entered is either right or wrong. You can create a patch for this target. You can patch this by toggling the jump. Say turn a JumpifZero (JZ) into a JumpifNotZero (JNZ). See the part about Patching for that. SoftIce: Getting Started Most of the time, when I want to crack a serial protection, I just set some breakpoint on GetWindowText(A) and GetDlgItemText(A). The A on the end means that the API is 32-bit. Short Intermezzo about APIs and dlls I just mentioned an API. I'll give you some more info about this. You probably seen all those weird .dll (dynamic-linked libraries) files in your windows directory. These dll files contain APIs or Application Programming Interface. Now what does this all mean? To start with the APIs: an API is something like a procedure or function as you know them in pascal or C. You call the API (or function) and gives it some parameters for input, in pascal you would have: Function CombineStrings(string1, string2 : string):string; In windows 32Bit assembly it would look like this: push string2 push string1 call CombineStrings (the API returns a pointer to the output string in EAX) This is just some fictional API. Notice that the parameters string1 and string2 are pushed in reverse order on the stack. You can probably guess what a dll is now: it's a library that contains APIs. End Intermezzo You press F12 (trace until you get out of a call) a few times so you get into the main program. How do you know you are out of a call? Well, that's in the caption of the code window, press 'wc' a few times to see what the code window is. If there's no caption, you aren't in a call anymore. Now look for a TEST or a CMP mnemonic (that's how these instructions are called, impress your friends with it :) You spotted such mnemonic??? Great! You've got a big chance that you landed right in the protection scheme, and -maybe- even discovered the Registered/Unregistered jump. Now trace (F9) until you reached this TEST ecx, ebx (or some other register, that doesn't matter). Take a look at the register (using 'd ebx' or 'd ecx') and write down the serial. BUT we are not always that fortunate that we get the serial at once...so read on! Note: Hmemcpy might break if GetWindowText(A) or GetDlgItemtext(A) doesn't work. See this for more API's. Combining the power of Windows32bitDisassembler and SoftIce I like W32Dasm very much! With some brain you can (sometimes) even get a serial without SoftIce. Open the Refs - String Data references, and take a look at the strings in the program. Some programs have their serial number hardcoded (written in plain text) in the program, bah, no honour to get from that program. Now, say the program has a better protection :) Say you even find a string that says you failed the serial test, or something like 'Thank you!'. That's what we want to hear! Now take a look at the address of this string (by double clicking on the string). Scroll a bit up and LOOK, examine the code, it won't take you long. You probably see something like 'Referenced by a conditional jump at 44E7C3'. Scroll up to this address and write down this address. You could Patch the jump. But there are some warnings. Now you don't want a lousy patch! You want a SERIAL. I'll tell you how to. Fire the target and place a breakpoint on Hmemcpy. Press a button or something and you'll get kicked into SoftIce. Place a breakpoint at the address you wrote down and disable the breakpoint on Hmemcpy. Go to the registration screen and enter some name/serial and the program should break. Look into some register to find out what your serial is. Why did I tell you to place a breakpoint on hmemcpy? Well, if you didn't place this breakpoint and just set a breakpoint at the address, SoftIce wouldn't break. That's because SoftIce has to know on which program it should break on. Intermediate tip: type 'addr' to see which program SoftIce is hooking on, you can also type 'addr name_program' to tell SoftIce which program it should break on. Softice: 'break on memory access' approach Ok, we got better protection scheme! Time for the 'break on memory access' approach. Say you got a program to break and you're in SoftIce. Do a search on the serial that you entered by typing 's 0 l ffffffff 'my_serial'' If SoftIce finds your serial before 80000000h then you got a good chance finding a serial. Why did I say 'before 80000000h'? Because above 80000000h you only have useless copies of your serial (well, most of the time). Now put a breakpoint on this memory location. Do this by typing 'bpm address' or 'bpr starting_address ending_address RW'. The RW means that SoftIce has to break when a program reads or writes to that address. Now continue running the program. The program should break. Take a look at the code and follow it. Look for CoMPare functions, procedures that check if you entered a correct serial (no ascii codes above 7Ah, etc). If you spot such procedures, you just have to trace to look what the program is doing, use your brain to figure out what the program is doing. If you didn't spot these procedures, well guess you have to do some more tracing, but most of the times you do get the serial comparison routine. Other Serial Protections Well, not all programs are as easy as I described above -Sigh-. But you'll feel great when you've cracked this little bastard. Maybe you couldn't find the right API to break. Ok, then check out this list. Or you got lost in the dark codewoods, which is a common problem. Well, also this time you might want to try another approach, using other API's to break on, OR if you think you are near the serial, trace a little more. Or some might encounter weird 'FSTP' etc. mnemonics. Then you got a program that uses the 80-bit FPU registers to generate/check it's serial. Go here to learn more about them. And if this doesn't solve your problem -Sigh- go to #cracking4newbies on EFNet, they'll help you if you ask nicely enough. .----------------------------------------------------------------------------------------------. | Patching | | Written by MisterE | `----------------------------------------------------------------------------------------------' A warning before we start I'll say it to you right now: I hate patching. There are numerous reasons why you should not patch, though there are situations when you can't do anything else. Like when you want to remove that nag-screen from some program that doesn't let you enter a name/serial. If you can enter a serial or register the program without patching, do it! If you want to patch you might encounter problems like programs that do some CRC checks or check multiple times. Another common problem is that newbies patch some jump just before the call to a MessageBoxA. The programs tells you it's register, but meanwhile you only thing you patched was that the program displays the 'regged' message instead of the 'unregged' message. MAJOR TIP: There's nothing worse than patching a file, and finding out that the program is still unregistered. You probably missed some other check, or simply patched the wrong code. Therefore TEST your solution before doing ANYTHING else. You can do this by breaking at the location of the jump and then reverse the zero flag by typing 'r fl z'. Finding the offset of the code you want to patch Anyway, if you're still interested in patching i'll tell you how to patch. To patch you need two things: you need to know the location (offset) of the code you want to patch and you'll need a hexeditor. Say you discoved some JumpifZero using SoftIce and you want it to change to JumpifNotZero. First we need to know what the location of that offset. Say softice tells you that the JZ is located at 4206DEh. From this location we have to get the file offset, meaning the location of the JZ in the file, this is NOT the same as the address you got from SoftIce. You can find the file offset by opening w32dasm and searching for the address SoftIce gave you. If you look at the bottom of the w32dasm window, you'll see something like: Code Data @:4206DE Offset 0003F3B4. The last offset is the one we need to know. Intermediate way of finding the offset Another way to get is the file offset using SoftIce and w32dasm is that you use SoftIce to find the location of the JZ. Then right-click on the address of the jump in the code window and click on 'diplay'. Now take a look at the title of the data window. The title should say something like Program_name!.text+000006DE. The offset of this program is at .text+6DE. Now we have to figure out where .text starts. When you open this program with w32dasm you'll see something like: Object1: .text RVA: 1000 Offset: 1000. So this JZ is located at 1000+6DE = 16DEh. This last method of getting the file offset might be more difficult, but i think it will work for programs that change their imagebase (imagebases for normal programs are around 00400000h, though DLLs are more likely to have image bases around 00680000h). Let's Patch! In both SoftIce and w32dasm you can see what the opcode for JZ is: 74h. if you don't know what the opcode for JNZ is, you could look up the opcodes reference (opcodes.hlp), which can be found on most good reverse engineering sites. At this time we're ready to patch. Start an hexeditor and open your target. Search for the file offset we found. Now change the 74h (JZ) to 75h (JNZ). Save the file and you patched the program! Let's hope the program doesn't have any other check apart from the one you just patched. Spreading the Patch You might want to write a patcher so you can spread your patch to other people. There are several utilities that can create a patch for you. Personally I don't like those utilities, even though some of them are real masterpieces. I like to do my cracks myself, easiest way is to learn some programming language. Believe it or not, but that was one of the reasons for me to learn pascal. I've also written a tutorial for writing a pascal patcher, contact me to get it. Problems Sometimes problems arise. The program is giving some weird error after you patched it, or simply remains unregistered. Serveral things can cause this. Maybe the target is doing a CRC check, you missed a check, or you just patched the program this way, it shows the registered window instead of the unregged one. Well, i can't help you with this, mind you: i have warned you before ;) .----------------------------------------------------------------------------------------------. | Nag Screens by Suby | | Edited by MisterE | `----------------------------------------------------------------------------------------------' A nag screen is a window that pops up and doesn't disappear until you click one particular button. There are a lot of ways to create this nag-window, so there are also lot of approaches to crack them. First we need to find where this nag-screen is located. Very Easy Nags (MessageBoxes) These are the simplest types of nag-screens, you can recognize them easily, because they are formed by a little window, with text and a windows icon and only one button. You can check if a MessageBox is causing you troubles, simply by putting a breakpoint on MessageBox(A). If SoftIce breaks, you can start removing the nag. You can Nop (Nop means 'Do Nothing') out the call to MessageBoxA, remember you also have to nop out all the pushes before the call as well! Though there are also other API's to generate windows. Universal approach to get rid of those nags This is a universal approach to get rid of the nags, and works for 99% of the nags. Load the program and when our target's nag is shown, go to SoftICE and type 'task' to see a list of names of currently active programs. Then type 'hwnd program_name' to get a list of all the window handles (objects) of this program. Look for a Window Handle that has a class name like 'Button'. Remember the Window Handle and put a breakpoint on it by typing 'bmsg Window_handle wm_command'. This means that SoftIce has to break when the window gets a 'wm_command' message. Knowledge of Windows32BitAssembly would help you some more here, but what you actually have done is saying to SoftIce: Break if the user presses a button. Notice there are also other wm_commands that will work for you, that will work for you, consult your win32 API reference to get more detail about them. Sometimes it is better to only use a 'bmsg Window_handle' because it is more general and simpler. Now try to exit Softice, press on the OK button and you should be kicked back into SoftIce, if not you might have entered the wrong Window Handle. Then press f12 a lot of times to get out of all those calls. Now you might see the main nag call. You should patch it, by for example, just nop the call out. Then re-run the program to see if it works, if not, use the backup of the program you made ;). Hard Nags Now I've got to tell that I rarely found programs protected with a hard-to-crack nag (like Paint Shop Pro). For these nags the universal approach and other ones failed, because there is no easy way to get rid of the nag without crashing the program. In this cases you have to forge some clever approach, like emulating the user's click, check out Bb's essay for this. Intermediate: String fishing using a hex-editor and W32dasm by BaneOldMan Here's a way to find strings that you can't find using W32dasm, but that you can find using a hex-editor. This can be very useful for nags, here is an example how to do it. Say we've found that string using a hex editor at offset B1602. Then open w32dasm to get the info where the DATA segment offset is located, you can find this info at the first page of the deadlisting. Say it is located at AC400. Now we subtract the DATA segment offset from the string offset (B1602-AC400=5202) and add this to 004C0000. But why 4C0000? Well, that's because the image base starts at 00400000h (get this info using w32dasm) for most programs, and in our example object DATA is located at the RVA(relative virtual address) C0000. So: 00400000 + 000C0000 = 004C0000 and at the end we add 5202 to this to get 004C5202. This is the address where our string is located. This tip is very useful when you can't find the string with W32dasm, but can with a hex editor. This is very handy to find out where that naggy message/error) gets pushed onto the stack. It's easy to find it now(in this example it will be push 004C5202). What you do with this info is up to you. .----------------------------------------------------------------------------------------------. | Keyfiles | | Written by MisterE | `----------------------------------------------------------------------------------------------' A keyfile is a registration file. The program looks if this file exists and if the characteristics of the file match with a good keyfile. If the keyfile is 'good' then the program is registered. NOTE: keyfiles are NOT .ini and .cfg files that have entries like: Name=MisterE; Serial=123454. Arriving at the protection scheme As you might have guessed, keyfiles are my favorite protection scheme, they really give you some things to think about. Keyfile protections can vary from very easy to very hard. But, before saying how you should crack such protection, i'll tell you how to discover you're dealing with a keyfile protection. Most of the time I open w32dasm and look for string like 'program.key' or 'program.lic'. If I don't find such string, and if I am still convinced it's a keyfile one, then I use Filemon. Get an old version of filemon at Fravia's Site. You might also want to take a look at his essay about this great tool. Now fire up Filemon and your program. You see the program looking for some kinda file that seems to be missing? Well, big chance that it's a keyfile. Most program's use the CreateFileA API, though there are other API's. At this time you might want to look up the CreateFileA Api. If you look the API up you'll read that the last parameter that get's pushed before the call is the filename of the file your program tries to open. So you put a breakpoint on this API (SI) and fire your target. SoftIce should break, now get out of this call and take a look at the file parameter. If it isn't the right filename, then continue running the program till you have the right filename. OK, you're at the protection scheme now! Some common keyfile checks Well, we reached the protection scheme. By now you should have created a yet unregistered keyfile with your favorite hexeditor. Most of the time the program uses the ReadFile API (other) to read some Data from the keyfile. This time it is quite important that you look up your win32.hlp. In case you're too lazy to look this one up, I've printed this one: BOOL ReadFile( HANDLE hFile, // handle of file to read LPVOID lpBuffer, // address of buffer that receives data DWORD nNumberOfBytesToRead, // number of bytes to read LPDWORD lpNumberOfBytesRead, // address of number of bytes read LPOVERLAPPED lpOverlapped // address of structure for data ); OK, take a look at the nNumberOfBytesToRead. This means that the program wants to read a certain number of bytes from the fileammount of bytes. If ReadFile fails it returns 0 in EAX. Well, this is the first common check. From now you can encounter quite a few different protections. Some programs only check if keyfile contains the name of the program. Another check, very common in the past when MS-DOS ruled the world, is that it only checks if some bytes match. Other programs do a CRC check. In other words, at this time you can encounter quite a few types of protection schemes (CRC, serial are common). So the rest is up to you. Good luck! .----------------------------------------------------------------------------------------------. | Visual Basic Cracking | | Written by Rhytm | `----------------------------------------------------------------------------------------------' Introduction Welcome, first a few words before we start learning how to reverse engineer Visual Basic programs. I wrote this tutorial to help newbies learn how to reverse engineer Visual Basic programs. This tutorial should only be used for educational purposes only, and NOT for people who are only interested in spreading quick & dirty cracks on the internet. Use the software you crack for your own goods and let other people learn the art of reversing themselves instead of doing a 2 second search on the internet. I would like to thank all my friends in #Dread and #Cracking4Newbies for all the help I got with all my reverse engineering problems. I want to thank Edison for his tutorial that gave me the courage to crack my first program. Other thanks go to Fravia+ and all the people on his site. Special thanks go to Razzia, lots of the info I used in this essay comes from his fabulous essay. Requirements There are a couple of basic tools you'll need to follow this complete essay. If you haven't got them yet, download them somewhere from the web or just buy them. These are the tools I've used in this tutorial: W32Dasm 8.93, SoftICE 3.24, SmartCheck 6.0, Visual Basic 3 Decompiler, Visual Basic 3 Decompiler Addon, Visual Basic 4 Decompiler, Visual Basic 4 Decompiler Addon. I added a list with the complete listing of all the Visual Basic 5.0 runtime library functions. You can read it in the other API's section. Visual Basic Programs I hope you all now that Visual Basic programs don't call Windows APIs directly. They call a large runtime library with the most common Visual Basic functions. Q: Does a Visual Basic Program NEVER use any of the standard Windows APIs? A: In general no, in all the VB programs that I've cracked, I only had one case of a program that called GetDlgItem. If you're not sure just look at the string data reference in Win32Dasm BUT the Visual Basic runtime library does call the Windows API calls. Every Visual Basic program needs this library else it won't work, in most cases you can find this file in your windows\system directory. Every version has it's own runtime library (I'll discuss version 3 and higher in this essay). This is also the weak spot of Visual Basic programs, if we know the functions inside the runtime library and if we have the code calling the function, all we have to do is break at the function and we're at the place we want to be... Hehe, but we're going too fast now. Let us first take a look at the different approaches. Approaches There are several approaches to cracking Basic programs. You can base your decision on the most appropriate approach to use by checking the version it's written in, and the method used to compile it. Q: How do I know which version my Visual Basic program was made in? A: Download a program like Quickview and quickview the executable, or use a filemonitor to see which version of the runtime library the program is using. Most of the time the programs documentation already gives you this information. As said before every program uses it's own runtime-library, here is a list with the different runtime libraries: Visual Basic 3.0 Vbrun300.dll 16-Bit Visual Basic 4.0 Vb40016.dll 16-Bit OR Vb40032.dll 32-Bit Visual Basic 5.0 Msvbvm50.dll 32-Bit Visual Basic 6.0 Msvbvm60.dll 32-Bit Case1: Visual Basic 3 Programs These programs are very easy to reverse, just use a vb3 decompiler (don't forget to install the additional ocx controls). When you've decompiled the target you've got the source-code of the program. You'll need a little bit of Visual Basic knowledge but with some brains you should have no problems reverse engineering the program. Hint: When you've decompiled your program and the protection-routine calls many subroutines, think about giving the variables easy to recognize names. Case2: Visual Basic 4 Programs These programs require a better look, first try to decompile your program. If you're lucky (chances are about fifty-fifty) you get the source and can start searching for the protection routine. Otherwise you'll have to use SoftICE and W32Dasm to reverse the program. Chapter 3 deals with this approach. Q: Does Decompiling only work with 16Bit Visual Basic programs? A: No, it works as good as with 32Bit Visual Basic programs, just try it out. An even better method is to examine it with SmartCheck, more about Smartcheck in Chapter 3. Case3: Visual Basic 5 and Visual Basic 6 programs The approach for these programs is the same. You can't decompile Vb5 programs yet, although the author of the Vb3 and Vb4 decompiler hopes to release a Vb5 Decompiler soon. Your approach will depend on several things; I would like to mention one important thing. When someone writes a Visual Basic program he can choose two methods for compiling his program. Compile it to P-Code or to Native Code. It's easy to find out which way the program has been compiled. First try to load the target into Smartcheck. Are you getting an error ?? Then it's P-Code. If there's P-Code involved try to get your serial with the help of SoftICE and W32Dasm. Using Numega's Smartcheck Well, this tool is as good as a decompiler, maybe better because it only shows you the routines you're looking for. An important thing is to configure Smartcheck. (I assume you're using Smartcheck v6.0). The most important setting can only be changed once a program is loaded. Choose for Program - settings - Error detection - Advanced. Uncheck 'suppress system API and OLE calls' You also might want to go to Program - settings - Reporting and set SmartCheck to report some more events. Well, it's time to load your first target in Smartcheck. The approach is very simple. Click the play button. Navigate to the registration part, enter a name and serial, and click the button. Go back to Smartcheck and go to the right event-handler. Collapse it and you'll see your name and code being saved in a String. Take a good look, sometimes the serial is right in front of you. If not, choose View Show All Events. Now things are going cool . You'll see all the API calls and all calls to the VB runtime library. Take a good look again, study this information and 9 out of 10 times you can reverse the program this way. Q: Why is the ExitProc suddenly called ?? A: ExitProc = Exit Procedure. Something went wrong, the serial you typed wasn't correct, most of the time this call is made AFTER the final compare. But sometimes the program checks the length of your serial before it compares the codes or it does some other compare before the final compare. If you're lucky, you can retrieve the proper length of the serial with the info Smartcheck gives you. But some times the help of SoftICE can come out very useful. Using SoftICE and W32Dasm So you failed to crack your program with the help of Smartcheck.. Well then the programmer must be a clever person.. SoftICE will help you here. You CAN'T use a normal approach such as you do with C++ programs. The VB runtime library uses it own calls. I've listed most of them in Appendix A. There's one function that still is in use :) It's the hmemcpy function. Just try it out on a program. The only bad thing about this call is that it'll take you quite some time to get to the code you're program uses (in other words: get out of the runtime library). When you finally get out of all those dlls you can study the assembly and find the info you were looking for. Note: If you study the Vb functions and start using them instead of the hmemcpy function you won't have to step that much (still quite much). You can discover which APIs the program is using by taking a look at the import table with W32Dasm. Most API's have pretty clear names.. You can reach Rhytm at Rhytm@newmail.net. .----------------------------------------------------------------------------------------------. | Greyed targets and CrippleWare by BaneOldMan | | Edited by MisterE | `----------------------------------------------------------------------------------------------' This part is about grey targets or crippleware: programs that you must send money to the programmer so he will send you back the FULL version. Cracking such program can be very difficult, if not impossible. But, lucky us, most of them have usual 'weak spots' on which we can attack the target. We will give some useful tips on how to tackle the targets, but most is up to you. Find out if the target is missing a feature The first step is to find out if this function/code has really been removed. Enabling some function is much easier that writing a missing function! Look in the dead listing for unused or unreferenced pieces of code that have something to do with the missing function. Like looking for calls to CreateFileA when dealing with a saved-disabled-program. It's very hard to say where you should start ungreying menuitem. Most of the time you see A LOT of calls to some routine that displays a messagebox telling you that 'this option is not available in the unregistered version'. Uncrippling Now...when you start uncrippling, you should use some Resource Editor like Borland Resource Workshop, Resource Studio32 or another Resource Editor to find the ID of the missing function. Try to locate the function using a dead listing. Look if you can see any conditional jump pointing at the function, or one that jumps over the function. Also look for calls to EnableWindow using a dead listing. One of the parameters of this function indicates if a menu should be enabled or disabled. To help you a bit I've printed some info about this API and an example on how to patch it below: The EnableWindow function enables or disables mouse and keyboard input to the specified window or control. When input is disabled, the window does not receive input such as mouse clicks and key presses. When input is enabled, the window receives all input. BOOL EnableWindow( HWND hWnd, // Identifies the window to be enabled or disabled. BOOL bEnable // flag for enabling or disabling input. TRUE means enable, FALSE means disable ); Study this call well, it'll be your best shot against this type of software. Below is the example code of a hypothetical program with its feature disabled: push 00000000 ; <-- disable flag push 0000031A ; <-- handle of the window (editbox, checkbox) call EnableWindow This code could be patched to push a 1 (enable flag) instead of a 0 (disable flag), or alternatively you can jump over the code if the window starts out enabled. A program can also enable/disable windows using the SendMessage API function by sending the window message WM_ENABLE: push 00000000 ; <-- lParam: not used push 00000000 ; <-- wParam: disable flag push 0000000A ; <-- WM_ENABLE push 0000031A ; <-- handle of the window (editbox, checkbox) call SendMessageA That's all the info we've got for you, it might not be enough, but it will surely help you on your way to enabling menuitems! .----------------------------------------------------------------------------------------------. | CD-Checks | | Written by MisterE | `----------------------------------------------------------------------------------------------' Well, these are most of the time easy to crack. Most CD-check follow a pattern...and that's BAD. Because that will only make things easier for us :). Usually, the check goes like this: 1) Look/check for CD-ROM drives. Programs do this using the some variable to keep track of the drive they're currently checking and the GetDriveTypeA API. Most of the time you can find this variable using w32dasm, just take a look at the string references, look for something like '%s:\' or 'xrom', then patch this variable this way it says 'c:\' or 'c'. Now the game will check if this drive is a CD-ROM using GetDriveTypeA. This API needs a drive letter as input and will then return some value representing to it's type. Take a look at the table below. Note: ofcourse there are other API's for all these checks. Value Meaning 0 The drive type cannot be determined. 1 The root directory does not exist. 2 The drive can be removed from the drive. 3 The disk cannot be removed from the drive. 4 The drive is a remote (network) drive. 5 The drive is a CD-ROM drive. 6 The drive is a RAM disk. As you can see is the return value 5 important for us. Now make a copy of some cd to your harddisk. Now place a breakpoint on GetDriveTypeA and run the game. You should get kicked back into SoftIce. You probably see a CMP eax, 5 after the call, followed by a jump. Patch the CMP so that it says 'CMP 5, 5' or change the jump. 2) The game takes a look if the label of the CD/HD matches using the GetVolumeInformationA API. Simply place a breakpoint on this API and patch the check. Note: this API also returns more information about the drive. Interesting for us might be the volume serial number and the maximum filename length on the drive. I haven't seen any checks for this, but there might be in the future. 3) Now we have to do a check if some files are on the CD/HD like movies, music tracks, etc. The program can check this using the CreateFileA API, but also -which is more common- GetLogicalDriveStings. Create these files or patch the program into thinking they're there. Though the game can also check the files on their contents and since we don't want a 100Mb on our HD using the ReadFile API. Just patch it. 4) As we all know CD's have zero bytes free on them, or at least, most CD's. Patch this simple check using a breakpoint on the GetDiskFreeSpace API. This API also returns more information like the number of free clusters. This information is used to check if the drive is write-protected. Also patch this check. Well we're done. Hope you removed all the checks. Though there are more possible checks, like checking the cluster size of the drive the game is on. But i've never seen a program doing these checks. Oh yeah, on note: you can also use w32dasm to crack these checks, might even be easier than SoftIce. .----------------------------------------------------------------------------------------------. | Last Words And Greetz | `----------------------------------------------------------------------------------------------' Well, I hope you enjoy reading this Guide as much as I enjoyed working on it. Still this Guide isn't complete and I always welcome help from you to write a piece. I will continue to work on this guide to keep it as up-to-date as possible. If you have had problems cracking a program you can always mail me here at MisterE@freemail.nl. Greetz in no particular order greetz go to: BaneOldMan, Rhytm, {_Suby_} (for helping me with this Guide, and being nice friends), Iczelion (Your win32asm tutorials RuLe!), Knotty Dread, Gattman, Ikke (for amazing me every time ;), Douby, Noos, VisionZ, G0rgon, Anarchriz, Elmopio, Lowton, Rdm_Task, Decoder|Z, Merkuur, H3llsp4wn, Fravia, Sandman, DEZM, [Kwai_Lo], Prophecy, Bisoux, [Six6Six] and all my friends on #Cracking4Newbies, #win32asm, #iNSiDE99 and #DREAD What now follows is reference material. I've included it to get the Guide as complete as possible. .----------------------------------------------------------------------------------------------. | Tools | `----------------------------------------------------------------------------------------------' This section is about tools that are usefull to us reverse engineers. SoftIce Guess i don't have to tell you about SoftIce, it's the most powerful debugger around. If you still haven't got it, download it now! Windows32bitDisassembler Well, you should also be familiar with this tool. It is one of the best disassemblers. Only IDA beats this guy disassembling. But w32dasm has a windows gui, so it looks much nicer and is easier to use. Visit the Win32Dasm WEB Page at http://www.expage.com/page/w32dasm. InteractiveDisAssembler IDA beats w32asm at disassembling and has more features, though it lacks a nice windows gui. But good news has arrived, the people at DataRescue are busy working on a windows version of IDA. Can't wait to see it working. FileMonitor This is a great tool from NtInternals (www.ntinternals.com). It monitors which files want to read from other files. This is particularly handy when you want check if a program uses a keyfile to see if it's registered. It might also be handy for programs that store their registration information in .ini or .cfg files. No reverse engineer should be without this tool. Note: this program has a very nice keyfile protection. RegistryMoninor This is also a great tool from NtInternals (www.ntinternals.com). Regmon monitors which programs are accessing the registry. Use regmon for all kinds of protection. Like most products from NtInternals, this program uses a keyfile. HexWorkShop This is imho the best Hexeditor around, it's simple to use. You will need this tools alot! Get it at www.bpsoft.com. HIEW (Hacker's view) This is also an hexeditor. Some people like it more than HexWorkShop because it also show all the mnemonics. You can easily change mnemonic with this tool, without knowing the right opcodes for them. I dislike it because it hasn't got a nice Win GUI...but if you think appearance isn't important, then get it! Do a simple search on the Internet to find it. .----------------------------------------------------------------------------------------------. | API's that might help you breaking into SoftIce | `----------------------------------------------------------------------------------------------' Here's a list of API's that might help you break into SoftIce, though if none of these API's work, you should open the target with Quickview or W32Dasm to get a list of the imports (the API's that this program uses) of this program. Take a look in the list if you see some API that might be usefull for cracking your target, then take a look in your win32.hlp for a description. Note: there are some variants on these API's, for example, try typing 'exp RegOpenKey' in SoftIce. API's that are used to get text from the screen GetDlgItemText(A) - Retrieves the title or text associated with a control in a dialog box. GetWindowText(A) - Copies the text of the specified window's title bar into a buffer. GetDlgItemInt - Translates the text of a specified control in a dialog box into an integer value. Hmemcpy - Makes a copy of data that it reads from a textbox, 16-bit BozosLiveHere - 32-bit version of Hmemcpy GetKeyState - Function retrieves the status of the specified virtual key. The status specifies whether the key is up, down, or toggled. API's that protection scheme's might use LstrlenA - Returns the length of the specified string. LstrcpyA - Function copies a string to a buffer. API's that keyfiles protections use CreateFileA - The CreateFile function creates or opens files and returns a handle that can be used to access the file. _lopen - 16-bit version of CreatefileA ReadFile - The ReadFile function reads data from a file. _lread - 16-bit version of ReadFile SetFilePointer - Function moves the file pointer of an open file. API's that CD protections use GetDriveTypeA - Function determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive. GetLogicalDrives - Function returns a bitmask representing the currently available disk drives. FindFirstFileA - Function searches a directory for a file whose name matches the specified filename. FindFirstFile examines subdirectory names as well as filenames. FindNextFileA - Function continues a file search from a previous call to the FindFirstFile function. GetVolumeInformationA - Function returns information about a file system and volume whose root directory is specified. GetLogicalDriveStrings - Function fills a buffer with strings that specify valid drives in the system. GetDiskFreeSpace - Function retrieves information about the specified disk, including the amount of free space on the disk. GetFileAttributesA - Function returns attributes for a specified file or directory. API's that are used to read/write from plain text files (INI, CFG) GetPrivateProfileString(A) - Retrieves a string from the specified section in an initialization file. GetPrivateProfileInt(A) - Retrieves an integer associated with a key in the specified section of the given initialization file. WritePrivateProfileString(A) - Copies a string into the specified section of the specified initialization file. WriteProfileString - Copies a string into the specified section of the WIN.INI file. API's that programs use to access the registry RegCreateKey(A) - Function creates the specified key. RegDeleteKey(A) - Function deletes a key and all its descendents. RegQueryValue(A) - Function retrieves the value associated with the unnamed value for a specified key in the registry RegCloseKey(A) - Function releases the handle of the specified key. RegOpenKey(A) - Function opens the specified key. API's that have something to do with time GetSystemTime - Function retrieves the current system date and time. The system time is expressed in Coordinated Universal Time (UTC). GetLocalTime - Function retrieves the current local date and time. SystemTimeToFileTime - function converts a system time to a file time. API's that put a nag-screen on the screen MessageBox(A) - Function creates, displays, and operates a message box. MessageBoxExA - Function creates, displays, and operates a message box. MessageBeep - Function plays a waveform sound. SetRect - Function sets the coordinates of the specified rectangle. EnableWindow - Function enables or disables mouse and keyboard input to the specified window or control. UpdateWindow - Function updates the client area of the specified window. CreateWindow - Function creates an overlapped, pop-up, or child window. CreateWindowExA - Function creates an overlapped, pop-up, or child window with an extended style; otherwise, this function is identical to the CreateWindow function. DialogBoxParamA - Display a DialogBox on the screen. ShowWindow - Function sets the specified window's show state. SendMessage - Function sends the specified message to a window or windows. wsprintf - Function formats and stores a series of characters and values in a buffer. Visual Basic APIs Here you find a list with APIs that VB uses. There are quite a lot...too many if you should ask me. For that reason I haven't included all of them. Sometimes you'll see some dots after an API, that means you have to go to SoftIce and type 'exp API' to see which variants of that API are available. Compare APIs __vbaStrCmp - Very important, compares two strings. __vbaStrTextCmp - Very important, compares two strings. __vbaVarCmpEq - Compare Equal __vbaVarCmpGe - Compare Greater/Equal __vbaVarCmpGt - Compare Greater Then __vbaVarCmpLe - Compare Lower Equal __vbaVarCmpLt - Compare Lower Then __vbaVarCmpNe - Compare Not Equal __vbaVarTextCmp... __vbaVarTextTst... __vbaVarTst... Other APIs that are common __vbaFreeStr - Very usefull __vbaFreeVar __vbaVarCopy __vbaVarMove __vbaVargVarCopy __vbaVargVarMove __vbaCopyBytes __vbaLenBstr... - Returns the length of a string __vbaLenVar... rtcBeep - Beep. rtcMsgBox - Puts a MessageBoxA on the screen rtc... - Some of them are very usefull for VB time-protections Copyright (c) 1999 MisterE. All rights reserved. PART 9: ~~~~~~ I've found this article from a computer magazine "PC Quest" in India. URL: http://www.pcquest.com/mar99/cracking.asp Very interesting, a worth to read it! They have mentioned my name here.. ;) The Dark Art of Cracking How programmers protect software, and how crackers get past them Let me start this article with a standard disclaimer that one sees on sites carrying similar topics. "All material in this article is for informational and educational purposes only. Neither the author nor the publication can be held responsible for misuse of the information provided herewith." That done, let me lead you down the dark side and tell you of the things you can do there. Well, not exactly. This article is not a step-by-step cracking guide for newbies. Nor is it a source for Web links that carry such stuff. This article introduces the methods and tools used by legitimate programmers to copy protect or limit functionality of shareware, and the methods crackers use to get rid of different types of protection schemes. A bit of history Cracking, as opposed to hacking, has always been on the wrong side of the law in computing circles. Hacking generally meant tweaking or understanding the software you use to a much greater extent than the average person. However, Hollywood flicks and misinformed newspaper reporters soon turned the word "hacking" into something illegal. True hackers were furious and had to curtail their activities, whereas crackers were laughing their heads off and continuing their work. Cracking probably started with DOS-based games. If someone didn't have enough health or lives to reach the next level even after trying for a long time, they could use programs like GameHack to directly edit the value in memory and increase it to whatever you felt like. This was a slightly complex process, which involved tracking variables in memory while the game was running and modifying them. In most cases it meant a system crash. So certain enterprising individuals came up with game trainers. Each trainer had a list of variables they could modify and their corresponding memory addresses. You simply had to select the value to modify, and presto! You're in the final level with full health, invincibility, all weapons, the works. Methods of protection The advent of the shareware concept brought along a new breed of software. These are functional programs that are given free for use for a time period, after which the user has to pay up to continue using them. Shareware authors think up different ways of reminding users to pay up. Some use nag screens every time the program is run, some need a registration code to be entered, some simply expire after a certain number of days, or after a number of times the program is run. The following are the most popular methods of protecting software: Nag screens: The simplest form of protection in which small windows appear before a program loads up which reminds you to buy the software. This is mostly achieved by creating a window before the program's main window is shown and providing a time- or button-based event to open the main program. Examples of programs using this are Paint Shop Pro and TextPad. Expiration: These programs simply expire after a certain time period, or after the program has run a certain number of times. To achieve this, many different methods are used. These include the simple date checks and registry flag checks, which are easily cracked to much more complex header and file checksum related ones. For example, the FrontPage 98 trial version on the March '98 PCQ CD expires after 45 days of installation. User registration: This requires you to pay up after which you'll receive an "unlock" code based on your name, e-mail address, or some such variable that you need to enter in the program for it to work. These work by passing the name entered through some algorithm and comparing the result with the entered code. If they match, the program is registered. Examples are the very popular programs WinZip and CuteFTP. Although these methods seem complex, they are quite simple to crack, as you'll see later. Commercial strength wrappers: Many companies are releasing software in the try-before-you-buy concept, which includes a fully working product, covered by a "wrapper" that allows online user registration after taking in user's details like name, e-mail, phone, and credit card number. All Symantec products, like Norton Utilities, Norton AntiVirus, and Norton CrashGuard use this. There are many commercial wrappers available, like Release Software Agent, VBox, unBoxed, Techwave, Stirling, and many more. These are fairly complex routines and the cracks available for them are complete programs by themselves. The best part about cracking these programs are that once a wrapper is cracked, all programs using that wrapper are automatically cracked. That is, if you crack the DLL that the wrapper uses, installing any other program using this wrapper will get you the cracked program, without needing to crack it separately. Dongle (hardware) protection: This is supposedly the ultimate tool to keep out crackers. Very few programs actually use this due to its complex nature and annoyances even to a legal user. A small hardware lock is provided with the program containing a unique key or even some API functions. The program checks for the existence of this lock while starting. I haven't seen too many programs using this method, except for some versions of AutoCAD and Tally. A different version of this protection is the CD-ROM check associated usually with large games like Quake II. This method is also fairly easy to trace and get rid of. Many programs use a combination of all these to protect themselves. However, as you will see, no protection scheme has been uncrackable yet. Tools and methods of the dark side The popularity of Windows and the ease of creating programs for this platform have lead to the development of thousands of shareware programs in different categories. Crackers have an enormous job ahead of them as they try and keep up with new releases everyday. Crackers usually work with the assembly code, reverse engineering it, and have an excellent grasp of the Windows APIs as well. There is no one modus operandi to crack a program. Depending upon the program and the kind of protection it has, crackers employ different techniques to get into the program. But there are some common tools that crackers employ to start cracking the program. These programs are perfectly legal and useful by themselves. The most popular tool for crackers is a Windows debugger named SoftIce from Numega Corporation. This enables developers to set "breakpoints"-points in the program code where the program pauses while variables are checked to see whether they match expected values, in Windows programs. You can trace through the assembly code to debug problems if they occur. But SoftIce in the hands of a cracker is like a Kalashnikov with a terrorist. For example, if a cracker wants to get rid of a nag screen that comes up every time a program is started, he simply sets a breakpoint on a Windows API call, ShowWindow() in SoftIce. He then calls up the program. The moment the nag screen is shown, SoftIce pauses the program and dumps the cracker into the piece of assembly code that shows the screen. It also shows a large amount of important information like values of many registers in memory and byte offsets in the EXE, or DLL. In fact, SoftIce is so powerful that the shareware version of SoftIce was used to crack itself and make it the full version. Numega now has many restrictions on its use and users need to prove that they need the program for legitimate purposes before being able to obtain a copy. But SoftIce does not help patch the file itself. You don't want to set a breakpoint every time you want to start the program, do you? So you need to "patch" the program itself. For this, read the Byte offset value for the part of the program you wish to crack. Then open the program (EXE or DLL) in a hex editor (trusty old Norton DiskEdit will do, but there are Windows versions around too), go to that offset and patch it with the hex equivalent of the assembly code you used in memory. If this sounds complex, as I said earlier, you need to have a good grasp of assembly for getting into this stuff. Another method for which SoftIce is popular is to obtain "reg codes" from programs that require registration. When prompted for a user name and registration code, enter anything you wish, while keeping a breakpoint on an API call like GetDlgItemA(), which is used to extract the contents of a text box in Windows. The moment you press "OK" you get dumped in SoftIce. Now you know that some variable holds the registration value you just entered. The program logically calculates the real code from the user name and compares the two. If they are the same, the program is registered. So all you need to do is trace the code till you see a comparison being done and check the value of the variables. You've got the reg code for the name you entered! You can actually use this method to crack some very popular programs. Another favorite tool of crackers is W32DASM, the Win32 DisAssembler, a shareware program used to disassemble code to trace code jumps. For example, you may have seen programs that check for the existence of its CD-ROM in the drive before continuing. If it doesn't exist, it gives you an error message and exits. With W32DASM, simply search for the string that is shown when quitting. The place where the string is found, you also find the reference in memory where this was called from. Trace back to the procedure that called it and disable it. (For assembly aficionados, change a JNE instruction-Jump if Not Equal, to a JE-Jump if Equal, or even better, simply NOP it.) Protection schemes Commercial strength protection schemes like Release Software Agent (the one used by Symantec in all Norton products), Vbox, Unboxed, and many others employ much more sophisticated routines for protecting the software. However, none of these protection schemes have really been able to stop crackers from breaking into the program and using the software for more time than it was meant to be. Crack programs like PC_RSAG6 help you crack these programs by simply pointing to the EXE file of the program. But this does not mean that the protection schemes are weak. These schemes are very powerful and secure when used to legally purchase the product. That is, you are not in danger of broadcasting your credit card number on the Internet when using the wrapper to buy the program. The crack works at your end of the line, so that you do not have to enter anything at all and can fool the program into believing that it has been purchased. The only programs that seem to have thwarted the crackers are the ones that employ some sort of Internet-based authentication, each time it's run. Ironically, most of these programs are from the same area that started the trend of cracking-games. Programs like GameSpy and Kali are shareware programs that allow users to play online games on commercial sites for a limited period. After which the user needs to register at the site to continue playing. Although crackers have been able to crack the program itself, users cannot use the program to connect to any server as no account exists for them until they pay up. As the world turns towards the Internet for almost everything, so will the software. This will make server authentication the trend for program registration. But knowing how resourceful crackers are, I'm sure they'll find ways of circumventing these checks too. Already cracking groups like Phrozen Crew, United Cracking Force, the Exterminators, and others are working toward this goal. The first successful Internet program crack I know of was the release of an alpha version of ICQ 99, which was released on many Warez sites. Although I've not seen the uncracked version of this alpha, which is supposed to use a different authentication server method, the cracked version works just fine, with all the new features enabled. Cracking is truly an art, even if it is a dark one. Ask any programmer who has had to understand code written by someone else without any documentation or comments, about what a nightmare it can be. Crackers, on the other hand, thrive on this, and many crackers, like tKC (founder of Phrozen Crew) and Saltine (who first cracked the commercial wrapper RS Agent), have become legends in their own right. To end this article on cracking, I cannot but use the tagline of one of the most popular cracking groups around, Phrozen Crew. This explains the psychology of the cracker in one simple line, "We always get what we want!" Vinod Unny ...From PC Quest, March 1999... PART 10: ~~~~~~~ I've included 2 source codes in Delphi 4 to show you how to make patches. Also below there's my copy of WinICE.DAT to get working with your SoftICE 3.24 Enjoy them! ;) 1) -=[How to code a patch without GUI in Delphi 4]=- If we compile this project, we'll get .EXE file with 18,432 bytes in size (as with Delphi 4 Client/Server (Build 5.108) Update Pack 3) -----------------------[cut here]--------------------------- program Patch_Without_GUI; uses windows; {$AppType Console} const crackfor : string = 'Date-A-Fix v5.60'; const cracker : string = 'tKC/CiA ''99'; const fname : string = 'DFv5.exe'; const shouldbe : LongInt = 925696; const numberbytes : integer = 3; const datum : string = '15 Mar ''99'; const A: Array[1..3] of Record A : Longint; B : Byte; End = ((A:$57F6;B:$EB), (A:$57F7;B:$00), (A:$57FB;B:$EB)); Var Ch:Char; cee:string; I:Byte; F:File; FN:file of byte; label shit; Begin writeln('Program: ' + crackfor); writeln('Cracker: ' + cracker); writeln('Date Cracked: ' + datum); writeln('Filename: ' + fname); writeln; writeln(chr(254) + ' Patching...'); assign(F,fname); {$I-} reset(F,1); {$I+} if IOResult <> 0 then begin writeln; writeln(chr(254) + ' ERROR: File NOT Found!'); goto shit; end; assign(F,fname); {$I-} reset(F,1); {$I+} assign(FN,fname); reset(FN); if filesize(FN) <> shouldbe then begin writeln; writeln(chr(254) + ' ERROR: Wrong Version!'); goto shit; end; For I:=1 to numberbytes do Begin {$I-} reset(F,1); {$I+} Seek(F,A[I].A); Ch:=Char(A[I].B); Blockwrite(F,Ch,1); End; closefile(F); writeln; writeln(chr(254) + ' Done, enjoy it!'); shit: readln(cee); End. -----------------------[cut here]--------------------------- 2) -=[How to code a patch with GUI in Delphi 4]=- If we compile this project, we'll get .EXE file with 17,920 bytes in size (as with Delphi 4 Client/Server (Build 5.108) Update Pack 3) -----------------------[cut here]--------------------------- program Patch_With_GUI; uses Windows, Messages; const crackfor : pchar = 'Program: Date-A-Fix v5.60'; const cracker : pchar = 'Cracker: tKC/CiA ''99'; const datum : pchar = 'Date Cracked: 15 Mar ''99'; const fname : string = 'DFv5.exe'; const shouldbe : LONGINT = 925696; const numberbytes : integer = 3; const A: Array[1..3] of Record A : Longint; B : Byte; End = ((A:$57F6;B:$EB), (A:$57F7;B:$00), (A:$57FB;B:$EB)); var WinClass: TWndClassA; Inst, Handle, Button1, Button2, Label1, Label2, Label3, Label4: Integer; Msg: TMsg; hFont: Integer; Var Ch:Char; I:Byte; F:File; FN:file of byte; procedure Check; begin assign(F,fname); {$I-} reset(F,1); {$I+} if IOResult <> 0 then begin MessageBoxA(Handle, 'File NOT Found!', 'Error!', MB_OK); exit; end; assign(F,fname); {$I-} reset(F,1); {$I+} assign(FN,fname); reset(FN); if filesize(FN) <> shouldbe then begin MessageBoxA(Handle, 'Wrong Version!', 'Error!', MB_OK); exit; end; For I:=1 to numberbytes do Begin {$I-} reset(F,1); {$I+} Seek(F,A[I].A); Ch:=Char(A[I].B); Blockwrite(F,Ch,1); End; closefile(F); MessageBoxA(Handle, 'File Succesful Patched!', 'Results', MB_OK); halt; end; function WindowProc(hWnd, uMsg, wParam, lParam: Integer): Integer; stdcall; begin Result := DefWindowProc(hWnd, uMsg, wParam, lParam); if (lParam = Button1) and (uMsg = WM_COMMAND) then Check; if (lParam = Button2) and (uMsg = WM_COMMAND) then halt; if uMsg = WM_DESTROY then Halt; end; begin Inst := hInstance; with WinClass do begin style := CS_CLASSDC or CS_PARENTDC; lpfnWndProc := @WindowProc; hInstance := Inst; hbrBackground := color_btnface + 1; lpszClassname := 'AG_TESTWINDOW'; hCursor := LoadCursor(0, IDC_ARROW); end; RegisterClass(WinClass); { Create Main Window } Handle :=CreateWindowEx(WS_EX_WINDOWEDGE, 'AG_TESTWINDOW','tKC''s Generic Patch 1.00', WS_VISIBLE or WS_SIZEBOX or WS_CAPTION or WS_SYSMENU, 383, 278, 255, 95, 0, 0, Inst, nil); { Create a button } Button1 := CreateWindow('Button', 'Patch!', WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT, 196, 8, 45, 23, handle, 0, Inst, nil); Button2 := CreateWindow('Button', 'Exit!', WS_VISIBLE or WS_CHILD or BS_PUSHLIKE or BS_TEXT, 196, 39, 45, 23, handle, 0, Inst, nil); { Create a label (static) } Label1 := Createwindow('Static', '', WS_VISIBLE or WS_CHILD or SS_LEFT, 5, 5, 190, 13, Handle, 0, Inst, nil); Label2 := Createwindow('Static', '', WS_VISIBLE or WS_CHILD or SS_LEFT, 5, 20, 190, 13, Handle, 0, Inst, nil); Label3:= Createwindow('Static', '', WS_VISIBLE or WS_CHILD or SS_LEFT, 5, 35, 190, 13, Handle, 0, Inst, nil); Label4:= Createwindow('Static', '', WS_VISIBLE or WS_CHILD or SS_LEFT, 5, 50, 190, 13, Handle, 0, Inst, nil); { Create Font Handle } hFont := CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH or FF_DONTCARE, 'MS Sans Serif'); { Change fonts } if hFont <> 0 then begin SendMessage(Button1, WM_SETFONT, hFont, 0); SendMessage(Button2, WM_SETFONT, hFont, 0); SendMessage(Label1, WM_SETFONT, hFont, 0); SendMessage(Label2, WM_SETFONT, hFont, 0); SendMessage(Label3, WM_SETFONT, hFont, 0); SendMessage(Label4, WM_SETFONT, hFont, 0); end; SetWindowText(Label1, CrackFor); SetWindowText(Label2, Cracker); SetWindowText(Label3, Datum); SetWindowText(Label4, 'Filename: DFv5.exe'); UpdateWindow(Handle); { Message Loop } while(GetMessage(Msg, Handle, 0, 0)) do begin TranslateMessage(msg); DispatchMessage(msg); end; end. -----------------------[cut here]--------------------------- 3) -=[My Copy of WinICE.DAT for SoftICE 3.24]=- Copy this file over your old file and reboot! When your SoftICE is loaded, press CTRL-D to get into SoftICE and press CTRL-F1 and you're set! :) -----------------------[cut here]--------------------------- PENTIUM=ON NMI=ON ECHOKEYS=OFF NOLEDS=OFF NOPAGE=OFF SIWVIDRANGE=ON THREADP=ON LOWERCASE=OFF WDMEXPORTS=OFF MONITOR=0 PHYSMB=128 SYM=1024 HST=256 TRA=8 MACROS=32 DRAWSIZE=2048 INIT="X;" F1="h;" F2="^wr;" F3="^src;" F4="^rs;" F5="^x;" F6="^ec;" F7="^here;" F8="^t;" F9="^bpx;" F10="^p;" F11="^G @SS:ESP;" F12="^p ret;" SF3="^format;" CF8="^XT;" CF9="TRACE OFF;" CF10="^XP;" CF11="SHOW B;" CF12="TRACE B;" AF1="^wr;" AF2="^wd;" AF3="^wc;" AF4="^ww;" AF5="CLS;" AF8="^XT R;" AF11="^dd dataaddr->0;" AF12="^dd dataaddr->4;" CF1="altscr off; lines 60; wc 25; wd 15; wl; wr;" CF2="^wr;^wd;^wc;" EXP=c:\windows\system\kernel32.dll EXP=c:\windows\system\user32.dll EXP=c:\windows\system\gdi32.dll EXP=c:\windows\system\comdlg32.dll EXP=c:\windows\system\shell32.dll EXP=c:\windows\system\advapi32.dll EXP=c:\windows\system\shell232.dll EXP=c:\windows\system\comctl32.dll EXP=c:\windows\system\crtdll.dll EXP=c:\windows\system\version.dll EXP=c:\windows\system\netlib32.dll EXP=c:\windows\system\msshrui.dll EXP=c:\windows\system\msnet32.dll EXP=c:\windows\system\mspwl32.dll EXP=c:\windows\system\mpr.dll EXP=c:\windows\system\msvbvm50.dll EXP=c:\windows\system\msvbvm60.dll -----------------------[cut here]--------------------------- We really hope you've enjoyed this tutorial too much as we did! Don't miss Tutor #17 soon! ;) And as I said last time: Without knowledge, there's no power! ;) Credits go to: FunkyZero/CiA for Splash Logo. RSiP for providing tuts in this version. Barnie for providing tuts in this version. IceBox for providing tuts in this version. Klefz/CST for providing tuts in this version. pIst0lS/CST for providing tuts in this version. BuLLeT/CiA for providing tuts in this version. Merkuur/CiA for providing tuts in this version. tKC/CiA (hey it's me!) for coding this version :) All the crackers (non-members of CiA) are welcome to send tutors for the next tutorials .. see below for my email address! Greetz goto all my friends! You can find me on IRC or email me at tkc@reaper.org Coded by The Keyboard Caper - tKC The Founder of PhRoZeN CReW/Crackers in Action '99 Compiled on 18 March 1999 Cracking Tutorial #16 is dedicated to all the crackers and to.. Katrien (tnx for our gr8 4th March, and $$$.. remember our songs Inside My Head and Repeated Love?) :)