GTPDOOR - A novel backdoor tailored for covert access over the roaming exchange By haxrob Published: 2024-02-27 · Archived: 2026-04-05 21:04:58 UTC This page was updated on the 8th of June, 2025 with an update on attribution. Introduction GTPDOOR is the name of Linux based malware that is intended to be deployed on systems in telco networks adjacent to the GRX (GRPS eXchange Network) with the novel feature of communicating C2 traffic over GTP-C (GPRS Tunnelling Protocol - Control Plane) signalling messages. This allows the C2 traffic to blend in with normal traffic and to reuse already permitted ports that maybe open and exposed to the GRX network. The following diagram illustrates a foreseen use of GTPDOOR. Here the actor already has established persistence on the roaming exchange network and access a compromised host by sending GTP-C Echo Request messages with a malicious payload: In addition to remote code execution capability, GTPDOOR can be beaconed by sending arbitrary TCP packets to a host the implant resides on. Supporting it’s stealth capability, the beacon response message hides particular information in a TCP header flag. Naming I have given this malware the name GTPDOOR as it uses a similar “port knocking / magic packet” technique as BPFDOOR as described here and here. Both use raw sockets to intercept packets on the network interface. Unlike BPDDOOR, GTPDOOR explicitly uses GTP-C echo request/response messages and does not utilize BFP / pcap filters, but rather filters on UDP and GTP header values through simple  cmp  instructions. At the time of writing, I am not aware of this malware being documented anywhere else. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 1 of 18 Attribution GTPDOOR is attributed to LIMINAL PANDA. GTPDOOR is likely attributed to UNC1945 (Mandiant) / LightBasin (CrowdStrike) As described in the CrowdStrike article this threat actor has been documented to use the GTP protocol for encapsulating tinyshell traffic in a valid PDP context session by employing an SGSN emulator to tunnel traffic to an external GGSN in another operator network. Here, GTPDOOR is leveraging not off a PDP context (GTP-U, userplane) but specific GTP-C signalling messages with it’s own extended message structure. As we will see below, both binaries contain the name of the original c source file,  dnsd.c . A google search links to a presentation by CrowdStrike about this threat actor that contains text from a process listing originating from what looks like a Solaris machine. In that listing is a process with the name  dnsd : If the attribution is correct, then given the discovery of this screenshot, it is likely that in addition to the two Linux binaries documented in this blog post, a third version exists which targets Sun Solaris systems. Background information In order to provide connectivity between telecommunication network operators around the globe, a “closed” network exists that provides interconnectivity between various systems. These network elements / functions need to have direct connectivity to the GRX network in order to route / forward roaming related signaling and user plane traffic. Examples of these systems are: eDNS - External DNS to resolve APN names, select packet gateway for routing the subscribers traffic SGSN, GGSN - 2G/3G packet core network elements for packet switched data P-GW (Packet Data Network Gateway) - 4G version of the GGSN STP - Signalling gateways for circuit switched routing (e.g. authentication to HLR/HSS) - specifically for SS7 signaling. DRA (Diameter Routing Agent) - 4G version of the STP, rather then SS7, the signaling traffic is over diameter. These functions are listed as to give examples of where GTPDOOR could be placed as they may require direct connectivity to the GRX network. That is - providing opportunity for direct access into a telco’s core network. It is more likely that it would be placed on systems that support GTP-C over GRX, such as SGSN, GGSN, PGW (which don’t run some esoteric operating system). That said, if the GRX firewall is not configured right, there would be opportunities to place this type of implant elsewhere, or even within the internal core network. 💡 A GSMA document called the  IR.21  is used for network providers to publish the details of these systems such as the GT (global titles), IP addresses, APNs etc. This list is used for other companies that have roaming agreements to https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 2 of 18 configure their network accordingly. Alternatively, they may exchange this information directly. Summary of functionality GTPDOOR supports the following: Listens for “magic” wakeup packet, a GTP-C echo request message (GTP type  0x01 ). The host does not need to have a listening sockets / listening services active, as all UDP packets are received into the user space via opening a raw socket Executes a command on the host which is specified in the magic packet and returns the output to the remote host, supporting a “reverse shell” type functionality. Both request/responses are  GTP_ECHO_REQUEST  /  GTP_ECHO_RESPONSE  messages accordingly. Can be covertly probed from an external network to illicit a response by sending a TCP packet to any port number. If the implant is active a crafted empty TCP packet is returned along with information if the destination port was open/responding on the host. Authenticates and encrypts contents of magic GTP packet messages using a simple XOR cipher. At runtime can be instructed to change it’s authentication + encryption key (rekeying). This prevents the default key hardcoded in the binary to be used by other actors Blend in to environment by changing it’s process name to look like syslog process invoked as a kernel thread Does not require ingress firewall changes if the target host is allowed to communicate over the GTP-C port. Versions At the time of writing two versions have been identified on Virus Total: Version Filename Architecture Hash 1 dbus-echo x86-64 827f41fc1a6f8a4c8a8575b3e2349aeaba0dfc2c9390ef1cceeef1bb85c34161 2 pickup i386 5cbafa2d562be0f5fa690f8d551cdb0bee9fc299959b749b99d44ae3fda782e4 pickup  has additional enhancements/features to  dbus-echo , and hence is assigned a higher version number. At the time of writing, both samples have been uploaded to Virus Total in late 2023. Version 1 - 1 detection https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 3 of 18 Version 2 - 0 detections Note: as of the 17th of March, 2024, there is now 37 detections Both binaries were targeted for a particularly old Linux distribution, “Red Hat Linux 4.1”. This is the equivalent to RHEL 5.x. The GCC date is marked 2008. It is quite likely the target network operator of this implant had quite poor patch / lifecycle management. 2024-03-17  - for maximum ABI compatibility, compiling against old glibc versions increases the chance of binaries working in newer releases, so the targetted version may not be exact, although it would be expected to be within proximity to ensure stability. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 4 of 18 As the binaries are not stripped, source code’s original filename was likely  dnsd.c : Technical Details GTP magic packet message types The command instruction is sent in the GTP Echo Request message along with the associated data. As summarized: GTPDOOR v1 Message Type Function Payload 0x01 Set new encryption key New key 0x02 Write data to system.conf File content 0x03 - 0xFF Execute command and return output Shell command to run GTPDOOR v2 Message Type Function Payload 0x01 Set new encryption key New key value 0x02 Write arbitrary data to system.conf File content 0x03 , 0x04 , 0x08 - 0xFF Execute command and return output Shell command to run 0x05 IP address or subnet to access control list. Multiple subnets or single IPs (/32) can be separated by a comma, e.g. 192.168.0.1/24,10.0.0.1 0x06 Return ACL list 0x07 Clear ACL Magic packet format The packet can be visually represented as followed:  https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 5 of 18 As a “c-like struct”: struct gtp_header { uint8_t flags; uint8_t type; https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 6 of 18 uint16_t length; uint32_t tei; // technically labelled spare if type == GTP_ECHO }; struct gtpdoor_header { uint8_t pad[5]; int32_t key1; uint8_t cmdMsgType; uint16_t cmdLength; }; struct gtpdoor_packet { ip_header iph; udp_header udph; gtp_header gtph; gtpdoor_header gtpdoorh; uint8_t payload[2020]; }; Operational detail Version 1 + 2: Checks if the length of it’s filename is greater then 8 characters, and if so, process name stomps itself to become  [syslogd]  by overwriting  argv . The length check is to ensure it does not corrupt the stack. Tells the parent process to ignore signals from it’s child process be setting  SIG_IGN  for the  SIGCHLD  signal Creates a raw socket listening for UDP packets on port 2123 (GTP-C) https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 7 of 18 Accepts UDP packets on destination port  2123  with a GTP header field type value of  GTP_ECHO_REQUEST Checks that the 32 bit symmetric key is correct in order to authenticate the message. The hardcoded value in the binary is  135798642 , representative of someone typing odd numbers up the length of a keyboard even numbers back down again: https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 8 of 18 Decrypts payload in GTP message using the same authentication key using a simple XOR at fixed blocks of the key size. An equivalent implementation of the decryption routine in python: def decrypt(key, ciphertext): key_idx = 0 strlen = len(ciphertext) plaintext = bytearray(strlen) for i in range(strlen): if key_idx >= len(key): key_idx = 0 plaintext[i] = key[key_idx] ^ ciphertext[i] key_idx += 1 return plaintext https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 9 of 18 Executes a function specified message type with the primary function to execute a shell command and return the result to the remote client via a  GTP_ECHO_RESPONSE  message If the message type number is not explicitly defined, the action will fall back to the remote code execution function: The above image also shows the approximate code for the “rekeying” message type. Can write arbitrary contents to a file,  system.conf . It’s exact purpose is unknown. Specific to version 2: Multithreaded (GTP magic packet handler and TCP probe beacon handler) As the binary was not stripped and debug symbols left in, we can see the original function names  tcpMethod  and  gtpMethod  which run in two pthreads: https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 10 of 18 Creates a mutex  /var/run/daemon.pid  to prevent more then once instance running. The mutex file contains the PID of the process Acknowledge it is alive by responding to any TCP packet on any port number with an empty TCP packet with both the  RST  and  ACK  flags set. On “remote command execution”, the process is  forked()  and  popen()  is utilized to execute a subprocess on the host. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 11 of 18 All printf statements such as those observed above are emitted to  stdout . As such it is likely GTPDOOR would be invoked similar to the following (redirecting  stdin  and  stderr  to  /dev/null  and detaching from the parent process): nohup ./gtpdoor 2>&1 2>/dev/null & More on the probing feature The TCP probe is a feature that allows an external host to probe the GRX listening address for TCP packets. A subnet filter is checked against the source IP address of the “client” and if it does NOT match, a reply beacon is sent to the (scanning) client. A crafted TCP  RST/ACK  response packet with the urgent pointer field set to  0x01  indicates the implant is running. Based on the analysis of the behaviour, it appears that two types of scans are supported: TCP connect scan (simple TCP three way handshake) ACK scans (client sending an ACK message with no initial SYN) TCP Connect Scan https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 12 of 18 For a TCP connect scan to work, there must be a service listening and port exposed on the host, either from a permissive firewall or no firewall at all. GTPDOOR will send a “decoy” TCP  ACK/RST  response on the initial TCP  SYN  from the client but with no identifying information to indicate GTPDOOR is running. It is the second TCP  ACK/RST  that is sent on the client’s ACK that has the urgent pointer set to signal GTPDOOR is running on the remote host. ACK Scan For an ACK scan to work, the condition would be no firewall or a non stateful firewall (so the TCP  ACK  is not dropped due to no initial  SYN  packet from the client). No service needs to listen the TCP beaconing port with an ACK scan: as with the GTP message handler, a raw socket is used to “intercept” all TCP packets. The beacon response packet that is sent back to the probing host is manually assembled, copying the incoming packet’s relevant IP and TCP header fields into the outgoing beacon packet. The probe response packets will always have the  ACK/RST  flags set and the urgent pointer flags set according to if an  TCP ACK  was observed. This is a covert way of encoding messages by bit manipulation in the TCP header. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 13 of 18 It is assumed that packets of this combination would be rare or non-existent in normal TCP/IP communication as the URG flag is set to 0, while the urgent pointer specifies a value. Additionally, this is occurring with the RST flag set. RFC0793 states that the urgent pointer has no meaning if the URG flag is not set: We can observe the differences in a tcpdump. In the following a TCP connect() from the probe “client” on a non existing port  22222  has a probe response  RST/ACK  with the urgent pointer flat set to  0 . The assumption here is that this is a “decoy” response to blend in  RST/ACK  responses for closed or open ports on the remote host. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 14 of 18 On the other hand, when the client connects to an open port  22 (SSH) , the probe response includes a  RST/ACK  but this time with the urgent pointer set to  1 ACL functionality It is not known if the ACL is intended to be a deny list or allow list - there are pros and cons of explicitly denying IP subnets from probing: Avoid keeping threat actor C2 infrastructure network/IPs resident in memory Specify internal victim networks or host IPs to prevent causing traffic disruption from beaconed TCP reset messages. Based on analysis of the samples alone, the author assumes this behaviour is intentional. The threat actor can change their C2 infrastructure or intermediate transit hosts without loosing the ability to send probe messages. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 15 of 18 It is likely that the  RST/ACK  responses from an initial  SYN  packet is there as a decoy - a casual review of a network capture would result in one assuming that this is normal behaviour of the firewall or hosts TCP/IP stack. One would have to notice that the  RST/ACK  packet has the urgent pointer field set only for incoming  ACK  packets. Tricky indeed! An approximation of the ACL filtering. Note the  !  on line  118 : Notably one condition before TCP packets are “intercepted” by the process is the global variable  local_grx_addr  must be set first. This is set based on the destination IP address in any GTP-C packet that is received. Another condition is that the ACL must have at least one subnet or IP defined for the probe feature to be operational. Detection GTPDOOR can be identified by listing raw sockets open on the system, e.g. via  lsof , looking for  SOCK_RAW  or  raw . netstat -lp --raw  also shows listening sockets: Process name stomped files that are disguised as kernel threads can be identified by their parent process not being  kthreadd . In the following screenshot the  PPID  of the backdoor is  1935 , while the other kernel thread parent IDs are  2 : https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 16 of 18 The presence of the mutex  /var/run/daemon.pid  could be an indicator. The presence of the file  system.conf  could be an indicator. Yara rule for threat hunting: rule Linux_Malware_GTPDOOR_v1v2 { meta: description = "Detects GTPDOOR" author = "@haxrob" data = "28/02/2024" reference = "https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-T hash1 = "827f41fc1a6f8a4c8a8575b3e2349aeaba0dfc2c9390ef1cceeef1bb85c34161" hash2 = "5cbafa2d562be0f5fa690f8d551cdb0bee9fc299959b749b99d44ae3fda782e4" strings: $s1 = "excute result is" ascii fullword $s2 = "idkey not correct" ascii fullword $s3 = "send ret message" ascii fullword condition: uint16(0) == 0x457f and 2 of them and filesize < 20KB } Defence GSMA has released two relevant guidelines: FS.31 GSMA Baseline Security Controls IR.77 Inter-Operator IP Backbone Security Requirements For Service Providers and Inter-operator IP backbone Providers GTP Firewall GPTDOOR handles malformed GTP packets. In the following test, the GTP protocol type of  0  (GTP prime - charging related) is set in custom client. GTP’ does not work over the GTP-C port. Additionally the extension header is corrupt. The GTPDOOR message encrypted payload is appended on the GTP message. As such, a GTP capable firewall may detect and drop abnormal packets like this. https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 17 of 18 Firewalling The inbound UDP port is required to be open for systems that require it on the GRX network. Firewall rules should be explicit enough to drop these packets inbound for any system that does not use the GTP protocol Aggressive rules to block inbound TCP connections via the GRX - There is not a lot that actually needs to be open Probe TCP packets with RST/ACK flag set could be dropped on the GRX firewall Active GTPDOOR network scanner A multithreaded network scanner is available which can be used to scan remotes hosts in attempt to detect the presence of GTPDOOR: https://github.com/haxrob/gtpdoor-scan/ Source: https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR https://doubleagent.net/telecommunications/backdoor/gtp/2024/02/27/GTPDOOR-COVERT-TELCO-BACKDOOR Page 18 of 18