P4r4n0id Reversing Lab

Walking Toe to Toe With Shylock

by on Dec.09, 2011, under Malware, Reversing

Contents

1. Walking Toe to Toe With Shylock

  1. Introduction
  2. Tools
  3. Links to other excellent analyses of shylock

2. Unpacking the Sample

  1. Sample Generic Overview
  2. Unpacking – step by step
    1. VirtualAlloc / Memory Copying – #1
    2. VirtualAlloc / Memory Copying – #2
    3. Decryption Routine
    4. VirtualAlloc / Memory Copying – #3
    5. Process Image – Erasing Routine
    6. Rebuilding the Process Image – Copying the PE header
    7. Rebuilding the Process Image – Copying the Sections
    8. Rebuilding the Process Image – IAT Rebuild – LoadLibrary / GetProcAddress Combination
    9. Rebuilding the Process Image – VirtualProtect the Sections
    10. The CleanUP

3. The OEP
4. Dump & Fix

  1. ImpREC – Fixing the Dump

5. OEP – Core Infection 

  1. The Decryption Routine
  2. GetModuleHandleA  / GetProcAddress
  3. Unique ID Generation
  4. Mutex Creation
  5. File System Changes – APPDATA folder
  6. Surviving Reboot
  7. Creating the .bat File
  8. cmd.exe Process
  9. explorer.exe – Process Injection
    1. Step #1: Retrieve a HANDLE to the remote process (OpenProcess):
    2. Step #2: Allocate memory in the remote process’s address space for injected data (VirtualAllocEx).
    3. Step #3: Write a copy of the initialised INJDATA structure to the allocated memory (WriteProcessMemory).
    4. Step #4: Start the remote copy of ThreadFunc via CreateRemoteThread.
    5. Step #5: Wait until the remote thread terminates (WaitForSingleObject).
    6. Step #6: Retrieve the result from the remote process (ReadProcessMemory or GetExitCodeThread).
    7. Step #7 and #8 – The clean Up

6. Conclusion

7. Final Notes 

1 Walking Toe to Toe With Shylock 

1.1 Introduction

Shylock is a new Trojan discovered by trusteer around 2 months ago. It is designed to be a Trojan Spy and specifically a Banker. Targets the windows platform, collects various system information from the infected system and send it to a remote C&C server, able to perform Man in the Browser attacks (IE and FF) against users of UK banks.

1.2 Tools

1.3 Links to other excellent analyses of shylock

1.3.1 EvilcryShylock via Volatility
1.3.2 MilaGreedy Shylock – financial malware
1.3.3 Malwarereversingshylock-in-depth-malware-analysis

2. Unpacking the Sample

2.1 Sample Generic Overview

  • File Size: 363.09 KB (371800 bytes)
  • MD5: 4FDA5E7E8E682870E993F97AD26BA6B2
  • SHA-1: D1B17C351BAFC899BA14C84E09B5CC258A2195BF
  • Packer: Unknown (PEID)
  • Company Name: He is ready at the door
  • File Description: So keen and greedy to confound a man
  • Signature:

2.2 Unpacking – step by step

As we’ve  seen from the previous paragraph the binary is packed with an unknown packer so we have to start analyzing it from the top.

The start code is quite typical, some several API calls including some Crypto functions:

2.2.1 VirtualAlloc / Memory Copying  - #1

On address 00404A69 we see a CALL instruction (CALL sub_004040C0). Once stepping in into the function we can notice the VirtuallAlloc API function call:

 

Creating a new executable memory region:

Once executed, on address 00380000 we can see the newly allocated memory – newly executable memory region (5E200 bytes size):

Directly after the memory allocation we can see a memory copying routine –  copying 5E000 bytes. The routine copies the full image of the running process (shylock.exe) starting from the process image base address (Shylock.00400000) to the newly virtually allocated space (00380000):

 By end of loop:

Next, on address 00404152 we can see a CALL EAX instruction. EAX points to 4160 bytes inside the newly virtually allocated memory (00384160):

2.2.2 VirtualAlloc / Memory Copying  - #2

On address 003841F0 we see the second call to the VirtualAlloc API function. This time allocating 703166  bytes marked as  PAGE_READWRITE (and not as PAGE_EXECUTE_READWRITE as  previous allocation). On address 00940000 we can see the newly virtually allocated memory:

 

Using the same memory copying routine, this time copying 55D5F bytes from offset 602E (first VirtualAlloc call  - 0038602E) to 00940000 (second VirtualAlloc call):

2.2.3 Decryption Routine

 Let’s see what we have at this offset (0038602E):

An encrypted executable. On address 00384220 we can see the decryption routine:

