这次是跟联队最顶尖的佬们组的队,对我来说完全高端局。师傅们很厉害,给队伍干到了第四名Orz,但是我又爆零了。。。

赛后看了其他队伍的wp,misc的黑白相间这题我没做出来真的纯纯千古罪人了OrzOrzOrz

多说无益,开始复现(能看懂的题都复现一下好了)

Misc

黑白相间

发现在图片的末尾还有一张倒着的图片,提取出来

image-20250418193757284

分别读取1.png和2.png,读到黑色像素记为1,白色像素记为0,将两张图片逐个像素异或得到一个二进制字符串,from bin以后发现是个zip文件

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
from PIL import Image
def image_to_binary(image_path):
img = Image.open(image_path).convert('1')
width, height = img.size
binary_data = []
for y in range(height):
for x in range(width):
pixel = img.getpixel((x, y))
binary_data.append('1' if pixel == 0 else '0')
return ''.join(binary_data)

def xor_images(image1_path, image2_path):
binary1 = image_to_binary(image1_path)
binary2 = image_to_binary(image2_path)
if len(binary1) != len(binary2):
raise ValueError("两张图片的尺寸不一致,无法逐像素异或")
xor_result = ''.join(['1' if b1 != b2 else '0' for b1, b2 in zip(binary1, binary2)])
return xor_result
if __name__ == "__main__":
image1_path = "1.png"
image2_path = "2.png"
try:
xor_result = xor_images(image1_path, image2_path)
print("异或结果的二进制字符串:", xor_result)
except Exception as e:
print("发生错误:", e)

image-20250418194818614

但是卡在这了,解压出来的flag看了半天不知道是什么东西,结果是个去掉了头的bmp文件。。。

作为一个misc手,对bmp文件的十六进制格式还如此生疏,在此做出深刻检讨。

flag是一个去掉了头的bmp文件,在开头补上424d即可

image-20250418195500568

是一个汉信码,但是可以看出左下角的定位点被旋转过了,转回去

image-20250418201538967

image-20250418201552400

knn

大体思路就是从检测数据的csv表格中读取A车和B车的数据,根据题目名称可知用knn算法训练模型,然后对待检测数据表格中的每一行数据进行识别判断出是A车还是B车,A车记为1,B车记为0,from bin得到flag

不清楚n_neighbors是多少,写个脚本爆破一下找找合乎格式的flag即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from Crypto.Util.number import long_to_bytes
data = pd.read_csv('1.csv', encoding='gbk')
X = data[['防碰撞评分', '电池容量评分', '智能驾驶能力', '智能座舱评分']]
y = data['名称'].map({'A车': 0, 'B车': 1})
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)
for i in range(1,100):
knn = KNeighborsClassifier(n_neighbors=i)
knn.fit(X_train, y_train)
new_data = pd.read_csv('2.csv', encoding='gbk')
X_new = new_data[['防碰撞评分', '电池容量评分', '智能驾驶能力', '智能座舱评分']]
X_new_scaled = scaler.transform(X_new)
predictions = knn.predict(X_new_scaled)
result = int(''.join(map(str, predictions)),2)
print(long_to_bytes(result))

最终flag:

flag{e0f095bd-16e6-4bf5-a1c5-3dce1d693aa5}

数据安全

数据脱敏

题目要求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
为了抵抗黑客攻击导致数据拖库等问题,需要将敏感数据识别并脱敏存储成⼀个表。给定脱敏算法逻辑,要求选⼿⽣成脱敏后的数据表数据(所有数据均为随机⽣成,与现实世界⽆任何联系)。为了防⽌⼀些隐私数据泄漏,现需要对该数据表进⾏脱敏操作,请按照指定要求对各字段进⾏脱敏处理,并按照先行后列拼接字符串(不包含标题行),对此字符串进行md5计算,得到答案。

脱敏要求:
编号:⽆需脱敏。

姓名:⼆字姓名对最后⼀位字使⽤ * 进⾏替换,三字姓名对中间⼀位字使⽤ * 进⾏替换,四字姓名对中间两位字使⽤ * 进⾏替换。

手机号:请对中间五位信息使⽤ * 进⾏替换。

身份证号码:请对除了前6位信息使⽤ * 进⾏替换。

银⾏卡:请对前四位和后十位信息使⽤ * 进⾏替换。

Email:请对字符 @ 前除 . 外的字符使⽤ * 进⾏替换。

性别:替换成未知。

微信号:请对为字符的信息使用 * 进行替换。

比赛时以为是格式上有什么问题,怎么调都不对。没想到这里这个编号无需脱敏的意思是,编号也不用加到最终的字符串中。。。

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
import pandas as pd
import hashlib

