实战|记一次攻防样本——shellcode分析(中)
开辟内存空间
跟入sub_19396
函数,其实现如下,首先很明确,主逻辑是要取其返回值的,所以分析的时候我们要重点关注v8;
通过分析我们可以发现,第一个参数就是指针,指向上面获取到的函数地址;这个sub_19396
主要就是调用里面函数进行了一些操作,如下:
先是调用CreatFileMapping+MapViewOfFile创建一个和内置pe文件内存大小的内存映射(CreatFileMapping的时候申请的权限是0x40(64), 可读可写可执行)
然后判断a4是否等于4,等于就调用VirtualProtect把内存属性调成可读可写
最后return的是创建的内存映射地址;
然后回到主逻辑里面,获取PE内存大小,并且把刚刚返回的内存映射地址做了一个初始化清0操作(从这里我们就能get到,攻击者上面sub_19396
做的组合操作,其实就是用来申请内存空间,然后有一个控制位来控制要申请的内存空间权限,控制位是pe头里面的Characteristics**IMAGE_FILE_BYTES_REVERSED_HI**
值,应该是一个配置项,生成payload的时候是可控的;简单说:攻击者利用CreatFileMapping+MapViewOfFile申请内存空间,来绕过杀软对VirtualAlloc的监控,并且存在一个配置影响申请空间的权限,因为有的杀软对带执行权限的内存是会做非常严格的扫描或者多的处理的,所以这里攻击者将其做成可以调整的配置,这个配置项非常微妙的嵌入在pe头中微软弃用的一个地址),
然后又获取了一个弃用地址的值,pe头中的NumberOfSymbols的值(符号表中的项数。 此数据可用于查找紧跟在符号表后面的字符串表。 映像的此值应为零,因为 COFF 调试信息已被弃用。);
接着调用sub_194b6函数,并传入四个参数,分别是:内存开辟并做了初始化空间的地址、shellcode藏着的peheader的地址、pe的基址、pe头的NumberOfSymbols的值;
跟入sub_194b6
函数,其实现如下,首先我们知道其存在一个return,并且我们可以看处,return的是一个地址(下面)
sub_194b6
逻辑做了几个操作:
1、如果pe头的numberofsymbols字段不为0,那么这里直接return 申请空间-区块对齐大小(pehead+0x38)
2、将pe头的内容复制到申请的空间
3、判断pe头IMAGE_FILE_RELOCS_STRIPPED
的值,如果为1,就开始对复制到申请的内存空间的PE文件头部内容去特征;
简单总结sub_194b6
就是把pe头复制到的映射的空间,并做了去特征化;
回到主逻辑sub_188E6
,调用sub_19576
,如下图,传入参数分别是:内存映射的空间地址、shellcode中影藏的pe头地址、pe基址、以及两个引用(大概率是用来回传东西的)
PE文件拉伸到内存
跟进sub_19576
,稍作解析,其实现如下,不难看出,这里其实就是对区节遍历,循环复制,将pe文件区节内容复制到的内存映射空间里面去;除此之外,就是对a4、a5的赋值,赋值逻辑是:找到带执行权限的区节,a4赋值对应区节的开始地址,a5赋值对应区节的大小
然后回到主逻辑,调用sub_19676
,传入参数分别是:v13、内存映射地址、shellcode影藏的pe头地址、pe基址、pe头中的numberofsymbols的值
跟入sub_19676
函数,如下:
解密还原导入表
我们来详细看下其逻辑:
首先,对v6赋值,通过a2(申请内存映射地址)+a3(0x50)(加载后pe文件的内存总大小)-0x40,拿到的是加载到内存之后的最后40个字节的地址;
然后遍历,这个影藏pe的导入表,获取导入模块的名称赋值到刚刚的v6处;随后作为参数调用sub_18b76
,随之传入的参数还有,0x40和a5(pe头中被弃用的numberofsymbols的值)
这个sub_18b76
实现如下:其实就是一个解密函数,我们可以把传入的numberofsymbols的值看作密钥,对刚刚获取的导入模块名称进行解密(这里不难看出攻击者做了静态分析对抗,隐藏导入模块的名称,所以这里需要恢复);解密方法也非常简单,就是一个异或解密,numberofsymbols一共四个字节,循环使用;
然后回到sub_19676
,在拿到解密后的名称后,调用LoadLibrary函数加载对应模块:
然后就是用相同的思想,遍历对应模块的导入函数,还原导入函数的名称:
最后return之前,把刚刚暂用的pe最后0x40个地址恢复0x0;
简单总结sub_19676
函数做的事情,解密还原导入模块名称和对应的导入函数名称;
解密可执行区节
然后我们回到主逻辑sub_188E6
,出来之后直接调用sub_18b76
,解密刚刚获取到的可执行段的内容(v11是pe可执行段起始地址,v8是长度),解密方法和上面解密导出函数名称一样,密钥放到了pe头中微软遗弃的字段:numberofsymbols;(这里也可以看出,攻击者为了免杀选择了将pe中的可执行段加密,因为一般带执行权限的段会被杀软重点“照顾”)
修复重定位表
接着调用sub_19366
,传入两个参数,一个是pe内存映射的地址,一个是shellcode中的隐藏的pe的peheader的地址,没有获取其返回值,其实实现如下:
上图简单分析,不难看出,其利用之前文件格式的pe,来修复映射到内存后的pe的重定位表:
然后回到sub_188E6
,其接着调用sub_19456
,传入参数分别:v13(指向一堆函数调用地址数组的指针)、加载到内存的恶意PE可执行段地址起始位置、可执行段的长度、最后一个参数a4(取值4或者64,上面分析,我们知道其取决于pe头的Characteristics**IMAGE_FILE_BYTES_REVERSED_HI**
值是否为1,为1就是64,反之则为4,大概率是攻击者的一个配置项)
- 点赞
- 收藏
- 关注作者
评论(0)