Decryption routine pseudo-code:

Lets see the decryption routine in action (first 2 loop runs):

First Byte – First Loop Run:

Encrypted_Byte_Value = 35h.

ECX (key) = 12345678  –>  CL = 78

35h ^ 78h = 4D (‘M‘)

Which gives us the ‘MZ’:

ECX = 12345678 * 218FB + 3CAC0047 = 262FAB0807EF ==> CL = EF

Second Byte  - Second Loop: 

EF ^ EF = 0

and so on 55D5F / 7 bytes….

2.2.4 VirtualAlloc / Memory Copying  - #3

On address 00384260 we see the third memory allocation call . This time allocating 55F5F bytes marked as PAGE_READWRITE.

On address 009F0000 we can see the newly virtually allocated memory:

And again,copying 55D5F bytes from 00940000 ,the decrypted executable, to the newly allocated memory space – 009F0000 (3′rd time VirtualAlloc call)

2.2.5 Process Image – Erasing Routine

Once copied the decrypted executable , on address 00384506 we see a memory erasing routine. Starting from the process ImageBaseAddress (EAX points to Shylock.00400000) the routine overwrites it’s own process virtual memory with “0″ byte after byte:

By end of routine:

Using PE Tools – lets create a full process dump before and after this routine:

2.2.6 Rebuilding the Process Image –  Copying the PE header

Next we can see ,the same as above, memory bytes copying routine, copies 400 bytes (PE header) from the decrypted executable (3′rd V.A call 009F0000) to the newly “clean” / erased process image (shylock.00400000):

2.2.7 Rebuilding the Process Image – Copying the Sections

After copying the PE header, it is time to copy the section. The following routine is responsible for this task. The loop runs 5 times, copies the following 5 sections:

 

The Routine 

2.2.8 Rebuilding the Process Image – IAT Rebuild  - LoadLibrary / GetProcAddress Combination

By the LoadLibrary / GetProcAddress combination the code loads the following DLLs and resolves functions addresses in order to rebuild the IAT: 

LoadLibrary:

GetProcAddress:

 The code resolves the following functions addresses:

advapi32.dll: RegFlushKey ,RegQueryValueExA ,RegSetValueExA ,IsValidSid ,GetTokenInformation ,ConvertSidToStringSidA ,OpenProcessToken ,CryptHashData ,CryptDestroyHash ,GetLengthSid ,CryptCreateHash ,CryptAcquireContextA ,CryptReleaseContext ,CryptGetHashParam ,RegCloseKey ,RegCreateKeyA

kernel32.dll: GetLastError ,lstrcmpi ,GetTempFileNameA ,FindClose ,FindNextFileA ,GetFileTime ,CloseHandle ,WaitForSingleObject ,VirtualFree ,CreateRemoteThread ,OpenProcess ,VirtualFreeEx ,VirtualAlloc ,VirtualAllocEx ,GetExitCodeThread ,WriteProcessMemory ,FindFirstFileA ,GetProcAddress ,GetModuleHandleA ,GetCurrentProcess ,ProcessFirst ,ProcessNext ,CreateToolhelpSnapshot ,LocalFree ,GetCommandLineA ,CreateProcessA ,FlushFileBuffers ,GetShortPathNameA ,CopyFileA ,CreateMutexA ,DeleteFileA ,ExitProcess ,CreateDirectoryA ,ReadFile ,WriteFile ,SetFileTime ,ExpandEnvironmentStringsA ,GetFileSize ,CreateFileA ,lstrcpy ,HeapSize ,GetEnvironmentVariableA ,lstrcat ,HeapCreate ,GetVolumeInformationA ,GetProcessHeap ,HeapFree ,HeapAlloc ,lstrlen ,HeapReAlloc ,GetComputerNameA

msvcrt.dll: memmove,free,malloc,memset,memcpy,srand,getenv,sprintf

shlwapi.dll: PathCombineA

winmm.dll: timeGetTime

user32.dll: CharToOemA

2.2.9 Rebuilding the Process Image – VirtualProtect the Sections

By using the following routine the code calls the VirtualProtect API on every section (.text, .rdata, .data , .reloc , .adata). The loop runs 5 times (a loop run for every section):

 

 The 5 sections were marked as follows:

  • .text section = PAGE_EXECUTE_READ (0×20)
  • .rdata section = PAGE_READONLY (0×02)
  • .data section = PAGE_READWRITE (0×04)
  • .reloc section = PAGE_READONLY (0×02)
  • .adata section = PAGE_READONLY (0×02)

2.2.10 The CleanUP

Two calls to the VirtualFree API function:

In the first VirtualFree call EBX points to 00940000 (2nd VirtualAlloc call) and in the second call ESI points to 009F0000 (3′rd VirtualAlloc call).
We can see that the dwFreeType parameter is set to MEM_RELEASE (0×8000) as required because both above addresses were allocated by using the VirtualAlloc function.

3. The OEP

On address 0038433D we see a CALL instruction that lands us directly on the OEP:

4. Dump & Fix

4.1 ImpREC – Fixing the Dump

 After dumping the unpacked process using PETools  we need to rebuild the IAT. I am using ImpREC:

 

 5. OEP – Core Infection

This can be considered as the True EntryPoint, in other words here starts the Infection Process. We can immediately see the GetModuleHandleA  / GetProcAddress  combination. Before we get to the GetModuleHandleA  / GetProcAddress calls we can notice the “CALL Dumped_.0040166E” instruction that gets called twice. The “Dumped_.0040166E” routine is shylock’s decryption routine.

5.1 The Decryption Routine

After a successful HeapCreate / HeapAlloc calls shylock copies from it’s .rdata section to the newly allocated heap ‘N’ encrypted bytes and a 4 bytes key:

Let’s see  how the 4 bytes key / ‘N’ encrypted bytes structure looks like in the .rdata section:

 

The decryption routine (Dumped_.0040164C):

 5.2 GetModuleHandleA  / GetProcAddress

Now we can move on to the GetModuleHandleA  / GetProcAddress  calls. As we’ve seen above there are 2 calls to the decryption routine before  calling the GetModuleHandleA  / GetProcAddress APIs.

The first decryption call returns the following string:

The second call returns:

 

So the first thing shylock does is resolving the address of kernel32.IsWow64Process API function. Once resolved, it tries to determine whether its running under WOW64 system by calling IsWow64Process with the handle returned  from a call to GetCurrentProcess function (current process handle (HANDLE)-1):

 

Unique ID Generation

For future usage ,as part of the infection process, shylock generates a 16 bytes (calculated from 55 bytes buffer) unique ID number:

First 8 bytes:

By using the following routine shylock generates the first 8 bytes. The loop runs 10 times, on each loop there is a call to the CPUID opcode with EAX from 8000000A to 80000000 :

Next 4 bytes:

In order to generate the next 4 bytes Shylock calls the GetVolumeInformationA API function. One of this function parameters is lpVolumeSerialNumber [out, optional] (A pointer to a variable that receives the volume serial number.) Shylock uses the returned serial ID as its next 4 bytes:

 Next 15 bytes (in my case)

The next bytes are generated by calling the GetComputerNameA API function. In my case the returned length is 15 bytes.

Last 28 bytes

The last 28 bytes are generated by calling the GetTokenInformation API function -  OpenProcessToken(GetCurrentProcess()….) = > GetTokenInformation()

The returned TokenInformation is saved to an allocated heap due to a “ERROR_INSUFFICIENT_BUFFER” error on first call.

Next there is a call to IsValidSid API function with pSid parameter points to 8 bytes offset inside the returned token from above (skips first 8 bytes) which leaves us 28 bytes token info.

Building the final buffer into a allocated heap:

 Once the 55 bytes buffer  (8 +4 + 15 + 28 ) is ready, Shylock executes some crypto API calls on it:

 The Unique ID: “03 B9 A9 07 8D 48 AE 06 CA 2C 89 39 AD 57 A5 07″

Reordering the bytes:

 and calling sprintf function:

Mutex Creation 

 Before calling the CreateMutex API function the code jumps to the decryption routine (this time decrypting 5 bytes)

The decrypted string:

Mutex name –  the decrypted string (“MTX_”) concated with the generated UniqueID:

MutexName = “MTX_06AE488D07A9B90339892CCA07A557AD”
InitialOwner = FALSE
pSecurity = NULL

 File System Changes – APPDATA folder 

 Shylock drops a copy of itself (running process) under the APPDATA folder in a random location with a random name, let’s see how it is done:

Calling the decryption routine:

The decrypted string:

Once got the decrypted string  we jump to the following routine:

 The routine generates a random number by calling time.GetTime function and than doing some math operations on the returned value.

By calling the FindFirstFileA/FindNextFileA APIs combination Shylock searches all exe files under the system32 folder and extracts the name of the file, to be its chosen random name, from the file which is located in the generated random number location. By using the same logic Shylock also chooses the random folder under APPDATA path to copy itself to:

 BTW, Shylock decides to drop a copy of itself under the APPDATA path because that’s the path he gets after calling the decryption routine:

The decrypted string:

Surviving Reboot 

 Calling the decryption routine:

The decrypted string:

