              ********************************************
              *\    \ \  \ \   \\   \ \  \ \ \\    \\   \*
              * \      \   *
              *    \      \  \     \           *
              *\         \ __ *
              *              \     \       \*
              *\\   \   \ \/\\\*
              ********************************************
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_
SAFE_DiSC / [yAtEs] / Best viewed with Edit.com / 21-Jan-00
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_


w00p, time for safedisc tutorial 2, you should of read my first
tutorial from cdchecks.cjb.net or this will make less sense :),

ok in the last tutorial we covered the old jump table protection,
well its not that old, you'll still find that its used in new games like
Warzone 2100, hmm is that a new game? maybe i'm just out of date, anyway
this tutorial will look at another variant of safedisc, today we'll
reverse The F.A Premier League Stars.

ok first thing we should do is install the game i guess, so, install,
make sure you select Custom and select everything for a full HD eating
version.

2 seconds later with my new 48x drive ;D


ok loadup Frogice and turn off BlueScreenOfDeath, run the game so we
can get the feel of it, you've probably played it 148hrs non
stop by now thou. Ok theres no splash screen on mine, just waits
then a dos box called Gameboy pops up and minimizes then the game
runs.

we need to get our dumps now, so lets gather some information from our
.ICD using procdump

Entry:545F44

-----.text 401000 152000
----.rdata 553000 4000
-----.data 557000 3F000
-----_text 675000 1000
idct_datL  676000 1000

now we're gonna dump these sections using icedump, run the game the cursor
will go to the loading cursor, then it will change back and the cdrom
will initialise, sometime around here press Ctrl+d to init SoftIce,
keep going into softice until your in the DXPLAYER, code,

set the following bpx, BPX FreeLibrary DO "D 545F44" now exit and when
softice pops back up, is the code decrypted?, e.g. has the ?? ?? ?? turned
into code? if so BC* and set BPX 545F44, if not press F5 and w8 for the
next break on freelibrary. Once you've set your bpx on the entry point, press
F5 to exit and wait for the entry point to popup, you should have a dos
box in the background, type BC*, now your at the entry of the ICD, lets
dump the sections like so :-

Pagein D 401000 152000 c:\1
Pagein D 553000 4000 c:\2
Pagein D 557000 3F000 c:\3
Pagein D 675000 1000 c:\4
Pagein D 676000 1000 c:\5

Ok now we have our dumps we need to find where the first API is called
and evaluate its system, heres what we see at the moment

0167:00545F44  PUSH      EBP                                                   ^ 0167:00545F45  MOV       EBP,ESP
0167:00545F47  PUSH      FF
0167:00545F49  PUSH      00554608
0167:00545F4E  PUSH      0054AA4C
0167:00545F53  MOV       EAX,FS:[00000000]
0167:00545F59  PUSH      EAX
0167:00545F5A  MOV       FS:[00000000],ESP
0167:00545F61  SUB       ESP,10
0167:00545F64  PUSH      EBX
0167:00545F65  PUSH      ESI
0167:00545F66  PUSH      EDI
0167:00545F67  MOV       [EBP-18],ESP
0167:00545F6A  CALL      [005531A4]
0167:00545F70  XOR       EDX,EDX
0167:00545F72  MOV       DL,AH

If we're lucky the first API is called from the first Call, but we are
always gonna be lucky, because i ain't gonna be writting the harder stuff
till later :P, so F10 upto the call and press F8, heres what we see

0167:00915837  PUSHAD                                                          ^
0167:00915838  PUSH      0000005B
0167:0091583D  PUSH      00000000
0167:00915842  CALL      [00915858]
0167:00915848  ADD       ESP,08
0167:0091584B  POPAD
0167:0091584C  JMP       [00915852]
0167:00915852  ADD       [EAX],AL

There, seen that before?, if your answer is no, Gah! :d go read blackchecks
tut :P, ok so what we have here is a nice little system to retrieve API's
, we push the API number, and the DLL number then go over the call
and the call returns the correct API in ECX and the wrong reference from
the rdata in EAX.


