Carberp Reverse Engineering

We are going to talk about Trojan Banker Carberp from a Reverse Engineering point of view. Carberp is a Botnet delivered in the usual ways of Blackmarket selling, designed to be a Trojan Spy and specifically a Banker similar to SpyEye and ZeuS, able to perform Man in the Browser attacks, steal victim credentials, kill antivirus softwares, remove other bots like SpyEye and Zeus and much more…

Tools & Files

  • IDA
  • OllyDbg
  • CFF
  • Volatility
  • WinDbg

Essay

Carberp is a Botnet delivered in the usual ways of Blackmarket selling, designed to be a Trojan Spy and specifically a Banker similar to SpyEye and ZeuS, able to:

  • Perform Man In The Browser
  • Steal Victim Machine Credentials
  • Kill AntiVirus Software
  • Remove Competitors Bots (SpyEye and ZeuS and others)
  • Plugin System
  • Screenshot Ability
  • Form Grabber
  • Backconnect

Works from XP to 7 even with limited accounts, and performs injections on IE, Firefox, Opera and Chrome.

Like the most famous Trojan Bankers, Carberp has a Plugin and Config structure, that during infection process are downloaded and decrypted by the bot, here a quick list of the most known plugins:

  • cfg/miniav.psd
  • cfg/stopav.psd
  • cfg/passw.psd

We have also a Configuration File that contains URL Triggers and Malicious JavaScript code to Inject.

The C&C server could present also the following additional files:

  • random_name.7z
  • /get/key.html
  • random_name.php3
  • w.php3
  • random_name.doc

Sample Generic Overview

The sample we are going to deal presents the following base characteristics

  • FileSize: 130.00 KB (133120 bytes)
  • MD5: C2D749950BFD092E5E3AD96EB64D4990
  • SHA1: 0C51FEC8397088F3E8AA7B9FDBF4DFB0EEF3D7BB
  • Company Name: Lriptddh Bhybugb
  • Product Version: 98.78.16.10

The binary presents a layer of UPX compression.

Section Header is composed as usual by the following sections:

  • .UPX0
  • .UPX1
  • .rsrc

Code Entry Point is located at 000358E0 inside UPX1 section, ImportTable and Resources Directory are both placed into rsrc.

Preliminary Analysis

As you have seen from the previous paragraph the binary is packed with UPX, so the first obvious operation should be the usual unpacking.

But let’s see what happens to the unpacked code, here is the Original Entry Point:

.text:004218A4 neg ecx
.text:004218A6 or eax, eax
.text:004218A8 jz loc_418615

As you can see, the start code is quite atypical, we have a conditional check, in our case jump is taken, this lead us to the following piece of code

.text:00418615 loc_418615:
.text:00418615                 neg     esi
.text:00418617                 inc     eax
.text:00418618                 retn         ; ExitProcess()

Aim is clear, eax drives the call flow, in this way we have a sort of Unpacking Awareness. Let’s considerate the alternative branch solution, in other words we assume a NON zero value for EAX. Test can be quickly done by using IDA x86 Emulator plugin.

EAX has a dummy value, now we can see that application correctly flows into a second layer of decryption. Following the way of manually changing register value is not secure, because entire stack and register values could affect the correct code flow o successive decryption stages. This implies that would be a good practice to follow code of the UPX packed sample.

The picture above shows UPX packed structure of the executable, it’s also pretty trivial to identify in the last block the jmp to the OEP, alias the previously seen code.

In this way, we are now able to continue the code flow analysis without the risk of incongruences. Here also a view of the second layer call flow.

We will keep an eye on the evolution of the code flow during the various decryption layers.

.text:004218BD                 db    0
.text:004218BE                 db    0
.text:004218BF                 db    0
.text:004218C0                 neg     esi
.text:004218C2                 adc     ecx, esi
.text:004218C4                 sbb     ecx, edi
.text:004218C6                 inc     edx
.text:004218C7                 dec     esi
.text:004218C8                 inc     ecx
.text:004218C9                 db    0
.text:004218CA                 db    0

We meet here a very long sequence of 0 opcodes and repeated pieces of code as you can see above.

Code can be seen from two points of view now:

* Direct Analysis
* Higher Abstraction Level

Second point implies some assumption to be done, this allow us to see the code from an higher perspective. Assuming that there are no pieces of SMC code, to break the flow we could have:

* Jumps
* RETs

Further observation will confirm the presence of a final jump, code is structure as follow:

  • Zero_Opcode_Padding
  • Real_Code
  • Zero_Opcode_Padding
  • Jmp to the Next Block