In order to survive reboot shylock writes itself to the registry under ”Software\Microsoft\Windows\CurrentVersion\Run” using it’s generated unique ID as the name value:

Creating the .bat File 

 Before creating the .bat file we see the GetTempFileNameA / DeleteFileA API calls.

GetTempFileName by MSDN:
“Creates a name for a temporary file. If a unique file name is generated, an empty file is created and the handle to it is released; otherwise, only a file name is generated.”

After the GetTempFileNameA / DeleteFileA calls we jumps to the decryption routine twice. First call decrypting 5 bytes:

The decrypted string:

Second call decrypting 119 bytes:

The decrypted string:

Now it is time for creating the .bat file by calling CreateFileA function:

Next, writing to the created .bat file the decrypted string when replacing all format strings “%s” with the full path of the running process (by using GetCommandLine API):

cmd.exe Process

 Again, calling the decryption routine. This time decrypting 11 bytes. The decrypted string:

Calling getenv function and GetShortPathName that returns the “C:\WINDOWS” string. Another decryption routine call – 22 bytes this time:

The decrypted string:

And 2 calls to the strcat API function:

First call – concats “C:\WINDOWS” and  “\system32\cmd.exe /c”

Second call – concats “C:\WINDOWS\system32\cmd.exe /c” and the full path to the tmp.bat file:

Executing the. bat file using the CreateProcessA function:

 explorer.exe – Process Injection

Calling the decryption routine. This time decrypting 13 bytes:

The decrypted string:

Once decrypted we land here:

By calling CreateToolhelp32Snapshot/ Process32First/Process32Next APIs, the code lists all running processes and by using strcmpiA function it compares the name of the running process to explorer.exe. Once found the explorer.exe process we jump here:

By looking at the involved APIs we can see that the code uses the CreateRemoteThread / WriteProcessMemory Technique to inject its’ code into explorer.exe process.
More info about the technique you can read here. Scrolling a bit down we see this:

We can see that the code calls WriteProcessMemory 3 times. Let’s follow the steps:

 Step #1:  Retrieve a HANDLE to the remote process (OpenProcess):

 

 Step #2: Allocate memory in the remote process’s address space for injected data (VirtualAllocEx):

Step #3: Write a copy of the initialised INJDATA structure to the allocated memory (WriteProcessMemory).

First VirtuallAllocEx/ WriteProcessMemory call:

We can see that the code writes 92000 bytes from address 00A50000 to the newly virtually allocated memory (022A0000). If we will look at address 00A50000 we can immediately see the MZ header :

 

Dumping the first explorer’s.exe injected code:

Before calling the second VirtuallAllocEx/ WriteProcessMemory combination the code changes 4 bytes at offset 28h (DOS Header->e_res2-> offset 28h / offset 2Ah) from 00000000 to be the base address of the v.allocated newly memory( 022A0000 ) and also changes at offset 2C (DOS Header->e_res2-> offset 2Ch / offset 2Eh) also from 00000000 to be the size of the newly v.allocated memory (00092000)

 

Second VirtuallAllocEx/ WriteProcessMemory call:

Writes again 92000 bytes from address 00A50000 (includes above bytes changes) to the newly virtually allocated memory – 023C0000:

 Dump:

 Let’s see the diff:

 Third VirtuallAllocEx/ WriteProcessMemory call: 

Writes 9D7 bytes to the newly allocated memory – 00AA0000:

 

 Step #4: Start the remote copy of ThreadFunc via CreateRemoteThread.

We see that the code calls CreateRemoteThread function in order to create a thread that runs in the virtual address space of explorer.exe process. The handle to the process in which the thread is to be created (arg1 – 68h) is the handle returned from the OpenProcess function. The lpStartAddress (arg4), the starting address of the thread in the remote process, is the address returned from the third VirtuallAllocEx – not the MZ code. And the lpParameter, a pointer to a variable to be passed to the thread function, is the address that returned from the 2rd VirtuallAllocEx call – the MZ code – the dll.

Step #5: Wait until the remote thread terminates (WaitForSingleObject).

Step #6: Retrieve the result from the remote process (ReadProcessMemory or GetExitCodeThread).

 

Step #7 and #8 – The clean Up


Free the memory allocated in Steps #2 and #4 (VirtualFreeEx), and Close the handles retrieved in Steps #6 and #1 (CloseHandle).

And we are infected :)

6. Conclusion

According to the title, the main scope of this blog post is walking toe to toe with Shylock Trojan. On my next post (in a few days) I will walk toe to toe with the injected code.

7. Final Notes

Thx 4 Reading!

p4r4n0id

Leave a Comment more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!