PECMD的解包

新脚本

F12检查到一个管道,别的虽然也挺令人在意,但还没有什么实际能看出来的。

老规矩,先断LoadResource。

堆栈跟踪到sub_472E88

调试的时候跑飞了,没想到这样本还怪好的,还提醒我反反调试没做好:

image

image

其中msdge拥有一个有效的数字签名,查询发现是一款杀软,看这形式猜测是用了这个杀软的某个漏洞提权,并且数字签名免杀。

本来是杀软,却被病毒用来提权,实在有点感慨。当然,这还只是猜测,还得继续验证

image

翻找temp目录总能有新的发现,比如这个7z带密码的压缩包:

image

发现和前面的几个文件相对应,看来这就是要提取的文件了。

检查日志,查看是否有遗漏的目标:

image
自身不滞留在后台,是好消息。
image
谁家写入分块分512的?不过有个好处:必定存在一个超大的循环,单步肯定跑不完的那种
image

可能是作者后门(纯猜测),检查到这个文件/文件夹后不执行病毒之类的。

在上述排查中,和逆向分析得到的结果一样,只发现那三个文件(或者说,一个7z文件)

那么现在的首要任务:

  • 获取文件数据

  • 解密文件数据

  • 获取7z压缩包密码

根据日志里面一堆的readfile和writefile,只要断这两个准没错,必断到加密算法中间。

00473C70:首次尝试直接读入7z文件

00474A45:读入失败后,创建新的空白7z文件

image

00473C70命中第三次的时候7z文件完成全部写入。

中断插入,得到断点为00474DEF时完成第一部分。

检查到sub_43362F是一个非常复杂的分支系统

image

image

image

image

PECMD脚本语言。

PECMD 命令帮助 - PECMD技术社区: www.pecmd.net