def mask_name(name):
if len(name) == 2:
return name[:-1] + '*'
elif len(name) == 3:
return name[:1] + '*' + name[-1:]
elif len(name) == 4:
return name[:1] + '**' + name[-1:]
else:
return name

def mask_phone(phone):
return phone[:3] + '*****' + phone[-3:]

def mask_id(id_number):
return id_number[:6] + '*' * (len(id_number) - 6)

def mask_bank_card(bank_card):
return bank_card[:4] + '*' * (len(bank_card) - 14) + bank_card[-10:]

def mask_email(email):
parts = email.split('@')
if '.' in parts[0]:
prefix, suffix = parts[0].rsplit('.', 1)
masked_prefix = '*' * (len(prefix) - 1) + prefix[-1:] if prefix else ''
return masked_prefix + '.' + suffix + '@' + parts[1]
else:
return '*' * len(parts[0])+ '@' + parts[1]

def mask_wechat(wechat):
return '*' * len(wechat)

def process_row(row):
return {
'姓名': mask_name(str(row['姓名'])),
'手机号': mask_phone(str(row['手机号'])),
'身份证号': mask_id(str(row['身份证号'])),
'银行卡号': mask_bank_card(str(row['银行卡号'])),
'Email': mask_email(str(row['Email'])),
'性别': '未知',
'微信号': mask_wechat(str(row['微信号']))
}

# 读取xlsx文件
df = pd.read_excel('data.xlsx')

# 初始化一个列表来存储处理后的数据
processed_data = []

# 处理每一行数据
for index, row in df.iterrows():
processed_row = process_row(row)
processed_data.append(processed_row)

# 创建新的DataFrame
new_df = pd.DataFrame(processed_data)

# 将所有处理过的数据拼接成一个字符串(不包括编号)
combined_data = ''.join(new_df.apply(lambda row: ''.join(row.values.astype(str)), axis=1))
print(combined_data)
# 使用md5进行加密
md5_hash = hashlib.md5(combined_data.encode()).hexdigest()

print("Flag:", md5_hash)

# 将处理后的数据写入新的xlsx文件
new_df.to_excel('masked_data.xlsx', index=False)
#Flag: b54cc7298aaaae763d605cf87bcd714a

Crypto

NumberTheory

题目

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from Crypto.Util.number import *
import hint

flag=b'xxx'
e=65537
p=getPrime(512)
q=getPrime(512)
n=p*q
m=bytes_to_long(flag)
c=pow(m,e,n)
k=getPrime(1024)
assert hint + 233 * k == 233 * k * p
print(n)
print(c)
print(hint)

# 84099006955126261966925371456202769943592466221370095794235167154956697927281125181449320270460637820908574232493978429962263974458426503598700104493216727535451616752760724333653967152401716945549285008242019874215196489846481143398374860288545040874468108191037481101604627874268575884573685952474988256841
# 28098063654079651384124474197746356824080585622155888018279898490747561415908220072536298610509681898119018709183606442183944207485940115624047842734359988590155403601250406116023121958193303908964857108526965815235457652033182982467968474248778435731228104089366239566977364311197776651102290796373095167764
# 411245630228311610573345621334618725748702407327926883063919892785851166202383809662483938501531987094884084543300939673794551515912845363503988032311234800260819110323258416786417746444373651130257247926678135654564298408894174083333804257126735899220917359603430399033328133462456659839525671074605146583034398735379485362144932899212206419889556154825755723979850750847762362288223441051219637465296077020565435562941976546609555729574021362954126496825972439730

由题
$$
hint+233k=233kp
$$
变换得
$$
hint=233
k*(p-1)
$$
设a
$$
a^{hint}\equiv a^{233k(p-1)}(mod\ p)
$$

由费马小定理得
$$
a^{hint}\equiv1(mod\ p)
$$
因此
$$
p=gcd(a^{hint}-1,n)
$$
exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import *
import gmpy2
n=84099006955126261966925371456202769943592466221370095794235167154956697927281125181449320270460637820908574232493978429962263974458426503598700104493216727535451616752760724333653967152401716945549285008242019874215196489846481143398374860288545040874468108191037481101604627874268575884573685952474988256841
c=28098063654079651384124474197746356824080585622155888018279898490747561415908220072536298610509681898119018709183606442183944207485940115624047842734359988590155403601250406116023121958193303908964857108526965815235457652033182982467968474248778435731228104089366239566977364311197776651102290796373095167764
hint=411245630228311610573345621334618725748702407327926883063919892785851166202383809662483938501531987094884084543300939673794551515912845363503988032311234800260819110323258416786417746444373651130257247926678135654564298408894174083333804257126735899220917359603430399033328133462456659839525671074605146583034398735379485362144932899212206419889556154825755723979850750847762362288223441051219637465296077020565435562941976546609555729574021362954126496825972439730
e=65537
a=2
p=gmpy2.gcd(pow(a,hint,n)-1,n)
q=n//p
phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(long_to_bytes(m))
#flag{a3878d9436b7c80e6ecfda33b7b0b840}