What we gain from this pattern? should be easy to understand, how to speed up debugging process by looking directly for jmp instruction. For some people this could be an obvious observation, here I wanted to show the process that lead us to such conclusions.

After traversing all these chained blocks we land to the following piece of code:

.text:0041AE3D                 push    ebp
.text:0041AE3E                 mov     ebp, esp
.text:0041AE40                 sub     esp, 28h
.text:0041AE43                 lea     edx, [ebp+var_18]
.text:0041AE46                 push    edx
.text:0041AE47                 push    6241726Bh
.text:0041AE4C                 push    eax
.text:0041AE4D                 push    [ebp+var_8]
.text:0041AE50                 push    6B4E4144h
.text:0041AE55                 lea     edx, [ebp+var_14]
.text:0041AE58                 push    edx
.text:0041AE59                 push    [ebp+var_4]
.text:0041AE5C                 push    offset dword_426938
.text:0041AE61                 push    [ebp+var_1C]
.text:0041AE64                 push    ecx
.text:0041AE65                 call    sub_42C19C
.text:0041AE6A                 add     eax, ebx
.text:0041AE6C                 add     esp, 1610h
.text:0041AE72                 sub     eax, ecx
.text:0041AE74                 adc     eax, ecx
.text:0041AE76                 jmp     loc_41A435  ; Next Block

Due to the change of code structure we can identify here a Third Layer of Decryption. Respect to the previous block we have an additional element, that affects code flow, is the CALL. The code that follows is composed by several nested calls.

After that bundle of calls, we can see some api call performed in the following way:

RETN ; GetModuleHandleW
LEAVE
RETN ; True RET

Function GetModuleFileNameW is called indirectly. In the same way is called a VirtualAlloc that will host another decryption layer, with a new kind of obfuscation.

003B4BE8    55              PUSH EBP
003B4BE9    8BEC            MOV EBP,ESP
003B4BEB  ^ E9 5AFEFFFF     JMP 003B4A4A
..
003B13FE    03E0            ADD ESP,EAX
003B1400    E9 0B3D0000     JMP 003B5110
..
003B1B3B    32EE            XOR CH,DH
003B1B3D    BB A0860100     MOV EBX,186A0
003B1B42    E9 0C070000     JMP 003B2253
..
003B53E5    0BDB            OR EBX,EBX
003B53E7  ^ E9 63C3FFFF     JMP 003B174F
..
003B0448    0F85 53380000   JNE 003B3CA1
003B044E    E9 58060000     JMP 003B0AAB

The structure is pretty clear:

  • Real_Code
  • Jmp
  • Real_Code
  • Jmp

Following a block of code like this could be a bit messy, especially on jmp based loops, in that case just locate:

  • Conditional_Jump
  • Jmp

and place a breakpoint on Jmp.

This was the last spaghetti code layer, finally we land to the unpacked and active infection layer.

Core Infection

0040F860    55              PUSH EBP
0040F861    8BEC            MOV EBP,ESP
0040F863    81EC 18020000   SUB ESP,218
0040F869    E8 82590000     CALL 004151F0
0040F86E    68 04010000     PUSH 104
0040F873    8D85 F0FDFFFF   LEA EAX,[EBP-210]
0040F879    50              PUSH EAX
0040F87A    6A 00           PUSH 0
0040F87C    E8 8FBFFFFF     CALL 0040B810
0040F881    83C4 0C         ADD ESP,0C
0040F884    8D8D F0FDFFFF   LEA ECX,[EBP-210]
0040F88A    51              PUSH ECX
0040F88B    E8 F06CFFFF     CALL 00406580

This can be considered the True EntryPoint, in other words here starts the Infection Process.

Let’s see the call flow graph of the core infection executable:

As you can see from the above graph, structure of the malicious code can be divided in 4 regions, each one identified by a different color rectangle.

The most interesting thing that we can observe is that after the first region, we have a bifurcation of the code path, and finally a common ending region. The double path as you can see, does not have intersection points except Start and End regions. This means the code flow could take two different ways of execution. Without going too deep in explanation, we should formulate two basic questions in order to achieve a complete functional and technical understanding.

* What’s the condition that determine the path?
* What are the differences between the two path?

We can immediately identify who determines the path, simply by looking better at the final zone of the start region:

call sub_406240 affects the EAX value, that will influence the code flow.

The second question to be answered, obviously, implies that we need to debug both branches.

The main routine does not uses directly Function Addresses, we will meet always the following construct:

0040B813    51              PUSH ECX
0040B814    68 FE934377     PUSH 774393FE ; Hash Function Identifier
0040B819    6A 01           PUSH 1
0040B81B    6A 00           PUSH 0
0040B81D    E8 0EDFFFFF     CALL 00409730 ; Resolve Function
0040B822    83C4 0C         ADD ESP,0C
0040B825    8945 FC         MOV DWORD PTR SS:[EBP-4],EAX
0040B828    8B45 10         MOV EAX,DWORD PTR SS:[EBP+10]
0040B82B    50              PUSH EAX
0040B82C    8B4D 0C         MOV ECX,DWORD PTR SS:[EBP+0C]
0040B82F    51              PUSH ECX
0040B830    8B55 08         MOV EDX,DWORD PTR SS:[EBP+8]
0040B833    52              PUSH EDX
0040B834    FF55 FC         CALL DWORD PTR SS:[EBP-4] ; Call Function

We have an hash, given by the third parameter that identifies unequivocally the function that need to be called, call 00409730 returns the address of the specified function and successively is called. In this case we have a GetModuleFileNameW.

The core point of Carberp functionalities can be summarized in one call.

UPX0:0040F9DF                 call    sub_40A580      ; Code Injection
UPX0:0040F9E4                 add     esp, 4
UPX0:0040F9E7                 movzx   ecx, al
UPX0:0040F9EA                 test    ecx, ecx
UPX0:0040F9EC                 jnz     short loc_40FA1B
UPX0:0040F9EE                 mov     ds:dword_42B928, 0
UPX0:0040F9F8                 push    offset sub_40F810
UPX0:0040F9FD                 call    sub_40A5F0
UPX0:0040FA02                 add     esp, 4
UPX0:0040FA05                 movzx   edx, al
UPX0:0040FA08                 test    edx, edx
UPX0:0040FA0A                 jnz     short loc_40FA1B
UPX0:0040FA0C                 lea     eax, [ebp+var_210]
UPX0:0040FA12                 push    eax
UPX0:0040FA13                 call    sub_406470      ; ExitProcess

First call, contains entire code injection routine that will target explorer.exe

# explorer.exe path is resolved
# CreateProcess of explorer, with creation flag CREATE_SUSPENDED
# Create a Map View of the File
# Map View of the Section
# NtQueueApcThread
# NtResumeThread

At this point code injection is completed and dropper ends its function.

Catching the Injection

As previously seen, to continue infection Carberp performs an Injection by creating a suspended explorer.exe process and mapping successively a view. We obviously need to keep track of the injected code, but we are in front of a Child Process created by main carberp executable which resides in suspended state.

The situation we have pose two problems:

* The Process does not Appear in the Process List
* Problems in Attaching a Debugger

Here the plan, we reach NtResumeThread, so we are sure that all is ready for execution, patch the malicious injected code with a classical 0xEBFE which means an endless jump over itself, and finally let the process run. The process will be now running, and available into the process list like every other process, both problems posed above are now solved.

But, how we can know the address where to inject our ‘EBFE’ ? As you have previously seen the third parameter of ZwMapViewOfSection is BaseAddress, a pointer to a variable that receives the base address of the view.

Keeping an eye over this variable, at NtResumeThread we have the correct value where to place the patch. We can use Olly Advanced plugin ( Process Patcher ) to apply our modifications, here a screenshot:

Now process is ready to be resumed and debugged, so we can execute NtResumeThread. This is the situation seen from Process Explorer:

The second explorer as you can see produces an high consumption of CPU, this is caused by the endless loop we placed on the top of the code. We can now attach a debugger to the process, we land here:

0009F810    EB FE           JMP SHORT 0009F810
0009F812    EC              IN AL,DX
0009F813    E8 D8590000     CALL 000A51F0
0009F818    833D 28B94200 0 CMP DWORD PTR DS:[42B928],0
0009F81F    74 2D           JE SHORT 0009F84E
0009F821    C705 28B94200 0 MOV DWORD PTR DS:[42B928],0
0009F82B    68 10F84000     PUSH 40F810
0009F830    E8 BBADFFFF     CALL 0009A5F0
0009F835    83C4 04         ADD ESP,4
0009F838    0FB6C0          MOVZX EAX,AL
0009F83B    85C0            TEST EAX,EAX
0009F83D    75 05           JNE SHORT 0009F844
0009F83F    E8 2CFFFFFF     CALL 0009F770
0009F844    6A 01           PUSH 1
0009F846    E8 151CFFFF     CALL 00091460
0009F84B    83C4 04         ADD ESP,4
0009F84E    E8 1DFFFFFF     CALL 0009F770
0009F853    33C0            XOR EAX,EAX
0009F855    5D              POP EBP
0009F856    C2 0400         RETN 4

