Archives

All posts for the month October, 2007

Some times ago I stumbled on a post at Offensive Computing where an user had some problems trying to figure out the encryption used by a malware (md5=36401cb9178232dde01b2788e8fc56f4).
The malware contains 2 files, located in the resource section. The files are encrypted, how to find out the encryption scheme? Well, using a debugger I would say. I didn’t start any debugger btw, deciding to take a look at the files using a resource editor. It’s a common thing to store files inside resource section. Here are the starting bytes of the first file:

If you know which are the first common bytes in an exe file you should be able to figure out yourself which kind of encryption has been used. The presence of many 0x13 bytes is a nice hint, the file has been rot13h-ed. Just to make things clear, I used the word rot13h which is different from the well known rot13 encryption.

In an old blog entry I talked about a little ida plugin able to extract and analyze an hidden file; I slightly changed the plugin adding the possibility to un-rot13h the hidden file.

Share this:

Like this:

14 days without internet connection, thanks to Telecom Italia. They suspended my service because they wanted to activate a new service I didn’t request; I told them I didn’t subscribe a new service and I want the old one back. They need 14 days to reactivate my old service, 14 days to click on some buttons… not bad :/

Share this:

Like this:

This post is a little bit long, for a better reading you can download the pdf version here

Roaming around Symantec web pages I stumbled on a review of a trojan named Ascesso. The malware does a lot of things that are described inside the “Technical details” section. I decided to give it a try just because it’s interesting to read what a malware does, but it’s much more funny when you play with it! In this blog entry I won’t talk about what the malware does, but I’ll write something about the way I used to obtain a readable dead list inside Ida. One of the next blog entry could be focused on the analysis of the malware, don’t know.

The file I’m going to analyze is named asc3550.sys, md5=BBEB49A32417226CABED3E104A9C94B5.
The malware is crypted, I think it’s a home made protection. If you load the file in Ida you are not able to see too much, almost all the code has been crypted. To view the uncrypted malware you have two options: you can run the driver dumping the memory image using a ring0 dumper (i.e. softice+icedump), or you can use Ida trying to convert the initial output into something really closer to the original driver. Generally, I like to work on a simple dump of the packed/crypted file, but with a driver I prefer to work on a perfect file. With a simple dump of the image you’ll have to deal with instructions like:

These are the starting instructions. Reading through various forums I had the impression that most of the people have some problems trying to anaylize this kind of snippets. It’s pretty obvious what the snippet does, it’s a simple decryption routine consisting in a sub operation. The main problem is: which part of code will be decrypted? Everything depends on value stored inside edx register, which is obtained by the instructions inside the call 400242:

How to know the exact value pointed by [esp+8]? Taking in mind that the file I’m analyzing is a .sys file you can get the value inside the stack with a simple deducting reasoning.

The first driver instruction is the one at 400240, but who brings me there? I mean, there should be an instruction which is executed before the one at 400240. The instruction is a call and it’s somewhere inside IopLoadDriver function (in ntoskrnl.exe):

[edi+2C] points to DriverInit, 400240 in this particular case. Look at the last parameter (pDriverObject), it’s really important. You have to concentrate on the stack only, when you are at the first driver instruction you’ll have something like:

DRIVER_OBJECT+0Ch is DriverStart, the memory address that points to the first byte of the driver. I don’t have the possibility to know the exact value stored inside DriverStart field, but for a static analysis you can suppose that the address is the ImageBase: 0x400000. It comes out that the edx value we want is: 0x400000+0x9540 = 0x409540

I inserted the Message function just because I wanted to see the first non-decrypted address: 0x409A9C; you can remove the function, if you prefer.

Ok, now that the decryption is complete I have to look at the decrypted code. The last instruction of the initial decryption routine will bring me directly at a fresh decrypted instruction, which is the next instruction to be executed?

The decrypted code is a small routine, all the other bytes of the file are still crypted; maybe I have to deal with some more layers. The decrypted code contains an initializations part, some calls end a final jmp instruction.

Initialization
It’s pretty easy to understand the initialization code. I won’t attach any snippet,it’s only a sequence of mov/add/lea instructions used to retrieve/store some special values that are used later.
At the end of the initialization part there’s a piece of code which is used to move 0x44 bytes:

Just wait some minutes and I’ll tell you everything about these parameters.
As you can see I renamed the call, the name suggests the task performed by the call: all the sections are decrypted. The call contains a loop which is executed until all the sections are not decrypted; it starts from the last section. At each round, it firstly gets the pointer to the IMAGE_SECTION_HEADER of the current section (he needs to know where the section starts/ends) and then decrypt it. The decryption algo is really simple:

