Introduction

Because it is simply obvious that I have not been posting on this blog for a while, here is a post about Safedisc v3.
Last week I was studying this protection in deep, each component under IDA, but I accidentally broke my external hard drive by giving a shot in. I lost a lot of .idb from different games, softwares or malware, my personal toolz, unpackers, ...
So to smile again I decided to write about how to unpack this protection.
For those familiar with safedisc, the only interesting part will be Nanomites, restoring Imports or emulated opcodes is a joke when you know how older versions work.

Extra data

During introduction I talked about different components, they are placed at the end of the file.
The size of the target game is 1 830 912 bytes, but if we look IMAGE_SECTION_HEADER closely :

1 748 992 bytes != 1 830 912 bytes.
Clearly there is some extra data at the end of the file.
By looking the main executable under IDA, I was able to find an interesting sub that retrieves and extracts those datas.
First, here is the structure used for extra data :

~e5.0001, an executable, this process will debug the main executable, for managing Nanomites.

PfdRun.pfd, No type, This file will de decyphered for computing instruction table used for emulated opcodes.

~df394b.tmp, another DLL, Load and decyph section from other DLL, and manage debug event for ~e5.0001 process.

I will not discuss more about all this stuff, by loosing all my idb I am bored to reverse (rename sub) again and again with all this shitty C++ stuff, you can find some fun crypto when they decypher pfd file or code section, rijndael modified, different xor operation, anyway let's continue !

This code will replace Module Entrypoint by a jump to Real OEP, so if you like using OllyDbg execute first instructions and put a breakpoint on that jump.
But you will encounter a "dead lock" problem, before jumping to real OEP, it decyphers sections, loads dll AND CreateProcess "~e5.0001" giving the pid of the game process as argument.
This process will load ~df394b.tmp aka SecServ.dll, all strings inside this dll are encrypted, we can decrypt all of them :

The most interesting things are DebugActiveProcess, ContinueDebugEvent, WriteProcessMemory, FlushInstructionCache, SetThreadContext.
As I said earlier this dll will be in charge of debugging the game process, it prevents debugging it with Olly or any Ring3 debugger.
The game process after calling CreateProcess will wait (WaitForSingleObject) signal that temp executable will attach to it and give it signal and continue to debug it, but if you are already debugging game process, WaitForSingleObject will never catch this signal.
All the code below can be found inside ~df394.tmp aka SecServ.dll :

What are doing these 0xCC (int 3) aka Trap to Debugger or software breakpoint after a call to a kernel32 API ?
It's a well known technique, instructions are replaced by this opcode and informations about the removed opcode is stored in a table. (Remember pfd file ?)
Then, by using self-debugging, when one of these breakpoints is hit, the debugging process will handle the debug exception, and will look up certain information about the debugging break.

Is it a Nanomite ?

Yes ! So I have to emulate the removed opcode

And restore the context of the thread correctly

But the problem is, if Nanomites are called several times, it can impact a little the performance, right ? (Not anymore today), but Safedisc decided to count how much time a Nanomite is executed, and if this Nanomite is executed too much time, it will restore the replaced opcodes by writting it inside the debugged process.
So if we want to fix theses Nanomites, we just have to patch a branch instruction that say : "This nanomites has been executed too much time, restore opcode !", and scan txt section of game process to find all the nanomites, call them, and the debugger process will restore all the removed opcode :).

How To

When unpacking (real?) protection you need to write cool toolz, here are all the steps that I did :

Create Game process in suspended state

Inject a first (malicious?) dll into it and continue execution

This first dll will setup an Hook on CreateProcessA, the goal of this task is when the debugger process ( ~e5.0001 ) will be created, it will change the dwCreationFlags to CREATE_SUSPENDED and inject a second dll in it.

A second hook from the first dll will be setup on GetVersionExA to gain execution just after the jump to Real OEP.

Once GetVersionExA is called, we scan txt section and look for 0xCC and for each one it create a thread at the address of the nanomites.

The second dll will patch the branch condition for WriteProcessMemory the emulated opcode and hook SetThreadContext for terminating the thread in question and not continue his execution.