Now we can restore the original bytes -> 0x558B but before committing the patch we have to place a breakpoint in the location immediately after the Prelude, or the code will run automatically immediately after changing the bytes.

The freshly injected code, drops a copy of the main dropper (the packed one) into automatic execution directory under the name of igfxtray.exe. Code performs also api hooking (presented in the next paragraph) and completes injection by downloading and decrypting configuration and plugins.

Revealing Hooks via Windbg

We can use WinDbg to discover hooks installed by Carberp in a very easy way. As you have seen, the trojan injects code into Explorer.exe process, this implies that in explorer.exe address space we will have traces of infection, a Full Dump can be taken via Process Explorer.

At this point we can enumerate all module and look for differences between functions in the dump and relative symbol in the following way:

> !for_each_module !chkimg @#ModuleName -d

Here what we have

DBGHELP: C:\WinDDK\7600.16385.1\Debuggers\sym\wininet.dll\41252C1Ba7000\wininet.dll - OK

77194ac5-77194ac9 5 bytes - wininet!HttpOpenRequestA

[ 8b ff 55 8b ec:e9 06 69 f7 89 ]

771961dc-771961e0 5 bytes - wininet!InternetCloseHandle (+0x1717)

[ 8b ff 55 8b ec:e9 5f 51 f7 89 ]

771976b8-771976bc 5 bytes - wininet!HttpSendRequestA (+0x14dc)

[ 8b ff 55 8b ec:e9 03 3b f7 89 ]

77199555-77199559 5 bytes - wininet!InternetReadFile (+0x1e9d)

[ 8b ff 55 8b ec:e9 26 1d f7 89 ]

771a325f-771a3263 5 bytes - wininet!InternetQueryDataAvailable (+0x9d0a)

[ 8b ff 55 8b ec:e9 ac 80 f6 89 ]

771a53eb-771a53ef 5 bytes - wininet!HttpSendRequestExW (+0x218c)

[ 8b ff 55 8b ec:e9 60 5e f6 89 ]

771a6345-771a6349 5 bytes - wininet!HttpOpenRequestW (+0xf5a)

[ 8b ff 55 8b ec:e9 c6 50 f6 89 ]

771c7e9a-771c7e9e 5 bytes - wininet!InternetReadFileExA (+0x21b55)

[ 8b ff 55 8b ec:e9 11 34 f4 89 ]

771c88d6-771c88dd 8 bytes - wininet!InternetWriteFileExW (+0xa3c)

[ 6a 78 ff 15 34 14 18 77:e9 05 2a f4 89 90 90 90 ]

771e1808-771e180c 5 bytes - wininet!HttpSendRequestW (+0x18f32)

[ 8b ff 55 8b ec:e9 e3 99 f2 89 ]

771e190d-771e1911 5 bytes - wininet!HttpSendRequestExA (+0x105)

[ 8b ff 55 8b ec:e9 0e 99 f2 89 ] 58 errors : wininet (77194ac5-771e1911)

Meaning should be clear, wininet modules presents some ‘errors’, more specifically some differences between functions in memory and the ones used as symbols.

Let’s inspect the code of HttpOpenRequestA

0:000> u 77194ac5
wininet!HttpOpenRequestA:
77194ac5 e90669f789      jmp     0110b3d0
77194aca 83ec5c          sub     esp,5Ch
77194acd a1189a2077      mov     eax,dword ptr [wininet!__security_cookie (77209a18)]
77194ad2 8945fc          mov     dword ptr [ebp-4],eax
77194ad5 8b4510          mov     eax,dword ptr [ebp+10h]
77194ad8 8945c0          mov     dword ptr [ebp-40h],eax
77194adb 8b4514          mov     eax,dword ptr [ebp+14h]
77194ade 8945c4          mov     dword ptr [ebp-3Ch],eax

As you can see, first instruction is a jump to a suspicious location, this piece of code clearly demonstrates the presence of an hook. We can know more about this location

0:000> !address 0110b3d0
Usage:                  <unclassified>
Allocation Base:        00000000
Base Address:           01100000
End Address:            0112d000
Region Size:            0002d000
Type:                   00000000
State:                  00000000
Protect:                00000000

In this way we know where Starts and Ends the piece of code responsible of handling hooks. These are two precious informations, especially the first one, because we have a range where to look for memory mapped executables.

0:000> s -a 01100000 l0112d000/4 "MZ"
01100000  4d 5a 90 00 03 00 00 00-04 00 00 00 ff ff 00 00  MZ..............

