2023NepCTF九龙拉棺
0x00 题目分析
8线程+1进程+反调试+多重加密+SMC
难度:easy
……
0x01 解
照例,查壳(Not packed)
没壳就拖进IDA直接到main函数看
多个线程+长度限制
还有看到个提权:https://www.jianshu.com/p/232fbd1a3cfb
感觉挺麻烦的
接下来看看每个线程都执行了什么函数
StartAddress函数
这个函数里面有个CreateProcessA,创建了一个进程,估计有一部分的操作是在创建的子进程里面进行的
sub_402460
下面有这个
这个byte_404210有点怪,里面是空的
sub_402630
这里面有个sub_401120
base64
结合这个base64和上面那个函数的1.37+1,可以知道上面那个函数应该是base58
参考:https://blog.csdn.net/weixin_34258782/article/details/88830132
sub_4020B0
看不太懂,但是应该是什么算法,下面有很多操作
结合WP,这应该是一个反调试(
反调试动态读取.text(第一个段)并通过累加的方式,不断读取对比的方式,来实现反调试。如果程序一开始就存在断点,则该反调试无效,若在调试中突然增加int3断点,则该程序直接退出
sub_401700
这些应该就是密文了,往下滑滑可以看到老朋友TEA
但是这个和原版不太一样,是XTEA
sub_4023A0
里面的这个sub_4012B0是这样的
看来是个base32的操作
sub_401E60
看不太懂,但是这个byte_406018有一大堆乱码,合理怀疑是被加密的什么东西
sub_4018F0
结合WP,这应该就是
上动调,会发现一下断点或者下了断点运行后程序会自动退出
看来有反调试,先干一下
刚刚那些进程里面的函数基本都有调用这个sub_4015E0
进这个函数看看
Dr7,看来这个是反调试了
参考:http://www.jybase.net/ruanjianpojie/20111221725.html
ExitProcess这个地方nop掉应该就行了
别忘了还要处理sub_4020B0
搞完之后就可以正常下断点调试了
看了一下官方WP发现有一个子线程是进行判断的,如果判断不对会直接退出程序
行吧,那就只能从上面的加密下手了
结合CreateProcessA和byte_406018的长度可以知道
这里应该是用了SMC
参考:https://segmentfault.com/a/1190000043519957
所以这串代码就要解密了
现在有两个方法进行解密
第一种是直接dump这段byte然后根据算法解密
第二种是直接动调然后在内存中找
第一种要注意解密顺序
可以根据各函数开头的while(dword_409804)来看,同时也要结合dword_409804来判断下一个执行的解密函数
以sub_401E60为例
这个算法是RC4,key是”MessageBoxA”(很有迷惑性)
它是第一个进行的解密,因为它的while (dword_409804 != 1)
它的下一个解密流程是dword_409804为3的函数
其他函数同理,顺序应该是
RC4 → Base32 → Base58 → Base64
解出结果是这样的
第二种方法就是直接动调然后在内存里找到解密后的代码
在CreateProcessA处下断点
之后在主线程中的WaitForMultipleObjects后会断下来
然后找到CreateProcessA下面的SetThreadContext
上图注意内存窗口的地址和ECX的值
然后就可以dump出来分析了
直接上IDA吧
函数很少,有用的就那么两个
主要是sub_2B2
往下滑滑,老朋友XTEA了
这里有点坑,数组长度要看v11,是4*i=64=0x40
看看这个函数的交叉引用
看来这个函数操作之后是用了MapViewOfFile传递给主函数的
然后就可以写脚本了
XTEA的抄抄大哥的
1 |
|
python转换自己写写了(
1 | c1 = bytes.fromhex("4E65704354467B633963646E77646933697534316D3070763378376B6C6C7A7538706471366D74396E326E776A6470366B617438656E743464686E3572313538") |