furryCTF-Lua
Lua编码
1 | local b = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' |
最底下解base64可得

Lua码就可以看到了,我们使用unluac可得以下代码
1 | local L1_1, L2_1, L3_1, L4_1, L5_1, L6_1, L7_1, L8_1, L9_1, L10_1, L11_1, L12_1, L13_1 |
概括就是异或114。
furryCTF-分组密码
期待了很久的AES算法题。
进入main逻辑
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
首先说明了flag格式,遍历所有函数后确认这是略有魔改的AES算法128位密钥模式,那么main逻辑里面那个地方就是密钥扩展混淆逻辑。
可以确认xmmword_403270和xmmword_403280是目标密文
1 | int __fastcall sub_4010B0(char *a1, int a2) |
可知sub_4010B0为AES算法中的轮换和列混淆函数。现在来看看传参,这个函数传入了v13和v37,由于main逻辑存在以下代码
1 | n0x20 = 0; |
可以推断v13为输入明文,而由于这个mm_xor_ps()是SSE指令,作用是将128位寄存器按位异或存储到另一个寄存器上,即v13^=v12,所以v12,即v39,就是初始向量。if的条件判断是放溢出,保证数据安全,无需过多在意。那么此时就可以确定v37是密钥。
那么现在我们密钥,初始向量,密文都有了,由于密钥混淆扩展函数写在main逻辑里面,那么那里的byte_403258就无疑是轮常数了。好,现在数据全齐,逻辑也大多摸清楚。检查魔改。
发现在轮换逻辑中
1 | sub_401050(v4); |
与普通的AES轮换不同,这里异或了一个常数0x66。函数sub_401050为
1 | char *__thiscall sub_401050(char *this) |
那么很明显这个就是标准的S盒查表替换混淆。
最终逆向脚本如下
1 |
|
噢噢对,值得注意的一点是,这里的轮换函数与标准的AES也不同,所以在逆向的时候需要按着IDA里面的逻辑来,以及异或的位置不要放错了
furryCTF-TimeManager
一道蛮有意思的题目,不算特别难,main逻辑如下
1 | int __fastcall main(int argc, const char **argv, const char **envp) |
摸清楚几个地方
v6和v7是不同的,即使它们都被赋值为time(0),但是由于所在位置的不同,所以它们触发的时间也就不同,那么v6和v7就是不一样的。由于程序进入循环后会sleep一秒,所以srand里面表达式的意义就在于循环次数加dword_6043,然后就是常规异或
1 | // attributes: thunk |
但是值得注意,这题是在Linux环境下产出的,所以在运行解密脚本的时候也要在Linux环境下运行,否则就会出现一大堆乱码。
逆向脚本如下
1 | import ctypes |
C语言逆向代码如下
1 |
|