The presence of “MZ” obviously is Necessary but NOT Sufficient condition to say that this is an executable, we need more proofs. These can be obtained by checking the validity of executable presumably located at 01100000.

File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
     14C machine (i386)
       4 number of sections
4DD1BAAC time date stamp Tue May 17 02:00:44 2011

       0 file pointer to symbol table
       0 number of symbols
      E0 size of optional header
     102 characteristics
            Executable
            32 bit word machine

This is an Executable. Now let’s suppose that we want to carve it from memory, how to do ?

0:000> .writemem carved_from_explorer 01100000 0112d000 Writing 2d001 bytes....

The injected executable contains Hook Handlers and Routines to Deal with Captured data.

Carberp Analysis via Volatility

Identification of the System

# python vol.py imageinfo -f carberp.dmp
Volatile Systems Volatility Framework 2.1_alpha
Suggested Profile(s) : WinXPSP3x86, WinXPSP2x86 (Instantiated with WinXPSP2x86)
AS Layer1 : JKIA32PagedMemory (Kernel AS)
AS Layer2 : FileAddressSpace (/home/.../carberp.dmp)
PAE type : No PAE
DTB : 0x39000
KDBG : 0x8054c760L
KPCR : 0xffdff000L
KUSER_SHARED_DATA : 0xffdf0000L
Image date and time : 2011-09-24 15:18:26
Image local date and time : 2011-09-24 15:18:26
Number of Processors : 1
Image Type : Service Pack 2

We are dealing with a Windows XP on x86 Platform with Service Pack 2.

Process Enumeration

# python vol.py pslist -f carberp.dmp

Volatile Systems Volatility Framework 2.1_alpha
Offset(V)  Name                 PID    PPID   Thds   Hnds   Time 
---------- -------------------- ------ ------ ------ ------ ------------------- 
0x812ed020 System                    4      0     54    255 1970-01-01 00:00:00       
0xffb43020 smss.exe                368      4      3     21 2011-09-24 14:14:38       
0xffb9ada0 csrss.exe               584    368     11    375 2011-09-24 14:14:39       
0xffb8f488 winlogon.exe            608    368     18    438 2011-09-24 14:14:39       
0x811b42e0 services.exe            652    608     15    255 2011-09-24 14:14:39       
0x811655d0 lsass.exe               664    608     20    333 2011-09-24 14:14:39       
0xffafb560 VBoxService.exe         824    652      8    107 2011-09-24 14:14:40       
0xffaf42a0 svchost.exe             868    652     20    201 2011-09-24 14:14:40       
0xffb01980 svchost.exe             956    652      9    228 2011-09-24 14:14:40       
0xffaeda18 svchost.exe            1052    652     61   1138 2011-09-24 14:14:41       
0xffae5458 svchost.exe            1112    652      6     91 2011-09-24 14:14:41       
0xffb60da0 svchost.exe            1172    652     13    204 2011-09-24 14:14:42       
0xffb6eca8 explorer.exe           1480   1404     14    355 2011-09-24 14:14:43       
0xffae41c8 spoolsv.exe            1604    652     11    110 2011-09-24 14:14:44       
0xffaef788 alg.exe                 500    652      5    101 2011-09-24 14:14:59
0xffb2ea78 ctfmon.exe              540   1480      1     66 2011-09-24 14:14:59       
0xffb31650 wscntfy.exe             588   1052      1     36 2011-09-24 14:15:00
0xffaef020 svchost.exe            1132   1480      4     58 2011-09-24 15:17:32       
0x811bcd60 svchost.exe             984   1480      1     39 2011-09-24 15:17:32       
0xffb53da0 svchost.exe            1212   1480      0 ------ 2011-09-24 15:17:32       
0x811ea258 firefox.exe            1332   1480     25    272 2011-09-24 15:17:45

These informations are enough to make some speculation and obtain an investigation direction.

As you can see we have various svchost.exe processes, the first 4 have a Parent PID (652) that belongs to services.exe PID (652) with a time of 14:14:40/41/42.

Successively you can see other 3 svchost.exe processes, but this time Parent PID is different (1480) that belongs to explorer.exe (PID= 1480), additionally these processes have the same Timing 15:17:32.

This basically means that there are some implications connected to explorer.exe that needs further investigations.

Due to the fact that our suspects are on svchost.exe, actively involved into network activity of a system, let’s scan physical memory for _TCPT_OBJECT objects (tcp connections) via

# python vol.py connscan -f carberp.dmp