Need a diagram ?

I encountered a little problem during those operation, if we create a thread at an addr containing 0xCC followed by nop operation (0x90), Safedisc debugger crashes or emulates shit...
Visual Studio uses 0xCC, 0x90 and 0x00 opcode for padding, don't ask me why they don't just use only 0x00, I don't know.
Just so you know, if you don't provide the full path of these dll while you are injecting it, the first dll must be placed in the folder of the game process, and the second one in %temp% path, because debugger process is extracted and executed here.

You can find the branch instruction inside ~def394.tmp (SecServ.dll) at addr 0x6678F562 :

As you can see at address 0x40170F, an event occured 0x1 -> EXCEPTION_DEBUG_EVENT and his code 0x80000003 (EXCEPTION_BREAKPOINT), so the debugger process replaces the 0xCC 0xCC by 0x85 0xC0 -> "test eax, eax", and try to SetThreadContext but we hooked it to terminate the thread.

Restoring Imports

Like the previous version import points to some virtual address where the code calls routine to find the correct import.
By using algo against itself we can resolve all correct address of imports.
Inside txt section we can find different type of call to imports :

call dword ptr[virtual_addr]

jmp dword ptr[virtual_addr]

jmp section Stxt774

The idea is simple, scan .txt section look for call dword ptr or jmp dword ptr or jmp section Stxt774, hook the function that resolve the api and get the result and save into into a linked list.
This function in question is in ~df394b.tmp :

As you can see the address in rdata 0x53327C, can resolve different API when it is called from different locations (txt address).
To fix it, it's very simple we reorder the linked list according to the api address, and choose one rdata for each call, and we will change value of the call or jmp dword ptr at txt address for each entry of an api.

We can now write back into rdata addr the real adress of the api and fix the call or jmp at adress in txt section, to point to the good rdata address.
Now you can look with ImportRec and see that all imports are restored correctly :)

To fix jmp section Stxt774, we just have to replace the jmp by a call dword ptr[rdata], but wait jmp stxt774 is 5 bytes and we need 6 bytes to change it to call dword ptr, don't worry, after resolving the api and ret to it, the api will return at jmp stxt774 + 6, so there is enough place.

And Import Reconstructor is happy (Invalid imports 0) :

Emulated opcodes

After fixing Nanomites and restoring imports, I encounter a last problem.

This code will just compute an address in txt section, get the value pointed by this address and jump to it. The jump destination is an address from ~df394b.tmp.

The goal of sub 0x6673E090 is simply to check from where it has been called, lookup in a table of emulated opcodes and restore it.
Here only one emulation is performed then it will write original opcode back.
Like for restoring imports, we find each reference to the sub 0x00404909, setup an hook at the end of the sub 0x6673E09, call each reference, and emulated opcodes will be restored automatically :)

Conclusion

Safedisc v3 is really not difficult, you can find the source of all my codes at the end of this post.
I will go back to school project, hopefully graduating this year :)

The first loop is for computing key for XOR operation. ebx will be equal to 0x77.
The second loop will decrypt first stage of the packer with the key stored into ebx.
Next the packer will resolve base address of kernel32.dll by getting the current structured exception handling (SEH) frame into fs:[0] and get an address inside kernel32 after the seh handler, and back
from this address into memory for finding 'PE' and 'MZ' signature.

At this point it will have the base address of kernel32.dll
Then it will parse PE header of this dll, get export function name table and search for GlobalAlloc().
It will Alloc some space, and copy different portion of code into it. We will return to the analysis of this code later (some stuff are here for api resolution during main execution).
For not loosing time by analysing all the copy of portion of code, we will setup memory breakpoint on acces on code section and run our debugger.

At this point ecx equal to 0x1E00, and raw size of code section equal to 0x7800, so it's actually deciphering all code section with 0xDEADCODE as XOR key.
Disable the memory breakpoint on access, and go to ret, then do the operation again (setup memory breakpoint acces), and we land here :