[[原创]2023-05-20更新--进程管理器-PECMD脚本作品展示-PECMD技术社区

image

参考了一下,果然是一个成熟的体系。程序里面大量使用的脚本非常奇怪,现在看到,也正常了。

image

再次检查,发现脚本资源下有一个可能是PE文件,但头部似乎多出了一些内容。

尝试提取检查。

image

只是简单的删除头部的字节,无法被识别为PE文件,IMHEX尝试使用PE结构解析时直接崩溃。

image

再次翻看,发现里面的内容也和其他正常软件不同,没有大片的空白。

0043EDCD:调用解密函数

004481A9:解密函数断点触发处

00448346:调用了一个看似完整的解密循环,看起来像是解密流程函数。

这里始终没找到v7怎么传递的,去找了一下thiscall的资料

image

image

通过ecx传递,看看ecx。

image

image
有指针,指针正常赋值到函数内

看看原调用:
image
image
v7在经过定义后就没有进行过任何赋值,直接传入thiscall里面
image

在thiscall内部,也就简单清理了一下数据区域就拿来用了,那这些函数是什么时候初始化的呢?

挠头起来了

尝试断一下v7的定义函数开头

image
image
断上了,但是栈空间太短,要么是dbg识别错误,要么就有点问题在里面了。

再检查一下ida那边,发现ida自动省略了一个栈空间申请函数,哦?这就有点意味在里面了。

image
image
image
image
过了那个所谓的栈空间申请函数以后,栈里面居然跳不到esp了,push还在正常执行?这也太奇怪了点吧。
image


sub_414F82:疑似加载资源附带解密资源

sub_4410C9:疑似判断资源类型是否需要解密

image

esp和ebp-d470无法访问的问题的答案:dbg版本太老了

image
换一个dbg解决问题

ecx不是指针,无法跳转的问题:系统内存申请问题
image
image
结构体赋值是在SUB_43E92E
image
sub_4355F6疑似主流程函数
image

尝试跟踪:this的最初值
image
image

上答案了

image
好简洁的代码。

Resource_TypeCheck_4410C9:资源检查,是否加密,这部分相同,返回的v5做什么的我暂时没搞明白,只是和他一样返回了,感觉可能是标志位。
image
image
我的报错点就在C8这里,但是学长的代码直接跳过了C8
image
另一个地方也一样,难道说。。。。
image
image
好吧,还是继续看学长的代码好了

Decode_MainProc:对应的是sub_43ED73,流程代码。不过外面还有一层sub_414F82,main函数代替之了。

sub_448188:主要解密函数

原程序并没有文件写出(或不在流程内),在学长的解密程序额外添加了文件写出以进行后续分析

大概思路是在中途退出之前进行一次写出,或者是在解密过程中逐渐写出。
image

C8的意义不明。


来点总结。

image

image
image
取得key和资源检查,DWORD类型,仅低3.5字节有效(DWORD共4字节),读入后一个小异或固定数字0x5AA59669u(这里居然用到了4字节)
image
image
image
这里的curb是指针指向的字节的意思。

4~6存储的是关键词CMPx(4 5 6 那其实只能匹配三个字节)

7存储的是flag 9720 658 120==4,是key的异或值。 flag最低位是flag是否有效,flag低第2位是key1是否有效。(实际上就是判断key1是否为0,这个位置没啥用)

8~12(0x10)存储的是key1

key的部分解析完成,接下来是文件。
image
别说这部分跑一遍才发现真是挺巧妙的。

v9一开始是空白的,先取一个byte的数据确定要跑多少次

sub_448188的作用是取下一个byte的数据,这里涉及到解密和指针自动右移一位。

第一次取到的是8次(一个byte8位最高了),那么本次,以及后续7次, 一共8次。

因为小端序的原因,v9 = result | 0xFF00;其实会填充v9的第二个字节为FF,第一个字节为result。

如果清空了FF,那么就是文件没读完,会再读一遍长度,也就是8个8个字节一组。

如果清空FF之前,就先碰到了result的0,那么说明该break了。

另外注意,8个8个字节一组,但是每个字节头需要一个FF用来标识长度,所以是9个字节一组

然后buf的起点并非从v1(pcn->DecodeB)开始,而是从v1 + v2(4078) + 12开始,以及每个文件片(在这部分中,还不能确定这部分一定是纯粹的文件内容。)最大可以达到0xFFF的长度,可谓也是非常小了。

每次写入0x1000的数据,基本算是一段,没确定下一段是否会去使用上一段的数据进行重复,不过这也不重要了。

然后一般sub_448188只会返回一个BYTE的数据,读到最后的时候会返回一个INT32的-1,遇到-1就可以终止了。
image
因此结构体如上。


编了个程序把其他的样本都扒下来了。

image

103号是通用的7z解压缩本体。
image
image
多出来的102号是一个不知道干啥的资源配置文件。
image
奇怪,那我之前找到的加密压缩包呢?
image
资源里面没有其他可用的东西了。

找找别的:
image
哦吼?你的意思是又放文件末尾了?

IMHex又出bug了,服了,还是换回稳定的010editor好了,工具果然还是得稳定一点。
image
image
试着截取此大小,然后修改文件头。

比对哈希
image

哈希比对成功,这个压缩包是被【原样】保存在exe里面的,不是资源。文件末尾有压缩包头。

先附上结论图
image

第一步:跳转到内容为004E的地方,比对内容是否正确。(固定从文件尾的偏移:十进制160)

第二步:跳转到内容为23313531的地方(固定偏移177),读取是否是##包括的数字。

第三步:跳转偏移 -160-177 获取到压缩文件尾部。

第四步:【未知压缩文件大小来源】跳转到压缩文件头部。 但是由截获的压缩文件可知大小为0x906A2F(缺少这步将会导致无法实现自动化。)

第五步:【未知比对目标】比对一个目标是否是cab格式,如果是,则获取到的压缩包头部替换为cab文件头,否则替换为7z文件头。

image

第四步和第五步的【未知】是因为在导出的脚本根本没有填充这部分内容,因此有可能是在exe后赋值的。

第六步:运行解压命令【解压密码为rfhujhfud4656575】(截图里面前面的-p不是密码)
image
image
另注:随便开了个别的样本,密码不一样。
image
但是结构是一样的,也没给压缩包长度(变量名不一样是因为我上面自己分析的时候修改了变量名)
image

posted @ 2025-02-24 10:34  Timmoc  阅读(106)  评论(0)    收藏  举报