过完年咕咕咕了十来天,现在简单总结一下年前的BeginCTF的逆向部分题解。面向WP学习CTF
红白机
附件是一个txt文本文件,里面是类似汇编的东西,没见过。后来才知道压缩包名字“6502”指的就是6502CPU汇编。
嗯看代码然后翻译成人话即可。
对照着指令集翻译。
或者直接把汇编跑一遍:在线编译
xor
题目很明显是异或相关。查壳发现是upx,还是最新版的,
脱掉后拖进ida,竟然没找到主函数。
点进start函数,跟进几次,进入这么一个函数:
代码倒是挺复杂,不过直接看最后返回值是Code,而代码中Code = sub_1400130F0()
,那就继续跟进。然后进入了这个函数:
这个函数很有意思。乍一看挺复杂,但是有很多Sleep函数,最后还有gets函数,看着像程序的初始化和输入字符界面,然后调用了sub_14001120D函数。双击跟进后发现有很多函数,随便进去几个发现都是长这样的:
和题目的“xor”对上了。回到sub_14001120D函数,直接从返回值的函数进行回溯,最终进入了这个函数:
显而易见是拿v5数组和byte_14001D7C0数组逐位对比。结合前面的好几个异或函数,只要把v5逆回去就能得到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合并,变成密文。
脚本如下:
key = [52, 49, 56, 48, 51, 56, 55, 51, 54, 50,
53, 57, 48, 49, 51, 54, 51, 48, 57, 50,
54, 48, 54, 54, 51, 50, 55, 56, 55, 57,
52, 55]
key1 = [54, 51, 50, 57, 48, 55, 57, 52, 50, 48,
55, 55, 49, 53, 53, 56, 55, 54, 55, 57,
54, 50, 49, 51, 56, 54, 55, 51, 53, 48,
48, 48]
hbkey = key[0:16] + [0]
qmkey = key[16:32] + [0]
enc = [ord(i) for i in "`agh{^bvuwTooahlYocPtmyiijj|ek'p"]
qm = enc[0:16]
hb = enc[16:32]
for i in range(16):
qm[i] ^= qmkey[16 - i]
qm[i] ^= hbkey[16 - i]
hb[i] ^= hbkey[16 - i]
hb[i] ^= qmkey[16 - i]
for i in range(16):
qm[i] ^= qmkey[i]
qm[i] ^= hbkey[i]
hb[i] ^= hbkey[i]
hb[i] ^= qmkey[i]
hbkey = key1[0:16] + [0]
qmkey = key1[16:32] + [0]
for i in range(16):
qm[i] ^= qmkey[16 - i]
qm[i] ^= hbkey[16 - i]
hb[i] ^= hbkey[16 - i]
hb[i] ^= qmkey[16 - i]
for i in range(16):
qm[i] ^= qmkey[i]
qm[i] ^= hbkey[i]
hb[i] ^= hbkey[i]
hb[i] ^= qmkey[i]
flag = "".join([chr(i) for i in qm + hb])
print(flag)
俄语学习
这道题方法很多,偷懒写个最简单的:
拖进IDA直接F5看主函数代码,前面基本都是俄语题目相关的还带答案,直接拉到最后,果然把题目答完还得填进去flag,题目没啥用。
先看if条件里的函数,跟进几次找到了疑似密文的东西:
继续跟进,找到了RC4:
回到主函数里。if条件的上一行的函数,跟进发现这里也用到了RC4,不过和上面提到过的用的密钥似乎不一样。
动态调试一下发现两处用到的密钥其实一样,那这个RC4其实没啥用???
直接密文去混淆就行了,
bbq1 = [53,109,53,100,53,119,53,100,53,98,53,110,53,109,53,100,
53,119,53,100,53,98,53,110,53,109,53,100,53,119,53,100,53,98,53,110,142]
bbq2 = [43,105,38,91,64,89,58,103,56,91,38,108,36,102,56,83,56,118,36,89,38,101,62,123]
input_str = ""
for i in range(len(bbq2)):
if i >= len(bbq1):
break
input_char = chr(bbq2[i] - bbq1[i] + 112)
input_str += input_char
print("Recovered input:", input_str)
ezpython
直接pyinstxtractor和uncompyle6连环拳反编译出python源码,发现是个SM4加密,
再反编译import那引用的pyc文件,但是我在文件夹里没找到??????
最后发现是python版本错了。原程序是python3.8编译的,那就必须用对应版本进行解包,不然解不出附属的库来。
反编译secret.pyc,得到key和enc,
尝试在线工具直接解SM4,但是失败了。
看到上面还引用了gmssl,猜测SM4被魔改了,直接把gmssl文件夹里的sm4.pyc反编译,发现对key进行了异或,对象是37,
那就搞到原始key然后直接解码,
CyberChef这个网站确实好用。
出题人的密码是什么
这道没学会,先欠着
arc
这附件好像是某个音游?没玩过。不过图标好像大小姐啊
按套路把py源码文件搞出来,结果发现被混淆了,
一看就犯恶心,先跑一下代码看看,
随便输入begin{
,
输出True。大吃一惊,flag是不是可以爆破出来?
直接gpt写exp,这里贴爆破最后一位的代码:
官方WP暂时没看明白,等以后搞懂了再复盘。
Superguesser
题目提示的很明确,这道题考察的是动调,
拖进IDA里静态分析啥也没看出来。字符串里有点线索:
给字符串下硬件断点,然后在start函数下断点,单步步入,看到了好像是密文一样的东西:
其实这里按F5就能看伪代码,
后面的加密逻辑应该是密文逐位异或。v0-25的值其实是0x33。
尝试一下爆破:
稀里糊涂地做出来了。官方WP有空再研究。
not main
看了WP发现是VEH异常处理,之前没见过这种题,超纲了属于是。学会了再来看。
ezvm babyvm
这更是超纲。vm逆向等两天再说。
goforfun
懒了。
stick game
js逆向,还有ob混淆。
打开js文件,找到被混淆的部分,
直接在线解之,
直接看见flag了23333。
real checkin xor
伟大的签到题。
异或的密文和key都给出来了,直接异或回去。