OK...I've been learning about network security for a few months now. In these few months I have learned how to write code, compile it and ultimately...compromise a machine on a network using several different methods.
When it comes to the basics of exploiting a buffer overflow vulnerability and writing code to run on the remote host, I know almost nothing...which is why I'm asking for someone with a bit more knowledge than myself to help the other members and I.
Ok. What I do know is that buffer overflows occur when attempting to write data outside of an arrays memory reference range. By this, I mean, for example, trying to assign a value to array_var[11] when array_var has only been allocated 10 slots of memory for the data in declaration.
Well even if you havn't learned Turbo Pascal (easiest language in the world) then I'm sure you can work out what the above code does. When compiled, the overflow occurs on the 11th keypress of the user. The program will then stop responding.
Maybe someone can now elaborate on this and explain what an attacker might be able to do with this (if the data was entered over a network with a streaming data socket) to compromise your system.
OneNight
Apr 5 2004, 02:31 PM
This link may help:
Haitchttp://www.uhagr.org/papers/UHAGr-Bof.txt
shaun2k2
Apr 5 2004, 02:40 PM
What you have stated so far is correct. I will attempt to explain the basic theory of stack based buffer overflow exploitation.
Certain languages such as C, C++ and Pascal don't have garbage collectors preventing data from being written outside of allocated space - other languages such as Perl and Python are therefore immune, as they do have garbage collectors to prevent this type of thing.
A buffer overflow occurs when too much data is written into a buffer, which doesn't have enough bytes allocated to hold it all. Therefore, the remainder of the data spills over the 'bounds' of the buffer, overwriting the Stack Frame Pointer, return address, several general purpose registers and other parts of the memory. The 'return address' is a very important part of program execution - this register controls the "program flow". It works basically like this:
- An instruction finishes executing - The address of the next instruction in memory is placed into EIP, the instruction pointer - this register holds the "return address" - The program "jumps" to the address held in EIP - The instruction is executed
This process basically happens in a non-ending loop until all of the instructions in the program are executed (in theory, but some instructions are in reality skipped, because users can choose different options and stuff).
So, now we know this; after the execution of an instruction, the memory address held in EIP is jumped to, and the instruction found there is executed.
However, what do we know about buffer overflows? So far we know that when more data is shoved into a buffer (array) than is physically possible, it OVERFLOWS THE BOUNDS OF THE BUFFER, "SPILLING" INTO UNAUTHORISED MEMORY. It should now be noted than data which overflows the bounds of the buffer/array, if there is enough of it, can overwrite EVERYTHING on the stack beyond the location of our buffer, in theory.
Therefore, if we overflow a buffer in a vulnerable program with enough data, WE CAN OVERWRITE EIP, THE RETURN ADDRESS. This is a VERY important concept to learn, as this is what makes exploitation of buffer overflows possible. But what if we overflow the bounds of the buffer with enough data to overwrite the content of EIP? The program *WILL* jump to that memory location. But, what if we overwrite EIP with a memory address which WE KNOW DESIRABLE CODE IS LOCATED AT? The program *WILL* execute that code! Exploited. This can potentially result in a shell or execution of any other code, if we can overflow the buffer to put that code somewhere in memory, and then overwrite EIP with the approximate address of that code.
So let's sumarise what we would need to do to exploit a buffer overflow vulnerability:
- Place our arbitrary code ("shellcode") in memory by overflowing the buffer - Overwrite EIP with the memory address of our shellcode by overflowing the buffer - The program jumps to the NEW contents of EIP - THUS EXECUTING OUR SHELLCODE
0wned
Do you understand the basic concept. If you don't, or my explanation was shitty, I WILL explain again. Don't by any means just say you did understand my explanation, if you don't understand it yet, PLEASE DO ASK ME AGAIN. I literally have all day. Drop by on IRC aswell
If you want, I will do a demo for you. Not faked - just a real demo.
-Shaun.
larsbruggie
Apr 5 2004, 03:19 PM
nice explanation
thhnx
BuzzDee
Apr 5 2004, 03:56 PM
yeah this thread could become interesting
i also have some questions on that matter - hope it isnt too much ^^:^
1.) how do u know how much data (shellcode) u can stuff into the buffer? i mean it isnt unlimited is it? does it depend on the program u want to exploit?
2.) is there a difference between offset and ret-addy or is it the same?
3.) why can u chose the ret-addy as a conastant value? i mean doesnt the ret depend on how "full" the stack is? or is the buffer always on the same place on the stack?
4.) could u generally explain how u work with that jump and call commands? i didnt really get that yet :S
5.) how many NOPs do u have to put @ the beginning of ur shellcode? does this also depend on the program u want to exploit?
well i think enough questions for now. would appreciate it if u could help me a bit. and sry for my bad english...
greetz, buzz
T3cHn0b0y
Apr 5 2004, 04:13 PM
Can I just say that the link posted by OneNight was a very good paper - I read that but did get a little confused when they started disassembling programs and overwriting the EIP to execute cached system calls.
Anyway...Shaun2k yes I do fully understand the concept of it and how it is done and the demo sounds great! Maybe you can do a win32 demo and show us how to find the exact amount of bytes it will take to cause a segment fault, where we can start inserting shellcode and then how to execute it. I've still got a great deal to learn, and my advice to other readers would be to read the paper posted by OneNight then read shaun2k's post....and hopefully he can give us a demo?
shaun2k2
Apr 5 2004, 04:47 PM
QUOTE
1.) how do u know how much data (shellcode) u can stuff into the buffer? i mean it isnt unlimited is it? does it depend on the program u want to exploit?
You generally find out how large the buffer is by looking at the program code. For example, if an overflowable buffer is called 'buf', it might be declared like this in the code:
CODE
[...] char buf[100]; [...]
This buffer has 100 bytes allocated for it. In theory, 101 bytes should overflow it, but 101 bytes usually won't produce a segmentation fault. Try 110 for a seg fault.
QUOTE
2.) is there a difference between offset and ret-addy or is it the same?
Yeah, there's a big difference, they're totally different things. An 'offset' is how far off a variable/location is from the top of the stack (stack pointer, ESP).
A return address is the address in EIP which essentially is the address of the next instruction.
QUOTE
3.) why can u chose the ret-addy as a conastant value? i mean doesnt the ret depend on how "full" the stack is? or is the buffer always on the same place on the stack?
When exploiting buffer overflows, you already know the approximate address of where your shellcode is going to be. This info is gained via trial and error, with help from a debugger such as GNU GDB or Valgrind.
The location of a buffer can move occasionally, such as when there is POPs and PUSHes (assembly programmers will know what I mean).
QUOTE
4.) could u generally explain how u work with that jump and call commands? i didnt really get that yet :S
I might've explained a little patchily. The hacker doesn't actually use those call or jmp commands - the program does that. The theory is that programs JMP to the address in EIP, thus executing the next instruction in the program. EIP = instruction pointer.
We just shove our calculated ret address into EIP and the program jmps to our shellcode.
QUOTE
5.) how many NOPs do u have to put @ the beginning of ur shellcode? does this also depend on the program u want to exploit?
I usually use around 100, but others have a lot more precision, using none at all. Yeap, it really does depend on the type of program you're sploiting. See, in theory, some buffer overflows aren't even exploitable to execute code. Whereas in others, you don't even need NOPs because you have local access and can calculate the required ret address perfectly. Note that the NOP instructions are basically if you calculate the wrong return address - if you are accurate enough to hit the NOP sled, the program will skip along executing the NOPs, and then run your code.
Sure, no prob, I can give a demo quite easily. However, note, I will be using a different technique - no shellcode. I will be using the "return-into-libc", which basically means you execute libc instead of shellcode. I find this more convenient for local exploits - it seems like a quicker alternative than messing with buggy shellcode oftentimes.
Don't get confused - the only difference than the generic exploitation method is this: Instead of placing the address of the shellcode into EIP, we place the address of a libc function into EIP instead - simple really. For example, I could put the address of 'system()' into EIP instead, with the necessary stuff to run /bin/sh. If enough people want me to execute shellcode instead, I'll do that
A show of hands please
-Shaun.
BuzzDee
Apr 5 2004, 05:16 PM
thx for ur answers first of all! that helped me a lot!
as for the demo: i would prefer a demo of a shellcode executing a cammandshell on a win32 machine! im not that much into unix yet...
greetz
BlaStA
Apr 5 2004, 06:02 PM
Yeah, this topic is very interesting.
So, how would you exploit some code like this:
CODE
int main(int argc, char *argv) { char buf[10]; scanf("%s",buf); }
Would this be possible?
shaun2k2
Apr 5 2004, 06:58 PM
Yeah, this would be quite easy. Gimme 10 minutes, and I'll post a sploit for this code.
-Shaun.
shaun2k2
Apr 5 2004, 07:45 PM
Blasta, I compiled your example program, set it to SUID root, and exploited it.
"HACK"x7 = garbage data to get \x90\x1f\x0e\x40 to overwrite EIP. \x90\x1f\x0e\x40 = the address of the 'chmod' system call on MY system. HACK = address to goto after executing the chmod syscall - no need for a real address. \x27\xfe\xff\xbf - address of OURSH environmental variable, which holds "/bin/sh". x22\xfb\xff\xbf - address of the OURMODE environmental variable, which holds S_ISUID, which means SUID.
Assuming vuln2 is SUID root, /bin/sh would now be SUID root. Woohoo!
I'm sorry about my perculiar exploitation techniques. I prefer to use perl + 'return into libc' type techniques when exploiting locally. Basically, this "perl one liner" overwrites EIP with \x90\x1f\x0e\x40, the address of 'chmod' syscall, and the other addresses, \x27\xfe\xff\xbf and \x22\xfb\xff\xbf point to the environmental variables which hold /bin/sh and the mode, S_ISUID. When I ran this command, /bin/sh was now SUID. This is because 'chmod' was called to set /bin/sh to SUID. Effectively, vuln2 was tricked into running the equivalent of this command:
CODE
chmod +s /bin/sh
Each to their own - others have cleaner exploitation methods.
THIS WON'T WORK ON ANY OTHER LINUX SYSTEM, BECAUSE THESE ARE THE ADDRESSES TO DATA ON *MY* SYSTEM, NOT YOURS.
If anyone really wants it, I'll code up an exploit which uses shellcode in C. I'm thinking about asking the admins if we can hold lectures regarding topics like buffer overflows on the GSO irc channel. I hope to be able to expand more on there.
However, the point is, I exploited it. I can explain things as well as write a better sploit, if anyone really cares .
-Shaun.
x1`
Apr 5 2004, 07:59 PM
so this is a new exploit thats been discovered or just testing ?
Blackknight
Apr 5 2004, 08:32 PM
Its an example exploit... The easist exploits to do are the ones that use Enviroment variables to store the shellcode.. You dont even have to have a NOP sled you can get the exact location of the shellcode and avoid ids detection just by doing the math.. and getting the exact location and keep in mind litte-endian.. which means 0xbfff8080 would have to be put into memory like \x80\x80\xff\xbf
BlaStA
Apr 5 2004, 09:08 PM
So, I got 2 questions:
1) Why did u use the perl command (echo `perl -e 'print "..."'`)? Can't you just use echo "HACK\x90\x1f\x0e\x40HACK\x27\xfe\xff\xbf\x22\xfb\xff\xbf"? 2) How did u get the offsets of the chmod call and your two variables OURSH and OURMODE?
brOmstar
Apr 5 2004, 10:29 PM
Ok I here i go hope that nobody beats me for that
I found a (I thought) very simple example of a way the buffer can be manipulated.
The code ############
CODE
#include <stdio.h>
void function(int a, int b, int c) {
char buffer1[8]; char buffer2[16];
int *ret;
ret = buffer1+12;
(*ret)+=8;
}
void main() {
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n",x);
}
This code should manipulate the buffer so that the instruction "x = 1;" is not executed and jumps directly to the printf-instruction, this manipulation should be done with the line "(*ret)+=8;". But I only get an error and the program crashes.
Can someone explain me what is wrong with that example?
T3cHn0b0y
Apr 5 2004, 11:46 PM
I'm not sure it's actually possible that way. Use some assembly language to munipulate the EIP instead:
__asm__(" add $0x??, %eip ret ")
From your code I can't tell how much to add to the Infrastructure Pointer but I think you can do it this way.
Blackknight
Apr 6 2004, 01:00 AM
you cant use echo because it doesnt convert the hex values to ascii to pass to the buffer and you can make a simple c program to get the enviorment variables address char *hax; hax=getenv(argv[1]); if(hax==NULL) exit(1); printf("%s locatated at %p\n,argv[1],hax);
archphase
Apr 6 2004, 06:57 AM
QUOTE
I'm not sure it's actually possible that way. Use some assembly language to munipulate the EIP instead:
__asm__(" add $0x??, %eip ret ")
From your code I can't tell how much to add to the Infrastructure Pointer but I think you can do it this way.
OK its a microsoft compiler, aint gonna use at&t assembly..__asm { }. Second you cant directly change EIP, its a protected registar due to a threading protected operating system (Windows, Linux, etc..) so you can use syscalls or Win32 API SetThreadContext or use
CODE
push xxxxx; addr ret
brOmstar: umm I want to say different implmentations of c runtime..use ollydbg to check the delta between x=1; and printf..oh ya and weve all seen Smashing stack for fun and profit so i dont think you beated anyones imporant
shaun2k2
Apr 6 2004, 09:35 AM
Listen to blackknight, he knows his shit.
QUOTE
1) Why did u use the perl command (echo `perl -e 'print "..."'`)? Can't you just use echo "HACK\x90\x1f\x0e\x40HACK\x27\xfe\xff\xbf\x22\xfb\xff\xbf"?
I believe blackknight already explained. 'echo' will just echo the exploit payload as it already is. Consider this:
The exploit buffer is printed "as-is". On another note, we also use 'perl -e' because sometimes we need to repeat garbage data (padding) or return addresses, hence the "HACK"x7. This repeats HACK 7 times. We use this garbage data for padding because 32 bytes are needed to overwrite the EIP register (32 bytes includes the new return address itself). Don't bug yourself about WHY 32 bytes are needed - I had already experimented with Blasta's example program for 5 minutes before writing the perl one-liner exploit - thus learning the amount of data required to zap out EIP.
QUOTE
2) How did u get the offsets of the chmod call and your two variables OURSH and OURMODE?
As blackknight was explaining, you can simply use the 'getenv()' library function in Linux, store the outpt in a pointer, and then use the %p printf format parameter to print the actual address of the desired variable.
I wrote a simple C program to get the address of a user-specified environmental variable - this is the one I used for the experiments I have presented briefly in this thread.
CODE
/* getenv.c - get address of an environmental variable. */ #include <stdio.h> #include <stdlib.h>
if(addr_ptr == NULL) { printf("Environmental variable %s does not exist!\n", argv[1]); exit(-1); }
printf("%s is stored at address %p\n", argv[1], addr_ptr); return(0); }
As blackknight stated earlier, to make exploitation via stack based buffer overflow vulnerabilities a lot easier, we often use environmental variables to store shellcode, eliminating the need for NOPs (often referred to as "NOP sleds" for obvious reasons). The almost exact address of the environmental variable holding shellcode or otherwise (i.e instead of shellcode, stuff needed for "return into libc" exploits) can be calculated quite easily, this address can be used to overwrite EIP, execution flow with jump to your environmental variable, and the shellcode will be executed.
For the other part of your question, the static addresses of LIBC functions on a particular machine (used when using the 'return into libc' technique I showed briefly) can be found quite easily using a debugging. Let me demonstrate:
CODE
[shaun@localhost shaun]$ cat <<EOF >> dummy.c > int main() { > system(); > } > [shaun@localhost shaun]$ cat dummy.c int main() { system(); } [shaun@localhost shaun]$ gcc dummy.c -o dummy [shaun@localhost shaun]$ gdb dummy 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"... (gdb) break main Breakpoint 1 at 0x8048342 (gdb) run Starting program: /home/shaun/dummy
Breakpoint 1, 0x08048342 in main () (gdb) p system $1 = {<text variable, no debug info>} 0x40061310 <system> (gdb) quit The program is running. Exit anyway? (y or n) y [shaun@localhost shaun]$
Above, I create a stupid dummy program calling 'system()' with a NULL argument. I compiled it, and then ran the GNU GDB debugger. It's essential that you become familiar with gdb, it's included with most all linux distributions. I used gdb commands to set a break point on main(), ran the program, and then printed the address of the LIBC 'system()' function. The memory address of 'system()' on MY system just happens to be '0x40061310'. When you consider little-endian byte ordering, and convert to hex, you get the following:
\x10\x13\x06\x40
I know it's leet looking, but all it really is is 0x40061310 with the bytes reversed (because of little-endian byte ordering - the bytes have to be reversed) with '\x' before every value. Easy, huh? No probs.
Now that we have the address of 'system()' we can shove values into environmental variables and get the address of them using the above program I pasted. By doing this properly, it's quite easy to get a shell. Note that even if vulnprog was SUID root, the shell wouldn't be root, because system() executes commands via /bin/sh, which drops the privileges first. However, execl() could be called with only a little bit more work, or you could call 'chmod()' to set SUID privs on a desired program - hence my example of the previous page. I could've created a program which executes a shell (not with system()), and then exploit vulnprog to execute the chmod() call to set SUID privs on my shell-exec program. And since vulnprog was SUID root, my shell-exec program now runs with root privileges - even though I didn't exploit vulnprog to execute a shell, I still have a root shell waiting for me
Maybe I've just rambled on a bit. Maybe we can get a lecture going in #gso-chat on our new irc server.
Blackknight - would you be willing to do a lecture with me for the guys? We could demonstrate the methods we just discussed; placing code in environmental variables, and overwriting EIP with the address of the environ variable. What do yer think?
-Shaun.
Blackknight
Apr 6 2004, 11:19 AM
Yeah would be good to give to the community good bunch of guys.. I can even tell you howto write your own shellcode and how the calls are made.. so you can pretty much write any shellcode you want Will even tell you howto print it so u can easily import into a file...
Windows shellcode is a bit of a tedious task and requires screenshots normally.. so we should start off with linux and see where people are at and what needs to be done
But yeah post ideas on what you guys want the lecture to be about.. i can explain very indepth on how the whole process works. And explain why it works etc.. and tricks to avoid IDS detection
edit: Note when you are explotining using getenvaddr the env variable will be padding the shellcode etc.. so keep that in mind because if its not divisible by 4 you will have a segment overflow
ScriptGod
Apr 6 2004, 11:42 AM
QUOTE (T3cHn0b0y @ Apr 5 2004, 11:46 PM)
I'm not sure it's actually possible that way. Use some assembly language to munipulate the EIP instead:
__asm__(" add $0x??, %eip ret ")
From your code I can't tell how much to add to the Infrastructure Pointer but I think you can do it this way.
the EIP register cannot be overwriten normally! to exploit a stack overflow you need to overwrite the return address to get control of the EIP
in assembler: main: [...] 0x00400100 call function_with_overflow_inside (0x00420000) [...]
function_with_overflow_inside 0x00420000 [...] 0x00421000 ret <- return to 0x00400100
after the call the address 0x00400100 is written on the stack. with an overflow you overwrite this address. ret gets the address of the stack an jumps to it
if your input string is larger then 100 bytes you overwrite the return address .THIS your new EIP after the ret is called.
this address should point to an instruction "jmp esp" or "call esp" so our code AFTER the new return/eip address IN "input" is called.
then you have complete control of it
BlaStA
Apr 6 2004, 05:57 PM
An IRC-lecture would be great, but I think it could get difficult because of the different time zones. I, for example, live in Germany. Don't know where you live?!
Another prob I see is, that I don't know much about Linux. I installed Knoppix under Vmware on my laptop, but don't know if this is the best?!
shaun2k2
Apr 6 2004, 06:43 PM
Blackknight has agreed to do a lecture with me. He'll be head-lecturer - we'll give details of when a little later.
We will keep a log of the lecture, so something can still be gained from it. Any questions that weren't asked because of absence can be asked in a thread we open, to distribute the IRC log.
To help combat the problem of misunderstandings and not having Linux, we are going to prepare lecture notes after the lecture is over, helping people further with concepts explained. We will also seperate the lecture into seperate parts, such as Windows, Linux, etc. Blackknight has access to Windows & Linux, so it shouldn't be a problem.
-Shaun.
T3cHn0b0y
Apr 6 2004, 09:52 PM
OK. Thanks guys for taking the time to do this but could you keep in mind for the lecture that I'm still pretty uneducated as far as programming is concerned. I understand the concepts of exploiting a segment fault vulnerability (aka stack overflow) but only understand what I've been taught in college about assembly code and registers, which, inconveniently, isn't much
I'll read some stuff about dynamic memory allocation and hex etc. before the lecture, as to be up to scratch on my knowledge of what your gonna be talking about.
Thanks again
Blackknight
Apr 6 2004, 10:51 PM
and script god is right u never overwrite the eip.. you overwrite the stack frame pointer so it jumps to ur function after that function has finnished.. In asm you can actually right a lil piece of code that prevents this
yuliang11
Apr 7 2004, 06:42 AM
cool . can't wait for the lectures. this topic is very interesting. thanks a lot to all of you
bambipower
Apr 7 2004, 02:56 PM
Gonna install linux again, very nice there people that want to show his skills and want to teach people
krackatoa
Apr 9 2004, 03:59 AM
Interesting discussion. I'd like to hear more about Windows stack based overflows while you guys are at it.
I've already read every Windows based text that I could find on the web. There hasn't really been a clear tutorial on windows using a simple C++ applet that actually details exploitation from start to cms shell or cmd execution.
archphase
Apr 9 2004, 05:54 AM
QUOTE (krackatoa @ Apr 9 2004, 03:59 AM)
Interesting discussion. I'd like to hear more about Windows stack based overflows while you guys are at it.
I've already read every Windows based text that I could find on the web. There hasn't really been a clear tutorial on windows using a simple C++ applet that actually details exploitation from start to cms shell or cmd execution.
LSD-PL Paper or Matt Millers paper, what else do you need?
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.