By

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:

Restore the original API code. 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

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:

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:

Establish if the process is a browser (Firefox or Internet Explorer) or not (Explorer.exe). 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.

: 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:

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:

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:

There are five basic regions:

Magic value. Encryption type (used to understand how to unpack the httpinject). CRC check value. Decryption key . 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:

Second example of WebInject:

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:

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:

In synthesis we can carve the following information:

C&C has /ping.html and /ping.html?r=random_value

and 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:

The 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.

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 :).