Volatile Systems Volatility Framework 2.1_alpha
Offset(P) Local Address Remote Address Pid
---------- ------------------------- ------------------------- ------
0x0106b6e0 10.0.2.15:1056 192.168.127.220:80 984
0x010a3008 10.0.2.15:1054 192.168.127.220:80 1212
0x01108008 10.0.2.15:1050 63.245.209.93:80 1332
0x028ab008 10.0.2.15:1050 63.245.209.93:80 1332
0x03656568 127.0.0.1:1049 127.0.0.1:1048 1332
0x03d9e9e8 10.0.2.15:1058 192.168.127.220:80 1132
0x03de2008 127.0.0.1:1048 127.0.0.1:1049 1332
0x03e26598 10.0.2.15:1051 63.245.209.93:80 1332
0x06a1ac10 10.0.2.15:1059 195.184.86.34:80 1132
0x06a65008 127.0.0.1:1047 127.0.0.1:1046 1332
0x06a66008 10.0.2.15:1052 213.92.11.90:80 1332
0x07a13b58 127.0.0.1:1046 127.0.0.1:1047 1332
0x08a33008 127.0.0.1:1047 127.0.0.1:1046 1332
0x0acd0008 127.0.0.1:1047 127.0.0.1:1046 1332

As you can see activity pertains mainly to Firefox (PID: 1332); we have also PID 984 and 1212 (suspect svchost) that aren’t of great help and finally

0x06a1ac10 10.0.2.15:1059 195.184.86.34:80 1132

Where we have an interesting IP that belongs to a suspect svchost.

Looking for 195.184.86.34 lead us to an interesting result:

the IP is malicious, belongs to Carberp ( 08C01BBE430F9FEA1A532DFD13F2836A )

Proven that svchost is malicious, due to its strict relationship with explorer.exe we are allowed to think that Carberp performed code injection.

Here comes a great and really handy plugin for Volatility called malfind.

# python vol.py malfind -f carberp.dmp -p 1480 -D /home/../vol_dumps

Name Pid Start End Tag Hits Protect
explorer.exe 1480 0x01a70000 0x1a70fff0 VadS 0 PAGE_EXECUTE_READWRITE
Dumped to: /home/../vol_dumps/explorer.exe.7585ca8.01a70000-01a70fff.dmp
0x01a70000 8b ff 55 8b ec e9 a9 e2 2a 76 00 00 00 00 00 00 ..U.....*v......
0x01a70010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a70020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a70030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a70040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a70050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a70060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a70070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

Disassembly:
01a70000: 8bff MOV EDI, EDI
01a70002: 55 PUSH EBP
01a70003: 8bec MOV EBP, ESP
01a70005: e9a9e22a76 JMP 0x77d1e2b3
01a7000a: 0000 ADD [EAX], AL
01a7000c: 0000 ADD [EAX], AL
01a7000e: 0000 ADD [EAX], AL
01a70010: 0000 ADD [EAX], AL
01a70012: 0000 ADD [EAX], AL
01a70014: 0000 ADD [EAX], AL

explorer.exe 1480 0x01a00000 0x1a00fff0 VadS 0 PAGE_EXECUTE_READWRITE
Dumped to: /home/../vol_dumps/explorer.exe.7585ca8.01a00000-01a00fff.dmp
0x01a00000 8b ff 55 8b ec e9 d7 61 79 75 00 00 00 00 00 00 ..U....ayu......
0x01a00010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a00020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a00030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a00040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a00050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a00060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x01a00070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

Disassembly:
01a00000: 8bff MOV EDI, EDI
01a00002: 55 PUSH EBP
01a00003: 8bec MOV EBP, ESP
01a00005: e9d7617975 JMP 0x771961e1
01a0000a: 0000 ADD [EAX], AL
01a0000c: 0000 ADD [EAX], AL
01a0000e: 0000 ADD [EAX], AL
01a00010: 0000 ADD [EAX], AL
01a00012: 0000 ADD [EAX], AL
01a00014: 0000 ADD [EAX], AL

malfind automatically locates and extract suspicious memory regions ( injected code ); dumped content is placed into /vol_dump, you must create an output directory for malfind.

Besides all the entries printed out during scan process let’s check the first entry saved into /vol_dump, explorer.exe.7585ca8.00e20000-00e5afff.dmp

Start Address is 0x00e20000, here its content

