Copylok by kilby

Published by +Tsehp feb 2001

 

Work on this protection system was slow, although the actual work on it only took about five evenings (and two early mornings).

 

My five evenings where spread out between mid December 2000 and mid Feb 2001, and required me to learn about Dumping, PE file formats and IAT rebuilding.

 

This research was the reason I victimised Crunch 2 by Bi Tarts .

 

There isn't much if any information regarding Copylok, in the scene so heres what I know.

 

This information is taken from the only example of copylok I have which is Sudden Strike (UK release)

 

 

 

Firstly how do I recognise Copylok

 

Well the CD has a visible ring on the data section, and the protected .exe file has .icd sections.

 

This accounts for why some 'crackers' claim that it is a version of Safedisc.

 

They claim to use 128 bit encryption keys, it has been mentioned that once again the TEA algorithm has been used (as in Safedisc.)

 

I only found the old CreateFileA anti-softice code, though Duke (Hi there), says that he has seen versions with better anti-softice code.)

 

The wrapper decrypts itself in phases, and each phase is made up of many small blocks (typically 0x64 to 0x72 bytes), and jumps all over memory like it has a dose of crabs.

 

The CD is easy to copy, despite what Panlok Ltd claim and I can't wait for them to start using their uncopyable CD-Roms as a replacement for smart cards :)

 

You can't run a straight dump the main .exe using pedump or icedump as the imports have been screwed with.

 

Copylok is becoming more common due to Take 2 Interactive using it, along with several other European publishers, so it's time for an essay.

 

The method I am going to use is a bit hack and slash, and requires an original (or working clone) CD.

 

 

 

 

However iNX offers the following information, for those without a suitable CD

 

--------------------

 

Anyway I can tell you that the cd checks seems not very efficient because there is an average of 10 sectors read and the bad one is always around the 7th or 8th read.

 

If you start sending back result error to aspi calls after the 7th, 6th read, the program starts...

 

I would guess they considered that a cd reader couldn't read some other sectors than the effective bad one (maybe because the cd has got many many bad sctors interleaved with good ones) and so they introduced some sort of tolerance.

 

--------------------

 

 

 

So as Frank would say "Let's hit the fuckin road"

 

 

Tools Used:

 

Softice           (Our old friend)

Icedump

Procdump

Revirgin      (Our new friend)

Hex Workshop

Sudden Strike+CD

Pen

Paper

Sony MZ-R55 playing Gomez.

 

 

 

Preparation:

 

In my case I have to stop DBServer from running, along with the creative launcher shit for my SB Live, so I don't get too many false breaks inder softice.

 

 

 

Method:

 

As I couldn't be arsed to trace the whole damn thing we will make use of a hole in Copyloks armour.

 

 

So what kind soul will let us gain entry to the unwrapped .exe

 

Well once again that kind individual is Microsoft, and in particular Visual C.

 

The inital setup code of the wrapped file is Visual C, so let us assume that the original file is also Visual C based.

 

Load Icedump, this will hide us from the debugger checks.

 

Place a breakpoint on GetVersion, then return to windoze.

 

Run SuddenStrike.exe

 

Immeditely sice breaks hit F11 and we see the following

 

:u 415d40 L 100

0167:00415D40  55                  PUSH      EBP

; Entry point of Executable

 

0167:00415D41  8BEC                MOV       EBP,ESP

0167:00415D43  6AFF                PUSH      FF

0167:00415D45  68B0E74600          PUSH      0046E7B0

0167:00415D4A  684CB14100          PUSH      0041B14C

0167:00415D4F  64A100000000        MOV       EAX,FS:[00000000]

0167:00415D55  50                  PUSH      EAX

0167:00415D56  64892500000000      MOV       FS:[00000000],ESP

0167:00415D5D  83C4A4              ADD       ESP,-5C

0167:00415D60  53                  PUSH      EBX

0167:00415D61  56                  PUSH      ESI

0167:00415D62  57                  PUSH      EDI

0167:00415D63  8965E8              MOV       [EBP-18],ESP

0167:00415D66  FF15F8624700        CALL      [KERNEL32!GetVersion]

