From OneNote to Quakbot (BB12)

Attackers started recently to use Microsoft OneNote file to distribute malwares by email. I’ve decided to take a to public sample and analyse it (Thanks @pr0xylife for sharing it !).

To proceed, I’ll use my Malware Analysis Lab as described here. I’ll start with a static analysis of the file to discover what will be executed by the OneNote file, then a behavioural analysis to observe what the malware does and the IOC left behind, and eventually I’ll proceed with a dynamic code analysis to discover how it works internally.

0x10 – Static Analysis
0x20 – Behavioural Analysis
0x30 – Dynamic Code Analysis
0x40 – Final Words

0x10 – Static Analysis

Download the sample from Malware Bazaar and open it with Malcat (not installed by default on FlareVM, but it’s a must have !). Malcat shows the 4 files contained in the OneNote, if we double-click on each file, Malcat shows their file type. We can note that the 2nd file is interesting because it’s an HTML file.

Files contained in the .one

Right click on the 2nd file and choose “Dump to file …” to extract it and save it as suspicious.html for example.

Dump the 2nd file to disk

Open the newly saves suspicious.html with VSCode. After a very long style section there are some interesting functions in which we can rename variables to make them cleaner.

The first function will store a long string into the registry and create a function (called later) to clean it.

First Function

The second function will call the previsouly created cleaning function to clean the string from the registry, and create a function (SuspiciousFunction) which will execute the cleaned string with an URL as parameter.

Second Function

The third function will execute the decoded string from the registry on a given URL.

Third Function

If we take the encoded string and replace the “111&” by “” (nothing), and arrange the code a bit, we see what it does .

Beautified code from the encoded string in the registry

We see now clearly what the .one does once the html file is opened :
– executes curl to fetch a DLL from URL “”
– executes the “Wind” export from this DLL using rundll32.exe
– displays a fake error message and kill mshta.exe

Let’s fetch this DLL manually to see what’s inside, I named my local copy “suspicious.png”

Fetch the DLL manually

As the URL will probably goes down quickly, I can share my copy of the DLL : HERE (password = infected)

Once downloaded, I usually open it with Malcat to have an quick overview, and Malcat already shows some interesting things in the CAPA section.

suspicious.png capacities

The Wind export called by the .one file is marked as suspicious because it’s seen as a “spaghetti function”.

Wind Export of suspicious.png at 0x10001b00