Do you recognize this operation ?
Opcode 0xE8, add 5 ?, it is making a call.
The destination of the call (eax) go to the first virtual part I talked, we will call this "api address solving".
The packer is making call redirection for each API.
The next memory breakpoint on access will land us here :

This entry in the table was for solving call to GetModuleHandleA() from kernel32.dll
So for dumping our program, we will have to reconstruct all those redirections, we will write a dll and inject it into the process.
What the injected code will do ?

Search call addr into code section, where the content of addr equal to a call to virtual memory (GlobalAlloc()) "api address solving".

Hook the jmp eax, for gaining control, we will replace it by a jmp ebx.

Store result (api address) into idata section.

Replace each call virtual memory by jmp dword ptr[idata_section].

But have we got enough for replacing call by jmp dword ptr [idata_section], the answer is yes !, the packer have replace them and left 1 byte between each call.

So as you can see, I used a little trick for waiting unpacking of all executables :
I setup an hook on GetVersionExA() and if the call occurs from one interesting address (near OEP), I call fix "fix_call" function and enter in infinite loop.
With this infinite loop we can attach Olly to our process and watch the result :

It's cool, but wait i forgot to talk about one thing, finding real OEP !
Restart OllyDBG, let the loop xor all the first stage, and setup breakpoint on :

This not api resolution, but call resolution !
This sub is quite simple, like api resolution it will check into a table the offset of the call and replace 0xDEADCODE by the addr of the (stolen ?) call.
I think (it's not sure) the packer has stolen some call from the virgin file and reconstruct them with a push addr ret.

Let's put a conditional log on ret address ( Expression = "[esp]" ).
We run the program and exit him and watch the log.

If you remember at the begining of the article, the second breakpoint on access on code section land us to the first entry of your log, is it OEP ?
I don't think so, it's a call to GetModuleHandleA(), ... strange, ... strange.
If you look closely, there is another thing strange, before the log of the loading module "USER32.dll", we can see a call to 0x004085D4, but this call is just a redirection to GetModuleHandleA,
so what's happen between ?
We will restart our debugger and put a breakpoint on the ret of the call redirection function and wait until it go to the last 0x004085D4.

We trace the code, call "api address solving", we put a breakpoint on the JMP EAX, trace into GetModuleHandleA(), and execute till return.
We are back into virtual memory code, and trace it until get :

CALL 03_unpac.00408670 will go to resolve api, and call DialogBoxParamA().
But wait we store first argument into eax, so this function need an argument.
If we look msdn documentation first parameter of DialogBoxParamA() is a handle to the module whose executable file contains the dialog box template.
So the parameter of this function should be the result of GetModuleHandleA(NULL) (this will be first stolen fix).
A second problem is when we will return from DialogBoxParamA, and return from sub_00401000 we should ret to a fonction wich call ExitProcess().
Launch the injector, and attach olly to the process, and search reference to kernel32.ExitProcess, and we found this sub :

Conclusion

Introduction

When I saw article from Xylitol's blog about Tracking Cyber Crime: Malwox (Win32/Cidox Affiliate) Mayachok.1, I asked my irc bot to scan each hour files dropped by this site to make some stats about repacking interval ( you can see a screenshot of statistics in next part).
It's cool to have a lot of samples but it's more funny to study them.

Statistics

As you can see it is repacked approximately each 5 / 6 hours to avoid AV detections.
At the moment the bot is in beta test, and many logout occur every time I have to recompile it, so stats are approximate.

Dropper

Here, I will not study packer, but just the method of infection which is not very interesting (and old school ?).

Finding this test was funny, if the unpacked executable found "/chk" on his command line argument, it will exit directly, maybe for testing their repack routine (~5hours).
If it don't find this argument, it will generate a random dll name using this routine :

The dll is then decrypted using custom TEA Algorithm ( we will study it in next part ), and written into %SYSTEMROOT%/system32.
Next it sets into a registry key the AppInit_Dlls value which is the path to this dll, in order that each process using user32.dll will load this dll.
Before restarting your computer with ExitWindowsEx(), it will delete all files present into :

They use SHGetSpecialFolderPath() with csidl argument equal to CSIDL_COOKIES and CSIDL_INTERNET_CACHE to delete them.
Maybe for cleaning traces of infection.

DLL

As you can imagine the dll is also packed.

The DLLMain graph looks like this :

As you can see there are four branches depending of the fwdReason argument of DLLMain function.
The first one, DLL_PROCESS_ATTACH, will be called when the dll is loaded in each process using user32.dll ( AppInit_Dlls ).
This branch is just here for allocating memory, and unpacking the real stuff of the dll.
It just unpacks the dll, but it will not execute the unpacked code.
It will be executed when fwdReason == DLL_THREAD_ATTACH, so when the process uses CreateThread() for example.
The other branches are not interesting.
After unpacking this stuff, I was able to work with IDA without problem.
There are three branches of different execution flow based on the process name the dll is into :

They use an hashing algorithm, in order to test if they are in a browser process or not, and they do the same thing to detect vm processes and av names into program files folder.
So here is a complete test program to test all their hash table :

As you can see, I just found 6 process name on the 7 hash, so if you have some idea, you can leave me a comment :], but it's not very important.
The main thing this dll does is hooking several functions from ws2_32.dll :

