L3HCTF
1.TemporaParadox
拿到题目就发现代码写得很乱,又是难看的C++
先找到主函数,有一个花指令
nop掉反编译,然后开始审计代码
代码的关键就是时间戳的条件判断和里面的sub_140001963函数,意味着只有在(v62 > 1751990400 && v62 <= 1752052051)中的某个特定时间下运行这个代码,才能得到正确的md5字符串
然后具体分析sub_140001963函数(标在注释上了)
考点貌似是加盐md5,然后通过判断左右两个表达式是否相等决定了两种不一样的字符串拼接方式
具体的盐值为tlkyeueq6fej8vtzitt25yl24kswrgm5,通过以下代码获取:
1 | import math |
字符串拼接要用到的a, b, x, y, r都通过随机数获取,而cipher值的计算经过了较为复杂的变换,与两个置换盒有关
前三轮分别取了第1~第3的片段,先异或,后分别与S盒和P盒进行两次不同的变换
第四轮提取了第4个片段的数据,异或后进行仅S盒的变换
最后一轮取最后一个片段,仅进行了异或操作
最后返回的值就是cipher
因为有伪随机数种子,那么只需要写代码在规定时间戳范围内进行爆破就能得到最后的md5字符串了
EXP:
1 | import math |
2.终焉之门
直接打开看不到什么有用的东西,所以直接启动动调看看
发现动调之后这两个位置的字符变了
跟进发现把主要逻辑藏在这儿了
然后把主要逻辑理出来,丢给ai后才知道这是OpenGL Shading Language代码语言
1 | #version 330 |
第一段是一个片段着色器,就是用来生成程序运行时会变换的彩色动态背景的代码
1 | #version 430 core |
第二段实现了一个简单的虚拟机,通过执行opcodes对应的操作,对栈数据加以运算
其中的比对校验是栈数据的前16位等于(cipher[i] - 20)
然后回去分析主函数,以下附上主函数及注释
1 | __int64 sub_7FF60DF61CF0() |
关键信息都已可见,接下来就是要写个虚拟机的解释器,获取加密逻辑了
1 |
|
得到VM的运行逻辑
1 | [IP=0] stack_data[0] = co_consts[0] = 0 |
每一步操作都是对栈数据进行处理,但只利用了加、减和异或这三种简单的运算
对每个字节的处理模式为:
1 | PUSH co_consts[i] // 压入当前字节 |
具体加密过程:(以字节0为例)
1 | [IP=0] stack_data[0] = co_consts[0] = 0 // 1. 压入字节0 |
最后就是写EXP:
1 | cipher = [0xF3, 0x82, 0x06, 0x1FD, 0x150, 0x38, 0xB2, 0xDE, 0x15A, 0x197, 0x9C, 0x1D7, 0x6E, 0x28, 0x146, 0x97] |
3.easyvm
找到主函数,是用C++编写的,代码比较难看
分析代码重命名一下,重点就在VM和check函数上,check函数里存有密文
看到题目的第一想法是具体分析VM每个指令的功能,但是进入代码一看发现写的特别乱,而且有很多switch函数和case的嵌套,不知道从哪下手了
然后去参考了一下SU的wp,知道了这道VM题要采用另一种解题方式:通过idapython脚本模拟trace获取加密逻辑
分析VM具体代码,发现里面有几个对数据进行处理的关键操作码
分别是:
- 0x18 异或
- 0x17 右移
- 0x16 左移
- 0x14 取模
- 0x13 除法
- 0x12 乘法
- 0x11 减法
- 0x10 加法
但是由于取模和乘除运算不太可能逆向恢复,所以可以在其它五个运算代码处下断点获取具体加密流程
写出五个运算对应的idapython脚本(参考星盟的讲解视频)
1 | import idc |
调试之后得到加密逻辑,取一段进行分析
1 | shl 0x32323232 , 0x3 = 0x91919190 //v1 << 3 |
找到密钥为0xa56babcd,0x0,0xffffffff,0xabcdef01,delta为0x11223344
然后我们看看下一组块加密进行了什么操作(即下一段以sub 0x40 , 0x1 = 0x3f为结尾的代码)
可以看到,下一组加密开始时的sum的值使用了上一组加密最后sum的值
1 | shl 0x32323232 , 0x3 = 0x91919190 |
分析出加密逻辑后就可以开始写解密代码了
EXP:
1 |
|