分析样本最重要的是搞清楚分析的目的,有时候我们只需要提取c2,那么甚至不用逆向,直接用fakenet就能提取,有时候我们关注的是样本流量的加密通讯方式,那么逆向的重点就是通讯代码周围的加密算法,有时候我们想搞清楚样本大致的功能,那就没必要太过关注加密的细节,这里我想搞清楚样本大致的功能
第一步当然是找关键函数,这一步需要配合各种断点的尝试以及栈回溯来分析
这里运气不错,样本跑起来发现主线程直接进入了shellcode,但是主线程的栈回溯已经看不出调用链了,没办法只能对createthread下断点,但发现createthread并没有成功断下。
Createthread这个断点走不通,只能换一条路了,经过观察发现样本执行过程有一个加载dll的过程,利用x64dbg下dll导入断点,然后通过x64dbg的符号界面跟踪ws2_32.dll的导入,经过调试发现
此时的函数就是样本循环导入dll的部分
通过栈回溯可以发现该函数仅有一个引用,且是从wWinMain进入的,猜测上一次层的函数便是关键函数
对上一层函数的入口下断点,单步调试,发现函数中用memove进行内存块的移动。对该函数下断点,很快就能定位到shellcode的移动的逻辑,以及执行shellcode的逻辑,这里发现不是通过creatthread来执行的shellcode而是直接call的一个PE文件的text段的地址。
分析时通过x64的内存布局发现shellcode是从RT_DATA段复制出来的PE文件,RT_DATA段本身就有一个PE文件,但是复制的PE文件是该段中动态解密出来的另一个PE,这里可以通过在x64dbg设置RT_DATA段的属性为只读的方式来定位PE解密的代码,当程序产生异常时就成功断在了解密PE的逻辑处。
通过x64dbg的scylla的fix dump可以为其添加导入信息,首先调试器运行到shellcode起始部分,通过IAT Autosearch自动找到shellcode的IAT表,之后Get Imports,最后Fix Dump,选择我们从内存中直接dump的文件
从CFF中可以发现生成的文件已经有导入表相关的信息了,但是IAT中的地址仍是内存中真实的函数地址,这种情况IDA是无法正常识别的
看来还得手工修复一下,不过在此之前我们再来复习一下PE文件的导入表相关的结构
在手工修复的过程中可以找个正常的PE对比,就能很方便的知道怎么修改dump文件的各种值了
PE文件中数据目录的第二个字段中保存了导入表的RVA
通过导入表的RVA找到IID(_IMAGE_IMPORT_DESCRIPTOR)数组,数组中的每一个结构如下所示共有5个DWORD,数组以5个DWORD的0作为结束标志,每个结构实际上就是描述了一个模块的基本信息
需要关注的主要是3个字段,一个是OriginalFirstThunk,第二个是Name,第三个是FirstThunk,这里FirstThunk指向的位置就是我们常说的IAT表,OriginFirstThunk指向的内容和FirstThunk基本一样,只不过加载到内存中之后IAT会被动态填充为实际的函数地址
这里第一次尝试修复的时候,我将IAT的地址和INT的地址修改为一样,发现IDA虽然可以识别导入函数,但是仍然无法正确将导入函数应用到代码上。
通过分析发现是因为IDA生成的.idata段跑到了.rdata的后面,这就导致了代码中的call指令错误的near jmp到了rdata段
而IDA是通过IAT的地址来生成.idata段的,为了让IDA正确生成idata段,还是需要让IAT的地址在INT的前面
实际操作时,可以在文件末尾添加一个一模一样的IAT结构,让OriginFirstThunk指向这里,FirstThunk指向原来的地址即可
最后,这里还有个要注意的点就是使用CCF时,当RVA超过文件本身的最大值时也能正确解析,比如这里的RVA7000实际上和RVA4000是相同的文件偏移,但是在IDA中RVA7000就和RVA4000不同了
之后对解密出的新PE文件进行分析发现
该样本通过socket进行通讯,会收集受害机器的用户信息,磁盘信息,权限信息
之后便是接受远端的文件并创建到tmp目录下,该样本并不具备命令执行的功能
参考
https://www.lyshark.com/post/ff060496.html