The Torpig (aka Sinowal) bot


Welcome back,

This morning I came across a variant of the Torpig bot (aka Sinowal) and since it’s a beautiful Saturday morning I though it’s a good opportunity to write a few word about it.

I found the sample while hunting for stuff on VirusTotal and looks it was first submitted on 2019-01-08 13:54:40. Is this a new variant?


Let’s look over it.



Looking statically over the file’s header, it seems to be packed using UPX, but this is not backup by what I’m seeing in the EntryPoint of the PE and also the IAT. The first call on the left side of the picture with 4 pushes before it might be the Main function. Following the call I see a lot of API calls and other malicious functionalities. Usually UPX has a few imports, one big routine with a JMP instruction at the end to a blank memory space. None of that is present here, but the file is not packed.


One of the first things I do after I open up IDA is to execute two simple IDAPython scripts that I wrote to ease analysis:

  • – looks over the IAT, compares it with a list of APIs that I’m interested in and it adds breakpoints on every call seen in the code towards the APIs.
  • –  searches for some x86 instructions that are used for detecting the presence of a VM and spits out a log in the Output window. This is not an accurate script, it just pinpoints possible techniques.

The results from the script are displayed in the Breakpoints window.


Looks like the PE creates a mutex, writes some files on disk along with windows registries and creates new processes.

The second script points to the sidt x86 instruction, this instruction can be used to store the IDT base address to a specific CPU register and check it later against a known default value. Because the malicious process is ran in a virtualised Windows OS the CPU has to keep track of multiple IDTs and this is achieved by storing the VM’s IDT at a different address rather than the default one seen on the bear metal running OS. You can find a more in depth explanation here.


Dereferencing the function will point the cursor back to the Main function. After the VM check is done in the previous routine, EAX is being tested and if it’s set to 0x01 the jump is not taken and execution continues with two more calls and a final jump to the end of the code, thus exiting the process. If the VM check returns with EAX=0x00, the next jump is taken and the next instruction to be called is the WinAPI IsDebuggerPresent. This API just checks the second byte from the PEB structure and return it’s value (0x01 debugger attached). This check can easily be patched by reseting the value from PEB+0x02.


These are the only two anti-reversing tricks seen in the binary, pretty easy ones but still effective in most cases.

The code continues by deobfuscating several strings with the help of a subroutine from 0x004017F6, it just XORes the encrypted data with 0x44. Nothing fancy here. The function is called 10 times. I’ll paste all the deobfuscated strings at the end of the post.



The decrypted strings are used to create a mutex, enable persistence and write some binaries to some paths on disk.

Execution continues by creating a mutex. If an ERROR_ALREADY_EXISTS is returned it means that another process is already running and the current one will stop execution.


Later, 6 iterations are done to decrypt 6 data blobs, 4 of which are PEs and these are written to the disk at some paths I’ll paste at the end of the blogpost (including hashes), and one lucky PE is chosen to spawn a new process from.



The process is close to termination, but has one last action to do before releasing the mutex and closing execution. That action is achieving persistence in the OS by writing a couple of registries that point to the newly written PEs on disk.



I’ll continue the analysis in this post, since there’s not a lot to add and this malware is not a new version. I don’t think it’s worth creating another post for it.

Let’s look over the second stage of the bot, the “ibm00001.exe” file. The role of this executable is to load the DLL named “ibm00001.dll”, call the “Eval” routine, wait for it to return and terminate execution. Also, keep in mind that the “DLLEntryPoint” of the DLL will be executed when the binary is loaded into memory by LoadLibrary. You can read more about how DLLs work over here on MSDN. This is an important aspect to know because part of the functionality from our DLL is ran in DLLMain.


I’ll now jump into IDA, disassemble the DLL and dissect the EntryPoint and the exported “Eval” routine.

In the export table of this DLL we can see 6 exported functions:

  • “DLLEntryPoint”
  • “Eval”
  • “Fixmode”
  • “RemoteLoadLibraryA”
  • “RemoteGetModuleHandleA”
  • RemoteFreeLibrary