0167:00915837  PUSHAD  <-Push all regs to stack
0167:00915838  PUSH      0000005B  <- Push API
0167:0091583D  PUSH      00000000  <- Push DLL
0167:00915842  CALL      [00915858] <- Cdilla Call
0167:00915848  ADD       ESP,08
0167:0091584B  POPAD
0167:0091584C  JMP       [00915852]
0167:00915852  ADD       [EAX],AL

you see?, ok keep F10ing until we get to 915848, thats just after
the cdilla call, now look what we have :-

0167:00915837  PUSHAD                                                          ^
0167:00915838  PUSH      0000005B
0167:0091583D  PUSH      00000000
0167:00915842  CALL      [00915858] <- note down 915858
0167:00915848  ADD       ESP,08
0167:0091584B  POPAD
0167:0091584C  JMP       [KERNEL32!GetVersion] <- returned API
0167:00915852  SBB       EBP,[EDI]

EAX=00915837  ECX=BFF92F1B


This returns a Kernel32 api, so cos we pushed 0 as the DLL number
0 must be Kernel and 1 will be User.

So now we have got the correct api for api 5B, so what can we do
to repair our rdata? hmmmmmmm,

if you were to look in the rdata you would find, 37589100 this needs
to be replaced with 1B2FF9BF.

Ok so heres what we have to do, we must code something in memory that
will push every API number into the call, then search the memory
for the bad reference, (which it will find in the rdata) then write
the correct API over it, gawd... i'm not sure which is worse, doing it
or explaining it.

ok exit from softice and the game should continue to run.

before we code this amazing fixer we need some info, we need to know
how many Kernel APIs there are, and how many User ones.

Hex ed your Rdata section we dumped, its called "2" , now can you see all
the bad Kernel refs? they start at 0x38, select them all, there are
0x1F0 bytes selected, each api is 4 bytes, so 1F0 / 4 = 7C, so there
is 7C kernel apis, now select the user ones, which begin shortly after
theres now 0xC0 selected, C0/4 = 30 , so theres 30h user api's



-----.text 401000 152000
----.rdata 553000 4000
-----.data 557000 3F000
-----_text 675000 1000
idct_datL676000 1000

--User Imports: 048 0x30
Kernel Imports: 124 0x7C
---Cdilla Call: [00915858]


Ok because the rdata memory isn't writtable we have to shift this into
a different part, so we will copy the rdata into the data section,

M <SRC> L <LENGTH> <DEST>

so we would do, M 553000 L 4000 55A000
i moved it to 55A000 instead of 557000 because i like 55A000 better :)
, ok we don't need to that yet, lets look at what we will code


01 PUSHAD
02 PUSH EBX             <- we push the api number, =0 @ start
03 PUSH 0               <- Push Dll number, 0=kernel
04 CALL [00915858]      <- Obtain values in EAX/ECX
05 ADD ESP,8            <- blah, nothing..
06 MOV EDX, 55A000      <- mov our start of rdata to EDX
07 CMP EAX,[EDX]        <- is the first value in our rdata the same
                               as the wrong ref?
08 JE 13                <- yes/no
09 INC EDX              <- no its not inc to the next point in rdata
10 CMP EDX,55A000+4000  <- are we at the end of the rdata?
11 JNE 07               <- No go back and check for wrong ref
12 INT 03               <- yes we are found no match, we are fux0r3d

13 MOV DWORD PTR [EDX],ECX <- called from 8, ok we found the wrong ref,
                                write the correct ref
14 POPAD                <- Restore Registers
15 INC EBX              <- Increase EBX, the api number , 
16 CMP EBX,7C           <- Have we done all apis?
17 JNE 01               <- yes/no, no goto start at push next api
18 INT 03               <- yes ok break here, w00p!

BLEH! hehe try and figure out how that works :P, lemme just add
some comments, hmm thats not too bad, you see how that works?

ok we're ready to put this beast into action :), its really best now
if you reboot your computer to make sure that the game has detected you
and won't hurt you during our operation.