Another simple decryption. This time a xor instruction between the crypted dword and a fixed value, it’s 0x003CF5B5 and it’s located at address 409A38.
Look at the comments I inserted in the code, don’t you have any doubt about it? The decryption routine resides in .reloc section, is it possible to decrypt all the bytes in .reloc section? Well, no because if you decrypt every single byte you’ll decrypt the decryption routine generating a bsod. That’s why the call needs the first two parameters (0x9540 and 0x8FA0). The values are taken from .reloc IMAGE_SECTION_HEADER. One of them, 0x8FA0, is the Raw Offset of of the section. To calculate the number of bytes to decrypt the malware uses 0x9540 substracting 0x8FA0 from it, obtaining 0x5A0. These are the bytes to decrypt. The rest of the bytes belong to the decryption routine I’m checking and they are untouchables.

Exploring the decryption routine I found a strange piece of code I’m not able to totally understand:

Three things:
1. it checks for ‘rsrc’. This is a common name generally used for resource type section, if the file contains this particular section the decryption won’t be executed over that section. The driver doesn’t have a .rsrc section for sure, why the author needs to add this check?
2. do you remember the 5 parameters passed to the function? One of them is the value 1. At 40995A it checks that value. The condition is satisfied and the conditional jump occours. This function is called one time only, which is the purpose of this check?
3. it really needs two parameters (0x9540, 0x8FA0) and a sub instruction? It only needs 0x5A0 and a different implementation algorithm.

I don’t have an answer for the first two things, but I think the author ripped this code. Why? It’s a behaviour of some packers, they leave resource section untouched. Moreover, there’s another check for [ebp+Fixed_Value_1]:

Call_4099A7 is almost identical to Call Decrypt_current_section, they only differ by a pushad, nothing more. Hm, who adds an useless bugged function in his code? I might be wrong but ‘rip’ is the first thing I can think of, what do you think?

Anyway, here is the script I used to decrypt the entire file:

#include

static main()
{
auto CurrentAddress;

// I need to copy some bytes from 0x409A48 to 0x400240, do you
// remember the last piece of code in the initialization?
CurrentAddress = 0x409A48;
while (CurrentAddress < 0x409A8C)
{
PatchDword(CurrentAddress-0x9808, Dword(CurrentAddress));
CurrentAddress = CurrentAddress + 4;
}

Relocation: to fix or not to fix, that is the question
When the file is totally decrypted the loader has to fix some things: relocations, some pe fields and something else. The function able to fix relocation is located at 40962F, essentially the algorithm is (click to enlarge):

This diagram should be enough for you to understand the algo. Taking in mind I’m going to reconstruct a fully readable file under IDA, is it necessary to change the relocated addresses? The answer is no; as you can see from the picture above relocation is not applied when DriverStart is equal to ImageBase, I’ll do the same.

Fix PE fields
After relocation there’s a little function, it changes some fields in the PE header.

Some minor changes to PE header. It changes rva and size relative to IMAGE_DIRECTORY_ENTRY_EXPORT and IMAGE_DIRECTORY_ENTRY_BASERELOC.
Again, there’s a strange thing in this piece of code. It zero-es PE+78 and PE+7C while they are already zero…

Change FirstThunk field
The last part of the loader, the function starts at 4096B7. The algorithm fixes every single FirstThunk element overwriting the old value with the starting memory address of the relative function.

The first two dwords are relative to the two Hal.dll’s imported functions, and the 3° dword represents the null terminator dword. I’m interested in the first function, _IMAGE_IMPORT_BY_NAME is located at rva 0x8A34:

At this point the malware uses MmGetSystemRoutineAddress to retrieve the function’s address, that’s why MmGetSystemRoutineAddress is one of the functions imported by the original encrypted file. Once it has the address of the function it stores the memory address at 4045C0.
There’s a little exception in this system regarding the function from ndis module, the malware doesn’t use MmGet.. function but it takes the addresses directly from the running module. Why? I’m sure you can easily find out why by yourself.

Now, to obtain a readable dead list I have to write a simple idc script able to convert:

.text:0040048D call ds:dword_4045C0

to the more readable instruction:

.text:0040048D call ds:_KfAcquireSpinLock

Here is the script:

#include

static main()
{
auto CurrentAddress, _dword;

CurrentAddress = 0x4045C0;
while (CurrentAddress < 0x4046CC)
{
// Do I need to fix this dword?
if (Byte(CurrentAddress) != 0x00)
{
// Get the pointer to the name of the API, patch and rename the address
_dword = Dword(CurrentAddress)+0x400002;
PatchDword(CurrentAddress, _dword);
MakeNameEx(CurrentAddress, “_”+GetString(_dword, -1, ASCSTR_C), SN_AUTO);
}