FinSpy analysis – Round One

Last month a number of FinSpy samples were found and later analysed by CitizenLab (see The details provided in the CitizenLab post are quite high-level; the aim of this blog is to dig deep into FinSpy and provide detailed analysis.

The samples from the CitizenLab post can be easily found on the internet by Googling the hashes. I found the following files:

  • 2ec6814e4bad0cb03db6e241aabdc5e59661fb580bd870bdb50a39f1748b1d14
  • 39b325bd19e0fe6e3e0fca355c2afddfe19cdd14ebda7a5fc96491fc66e0faba
  • 49000fc53412bfda157417e2335410cf69ac26b66b0818a3be7eff589669d040
  • cc3b65a0f559fa5e6bf4e60eef3bffe8d568a93dbb850f78bdd3560f38218b5c
  • e48bfeab2aca1741e6da62f8b8fc9e39078db574881691a464effe797222e632

After searching VirusTotal for the hashes listed above, I was relieved to see that the AV industry appeared to be on top of this threat, with around 30 of the 40 or so AVs detecting the files as malicious.  Little did I know how poor an effort all but two AVs had actually done.

For my research I focused on the first file (2ec6814e4bad0cb03db6e241aabdc5e59661fb580bd870bdb50a39f1748b1d14), but from what I could tell all of the files listed above look similar (in terms of their disassembly) so the following details are most probably applicable to the other files.

The first step I took was to run Ero Carrera’s pefile script (see against the sample. Nothing too interesting popped up except for the number of resources the file has. I went ahead and dumped the resources and after looking through each resource, I found the biggest one (resource [0x5] – [0x1] – [0x409]) didn’t appear to have any file format structure to it (eg jpg, ico) and looked to be obfuscated or encrypted. I couldn’t immediately see how to deobfuscate/decrypt the file, so I put it aside and cracked open the sample file in IDA.

Opening up  the sample  in IDA Pro didn’t show anything too interesting at first – mainly boring win32 GUI code. The WinMain routine isn’t very big at all and looks like it just tries to load a couple of icons/strings from the PE resources before starting a Windows message loop.

Close to the top of WinMain though, there’s a call to a routine that uses some manual PE traversing and VirtualProtect to update two of the imports (RegisterClassExW and CreateWindowExW) for the sample PE file.

So what do these routines do? Well, the first routine that gets called is NewRegisterClassExW, which just  copies the sample’s PE file into the temp directory when the routine is first run (I’ll talk about some funky stuff it does when it’s called again later).

Almost directly after the call to the NewRegisterClassExW routine, the NewCreateWindowExW routine gets called. This routine is responsible for launching the copy of the sample in the temp directory. Under normal circumstances, this would just require a quick call to CreateProcess, however the authors went for a more complicated and sneaky approach. Here are the steps they take:

  • Start the new process in a suspended state
  • Map in their own private copy of ntdll
  • Get the address of NtUnmapViewOfSection from their private ntdll (using their own implementation of GetProcAddress)
  • Make a copy of the memory of the executable from the new process
  • Use NtUnmapViewOfSection to unmap the executable from the new process
  • Rewrite the executable into the new process’ address space, but also update a global variable that stores a handle to the current (parent) process.
  • Resume the new process and terminate the current process.

I believe the point of this is to allow the new process to self-delete on cleanup, as the Windows loader will no longer have a handle open to the executable (it will be unmapped).

So now the new process starts up and performs the steps outlined above, except its control flow is altered when it enters the NewRegisterClassExW because the global variable that stores a process handle has been set. The sample now enters a huge routine I’ve called DecryptAndDropFiles.

This routine pulls out two of the PE resources from itself (using PE traversal rather than the Win32 API) and deobfuscates them using a simple rolling XOR algorithm. One of the resources (resource [0x5] – [0x2] – [0x409]) deobfuscates to a JPEG file that is then used as a replacement to the original sample file. The other resource (resource [0x5] – [0x1] – [0x409]) is a PE file that is later loaded into the current process’ address space using a custom PE loader. From now on I’ll refer to this resource as the payload. The routine launches the replaced sample file (which is now a JPEG), then it drops and executes a bat file to clean up after itself.

I’m definitely no python expert and know barely enough to get around with it, so please excuse the ugliness of the following script I used to deobfuscate the PE resources:

encrypted_file = open( 'encrypted', 'rb' )

encrypted_data = )


decrypted_file = open( 'decrypted', 'wb+' )

key = '\x67\xCA\x1E\x5F'

for i in range( len(encrypted_data) / 4 ):
    decrypted_file.write( chr( ord( key[0] ) ^ ord( encrypted_data[i*4 + 0] ) ) )
    decrypted_file.write( chr( ord( key[1] ) ^ ord( encrypted_data[i*4 + 1] ) ) )
    decrypted_file.write( chr( ord( key[2] ) ^ ord( encrypted_data[i*4 + 2] ) ) )
    decrypted_file.write( chr( ord( key[3] ) ^ ord( encrypted_data[i*4 + 3] ) ) )
    key = encrypted_data[i * 4 + 0] + encrypted_data[i * 4 + 1] + encrypted_data[i * 4 + 2] + encrypted_data[i * 4 + 3]


As you can see, the deobfuscation is pretty simple:

  • Start with 0x5F1ECA67 and XOR that with the first 4 bytes.
  • XOR the next 4 bytes with the (obfuscated) previous 4 bytes.

It’s worth noting that the seed value (0x5F1ECA67) is used in all of the samples I listed earlier. As such, I was able to use this script to deobfuscate all of the payloads from each sample. The hashes for the payloads are as follows:

  • 2bbc8f46a6efc6c824e55dc3ec18e2cf4a6d594b3d4f6fa54b95a4521e0a503e (disguised as FlashUtil.exe, Adobe Flash Installer/Uninstaller)
  • a99fca440934ea43ec71cecb8f2aa1a60c0350eef939450c17eb94fecf8453ee (disguised as Opera.exe, Opera Internet Browser)
  • a9da850395755704d33ff8c4c5f469dfcbcec9f373a5cf5b0b3290dff2a5c43f (disguised as Opera.exe, Opera Internet Browser)
  • 9011cc655228333dd35b2e8fe079861325ef511a32e45819bcc7dff13f9d2440 (disguised as autoruns.exe, Autostart program viewer)
  • a436042896aa7af9a16af04a5e568db4b8c5ddf7ccb013af402ac9e4930da693 (disguised as Opera.exe, Opera Internet Browser)

To my utter amazement, these PE files are (at the time of this post) being detected by just 2 AVs of the 40 or so on VirusTotal. Congratulations go to ESET and AVG for taking the time to protect their users.

That’s it for the first round of analysis. Stay tuned for round two where I dig into the payloads to uncover more Gamma Group goodies!

4 responses to “FinSpy analysis – Round One

  1. Hi poof,
    I agree with you – there’s nothing new or novel about their technique for process hollowing. Actually, I haven’t found anything ground-breaking (yet) in any of the samples I have. It really makes me wonder why governments have paid big bucks for this kit, and why the AV community isn’t more on top of this.

  2. Hi IDA Fan,
    I looked at doing that when I started but the CrowdRE plugin doesn’t support my (only slightly older) version of IDA. I don’t have the money to upgrade so I’m afraid it won’t be happening any time soon.

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 )

Google photo

You are commenting using your Google 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