0x00e20000 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZ..............
0x00e20010 b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@.......
0x00e20020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0x00e20030 00 00 00 00 00 00 00 00 00 00 00 00 c8 00 00 00 ................
0x00e20040 0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 ........!..L.!Th
0x00e20050 69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f is.program.canno
0x00e20060 74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 t.be.run.in.DOS.
0x00e20070 6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 mode....$.......
0x00e20080 da 83 9c 2b 9e e2 f2 78 9e e2 f2 78 9e e2 f2 78 ...+...x...x...x
0x00e20090 b9 24 89 78 9b e2 f2 78 9e e2 f3 78 88 e2 f2 78 .$.x...x...x...x
0x00e200a0 80 b0 76 78 a2 e2 f2 78 80 b0 63 78 9f e2 f2 78 ..vx...x..cx...x
0x00e200b0 52 69 63 68 9e e2 f2 78 00 00 00 00 00 00 00 00 Rich...x........
0x00e200c0 00 00 00 00 00 00 00 00 50 45 00 00 4c 01 04 00 ........PE..L...
0x00e200d0 78 8b f6 4d 00 00 00 00 00 00 00 00 e0 00 0f 01 x..M............
0x00e200e0 0b 01 09 00 00 70 02 00 00 10 01 00 00 00 00 00 .....p..........
0x00e200f0 80 a5 01 00 00 10 00 00 00 80 02 00 00 00 40 00 ..............@.

Let’s take a list of the strings that appears into the executable

#strings explorer.exe.7585ca8.00e20000-00e5afff.dmp >> Rapport has been found! Trying to kill...
C:\anti_rapport_dll.dll
..
/cfg/stopav.plug
/cfg/miniav.plug
..
GET /stat?uptime=%d&downlink=%d&uplink=%d&id=%s&statpass=%s&comment=%s HTTP/1.0
>>>>>> Inject URL=%s
...

These strings clearly indicates that malfind correctly catched the malicious executable injected.

It’s important to say that in this phase of analysis VAD (Virtual Address Descriptor) could give pretty interesting hints. We have four plugins that deals with VAD vadwalk, vadinfo, vadtree, vaddump. Let’s see usage of vadinfo

# python vol.py vadinfo -f carberp.dmp -p 1480
VAD node @81137098 Start 00e20000 End 00e5afff Tag VadS
Flags: MemCommit, PrivateMemory
Commit Charge: 59 Protection: 6

The VAD entry I’ve chosen to show belongs to the memory range in which stands the executable previously carved, as you can see informations indicates a Protection of 6 belongs PAGE_EXECUTE_READWRITE.

As we know, Carberp is a Banking trojan which performs Web Code Injections, this means that we should find traces of its presence into the Browser Process.

# python vol.py apihooks -f carberp.dmp -p 1332

Volatile Systems Volatility Framework 2.1_alpha
Name Type Target Value
firefox.exe[1332] inline nspr4.dll!PR_Close[0x375bc0L] 0x375bc0 JMP 0x15f0f0 (UNKNOWN)
firefox.exe[1332] inline nspr4.dll!PR_DestroyPollableEvent[0x375bc0L] 0x375bc0 JMP 0x15f0f0 (UNKNOWN)
firefox.exe[1332] inline nspr4.dll!PR_OpenTCPSocket[0x389a50L] 0x389a50 JMP 0x15f140 (UNKNOWN)
firefox.exe[1332] inline nspr4.dll!PR_Read[0x373160L] 0x373160 JMP 0x15ef30 (UNKNOWN)
firefox.exe[1332] inline nspr4.dll!PR_Write[0x373170L] 0x373170 JMP 0x15f000 (UNKNOWN)
firefox.exe[1332] syscall ntdll.dll!NtAcceptConnectPort[0x7c91d379L] 0x7ffe0300 MOV EDX, 0x7ffe0300 (UNKNOWN)
firefox.exe[1332] syscall ntdll.dll!NtAccessCheck[0x7c91d38eL] 0x7ffe0300 MOV EDX, 0x7ffe0300 (UNKNOWN)
firefox.exe[1332] syscall ntdll.dll!NtAccessCheckAndAuditAlarm[0x7c91d3a3L] 0x7ffe0300 MOV EDX, 0x7ffe0300 (UNKNOWN)
firefox.exe[1332] syscall ntdll.dll!NtAccessCheckByType[0x7c91d3b8L] 0x7ffe0300 MOV EDX, 0x7ffe0300 (UNKNOWN)
firefox.exe[1332] syscall ntdll.dll!NtAccessCheckByTypeAndAuditAlarm[0x7c91d3cdL] 0x7ffe0300 MOV EDX, 0x7ffe0300 (UNKNOWN)
firefox.exe[1332] syscall ntdll.dll!NtAccessCheckByTypeResultList[0x7c91d3e2L] 0x7ffe0300 MOV EDX, 0x7ffe0300 (UNKNOWN)
...