Export Table of ibm00001.dll:


This routine just calls the “DLLMain” subroutine which does the following actions:

  • check if a debugger is attached, if yes, then exit
  • check if the process is running inside a VM by using the SIDT x86 instruction, if yes, then exit
  • checks availability of the “cookies” folder (“c:\Users\\Cookies\”)
  • deobfuscates multiple strings, including some filenames and domains. Get the IDAPy script from here and the decoded strings
  • calculates a MD5 value out of the computer name
  • resolves several Win APIs, these are not seen referenced anywhere in the code…
  • opens a Mutex and a Event
  • creates a new thread
    • writes a file on disk containing an ID (“C:\Windows\Temp\$_2341235.TMP”)
    • creates several mutants and filemappings out of the deobfuscated strings
    • gets location info. Checks for “Russia”, “China” or “other”
    • gathers computer information
    • creates a URL composed with computer details and does a HTTP request to register the bot on the C&C



  • checks for debugger and VM
  • calls one of these two exported function and both of them call the subroutine from offset 0x13E2:
    • “RemoteLoadLibraryA” (ordinal 3)
    • “RemoteGetModuleHandleA” (ordinal 2)

RemoteLoadLibraryA / RemoteGetModuleHandleA:

  • creates a mutex: “{6A5FB623-82F2-4852-A484-753A569E02CA}”
  • installs a low level hook procedure on all existing threads using SetWindowsHookEx“. 
    • hook
  • the hook routine:
    • AntiVM and AntiDbg tricks
    • Deobfuscates the “FixMode” exported function name
    • Resolves the pointer to “FixMode” and calls the function


The main functionality of this malware is embedded mainfuncFixmodein this exported function. Dereferencing any of the interesting strings and generating a graph of cross-references will have at the top the FixMode routine, thus all that needs to be done now is to reverse the logic of all subroutines under FixMode.  Some of these functionalities are done via separate threads.

  • Gathers all kind of credentials (ftp, email, etc) stored in registries and files from different applications (Ak-Mail, Thuderbird, Eudora, TotalCommander, FAR, etc)
  • Enumerates through installed browsers (“mozilla”, “iexplore”, “opera”) to dump passwords
  • Monitors activity from security software with the following windows titles and tries to close them:
    • “Warning: Components Have Changed”
    • “Hidden Process Requests Network Access”
    • “Windows Security Alert”
    • “Allow all activities for this application”
    • “Remember this answer the next time I use this program.
    • “PermissionDlg
  • AntiDebugger and AntiVM tricks scattered in different parts of the code
  • Creates different events or mutexes (see the IOC section)
  • Helps out the initiated threads by sleeping random time intervals
  • Loads the “ibm00002.dll” DLL and calls the “Fire” exported function
  • Connects to different domains to export the collected data (see IOC section)


This is a multi-stage bot that gathers credentials from the infected system and exfiltrates them to the C&C.

The first stage begins by checking if it’s running in a VM or debugger writes several other binaries on disk, achieves persistence and creates a new process that has the main logic of the bot.

The second stage uses the same antidbg and antivm tricks in different parts of the binary, if these pass successfully the bot creates multiple threads that are responsible for registering itself on the C&C, others collect credentials from the computer and others look for various security tools windows and tries to close them.

Looks like I kinda wasted my time on an old piece of code, written for old versions of the Windows OS (considering the deprecated API calls, searches for old software and no sign of Chrome being mentioned in the code).  I also googled for some IOCs, got to this post from Symantec posted in 2005…

Patch the anti-VM and anti-debugger tricks.

