?Exploit creation ? The random approach? or ?Playing with random to build exploits? Sunday, September 21, 2008 By Nelson Brito <nbrito@xxxxxxxxxx> -[ Introduction It is just a matter of time to get things worse on the Internet. We saw worms getting more and more sophisticated in last decade, and, believe me, it could be worst. Nowadays we have botnets and a lot of worms and the respective variants, but what if a stealth worm reaches the Internet today? Are we prepared to deal with this kind of threat? Are we walk to the right direction to get this kind of threat controlled in a short period of time? Do we remember 2003? That said there is no other answer than: No, we are not prepared and we will surrender if such bad thing happens again. Why am I saying that? You will figurate. Just for the records: I will not write that much, even because it is very, very simple, and I do believe some one else will write a good stuff for academic audiences. If you still believe in Santa Claus, please, stop reading right now, because this paper will show that bad things can get worse, and worse, and worse, if we are not paying attention on the signs. And according to some people: it is all old news, and the techniques were already presented by someone, somewhere. Ok, then! -[ What happened during 2003? Two incredible things happened: 1. Slammer was the very first Flash Worm, incredible fast in its dissemination, it only took 15 minutes to crash all the Internet infra-structure and let us know that a new age was coming out. 2. Blaster was the very first worm targeting almost all Microsoft Windows OS versions, incredible infecting machines around the world. After Blaster we saw Sasser, and, apparently, underground became to use a ?worm template? to make new worms dissemination. These two facts combined could give us a good lesson. But, even after 1988, we didn't learn how to deal with worms and I think we have a long, long path to reach this point. So, imagine a worm using polymorphic techniques. It is the worst nightmare we couldn?t even imagine. -[ Polymorphic Code This is not a new topic and some researchers have been talking about this for years and years, but all our attention was gave to the shellcode. And even during my research, when I talked to someone about the perspective of having a real polymorphic code, people always got confused with polymorphic shellcode. No, I am not writing another paper about polymorphic shellcode, there are too many papers flying around since ADM created ADMutate, good papers about nop sled, jmp sled, junk code insertion, etc? I am writing about a real polymorphic code: a code that every time it executes it will have a new appearance, a new fingerprint, being almost unpredictable, and, yes, I will use some of the previous techniques to move forward and step ahead creating a real polymorphic attack. I have sent the ENG code already, but this is a paper to show what the techniques are and the possible damages can be caused if hackers apply such techniques in their codes. Polymorphic code means that a code will change every time it executes, making it unpredictable. What we have, so far, are static codes, and I never saw any ?dynamic? code exploiting any vulnerability. That is the reason some IPS/IDS can easily add signatures. -[ ENG (Encore Next Generation) Techniques First of all, to make a polymorphic code we have to be sure we have all the requirements to achieve the concept that a polymorphic code must be unpredictable, and it means random. I choose the MS02-039[1], because I have all the requirements for this proof of concept: 1. Microsoft Windows Buffer Overflow[2]; 2. Buffer to overflow is not too big; 3. More than just one Return Address[3]; 4. Incredible high number of writable addresses only in SQLSORT.DLL[4]. -[ MS02-039 Exploit Structure Before we start talking about the techniques applied in ENG, let?s take a look on how the exploit structure must be. David Litchfield Very First Exploit [VECTOR] [BUFFER ] [RETURN ADDRESS] [JUMP] [WRITABLE ADDRESS ] [NOPS ] [SHELLCODE] [0x04 ] [AAAABBBB...] [0x42b0c9dc ] [0x0e] [0x42ae7001 (SP0) | 0x42ae7001 (SP1-2)] [0x90 ] [STATIC ] Slammer Worm [VECTOR] [BUFFER ] [RETURN ADDRESS] [JUMP] [WRITABLE ADDRESS ] [NOPS ] [SHELLCODE] [0x04 ] [0x01 ] [0x42b0c9dc ] [0x0e] [0x42ae7001 (SP0) | 0x42ae7001 (SP1-2)] [0x90 ] [SLAMMER ] HD Moore Metsploit Framework [VECTOR] [BUFFER ] [RETURN ADDRESS] [JUMP] [WRITABLE ADDRESS ] [NOPS ] [SHELLCODE] [0x04 ] [RANDOM ] [0x42b48774 ] [0x69] [0x7ffde0cc (SP0) | 0x7ffde0cc (SP1-2)] [RANDOM] [SLAMMER ] Now, we know how we must build the exploit, and I think we can do a great job randomizing all the fields. Here are the fields ENG needs to deal with: attack vector, buffer, return address, jumps, writable address, nops, and shellcode. -[ Attack Vector For this vulnerability there are three vectors [5]: 1. 0x04: Stack Based Buffer Overflow; 2. 0x08: Heap Based Buffer Overflow; 3. 0x0a: Denial of Service. -[ Buffer [6] To fill the buffer, it does not need to be static data, so ENG uses random data to fill the entire buffer, using a very, very simple technique that any student is able to apply while learning C programming language: 1. Check the length of buffer to overflow: in this case it is 96 bytes; 2. Make a choice: lower case or mixed case; 3. Use randomized data to fill it up: lower case (0x41 to 0x5a) and (0x41 to 0x5a for odds and 0x61 to 0x7a for evens) -[ Return Address [7] The return address in any Buffer Overflow exploitation is the key to have the control of the execution flow, and that is very well known since Aleph1?s article8. As I mentioned above, a good start to figurate out if ENG can apply polymorphism in an exploit is check how many return addresses it will be able to use in its code. In this particular vulnerability there, at least, two public return addresses: David Litchfield?s 0x42b48774 (?call esp? @ SQLSORT.DLL?) and MSF?s 0x42b0c9dc (?jmp esp? @ SQLSORT.DLL). However, there are much more DLLs we can try to find new return addresses, and we are not sure that there are no more return addresses in this particular DLL, yet. >From my research, I found two more return addresses in the SQLSORT.DLL and there are much more return addresses in others DDLs. The best way to find return addresses is launching your preferred disassembler and search for them, and the easiest way to find a huge list of return address is use someone?s research. In this case I have found a huge number of possible return addresses using the great OpcodeDB9, by HD Moore and Matt Miller. Here is some possible return addresses and respective Microsoft Windows OS version: 1. Microsoft Windows 2000 SP0: * 0x750362c3 (?jmp esp? @ ws2_32.dll) * 0x776167d1 (?jmp esp? @ shell32.dll) * 0x77686c38 (?jmp esp? @ shell32.dll) * 0x776f0940 (?jmp esp? @ shell32.dll) * 0x77755f6d (?jmp esp? @ shell32.dll) * 0x77797c4d (?jmp esp? @ shell32.dll) * 0x777b5313 (?jmp esp? @ shell32.dll) * 0x777b5af7 (?jmp esp? @ shell32.dll) * 0x77e33f4d (?jmp esp? @ user32.dll) * 0x77e33f69 (?jmp esp? @ user32.dll) * 0x77e33f6d (?jmp esp? @ user32.dll) * 0x77e3c289 (?jmp esp? @ user32.dll) * 0x77f8948b (?jmp esp? @ ntdll.dll) * 0x77fb2b36 (?jmp esp? @ ntdll.dll) * 0x775be214 (?call esp? @ shell32.dll) * 0x775e5cc1 (?call esp? @ shell32.dll) * 0x7760b785 (?call esp? @ shell32.dll) * 0x7766d1b9 (?call esp? @ shell32.dll) * 0x776ee139 (?call esp? @ shell32.dll) * 0x776ee13d (?call esp? @ shell32.dll) * 0x776ee141 (?call esp? @ shell32.dll) * 0x776ee145 (?call esp? @ shell32.dll) * 0x777334fd (?call esp? @ shell32.dll) * 0x7773432d (?call esp? @ shell32.dll) * 0x77755f95 (?call esp? @ shell32.dll) * 0x777b5527 (?call esp? @ shell32.dll) * 0x77ea162b (?call esp? @ kernel32.dll) 2. Microsoft Windows 2000 SP1: * 0x69801365 (?jmp esp? @ shell32.dll) * 0x69808767 (?jmp esp? @ shell32.dll) * 0x698370d6 (?jmp esp? @ shell32.dll) * 0x698e1036 (?jmp esp? @ shell32.dll) * 0x6994f2e4 (?jmp esp? @ shell32.dll) * 0x69952208 (?jmp esp? @ shell32.dll) * 0x699b7835 (?jmp esp? @ shell32.dll) * 0x699f9515 (?jmp esp? @ shell32.dll) * 0x69a16bdb (?jmp esp? @ shell32.dll) * 0x69a173bf (?jmp esp? @ shell32.dll) * 0x75035173 (?jmp esp? @ ws2_32.dll) * 0x77e3cb4c (?jmp esp? @ user32.dll) * 0x77e4ff15 (?jmp esp? @ user32.dll) * 0x77e53e4b (?jmp esp? @ user32.dll) * 0x77e8898b (?jmp esp? @ kernel32.dll) * 0x77f967ab (?jmp esp? @ ntdll.dll) * 0x69866804 (?call esp? @ shell32.dll) * 0x6994c199 (?call esp? @ shell32.dll) * 0x6994c19d (?call esp? @ shell32.dll) * 0x6994c1a1 (?call esp? @ shell32.dll) * 0x6994c1a5 (?call esp? @ shell32.dll) * 0x69994dc5 (?call esp? @ shell32.dll) * 0x69995bf5 (?call esp? @ shell32.dll) * 0x699b785d (?call esp? @ shell32.dll) * 0x69a16def (?call esp? @ shell32.dll) * 0x77e9eba1 (?call esp? @ kernel32.dll) 3. Microsoft Windows 2000 SP2: * 0x77e2492b (?jmp esp? @ user32.dll) * 0x77e3af64 (?jmp esp? @ user32.dll) * 0x783d15fc (?jmp esp? @ shell32.dll) * 0x7843f2e4 (?jmp esp? @ shell32.dll) * 0x78442208 (?jmp esp? @ shell32.dll) * 0x784a7835 (?jmp esp? @ shell32.dll) * 0x784e9515 (?jmp esp? @ shell32.dll) * 0x78506bdb (?jmp esp? @ shell32.dll) * 0x785073bf (?jmp esp? @ shell32.dll) * 0x7503431b (?call esp? @ ws2_32.dll) * 0x77e27741 (?call esp? @ user32.dll) * 0x77e8250a (?call esp? @ kernel32.dll) * 0x782fb31b (?call esp? @ shell32.dll) * 0x7835744b (?call esp? @ shell32.dll) * 0x7843c199 (?call esp? @ shell32.dll) * 0x7843c19d (?call esp? @ shell32.dll) * 0x7843c1a1 (?call esp? @ shell32.dll) * 0x7843c1a5 (?call esp? @ shell32.dll) * 0x78484dc5 (?call esp? @ shell32.dll) * 0x78485bf5 (?call esp? @ shell32.dll) * 0x784a785d (?call esp? @ shell32.dll) * 0x78506def (?call esp? @ shell32.dll) 4. Microsoft Windows 2000 SP3: * 0x77e2afc5 (?jmp esp? @ user32.dll) * 0x77e2afc9 (?jmp esp? @ user32.dll) * 0x77e2afe5 (?jmp esp? @ user32.dll) * 0x77e388a7 (?jmp esp? @ user32.dll) * 0x783d3d81 (?jmp esp? @ shell32.dll) * 0x784432e4 (?jmp esp? @ shell32.dll) * 0x78446208 (?jmp esp? @ shell32.dll) * 0x784ab835 (?jmp esp? @ shell32.dll) * 0x784ed515 (?jmp esp? @ shell32.dll) * 0x7850abdb (?jmp esp? @ shell32.dll) * 0x7850b3bf (?jmp esp? @ shell32.dll) * 0x77e1444c (?call esp? @ user32.dll) * 0x77e3bc34 (?call esp? @ user32.dll) * 0x77e3d3f7 (?call esp? @ user32.dll) * 0x77e822ea (?call esp? @ kernel32.dll) * 0x78358d28 (?call esp? @ shell32.dll) * 0x78440199 (?call esp? @ shell32.dll) * 0x7844019d (?call esp? @ shell32.dll) * 0x784401a1 (?call esp? @ shell32.dll) * 0x784401a5 (?call esp? @ shell32.dll) * 0x78488dc5 (?call esp? @ shell32.dll) * 0x78489bf5 (?call esp? @ shell32.dll) * 0x784ab85d (?call esp? @ shell32.dll) * 0x7850adef (?call esp? @ shell32.dll) 5. Microsoft Windows 2000 SP4: * 0x77e14c29 (?jmp esp? @ user32.dll) * 0x77e3c256 (?jmp esp? @ user32.dll) * 0x782f28f7 (?jmp esp? @ shell32.dll) * 0x78326433 (?jmp esp? @ shell32.dll) * 0x78344d6f (?jmp esp? @ shell32.dll) * 0x78344d83 (?jmp esp? @ shell32.dll) * 0x78344d97 (?jmp esp? @ shell32.dll) * 0x78344dd3 (?jmp esp? @ shell32.dll) * 0x78344de7 (?jmp esp? @ shell32.dll) * 0x78344dfb (?jmp esp? @ shell32.dll) * 0x78344e23 (?jmp esp? @ shell32.dll) * 0x78344e37 (?jmp esp? @ shell32.dll) * 0x78344e4b (?jmp esp? @ shell32.dll) * 0x78344e5f (?jmp esp? @ shell32.dll) * 0x78344e73 (?jmp esp? @ shell32.dll) * 0x78344e87 (?jmp esp? @ shell32.dll) * 0x78344e9b (?jmp esp? @ shell32.dll) * 0x78344eaf (?jmp esp? @ shell32.dll) * 0x783d6ddf (?jmp esp? @ shell32.dll) * 0x784452e4 (?jmp esp? @ shell32.dll) * 0x78448208 (?jmp esp? @ shell32.dll) * 0x784ad835 (?jmp esp? @ shell32.dll) * 0x784ef515 (?jmp esp? @ shell32.dll) * 0x7850cbdb (?jmp esp? @ shell32.dll) * 0x7850d3bf (?jmp esp? @ shell32.dll) * 0x783629d0 (?call esp? @ shell32.dll) * 0x78442199 (?call esp? @ shell32.dll) * 0x7844219d (?call esp? @ shell32.dll) * 0x784421a1 (?call esp? @ shell32.dll) * 0x784421a5 (?call esp? @ shell32.dll) * 0x7848adc5 (?call esp? @ shell32.dll) * 0x7848bbf5 (?call esp? @ shell32.dll) * 0x784ad85d (?call esp? @ shell32.dll) * 0x7850cdef (?call esp? @ shell32.dll) * 0x7c4fedbb (?call esp? @ kernel32.dll) Now, ENG has enough return addresses to make the choice randomized. -[ Jumps [10] The first exploit and Slammer share the same ?jmp short 0xa0?, and the MFS uses ?jmp short 0x69?. So, ENG still has more options in this case as well, and it uses the range from ?jmp short 0x10? to ?jmp short 0x7f?, randomly. -[ Writable Address [11] According to many papers about Win32 buffer overflows, and ?The Shellcoder?s Handbook?, ENG needs to set a memory space it can write to inject the shellcode. In this case there are two approaches: 1. First exploit and Slammer uses 0x42ae7001 (SQLSORT.DLL); 2. MSF uses 0x7ffde0cc (?write to thread storage space ala msrpc?). >From my research, I found, just in SQLSORT.DLL, 25,878 ?new? writable addresses, at least: from 0x42afb1b8 (SQLSORT.DLL) to 0x42af4930 (SQLSORT.DLL). That is a huge number of possible writable memory space ENG can use randomly. The only thing ENG has to keep in mind is that it should use the writable address in two four (04) bytes blocks: first four (04) bytes block targets the Microsoft SQL Server SP0, and the second four (04) bytes block targets the Microsoft SQL Server SP1-2. -[ NOPs [12] To fill the nops? field, ENG uses the same simple technique used to fill up the buffer, but here ENG has a problem, because it uses randomized jumps it must calculate the right length, here is the formula: ((jmp >> 8) & 0xff) - (sizeof(int64_t) * 2). 1. Get the address value: ((jmp >> 8) & 0xff); 2. Decrement 128 bits: (sizeof(int64_t) * 2). Right now, the nops? field is able to be filled by random characters. -[ Shellcode There are good papers on that matter, and I don?t pretend to write a new document about this. There are just a few comments about this: 1. ENG uses Alpha2.c13; 2. ENG uses only ASCII decoders, because the UNICODE decoders doesn?t work against this vulnerability; 3. ENG injects junk codes in each decoder it uses randomly, and it is good piece of code to take a look (randnops.c), here some explanation: * Ignore the ?7QZ? and ?IQZ?, they cannot be disturbed at all; * Calculate the length of decoder, ignoring three bytes, as mentioned; * Get random number between 0 and total length available, this will control how many bytes will be injected; * Get random number to determine the position of bytes to inject; this will control the randomized positions bytes will be injected; * Check if the position is not already in use, if so skip the position and try again; * With the number of bytes to inject and the positions, inject ?A? in each position. 4. ENG uses only one ?GetPC?14 code, and it is necessary when using Alphanumeric Shellcodes15. -[ ENG Exploit Structure [VECTOR] [BUFFER ] [RETURN ADDRESS] [JUMP] [WRITABLE ADDRESS ] [NOPS ] [SHELLCODE] [0x04 ] [RANDOM ] [RANDOM ] [RAND] [RANDOM (SP0) | RANDOM (SP1-2)] [RANDOM] [RANDOM ] -[ Conslusions I do hope I could proof all the concepts behind this idea, and I will let the conclusions for anyone whom read this paper. It is too early to get the real impacts this technique can bring to next threats coming out, and forgive me for my poor English. Send any feedback, comments, flames and ideas to: nbrito@xxxxxxxxxx or nbritoo@xxxxxxxxxx Some greetings to: Emanuel Almeida (corb), Rafael Granha (netrap), Marcelo Bezerra, Raphael D?Avila, Sekure SDI members, Neel Mehta, David Maynor, Mark Dowd, Wallace John (negão), Nilson Brito, Carla Brito, Carlos Rienzi (hijo), and Daniel Austin. -[ Collision Course The main goal of ?Collision Course? is to help people to understand and evaluate the security approach some IPS/IDS still have: Pattern Matching. But, after re-started the research I realized that it could be more than just by-pass an IPS/IDS. Both NNG (Numb Next Generation) and ENG (Encore Next Generation) are available @ PacketStorm16. 1. NNG: http://www.packetstormsecurity.com/UNIX/IDS/nng-4.13r-public.rar 2. ENG: http://www.packetstormsecurity.com/UNIX/IDS/eng-4.23-public.rar [1] Microsoft SQL Server Buffer Overflow, by David Licthfield. [2] ?Win32 Buffer Overflows (Location, Exploitation and Prevention)?, issue 55, article 15, by Barnaby Jack (dark spriti). [3] In fact, just in SQLSORT.DLL there are four (04) return addresses, two are public known: 0x42b48774 and 0x42b0c9dc. [4] Read the The Shellcode?s Handbook, page 125, for further information. [5] http://www.blackhat.com/presentations/bh-asia-02/bh-asia-02-litchfield.pdf. [6] The same piece of code can be used to fill the nops? field, further information is available in this document. [7] Some people use the word Offset instead of Return Address. [8] Smashing The Stack For Fun And Profit, issue 49, article 14, by Elias Levy (Aleph1). [9] http://www.metasploit.com/opcodedb. [10] Keep in mind that this jump will influence the nops? field. [11] I didn?t want to detail the aspects in this vulnerability, because it is pretty old and many people already know all them, but in this case I must point one thing: there are, as HD Moore call them, bad characters we have to avoid. These bad characters are: 0x00, 0x0d, 0x2f, 0x3a, and 0x5c. I believe it can be more, but I didn?t spend time to find them out and assumed only these. [12] The same piece of code used to fill the buffer?s field. [13] Copyright© 2003, 2004 by Berend-Jan Wever. [14] That is only piece of code intentionally left static, but you can apply any other good polymorphic shellcode engine. [15] ?Applying Polymorphism to Alphanumeric IA-32/IA-32e/AMD-64 Shellcode?, by Matt Conover. [16] http://www.packetstormsecurity.nl/ Nelson Brito IT Security Professional {(!($^O=~/^[M]*$32/i)&&($0=~s!^.*/!!))||($0=~s!.*\\!!)}$0;