send()

select()

recv()

ioctlselect()

connect()

closesocket()

WSASocketW()

WSASend()

WSARecv()

WSAGetOverLappedResult()

WSASetEventSelect()

WSAEnumNetworkEvents()

WSAConnect()

WSAAsyncSelect()

Theses hooks are setup for redirecting you on phising website when you go on :

help.vkontakte.ru

help.mail.ru

admin.vkontakte.ru

update.microsoft.com

update.mozilla.org

download.opera.com

chrome.google.com

official.odnoklassniki.ru

rushotgirls.com (#lulz)

internet.com

*.co.cc

Each time your browser window name changes, it will try to contact their command and control server (C&C), to update an interesting configuration file, that you can find into : "C:Documents and SettingsAll UsersApplication Data" under the name "cf".
At the end of this post you can find a toolz to decrypt this configuration file :

When the dll is inside a svchost process, the infection remains persistant, by checking if the configuration file exist, or if AppInits_DLL is set ; but they failed on one thing, the dll file, for desinfecting your pc you have just to rename the dll (my toolz checks if you are infected too and generate for you the name of the dll), and reboot your computer ( not my toolz ;) ).

A last thing that I wasn't able to study is the fact that some times, command and control drops a new executable, and createprocess() after decyphering it.
But it didn't drop me this PE, its name is "ru", because I saw his name when it try to write it at location : "C:\Documents and Settings\All Users\Application Data".

Introduction

I disovered a new method of injection (I don't know if it is really new) in a malware dropped by duqu.
So I want to share it with you and as usual write a p0c.
Edit : This method is not new, apparently it have been using by game cheats for years, but instead of using
ZwUnmapViewOfSection they use FreeLibrary.

Injection Method

The malware in question is simply a keylogger, but it uses a nice tricks for injecting into another process.
First it will create (as usual) a suspended lsass.exe process via CreateProcess().
Then it will gather process information via ZwQueryInformationProcess(), especially PebBaseAddress.
But what can he do with this address, if we look at PEB struct :

It will get the ImageBaseAddress at offset 0x8, by reading it with ReadProcessMemory().
First it create a section with ZwCreateSection(), then it will in the actual process (not in lsass.exe supended), ZwMapViewOfSection() with argument BaseAdress equal to 0, copy old lsass.exe PE image and modify entry point, he will do the same operation on lsass.exe process but with BaseAdress equal to BaseImage, but wait ! if we read the documentation of ZwMapViewOfSection, we will get a NTSTATUS equal to STATUS_CONFLICTING_ADDRESSES, and the answer is no, because before the second ZwMapViewOfSection, it will perform ZwUnmapViewOfSection() with BaseAddress equal to ImageBaseAddress on lsass.exe process.
And if you wonder : "Wait what !? is it possible ?", and the answer is yes.
With this tricks the malware is able to replace ALL the PE image of the suspended process.

p0c

So I decided to rewrite this tricks, to well understand the stuff done by the malware ( maybe you will better understand what I explained before ).
Tested under Windows XP SP3, and Windows Seven SP1 (32 bits).

Conclusion

Introduction

An (IRC) friend Horgh told me : "Why not study prioxer, it could be fun ?".
But what is prioxer ?
It's simply a backdoor Trojan, wich has a dropper with his own parser for NTFS and FAT format.
That's why it's fun :], it was a cool way to study approximately how can work NTFS File System.