As you can see first 5 entries are classical inline hooks on the most common APIs used to intercept and modify user’s browsing activity. Successively we have some ‘syscall’ hooking type, further investigations can be done by using another Volatility plugin, called volshell plugin.

Inline hook Sample

# python vol.py volshell -f carberp.dmp
Volatile Systems Volatility Framework 2.1_alpha
Current context: process System, pid=4, ppid=0 DTB=0x39000
Welcome to volshell! Current memory image is:
file:///home/../carberp.dmp
To get help, type 'hh()'
>>> cc(pid=1332)
Current context: process firefox.exe, pid=1332, ppid=1480 DTB=0x2c4e000
>>> dis(0x375bc0)
0x375bc0 e92b95deff JMP 0x15f0f0
0x375bc5 90 NOP
0x375bc6 89442404 MOV [ESP+0x4], EAX
0x375bca 8b5104 MOV EDX, [ECX+0x4]
0x375bcd ffe2 JMP EDX
0x375bcf cc INT 3
0x375bd0 8b442404 MOV EAX, [ESP+0x4]
0x375bd4 8b4804 MOV ECX, [EAX+0x4]
0x375bd7 8b01 MOV EAX, [ECX]
0x375bd9 8b10 MOV EDX, [EAX]
0x375bdb 6a01 PUSH 0x1
0x375bdd 68c93a3900 PUSH DWORD 0x393ac9
0x375be2 50 PUSH EAX
0x375be3 8b420c MOV EAX, [EDX+0xc]
0x375be6 ffd0 CALL EAX
0x375be8 83e801 SUB EAX, 0x1
0x375beb 83c40c ADD ESP, 0xc
0x375bee f7d8 NEG EAX
0x375bf0 1bc0 SBB EAX, EAX
0x375bf2 c3 RET

Syscall Hook Sample

>>> dis(0x7c91d379)
0x7c91d379 b800000000 MOV EAX, 0x0
0x7c91d37e ba0003fe7f MOV EDX, 0x7ffe0300
0x7c91d383 ff12 CALL DWORD [EDX]
0x7c91d385 c21800 RET 0x18
0x7c91d388 90 NOP
0x7c91d389 90 NOP

Where 0x7FFE0300 is a pointer to KiFastSystemCall

Further informations here http://www.honeynet.org/node/578

Now we can check for Registry and FileSystem presence of Carberp in the victim system.

Usually malicious applications uses registry to ensure survival (malware execution) on system restart.

This can be done via printkey plugin in the following way.

# python vol.py printkey -f carberp.dmp -K &quot;Software\Microsoft\Windows\CurrentVersion\Run&quot;
Volatile Systems Volatility Framework 2.1_alpha
Legend: (S) = Stable (V) = Volatile

----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\-\NTUSER.DAT
Key name: Run (S)
Last updated: 2011-09-24 11:45:07

Subkeys:

Values:
REG_SZ CTFMON.EXE : (S) C:\WINDOWS\system32\ctfmon.exe
----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\NetworkService\NTUSER.DAT
Key name: Run (S)
Last updated: 2011-09-24 06:31:50

Subkeys:

Values:
REG_SZ CTFMON.EXE : (S) C:\WINDOWS\System32\CTFMON.EXE
----------------------------
Registry: \Device\HarddiskVolume1\Documents and Settings\LocalService\NTUSER.DAT
Key name: Run (S)
Last updated: 2011-09-24 06:31:50

Subkeys:

Values:
REG_SZ CTFMON.EXE : (S) C:\WINDOWS\System32\CTFMON.EXE

We have only ctfmon.exe as entry, nothing interesting, we can now look directly into the filesystem for some suspicious entry. This can be accomplished by using filescan plugin that enumerates _FILE_OBJECT pool allocations.

# python vol.py filescan -f carberp.dmp | grep automatica

Volatile Systems Volatility Framework 2.1_alpha
0x01114948 1 1 R--r-- '\\Documents and Settings\\-\\Menu Avvio\\Programmi\\Esecuzione automatica\\igfxtray.exe'
0x023b8948 1 1 R--r-- '\\Documents and Settings\\-\\Menu Avvio\\Programmi\\Esecuzione automatica\\igfxtray.exe'
0x08f50180 1 0 -WD--- '\\Documents and Settings\\-\\Menu Avvio\\Programmi\\Esecuzione automatica\\igfxtray.exe'

igfxtray.exe it’s exactly the name that Carberp uses to copy itself into automatic execution directory.

Conclusion

According to the title, the main scope of this blog post, is not a complete functional analysis (that will be covered in another one) but a simple view of the ‘problem carberp’ under a reverse engineering point of view.