At this point, I tried to submit it to Triage but nothing was found (

Triage didn’t find this DLL interesting 🙁

Let’s run this export ourself and see what it does !

0x20 – Behavioural Analysis

Before running the malware, make sure the Lab is configured properly :
– FlareVM is running in the dedicated Virtual Network of the Lab with REMnux IP as DNS and default route
– We have a snapshot of the FlareVM before detonation
– REMnux is up and running in the dedicated Virtual Network of the Lab also
– INetSim is running on REMnux, ready to intercept all network activity from the FlareVM
See details in Installing a Malware Analysis Lab if you have any doubt !

To observe the behaviour of the malware, I started ProcMon & Process Hacker on FlareVM, and WireShark on REMnux, then executed rundll32.exe C:\temp\suspicious.png,Wind in a command prompt.

After a few seconds, Process Hacker showed that rundll32 spawned
– wermgr.exe (PID 5356) killed quickly
– wermgr.exe (PID 4792) that is still running

wermgr.exe spawned by rundll32.exe

After a few minutes, I started to see connection attempts from the FlareVM ( in Wireshark running on REMnux ( towards some external IP (the C2 infrastructure).

Connection attempts to C2 infrastructure

Now the malware is running, let’s kill the process tree in Process Hacker, and stop capturing events in ProcMon. (Don’t take the Timestamps into account in the screenshots as I did a few times …)

I added some filters to see what happened
– with processes
– with the registry
– with files/directories level

Process Activity
Registry Activity
File Creation Activity

Now we have a pretty good idea of what will be executed, let’s try to understand how it’s done !

0x30 – Dynamic Code Analysis

Here comes the hardest part on which I spent most of my time, but I learned a lot ! If you see some errors, feel free to reach me via social networks and discuss, I’m always eager to learn from my mistakes !

First thing to know is that after each successfull execution (wermgr.exe is spawned), the main dll (suspicious.png here) is corrupted, make sure to keep a valid copy of it and restore it before each debug session.

Secondly, there are some anti-debug checks via the PEB, if a debugger is detected, the malware and exits and nothing is done. We can patch them manually or simply ScyllaHide plugin which worked perfectly in this case with the Basic Profile.

Now we want to run and debug a specific export (Wind) of suspicious.png, not the usual DllMain.
To do so :
– Options / Preferences / Break on “DLL Entry” must be checked
– File / Open (F3) / Choose “C:\Windows\SysWOW64\rundll32.exe” -> x32dbg will break at System Breakpoint
– File / Change Command Line / Choose “C:\Windows\SysWOW64\rundll32.exe” C:\temp\suspicious.png,Wind
– Debug / Restart -> x32dbg will break at System Breakpoint
– Debug / Run (F9) -> x32dbg will break at rundll32 EntryPoint
– Debug / Run (F9) -> x32dbg will break at suspicious.png EntryPoint
– Set a breakpoint on the Wind export in the command window : “bpx 10001b00”
– Debug / Run (F9) -> x32dbg will break at the beginning of the Wind export of suspicious.png

Breakpoint on the Wind export

Now the list of API calls I discovered that were in use by this sample :

CreateProcessW is used to start wermgr.exe in suspended mode (dwCreationFlags = 4)

CreateProcessW used to start wermgr.exe in suspended mode

NtCreateSection / NtMapViewOfSection / ZwUnmapViewOfSection are used to create a memory space shared between 2 processes (a section). Interesting articles describing this method are visible HERE & HERE.

Mapping the new section to current process
Mapping the new section to child process wermgr.exe (handle 0x328)
After the code is written into the section it can be unmapped from the current process

GetThreadContext / ZwProtectVirtualMemory / ZwWriteVirtualMemory are used to modify code at EntryPoint of wermgr.exe and make it jump to the malicious code.

Buffer containing JMP instructions (E9 11 B8 74 02) written to EntryPoint of wermgr.exe

ResumeThread is used to start the execution of the modified wermgr.exe

First thread of wermgr.exe is resumed with modified code at EntryPoint

Before executing the ResumeThread API call, I used Process Dump to dump the process and the modules to disk.

Dumping executable and modules to disk

We have now 1 executable and 3 DLL. The executable is the wermgr.exe with modified code (JMP) at EntryPoint.

JMP to malicious code in wermgr.exe

The 2 biggest DLL seem to be from Microsoft, but the smallest one (internal name comrepl.dll) seems interesting as it has a “Wind” export we are getting familiar with.

Wind export in the dumped DLL

We can try to execute the Wind export from this dumped DLL and observe it creates again a wermgr.exe process.

Behaves like the suspicious.png

I decided to submit this new DLL to Triage and bingo, Qbot was identified and Triage was even able to extract the configuration from it ! (

qbot identified and configuration extracted 🙂

0x40 – Final Words

I wasted quite a lot of hours on this, but I learned a lot thanks to some :

Great articles :
CheckPoint Anti-Debug Tricks
Ten process injection techniques: A technical survey of common and trending process injection techniques
NtCreateSection + NtMapViewOfSection Code Injection
Code injection via memory sections.

Great Tools :
MALCAT – the binary file dissector
Process Dump

Great People : @pr0xylife, @malcat4ever, @malwrhunterteam, @jstrosch

Some questions/tasks remain open :
– Don’t know why wermgr.exe is created 2 times (1st one being killed quickly)
– Don’t know what is RegisterClassExA used for, maybe callback stuff ?
– Don’t know why there is a CreateEventA call with “{4334B2C1-AB0B-4E43-AEE7-FDF4E75E8127}” at the end
– Don’t know if there is a cleaner way to dump/extract the Qbot Core DLL
– Don’t know (yet) how to extract the C2 config from the Qbot Core DLL (there are tons of articles I need to read)
– I still need to practice x64dbg as I wasted a LOT of time with breakpoints in threads that were not reached 🙁

Feel free to reach me ! Hope it helps !

Leave a Comment

Your email address will not be published. Required fields are marked *