Unpacking Osiris

Today we will look at a Sample that uses Process Doppleganging to evade detection, Process Doppleganging is a pretty recent Injection Method that is not usually used alone, but mixed with other injection methods, most likely Process Hollowing, which is the case in this Sample.

Further read on Process Doppleganging, Process Hollowing and how Osiris Implemented a Hybrid of both worlds, Check the Malware Evasion Through Injection episode in The REM-Essentials Series.

Video Walk-through:

Basic Threat Intel

This Sample is of Agent Kroner Banking Trojan Family Osiris . The first stage involves injecting it's malicious payload into wermgr.exe .

→ Since This Sample use it's own copies of ntdll.dll and other dlls to evade AV hooks, we would go through a different approach of debugging, rather that set breakpoints on known APIs that's involved in Process Doppleganging we would instead walk through the Code and check each function, this is going to be a long process but we'll end up following the Injection step by step.

Dynamically Unpacking the Sample


From the Dynamic Execution Analysis we see the Sample spawns wermgr.exe , So as a start we would set a breakpoint on CreateProcessInternalW() and will debug through from there.

Once Running the Sample we hit the breakpoint with a path to wermgr.exe and the process is spawned in a suspended state.


Following the Return from Step1 to User Code and Stepping through execution, we find calls to ZwQueryInformationProcess() over the spawned wermgr.exe by passing its hProcess 0x9c in my case, Continuing on we find a Function that takes NtCreateFile() as a parameter[2], this could be performing some functions over a given hFile, Stepping into this function we find a call to another function that looks the same but this time with the path to wermgr.exe that it might tries to open wermgr.exe as a file[2`].


Stepping into this function, we see it constructs the path string to wermgr.exe [3] and calls a NtAllocateVirtualMemory() to allocate memory in it's own process[3`], on execution it returns a pointer to the allocated region of memory[3``].

Finally on Return a file of wermgr.exe is created in the Osiris.exe Process Memory.


Continuing On we find a Call to NtCreateSection with a hFile to the wermgr.exe file that's been Created. So this Section will Contain the information inside the wermgr.exe file[4]. On Execution a Section is Created [4`].


Continuing On the Sample Tries to Map the Section into it's own Process Memory by calling NtMapViewOfSection() over hSection[5], Returning a pointer to the Mapped Section that now Contains wermgr.exe [5`].


Now that the Sample have a mapped copy of wermgr.exe it calls ZwClose() on both hSection and hFile (both of wermgr.exe) so we end up with the spawned wermgr.exe that is still suspended and not altered and a mapped copy of it inside Osiris.exe Process Memory.


Later On we find an interesting Function that takes hProcess of the remote wermgr.exe as a parameter, Stepping into it[7], it calls NtQueryVirtualMemory() over hProcess of wermgr.exe couple of times, so we can assume it tries to figure out offsets of the legitimate binary[7`].


Now we come to the important part, where the Sample will create a file that does not really exist on disk, with which the legitimate wermgr.exe will be injected in Memory.

This starts by an interesting function that is a wrapper to calls to NtCreateFile()| NtAllocateVirtualMemory(), This function construct the path string of the file to be created \TEMP\\Liebert.bmp[8] in this case, and returns a pointer to the allocated region of memory in it's own process[8`].

Next it Constructs a full path to the .bmp file.


The Sample still uses wrapper functions to implement low-level API calls, and by following through execution we find a call to NtCreateTransaction() that returns a handle to a TmTx inside Osiris.exe

The existence of a TmTx Transaction is a clear indication of using Process Doppleganging / NTFS Transactions as an Evasion/Injection Technique to inject a payload in the Process Memory without ever getting caught on disk.

10 →

Finally the Leibert.bmp file is created[10].

The Sample uses another wrapper function that from it's parameters [ String to Leibert.bmp path, hTmTx, Base Address 0x300000, region of memory containing an Executable ] we can assume this will be the Write operation of the malicious payload[10]. Stepping into the function we see the call to NtWriteFile() of Liebert.bmp` file[10``].

We would want to dump this out as it's still unmapped and easier to analyze.


Next the Sample Creates a Section Containing Liebert.bmp data that's been written recently.

The Sample then will Rollback the TmTx Transaction to revert changes made to it by calling ZwRollbackTransaction(), Closes the Transaction with calls to ZwClose(). Now we're left with the newly created Section that Contains the Malicious Payload.


The Obvious Next Step is to Map that Section into the remote wermgr.exe process, which is done by calling NtMapViewOfSection from hSection into hProcess at Base Address 0x400000 .


Next is a Call to ZwProtectVirtualMemory() to change the protection of the written binary, and couple of calls to NtWriteVirtualMemory() for Process/Thread Parameters Setup and PEB entry point update and everything.

Next a Call to ZwResumeThread() to execute the remote/injected wermgr.exe process.

The Dropper for Osiris used a couple of techniques that made it a very interesting Sample, Starting with making their own copy of NTDLL to escape the Security Products' hooks on important APIs, to using Process Doppleganging for writing a Malicious Payload into a Transaction with the illusion it's from a bmp file, and lastly using Process Hollowing to inject the Malicious Payload into a suspended Legitimate Windows Binary.

:Now that's everything when it comes to using Process Doppleganging as part for dropping the first stage payload without getting caught on disk, this method is very stealthy and usually coupled with other Injection Method to make it even more stealthier.

Last updated