Presenting itself as a 205108 bytes statically-linked Linux ELF binary named “the-binary” (probably not the original name), this program has been found to be a Linux backdoor and denial-of-service tool.
#
file the-binary
the-binary: ELF 32-bit LSB executable,
Intel 80386, version 1, statically linked, stripped
#
md5sum the-binary
1d726de4f7fe7e580c8fad4b3e4703f6 the-binary
In the following paragraphs, we will
discuss the main features of this backdoor. We will then discuss the threats it
poses to the
The server (backdoor), when executed, forks
itself in the background, hides its process name, opens a raw socket and awaits
command packets from the wire. Each packet read is checked for a special
signature, then a command byte within the packet is tested in a switch() construct to determine what has to be done.
Depending on this command byte, the backdoor takes various actions from actual
backdoor functions to denial of service.
When run, the backdoor hides itself by changing its program name to “[mingetty]”, name of a rather standard getty-replacement for Linux consoles. It does this by erasing its argv[0] with the words “[min” “gett” “y]”. Note that this does not hide the whole word mingetty from a strings output, so we do not know exactly whether the author was trying to hide the string by doing the 3 copies (usual method) or whether it was just a convenient construct.
We also noted that there is no real anti-debugging trick implemented in the binary. For example, no ptrace() prevention is done at all, so it is possible to debug (strace, gdb, …) the binary at will.
However, we also noted that the binary is statically linked, which renders disassembly and debugging a bit harder, mostly because of the volume of the built-in libc routines.
As a side note, the libc version used is Linux libc 5.3.12, an old (1998) version of the Linux (pre-glibc) libc. We can thus deduce that the author compiled it on an old machine or wrote it awhile back.
To conclude this paragraph, we can say that
there is no real anti-debugging/anti-reversing trick used. Most problems we
encountered while reversing the binary were related to compiler optimization,
static linkage and poor coding.
The main feature of this backdoor is that it can be remotely triggered by network events. Those network events are IP packets with the following characteristics:
- IP DST address: IP of backdoored system
- IP SRC address: any IP address, possibly spoofed
- IP Proto: 11
- valid checksum (for being passed in all routers)
- packet len > 200 bytes
- first word of DATA part of packet is 0200 (command) or 0300 (reply)
- byte is then a command identifier (from 1-12)
- byte is then a decoy flag (see below)
Warning: We did not verify whether the 0200/0300 signature was a standard ip proto 11 signature (Voice over IP) or if it is actually a backdoor signature as we suspect.
Though this can be seen as an attempt at evading poorly configured NIDS or firewalls, this is (fortunately!) in our opinion a very poor choice. Instead of using standard traffic that can always be seen on the wire (for example, HTTP or DNS encapsulation), using such an obvious network oddity makes it easy to develop NIDS signatures.
The backdoor has the ability to generate network noise (decoy packets) to dissimulate real backdoor packets in many decoys. More precisely, the binary contains an array of 9 IP addresses to send responses to:
- the IP address of the real “client”
- 8 random IP addresses
Each command being received by the backdoor from the client contains a flag (byte) telling if decoys are to be sent with the response or not. If decoys are to be sent, it is done in such a way that the real response packet is dissimulated in the decoys. A usleep-based timer is also used to introduce delays between packets.
The backdoor receives and sends packets
using raw sockets. A raw socket is opened upon startup in the main() function of the program, and used to receive packets.
Responses are sent using other raw sockets, which are created each time it is
required. As a side note, we consider this as bad coding rather than any other
reason. On the other side, if promisc mode is used, the backdoor can catch
traffic sent to other IP addresses in the neighborhood. However, the author did
not directly put this functionality in the binary itself.
Because of the previous feature, it is possible for the client to send forged IP packets to the destination. Those forged packets can have forged source IP addresses; the only required valid field in the packet being the destination (compromised system) IP address, necessary for routing. Responses however have to be sent to valid IP addresses if the cracker wants to get them. To indicate the real source address (ie the real cracker address), the backdoor embeds a function we could call a “remote bind”, and which will be explained later.
The backdoor (client and server) obfuscates
each packet sent on the wire. However, the obfuscation method, shuffle and byte
arithmetic, isn’t really efficient: a construct similar to input[n]-input[n-1] is used to encrypt/decrypt, which leads to the
propagation of the original input the initializing byte was zero. This explains
why it is possible to see parts of rpcinfo outputs in the snort dumps furnished
by the
Here is a fast sample decoder for the obfuscation algorithm used:
for(i=0;i<size;i++)
{
if (i
> 0) d = data[i] - data[i-1];
else d = data[i];
d -= 23;
while
(d < 0) d+= 256;
b1[i]
= (unsigned char)d;
}
(data =
original data, b1 = unencrypted data)
This function is used to test the presence of the backdoor on the target system. Unidentified fixed data is set in the response packet, probably a signature mechanism. Unidentified dynamic data bytes are also set in the response packet, but investigations did not determine their exact use.
From the administrator point of view, this
is a convenient way to look for the presence of the backdoor on a big network. We
will ship template ping packets for that purpose.
This function allows the client to tell the backdoor the (real) IP to send responses to. As we saw previously, it is possible for the client to send commands from spoofed addresses. It is thus necessary to have a way to specify the real address for non-blind commands.
This real return address is stored in a global variable at memory address 0x807e780. Since this address does not appear to be regularly cleared, it is thus possible to determine the address of a previous use of the backdoor on a compromised system running the backdoor by attaching to the process with GDB and executing the following statement: x/4b 0x807e780.
[root@redhat
nico]# ps ax |grep \\[ming
1030 ? S
0:00 [mingetty]
[root@redhat
nico]# gdb -q ./the-binary 1030
(no debugging symbols found).../home/nico/1030: No such file
or directory.
Attaching
to program: /home/nico/./the-binary, process 1030
0x08056b74 in ?? ()
(gdb) x/4xb 0x807e780
0x807e780: 0x00
0x00 0x00 0x00
(gdb)
This function also populates the decoys list, by randomizing 4*8 bytes (4 bytes/address) in the decoys array.
Similarly, the client can order the backdoor to launch a command on the compromised system and send output in network packets back to the client.
This function is basically the same as the previous one, except that the delay before the child is killed is 10 seconds, and also that the output of the command is, through a shell redirection, put in a file called /tmp/.hj237349, on the compromised machine’s disk.
The actual command line supplied to system() is: /bin/csh -f -c \"%s\" 1> %s 2>&1
Upon command completion, the content of the output file is sent back to the IP address specified in the “remote bind” command, with decoys or not as described in the Network features. The file is ultimately unlinked from disk.
We can here question ourselves about the use of shell redirections and systems, where a popen() or similar would have done the job perfectly and more easily for an usual Unix programmer.
This instructs the backdoor to launch a DNS Reflector Denial of Service attack to a chosen target. A child is created that launches the reflection attack on the selected target. The binary has its own internal static list of 11000+ DNS servers at address 0x806d22c.
See:
- http://www.cert.org/incident_notes/IN-2000-04.html for the CERT advisory
- http://lists.insecure.org/incidents/2002/Feb/0100.html for a very good writeup about those attacks by David Dittrich)
-
http://packetstormsecurity.org/9907-exploits/DNS_DoS.txt
for a sample DNS reflection DoS tool.
The client can order the backdoor to remotely execute commands on the compromised system without bothering of the result of the command. This can for example be used to destroy the infected system, or to launch denial of service attacks against other systems.
Upon reception of the blind command request, the backdoor extract the desired command to be executed, then double-fork(), then executes the command "/bin/csh -f -c \"%s\" using the libc system() function (%s being the command to be executed, found in the packet). If the command doesn’t terminate before 1200 seconds, it is automatically killed by the first child, thus explaining the double-fork.
We find the use of the system() function
rather unusual, given the command-line constructed above. We believe it is bad
code or convenience.
The client has the ability to do a classical bindshell on TCP port 23281, which is hardcoded in the binary. Access to the bindshell is also password-protected, by the password SeNiF. Note that this password doesn’t appear in the strings output, since it each byte of the password supplied is actually incremented before comparing to the string TfOjG.
Other than that, this bindshell is written in a very usual manner, dup2()/execl(). The new shell environment is also sanitized to evade shell HISTORY files and similar.
The client can remotely order the backdoor to terminate one of its processes, which PID is stored in a global variable in the binary.
The backdoor contains several other remotely callable functions, which have not yet been identified because of a lack of time for the analysis. Most apparently are other DoS functions (SYN flooders, ICMP flooders), though this is pure speculation based on a quick glance at the assembly dump.
We reckon one more day would be appropriate to fully understand those remaining parts we did not manage to get in time.
We do not consider this tool as a major breakthrough in the field of the crackers backdoors. Even if it supplies a few interesting features, like the decoys and a stateless, non standard, obfuscated communication, the network traffic it generates appears very sloppy to us. Furthermore, no real attempt at hiding itself and preventing reverse engineering seems to be done.
However, as any incident, it must be seen as important and not as a benign network event, “things that happen”.
We thus detail the following threats:
First, it is obvious but nonetheless
important to remind that this binary has been found on a compromised
system. Understanding why the system has been compromised at the first place
would be also an important part of the incident handling work. Having it being
compromised by a known attack would demonstrate problems in the daily
enforcement of the HoneyPot security policy. Having it compromised by an
unknown vulnerability would certainly prove that the
As we saw in the Features paragraph, the
backdoor tries to hide itself in numerous ways. It is
thus possible that other backdoors may already been running on other university
systems, without anyone knowing about it.
As always in computer break-ins, it is
important to understand that even if the compromised system was not important,
the intrusion itself can become very important if the cracker uses the system
as a base for attacking others. Leaving on the network known compromised
systems can be disastrous for the reputation of the
The backdoor has the native functionality
of launching various Denial of Service attacks to any host, specified by the
client. It is thus possible for the cracker to launch such attacks from the
As detailed in the “Features” part of this document, the backdoor sends decoy packets to random locations on the Internet. More exactly, 8 decoys are sent by packet. This raises two problems:
- the backdoor could also be used as a traffic amplifier by malicious users, using the decoy functionality to generate traffic coming from the compromised system
-
the backdoor could randomly send packets to real locations on the
Internet, possibly triggering alarms at the remote side and involving the
Considering the two previous parts of this document, we recommend the following actions to be taken immediately (by order):
This can include, depending on the security
policy (which we did not have access to at the time of writing this document),
unplug the compromised system from the network, reporting the break-in to law
enforcement agencies.
A scanning program that remotely determines if a backdoor is installed on the target system can relatively easily be developed in-house, given the technical specifications described in this report. We recommend that the network staff scan the whole university network (including student machines if possible – see legal dept.).
Locally, it is possible to determine the presence of the backdoor by detecting the raw socket used for reception. This can be done by tools such as LSOF, or even netstat.
The bindshell port can also be used to determine use of the backdoor locally or remotely, by scanning TCP port 23281.
Network signatures can be installed on certain machines (also called NIDS) to detect attempts to use the backdoor. These signatures could determine attempts at contacting the compromised system again or contacting other backdoors on the network.
Signatures can be based on:
- IP PROTO 11
- (optional) DATA[0] = 02 (command) or 03 (reply), DATA[1] = 00
- (optional) PKT LEN > 200
Warning: We did not verify whether the 0200/0300 signature was a standard ip proto 11 signature (Voice over IP) or if it is actually a backdoor signature as we suspect.
A basic Snort rule (please also refer to the supplied snortrules.txt file):
alert ip any any -> any any (ip_proto:
11; msg:”IP-PROTO-11: possible backdoor traffic”;)
Another Snort rule checking for the 0200 signature:
alert ip any any -> any any (ip_proto:
11; offset: 0; content: “|0200|”; msg:”possible DoS/Backdoor traffic”;)
It is important to apply network filtering
at the perimeter limits to drop unknown incoming traffic but also ingres traffic
preventing spoofed packets to cross the border routers and thus target Internet
systems. This would be sufficient to narrow the incident to the