; The call to GetVersion (Look at the address the call uses)

 

0167:00415D6C  A3B4484700          MOV       [004748B4],EAX

; Where we have ended up after F11

 

As we can see typical Visual C setup code

 

We are now in the .icd1 section of SuddenStrike

 

Hit F5 again to return to executing the code.

 

A splash screen appears, and there is a few seconds pause.

 

Sice breaks again, this time after hitting F11 we find that we are in WNASPI32, (this dosn't matter to us as we are being lazy) so hit F5 again.

 

Another pause and sice reappears hit F11 and we find the following;

 

0167:00402F8D  FF1570A04000        CALL      [KERNEL32!GetVersion]

 

; Where Get version was called from (Look at the address the call uses now)

 

0167:00402F93  33D2                XOR       EDX,EDX

 

If we look back through this section of code we will see this;

 

:u 402f67 L 100

0167:00402F67  55                  PUSH      EBP

0167:00402F68  8BEC                MOV       EBP,ESP

0167:00402F6A  6AFF                PUSH      FF

0167:00402F6C  6880A14000          PUSH      0040A180

0167:00402F71  68905B4000          PUSH      00405B90

0167:00402F76  64A100000000        MOV       EAX,FS:[00000000]

0167:00402F7C  50                  PUSH      EAX

0167:00402F7D  64892500000000      MOV       FS:[00000000],ESP

0167:00402F84  83EC58              SUB       ESP,58

0167:00402F87  53                  PUSH      EBX

0167:00402F88  56                  PUSH      ESI

0167:00402F89  57                  PUSH      EDI

0167:00402F8A  8965E8              MOV       [EBP-18],ESP

0167:00402F8D  FF1570A04000        CALL      [KERNEL32!GetVersion]

 

; Where F11 placed us

 

0167:00402F93  33D2                XOR       EDX,EDX

 

More Visual C setup code.

 

In addition we are also in SuddenStrike.Text, this means that we are at the start of the unwrapped file and we have found the OEP (Original Entry Point)

 

So we dump the file, I prefer using icedump for this as we don't have to halt the exe to dump it so;

 

/pedump 400000 2f67 f:\ssdumped.exe

 

The 2f67 is the RVA (Relative Virtual Address) of the programs entry point.

 

As we can see the pointer to the import of GetVersion has moved from 004762F8 to 0004a070, this means that we are working with a new IAT

 

 

So lets look at the IAT we know it lives around 0040A070

 

:d 40a070 l 20

0030:0040A070 1B 2F F9 BF E8 FF 42 00-4C 10 43 00 31 0E 43 00  ./....B.L.C.1.C.

0030:0040A080 CF 05 43 00 B3 02 43 00-83 F8 42 00 5C 1D 43 00  ..C...C...B.\.C.

 

Well the address for GetVersion looks pretty normal BFF92F1B.

 

However look at the following address at 40a074 it's pointing to 0042FFE8 which is a strange address for a KERNEL32 call.

 

So lets look at 0042FFE8

 

:u 42ffe8 l 10

0167:0042FFE8  A1E49CFCBF          MOV       EAX,[BFFC9CE4]

0167:0042FFED  FF742404            PUSH      DWORD PTR [ESP+04]

0167:0042FFF1  8B08                MOV       ECX,[EAX]

0167:0042FFF3  E90BD5B5BF          JMP       BFF8D503

 

So the jmp at 0042FFF3 looks like it's jumping into the right area for a KERNEL32 import, so let's look at the code we are jumping to;

 

:u bff8d4f8 l 20

KERNEL32!ExitProcess

0167:BFF8D4F8  A1E49CFCBF          MOV       EAX,[BFFC9CE4]

0167:BFF8D4FD  FF742404            PUSH      DWORD PTR [ESP+04]

0167:BFF8D501  8B08                MOV       ECX,[EAX]

 

0167:BFF8D503  80492220            OR        BYTE PTR [ECX+22],20

 

; Address jumped to !

 

0167:BFF8D507  E8C3FCFFFF          CALL      BFF8D1CF

0167:BFF8D50C  C20400              RET       0004

0167:BFF8D50F  8B442404            MOV       EAX,[ESP+04]

0167:BFF8D513  33D2                XOR       EDX,EDX

0167:BFF8D515  8B4854              MOV       ECX,[EAX+54]

 

As we can see Copylok has;

 

1:      Borrowed the first three instructions of ExitProcess

 

2:      Executed them locally

 

3:    Jumped directly to the fourth instruction in the 'REAL' routine

 

This is known as redirection, and is used to make the reconstruction of the IAT more difficult.

 

So what can we do about this, well in times past it would have involved rebuilding the real calls by hand, or writing a routine to do the job for us.

 

However thanks to +Tshep we have a new friend which can do this for us, and that friend is called ReVirgin.

 

For using ReVirgin we need the start address and length of the IAT, although revirgin can find this on normal programs and some protected apps (ASProtect for example), we will hunt down the table just incase.

 

We know that GetVersion sits around 40a070, so lets start hunting;

 

:d 40a000 l 170

0030:0040A000 E8 19 43 00 3C 13 43 00-E4 F2 42 00 00 00 00 00  ..C.<.C...B.....

0030:0040A010 4B E3 42 00 00 00 00 00-B0 01 42 00 00 00 00 00  K.B.......B.....

0030:0040A020 47 F8 42 00 91 00 42 00-20 1D 43 00 39 1B 43 00  G.B...B. .C.9.C.

0030:0040A030 34 19 43 00 88 12 43 00-A6 F7 42 00 30 F2 42 00  4.C...C...B.0.B.

0030:0040A040 3A E8 42 00 C8 E4 42 00-E3 E3 42 00 97 E2 42 00  :.B...B...B...B.

0030:0040A050 0C 00 42 00 FC 00 42 00-64 B0 46 00 BB 92 43 00  ..B...B.d.F...C.

0030:0040A060 C0 BC 46 00 E8 CD 42 00-18 2D 42 00 9F 00 43 00  ..F...B..-B...C.

0030:0040A070 1B 2F F9 BF E8 FF 42 00-4C 10 43 00 31 0E 43 00  ./....B.L.C.1.C.

0030:0040A080 CF 05 43 00 B3 02 43 00-83 F8 42 00 5C 1D 43 00  ..C...C...B.\.C.

0030:0040A090 75 1B 43 00 70 19 43 00-C4 12 43 00 6C F2 42 00  u.C.p.C...C.l.B.

0030:0040A0A0 76 E8 42 00 04 E5 42 00-D3 E2 42 00 38 01 42 00  v.B...B...B.8.B.

0030:0040A0B0 A0 B0 46 00 F7 92 43 00-FC BC 46 00 24 CE 42 00  ..F...C...F.$.B.

0030:0040A0C0 D8 BF FC BF 54 2D 42 00-DB 00 43 00 BF BF FC BF  ....T-B...C.....

0030:0040A0D0 88 10 43 00 6D 0E 43 00-0B 06 43 00 EF 02 43 00  ..C.m.C...C...C.

0030:0040A0E0 BF F8 42 00 98 1D 43 00-17 C2 FC BF B1 1B 43 00  ..B...C.......C.

0030:0040A0F0 AC 19 43 00 00 13 43 00-A8 F2 42 00 B2 E8 42 00  ..C...C...B...B.

0030:0040A100 40 E5 42 00 0F E3 42 00-DF C2 FC BF 74 01 42 00  @.B...B.....t.B.

0030:0040A110 00 00 00 00 DC B0 46 00-91 55 F5 BF 33 93 43 00  ......F..U..3.C.

0030:0040A120 38 BD 46 00 60 CE 42 00-3D 57 F5 BF 90 2D 42 00  8.F.`.B.=W...-B.

0030:0040A130 17 01 43 00 C4 10 43 00-A9 0E 43 00 47 06 43 00  ..C...C...C.G.C.

0030:0040A140 2B 03 43 00 FB F8 42 00-8C 55 F5 BF 0D 58 F5 BF  +.C...B..U...X..

0030:0040A150 D4 1D 43 00 ED 1B 43 00-00 00 00 00 EE E8 42 00  ..C...C.......B.

0030:0040A160 7C E5 42 00 00 00 00 00-00 00 00 00 00 00 00 40  |.B............@

 

 

If we work backwards from 40a070 the data is consistant with an IAT down to 0040a000

 

The data is also consistant up to 40a164, where we find the data terminated by ten 00 bytes

 

--------------------

 

This isn't a lecture on IAT but here is some helpful information;

 

The IAT data is in sections, each separated by 00 00 00 00

 

Each section represents a set of imports from a .DLL

 

Therefore if routines are being imported from KERNEL32, GDI32 and SHELL32

 

This would result in an IAT with 3 sections each with 00 00 00 00 separating them, the final import would be terminated with ten 00 bytes

 

--------------------

 

The IAT base is 40a000 with a length of 164 bytes

 

The RVA (Relative Virtual Address) is 40a000 - 400000 (the Image Base)

 

Lets place SuddenStrike in a holding Pattern,

 

r eip=402F67

A eip

jmp eip

 

Hit Esc

Hit F5

 

We are now back in windoze, so start revirgin running;

 

Select the task SuddenStrike, and look at the imports listed in the window on the right hand side.

 

Hmmm no redirections listed, so somebody is lying and it's not revirgin or me !

 

If you look at the IAT Start RVA revirgin is showing us we can see that it's pointing to the IAT used BEFORE the unwrapping took place.

 

Let us enter the correct value into the fields;

 

IAT Start RVA   A000 (Address - Base Address)

IAT Length      164

 

Hit the IAT resolver button, and we see a lot more imports, most of which are marked as redirected.

 

Now hit the Resolve Again button, after a few seconds, you now get all the normal addresses listed.

 

Hit Save resolved, incase of crashes etc.

 

Now we need to create the import table.

 

We need to place this somewhere, looking at the original executable with procdump, the original and now unused IAT looks fine so 761f8 was chosen.

 

I know I should at this point kill the unused .sections and create a nice shiney new one for the IT but it was 03:00 on Sunday morning and there was two beers still left in the fridge.

 

So we place 761F8 into the IT RVA field.

 

Remember to write down the IT length (it was CC for me)

 

Hit IAT Generator button.

 

You will be prompted for filenames, give them sensible filenames, so you don't get them mixed up, I used SSIAT and SSIT (not exactly easy to tell apart)

 

When you have done this You may enter procdump (again), firstly kill the task SuddenStrike.

Then you choose Rebuild PE, on the file f:\ssdumped.exe.

 

Now enter hex workshop (or your preferred hex editor), and paste the newly created .bin files into the appropiate locations of ssdumped.exe

 

In the case of SSIAT.BIN go to file offset a000 (remember 40A00 - 40000), highlight 164 bytes and choose Replace with file.

 

 

Starting at 741F8 highlight1964 bytes (for that is the length of SSIT), and chose Replace with file, and choose SSIT.BIN

 

Why not 761f8, well look at the section information, particularly at the Virtual & Raw Offset fields, on the .data and .rsrc sections.

 

 

After saving this change, choose PE Editor in procdump and open ssdumped.exe and go into Directory and change the following fields:

 

Import Table            Length

 

000761F8          000000CC

 

Close Procdump.

 

Double click ssdumped.exe.

 

We should now see a messagebox appearing stating

 

VStart Error

 

Can't load profile .\SudTest.ini

 

This means that the file is working, simply copy ssdumped.exe into the suddenstrike home directory.

 

I have tested the file on 98 & 2K professional without any problems.

 

An added advantage, is that if a full install was chosen, no CD is required in the drive.

 

As I mentioned earlier I should clean up the file so as the .icd1 & .icd2 sections are removed, and that the IT is in a tidy place (like a section of it's own.)

 

With the aid of revirgin the whole process is pretty smooth.

 

Thanks to;

 

+Tsehp, for revirgin and answering a couple of dumb questions

 

ArthaXerXes, for the message board

 

R!sc, for the essay on Settlers 3, supplied me with more IAT info than any other source

 

Duke, early copylok info

 

Hi to;

 

webmasta of pGC

iNX

 

 

Regards,

 

Kilby...