last updated-2.24
参考链接:
BeginCTF官方WP - 飞书云文档 (feishu.cn)
BeginCTF 2023 Reverse 题目附件 - 飞书云文档 (feishu.cn)
BeginCTF2024 RE WP 部分复现-CSDN博客
Reverse目前未复现:ezvm,babyvm,真龙之力
Misc
real check in
为了选手有更好的游玩体验请及时加入beginctf2024官方群,群号:612995005
从catf1y的笔记本中发现了这个神秘的代码MJSWO2LOPNLUKTCDJ5GWKX3UN5PUEM2HNFXEGVCGL4ZDAMRUL5EDAUDFL5MU6VK7O5UUYMK7GEYWWZK7NE3X2===
你能帮助我找到最后的flag吗?
直接basecrack一波得到
begin{WELCOMe_to_B3GinCTF_2024_H0Pe_YOU_wiL1_11ke_i7}
devil’s word
leu lia leu ng leu cai leu jau leu e cai b cai jau sa leng cai ng ng f leu b leu e sa leng cai cai ng f cai cai sa sa leu e cai a leu bo leu f cai ng ng f leu sii leu jau sa sii leu c leu ng leu sa cai sii cai d
我当时的思路看到了有15个字符,且出现了a b c d e f 盲猜是16进制,只要推断出leng lia sa sii ng leu ai bo jau 代表的数字,然后两两一组 根据flag格式是begin{}
1696
没推出来的就要爆破了
for (ii,jj,kk) in [(1,4,8),(1,8,4),(4,8,1),(4,1,8),(8,1,4),(8,4,1)]:
replace_dict={'lia':'2','leng':'0','cai':'7',
'jau':'9',
'au':f'{ii}',
'sii':f'{jj}',
'leu':'6',
'bo':f'{kk}',
'sa':'3',
'ng':'5'
}
newlist=[]
for x in mylist:
for key,value in replace_dict.items():
x=x.replace(key,value)
newlist.append(x)
list2=list(' '.join([newlist[i]+newlist[i+1] for i in range(0,len(newlist),2)]).split(' '))
list3=[]
for it in list2:
list3.append(chr(int(it,16)))
print(''.join(list3))
最后一个一个试出来
begin{y0u_kn0w_w3nzhou_di4lect}
事实上预期解法是这样的
魔鬼的语言是一个梗,指的是温州话。
密文中除了i是单个字母外,其他单个字母都是a-f,说明可能是十六进制。
那么这些奇奇怪怪的单词应该是温州话数字的读音。
去搜索温州话读音就能知道那些语言代表什么,还是要提高自己的信息搜索能力
你知道中国文化嘛
4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFX4KMLDYUYWLRJRNXCTCZ6FGFT4KMLJYUYW7RJRMXCTC26FGFV4KMLFYUYWHRJRMPCTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNHCTC26FGFS4KMLDYUYW7RJRMXCTCY6FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLNYUYWLRJRMHCTC2OFGFT4KMLJYUYW3RJRMXCTC3OFGFT4KMLFYUYWLRJRNPCTCZ6FGFU4KMLNYUYWLRJRNXCTCZOFGFS4KMLPYUYWPRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRNXCTCZOFGFW4KMLHYUYWLRJRMXCTC26FGFT4KMLJYUYW3RJRMXCTC3OFGFS4KMLFYUYW7RJRM7CTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC3OFGFS4KMLFYUYW3RJRMXCTCYOFGFX4KMLHYUYWTRJRNXCTCZOFGFT4KMLBYUYWLRJRMPCTC3OFGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGF$4KMLJYUYWPRJRM7CTC2OFGFV4KMLFYUYW7RJRMPCTCZOFGFW4KMLHYUYWPRJRNHCTC36FGFS4KMLLYUYWXRJRMXCTCY6FGFR4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLLYUYWLRJRN7CTCY6FGFS4KMLNYUYWPRJRM7CTC2OFGFX4KMLFYUYWXRJRNPCTCZOFGFR4KMLDYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYW7RJRMXCTCY6FGFQ4KMLFYUYW3RJRMPCTCZ6FGFU4KMLLYUYWLRJRM7CTCZ6FGFS4KMLPYUYWXRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFX4KMLDYUYWLRJRNXCTCZ6FGFT4KMLJYUYW7RJRMXCTC26FGFV4KMLFYUYWHRJRMPCTCZ6FGFU4KMLLYUYWLRJRMXCTCZOFGFS4KMLDYUYWTRJRM7CTC26FGFQ4KMLFYUYW3RJRMHCTCZOFGFS4KMLBYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGFS4KMLJYUYWPRJRM7CTC26FGFQ4KMLFYUYWDRJRN&CTCZOFGFV4KMLFYUYWPRJRNHCTC36FGFS4KMLFYUYWTRJRMXCTC3OFGFR4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLPYUYWLRJRMPCTCYOFGFS4KMLNYUYWHRJRM7CTC2OFGFV4KMLFYUYWPRJRM7CTCZOFGFX4KMLLYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYWXRJRMXCTC26FGFX4KMLFYUYWHRJRNHCTCZ6FGFU4KMLLYUYWLRJRN&CTC2OFGFS4KMLPYUYWLRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRN7CTCZOFGFR4KMLBYUYWLRJRNXCTCY6FGFT4KMLJYUYWXRJRMXCTCZ6FGFT4KMLFYUYW7RJRNPCTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGFS4KMLJYUYWPRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLNYUYWLRJRNXCTCZ6FGFS4KMLFYUYWXRJRM7CTC2OFGFW4KMLFYUYW3RJRMXCTCZOFGFX4KMLHYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTC36FGFR4KMLFYUYW3RJRM7CTCZ6FGFU4KMLPYUYWLRJRNPCTC26FGFS4KMLDYUYWHRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWXRJRMHCTCZOFGFQ4KMLPYUYWLRJRNPCTCZOFGFT4KMLJYUYW7RJRMXCTCZOFGFU4KMLFYUYW3RJRMPCTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNPCTCYOFGFS4KMLLYUYW7RJRMXCTCZ6FGFS4KMLHYUYWTRJRNHCTCZOFGFX4KMLPYUYWLRJRNHCTCY6FGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFV4KMLFYUYWLRJRMXCTCZOFGFR4KMLJYUYWPRJRNPCTCYOFGFS4KMLNYUYWDRJRMXCTCZOFGFQ4KMLHYUYWTRJRNXCTCZOFGFS4KMLNYUYWLRJRMHCTC36FGFT4KMLJYUYW3RJRMXCTCZ6FGFQ4KMLFYUYWHRJRNXCTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC26FGFS4KMLPYUYWHRJRMXCTC3OFGFT4KMLHYUYWTRJRN7CTCZOFGFV4KMLLYUYWLRJRMPCTCY6FGFT4KMLJYUYWXRJRMXCTCYOFGFV4KMLFYUYWXRJRNHCTCZ6FGFU4KMLNYUYWLRJRNPCTC26FGFS4KMLJYUYWPRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLNYUYWLRJRMXCTC26FGFS4KMLLYUYWTRJRM7CTC2OFGFU4KMLFYUYW7RJRMHCTCZOFGFT4KMLFYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLLYUYWDRJRMXCTCYOFGFX4KMLFYUYWXRJRMXCTCZ6FGFU4KMLPYUYWLRJRMXCTC2OFGFS4KMLNYUYWHRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFQ4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYW3RJRMXCTC26FGFV4KMLFYUYWTRJRM7CTCZ6FGFU4KMLNYUYWLRJRNXCTCZ6FGFS4KMLFYUYWXRJRM7CTC2OFGFW4KMLFYUYW3RJRMXCTCZOFGFX4KMLHYUYWPRJRNHCTC26FGFS4KMLDYUYW7RJRMXCTCY6FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLNYUYWLRJRMHCTC2OFGFT4KMLJYUYW3RJRMXCTC3OFGFT4KMLFYUYWLRJRNPCTCZ6FGFU4KMLNYUYWLRJRNXCTCZOFGFS4KMLPYUYWPRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNXCTCZOFGFS4KMLLYUYWLRJRNPCTC2OFGFT4KMLJYUYWTRJRMXCTC36FGFQ4KMLFYUYWPRJRMXCTCZ6FGFU4KMLNYUYWLRJRNXCTCZ6FGFS4KMLFYUYWXRJRM7CTC2OFGFW4KMLFYUYW3RJRMXCTCZOFGFX4KMLHYUYWPRJRNHCTC26FGFS4KMLDYUYW7RJRMXCTCY6FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLNYUYWLRJRMHCTC2OFGFT4KMLJYUYWXRJRMXCTC36FGFR4KMLFYUYW3RJRM7CTCZ6FGFU4KMLPYUYWLRJRNPCTC26FGFS4KMLDYUYWHRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNXCTCZOFGFW4KMLBYUYWLRJRMXCTCY6FGFT4KMLJYUYWTRJRMXCTC36FGFQ4KMLFYUYW7RJRM7CTCZ6FGFU4KMLLYUYWLRJRMXCTCZOFGFS4KMLDYUYWTRJRM7CTC26FGFQ4KMLFYUYW3RJRMHCTCZOFGFS4KMLBYUYWPRJRNHCTC3OFGFS4KMLNYUYWPRJRMXCTCZOFGFV4KMLHYUYWTRJRNXCTCZOFGFW4KMLFYUYWLRJRN7CTCZ6FGFT4KMLJYUYW3RJRMXCTCZOFGFW4KMLFYUYWDRJRN7CTCZ6FGFU4KMLNYUYWLRJRM7CTCYOFGFS4KMLDYUYW3RJRM7CTC26FGFQ4KMLFYUYWXRJRN7CTCZOFGFT4KMLFYUYWPRJRNHCTC2OFGFS4KMLPYUYW7RJRMXCTC2OFGFR4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLLYUYWLRJRMXCTCZOFGFS4KMLDYUYWTRJRM7CTC26FGFQ4KMLFYUYW3RJRMHCTCZOFGFS4KMLBYUYWPRJRNHCTC3OFGFS4KMLNYUYWDRJRMXCTCZOFGFR4KMLHYUYWTRJRNHCTCZOFGFX4KMLBYUYWLRJRN7CTCZ6FGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFX4KMLFYUYWHRJRMHCTCZOFGFW4KMLDYUYWPRJRNHCTC26FGFS4KMLHYUYWPRJRMXCTC36FGFV4KMLHYUYWTRJRNXCTCZOFGFS4KMLNYUYWLRJRMHCTC36FGFT4KMLJYUYW3RJRMXCTCZ6FGFQ4KMLFYUYWHRJRNXCTCZ6FGFV4KMLBYUYWLRJRNPCTC36FGFS4KMLHYUYWLRJRM7CTC2OFGFU4KMLFYUYW7RJRN7CTCZOFGFU4KMLDYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYWXRJRMXCTCZOFGFS4KMLFYUYWHRJRNHCTCZ6FGFV4KMLBYUYWLRJRNXCTCYOFGFS4KMLFYUYWDRJRM7CTC2OFGFW4KMLFYUYW3RJRMHCTCZOFGFS4KMLDYUYWPRJRNHCTC2OFGFS4KMLPYUYWDRJRMXCTC36FGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLNYUYWLRJRMXCTC3OFGFS4KMLBYUYW7RJRM7CTC2OFGFW4KMLFYUYWPRJRMHCTCZOFGFR4KMLNYUYWPRJRNHCTC26FGFS4KMLBYUYWXRJRMXCTC26FGFU4KMLHYUYWTRJRNXCTCZOFGFV4KMLLYUYWLRJRNHCTCZ6FGFT4KMLJYUYWXRJRMXCTCY6FGFX4KMLFYUYWHRJRM7CTCZ6FGFU4KMLLYUYWLRJRMXCTC3OFGFS4KMLBYUYWTRJRM7CTC2OFGFX4KMLFYUYWHRJRMHCTCZOFGFW4KMLDYUYWPRJRNHCTC26FGFS4KMLHYUYWPRJRMXCTC36FGFV4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC@OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLPYUYWLRJRMPCTCYOFGFS4KMLNYUYWHRJRM7CTC2OFGFV4KMLFYUYWPRJRM7CTCZOFGFX4KMLLYUYWPRJRNHCTC26FGFS4KMLFYUYWLRJRMXCTCY6FGFU4KMLHYUYWXRJRMHCTCZOFGFW4KMLBYUYWLRJRMXCTCYOFGFT4KMLJYUYW3RJRMXCTC3OFGFQ4KMLFYUYWLRJRMPCTCZ6FGFU4KMLJYUYWLRJRN7CTCYOFGFS4KMLPYUYWPRJRM7CTC2OFGFV4KMLFYUYWDRJRNPCTCZOFGFV4KMLJYUYWPRJRNHCTC3OFGFS4KMLLYUYWXRJRMXCTC2OFGFT4KMLHYUYWTRJRNPCTCZOFGFS4KMLFYUYWLRJRMPCTC2OFGFT4KMLLYUYWDRJRMXCTC3OFGFQ4KMLFYUYWLRJRMHCTCZ6FGFU4KMLLYUYWLRJRMHCTC26FGFS4KMLLYUYWTRJRM7CTC@OFGFW4KMLFYUYWXRJRNPCTCZOFGFU4KMLHYUYWPRJRNHCTC26FGFS4KMLPYUYWHRJRMXCTC3OFGFT4KMLHYUYWTRJRN7CTCZOFGFV4KMLLYUYWLRJRMPCTCYQ====
我当时看到后面====就猜测是个base32但是我解码解不出来 就很奇怪
先解密前面部分可以看到解密出来了八卦 有特殊字符,直接替换一下:$换成S &换成P @换成2
这个是真难猜啊,这个地方谁想得到
解密后随波逐流一把梭
☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☴☵☲☱☷☲☱☳☳☴☵☲☲☶☲☰☴☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☷☲☱☰☲☶☱☳☴☵☲☳☳☲☷☵☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☵☰☲☰☷☲☵☲☳☴☷☲☲☴☲☶☱☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☷☲☱☰☲☶☱☳☴☵☲☳☳☲☷☵☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☵☷☲☱☴☳☴☵☲☷☴☲☷☲☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☷☲☱☰☲☶☱☳☴☵☲☳☳☲☷☵☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☵☰☲☰☷☲☵☲☳☴☷☲☲☴☲☶☱☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☵☰☲☵☷☲☳☲☳☴☴☲☷☷☲☴☱☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☲☵☲☵☴☳☴☴☲☷☰☲☳☲☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☵☰☲☰☷☲☵☲☳☴☷☲☲☴☲☶☱☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☵☲☱☷☲☱☳☳☴☵☲☲☶☲☰☴☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☶☲☲☵☲☵☴☳☴☴☲☷☰☲☳☲☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☵☲☱☷☲☱☳☳☴☵☲☲☶☲☰☴☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☶☲☶☰☲☲☱☳☴☴☲☷☰☲☷☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☶☳☲☲☵☳☴☶☲☶☲☲☷☳☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☵☰☲☵☷☲☳☲☳☴☴☲☷☷☲☴☱☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☶☰☲☲☱☳☴☴☲☷☰☲☷☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☷☲☱☰☲☶☱☳☴☵☲☳☳☲☷☵☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☵☰☲☵☷☲☳☲☳☴☴☲☷☷☲☴☱☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☶☰☲☲☱☳☴☴☲☷☰☲☷☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☲☶☲☰☷☳☴☶☲☳☰☲☱☶☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☱☷☲☱☳☳☴☵☲☲☶☲☰☴☳☴☷☲☱☰☲☶☱☳☴☵☲☳☳☲☷☵☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☷☲☱☰☲☶☱☳☴☵☲☳☳☲☷☵☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☶☲☶☰☲☲☱☳☴☴☲☷☰☲☷☳☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☲☲☲☱☴☳☵☰☲☶☰☲☲☰☳☴☵☲☰☵☲☵☴☳☴☶☲☵☵☲☴☳☳☴☵☲☷☱☲☶☳☳☴☷☲☵☵☲☱☱
八卦解码
公正文明公正和谐公正平等文明友善法治和谐法治公正文明公正平等公正平等和谐爱国公正平等和谐和谐公正自由和谐爱国和谐富强和谐爱国公正公正公正和谐公正法治公正平等公正自由文明诚信和谐和谐文明公正平等公正公正和谐敬业和谐自由公正公正法治友善法治公正敬业法治友善平等公正民主和谐法治文明诚信和谐和谐民主和谐爱国文明诚信和谐和谐民主和谐文明公正友善爱国和谐爱国和谐民主公正和谐公正平等
社会主义核心价值观解码
bce-7bee8e3d808fcged-2ef94f}i{a7-18-12n81ce
显然是栅栏,直接一把梭
W型栅栏分为5栏时
解密结果为:begin{eec8da87-ee32-11ed-8f8c-907841e2ffbc}
下一站上岸
使用010 Editor打开图片看到最后有一段BASE64,解码得到:“提示:摩斯密码”根据提示找图片中图形规律,查看图像中的交点发现,两个交点代表 - 一个交点代表 . 没有交点代表空格
得到摩斯密码: --. — …–.- .- … … — .-. .
解密后加上begin{}得到flag:begin{go_ashore}
Tupper
解压完看到里面txt文件内容像是某种编码,先写脚本提取发现是base64,然后cyberchef解码,结合题目名找网站生成图片,写脚本的也可以,网站https://tuppers-formula.ovh/
Reverse
real checkin xor
def verify_func(ciper,key):
encrypted = []
for i in range(len(ciper)):
encrypted.append(ciper[i]^ord(key[i%len(key)]))
return encrypted
secret = [7, 31, 56, 25, 23, 15, 91, 21, 49, 15, 33, 88, 26, 48, 60, 58, 4, 86, 36, 64, 23, 54, 63, 0, 54, 22, 6, 55, 59, 38, 108, 39, 45, 23, 102, 27, 11, 56, 32, 0, 82, 24]
key = "ez_python_xor_reverse"
flag = verify_func(secret,key)
print("".join(flag))
#begin{3z_PY7hoN_r3V3rSE_For_TH3_Be9inNEr!}
红白机
问了下GPT,是6502汇编,google一下发现有个6502在线编译器,直接一把梭了
看了官方Wp,本意是让你翻译指令集,然后手搓一个简单的编译器,我是真不会,学习一下dl的脚本
import re
arr = [1]*0x400
with open("code.txt", "r") as f:
lines = f.readlines()
A = -1
X = -1
Y = -1
for line in lines:
line = line.strip("\n")
if line.startswith("LDX"):
mat = re.search(r"LDX \#\$(.*)", line)
X = int(mat.group(1), 16)
elif line.startswith("LDA"):
mat = re.search(r"LDA \#\$(.*)", line)
A = int(mat.group(1), 16)
elif line.startswith("STA"):
mat = re.search(r"STA \$(.*),X", line)
off = int(mat.group(1), 16)
off -= 0x200
arr[off+X] = A
elif line.startswith("INX"):
X += 1
for i in range(0x20):
for j in range(len(arr)//0x20):
if arr[i*0x20+j] == 0:
print("*", end="")
else:
print(" ", end="")
print()
Xor
首先查壳 发现存在upx壳 用upx-d脱壳得到原来程序
直接shift+f12查找到flag字符串然后交叉引用jump到关键函数,发现
这个是函数的主逻辑,可以把sleep给nop掉,防止动态浪费时间
可以发现先get了一个字符串,然后进入了一个加密函数,里面有4个函数,慢慢分析
加密函数内部分成了两个函数,这两个函数内部各有四个函数,这八个函数共同组成了flag的加密算法
依次分析这八个函数,我们可以发现,这是一个仿轮式加密的算法
算法先将前32个字符拆分成相同长度的两段,我们称之为输入1和输入2,再将长度为32的密钥同样拆分为两段,密钥1和密钥2
第一轮中会将:
输入1和密钥2异或
输入2和密钥1异或
输入1和密钥1异或
输入2和密钥2异或
输入1和逆序密钥2异或
输入2和逆序密钥1异或
输入1和逆序密钥1异或
输入2和逆序密钥2异或
第二轮加密同理,只是将之前的密钥换成了其他密钥
在两轮加密结束后,将输入2和输入1合并,变成密文
通过判断密文是否为`agh{^bvuwTooahlYocPtmyiijj|ek'p来输出结果的正确与否
第一轮的key63290794207715587679621386735000
第二轮的key41803873625901363092606632787947
都是异或,根据异或的可逆性,我们直接把密文输入进去然后就可以得到flag了,直接动调
也可以写脚本直接逆,无非是麻烦点
data6 = bytearray.fromhex("606167687b5e62767577546f6f61686c")
data5 = bytearray.fromhex("596f6350746d7969696a6a7c656b2770")
a4 = bytearray.fromhex("3431383033383733363235393031333600")
a5 = bytearray.fromhex("3330393236303636333237383739343700")
for i in range(16): data5[i] ^= a4[16 - i]
for i in range(16): data6[i] ^= a5[16 - i]
for i in range(16): data5[i] ^= a4[i]
for i in range(16): data6[i] ^= a5[i]
for i in range(16): data5[i] ^= a5[16 - i]
for i in range(16): data6[i] ^= a4[16 - i]
data1 = bytearray.fromhex("3633323930373934323037373135353800")
data2 = bytearray.fromhex("3736373936323133383637333530303000")
for i in range(16): data5[i] ^= a5[i]
for i in range(16): data6[i] ^= a4[i]
data4 = data5
data3 = data6
for i in range(16): data3[i] ^= data2[16 - i]
for i in range(16): data4[i] ^= data1[16 - i]
for i in range(16): data3[i] ^= data1[16 - i]
for i in range(16): data4[i] ^= data2[16 - i]
for i in range(16): data3[i] ^= data2[i]
for i in range(16): data4[i] ^= data1[i]
for i in range(16): data3[i] ^= data1[i]
for i in range(16): data4[i] ^= data2[i]
flag = data3 + data4
print(flag.decode())
后面的逆向题就都不会写了,以下逆向题全是复现
俄语学习
找到主函数,直接拉到最后的主要加密函数
进入加密函数内部,有strlen还要%256大概率是RC4,重命名进行分析,的确,但是不一样的地方在于没有box初始化函数,box是已经给出来的,所以破解rc4关键要找到box的值,但是box是空的,猜测前面的函数可能决定了box的取值,懒得去前面的一坨翻所以直接动态调试提取密码吧
再进入判断函数
程序的正向逻辑,梳理一遍就是这样的
输入flag
```
for ( i = 0; ; ++i )
{
v0 = j__strlen(flag); // flag和str1哪个小用哪个
v3 = v0 >= j__strlen(str1) ? j__strlen(str1) : j__strlen(flag);
if ( i > v3 )
break;
flag2[i] = flag[i] + str1[i] - 112;
}
```flag 经过此逻辑后变为 flag2 ,对flag2进行rc4,box变换
密文是+i&[@Y:g8[&l$f8S8v$Y&e>{
对密文进行rc4,box2 然后与flag2比较
box=358E0B78B4F6319CD92CC1FCE2D81D8D4F978126C0B89627D55BAA1885FA61E4A1BCF8A4563743582BC97764CC6B986575388009113DD0E68FA9579906105DC569BD2D687EE367D1FF5EF9F5418CDD214BA747866DC32A9A9F2048BB94B97A9202747D1B1E5FBA49D6E75304CB283FE8333E009B6AFDBE1C90EDDF4D256FB513703C9E160C054A73DEB18A513B5414E05ADC9162A395D33A17EE32F27CAFB388EC0EAE9D5C0D554EFB46224445BF52126607D236936E421A0FE960CAB26C83F00376A81F63EFA5CD797B0ADAABDBD47F01342359E129C6ACA240C8ADC489C2B671A0EB2F19F3B0FECEF78472F4CFC7D7B7F14C8230502E24870839E5EAA68B15
box2=35F1DA197AF6319CD92CC1FCE2D81D8D4F978126C0B89627D55BAA1885FA61E4A1BCF8A4563743582BC97764CC6B986575388009113DD0E68FA9579906105DC569BD2D687EE367D1FF5EF9F5418CDD214BA747866DC32A9A9F2048BB94B9B49202747D1B1E5FBA49D6E75304CB283FE8333E009B6AFDBE1C90EDDF4D256FB513703C9E160C054A73DEB18A513B5414E05ADC9162A395D33A17EE32F27CAFB388EC0EAE9D5C0D554EFB46224445BF52126607D236936E421A0FE960CAB26C83F00376A81F63EFA5CD797B0A0BABDBD47F01342359E129C6ACA240C8ADC489C2B671A0EB2F78F3B0FECEF78472F4CFC7D7B78E4C8230502E24870839E5EAA68B15
两个box的值都是一样的,rc4如加,直接逆前面那段逻辑就行了,
这个就是给box的函数,懒得逆了,rnm写到这发现没提str1[]的值,又坐一遍牢
enc='+i&[@Y:g8[&l$f8S8v$Y&e>{'
Str1='5m5d5w5d5b5n5m5d5w5d5b5n5m5d5w5d5b5n\x8e'
flag=''
for i in range(min(len(enc),len(Str1))):
flag+=chr(ord(enc[i])-ord(Str1[i])+112)
print(flag)
#flag{Russian_is_so_easy}
EzPython
首先利用pyinstxtractor工具拆包得到ezpython.exe_extracted
在里面找到ezpython.pyc文件,使用uncompyle6 反编译出源码
这里有个坑,如果python版本不对,作者自己写的东西是提不出来的,用conda下个3.8提取作者写的东西
如果用其他版本的py提会导致ezpython.exe_extracted\PYZ-00.pyz_extracted是空的
(python37) PS C:\Users\Npc\.conda\envs\python37\Scripts> .\uncompyle6.exe .\ezpython.pyc
# uncompyle6 version 3.9.0
# Python bytecode version base 3.8.0 (3413)
# Decompiled from: Python 3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 05:35:01) [MSC v.1916 64 bit (AMD64)]
# Embedded file name: ezpython.py
from gmssl import sm4
from secret import key, enc
import base64
def pad_pkcs7(data):
"""PKCS#7填充"""
padding_len = 16 - len(data) % 16
padding = bytes([padding_len] * padding_len)
return data + padding
def unpad_pkcs7(padded_data):
"""PKCS#7去填充"""
padding_len = padded_data[-1]
return padded_data[:-padding_len]
class SM4:
def __init__(self):
self.gmsm4 = sm4.CryptSM4()
def encryptSM4(self, encrypt_key, value):
gmsm4 = self.gmsm4
gmsm4.set_key(encrypt_key.encode(), sm4.SM4_ENCRYPT)
padded_value = pad_pkcs7(value.encode())
encrypt_value = gmsm4.crypt_ecb(padded_value)
return base64.b64encode(encrypt_value)
if __name__ == '__main__':
print('请输入你的flag:')
flag = input()
sm4_instance = SM4()
flag_1 = sm4_instance.encryptSM4(key, flag)
if flag_1 != enc:
print('flag错误!!')
else:
print('恭喜你获得flag😊😀')
# okay decompiling .\ezpython.pyc
uncompyle secret库
# Embedded file name: secret.py
key = 'BeginCTFBeginCTF'
enc = b'JmjJEAJGMT6F9bmC+Vyxy8Z1lpfaJzdEX6BGG/qgqUjUpQaYSON1CnZyX9YXTEClSRYm7PFZtGxmJw6LPuw1ww=='
# okay decompiling C:\Users\Npc\Desktop\CTF\beginCTF\beginctfRE\ezpython\ezpython.exe_extracted\PYZ-00.pyz_extracted\secret.pyc
加密逻辑实际上是对flag进行一次SM4加密
# Embedded file name: gmssl\sm4.py
import copy
from .func import xor, rotl, get_uint32_be, put_uint32_be, bytes_to_list, list_to_bytes, pkcs7_padding, pkcs7_unpadding, zero_padding, zero_unpadding
SM4_BOXES_TABLE = [
214, 144, 233, 254, 204, 225, 61, 183, 22, 182, 20, 194, 40, 251, 44,
5, 43, 103, 154, 118, 42, 190, 4, 195, 170, 68, 19, 38, 73, 134,
6, 153, 156, 66, 80, 244, 145, 239, 152, 122, 51, 84, 11, 67, 237,
207, 172, 98, 228, 179, 28, 169, 201, 8, 232, 149, 128, 223, 148, 250,
117, 143, 63, 166, 71, 7, 167, 252, 243, 115, 23, 186, 131, 89, 60,
25, 230, 133, 79, 168, 104, 107, 129, 178, 113, 100, 218, 139, 248, 235,
15, 75, 112, 86, 157, 53, 30, 36, 14, 94, 99, 88, 209, 162, 37,
34, 124, 59, 1, 33, 120, 135, 212, 0, 70, 87, 159, 211, 39, 82,
76, 54, 2, 231, 160, 196, 200, 158, 234, 191, 138, 210, 64, 199, 56,
181, 163, 247, 242, 206, 249, 97, 21, 161, 224, 174, 93, 164, 155, 52,
26, 85, 173, 147, 50, 48, 245, 140, 177, 227, 29, 246, 226, 46, 130,
102, 202, 96, 192, 41, 35, 171, 13, 83, 78, 111, 213, 219, 55, 69,
222, 253, 142, 47, 3, 255, 106, 114, 109, 108, 91, 81, 141, 27, 175,
146, 187, 221, 188, 127, 17, 217, 92, 65, 31, 16, 90, 216, 10, 193,
49, 136, 165, 205, 123, 189, 45, 116, 208, 18, 184, 229, 180, 176, 137,
105, 151, 74, 12, 150, 119, 126, 101, 185, 241, 9, 197, 110, 198, 132,
24, 240, 125, 236, 58, 220, 77, 32, 121, 238, 95, 62, 215, 203, 57,
72]
SM4_FK = [
2746333894, 1453994832, 1736282519, 2993693404]
SM4_CK = [
462357, 472066609, 943670861, 1415275113,
1886879365, 2358483617, 2830087869, 3301692121,
3773296373, 4228057617, 404694573, 876298825,
1347903077, 1819507329, 2291111581, 2762715833,
3234320085, 3705924337, 4177462797, 337322537,
808926789, 1280531041, 1752135293, 2223739545,
2695343797, 3166948049, 3638552301, 4110090761,
269950501, 741554753, 1213159005, 1684763257]
SM4_ENCRYPT = 0
SM4_DECRYPT = 1
PKCS7 = 0
ZERO = 1
class CryptSM4(object):
def __init__(self, mode=SM4_ENCRYPT, padding_mode=PKCS7):
self.sk = [0] * 32
self.mode = mode
self.padding_mode = padding_mode
@classmethod
def _round_key(cls, ka):
b = [0, 0, 0, 0]
a = put_uint32_be(ka)
b[0] = SM4_BOXES_TABLE[a[0]]
b[1] = SM4_BOXES_TABLE[a[1]]
b[2] = SM4_BOXES_TABLE[a[2]]
b[3] = SM4_BOXES_TABLE[a[3]]
bb = get_uint32_be(b[0:4])
rk = bb ^ rotl(bb, 13) ^ rotl(bb, 23)
return rk
@classmethod
def _f(cls, x0, x1, x2, x3, rk):
def _sm4_l_t(ka):
b = [
0, 0, 0, 0]
a = put_uint32_be(ka)
b[0] = SM4_BOXES_TABLE[a[0]]
b[1] = SM4_BOXES_TABLE[a[1]]
b[2] = SM4_BOXES_TABLE[a[2]]
b[3] = SM4_BOXES_TABLE[a[3]]
bb = get_uint32_be(b[0:4])
c = bb ^ rotl(bb, 2) ^ rotl(bb, 10) ^ rotl(bb, 18) ^ rotl(bb, 24)
return c
return x0 ^ _sm4_l_t(x1 ^ x2 ^ x3 ^ rk)
def set_key(self, key, mode):
key = bytes_to_list(key)
key = [k ^ 37 for k in key]
MK = [0, 0, 0, 0]
k = [0] * 36
MK[0] = get_uint32_be(key[0:4])
MK[1] = get_uint32_be(key[4:8])
MK[2] = get_uint32_be(key[8:12])
MK[3] = get_uint32_be(key[12:16])
k[0:4] = xor(MK[0:4], SM4_FK[0:4])
for i in range(32):
k[i + 4] = k[i] ^ self._round_key(k[i + 1] ^ k[i + 2] ^ k[i + 3] ^ SM4_CK[i])
self.sk[i] = k[i + 4]
else:
self.mode = mode
if mode == SM4_DECRYPT:
for idx in range(16):
t = self.sk[idx]
self.sk[idx] = self.sk[31 - idx]
self.sk[31 - idx] = t
def one_round(self, sk, in_put):
out_put = []
ulbuf = [
0] * 36
ulbuf[0] = get_uint32_be(in_put[0:4])
ulbuf[1] = get_uint32_be(in_put[4:8])
ulbuf[2] = get_uint32_be(in_put[8:12])
ulbuf[3] = get_uint32_be(in_put[12:16])
for idx in range(32):
ulbuf[idx + 4] = self._f(ulbuf[idx], ulbuf[idx + 1], ulbuf[idx + 2], ulbuf[idx + 3], sk[idx])
else:
out_put += put_uint32_be(ulbuf[35])
out_put += put_uint32_be(ulbuf[34])
out_put += put_uint32_be(ulbuf[33])
out_put += put_uint32_be(ulbuf[32])
return out_put
def crypt_ecb(self, input_data):
input_data = bytes_to_list(input_data)
if self.mode == SM4_ENCRYPT:
if self.padding_mode == PKCS7:
input_data = pkcs7_padding(input_data)
else:
if self.padding_mode == ZERO:
input_data = zero_padding(input_data)
else:
length = len(input_data)
i = 0
output_data = []
while True:
if length > 0:
output_data += self.one_round(self.sk, input_data[i:i + 16])
i += 16
length -= 16
if self.mode == SM4_DECRYPT:
if self.padding_mode == PKCS7:
return list_to_bytes(pkcs7_unpadding(output_data))
if self.padding_mode == ZERO:
return list_to_bytes(zero_unpadding(output_data))
return list_to_bytes(output_data)
def crypt_cbc(self, iv, input_data):
i = 0
output_data = []
tmp_input = [0] * 16
iv = bytes_to_list(iv)
if self.mode == SM4_ENCRYPT:
input_data = pkcs7_padding(bytes_to_list(input_data))
length = len(input_data)
while True:
if length > 0:
tmp_input[0:16] = xor(input_data[i:i + 16], iv[0:16])
output_data += self.one_round(self.sk, tmp_input[0:16])
iv = copy.deepcopy(output_data[i:i + 16])
i += 16
length -= 16
else:
return list_to_bytes(output_data)
length = len(input_data)
while True:
if length > 0:
output_data += self.one_round(self.sk, input_data[i:i + 16])
output_data[i:i + 16] = xor(output_data[i:i + 16], iv[0:16])
iv = copy.deepcopy(input_data[i:i + 16])
i += 16
length -= 16
return list_to_bytes(pkcs7_unpadding(output_data))
# okay decompiling C:\Users\Npc\Desktop\CTF\beginCTF\beginctfRE\ezpython\ezpython.exe_extracted\PYZ-00.pyz_extracted\gmssl\sm4.pyc
直接SM4一把梭,结果发现得不到flag,猜测SM4加密算法进行了魔改
120299
diff一下sm4源码发现key多^了个37,直接在原有的基础上写解密脚本
from gmssl import sm4
import base64
def pad_pkcs7(data):
"""PKCS#7填充"""
padding_len = 16 - len(data) % 16
padding = bytes([padding_len] * padding_len)
return data + padding
def unpad_pkcs7(padded_data):
"""PKCS#7去填充"""
padding_len = padded_data[-1]
return padded_data[:-padding_len]
class SM4:
def __init__(self):
self.gmsm4 = sm4.CryptSM4()
def decryptSM4(self, encrypt_key, value):
gmsm4 = self.gmsm4
gmsm4.set_key(encrypt_key.encode(), sm4.SM4_DECRYPT)
padded_value = pad_pkcs7(value)
decrypt_value = gmsm4.crypt_ecb(padded_value)
return decrypt_value
if __name__ == '__main__':
key1 = 'BeginCTFBeginCTF'
key=''
enc = b'JmjJEAJGMT6F9bmC+Vyxy8Z1lpfaJzdEX6BGG/qgqUjUpQaYSON1CnZyX9YXTEClSRYm7PFZtGxmJw6LPuw1ww=='
for i in key1:
key+=chr(ord(i)^37)
sm4_instance = SM4()
flag = sm4_instance.decryptSM4(key, base64.b64decode(enc))
print(flag)
# b'flag{Pay_M0re_@ttention_to_th3_key!!}\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'
出题人的密码是什么
先查壳,无壳,直接ida打开
最后得到函数主逻辑
想找到函数加密的逻辑只能一个一个地翻函数,翻了三十多个,找到了账号的加密方式
从二进制角度理解更容易逆向
和0比较实际上是比较最高位(标志位)是0还是1:
- 如果是1(负数),就左移一位(*2)与key异或
- 由于key最后一位是1,v6左移一位最后一位是0,异或结果最后一位必然是1。因此逆向的时候,如果一次加密后最后一位是1,这次加密前它肯定是负数
- 如果是0(正数),就左移一位,最后一位就变成0。同理,最后一位是0的本次加密前一定是正数。
类似CRC的部分需要动调获得key的值,虽然是随机生成的但是其值不变
enc1=[0xB4, 0xBB, 0xD8, 0xEB, 0xD0, 0x6E, 0xAB, 0xCA, 0x65, 0x8E, 0x4B, 0xE9, 0x4D, 0xD4, 0x4A, 0xF3, 0x7D, 0x29, 0xC2, 0xF9, 0x95, 0x89, 0xA4, 0x85, 0x9D, 0xCD, 0xDF, 0x77, 0xFD, 0x45, 0xCB, 0x5D, 0x7D, 0xFD, 0x93, 0x4B, 0xBC, 0xF6, 0x7C, 0xF3, 0x24, 0x42, 0xF5, 0xD2, 0xDD, 0xE3, 0x56, 0xAE]
key = 0x33077D
enc=[]
#异或部分逆向
for i in range(len(enc1)):
b=((enc1[i]^0x25)-5)&0xff
enc.append(b)
#CRC部分加密
def decrc(value,key):
for i in range(64):
if value&1 :
value=(value^key)>>1#最后一位是1,加密前肯定是负数
value |= 0x8000000000000000
else:#最后一位是0,加密前必为正数
value=value>>1
return value
flag=b''
for i in range(0,len(enc),8):
enc1=int.from_bytes(enc[i:i+8],'little')
flag+=decrc(enc1,key).to_bytes(8,'little')
print(flag)
# b'begin{Th1s_reverse_pr0blem_may_t@ke_some_time#!}'
stick game
使用js在线工具格式化然后这是混淆后的代码,找到score发生改变 的位置,手动给score加点分
Arc
这题的基本思路是这样的
[[1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0], [1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0], [1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0], [1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0], [1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0], [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0], [1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0], [1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0], [1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0], [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0], [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0], [1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0], [1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0], [1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0], [1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0], [1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0], [1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0], [1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0], [1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0], [1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0], [1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0]]
接着分析后面的主要逻辑
使用了一堆列表推导式完成循环结构,对应逻辑如下:
1.遍历input,获取index和context
2.遍历b"beginCTF"为x,进行 ((ord(context) << 0x6 ^ 0x7 + 0xFFF - index) ^ x) 运算,然后求和
(出题人对着出题源码搓的exp,数值表达上略有出入)
3.转为bin,去除0b两个字符,保留原始的二进制数据,遍历出来转为int存为list
4.一个字符对应一个list,组成list[list[int]],与data进行比较,全相等(all)则输出True
然后直接手搓出正向解密脚本
from string import printable
data=[...]
ndata=[int("".join(map(str,x)),2)for x in data]
for i,y in enumerate(ndata):
for x in printable:
if sum((ord(x))<<6^4102-i^k for k in b'beginCTF') == y:
print(x,end='')
# begin{Y@u_aRe_g00d_aT_play1ng_witH_sNake
熟练嵌套列表推导式的分析,以及map,enumer的使用
SuperGuessor
直接写出解密脚本
data =bytearray.fromhex("5151525f59435d5f59495a59562e261d2a371a27291728242a3825213d0f323a3c3d36332a")
for i in range(37):
print(chr(data[i] ^ (i + 51)), end="")
Not main
具体的原理在官方WP,看不懂,先简单记录一下操作流程,以后深入了解原理
通过实现一个全局类让程序在main函数之前就执行类的构造函数,在main函数结束后执行类的析构函数。
nt3断点的处理逻辑是,当前程序在main函数中会执行事先放置的int3,此时如果在未调试的情况下,程序将异常交给veh处理,将一个dword_405038赋值为0. 如果是调试情况下将异常交给调试器处理,如果此时调试器处理异常则不会交给veh,则dword_405038为1.main函数接下来会对输入进行虚假的判断。在判断后进入到析构函数中
析构函数会根据先前的dword_405038即图中的is_debug变量的值判断是否除零。除零进入到veh handler的除零异常处理块中
在这里进行真正的检测。正常的xxtea加密。构造函数和析构函数可以在start->__scrt_common_main_seh->initterm((_PVFV *)&dword_403140, (_PVFV *)&dword_403154);
所以正向的流程是
实现一个全局类,在main函数之前就执行类的构造函数
main函数开始 进行tea加密
main函数结束
析构函数开始
判断isdebug =0 进入异常处理块
进行btea加密
所以直接逆向就可以了
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x9e3779b9
#define MX (((z>>5^y<<2)+(y>>3^z<<4))^((sum^y)+(key[(p&3)^e]^z)))
void btea(uint32_t* v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1)
{
rounds = 6 + 52 / n; //这里可以说是预定义值,n=2是rounds=32
sum = 0;
z = v[n - 1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p = 0; p < n - 1; p++) //注意这里的p是从0~n-1
{
y = v[p + 1];
z = v[p] += MX;
}
y = v[0];
z = v[n - 1] += MX; //这里的MX中传入的p=n-1
} while (--rounds);
}
else if (n < -1)
{
n = -n;
rounds = 6 + 52 / n;
sum = rounds * DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p = n - 1; p > 0; p--) //注意这里的p是从n-1~0,和上面是反过来的
{
z = v[p - 1];
y = v[p] -= MX;
}
z = v[n - 1];
y = v[0] -= MX; //这里的MX中传入的 p=0
sum -= DELTA;
} while (--rounds);
}
}
void detea(uint32_t* v, uint32_t* k) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
uint32_t delta = 0x9e3779b9;
uint32_t k0 = k[0], k1 = k[1], k2 = k[2], k3 = k[3];
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
v0 -= ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
sum -= delta;
}
v[0] = v0; v[1] = v1;
}
int main()
{
uint32_t v[8] = { 0xCFBE0F1B, 0x05F3083F, 0x4220E43B, 0x3383AFEE, 0xFA3237CE, 0xECADA66E, 0xA8D47CA7, 0xEFC51077 };
uint32_t k[4] = { 116,114,117,101 };//true
uint32_t fk[4] = { 0x66,0x61,0x6B,0x65 };//fake
int i, n = 8;
btea(v, -n, k);//负号是解密
for (i = 0; i < 8; i += 2)
detea(v + i, fk);
printf("%s", v);//begin{not_main_is_matter!}
return 0;
}
Goforfun(待复现)
函数主体都看不明白,放着以后再看
先贴一下exp
def big_int_to_byte_array(big_int):
ans=[]
while big_int :
ans.append(big_int&0xff)
big_int>>=8
return ans[::-1]
cmpString = "HZ0sMJXqxHgUb2b9RNg+1xw"
str1 = "8G+cazk2jqb7w01CtoKH4FsrgR3vVmQ9pPhXLAleOd/nB6DfIxMWYiUZ5SEJyNuT"
cmpString = list(cmpString)
str1 = list(str1)
tmp=[]
for i in cmpString:
tmp.append(str1.index(i))
print('index:')
print(tmp)
bignum = 0
for i in range(len(tmp)-1,-1,-1):
bignum = bignum*0x40 + tmp[i]
#print('bignum:')
#print((bignum))
bytea = big_int_to_byte_array(bignum)
#print(bytea)
def rc4_crypt(key, data):
S = list(range(255,-1,-1))
j = 0
out = []
# 初始化S盒
for i in range(256):
j = (j + S[i] + ord(key[i % len(key)]) ) % 256
S[i], S[j] = S[j], S[i]
# 生成密钥流并加解密
i = j = 0
for char in data:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = S[j], S[i]
out.append(((char) ^ S[(S[i] + S[j]) % 256]^0x2f))
return out
key1='happynewyear'
key1 = list(key1)
flag=rc4_crypt(key1,bytea)
for i in flag:
print(chr(i),end='')
Crypto
我玩青水的
题目描述
from Crypto.Util.number import *
from secret import flag
m = bytes_to_long(flag)
e = 2
p = getPrime(512)
c = pow(m, e, p)
print(f"p = {p}")
print(f"c = {c}")
'''
p = 7709388356791362098686964537734555579863438117190798798028727762878684782880904322549856912344789781854618283939002621383390230228555920884200579836394161
c = 5573755468949553624452023926839820294500672937008992680281196534187840615851844091682946567434189657243627735469507175898662317628420037437385814152733456
'''
e=2,很自然地想到低指数加密攻击,我直接暴力枚举了
import gmpy2
from Crypto.Util.number import bytes_to_long, long_to_bytes
from tqdm import tqdm
import time
p = 7709388356791362098686964537734555579863438117190798798028727762878684782880904322549856912344789781854618283939002621383390230228555920884200579836394161
c = 5573755468949553624452023926839820294500672937008992680281196534187840615851844091682946567434189657243627735469507175898662317628420037437385814152733456
i = 1000000000
max_attempts = 10000000000000000
with tqdm(total=max_attempts, desc="Decrypting", unit="iteration") as pbar:
while i < max_attempts:
root, is_exact = gmpy2.iroot(c + i * p, 2)
if is_exact:
print(long_to_bytes(int(root)))
break
i += 1
pbar.update(1) # 更新进度条
# time.sleep(0.01) # 可选的睡眠,以减缓进度条更新速度
else:
print("Exceeded maximum attempts. Decryption failed.")
运行15分钟大概就出了
但是看了官方wp发现这是一个二次剩余问题,可以用sagemath直接秒,还是要多熟悉sagemath的语法以及函数
from Crypto.Util.number import *
sage: from Crypto.Util.number import *
sage: p = 7709388356791362098686964537734555579863438117190798798028727762878684
....: 78288090432254985691234478978185461828393900262138339023022855592088420057
....: 9836394161
sage: c = 5573755468949553624452023926839820294500672937008992680281196534187840
....: 61585184409168294656743418965724362773546950717589866231762842003743738581
....: 4152733456
sage: R.<m> = PolynomialRing(Zmod(p))
sage: f = (m^2) - c
sage: m0 = f.roots()[1][0]
sage: flag=long_to_bytes(int(m0))
sage: print(flag)
b'begin{quadr4ticresidue_i5_s0_3asy}'
OEIS2
题目描述
from hashlib import *
upper = 2**28 + 5
res = 1
for i in range(1, upper + 1):
res *= i
flag = 'Beginctf{' + sha256(str(sum([int(i) for i in str(res)])).encode()).hexdigest() + '}'
应该是需要优化算法,加快阶乘的计算,没看懂OEIS2的题目是什么意思,我查表没查出来,也不会手搓优化算法
我直接sagemath挂着跑
from hashlib import sha256
x = gamma(2 ** 28 + 6)
b = str(x)
res = 0
for i in b:
res += int(i)
print(sha256(res))
#c60a2e5c9e9572ed848776f282a9c90d6ca0fe29f8308b0b9b43c61d493133e9