写了逆向方向7个题
ASM?Signin!
汇编题,直接梭
1 | # 处理后的DATA1数组(经过DO1过程) |
FishingKit
hook+tea+z3
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
第一个是z3约束求解
1 | from z3 import * |
后面的函数点进去像是魔改rc4
1 | __int64 __fastcall sub_140002460(const char *a1, __int64 a2, __int64 a3) |
但是有问题,我在看交换函数sub_140002D90的时候发现了交叉引用
1 | .rdata:0000000140004230 38 32 00 40 01 00 00 00 dq offset ?pre_cpp_initialization@@YAXXZ ; pre_cpp_initialization(void) |
他们的根源都是这个,并且可以猜到是init,初始化的时候调用的,sub_140001000点进去会发现
1 | char sub_140001AD0() |
第一个是dll的名字,第二个是strcmp函数,所以这里实现了对strcmp函数的hook,后续调用strcmp的时候实际上是调用了sub_140001CE0
1 | __int64 __fastcall sub_140001CE0(_BYTE *a1, unsigned __int8 *a2) |
后面这个函数实际上就是实现了tea的魔改,三组就是24位刚好符合,key呢就是前面第一次的输入
1 |
|
彩蛋,后面hook了MessageboxA
LockedSecret
upx改壳+32,而且和一般壳不太一样,我选择和ida配合手脱
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
第一个字写函数是造盒,用于初始化第二个函数里的key,第二个函数确实难看,提示说在Ghidra中查看
1 |
|
一下就很好看了,是tea,常数是在模拟+=delta,key的实现动调看,dump下来是0x423DF72D, 0x05F59A01, 0x633FCF1D, 0x77D19122
1 |
|
Mio?Ryo?Soyo?
python文件,解密出来是引用自己的库
1 | import math |
简单分析base45->凯撒->base85->凯撒,直接解密即可
1 | # 反向偏移的函数 |
TimeSpaceRescue
拖入ida
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
先造aes用到的key,然后加密输入,所以先看initkey
1 | int __cdecl sub_B21DD0(int a1) |
看到time我就有不好的预感,果然是根据时间戳,md5加密生成key,这里有个细节
1 | .text:00B21E8E loc_B21E8E: ; CODE XREF: initkey+96↑j |
本来这个位置是返回,但是看ida汇编代码就会发现,这里有点像花指令,因为再运行的时候会发现这个地方是要跳过的,所以可以nop了,然后就可以看到我的那个伪代码界面了
所以这个函数实现了,md5加密时间戳,然后简单加密生成key(注意,这个时间戳是否赋值是要根据是否处于反调试的)提到这里还有个细节,这个程序肯定要多次调试做,然后就会发现,无论怎么再main中下断点都会退出程序,我直接再start下断点追本溯源发现
1 | if ( dword_B264DC ) |
在这里有反调试,也就是那个if判断,每一次都要手动跳过一下,好的接下来看aes了
1 | int __cdecl aes(void *Src, size_t Size, char *a3, unsigned int a4) |
经典AES_EBC,但是有小魔改,我标记成了de2和de3,同样的这个函数的末尾也有一个小花,不过观察发现,a3一共加了32字节,所以后面的异或是不影响输入明文的,最后与flag对比,逻辑就清晰了
time—md5—>key—de2—–AES-EBC
^
input—de2——— |
所以要。。。。。爆破时间,根据题目提示,2024的某一天
1 |
|
1 |
|
Room0
异常+SMC+rc4变
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
输入分两个一个key一个input,看汇编码会发现
这里是有异常处理的,并且还是有模有样地,不难猜测会有地方触发异常,肉眼可见的没有,就看看函数
1 | int __cdecl sub_402000(char *Str) |
/-div,能够引发除零异常,所以这里必然会引起异常到异常处理模块,这么一看题目名字room 0 原来意思是异常提示,真是旁观者清啊
那么看异常怎么做了
1 | mov esp, [ebp+ms_exc.old_esp] |
三个函数,第一个之前在验证函数就出现了,是ascii码转16进制,比如你输入的是1a,就会变成0x1a,类似于python代码的int(‘1a’,16)实现了
第二个函数有花指令去一下
这里是永真不爆红花,需要把retn去掉
后面是永真跳转
1 | int __stdcall sub_402410(unsigned int a1) |
检测当前块是不是enc,如果是的话就进行SMC,解密而SMC异或的对象就是前面输入的key,那么问题来了,key应该是多少呢,这里我动调发现SMC解密的对象就是下一个要调用的函数,再因为一般函数的开头都是55 8B EC 第四个有多种可能,我后来尝试发现对应异或应该是d3,并且
我们能发现,这个函数后续都是75 5f f0 d3并且我计算出key的前几位也是75 5f f0,这也验证了第四位是d3的思路,这样这里SMC解密后就是0了,所以key就是755ff0d3
idc脚本:
1 | start=0x00401000 |
这里如果是动调看的话有两种花各两个,一种是爆红的永真跳,另一种是不爆红的花,但是如果是脚本静态的看好像就不报错
1 | int __cdecl sub_401000(char *Str, unsigned int a2) |
可以看出来时rc4,但是再rc4最后一步异或的时候多异或了一个key,逻辑就是把a2 01233210的方式加倍生成8位key,然后rc4,所以现在只需要知道key就可以解密了,动调看把
后面我测试了一下,如果除零异常时手动将div ecx里面的ecx改成了0,则最终ebx,也就是a2传参就是0,但如果是正常的输入正确key然后运行过程中爆除零异常,那么ebx就会是正确的key
可以看到如果是正常输入的话,i==0xf的时候会变成0,这时候
ebx会是正确key,大概能猜到,这里的ebx就是之前那些计算留下来的数
解题脚本如下:
1 |
|
canno
就是考加解密的,拖进ida
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
把输入拆成三部分(i1,i2,i3),然后根据 j 012决定谁做key谁做密文,看加密函数
1 | void __fastcall crypt(char *a1, const char *a2, int a3) |
可以看到根据前文的v15来决定这里是哪种加密,一共7种case,所以先模拟出每一种的j对应的case,然后写每一种的解密
1 |
|
解决了