The thing it will do is to infect the dll "dhcpcsvc.dll" ( we will see after what the purpose of the infection ).

NTFS

(This is not a tutorial about NTFS, it's just result af all the stuff reversed from prioxer, i wanted to have fun with IDA, and take some challenge by not looking too much documentation or source code like ntfs-3g, so if there is some mistake please refer to your friend google for more about NTFS).
But it will not directly open an handle (CreateFile())on this file which is located in "%SYSTEMROOT%/System32/".
It will open an handle on your current hard disk driver( like C: ).
So here is a schem about how it works :

The first thing, we must know on NTFS : all data stored on a volume is contained in file, including data structures used to locate and retrieve files.
A NTFS Volume, will start every time, with a data structures, named NTFS Volume Boot Record, she is here for gathering a maximum of information about the volume, like Number Of Sector, or Bytes Per Sector, ... etc ...
Then with thoses informations, we can access the MFT (Master File Table) which is the heart of the NTFS, it is implemented as an array of file records.
Shel will contain one record, for each file on the volume including a record for the MFT itself.
I will not describe all these files, but a special one : Root directory (also known as "\" or "$I30"). This file record contains an index of the files and directories stored in the root of the NTFS directory structure.
You have understood that prioxer will use this File Record :].
But ! if you look at my schem, we know Root_Directory is the fifth entry in the array of file_record, and i don't know why they do that but they compute the offset to read this file_record with values found in in $DATA Attributes from MFT, why they don't compute the offset in this simply way :

MFT_Addr + sizeof(FILE_ENTRY) * 5.

Anyway, it's not important :], we continue your investigation.
The thing to know is, that every FILE_RECORD has a list of attributes : (especially those)

A directory, is simply an index of file names (along with their file references), organized like a b-tree.
VCN is Virtual Cluster Numbers, a vnc is a linked value to LCN (Logical Cluster Numbers) wich allow to read, write directly on the hardware disk.
So, in your case prioxer will travel the root_directory, look for WINDOWS directory node, then travel "Windows" node, and get "SYSTEM32" node, and get dhcpcsvc.dll.
And he is able now to read, write (with ReadFile() and WriteFile() API) directly to VCNs of this file.
I will not explain more about NTFS, First I'm not familiar with this FileSystem (new for me), and working almost with IDA took me about 2 ~ 3 evenings to well understand how prioxer work.
Next time, I will read some docs :], it will be easier.
Ho by the way i wrote some shit for parsing only my root directory :

Infection

Ok so now we know that prioxer will do some shit with this file, but what !?
So prioxer will change the offset value, of "ServiceMain" exported function :
And put some code in .text section located at ServiceMain changed offset :

The snippet of code, will simply load a library with a random name in our case "ctapi3.dll", dropped by prioxer and then jump to the real address of ServiceMain.
I will not study this dll (you can find her into ressource, directly), it simply a botnet component that can exchange commands and data over IRC with a command-and-control.
Then it write a .bat file, and execute it for deleting the dropper.
The only interesting thing was the infection method via a NTFS parser, and infect a windows dll, wihch will be load each time you want to use DHCP.
Another interesting fact is a side effect of this technics, you can find a dllcache directory in %SYSTEMROOT%, NTFS maintains it for some often used system files.
That's why if you are infected by this trojan, you won't be able to see the difference on dhcpsvc.dll, but a tools like gmer with his own ntfs parser can do it, or if you reboot your computer, you will be able to see it, and your AV too.

Conclusion

Introduction

I received several mail asking me, if I was still active on my blog.
And the answer is YES!, i'm just (very) busy by my internship, and some personal projetcs.
So today I give you some news.

