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 :)