Welcome to Cracking Tutorial #40! Hiya peepz, Here's another tutor for you, nothing special :) As always, I'm busy with coding other projects... Jess: are u gonna hate me for giving u lots to do with your web site?? :p Anyway, let's go! 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 4.01 W32Dasm 8.93 Hacker's View 6.20 SmartCheck 6.03 TASM 5.00 Windows Commander 4.01 (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 is a good site where you can grab tools from: http://mercury.spaceports.com/~quel/protools/ or ask any crackers to get you these tools! Are you ready?! OK! ;) (....this tutor was wrongly published in my previous version, hereby this article is corrected, DongJong asks for apology, tnx tKC....) DongJong's NEWBIE TUTORIAL DongJong's How to get a PERSONAL SERIAL for Nokia Smart Messaging Agent v0.99b Tools to use ~~~~~~~~~~~~ SmartCheck 6.01 Where to get Tools ~~~~~~~~~~~~~~~~~~ http://cracking.home.ml.org http://surt.to/HarvestR http://crackstore.com http://www.pepsoft.com Where to get the program ~~~~~~~~~~~~~~~~~~~~~~~~ Nokia Smart Messaging Agent v0.99b http://www.wildies.de/nokia Program description ~~~~~~~~~~~~~~~~~~~ This software enables you to send smart messages (here: group graphics and operator logos, soon: ringtones) to your phone. This is nothing special, we know. But with the NSMA itïs possible to send it WITHOUT any cable or infrared connection. Procedures ~~~~~~~~~~ Start SmartCheck (sc) and open Smart Messaging Agent.exe, run the program by pressing F5 Press on all the errors the "Acknowledge" button until the program starts, NOTE: DO NOT PRESS "SUPRESS" BUTTON! as undesirable outcome will appear :> After the Smart Messaging Agent program appears, it will have a 5 second delay message dialog, just wait till countdown and press OK, now you are in program proper, click on help menu then scroll down to register and click it, i register with my friends name, like this (you can input your name and any number you want, just follow my tut) : Name: Albert Alexander Lay Serial: 3593 Key: 3456789 When all pertinent data is entered press OK, hmmm... the program just exits from the registration dialog, no error messages!, never mind, what we are after is to have done that registration thing so that SmartCheck will follow our every move, then quit or exit Smart Messaging Agent and after few clickings of "ACKNOWLEDGE" button (do you still remember that and the warning... he he, ic, that's good) SmartCheck would stop tracing already, leaving you, those bits and pieces of the traces it made for the program Smart Messaging Agent. Ok, so now let's look on the left side of SmartCheck, and look at the string with [+] Toolbars_MouseDown, click that and it expand, whew! he he, we're kind of near, below that is [+]_Click, so click on it and trace down, you'll see as Len returns LONG:20 --------> The number of input character (name) --- snip for brevity --- Mid Asc returns Integer:65 Mid Asc returns Integer:108 Mid Asc returns Integer:98 Mid --- snip for brevity --- Look here, just follow it, as the "Asc returns Integer:xx" keeps on appearing way down but of different value, why? you ask, because that corresponds to the letter of name you input, and that is case sensitive :> like this ... Place the cursor on Asc retuns Integer:65 ( it would be highlighted in blue) Now look at the right hand side of SmartCheck, waddaya see... of course a letter ... [-] String string=004557AC | |-- = "A" do the same for others, and you'll spell out your name, kewl ;-) we're near, yes checkout what should be for a small letter "a", well in case you still hadn't get it it's ... Asc returns Integer:97 ------> corresponds to letter "a" Ok, now trace down till the last letter of your name, wat da ya got? Well, same as tracing down your name input but this time, it's for the serial key you input (remember, that's the second line of input we have to deal from the registration dialog) trace down... Len returns Long:4 -----> number of input numbers, check out the right hand side... :) Mid Asc returns Integer:51 Mid --- snip for brevity--- "51" corresponds to 3, trace down, you'll notice your input serial (e.g. 3593), until... Len returns LONG:19 -----> highlight on it and see the right hand side of SmartCheck ;) [-] String string1=00455A78 | |-- = "1426836896311058481" Well, what we have, it simply says we have 19 digits for our serial input, copy it! Hep, we aren't finish yet, as we have to find our third input, which is the key input, now trace down till the end of the loop of [+] Toolbars_MouseDown, what it shows is ... Left Len returns Long:30 Click on Left and you'll see something like this... [-] sting (variant) | | | |-- Unsigned short ** .pbstrVal=0066FB64 | | | |-- String =0044855C | | | |-- = "5858585003265858553523394B351E08542F" | |-- Long Length = 30 0X0000001E It kind of suggest to get the first 30 numbers, and it's verified by the Len returns Long:30, click on it and check out the right side of SmartCheck, waddya got ... hehe... [-] String string1 = 0054014F | |-- "5858585003265858553523394B351E" Well, that's it, you've made it! Start Smart Messenger Agent.exe, and register using this: Name: Albert Alexander Lay Serial: 1426836896311058481 Key: 5858585003265858553523394B351E Check the Help --> About box and see what we got there :> Say cheese ^^!^^, in place of the Share-It! Registration reminder is your name and serial number, how kewl :> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Greetings goes to these people: tkc- i would like to thank tKC for his tutors. MsJessca- for hosting the tuts and inspiring tkc :> Albert Alexander Lay- KeWl DuDe! for the computer and Internet ;) All cracking groups and cracking fanatics and newbies galores! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hanggang sa Muli... MABUHAY! Another Tutor by DongJong ;-) sutra@goplay.com Heya Cracker, so you want to improve your skills? Well read this and you'll be a little better ;) Tools needed: WDASM and Hiew. Target: Directory Printer 2.6. Ok lets rock. First try to open Directory Printer to see how it acks. Uh an ugly Nag box that says "thank you for trying Directory Printer". Lets remember this now press ok. A Cap. We hate them dont we. So lets remove it. Fire up under Asm and Disassembler dirprint.exe. Goto Refs chouse String Data References, look after Directory Printer [Evaluation. this is the Cap we see after we pushed Ok at the ugly nag. \\\\\\\\\\\\\\\\\\\\\\\\\\\ Cut out ////////////////////////////// * Possible StringData Ref from Cde Obj -> "Directory Printer [Evaluation " -> "Copy - Day " :00447E3E 681C824400 push 0044821C (where it push that ugly msg) :00447E43 8D55DC lea edx, dword ptr [ebp-24] :00447E46 8B45E8 mov eax, dword ptr [epb-18] :00447E49 E82EF4FBFF call 0040727C :00447E4E FF75DC push [ebp-24] * Possible StringData Ref from Code Obj ->" of 30-Day Trial Period]" \\\\\\\\\\\\\\\\\\\\\\\\\\\ Cut out ////////////////////////////// what do we see here push 0044821C here it calls the ugly cap from. Lets think real hard, what would be the best to do, ofcouse to make sure that it will never push this. This is called No Operation (Nop). Double click on the line with :00447E3E 681C824400 push 0044821C Look at the buttom of Asm. Line: 163129 Pg 1942 and 1943 0f 2039 Code Data @:00447E3E @Offset 0004723Eh File: dirprint.exe Now consentrade on the offset 4723E. 4723E is the number we need. Now open Hiew, Press F9 and find dirprint.exe. Press F4 and chouse decode. Now press F5 (goto) and enter 4723E now it should look like this .00447E3E: 681C824400 push 00044821C ;" D‚L" Now press F3 (Edit) and then F2 (Asm) now delete the stuff that is there type Nop and press enter. Now there should come a box saying sbb al,082 dont edit in this just press Esc and then F9 (Safe) now press F10 (quit) and open Directory Printer. And look it doesn't play these nasty msg. GreetZ fly out too: tKC - NorthPole - [iNC] - ShannoW And Robin. Thanks you guys for all the help. Watch out for another of my tuts. -> FileCAT grrr 'Securom, another damn Addendum' tools: tasm5.0, softICE 3.23 with memory dumper (icedump?), hex editor, procdump, RPPv1.2i.. btw, my target, loader.exe 920,991 bytes 27/05/99, compressed with 'Petite'(v1.4??) from the game 'Outcast' by Appeal/Infogrames www.outcast-game.com (nice target, as 50% of the time doesnt want to run with the correct cd in anyway.) hello.. hi r!sc, wassup?? hi, i have been playin with securom.. i loved pedros tutorial on it (http://crknotez.cjb.net), and this helped me crack a few securom games, but, alas, i think sony have updated securom, so pedros tutorial dont help much now.. remember how if it knew you had been debugging it, and it refused to run anymore, until a reboot?? well, this sucks, and there were a few safe breakpoints you could use before, bpx writeprocessmemory, bpx getdrivetypea, erm, well, it knows about these now, and refuses to run.. alas, we run into a few problems.. :D well, are you a reverse engineer or a mouse?? hehe, we aint afraid of no securom.. say i wanna bpx on writeprocessmemory, to find out where it decrypts the data in the programs code, i get one break, the first one where it decrypts some securom code, then no more, the program runs in a continous loop, ctrl-alt-del to kill it, then it wont run again.. say i wanna avoid the code decryption part of it, and break on the getdrivetypea, no no no, if you have any nice breakpoints set, it just doesnt run, and after clearing them, it still doesnt run.. stuff i noticed, cms16.dll, cms32_95.dll & cms32_nt.dll are inside the program, and wrote to disk when its executed.. probably to stop people tampering with them.. :D if it knows you have been debugging it, it exits without closing the file handle to cms16.dll. try deleting it, you get a nice error, 'Cannot delete cms16: The specified file is being used by windows'. well, theres a clue, maybe.. clear all breakpoints, bpx createfilea.. run ya securom protected game: first few breaks arnt important.. windows loading the file, then a short pause, where it gets decompressed, then these are the ones we want, the first opens itself, the second? cms16.dll? the third, cms16.dll.. wait, take a look at this code.. 0137:005A1298 50 PUSH EAX <-- ptr to x:\xx\cms16.dll 0137:005A1299 FF1534685C00 CALL [KERNEL32!CreateFileA] 0137:005A129F 8945DC MOV [EBP-24],EAX 0137:005A12A2 837DDCFF CMP DWORD PTR [EBP-24],-01 <-- its already there, and 0137:005A12A6 753B JNZ 005A12E3 - cant be opened again.. 0137:005A12A8 C70580645C0000000000MOV DWORD PTR [005C6480],00000000 0137:005A12B2 6A00 PUSH 00 0137:005A12B4 6A00 PUSH 00 0137:005A12B6 6A03 PUSH 03 0137:005A12B8 6A00 PUSH 00 0137:005A12BA 6A00 PUSH 00 0137:005A12BC 6800000080 PUSH 80000000 0137:005A12C1 8D8D38FFFFFF LEA ECX,[EBP-00C8] 0137:005A12C7 51 PUSH ECX <-- same ptr to cms16.dll 0137:005A12C8 FF1534685C00 CALL [KERNEL32!CreateFileA] 0137:005A12CE 8945DC MOV [EBP-24],EAX 0137:005A12D1 837DDCFF CMP DWORD PTR [EBP-24],-01 <-- oh crap, its still -1 0137:005A12D5 750A JNZ 005A12E1 - but forcing this jump 0137:005A12D7 6A00 PUSH 00 - it will run again :D 0137:005A12D9 E8022C0000 CALL 005A3EE0 0137:005A12DE 83C404 ADD ESP,04 0137:005A12E1 EB0A JMP 005A12ED 0137:005A12E3 C70580645C0001000000MOV DWORD PTR [005C6480],00000001 0137:005A12ED 8B15C4675C00 MOV EDX,[005C67C4] well, see, it tries to create this file, and if it fails, return code FFFFFFFF, it exits.. if we trick it, make it think it could create this file, just by forcing either of these jumps, it runs again :D so not all is lost.. oops, we still cant bpx writeprocessmemory, or bpx getdrivetypea, so things are trickier, but not impossible.. what i noticed about the older versions of securom, it decrypts 20kb of program code, around the original entry point, then checks the disk, and if the correct one is in, it decrypts 200h bytes more of code at the original entry point.. the other code it decrypts wasnt important, as this was securom code.. theory, trace petite until it has unpacked the program, dump the memory, bpx on the exit point of the securom code, and when you reach it, dump the memory again, and just do a file compare, you should find a nice 20kb block of decrypted code in the second dump.. arrgh! how to bpx on the exit point of the securom code?? heh, dont ph34r, 'tis easy :D i expect you to have already fucked up the program, so it wont run anymore, and we have to make it run by changing one of the jumps after the call to createfilea, 'cms16.dll'.. good.. i used my dodgy process patcher to make a loader that fixed this for me.. T=10000: F=loader.exe: O=securomfix_cc.exe: P=5A12A6/75/CC: ; 0137:005A12A6 753B JNZ 005A12E3 $ changing this to a EB makes it run all the time, but i wanted to break here, so i change it to a CC, an int 03, then in softice, bpint 03, x. run the loader.. hey, when it breaks, dont forget to change the CC to an EB..e eip eb.. okay, when it breaks, and you have changed your int 03 to a jmp, just make your code window nice and big, and scroll, ctrl-page-down. this is where we could normally break, but bpx getdrivetypea or just bpx 5a25a2, it knows about them and stops running.. bad, keep scrolling 0137:005A259B 52 PUSH EDX 0137:005A259C FF15E04F5C00 CALL [KERNEL32!GetDiskFreeSpaceA] 0137:005A25A2 8D8548FCFFFF LEA EAX,[EBP-03B8] 0137:005A25A8 50 PUSH EAX 0137:005A25A9 FF15004B5C00 CALL [KERNEL32!GetDriveTypeA] 0137:005A25AF 83F805 CMP EAX,05 look, another place we could normally break, but, alas, we cant no more.. keep scrolling.. 0137:005A28E0 8D9548FCFFFF LEA EDX,[EBP-03B8] 0137:005A28E6 52 PUSH EDX 0137:005A28E7 FF15E04F5C00 CALL [KERNEL32!GetDiskFreeSpaceA] 0137:005A28ED 8D8548FCFFFF LEA EAX,[EBP-03B8] 0137:005A28F3 50 PUSH EAX 0137:005A28F4 FF15004B5C00 CALL [KERNEL32!GetDriveTypeA] 0137:005A28FA 83F805 CMP EAX,05 Yippee! this is another place where we would break, many many pages of code have passed before us, and we know, this is where the securom code ends, and jumps to the proper program :D 0137:005A31A8 B8A1535000 MOV EAX,005053A1 0137:005A31AD 90 NOP 0137:005A31AE 90 NOP 0137:005A31AF 50 PUSH EAX 0137:005A31B0 EB03 JMP 005A31B5 0137:005A31B2 58 POP EAX 0137:005A31B3 FFE0 JMP EAX hmm, good news, we can bpx here 0137:005A31B3 FFE0 JMP EAX, and all is well.. the program still works fine :D yah.. fine! heres another lame loader to help us on our way.. T=10000: F=loader.exe: O=securom.cc.jmp.eax.exe: ;P=5A12A6/75/EB: ; heh, my pc crashed for some reason, so this isnt needed yet :) P=5A31B3/FF/CC: ; i just wanna break on the securom exit point, the jmp eax.. $ nice one r!sc, almost time to be destructive :D now, using this loader, when softice breaks on the int 03, we can get our decrypted code, what about our dodgy calls?? remember older securom? call dword ptr [securom] for every import? and if you traced over it, the nice securom code replaced [securom] with the actual address of the import in out IAT somewhere in memory? hehe, well, buggered if this works now :( look here.. this is my original program entry point, see 005053C7.. thats the api call GetVersion, but it calls the securom code, which in time, jmp's to GetVersion, trace into one of the calls, then scroll the code window until a jmp eax.. put a breakpoint on this.. and run it.. 0137:005053A1 55 PUSH EBP 0137:005053A2 8BEC MOV EBP,ESP 0137:005053A4 6AFF PUSH FF 0137:005053A6 6810EB5100 PUSH 0051EB10 0137:005053AB 68C0525000 PUSH 005052C0 0137:005053B0 64A100000000 MOV EAX,FS:[00000000] 0137:005053B6 50 PUSH EAX 0137:005053B7 64892500000000 MOV FS:[00000000],ESP 0137:005053BE 83EC58 SUB ESP,58 0137:005053C1 53 PUSH EBX 0137:005053C2 56 PUSH ESI 0137:005053C3 57 PUSH EDI 0137:005053C4 8965E8 MOV [EBP-18],ESP 0137:005053C7 FF1528C25A00 CALL [005AC228] <-- call [securom] ... 0137:005053CD 33D2 XOR EDX,EDX 0137:005053CF 8AD4 MOV DL,AH 0137:005053D1 891594585900 MOV [00595894],EDX 0137:005053D7 8BC8 MOV ECX,EAX 0137:005053D9 81E1FF000000 AND ECX,000000FF 0137:005053DF 890D90585900 MOV [00595890],ECX my 'jmp eax' was at 59F16F Break due to BPX #0137:0059F16F (ET=286.97 microseconds) :?eax BFF9137C 3220771708 (-1074195588) "¾…|" :what eax The value BFF9137C is (a) KERNEL32!GetVersion <-- ahh now, theory, petite unpacks the code, and unpacks a real import address table :D, we just gotta find the real IAT in memory, search for the correct imports for our calls, and fix the calls to call our import table instead of the securom code.. :s 400000 l ffffffff 7c 13 f9 bf Pattern found at 0137:0051B110 (0011B110) :s Pattern found at 0137:005C6530 (001C6530) :s Pattern found at 0137:005CA3E8 (001CA3E8) :s Pattern found at 0137:0095067C (0055067C) well, we got four choices at the moment, i trace the unpacker code, and stop just before the securom code runs.. then search again.. :s 400000 l ffffffff 7c 13 f9 bf Pattern found at 0137:005CA3E8 (001CA3E8) yippee, it only finds one.. so if i edit this line.. 0137:005053C7 FF1528C25A00 CALL [005AC228] to 0137:005053C7 FF15E8A35C00 CALL [KERNEL32!GetVersion] ; CALL [005CA3E8] thats one call fixed, only about 300 left to go :) lets code something.. WHOOPS, i coded something, fixed everything, dumped the memory, copied and pasted it into my previous dump, and it worked ok.. but.. it didnt work on win95 (i am working with win98).. further debugging revealed some code like this.. 015F:00508FE0 55 PUSH EBP 015F:00508FE1 8B2D68B15100 MOV EBP,[KERNEL32!CloseProfileUserMapping] 015F:00508FE7 56 PUSH ESI 015F:00508FE8 57 PUSH EDI 015F:00508FE9 33DB XOR EBX,EBX 015F:00508FEB 33F6 XOR ESI,ESI 015F:00508FED 33FF XOR EDI,EDI 015F:00508FEF 3BC3 CMP EAX,EBX 015F:00508FF1 7533 JNZ 00509026 015F:00508FF3 FFD5 CALL EBP see this line : 015F:00508FE1 8B2D68B15100 MOV EBP,[KERNEL32!CloseProfileUserMapping] its really MOV EBX, DWORD PTR [0051B168], moving an api address from the first IAT we found.. the one thats not their when its unpacked.. securom didnt mess with this, as its not a direct call to the IAT.. well, i unpacked the executable with procdump.. ran it with loader32, and checked out the memory at 51B168, it contained 72981200.. obviously, as this is replaced with the linear address of the api function, this was my 'broken' first thunk.. i searched the unpacked exe for 72981200, and found two places, one just before all the imported function names, and the other one i had found before, further studying of the exe with my hex editor, i located the start of the import table.. the list of my image_import_descriptors, 8 of them, followed by 14h null bytes.. the terminating descriptor :D yippee! just use procdumps pe editor, edit the directory structure, point the import table to the real one.. for this program, it was 528ed8, - imagebase makes 128ed8.. okay, running it with loader32 again, checking out address 51b168, yes, its been written over with the linear address of the correct api function.. great.. halfway their.. lets code something again.. ;------------------------------------------------------------------------------ ; R!SC's dodgy call fixer for 'newer' securom ; (c) august 27th 1999 risc@notme.com ; tasm32 /mx /m3 /z /q call_fix ; tlink32 -x /Tpe /aa /c call_fix,call_fix ; copy and paste the code into compressed securom executable.. i like the pe header.. ; break on the jmp eax (in the securom code, jmp orig_entry_point) ; recode the 'jmp eax' in the call [securom] code to jmp ebx ; i3here on, faults on ; copy the code to a empty part of memory.. m 400300 l 60 530000, r eip 530000, run it :0 .486P .Model Flat .code main: call @1 ; please excuse my first attempt at kinda relocatable code @1: pop ebx mov esi, ebx add ebx, offset here-offset @1 ; return address from jmp [5ac228] add esi, offset boring-offset @1 mov edx, 401000h mov ecx, 51b000h-401000h ; iat begins at 51b000, so code hopefully ends before it search_loop: cmp [edx], 0c22815ffh ; search pattern for CALL [005AC228] jne try_again cmp word ptr [edx+4],005ah ; - jne try_again lea eax, [edx+6] ; get the address which would be pushed onto the stack pushad push eax ;jmp dword ptr [5ac228h] db 0ffh,25h,28h,0c2h,5ah,0 ; jmp blah.. here: ; k, we return here from securom code, the api address is in EAX mov edx, 51b000h ; start address of my *real* IAT, first thunk.. search_iat: cmp [edx],eax jz got_match inc edx cmp edx, 51b2a0h jne search_iat pop eax ; safty, if it cant find a match for whats in EAX in our IAT popad int 03 ; match wasnt found, break on the int 03, write down the address in EDX jmp try_again ; and fix it by hand.. got_match: mov [esi+4],edx ; save the addr of the import address we got a match for pop eax popad mov eax, [esi+4] ; retrive the address of the import in our IAT mov [edx+2], eax ; paste it over the 005ac228 in the call [securom] try_again: inc edx mov [esi],edx ; store the last addr EDX was on.. (in case of any problems..) dec ecx jne search_loop int 03 nop boring: end main ;------------------------------------------------------------------------------ right, compile it, hex edit it and hex edit the compressed securom exe, cut and paste the code from the call fixer into the securom executable somewhere.. i chose file offset 300h, in the pe header.. run your loader which breaks on the securom exit point. move the code from the pe header to somewhere else.. m 400300 l 100 530000 , r eip 530000.. put a bpx on JMP [005AC228], and run it. when you get a break, trace into the jmp, and scroll your code window until you see some code like this.. 015F:0059F15E 83C408 ADD ESP,08 015F:0059F161 61 POPAD 015F:0059F162 8B45F4 MOV EAX,[EBP-0C] 015F:0059F165 8BF0 MOV ESI,EAX 015F:0059F167 8B06 MOV EAX,[ESI] 015F:0059F169 5F POP EDI 015F:0059F16A 5E POP ESI 015F:0059F16B 5B POP EBX 015F:0059F16C 8BE5 MOV ESP,EBP 015F:0059F16E 5D POP EBP 015F:0059F16F FFE0 JMP EAX then change the jmp eax, which would jmp to the api call, to jmp ebx.. to jump back to our call fixing routine :a 59f16f 0137:0059F16F jmp ebx bc*, i3here on, faults on, cause we wanna trap any errors, and softice to break if it hits either of our int 03's.. welp, anyway, run the code, and cross your fingers.. i got a some errors, three calls returned invalid addresses, so i couldnt find them in my IAT, and two calls caused a crash.. with faults on, softice caught the crash, and all i had to do was look in memory location at the end of my code, where i store the address counter, to see what call crashed it.. 502bdd crashed it, and after fixing that, 50ce1c crashed it, so when i run it again, i edit those memory locations, replacing the FF 15 with CC 15, which stopped the code finding the correct byte pattern, thus stopping the crash, and investigate those calls by hand.. it popped up at this int 03 three times aswell.. int 03 ; match wasnt found, break on the int 03, write down the address in EDX jmp try_again ; and fix it by hand.. just write down the address in edx, and carry on, we can investigate those calls by hand aswell.. bad calls were 507c39, 50a324 & 50e0be, so run the program with your break on the securom exit point, edit the eip to point to one of those dodgy call's, and trace, break on the jmp eax.. and search for the api address in your IAT by hand :D, after all the calls are fixed, dump the memory, pagein 400000 11b000 c:\callsfixed.dat .. copy and paste this into the file you unpacked with procdump, and fixed the IAT address in the pe-header.. cross your fingers, run it :D hey, it works :P thats it! securom is a bit more fun this time around, but if it wasnt for Pedro and +Xoanon, i doubt this tutorial would have been possible. In the three or so days this crack took me, i have learnt quite a lot, and hopefully, you, have learnt something from it aswell.. R!SC 27th August '99 tiberian sun c-dilla and cd check removal by r!sc used sicetool to bypass the anti softice code cause i'm a lamer entry point is 6854e3, but bpx anywhere in the .text section causes it to decrypt wrong and if its decrypted wrong, everything will go wrong.. and you have to reboot to make it run correctly again.. heh i traced dplayerx.dll, the c-dilla dll that decrypts the *.icd.. got a great breakpoint.. run the game, wait for the splash screen to die.. ctrl-d, if your in dplayerx.dll, bpx freelibrary, wait, on the break, hit F11 (p ret), should be back in dplayerx.dll, display the program entry point in the data window, d 6854e3, see if its decrypted correctly.. if so, clear the breakpoint on freelibrary, bpx entrypoint, F5.. code the import fixer, run it :d, dump the rdata section.. rebuild my exe, ts.header is the only part from game.icd i used, i know .rsrc wasnt encrypted, but, who cares :D copy /b ts.header + ts.text + ts.rdata.new + ts.data + ts.rsrc mygame.exe borrowed dumped fixed.dump dumped dumped my exe fixed it, nearly, it runs, but crashes, tiberian sun has encountered an internal error, pls contact westwood.. it made a text file for me.. except.txt Stack dump (* indicates possible code address) : 00A6EDD4: 00A6EDFC 00A6EDD8: 0044C23B <-- did a bpx here 00A6EDDC: FFFFFFFF 00A6EDE0: 004DC711 00A6EDE4: 004DC726 <-- and here 00A6EDE8: 00000100 00A6EDEC: 00000000 00A6EDF0: 00000001 00A6EDF4: 0069AC10 00A6EDF8: FFFFFFFF 00A6EDFC: 0069AC10 and ended up at a cd-check, with a dodgy api call in it.. on exit from this call, it rets to a silly address, so this dodgy api must be it.. just try bpx getdrivetypea on the original, and check what it should be :d then fix it by hand... hmm, fixed the cd check, by taking it out, mov al,1, ret .. :D games runs, but when i try to exit, it crashes, another damn api fux0red up nice game, without the cd, didnt run.. found some files i needed to add using filemon.. as i was patching the cd-check in memory, these patches got made to the file aswell :d hreh hreh.. runs ok , but still asks for cd 2 if i try to play nod *1* haha, it was a total fuckup, but, after 1 hr reversing, i figured it out, call cd check, test result, and/or compare it with edi.. if edi was 0, it wants cd 1, and wants eax to return 0, if edi was 1, it wants cd 2, and eax to return 1, if edi was -1, it just wants either cd, if edi is another number, like 682540, heh, fucked if i know, but my patch still works.. :D welp, just gotta beta test it know, and probably fix the imports that are still wrong, i think theirs three or four, i did a file compare on my .rdata to the one from the *.icd, and all the kernel and user rva's should be different, unless by chance they only messed with 99% of them. it still runs ok.. not a single crash yet since i killed the first cd check with the dodgy api call in it (; i feel like a god :d r!sc :'( this is getting annoying.. after first tests, whilst i was already in the game, i had patched it to copy edi into eax, and this worked.. cd1, cd2 worked.. upon reloading it.. 'error whilst initializing' and it would exit.. i fixed this, there was a call to the cd check with edi==100h.. i tracked this down, and did a xor edi,edi, after the exit from the call.. well, it loaded again, and gdi(cd1) works okay.. but for nod(cd2) i get another error, 'unable to read scenario' this happened with the warez version on dead-mikes computer, and my other computer.. ..hum.. bit more debugging needed.. bleh.. somewhere deep inside the cd-check :00471DC8 8D7301 lea esi, dword ptr [ebx+01] :00471DCB 8D9424B8000000 lea edx, dword ptr [esp+000000B8] :00471DD2 56 push esi * Possible StringData Ref from Data Obj ->"TS%d" <--ts1.dsk / ts2.dsk / ts3.dsk etc :d | :00471DD3 68F8536C00 push 006C53F8 :00471DD8 52 push edx :00471DD9 E8D00C2100 call 00682AAE :00471DDE 8D8424E4000000 lea eax, dword ptr [esp+000000E4] :00471DE5 8D8C24C4000000 lea ecx, dword ptr [esp+000000C4] <-- ptr to 'TSxxxxx',0 :00471DEC 50 push eax :00471DED 51 push ecx :00471DEE E8BD2B2100 call 006849B0 <-- string compare code ?? :00471DF3 83C414 add esp, 00000014 :00471DF6 85C0 test eax, eax :00471DF8 7417 je 00471E11 <-- je got the correct disk (either ts1.dsk or ts2.dsk) :00471DFA 83FE08 cmp esi, 00000008 <-- check esi, possible 8 disks max :D ARRGH! :00471DFD 89742410 mov dword ptr [esp+10], esi :00471E01 7CC1 jl 00471DC4 oh, dear, probably got to recode this bit, aswell, so if er, edi=0, i run this code, if edi==1, i run this code twice, cause i think this is what decides whether it loads xxx01.mix or xxx02.mix.. after testing, my theory is correct, well, seems to be anyway.. just gotta figure out how to rearrange my code :d darn, my previous theory was correct.. (*1*) but fuckit anyway, i recoded the call to getvolumeinformation to store 'TS1',0 in the memory where the name buffer was, and checks if edi was 1, jne continue, otherwise store 'TS2',0 in the name buffer.. now the name of the cd it wants is in memory, so the label check code works, and i patched the call to createfilea to fake it being able to open 'tsx.dsk' on the cd.. the cd check is patched 100%, but it still cant read the nod scenario.. also, it takes an age to load a level, but with a cd in, any cd, it loads quite rapid :d ahh, i also took out the call to lock the cd tray, as this was REALLY annoying.. god do i babble on lot. decided, it may take an age, because when it tries to access files off the cd rom, if theirs no disk in, the system may be using up the time.. so the first call to getrivetypea, where it finds the cd-rom letter, i patched to find hard disks instead, cmp eax,05 --> cmp eax,03 :d and it fucking works sweet ;) figured out how to fix the nod scenario :d the call to the cd check, where edi==100, where it started failing before, after i had patched the cd check.. :004DCBAE E83DF6F6FF call 0044C1F0 ; call cd check, should return 00 or 01 in eax :004DCBB3 8BF8 mov edi, eax :004DCBB5 8D442474 lea eax, dword ptr [esp+74] :004DCBB9 47 inc edi :004DCBBA 57 push edi * Possible StringData Ref from Data Obj ->"MAPS%02d.MIX" | :004DCBBB 68DC1E6C00 push 006C1EDC then it adds one to the number, so if it was cd1, the call returns 0 in eax, which gets 1 added to it, which then gets put into the maps%02d.mix string.. %02d is decimal number in wsprintf wayhey! just have to find the code which asks for cd1 or cd2, find the bit which modifies "MAPS%02d.MIX" after you have inserted the requested CD, and call that from the cd-check which i have been modifying :d yikes, tracked down the disk swap code, but it also calls the cd check, to find out what disk is in, so it knows to use '01' or '02' for loading the files.. thing is, it doesnt push the value of the disk it wants.. so, at the regular cd check, i compare the result with one i stored earlier, and if it wants a different disk, i jump to the code to call the disk swap, and, i patched the disk swap code, so it dont check what disk was in.. it just uses the other disk :d i *really* feel like a god ;) but, disk swap code crashes if edi==-1, i was only checking eax against my stored varible.. edi==-1, means it wants either disk, so, er, i added another check for this, and, er, skipped the swap cd code if edi==-1.. i give you Tiberian Sun, cracked, 100% 9.9.99 by r!sc (just gonna rip the movies now) Here's a code for Memory Patch in Delphi 4, coded by p0SEIDON ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ program MemPatch; uses Windows, ProcessAccess; CONST OrigBytes1 : ARRAY [1..2] OF Byte=($74, $09); // original bytes #1 OrigBytes2 : ARRAY [1..2] OF Byte=($46, $10); // original bytes #2 NewBytes1 : ARRAY [1..2] OF Byte=($EB, $00); // new bytes #1 NewBytes2 : ARRAY [1..2] OF Byte=($00, $00); // new bytes #2 Patch_Adress1 : Cardinal = $4ACEDC; // address where to patch #1 Patch_Adress2 : Cardinal = $4E15ED; // address where to patch #2 Program_Name : String = 'MOOKIE.EXE'; // program filename VAR Process : TProcess; BEGIN Process:=TProcess.Create; Process.IdleLaunch(program_name); IF Process.Verify(Patch_Adress1,OrigBytes1)=False THEN BEGIN APIMessageBox('MemPatch by p0SEIDON','Check Failed! Wrong Version?',MB_OK); Process.Terminate; Process.Free; Exit; END; Process.WriteMemory(Patch_Adress1,NewBytes1); Process.WriteMemory(Patch_Adress2,NewBytes2); Process.Free; END. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ With this code, it generates 20Kb .exe file, not real bad. Enjoy it, tKC.......... We really hope you've enjoyed this tutorial too much as we did! Don't miss Tutor #41 soon! ;) And as I said last time: Without knowledge, there's no power! ;) Credits go to: HexMaster for Splash Logo. FileCAT for providing a tut in this version. R!SC for providing 2 tuts in this version. DongJong for providing a tut in this version. p0SEIDON for coding a Memory Patch in Delphi. 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! And all the tutors can be found at www.msjessca.da.ru! Greetz goto all my friends! You can find me on IRC or email me at tkc@reaper.org Oh btw, please don't expect me to reply your mails, since I get 50 +/- mails everyday be sure that I really appreciate your mails! :) Coded by The Keyboard Caper - tKC The Founder of PhRoZeN CReW/Crackers in Action '99 Compiled on 11 September 1999 Cracking Tutorial #40 is dedicated to Ms_Jessca, my liefie only. Who else?