Since the antiVM and anti-debugger subroutines are called several times, it’s impractical to manipulate the registries every time, so it’s better to just patch the code.

  1. locate the antiVM subroutine and patch with a simple XOR EAX,EAX the instruction before RET
    • patchVM
  2. Press CTRL+G in the dump window of x86dbg, type PEB()+0x02 and modify that byte from 0x01 to 0x00. The “IsDebuggerPresent” goes into PEB at offset 0x02 and checks if that byte is set to 0x01 (debugger is attached).
    • peb



  • “{6A5FB623-82F2-4852-A484-753A569E02CA}”
  • “stsvcsmut”
  • “stsvcmut”


  • “stsvcsnd”
  • “stsvcevt”


  • “stsvcmem”


  • file analysed in the post
  • c:\Program Files (x86)\Common Files\microsoft shared\Web Folders\ibm00001.exe
  • c:\Program Files (x86)\Common Files\microsoft shared\Web Folders\ibm00001.dll
  • c:\Program Files (x86)\Common Files\microsoft shared\Web Folders\ibm00002.dll
  • c:\Program Files (x86)\Common Files\microsoft shared\Web Folders\ibm00003.exe
  • C:\Windows\temp
    • “$_3472452.EXE”
    • “$_2341234.TMP”
    • “$_2341233.TMP”
    • “$_2341235.TMP”


  • user-agent: “Mozilla/4.0”
  • “”
  • “”
  • “”
  • “”
  • “”
  • “gamma/c25.php”


  • HKLM\SOFTWARE\(Wow6432Node)\Microsoft\Windows NT\CurrentVersion\Winlogon\shell -> “C:\Program Files (x86)\Common Files\Microsoft Shared\Web Folders\ibm00001.exe”
  • HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -> “C:\Program Files (x86)\Common Files\Microsoft Shared\Web Folders\ibm00001.exe”



Decrypted strings from Stage 1:

[0x17,0x0B,0x02,0x10,0x13,0x05,0x16,0x01,0x18,0x09,0x2D0x27,0x36,0x2B,0x37,0x2B,0x22,0x30,0x18,0x13,0x2D,0x2A0x20,0x2B,0x33,0x37,0x64,0x0A,0x10,0x18,0x07,0x31,0x36,0x36,0x21,0x2A,0x30,0x12,0x21,0x36,0x37,0x2D,0x2B,0x2A] = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
[0x17,0x0B,0x02,0x10,0x13,0x05,0x16,0x01,0x18,0x09,0x2D0x27,0x36,0x2B,0x37,0x2B,0x22,0x30,0x18,0x13,0x2D,0x2A0x20,0x2B,0x33,0x37,0x18,0x07,0x31,0x36,0x36,0x210x2A,0x30,0x12,0x21,0x36,0x37,0x2D,0x2B,0x2A] = "SOFTWARE\Microsoft\Windows\CurrentVersion"
[0x18,0x09,0x2D,0x27,0x36,0x2B,0x37,0x2B,0x22,0x30,0x64,0x17,00x2C,0x25,0x36,0x21,0x20,0x18,0x13,0x21,0x26,0x64,0x02,0x2B,0x28,0x20,0x21,0x36,0x37] = "\Microsoft SFared\Web Folders"
[0x09,0x17,0x05,0x16,0x07,0x0C,0x1B,0x09,0x11,0x10,0x01,0x1C,0x1B,0x0A,0x05,0x09,0x01] = "MSARCH_MUTEX_NAME"
[0x21,0x3C,0x34,0x28,0x2B,0x36,0x21,0x36,0x6A,0x21,0x3C,0x21] = "explorer.exe"
[0x37,0x3D,0x37,0x30,0x21,0x29,0x6A,0x2D,0x2A,0x2D] = "system.ini"
[0x18,0x13,0x2D,0x2A,0x08,0x2B,0x23,0x2B,0x2A] = "\WinLogon"
[0x37,0x2C,0x21,0x28,0x28] = "shell"
[0x18,0x16,0x31,0x2A] = "\Run"
[0x26,0x2B,0x2B,0x30] = "boot"

Decrypted strings IBM00001.dll:

{0x37,0x30,0x37,0x32,0x27,0x37,0x30,0x29,0x21,0x29} = "stsvcstmem"
{0x37,0x30,0x37,0x32,0x27,0x37,0x29,0x31,0x30} = "stsvcsmut"
{0x37,0x30,0x37,0x32,0x27,0x37,0x30,0x29,0x21,0x29} = "stsvcstmem"
{0x2D,0x21,0x3C,0x34,0x28,0x2B,0x36,0x21} = "iexplore"
{0x29,0x2B,0x3E,0x2D,0x28,0x28,0x25} = "mozilla"
{0x2B,0x34,0x21,0x36,0x25} = "opera"
{0x37,0x30,0x37,0x32,0x27,0x37,0x29,0x31,0x30} = "stsvcsmut"
{0x13,0x2D,0x2A,0x2D,0x2A,0x21,0x30} = "Wininet"
{0x07,0x25,0x27,0x2C,0x21,0x07,0x36,0x21,0x20,0x21,0x2A,0x30,0x2D,0x25,0x28,0x37} = "CacheCredentials"
{0x7E,0x17,0x30,0x36,0x2D,0x2A,0x23} = ":String"
{0x7E,0x17,0x30,0x36,0x2D,0x2A,0x23,0x0D,0x2A,0x20,0x21,0x3C} = ":StringIndex"
{0x60,0x1B,0x77,0x70,0x73,0x76,0x70,0x71,0x76,0x6A,0x01,0x1C,0x01} = "$_3472452.EXE"
{0x60,0x1B,0x76,0x77,0x70,0x75,0x76,0x77,0x70,0x6A,0x10,0x09,0x14} = "$_2341234.TMP"
{0x60,0x1B,0x76,0x77,0x70,0x75,0x76,0x77,0x77,0x6A,0x10,0x09,0x14} = "$_2341233.TMP"
{0x60,0x1B,0x76,0x77,0x70,0x75,0x76,0x77,0x71,0x6A,0x10,0x09,0x14} = "$_2341235.TMP"
{0x29,0x30,0x26,0x2D,0x2A,0x22,0x2B,0x6A,0x36,0x31,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34} = ""
{0x2F,0x25,0x30,0x36,0x2D,0x2A,0x73,0x6A,0x27,0x2B,0x29,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34} = ""
{0x32,0x21,0x36,0x29,0x3D,0x30,0x73,0x6A,0x27,0x2B,0x29,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34} = ""

Decrypted strings IBM00002.dll:

[0x21,0x3C,0x34,0x28,0x2B,0x36,0x21,0x36,0x6A,0x21,0x3C,0x21] = "explorer.exe"
[0x1B,0x2D,0x26,0x29] = "_ibm"
[0x1B,0x21,0x3C,0x34,0x2D,0x2B,0x36,0x21,0x36] = "_expiorer"
[0x7C,0x71,0x6A,0x76,0x70,0x7D,0x6A,0x76,0x77,0x6A,0x7C,0x76] = ""
[0x31,0x37,0x76,0x76,0x6A,0x36,0x31,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34] = ""
[0x29,0x2B,0x3E,0x2D,0x28,0x28,0x25,0x6A,0x21,0x3C,0x21] = "mozilla.exe"
[0x22,0x2D,0x36,0x21,0x22,0x2B,0x3C,0x6A,0x21,0x3C,0x21] = "firefox.exe"
[0x2D,0x21,0x3C,0x34,0x28,0x2B,0x36,0x21,0x6A,0x21,0x3C,0x21] = "iexplore.exe"
[0x23,0x25,0x29,0x29,0x25,0x6B,0x27,0x76,0x71,0x6A,0x34,0x2C,0x34] = "gamma/c25.php"
[0x27,0x2D,0x26,0x6A,0x2D,0x26,0x25,0x2A,0x2F,0x2D,0x2A,0x23,0x69,0x37,0x21,0x36,0x32,0x2D,0x27,0x21,0x37,0x6A,0x27,0x2B,0x29] = ""
[0x6B,0x27,0x2D,0x26,0x6B,0x28,0x2B,0x23,0x2D,0x2A,0x6A,0x2E,0x37,0x34,0x7B,0x6E,0x22,0x2D,0x2B,0x36,0x23,0x79] = "/cib/login.jsp?*fiorg="
[0x6E,0x32,0x36,0x69,0x6E,0x21,0x26,0x25,0x2A,0x2F,0x2D,0x2A,0x23,0x6A,0x20,0x21] = "*vr-*"
[0x6B,0x21,0x26,0x25,0x2A,0x2F,0x2D,0x2A,0x23,0x6E,0x25,0x27,0x30,0x2D,0x2B,0x2A,0x79,0x37,0x30,0x25,0x36,0x30,0x28,0x2B,0x23,0x2D,0x2A] = "/ebanking*action=startlogin"
[0x26,0x25,0x2A,0x2F,0x2D,0x2A,0x23,0x6A,0x36,0x25,0x2D,0x22,0x22,0x21,0x2D,0x37,0x21,0x2A,0x6A,0x25,0x30] = ""
[0x6B,0x2C,0x30,0x29,0x28,0x6B,0x23,0x21,0x36,0x29,0x25,0x2A,0x6B,0x28,0x2B,0x23,0x2D,0x2A,0x34,0x2D,0x2A,0x6A,0x2E,0x37,0x34] = "/html/german/loginpin.jsp"
[0x6B,0x2C,0x30,0x29,0x28,0x6B,0x27,0x2B,0x29,0x29,0x2B,0x2A,0x6B,0x2E,0x37,0x6B,0x27,0x28,0x2D,0x21,0x2A,0x30,0x37,0x2A,0x2D,0x22,0x22,0x21,0x36,0x6A,0x2E,0x37] = "/html/common/js/clientsniffer.js"
[0x26,0x25,0x2A,0x2F,0x2D,0x2A,0x23,0x34,0x2B,0x36,0x30,0x25,0x28,0x6A,0x2A,0x25,0x37,0x34,0x25,0x6A,0x20,0x21] = ""
[0x6B,0x26,0x25,0x2A,0x2F,0x2D,0x2A,0x23,0x6B,0x28,0x2B,0x23,0x2D,0x2A,0x34,0x36,0x21,0x37,0x21,0x2A,0x30,0x25,0x30,0x21,0x6A,0x2E,0x37,0x34] = "/banking/loginpresentate.jsp"
[0x3D,0x2F,0x26,0x6A,0x30,0x21,0x28,0x21,0x33,0x21,0x26,0x6A,0x27,0x2B,0x29,0x6A,0x30,0x36] = ""
[0x6B,0x27,0x6B,0x2E,0x37,0x21,0x2A,0x27,0x6B,0x29,0x25,0x2D,0x2A,0x6A,0x2E,0x37] = "/c/jsenc/main.js"
[0x60,0x1B,0x77,0x70,0x73,0x76,0x70,0x71,0x76,0x6A,0x01,0x1C,0x01] = "$_3472452.EXE"
[0x60,0x1B,0x76,0x77,0x70,0x75,0x76,0x77,0x70,0x6A,0x10,0x09,0x14] = "$_2341234.TMP"
[0x60,0x1B,0x76,0x77,0x70,0x75,0x76,0x77,0x77,0x6A,0x10,0x09,0x14] = "$_2341233.TMP"
[0x60,0x1B,0x76,0x77,0x70,0x75,0x76,0x77,0x71,0x6A,0x10,0x09,0x14] = "$_2341235.TMP"
[0x29,0x30,0x26,0x2D,0x2A,0x22,0x2B,0x6A,0x36,0x31,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34] = ""
[0x2F,0x25,0x30,0x36,0x2D,0x2A,0x73,0x6A,0x27,0x2B,0x29,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34] = ""
[0x32,0x21,0x36,0x29,0x3D,0x30,0x73,0x6A,0x27,0x2B,0x29,0x6B,0x23,0x25,0x29,0x29,0x25,0x6B,0x3C,0x76,0x71,0x6A,0x34,0x2C,0x34] = ""

Tools used:

One thought on “The Torpig (aka Sinowal) bot

  1. I dealt with Torpig years back and wish I knew then what you have posted now. At the time it was a challenge for me but it would be less painful now.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s