TDL4

I'm sorry for my english readers (if there are), but my draft article about all reverse stuff from tdl4 is written in French. But you can use Google Translate !
So here is the link to the article.
Be careful this is an oldschool version ( 0.3 ), I'm currently studying new version.

TDL4 (New version)

And we will start with a tricks for detecting Virtual Machine, apparently the new loader do this check, instead of the loader from my article.
Maybe for you it will not be new, but for me it is, I'm a beginner in malware analysis.
It will use WQL language to query Windows Management Instrumentation.
I will not bore you with disassembly code, but with a picture, that will show you a little script that I wrote for defeating unicode string obfuscation :

First it will gather all the information about your pc and send this to a C&C.
And after for example, it will check if in process list there is "CaptureClient.exe", or execute the request "SELECT * FROM Win32_DiskDevice WHERE Manufacturer = "VMware", etc...
This is how they can detect that you are in virtualized or emulated environment.
I didn't know how WQL work, so I decided to develop someshit :

Introduction

If you are bored of my tutorial on safedisc just go to Bonus section for laughing.
Today we are going to see safedisc version 2 (in this case i worked on v2.05.030).

Detection

No more *.icd file, the loader is now integrated into the main executable.
The signature is the same : "BoG_ *90.0&!! Yy>" followed by 3 unsigned integers : the version, subversion an revision number.

Anti Debug

In this case we are using ring 3 debugger, the tricks are the same than in safedisc version 1 :

IsDebuggerPresent()

PEB!IsDebugged

ZwQueryInformation (ProcessInformationClass = ProcessDebugPort)

You can use Phant0m plugin or follow what i did for safedisc 1.

Find OEP

Like I said in "detection" section, the loader is now integrated in the main executable, so we must find real oep after safedisc decyphering stuff.
I don't know if it's a good way to find it, but i set an hardware breakpoint on GetVersion, and look around for finding where am i. (GetVersion is one of the first called api).
But after watching some disas when i opened my ra2.exe into OllyDbg :

Routine are exactly the same than my previous post about version 1 subersion 41, they compute the addr and then ret to it.
BUT ! now they check on the stack from where you have called this routine, and if it's an unknow address, it will compute a random api address.
So when we will want to fix import, we will have to scan code section find 0xFF15 (call dword [rdata]) and push the addr + 6.
I will spare you from crash, because it's not the only protection ... after making a call fixer, i encoutered a second problem, you can have several call to the same offset to rdata section, and in function of where you called it it will compute different api address :

As you can these 2 calls call the same routine, but ret on different api.
So for our call fixer we will have to create a temporary kernel32 and user32 table, and fix each call dword ptr to call the good index :

Make a temporary dword table size of nb api, fill with null at start

Scan code section, compute address api with safedisc routine

Hook return safedisc routine, and put address into a register

If computed address is not known find place (null bytes) into temporary table, and fix destination of the call dword ptr with new index into the table.

If computed adress is already known and index into the table didn't change, do nothing, else fix
destination of the call dword ptr.

We will remplace the JMP SHORT ~df394b.100183EE, to jump to our code (in my case i used a dll, why because dll injection FTW !, no it's a simply way to fuck this anti dump, and not assemble code in ollydbg each time, yes safedisc 2 call fixer is longer than safedisc 1).

So if you are following my tuts and code some shit, your dump will crash... we need to fix 3 more tricks.
The problem is mov REG, [rdata] ... call REG :

This routine will just compute an addr to rdata section, and ret to it, so for fixing this we will have to replace jmp by call [rdata], but wait jmp addr it's only 5 bytes and call [rdata] is equals 6 bytes, but don't worry when we will ret from this routine we will ret at 0x0040C488 + 6 (in the example above), so we have enough place to fix it.
And the last tricks is similar than this one seen below, it is jmp [rdata], and we have enough place too for fixing it too.

For injecting the dll, i used a olly plugin writtent by baboon, big thanks to him :]
Then after injecting dll, dump process, use importrec, and enjoy !

Bonus

