{
	"id": "4975a85b-fe1f-4e3f-86e0-43be52d22f76",
	"created_at": "2026-04-06T00:15:52.145502Z",
	"updated_at": "2026-04-10T13:11:25.770694Z",
	"deleted_at": null,
	"sha1_hash": "53315e70da729b3b9a1a63327b57e27ad402bebb",
	"title": "Open-source toolset of an Ivanti CSA attacker",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 1370953,
	"plain_text": "Open-source toolset of an Ivanti CSA attacker\r\nBy Maxence Fossat\r\nArchived: 2026-04-05 18:05:12 UTC\r\nIn recent incident responses where the root cause was an Ivanti CSA compromise, Synacktiv's CSIRT came across\r\nmultiple open-source tools used by threat actors. This article dives into each of these tools, their functionalities\r\nand discusses efficient detection capabilities.\r\nIntroduction\r\nIn September and October 2024, Ivanti published multiple1 security2 advisories3 regarding security policy\r\nbypasses and remote code execution vulnerabilities in their Cloud Services Appliance (CSA) product. It was later\r\nrevealed by FortiGuard Labs Threat Research's work4 that some threat actors had been actively chaining these\r\nvulnerabilities as early as September 9, 2024, before any security advisory or patch was publicly released by\r\nIvanti.\r\nIn some compromise scenarios, even though the initial access stemmed from the exploitation of zero-day\r\nvulnerabilities, later stages were short of such proficient attacker tradecraft. Threat actors were seen using known\r\nmalicious tools and noisy payloads for lateral movement, persistence and credential dumping.\r\nSynacktiv's CSIRT was recently in charge of different forensic investigations where the root cause was a\r\nvulnerable CSA appliance exposed to the internet. During these engagements, we found a set of open-source tools\r\nused by the attacker to achieve its goals. In this article, we take a tour of the OSS toolset from an Ivanti CSA\r\nexploiter and discuss related detection capabilities.\r\nsuo5\r\nAfter initial compromise of the Ivanti CSA appliance, the attacker managed to move to an internet-facing\r\nExchange Server used for OWA connections. They planted an HTTP proxy tunnel going by the name of suo5.\r\nAvailable publicly on GitHub, with an initial commit dated February 2023, this tool is presented as a more\r\nperformant alternative to other tunnelling tools such as reGeorg and Neo-reGeorg.\r\nInterestingly enough, the GLASSTOKEN custom webshell, used during intrusions linked to the exploitation of 0-\r\nday vulnerabilities in Ivanti Connect Secure VPN5 in January 2024, was based on the Neo-reGeorg tool.\r\nAdditionally, the reGeorg tool was used as a commodity webshell in attacks linked to the exploitation of 0-day\r\nvulnerabilities in Microsoft Exchange6 in March 2021.\r\nThe suo5.aspx webshell was dropped on the Exchange Server at the location C:\\Program\r\nFiles\\Microsoft\\Exchange Server\\V15\\FrontEnd\\HttpProxy\\owa\\auth\\OutlookEN.aspx . This name could be a\r\nreference to HAFNIUM-related activities during post-exploitation of the Microsoft Exchange vulnerabilities7 in\r\nMarch 2021.\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 1 of 14\n\nFunctionalities\r\nFor suo5 to work, an attacker-accessible web server (usually a server exposed to the internet) must run suo5\r\nserver-side code, available in .NET, Java or PHP (experimental). In our test case, the OutlookEN.aspx page run\r\nby the IIS component of the Exchange Server is the .NET-flavor of suo5 server-side code.\r\nOn the attacker's side, a SOCKS5 proxy must be set up and the suo5 binary communicates with the server-side\r\ncode to transmit TCP data encapsulated in the HTTP(S) communication.\r\n$ ./suo5 -t https://mail.corporation.local/owa/auth/OutlookEN.aspx\r\n[INFO] 02-27 13:28 header:\r\nUser-Agent: Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome\r\nReferer: https://mail.corporation.local/owa/auth/\r\n[INFO] 02-27 13:28 method: POST\r\n[INFO] 02-27 13:28 connecting to target https://mail.corporation.local/owa/auth/OutlookEN.aspx\r\n[INFO] 02-27 13:28 got data offset, 0\r\n[WARN] 02-27 13:28 the target may behind a reverse proxy, fallback to HalfDuplex mode\r\n[INFO] 02-27 13:28 starting tunnel at 127.0.0.1:1111\r\n[Tunnel Info]\r\nTarget: https://mail.corporation.local/owa/auth/OutlookEN.aspx\r\nProxy: socks5://127.0.0.1:1111\r\nMode: half\r\n[INFO] 02-27 13:28 creating a test connection to the remote target\r\n[INFO] 02-27 13:28 start connection to 127.0.0.1:0\r\n[INFO] 02-27 13:28 successfully connected to 127.0.0.1:0\r\n[INFO] 02-27 13:28 connection closed, 127.0.0.1:0\r\n[INFO] 02-27 13:28 congratulations! everything works fine\r\n[INFO] 02-27 13:28 start connection to 192.168.123.15:22\r\n[INFO] 02-27 13:28 successfully connected to 192.168.123.15:22\r\nUsing a tool like proxychains , the attacker can then communicate with any system accessible by the Exchange\r\nServer. This enables him to get a foothold inside the internal network of the victim. In our test case, using suo5\r\nenables us to connect to a system ( 192.168.123.15 ) on another subnet, which would have been otherwise\r\ninaccessible:\r\n$ proxychains ssh victim@192.168.123.15\r\n[proxychains] config file found: /etc/proxychains4.conf\r\n[proxychains] preloading /usr/lib/x86_64-linux-gnu/libproxychains.so.4\r\n[proxychains] DLL init: proxychains-ng 4.16\r\n[proxychains] Strict chain ... 127.0.0.1:1111 ... 192.168.123.15:22 ... OK\r\nvictim@192.168.123.15's password:\r\nLinux lab-victim 6.1.0-28-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.119-1 (2024-11-22) x86_64\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 2 of 14\n\nThe blog post associated with the tool8 explains how suo5 achieves better performance than its competitors: it\r\nuses the chunked directive for the Transfer-Encoding HTTP/1.1 header9. This essentially means that the\r\nrequest's sender can keep the connection open until it notifies the recipient that the entire message has been sent.\r\nIn this mode, all encapsulated TCP packets are contained in a single HTTP connection, reducing overhead of\r\nmultiple HTTP requests and responses. This is the \"full duplex\" mode advertised in the GitHub project's\r\nREADME :\r\nsuo5 full duplex mode (source: https://koalr.me/posts/suo5-a-hign-performace-http-socks/).\r\nDue to a limitation in .NET HTTP request processing10, the \"full-duplex\" mode cannot be used. The tool then\r\nfalls back to \"half-duplex\" mode, where only the response is sent as a continuous data stream, but requests are\r\nsent as separate HTTP requests. The goal of \"half-duplex\" mode is also to bypass restrictions of an Nginx reverse\r\nproxy that would stand between the suo5 client and the server-side code. By default, Nginx buffers requests11, a\r\nlimitation that cannot be circumvented without modifying the reverse proxy's configuration. However, Nginx also\r\nbuffers responses by default except if the X-Accel-Buffering: no header field is sent as part of the response12\r\n(which is the case for the suo5 webshell). This results in a connection still having better performance than Neo-reGeorg:\r\nsuo5 half duplex mode (source: https://koalr.me/posts/suo5-a-hign-performace-http-socks/).\r\nDetection\r\nTo detect the server-side file (either on disk or loaded in memory), we want to create a YARA rule that avoids\r\nusing easily changeable data like function and variable names. We want to focus on detecting functionalities of the\r\nwebshell. One contextual IOC that we could use, however, is the User-Agent that acts as a kind of \"password\" so\r\nthat only the client is authorized to connect to the webshell. Careless attackers might leave the default value:\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 3 of 14\n\nMozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.1.2.3\r\nThis is the User-Agent of a Chrome browser (version 109.1.2.3) on an LG Nexus 5 smartphone (Android 6.0 -\r\nMarshmallow).\r\nStealthier attackers will change the User-Agent checked by the server:\r\nprivate bool checkAuth()\r\n{\r\n string ua = Request.Headers.Get(\"User-Agent\");\r\n if (ua == null || !ua.Equals(\"CUSTOM_USER_AGENT\"))\r\n {\r\n return false;\r\n }\r\nThey will then pass that User-Agent string as an argument to the suo5 client, via the --ua flag:\r\n$ ./suo5 --target https://mail.corporation.local/owa/auth/OutlookEN.aspx --ua \"CUSTOM_USER_AGENT\"\r\nDue to the nature of this string, which goal is to discriminate against other suo5 clients or unintentional\r\nconnections to the webshell, there is a high chance that it will be relatively unique, leaving an interesting IOC for\r\nDFIR and SOC analysts.\r\nThe following YARA rule focuses on key characteristics of the webshell:\r\nDefault User-Agent.\r\nX-Accel-Buffering: no response header.\r\nUser-Agent-based authentication.\r\nUsage of TCP client to proxy communications.\r\nBinary serialization and de-serialization.\r\nByte XORing and random key generation.\r\nrule SYNACKTIV_WEBSHELL_ASPX_Suo5_May25 : WEBSHELL COMMODITY FILE\r\n{\r\n meta:\r\n description = \"Detects the .NET version of the suo5 webshell\"\r\n author = \"Synacktiv, Maxence Fossat [@cybiosity]\"\r\n id = \"d30a7232-f00b-45ab-9419-f43b1611445a\"\r\n date = \"2025-05-12\"\r\n modified = \"2025-05-12\"\r\n reference = \"https://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\"\r\n license = \"DRL-1.1\"\r\n[...]\r\n score = 75\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 4 of 14\n\ntags = \"WEBSHELL, COMMODITY, FILE\"\r\n tlp = \"TLP:CLEAR\"\r\n pap = \"PAP:CLEAR\"\r\n strings:\r\n $user_agent = \".Equals(\\\"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTM\r\n $header = \"Response.AddHeader(\\\"X-Accel-Buffering\\\", \\\"no\\\")\" ascii // X-Accel-Buffering response hea\r\n $xor = /= \\(byte\\)\\(\\w{1,1023}\\[\\w{1,1023}\\] \\^ \\w{1,1023}\\);/ // XOR operation\r\n // suspicious functions\r\n $s1 = \"Request.Headers.Get(\\\"User-Agent\\\")\" ascii\r\n $s2 = \"if (Request.ContentType.Equals(\\\"application/plain\\\"))\" ascii\r\n $s3 = \"Response.ContentType = \\\"application/octet-stream\\\";\" ascii\r\n $s4 = \"= Request.BinaryRead(Request.ContentLength);\" ascii\r\n $s5 = \"= Response.OutputStream;\" ascii\r\n $s6 = \"new TcpClient()\" ascii\r\n $s7 = \".BeginConnect(\" ascii\r\n $s8 = \".GetStream().Write(\" ascii\r\n $s9 = \"new BinaryWriter(\" ascii\r\n $s10 = \"new BinaryReader(\" ascii\r\n $s11 = \".ReadBytes(4)\" ascii\r\n $s12 = \"BitConverter.GetBytes((Int32)\" ascii\r\n $s13 = \"BitConverter.ToInt32(\" ascii\r\n $s14 = \"Array.Reverse(\" ascii\r\n $s15 = \"new Random().NextBytes(\" ascii\r\n condition:\r\n filesize \u003c 100KB and ( $user_agent or ( ( $header or $xor ) and 8 of ( $s* ) ) or 12 of ( $s* ) )\r\n}\r\nSecurity professionals wishing to set up an IDS/IPS rule to detect HTTPS suo5 traffic are out of luck. Except for\r\nhaving TLS interception, their best bet would have been to detect specific client JA313/JA414 fingerprints, but\r\nsuo5 uses the Randomized TLS Client Hello Fingerprint functionality of the uTLS15 Go library:\r\nuTlsConn := utls.UClient(conn, \u0026utls.Config{\r\n InsecureSkipVerify: true,\r\n ServerName: hostname,\r\n MinVersion: utls.VersionTLS10,\r\n Renegotiation: utls.RenegotiateOnceAsClient,\r\n}, utls.HelloRandomizedNoALPN)\r\niox\r\nThe attacker wished to keep a foothold inside the victim's network that would last even after patches were applied\r\non the Ivanti CSA appliance. They proceeded to deploy another tunnel named iox, directly on the internet-facing\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 5 of 14\n\nappliance.\r\nIn its GitHub page, iox is presented as a better alternative to two other port forwarding tools: lcx (also known as\r\nHTran16 for HUC Packet Transmit Tool) and ew (also known as Earthworm17).\r\nThe lcx tool is a piece of history linked to Chinese hacking culture in the early 2000s. It is a port forwarding tool,\r\ncreated around 200318 by a Chinese hacker going by the name \"Li0n\" which is the founder of a nationalist\r\nhacking group called Honker's Union of China (HUC)19. It has been used20 in numerous21 attacks22 attributed\r\nto Chinese threat actors23 over the years.\r\nThe Earthworm tool came as a more powerful replacement to the ageing lcx/Htran one. It incorporated lcx's\r\ncore concepts (different modes of port forwarding) and added SOCKS5 proxy and reverse SOCKS5 proxy\r\nfunctionalities. Its versatility made it an interesting tool to make complex forwarding chains, abstracting\r\nconnection from a source to a destination host through multiple hops and taking advantage of the few open ports\r\nof each firewall in the way24. It was used as a commodity tunnelling tool in different attacks such as the active\r\nexploitation of the ProxyShell vulnerability by UNC298025 or the attack on US critical infrastructure by Volt\r\nTyphoon26.\r\nFunctionalities\r\niox has similar functionalities to Earthworm, with a cleaner syntax and some network code optimizations. It adds\r\noptional traffic encryption and UDP traffic forwarding.\r\niox's port forwarding capabilities can be used to circumvent network flow restrictions (using well-known ports)\r\nand obfuscate the true source of network connections when a foothold has been established inside the victim's\r\nLAN. In the following example, the edge server (second hop — hop2) can communicate with outside hosts via\r\nport 443, so it establishes a connection to the first hop (hop1). The third hop in the chain (hop3) runs a SOCKS5\r\nproxy. From the point of a view of the victim's network, requests that are coming from the attacker seem to\r\noriginate from the third hop (hop3).\r\nExample of iox's port forwarding and proxy capabilities.\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 6 of 14\n\nCommunications that are forwarded inside the victim's internal network are encrypted with symmetric encryption\r\nalgorithm XChaCha20. This encryption is not meant to be a bullet-proof protection of the privacy of forwarded\r\ncontent, but an evasion technique against NIDS/NIPS.\r\nA reverse SOCKS5 proxy can also be established. In the following scenario, traffic coming from the attacker\r\nmachine seems to originate from the second hop (hop2).\r\nExample of iox's reverse SOCKS5 proxy capabilities.\r\nIn this scenario, traffic encryption, which is an optional feature, is not activated.\r\nDetection\r\nExisting public detection rules rely on function and library names27 or on arguments passed to the command\r\nline28. In the interest of adding complementary rules to the open-source community, we worked on detection rules\r\nrelying on different identifiers.\r\nDuring our engagement, we found an obfuscated sample of iox. Function names, library names, arguments and\r\nmost of the strings had been removed or obfuscated. We then worked on a detection logic that would rely on\r\ndiscriminating patterns in the code. We needed homemade functions which logic would not rely on standard\r\nlibraries. We focused on the homemade iox/crypto library.\r\nTwo constructs were chosen for our detection logic:\r\nif len(key) \u003c 0x20 {\r\n var c byte = 0x20 - byte(len(key)\u00260x1F)\r\nin function ExpandKey and\r\nbs[i] ^= byte(i) ^ bs[(i+1)%len(bs)]*((bs[len(bs)-1-i]*bs[i])%255)\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 7 of 14\n\nin function shuffle .\r\nExtracting small chunks of assembly code from the disassembled sample respectively gives the following patterns\r\nto detect:\r\n00000000004BFA73 48 8B 9C 24 88 00 00 00 mov rbx, [rsp+88h]\r\n00000000004BFA7B 48 83 FB 20 cmp rbx, 20h\r\n00000000004BFA7F 0F 8D 87 02 00 00 jge loc_4BFD0C\r\n00000000004BFA85 48 89 DE mov rsi, rbx\r\n00000000004BFA88 48 83 E3 1F and rbx, 1Fh\r\n00000000004BFA8C 83 C3 E0 add ebx, 0FFFFFFE0h\r\n00000000004BFA8F F7 DB neg ebx\r\nand\r\n00000000004BF92C 44 0F B6 0C 07 movzx r9d, byte ptr [rdi+rax]\r\n00000000004BF931 45 0F AF C8 imul r9d, r8d\r\n00000000004BF935 41 BA FF FF FF FF mov r10d, 0FFFFFFFFh\r\n00000000004BF93B 45 0F B6 DA movzx r11d, r10b\r\n00000000004BF93F 41 0F B6 C1 movzx eax, r9b\r\n00000000004BF943 41 89 D1 mov r9d, edx\r\n00000000004BF946 31 D2 xor edx, edx\r\n00000000004BF948 66 41 F7 F3 div r11w\r\n00000000004BF94C 41 0F AF D1 imul edx, r9d\r\n00000000004BF950 31 CA xor edx, ecx\r\n00000000004BF952 41 31 D0 xor r8d, edx\r\n00000000004BF955 44 88 04 0F mov [rdi+rcx], r8b\r\nIn order to make our rule more effective while limiting false positives and maintaining sufficient performance, we\r\nstructured it to detect patterns of assembly instructions regardless of registers used. For example, the instruction\r\ncmp rbx, 20h could use any register for integer arguments and results specified in the Go internal ABI\r\nspecification29: RAX, RBX, RCX, RDI, RSI, R8, R9, R10, R11 . While making sure to use 4-byte patterns as\r\nmuch as possible (to improve performance with the YARA/YARA-X engine), this results in the following\r\nhexadecimal string:\r\n( 48 83 F8 20 | 48 83 FB 20 | 48 83 F9 20 | 48 83 FF 20 | 48 83 FE 20 | 49 83 F8 20 | 49 83 F9 20 | 49 83 FA 20\r\nThe resulting YARA/YARA-X detection rule is as follows:\r\nrule SYNACKTIV_HKTL_Tunnel_X64_GO_Iox_May25 : COMMODITY FILE\r\n{\r\n meta:\r\n description = \"Detects the 64-bits version of the iox tunneling tool used for port forwarding and SOCKS5\r\n author = \"Synacktiv, Maxence Fossat [@cybiosity]\"\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 8 of 14\n\nid = \"0b5a4689-58ea-45d5-aa14-a1455276352a\"\r\n date = \"2025-05-12\"\r\n modified = \"2025-05-12\"\r\n reference = \"https://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\"\r\n license = \"DRL-1.1\"\r\n[...]\r\n score = 75\r\n tags = \"COMMODITY, FILE\"\r\n tlp = \"TLP:CLEAR\"\r\n pap = \"PAP:CLEAR\"\r\n strings:\r\n /*\r\n 00000000004BFA73 48 8B 9C 24 88 00 00 00 mov rbx, [rsp+88h]\r\n 00000000004BFA7B 48 83 FB 20 cmp rbx, 20h\r\n 00000000004BFA7F 0F 8D 87 02 00 00 jge loc_4BFD0C\r\n 00000000004BFA85 48 89 DE mov rsi, rbx\r\n 00000000004BFA88 48 83 E3 1F and rbx, 1Fh\r\n 00000000004BFA8C 83 C3 E0 add ebx, 0FFFFFFE0h\r\n 00000000004BFA8F F7 DB neg ebx\r\n */\r\n $expand_key = {\r\n ( 48 8B 84 24 | 48 8B 9C 24 | 48 8B 8C 24 | 48 8B BC 24 | 48 8B B4 24 | 4C 8B 84 24 | 4C 8B 8C 24 |\r\n ( 48 83 F8 20 | 48 83 FB 20 | 48 83 F9 20 | 48 83 FF 20 | 48 83 FE 20 | 49 83 F8 20 | 49 83 F9 20 |\r\n ( 0F 8D ?? ?? ?? ?? | 7D ?? )\r\n ( 48 89 ?? | 49 89 ?? | 4C 89 ?? | 4D 89 ?? )\r\n ( 48 83 E0 1F | 48 83 E3 1F | 48 83 E1 1F | 48 83 E7 1F | 48 83 E6 1F | 49 83 E0 1F | 49 83 E1 1F |\r\n ( 83 C0 E0 | 83 C3 E0 | 83 C1 E0 | 83 C7 E0 | 83 C6 E0 | 41 83 C0 E0 | 41 83 C1 E0 | 41 83 C2 E0 | 4\r\n ( F7 D8 | F7 DB | F7 D9 | F7 DF | F7 DE | 41 F7 D8 | 41 F7 D9 | 41 F7 DA | 41 F7 DB )\r\n }\r\n /*\r\n 00000000004BF92C 44 0F B6 0C 07 movzx r9d, byte ptr [rdi+rax]\r\n 00000000004BF931 45 0F AF C8 imul r9d, r8d\r\n 00000000004BF935 41 BA FF FF FF FF mov r10d, 0FFFFFFFFh\r\n 00000000004BF93B 45 0F B6 DA movzx r11d, r10b\r\n 00000000004BF93F 41 0F B6 C1 movzx eax, r9b\r\n 00000000004BF943 41 89 D1 mov r9d, edx\r\n 00000000004BF946 31 D2 xor edx, edx\r\n 00000000004BF948 66 41 F7 F3 div r11w\r\n 00000000004BF94C 41 0F AF D1 imul edx, r9d\r\n 00000000004BF950 31 CA xor edx, ecx\r\n 00000000004BF952 41 31 D0 xor r8d, edx\r\n 00000000004BF955 44 88 04 0F mov [rdi+rcx], r8b\r\n */\r\n $shuffle = {\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 9 of 14\n\n( 44 0F B6 04 | 44 0F B6 0C | 44 0F B6 14 | 44 0F B6 1C | 44 0F B6 44 | 44 0F B6 4C | 44 0F B6 54 |\r\n ( 45 0F AF C0 | 45 0F AF C1 | 45 0F AF C2 | 45 0F AF C3 | 45 0F AF C8 | 45 0F AF C9 | 45 0F AF CA |\r\n [0-4]\r\n ( 41 B8 | 41 B9 | 41 BA | 41 BB ) FF FF FF FF\r\n ( 45 0F B6 C0 | 45 0F B6 C1 | 45 0F B6 C2 | 45 0F B6 C3 | 45 0F B6 C8 | 45 0F B6 C9 | 45 0F B6 CA |\r\n [0-4]\r\n ( 41 89 D0 | 41 89 D1 | 41 89 D2 | 41 89 D3 | 89 D0 | 89 D1 | 89 D2 | 89 D3 )\r\n 31 D2\r\n ( 66 41 F7 F0 | 66 41 F7 F1 | 66 41 F7 F2 | 66 41 F7 F3 )\r\n ( 41 0F AF D0 | 41 0F AF D1 | 41 0F AF D2 | 41 0F AF D3 | 44 0F AF C2 | 44 0F AF CA | 44 0F AF D2 |\r\n ( 31 ?? | 41 31 ?? | 44 31 ?? | 45 31 ?? )\r\n ( 31 ?? | 41 31 ?? | 44 31 ?? | 45 31 ?? )\r\n ( 44 88 04 ?F | 44 88 0C ?F | 44 88 14 ?F | 44 88 1C ?F | 44 88 04 ?7 | 44 88 0C ?7 | 44 88 14 ?7 |\r\n }\r\n condition:\r\n ( uint16be( 0 ) == 0x4d5a or uint32be( 0 ) == 0x7f454c46 or uint32be( 0 ) == 0xcffaedfe ) and filesize \u003c\r\n}\r\nThis rule was tested with YARA, YARA-X and yaraQA to assess its performance. It helped us detect other in the\r\nwild obfuscated samples of the tool.\r\nFor the sake of completeness, the following rule, based only on strings found in the unobfuscated samples, was\r\nalso created:\r\nrule SYNACKTIV_HKTL_Tunnel_GO_Iox_May25 : COMMODITY FILE\r\n{\r\n meta:\r\n description = \"Detects the iox tunneling tool used for port forwarding and SOCKS5 proxy\"\r\n author = \"Synacktiv, Maxence Fossat [@cybiosity]\"\r\n id = \"407d4f90-a281-4f0c-8d8e-ebe45217d3d9\"\r\n date = \"2025-05-12\"\r\n modified = \"2025-05-12\"\r\n reference = \"https://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\"\r\n license = \"DRL-1.1\"\r\n[...]\r\n score = 75\r\n tags = \"COMMODITY, FILE\"\r\n tlp = \"TLP:CLEAR\"\r\n pap = \"PAP:CLEAR\"\r\n strings:\r\n $s1 = \"Forward UDP traffic between %s (encrypted: %v) and %s (encrypted: %v)\"\r\n $s2 = \"Open pipe: %s \u003c== FWD ==\u003e %s\"\r\n $s3 = \"Reverse socks5 server handshake ok from %s (encrypted: %v)\"\r\n $s4 = \"Recv exit signal from remote, exit now\"\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 10 of 14\n\n$s5 = \"socks consult transfer mode or parse target: %s\"\r\n condition:\r\n ( uint16be( 0 ) == 0x4d5a or uint32be( 0 ) == 0x7f454c46 or uint32be( 0 ) == 0xcffaedfe or uint32be(0) =\r\n}\r\natexec-pro\r\nThe atexec.py 30 script is a well-known lateral movement tool leveraging Impacket31 classes to gain remote\r\ncode execution on an endpoint through the Task Scheduler service.\r\nThe attacker executed commands on the Active Directory Domain Controller from another host inside the network\r\nusing a variation of this script called atexec-pro.py 32.\r\nFunctionalities\r\nThe original atexec.py script first establishes an RPC connection over an SMB named pipe33 targeting the\r\n\\pipe\\atsvc 34 endpoint, and then uses this connection to specifically bind to the ITaskSchedulerService 35\r\ninterface for subsequent operations. It then creates a scheduled task, with a name made up of 8 random characters,\r\nwhich is configured to run a single command through the Command Prompt ( cmd.exe ) with the highest\r\npermissions available ( NT AUTHORITY\\SYSTEM ) and to redirect the output to %WINDIR%\\Temp\\\u003cTASK_NAME\u003e.tmp .\r\nThe script triggers the task's execution, deletes the task, reads the content of the .tmp file through an SMB\r\nconnection to the ADMIN$ share and then deletes this file. This means the script only communicates with port 445\r\nthroughout its execution.\r\nThe atexec-pro.py script works quite differently. First of all, an alternative to RPC over SMB is offered, relying\r\non RPC over TCP/IP36 for task manipulation. This protocol uses the RPC Endpoint Mapper, listening on port 135,\r\nto resolve the dynamic endpoint (high ports, ranging typically from 49152 to 6553537) of the\r\nITaskSchedulerService interface. While it is interesting to have another option, most Windows Firewall\r\nconfigurations will, by default in AD domain networks, block incoming requests to dynamic ports, rendering this\r\nmethod of connection useless.\r\nOnce the connection is established, the tool presents itself as a shell:\r\n$ python3 atexec-pro.py -i TSCH corporation.local/Administrator@192.168.122.71\r\n[!] This will work ONLY on Windows \u003e= Vista\r\nPassword:\r\n[*] Connecting to DCE/RPC as corporation.local\\Administrator\r\n[*] Successfully bound.\r\n[+] Type help for list of commands. 🚀\r\nATShell (Administrator@192.168.122.71)\u003e help\r\nDocumented commands (use 'help -v' for verbose/'help \u003ctopic\u003e' for details):\r\nRun Command\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 11 of 14\n\n===========\r\ncmd_exec ps_exec\r\nPost Exploitation\r\n=================\r\ndownload execute_assembly upload\r\nRemote command execution works as follows:\r\nIt works similarly for .NET assembly execution. For upload and download, the file's content is encoded and read\r\nfrom or placed into the task's description.\r\nOverall, the following functionalities are available:\r\nCommand Prompt command execution.\r\nPowerShell command execution.\r\nFile upload.\r\nFile download.\r\n.NET assembly execution.\r\nInteraction with  ITaskSchedulerService via RPC over SMB or RPC over TCP/IP.\r\nDue to the way files are transferred (via the Description field of the task), file upload, file download and .NET\r\nassembly execution only support files up to 1 MB in size.\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 12 of 14\n\nDetection\r\nWhat atexec-pro.py makes up for in functionality, it lacks in stealth. Every command launched through the\r\nTask Scheduler first goes through a PowerShell script, as defined in the task XML definition:\r\n\u003cExec\u003e\r\n \u003cCommand\u003epowershell.exe\u003c/Command\u003e\r\n \u003cArguments\u003e-NonInteractive -enc {ps_command}\u003c/Arguments\u003e\r\n\u003c/Exec\u003e\r\nwhere {ps_command} is replaced by atexec-pro.py with a base64-encoded PowerShell script. The default\r\nscripts provided for each command of the tool can easily be flagged as suspicious:\r\nBase 64 encoding and decoding.\r\nAES encryption and decryption.\r\nInteraction with the Task Scheduler service via the Task Scheduler Scripting Objects38.\r\nAs such, even on default Windows Event Log configurations where Script Block Logging is not fully enabled and\r\nonly suspicious scripts are logged, Event ID 4104 events are generated in Microsoft-Windows-PowerShell\\Operational for each execution of an atexec-pro's command.\r\nThis results in the following Sigma rule:\r\ntitle: atexec-pro - Suspicious PowerShell script\r\nid: 8da0570e-adc3-4d2d-8acf-07f8cde5db3a\r\nstatus: experimental\r\ndescription: Suspicious PowerShell script contents related to execution of atexec-pro remote execution tool\r\nlicense: DRL-1.1\r\nreferences:\r\n - https://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nauthor: Synacktiv, Maxence Fossat [@cybiosity]\r\ndate: 2025-05-12\r\nmodified: 2025-05-12\r\ntags:\r\n - attack.execution\r\n - attack.t1053\r\n - tlp.clear\r\n - pap.clear\r\nlogsource:\r\n product: windows\r\n category: ps_script\r\n definition: Script Block Logging must be enabled\r\ndetection:\r\n selection_base:\r\n EventID: 4104\r\n ScriptBlockText|contains|all:\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 13 of 14\n\n- '[System.Convert]::ToBase64String('\r\n - '[System.Convert]::FromBase64String('\r\n - 'New-Object System.Security.Cryptography.AesManaged'\r\n - '[System.Security.Cryptography.CipherMode]::CBC'\r\n - '.CreateEncryptor()'\r\n - '.CreateDecryptor()'\r\n - 'New-Object -ComObject Schedule.Service'\r\n - '.GetTask('\r\n - '.RegistrationInfo.Description'\r\n - '.RegisterTaskDefinition('\r\n selection_script_cmd:\r\n ScriptBlockText|contains: 'iex'\r\n selection_script_upload:\r\n ScriptBlockText|contains: 'Set-Content -Path '\r\n selection_script_download:\r\n ScriptBlockText|contains: 'Get-Content -Path '\r\n selection_script_net:\r\n ScriptBlockText|contains|all:\r\n - '[System.Reflection.Assembly]::Load('\r\n - 'New-Object System.IO.StreamWriter'\r\n - '.Invoke('\r\n - 'New-Object System.IO.StreamReader('\r\n condition: selection_base and 1 of selection_script*\r\nfalsepositives:\r\n - Legitimate scripts using these cmdlets\r\nlevel: high\r\nA similar rule can be created based on command line content if process creation is logged.\r\nAs for forensic artefacts left by the execution of the original atexec.py script, the following article explores\r\nthem (and many more remote code execution tools ;).\r\nConclusion\r\nThroughout this article, we discovered three tools actively used by threat actors to tunnel traffic to and from the\r\ninternal network (suo5, iox) and to execute code remotely (atexec-pro). We analysed their core capabilities and\r\nused them to create YARA and Sigma detection rules, focusing on broad detection, harder defence evasion and\r\nlow false positive rates.\r\nAll detection rules created for this article will be maintained in the following GitHub repository.\r\nIf your organization needs assistance in removing doubt or responding to a security incident, please feel free to\r\ncontact Synacktiv's CSIRT.\r\nSource: https://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nhttps://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker\r\nPage 14 of 14",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"Malpedia"
	],
	"origins": [
		"web"
	],
	"references": [
		"https://www.synacktiv.com/en/publications/open-source-toolset-of-an-ivanti-csa-attacker"
	],
	"report_names": [
		"open-source-toolset-of-an-ivanti-csa-attacker"
	],
	"threat_actors": [
		{
			"id": "7c969685-459b-4c93-a788-74108eab6f47",
			"created_at": "2023-01-06T13:46:39.189751Z",
			"updated_at": "2026-04-10T02:00:03.241102Z",
			"deleted_at": null,
			"main_name": "HAFNIUM",
			"aliases": [
				"Red Dev 13",
				"Silk Typhoon",
				"MURKY PANDA",
				"ATK233",
				"G0125",
				"Operation Exchange Marauder"
			],
			"source_name": "MISPGALAXY:HAFNIUM",
			"tools": [],
			"source_id": "MISPGALAXY",
			"reports": null
		},
		{
			"id": "2704d770-43b4-4bc4-8a5a-05df87416848",
			"created_at": "2022-10-25T15:50:23.306305Z",
			"updated_at": "2026-04-10T02:00:05.296581Z",
			"deleted_at": null,
			"main_name": "HAFNIUM",
			"aliases": [
				"HAFNIUM",
				"Operation Exchange Marauder",
				"Silk Typhoon"
			],
			"source_name": "MITRE:HAFNIUM",
			"tools": [
				"Tarrask",
				"ASPXSpy",
				"Impacket",
				"PsExec",
				"China Chopper"
			],
			"source_id": "MITRE",
			"reports": null
		},
		{
			"id": "529c1ae9-4579-4245-86a6-20f4563a695d",
			"created_at": "2022-10-25T16:07:23.702006Z",
			"updated_at": "2026-04-10T02:00:04.71708Z",
			"deleted_at": null,
			"main_name": "Hafnium",
			"aliases": [
				"G0125",
				"Murky Panda",
				"Red Dev 13",
				"Silk Typhoon"
			],
			"source_name": "ETDA:Hafnium",
			"tools": [],
			"source_id": "ETDA",
			"reports": null
		}
	],
	"ts_created_at": 1775434552,
	"ts_updated_at": 1775826685,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/53315e70da729b3b9a1a63327b57e27ad402bebb.pdf",
		"text": "https://archive.orkl.eu/53315e70da729b3b9a1a63327b57e27ad402bebb.txt",
		"img": "https://archive.orkl.eu/53315e70da729b3b9a1a63327b57e27ad402bebb.jpg"
	}
}