woah, tutorial time! but first, a little spam . http://csir.cjb.net . oki, on with the show Settlers 3 v1.54 . . VOB Protect CD . PeCrypt . IAT Rebuilding . & Stuff grr . Split into 'Chapters' . . . Chapter 01, "Getting s3.exe to run with softice" Chapter 02, "Unwrapping VOB" Chapter 03, "Rebuilding the IAT" Chapter 04, "Thank god its over!!" well, where do i start? hah . Start off by downloading one of the settlers3 update patches . . i know v1.52 & v1.54 & 1.56 use VOB .. which is what im going talk about now.. (v1.54 may be on my website somewhere . . maybe near the link to this tutorial) having the original CD's would probably be a good idea . im not too sure if they are needed, but im a lazy cracker, and enjoy a quick fix, not a long boring reversing session. being a cracker, i know u have the normal 'tools of the trade' . Softice for windoze, with IceDump5.x FrogsIce ProcDump A Hex Editor . . ==Chapter 01============================ =="Getting s3.exe to run with softice"== ======================================== Okay, insert CD#1, run s3.exe (updated to v1.54).. coo . 'Debugger Detected!' 'Unload Debugger and try again (#0001)' heheh, right, run frogsice, and then s3.exe again .. oh no! No nasty nags, but it just doesnt want to run does it? take a look at the nice log file frogsice created . . . it tries to load SICE / SIWVID / NTICE, and it also tries int68h .. hmm let me do the hard work for u, wait, i'll reboot & run without softice, see if s3.exe runs then. heh, okay, Frogsice works better without Softice in the background, like it says in the readme. s3.exe ran fine without softice :) . . but when i fired up Frogsice again, boom! 'S3' 'VIRUS detected! Aborting. (#5000)' oh dear, but its okay, so s3 detected frogsice, no matter, look at the log file again... => S3 ** SoftICE detection ** code 01, at 015F:0000015F Interrupt:03h >eax=00000004h ebx=FFFF86C2h ecx=00000004h edx=00000000h esi=BFF7771Ah edi=00000003h >ebp=4243484Bh yep! we got a new one, that couldnt be detected when softice was running . . int 03, eax==04, ebp=='BCHK' . . time to reboot again, and fire up Softice. god fucking damn it . erm, well, keeping things easy for you, lets just patch softice in memory to hide it from this nasty little program . we have to edit the text for 'SICE' and 'SIWVID' and patch the int68 and int3/BCHK.. run sice, and er, type in these search commands.. s 0 l ffffffff b8 86 f3 cf 2e (search for int68h . . when found, edit it to read b8 00 43 cf which will make it return 43 in ax, instead of f386..) s 0 l ffffffff 'SIWVID ' 00 00 (heh, just edit it so it doesnt read SIWVID no more.. ) s 0 l ffffffff 'SICE ' 00 00 (same thing here..) s 0 l ffffffff 'KHCB' 0f 84 33 (edit the KHCB to read something else.. like 0000?, this will stop softice handling it, and returning any revealing codes) okay, having done this, Settlers3 will run okay with SoftICE present, if it doesnt, u did something wrong . ==Chapter 02============================ =="Unwrapping VOB"====================== ======================================== Okay, now it runs, lets be destructive. We want VOB to unwrap the program for us, then get a break asap, and dump the process, then fix it.. we need all the information from the pe header so we know what & where & how much to dump, hi procdump :d . . their are 7 sections, all called '.vob.pcd' .. Name VSize VAddr Raw Size Offset .vob.pcd 0x276d52 0x1000 0xf2000 0x1000 .vob.pcd 0x3faa4 0x278000 0x14000 0xf3000 .vob.pcd 0x158c4c 0x2b8000 0x68000 0x107000 .vob.pcd 0x1840 0x411000 0x2000 0x16f000 .vob.pcd 0x8000 0x413000 0x8000 0x171000 .vob.pcd 0x7a000 0x41b000 0x7a000 0x179000 .vob.pcd 0x1000 0x495000 0x1000 0x1f3000 see what we have to do? We need each section's address, and its virtual size, so we can dump them using icedump . .. the RAW size is the size in the file, which is no good to us as the file is compressed and encrypted. the imagebase is 0x00400000 . . . so section 1 loads into 0x00401000, and the size of section 1 is 0x00277000, so we dump ?? section 2 loads into 0x00678000, and the size of section 2 is 0x00040000 . . . etc.. lets find a nice place to break . . in softice, bpint 03... run s3.exe , softice will catch the int3/BCHK, hit F5, ooh, it catches it again, hit F5 .. . . VOB checks the cd.. softice breaks again . .. this time, kill your breakpoint on int3, and set a nice one that will catch a program just starting up... most windows programs, in their first lines of code, call GetVersion, GetCommandLineA or GetModuleHandleA. This way is mega-lame, but , no-but.. hehe bpx GetVersion, hit F5... Sweet, when softice breaks, hit F11, see where u are.. still in s3.exe? see anything u like? take a look. Break due to BPX KERNEL32!GetVersion (ET=2.76 seconds) Break due to G (ET=172.47 microseconds) :u 641886 l 100 015F:00641886 55 PUSH EBP 015F:00641887 8BEC MOV EBP,ESP 015F:00641889 6AFF PUSH FF 015F:0064188B 6870106800 PUSH 00681070 015F:00641890 68201F6400 PUSH 00641F20 015F:00641895 64A100000000 MOV EAX,FS:[00000000] 015F:0064189B 50 PUSH EAX 015F:0064189C 64892500000000 MOV FS:[00000000],ESP 015F:006418A3 83EC58 SUB ESP,58 015F:006418A6 53 PUSH EBX 015F:006418A7 56 PUSH ESI 015F:006418A8 57 PUSH EDI 015F:006418A9 8965E8 MOV [EBP-18],ESP 015F:006418AC FF15AC826700 CALL [KERNEL32!GetVersion] 015F:006418B2 33D2 XOR EDX,EDX 015F:006418B4 8AD4 MOV DL,AH looks like a program entry point, doesnt it? doing that 'stuff' with FS:[00000000] ;) . . . i think we found a real place to break . no matter though, lets just dump . dump the whole bloody thing. all the sections are kinda like, stuck together, @ the end of section 1, section 2 begins, @ the end of section 2, section 3 begins, etc. so we can dump from 0x00400000 to 0x00896000 . . (do it, blow the fuses!) after the break for GetVersion, if your in s3.exe, dump away!! pagein d 400000 496000 d:\s3.novob.exe 'bc*' / F5 or 'exit' . . You should have a nice phat 4.59mb exe, with nothing encrypted in it, and a screwed up (already initialised) import address table . . . lets make this dump work (run? execute?) Load the dump into ProcDump's pe-editor, first thing we have to do is fix the Process size, and the EntryPoint . . . the Entry Point is 00641886 - ImageBase == 00241886 the 'Size of Image' or 'Process size', is what it was before, 00496000 . now we have to fix the section's Raw sizes, and File Offset's. This is simpler than it sounds :d just edit the Raw Size to the new RAW size's, and fix the offset's with the new offset's ;) Name VSize VAddr Raw Size Offset .vob.pcd 0x276d52 0x1000 0x277000 0x1000 .vob.pcd 0x3faa4 0x278000 0x40000 0x278000 .vob.pcd 0x158c4c 0x2b8000 0x159000 0x2b8000 .vob.pcd 0x1840 0x411000 0x2000 0x411000 .vob.pcd 0x8000 0x413000 0x8000 0x413000 .vob.pcd 0x7a000 0x41b000 0x7a000 0x41b000 .vob.pcd 0x1000 0x495000 0x1000 0x495000 okay, now to deal with our semi screwed iat, still with ProcDump's pe-editor, goto the 'Directory' section, and change the size of the Import Table to 00000000 . . this will stop any errors due to our 'semi screwed iat' .. run tha file :d . .. i kept getting this error, 'Windows error #8007007e (the specified module could not be found) occured at hKernel !=NULL, file E:\siedler3\DirectX\Dxbase.cpp, line 75.' woah! traced it to a failure to 005C6ACC 6878387C00 PUSH 007C3878 <--ptr to 'ole32',0 005C6AD1 FF15C0816700 CALL [KERNEL32!GetModuleHandleA] 005C6AD7 8BE8 MOV EBP,EAX bah, no import table, so it doesnt load that library, so it cant get the handle to it, so we obviously have to change it to LoadLibrary, instead of GetModuleHandleA. 005C6AD1 ff15b0816700 call [LoadLibraryA] got the rva of this import by running s3.novob.exe, and did 's 0 l ffffffff d4 76 f7 bf' in softice, it turned up @ address 006781b0 . .. d476f7bf reversed == bff776d4 == LoadLibraryA patch this, hex edit s3.novob.exe, goto offset 1c6ad3, change the C0 to a B0 . . hey, run tha file again :d . .. superb! it runs fine! We are getting somewhere now, erm, so my import table loads around 678000? need to rebuild it so the exe will run on other versions of windoze.... ==Chapter 03============================ =="Rebuilding the IAT"================== ======================================== Right then, the import address table is in section 2 of the file, loads into 678000, and its @ file offset 278000, in our dump.. Name VSize VAddr Raw Size Offset .vob.pcd 0x3faa4 0x278000 0x40000 0x278000 00278000 F2 1A EA BF 76 13 EA BF EA 15 EA BF 44 16 EA BF ....v.......D... 00278010 98 14 EA BF E2 1C EA BF 7D 16 EA BF 87 17 EA BF ........}....... 00278020 D1 14 EA BF 2B 18 EA BF B7 13 EA BF 34 15 EA BF ....+.......4... 00278030 00 00 00 00 1F 27 F2 BF 93 22 F2 BF 8D 14 F2 BF .....'..."...... well, thats a small dump of our import tables 'first thunk'. in this section, should be the untouched pointers for the 'original first thunk', the asciiz's for the imports, and hopefully, the image_import_descriptors as we can see from the little dump, 278000 is the beginning of one set of api addresses, 278034 is the beginning of another . . so, their must be pointers somewhere to these locations, ah haa, our image_import_descriptors, search for them, bwahahaha!! their nowhere to be seen, or at least not within 40000 bytes of this section like they should be :( please also note, no asciiz's in this section either, weird or what. hehe, dont phear . we need a virgin import table, one that hasnt been initialised, either by windows, or the file protectors used by s3. Since the import table is compressed / encrypted, the exe will have to initialise the import table itself, using LoadLibraryA and GetProcAddress. here we have two fine targets for breakpoints. but, but, pe-crypt is not cracker friendly, as you will soon see.. .. we have to run the protected exe again, best to 'bpint 3' to catch the sice check, like we did before.. .. did you note the sections RVA & RAW SIZE that we have to dump??? in softice, bpint 03... run s3.exe , softice will catch the int3/BCHK, hit F5, ooh, it catches it again, hit F5 .. . . VOB checks the cd.. softice breaks again . .. this time, kill your breakpoint on int3, and set a nice one that will catch the import table being initialised :D (bpm 678000, after the 3rd int 3 break.. LoadLibraryA is a good bpx, but not this time sir) yippee?? on viewing 678000 after each break, do you see a virgin import table ? (hint, if u break on a repz movsb, trace it with F10, and before u execute 'pagein', bd *) if yes, then dump with 'pagein d 678000 40000 c:\s3.154.rdata.bin' or whatever.. 00678000 38 7A 2B 00 92 7A 2B 00 80 7A 2B 00 1C 7A 2B 00 8z+..z+..z+..z+. 00678010 2A 7A 2B 00 9A 6E 2B 00 EA 79 2B 00 FC 79 2B 00 *z+..n+..y+..y+. 00678020 0C 7A 2B 00 4C 7A 2B 00 5C 7A 2B 00 6C 7A 2B 00 .z+.Lz+.\z+.lz+. 00678030 00 00 00 00 C6 6D 2B 00 AA 79 2B 00 9C 79 2B 00 .....m+..y+..y+. here we can see, that instead of pointers to actual api address's, we have pointers to the asciiz's just like it should be . . hex edit your dump, and check it out . . . yah, loads of weird numbers, and right near the end, we have the asciiz api names . . great, almost great anyway . notice something strange? hmm, no actual library names! wtf? anyway, we need to locate the image_import_descriptors before we worry about library names. . one set of api pointers started at 00278000, another one at 00278034, so, our image_import_descriptors will have these dword's in them. search for 00802700 (00278000 reversed) i found one occurance . @ file offset 3e56c . . the other one turns up @ file offset 3e544 . . what is the format of image_import_descriptor's ? well, they contain 5 dwords, and er, read on.. dd offset original_first_thunk dd timedatestamp dd forwardchain dd offset library name dd offset first_thunk timedatestamp and forwardchain are useually set to 00000000, original first thunk isnt needed, its just an exact copy of the first thunk . libraryname is a pointer to the libraryname :d and the first thunk is the array of pointers to the asciiz's. its the first thunk that gets overwritten with the api's address's . . . so knowing this, we know 278000 / 278034 are in our first thunk . thus, the dword right before '00802700' will point to the library name . . . ofthunk timedate fwdchain lib name 1stthunk AC652B00 00000000 00000000 AA6E2B00 00802700 002b65ac 00000000 00000000 002b6eaa 00278000 002b6eaa is the pointer to the libraryname for the first section of our import table . 002b6eaa-278000 == 3eeaa == file offset to the library name . . okay?? hmm, but at file offset 3eeaa we have '..(U..d.]...', nothing much at all, maybe an encrypted libraryname? bastard pecrypt! anyway, locate the first image_import_descriptor . . just study the hex, keep stepping backwards 14h bytes from the image_import_descriptor's terminator. (they are terminated with 5 NULL dwords) see where they start? see where they end?? 0003E4E0 60 29 6A 00 00 00 00 00 00 00 00 00 AE F2 63 00 `)j...........c. 0003E4F0 00 00 00 00 D8 64 6B 00 58 69 2B 00 00 00 00 00 .....dk.Xi+..... 0003E500 00 00 00 00 D4 69 2B 00 AC 83 27 00 48 66 2B 00 .....i+...'.Hf+. 0003E510 00 00 00 00 00 00 00 00 94 6B 2B 00 9C 80 27 00 .........k+...'. 0003E520 A4 68 2B 00 00 00 00 00 00 00 00 00 F4 6C 2B 00 .h+..........l+. 0003E530 F8 82 27 00 E0 65 2B 00 00 00 00 00 00 00 00 00 ..'..e+......... 0003E540 76 6E 2B 00 34 80 27 00 A0 69 2B 00 00 00 00 00 vn+.4.'..i+..... 0003E550 00 00 00 00 90 6E 2B 00 F4 83 27 00 AC 65 2B 00 .....n+...'..e+. 0003E560 00 00 00 00 00 00 00 00 AA 6E 2B 00 00 80 27 00 .........n+...'. 0003E570 9C 68 2B 00 00 00 00 00 00 00 00 00 CA 6E 2B 00 .h+..........n+. 0003E580 F0 82 27 00 90 68 2B 00 00 00 00 00 00 00 00 00 ..'..h+......... 0003E590 F8 6E 2B 00 E4 82 27 00 00 00 00 00 00 00 00 00 .n+...'......... 0003E5A0 00 00 00 00 00 00 00 00 00 00 00 00 7E A8 58 5C ............~.X\ okay! lets find the address's of our library names, and then find out which library's are actually used. think for a moment, we have a nice linear structure of image_import_descriptors, and, if i was a nice coder, i would load the library's one by one, in a kinda linear fashion, get pointer to lib#1, load it, get pointer to lib#2, load it, etc, etc.. well, first we need the pointers to the library names. so get the image_import_descriptors, and fish out the info. lib#1== 2b69d4 == 3e9d4 lib#2== 2b6b94 == 3eb94 lib#3== 2b6cf4 == 3ecf4 lib#4== 2b6e76 == 3ee76 lib#5== 2b6e90 == 3ee90 lib#6== 2b6eaa == 3eeaa lib#7== 2b6eca == 3eeca lib#8== 2b6ef8 == 3eef8 (boy oh boy, what fun that was :) bah, sux . after a bit of the good old zen cracking, we come up with this info .. .. lib#1== 2b69d4 == 3e9d4 == winmm.dll lib#2== 2b6b94 == 3eb94 == kernel32.dll lib#3== 2b6cf4 == 3ecf4 == user32.dll lib#4== 2b6e76 == 3ee76 == gdi32.dll lib#5== 2b6e90 == 3ee90 == ole32.dll lib#6== 2b6eaa == 3eeaa == advapi32.dll lib#7== 2b6eca == 3eeca == shell32.dll lib#8== 2b6ef8 == 3eef8 == rpcrt4.dll so, patch those names into the correct places in your dump . . . then, paste your nice virgin rdata section into the main exe . . (pasting it over the old rdata section, from file offset 278000 - 2b8000 . . .) remember where the first image_import_descriptor began? file offset 3e4f8 . . 3e4f8 + 278000 == 2b64f8 .. 2b64f8 == our new pointer to the import table, what we stamp into the pe-header.. size? a0h ? yah, so use procdump to do that . . run it! boom! blah blah linked to missing export blah blah . .. well, we have pointers to the original first thunk, but its missing / encrypted . theirs two ways to fix this problem, either copy and paste the first thunk over the top of the original first thunk, or kill the pointers to the original first thunk (overwrite them with NULL (00000000)) do dee doo . . .done? really? okay .. i belive you . ==Chapter 04============================ =="Thank god its over!!"================ ======================================== heh . now for that lame cd check . bpx getdrivetypea . . see where the drive letter is that it push's? and where it inc's the drive letter? well . just change that code to make the drive letter '.\',0 . . mov [edi], 00005c2e . . . or whatever register it used . . and it only checks for s3cd1.dat or s3cd2.dat in the root of whatever drive it was looking at . so, pointing it to .\ instead of e:\ or whatever, it checks the current dir . and it uses this drive letter for loading game files, thus, if u have all the game files on your hd, it will find them :) well, my final words ... . "Thank god its over!!" your very aggitated and incredibly tired krakwh0re, r!sc . . . p.s. all this bollocks of unpacking / dumping / rebuilding can be done quite fast . i cracked v1.56 in less than 90 minutes on christmas eve (whilst drunk) (and only had three complaints about it :)