And now ! the lulz part :]
In the folder of red alert 2, we can see ra2.exe (protected by safedisc) and game.exe (not protected), ra2.exe will simply launch game.exe. So removing safedisc was a long solution for breaking it.
But they used lame protection to watch if the process was launched by ra2.exe or not.

This routine is called for checking the type of message in our case 0xBEEF, and then if the MapViewOfFileEx() is well done, it will set a value in 0x839E4C. By watching reference to this immediate constant, we can see this :

Introduction

No this is post will not be about SVN (a software versioning).
We will just see a litlle difference in the subversion 41 of safedisc 1.
I invite you to read this post about version 1, before reading this.

Anti debug

It is the same stuff than before, you have to use EBFE tricks too.
This part is exactly the same than the previous post.

Call redirection

Each call to Kernel32 or User32 api, are done through dplayerx.dll as usual :

But in this revision for each api you will have to push a predefined value (random?) like 0xBFEA1267 in this example.
We can see the number of the api to call, and 0 or 1 for kernel32 or user32.
But ! after the call, we haven't got a jmp dword for jumping to the resolved address api
Because now the routine dplayerx.00E75310, will GetProcAddress() and then ret to this address, code at 0x013E5BED will never be executed.
So we must fix the previous code for fixing the iat :

Now set new origin, run it,then do the same thing with user32 api, change edx start value,push 0 by push 1, and 50 by 29. Now you can dump fix the iat with ImportRec and enjoy your game :]

Conlusion

This post is not very important but just to see a little difference, and how to fix it.
Btw today is Saturday, girlz go shopping for new shoes, guyz buy their alcohol for saturday night party, and me I wrote a list of fun (protection) games and buy some of them :

I just need time for beeing able to publish my research about this new stuff.

Introduction

I'm actually doing an internship, so it's difficult to work on my personal project.
But today i found some times to finish the first release of my unsafedisc, actually it will work
only with version 1.11.0 because i haven't got enough game with safedisc protection.
But when i will touch my pay, i will have the possibility to buy some old school games :]

Tiny Encryption Algorithm

In my last post about safedisc, i said dplayerx.dll was here for decrypting some sections of the icd file, like .data and .text. I reversed all the stuff from this dll, there is a lot obfuscation inside by using stc, jb, jmp instruction, the only solution i found was to trace the code and reconstruct with my own hand. If you want to check the decrypt routine look at the begining of segment text2 inside dplayerx.dll.
The interesting thing to know is the key that is present in this form :
ABCD - ABCD - ABCD - ABCD
It uses a 128-bit key with the same 32-bit pattern.
So we are able to bruteforce it, but how to know it's the good key ?
At the begining i was thinking about decrypting the 64-bit blocks where oep is, and check if the value equal to push ebp, mov ebp, esp (0x55 0x89 0xe5), but it's not enough, it was a really bad idea.
After switching on my brain, i looked at .data section :

We can easily see the same pattern : 0xA7E6ED0A 0x01E06592, TEA use electronic codebook mode (ECB), if we got in our example two 64-bit block of "0" they will have the same cipher.
With the end of section data, we are able to bruteforce easily the key :].

Monte Carlo algorithm

The last part for breaking safedisc, is reconstruct all the iat. By reading information from woodmann, and my reversed stuff from dplayerx.dll especially this routine :

Conclusion

Screenshot

Introduction

It's my first english article so please be cool.
If you haven't noticed yet, I (only) like old video games (see SNES), today i'm going to play with Red Alert : Tiberian Sun.
This game is protected by an old commercial protection : Safedisc aka C-dilla.

Detection

Safedisc version 1 can be recognized by several files on the CD :

00000001.TMP

CLOKSPL.EXE

DPLAYERX.DLL

SECDRV.SYS

And also the existence of two executables, Game.EXE and Game.ICD.
We can also recognize this protection by her signature :

The signature is "BoG_ *90.0&!! Yy>" followed by 3 unsigned integers : the version, subversion an revision number.

Or simply by using Protection ID :