能源行业

usb

又来见识新的妙妙工具了

经典usb流量,knm.py把所有hid data提取出来

image-20250425213629859

然后处理数据

image-20250425214107329

或者用祖传脚本对应按键解码hid data。解出来的东西不大精准,但大概也能看出来。

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
KEYCODE_MAP = {
0x04: 'a', 0x05: 'b', 0x06: 'c', 0x07: 'd', 0x08: 'e', 0x09: 'f', 0x0A: 'g', 0x0B: 'h',
0x0C: 'i', 0x0D: 'j', 0x0E: 'k', 0x0F: 'l', 0x10:'m', 0x11: 'n', 0x12: 'o', 0x13: 'p',
0x14: 'q', 0x15: 'r', 0x16:'s', 0x17: 't', 0x18: 'u', 0x19: 'v', 0x1A: 'w', 0x1B: 'x',
0x1C: 'y', 0x1D: 'z', 0x1E: '1', 0x1F: '2', 0x20: '3', 0x21: '4', 0x22: '5', 0x23: '6',
0x24: '7', 0x25: '8', 0x26: '9', 0x27: '0', 0x28: '\n', 0x29: 'Escape', 0x2A: 'Backspace',
0x2B: 'Tab', 0x2C:' ', 0x2D: '-', 0x2E: '=', 0x2F: '[', 0x30: ']', 0x31: '\\', 0x32: ';',
0x33: '\'', 0x34: '`', 0x35: ',', 0x36: '.', 0x37: '/', 0x38: 'Caps Lock', 0x39: 'F1',
0x3A: 'F2', 0x3B: 'F3', 0x3C: 'F4', 0x3D: 'F5', 0x3E: 'F6', 0x3F: 'F7', 0x40: 'F8',
0x41: 'F9', 0x42: 'F10', 0x43: 'F11', 0x44: 'F12', 0x45: 'Print Screen', 0x46: 'Scroll Lock',
0x47: 'Pause', 0x48: 'Insert', 0x49: 'Home', 0x4A: 'Page Up', 0x4B: 'Delete', 0x4C: 'End',
0x4D: 'Page Down', 0x4E: 'Right Arrow', 0x4F: 'Left Arrow', 0x50: 'Down Arrow', 0x51: 'Up Arrow',
0x52: 'Num Lock', 0x53: 'Keypad /', 0x54: 'Keypad *', 0x55: 'Keypad -', 0x56: 'Keypad +',
0x57: 'Keypad Enter', 0x58: 'Keypad 1', 0x59: 'Keypad 2', 0x5A: 'Keypad 3', 0x5B: 'Keypad 4',
0x5C: 'Keypad 5', 0x5D: 'Keypad 6', 0x5E: 'Keypad 7', 0x5F: 'Keypad 8', 0x60: 'Keypad 9',
0x61: 'Keypad 0', 0x62: 'Keypad .', 0x63: 'Non-US # and ~', 0x64: 'Application', 0x65: 'Power',
0x66: 'Keypad =', 0x67: 'F13', 0x68: 'F14', 0x69: 'F15', 0x6A: 'F16', 0x6B: 'F17', 0x6C: 'F18',
0x6D: 'F19', 0x6E: 'F20', 0x6F: 'F21', 0x70: 'F22', 0x71: 'F23', 0x72: 'F24', 0x73: 'Execute',
0x74: 'Help', 0x75: 'Menu', 0x76: 'Select', 0x77: 'Stop', 0x78: 'Again', 0x79: 'Undo',
0x7A: 'Cut', 0x7B: 'Copy', 0x7C: 'Paste', 0x7D: 'Find', 0x7E: 'Mute', 0x7F: 'Volume Up',
0x80: 'Volume Down'
}


def decode_usb_keyboard_data(data):
try:
bytes_data = bytes.fromhex(data.replace(" ", ""))
keys = []
for i in range(2, len(bytes_data)):
keycode = bytes_data[i]
if keycode in KEYCODE_MAP:
keys.append(KEYCODE_MAP[keycode])
return keys
except ValueError:
print("输入的不是有效的十六进制字符串")
return []


if __name__ == "__main__":
try:
with open('out.txt', 'r') as file:
s=''
for line in file:
line = line.strip()
decoded_keys = decode_usb_keyboard_data(line)
if decoded_keys:
s+=''.join(decoded_keys)
print(s)
except FileNotFoundError:
print("文件 out.txt 不存在")
#whoami 77 rm -rf Caps Lockopt

whoami && rm -rf /opt