FinFisher Malware Analysis - Part 2
In previous post, I fully analyzed dropper part of FinFisher malware. In this post, I'll share with you details of FinFisher malware main component which I got it from the dropper. This part is also as interesting as dropper part and does have several techniques and tricks, but as far as I know, again, most of them was already known and used in other malwares, but I might be wrong. So stay tuned for a another very detailed step by step analysis.
As first step, I fired up IDA for initial analysis, so I would have general idea of the malware, then I started Ollydbg for dynamic analysis. By the way, I've received several messages about use of Ollydbg, that why I use Ollydbg and not IDA's debugger. To be honest, in my own very personal opinion, IDA debugger is only good for operating systems Ollydbg doesn't work (MacOS, Linux, FreeBSD, etc.), Ollydbg's ability to show string references in registers, very detailed memory map and memory pages, changing memory pages permissions or dumping or modifying them easily, breakpoint management, easy to navigate stack view, extended details in registers (when register hold an address to an API entry or a pointer to a string), Ollydbg's plugins, ease of use, being first tool that introduced me to reverse engineering world and using it since 2003, makes Ollydbg my primary tool for dynamic analysis in Windows, for rest of things (decompiling, other operating systems, graphs, patch analysis, bindiffing, static analysis, vulnerability research, etc.) IDA is perfect.
Anyway, let's return to our main goal of analyzing FinFisher malware's main component. At first look, I've noticed that compilation date/time of this malware intentionally modified to hide real compilation date/time. It was set to 0xE6751A81 which means it compiled at 07/31/1983 08:58:39 PM, I don't know if this day have any special meaning, birthday of the developer maybe? Warmest July in Dutch history since 1852?
Also this is Version info of the malware:
LegalCopyright: ©Firefox and Mozilla Developers, according to the MPL 1.1/GPL 2.0/LGPL 2.1 licenses, as applicable. CompanyName: Mozilla Corporation FileDescription: Windows Generic Installer FileVersion: 188.8.131.52 ProductVersion: 3.6.11 InternalName: Windows Generic Installer LegalTrademarks: Firefox is a Trademark of The Mozilla Foundation. OriginalFilename: setup.exe ProductName: Firefox BuildID: 20101012104950
Can Mozilla sue them for illegal use of their name in FinFisher malware?
Anyway, after setting initial parameter, initializing security cookie, etc. first interesting thing in this malware was using EnumWindows API callback parameter to call a function. Basically it doesn't have anything to do with enumerating windows, but this API call acts as a sort of a small smoke screen. This call is located at 0x4020F1 and callback function is located at 0x00401C1B.
This trick might be nothing, but the callback function itself is amazing. To summarize this function, here is step by step what it does:
- Calls 0x004013DD to get ntdll.dll module handle
- Calls 0x004034CE. This function, calls GetModuleHandleA to get ntdll.dll handle again, then it locates KiUserExceptionDispatcher API. Next, it calls VirtualProtect to make first 16 (0x10) bytes of KiUserExceptionDispatcher in ntdll.dll writable. Finally it replaces first bytes of KiUserExceptionDispatcher with:
PUSH 0x4034C1 RETN
- Intentionally causes crash by three UD2 opcodes which is sort of "throw exception" in assembly. There is UD0, UD1 and UD2 which means "Undefined behavior" or "Undefined instruction". Naturally this exception will need an exception handler, as result, KiUserExceptionDispatcher will be called. As KiUserExceptionDispatcher is already modified, it will redirect program's flow to a new location using this exception and exception handler trick.
Here is KiUserExceptionDispatcher before patch:
After patching ntdll, here is UD2 opcodes for triggering an exception:
Exception handler code just puts ESP value into EAX and then calls 0x00403489. This function, calls NtContinue API from ntdll.dll to let program continue as it was before exception. I think this whole trick was to bypass some sandboxes and mostly heuristic engines, as they'll imagine that the application has crashed three times.
After patching and triggering exceptions 3 times, it calls 0x00403447 function, which reverses the patched bytes from original values stored into stack and even restores the permission to PAGE_EXECTURE_READ for first 16 bytes. It returns everything to it's original like nothing ever happened to KiUserExceptionDispatcher.
After these tests, it calls 0x004014F4 function to determine if the OS is 64-bit, if so, it creates a new x64 malware in %TEMP% folder. This x64 bit application does have same version info and compilation date of it shows it will be compiled in future: 07/25/2022 09:18:21 AM. So I think they modified these values randomly just to hide real compilation date/time. So if OS is x64, it just creates new 64-bit malware, executes it using CreateProcess API and terminates itself.
If it's 32-bit process, it decrypts 32-bit modules one-by-one, writes them on memory and calls CreateRemoteThreadEx to execute them. As first thing, this code tries to create C:\Windows\Installer folder (which I think it exists on all Windows default installations) and then it creates a new randomly generated folder name in C:\Windows\Installer, see:
Malware from here tries to decrypt resources as needed (5 entries in BIN resource folder). One of them is driver, FinFisher calls it "Microsoft Disk Driver" and driver name is "driverw". See:
MD5 of driver file is: DB5BD1054B4FE763FAAC049B72DA2EB6. It seems no one analyzed it as Google search yields no result. Here is the driver entry in Services key of registry:
The driver would need an additional post for analysis, but generally speaking, it does two things, one of them is receiving name of an object to get attached devices to this object and detaching them. For example if you pass tcpip.sys to this function, if a firewall device is attached to tcpip.sys, it will try to detach it, so software firewall won't work anymore. Also it does have another function for just opening file from kernel and passing the handle.
Another module is called shell32.dll which is located in resources and it's 23552 bytes. Generally, it's an injector, it injects msvcr90.dll (another module located in resources) into another process. The shell32.dll does have one interesting piece of function/code which I want to show in this post. It two times calls ZwQuerySystemInformation, one time with SystemModuleInfo as InfoType parameter and the other time SystemProcessThreadInfo as InfoType parameter. it writes all these info in a newly allocated 65536 bytes memory page:
which result of API calls looks like this:
Here is the interesting part, it checks loaded drivers and loaded processes for "cmdguard.sys" and "cfp.exe" to determine if Comodo Firewall is running or not and then it checks for "klif.sys" and "avp.exe" to see if Kaspersky Internet Security is running and it doesn't care about any other anti-virus or firewall solution.
So if AV solutions doesn't exists it will open already running explorer.exe, duplicate tokens, inject code in it and run injected code from explorer.exe, but if one of these solutions exists in your computer, it will call sub_4A3816D2 which basically, calls GetWindowsDirectory, appends explorer.exe to it, creates a suspended process with explorer.exe as commandline argument. As next step, it calls GetCurrentProcess, duplicates the handle for current process using DuplicateHandle API, calls VirtualAllocEx to allocate 0xEE (238) bytes in it. Finally it calls WriteProcessMemory and ResumeThread to continue execution. In a nutshell, if Kaspersky AV or Comodo Firewall exists, it won't inject code into already existing explorer, instead it will create a new explorer.exe as suspended process, inject code in it and continue execution.
The msvcr90.dll is an encrypted and packed DLL file. It never writes decrypted and ready to use DLL file into disk, it uses CreateFileMapping and MapViewOfFile APIs to load the encrypted file into memory, then decrypts it on memory and executes it. I have dumped the decrypted DLL with all IAT entries fixed properly. My DLL MD5 is 3AAF1242246A2F3443CD9125C3280F06. This is the main DLL, it does everything with the help of other modules, this DLL does also have it's own set of modules and resources. For instance, this DLL does have 3 resource entries, first resource entry is another DLL embedded inside it. This embedded DLL does have (presumably) an un-altered compilation date/time information. This one is compiled at 10/28/2010 11:56:39 AM. The embedded DLL does have 1 exported function which does nothing. It uses global variables to receive parameters such as host and port and IP and it does act as an internet proxy, so when this DLL injected into e.g. svchost.exe, all sent and received data will be through this process and it will appear so in firewall logs. This DLL is just 11264 bytes specially designed for this purpose. When this tiny DLL loaded, it creates an event with "WininetProxyExit" string. Then it creates a mutex called "WininetProxyMutex". Finally it creates two threads, one for socket operations and the other one is a watchdog for socket thread (to keep DLL alive). That's all about this tiny DLL.
About startup entries, for instance, it creates shell32.dll and msvcr90.dll in it's own folder (in newly created Installer folder in Windows directory) and then it creates a registry entry for shell32.dll inside HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run and REG_SZ value of rundll32:
which as I said before, shell32.dll is an injector with special features for msvcr90.dll.
I think I need another post with more detailed explanation about the driver and msvcr90.dll and 64-bit module. Just before finalizing this post, I want to share three small interesting points:
1) Finfisher malware dev team sense of humor:
2) Interestingly malware does have plain text explanation of information it steals from victim's computer inside the malware, usually malwares does have an indicator code (like a digits 0x01, 0x02, ...) and the C&C server translates each entry to it's type, but FinFisher does it in malware:
3) One dangerous function, as it supposed to be running in temp folder, it locates all files in current folder and deletes them all. So if you analyze the file in Desktop or any other folder, it will attempt to delete all files in current folder, I almost felt for it and it was going to delete all screen shots I gathered, so if this function was running, you was going to read a boring article without any picture, because nobody got time for re-taking all screenshots, IDA actually helped me to understand whole logic of this function before running it:
So in next post, I'll try to analyze last remained components: 64-bit malware, msvcr90.dll and the driver.