So in this article we will talk about how to defeat Safedisc version 1.11.0000 using a ring3 debugger.
Yes because all over the internet, i just found article / tutorial using Softice.

Anti Debug

So let's open Game.exe into OllyDbg.
We can found two anti debug tricks related to a ring 3 debugger.
The first anti debug trick is several call to IsDebuggerPresent(), and they also check this manually :

The second trick is several call to ZwQueryInformationProcess(), with ProcessInformationClass argument set to ProcessDebugPort for checking if the process is being run under the control of a ring 3 debugger.
I know, it can be simply bypass by using the Phant0m plugin, but i wanted to write a script to defeat it :

Put an hardware breakpoint at the entry point of the function, and at the end.

Check if the function was called with ProcessInformationClass argument = ProcessDebugPort ( 0x7 ).

If it was called with the fact mentionned before, we set the buffer to 0 (The process is not being run under ring 3 debugger).

No we can work with our executables without problems.
There are another anti debug tricks, like calls to CreateFileA() with argument : "\.SICE" and "\.NTICE", for checking is softice is running.
Also in this version, they load a driver (secdrv.sys) but i have noticed nothing about anti debug techniques.
I don't know what the purpose of this driver
in this version of safedisc (1.11.0000), i tried to do some shit with DeviceIoControl() api but without result.
Apparently, the driver is safe in this version while others are : CVE-2007-5587.

*.ICD

At the beginning of the post, I mentionned the existence of two files Game.EXE and Game.ICD.
Game.EXE executable is only a loader which decrypts and loads the protected game executable in the encrypted ICD file :

Safedisc uses a debug locker technique with buffer overflow to the start the real executable (ICD file).
So let's see the buffer used by WriteProcessMemory() :

You can notice the different call eax, LoadLibrary("dplayerx.dll"), GetProcAdress("Ox77F052CC"), then it call this function, for decrypting all sections of the icd file (it uses TEA ).
So if we want to attach a debugger to the icd process, remember my last post about EBFE or CC tricks, and notice the PUSH EBP RET (0x53C3), we can replace these opcode by EBFE,
then attach olly to the process.
We can see that if DEP is on, the game will crash (failed?).
So let's replace (0x53C3 by 0xEBFE), continue the program (ResumeThread() will be called) and open a new ollydbg and attach to this process.
Then pause the program ( F12 ), and replace JMP SHORT 0012FFB2 by PUSH EBX RET.
Trace the code you will arrive into kernel32, continue tracing, then at the entry point of the icd file.

So we are here and the fun part can begin :] :

006854E3 > 55 PUSH EBP
006854E4 8BEC MOV EBP,ESP

Call redirection

In Safedisc, all the calls to Kernel32 or User32 api are done through dplayerx.dll.
Let's take an example :

You can notice a call to dplayerx.00D4E9D0, with a stack where we pushed 0x67 and 0x0.
What does it mean ?
It simple, 0x0 is for telling the routine that it's a kernel32 api, and 0x67 is the number of the api to call.
This routine will GetProcAddress() for the specified api, then jump to it.
And what about User32 api ?

When we got out of the func dplayerx.00D4E9D0, ecx equals the address of api wich will be called, so we save this in a memory region writable.
And then we fix this in the rdata section for each api for kernel32.
Set a new origin at the begining of your code and run it.
Olly break, and our rdata look pretty nice :

We need to do the same thing for user32.

>>> hex(((0x6984C4 - 0x698358) / 4) + 1)
'0x5b'

We will use the same code as above but change the start value of edx to 0x698358, PUSH 0 to PUSH 1 and cmp EBX, 99 to cmp EBX, 5C.
Run it and now come back into import rec :

Everything is ok, we can dump and fix the iat without problems. Safedisc has been removed correctly :].
BUT ! there is an another problem when we launch the game it ask us for the a cd ....

This is not the purpose of the article but you should copy all *.mix files form the cd into the tiberian sun directory and look around 0x004DCBAE ;)

Conclusion

I know over the internet there are several unwrappers for safedisc but with closed source, so i'm actually studying differents versions of safedisc, for writting a similar tools but with source included.