Ok run the game and get to the entry point again, make sure all breakpoints
are cleared, BC*. now we shall code this thing here, first move the rdata
into the data section like so..

M 553000 L 4000 55A000


if you get a 'Page not present' error then you've probably tried to
move the rdata into a space which isn't big enough, we are moving

rdata 4000 bytes into data 3F000 bytes, just thought i would mention
that incase your using a different game, blah blah.

ok now code the thing type A then press enter and code the following
be real carefull!

0167:00545F44  PUSHAD                                                          ^
0167:00545F45  PUSH      EBX                                                   ^
0167:00545F46  PUSH      01
0167:00545F48  CALL      [00915858]
0167:00545F4E  ADD       ESP,08
0167:00545F51  MOV       EDX,ADVAPI32!RegCloseKey
0167:00545F56  CMP       EAX,[EDX]
0167:00545F58  JZ        00545F64
0167:00545F5A  INC       EDX
0167:00545F5B  CMP       EDX,0055E000
0167:00545F61  JNZ       00545F56
0167:00545F63  INT       3
0167:00545F64  MOV       [EDX],ECX
0167:00545F66  POPAD
0167:00545F67  INC       EBX
0167:00545F68  CMP       EBX,30
0167:00545F6B  JNZ       00545F44
0167:00545F6D  INT       3

After coding it should look like this, notice @ 545F51 the 55A000
changes to RegCloseKey if you have Moved the memory correctly, and
@ 545F64 the Dword Ptr doesn't show, @ 545F5B it has added to 4000
to our offset aswell.

okey dokey we're nearly ready, first we must set EBX to 0 , type
R EBX 0   now ebx is 0, and type  i3here on   now we will break
on the int 03's, hmmm ok ready, press F5 you will be returned to
softice

Break due to Embedded INT 3 (ET=19.31 milliseconds)

If everything went good, you should be @ 545F6D, ok thats the kernels
fixed, now we must change the above code to fix Users, we need to :-

1) change push 0 to push 1
2) change cmp ebx,7c to cmp ebx,30

k lets change the push 0,

type A 545F68 then change to Push 1

:a 545f46
0167:00545F46 push 1
0167:00545F48

now change the cmp, type A 545F68 then change to cmp ebx,30

:a 545f68

0167:00545F68 cmp ebx,30
0167:00545F6B

ok now set ebx to 0, by , R EBX 0, now reset the EIP to 545F44
R EIP 00545F44

once again press F5, it will break on the same int 03, now we have
a total repaired Rdata section in memory all we have to do is dump it,

Pagein D 55A000 4000 c:\2.fix

Now if your program broke on 545F63, this means that it didn't find the
wrong ref from EAX in the rdata, this means you probably didn't move
the memory correctly or have the values wrong, the memory has been moved
correcty if you get that value from before changing into RegCloseKey,
but this is not always for all progs.

If you hex ed our new rdata section, you'll see all the API's.

w00p!, now exit softice, we need to grab the header from the ICD to
rebuild our exe, so use procdump and pe edit stars.ICD and choose
sections, noe you can see that .text starts at 0x1000, so our header
must be 1000bytes long, close all procdump down making sure that you
are clicking cancel etc,. now hex edit Stars.icd and copy the first
1000 bytes into a new file called header.

Now lets stick our bits together like so :-

copy /b header + 1 + 2.fix + 3 + 4 + 5 Rebuild.exe

Once our new exe is compiled, goto procdump and Rebuild PE, now
copy the EXE to the F.A.P.L.S directory and run,,,,,,!? yup
it runs :D, lalalalalalalal we've done it.

Now remove your CD and try running it and you'll get a Msg box saying
insert the CD, bleh simple pimple eh? i'll leave you to remove this
simple check, after all,.. your a leetoe now ;)

***************************************
*Questions to,..JamesLuton@hotmail.com*
*[yAtEs]                              *
*CDCHECKS.CJB.NET                     *
***************************************


























