上面这个样本的服务器已经不能通信了,该病毒的最新变种前面的步骤和上面的都差不多,到这一步的xsl文件内容不同,最新的变种的xsl文件从服务器下载的是个dll文件。保存在C:/Windows/Temp文件下,名称是随机命名的。
第一段shellcode
拷贝数据
将加密的数据复制到指定的地址。
修改内存页属性
修改shellcode所在地址内存执行权限为可读可写可执行。
执行shellcode
跳转到shellcode执行。
自解密
解密自身中加密的代码
解密shellcode中的代码。
获取指定函数地址
获取函数地址kernel32.dll中指定函数的地址。这里shellcode当中使用的循环,每次都对kernel32.dll的导出表进行遍历,找到需要的函数名之后在从头开始遍历
获取加载基址
通过pe头标志和对地址每次减0x1000来获取加载基址。
第二段shellcode
拷贝数据
将shellcode拷贝到刚申请的内存空间当中。
执行并拷贝第三段shellcode
上面拷贝完第二段shellcode之后,接着执行第二段shellcode中的内容,然后拷贝第三段shellcode的内容到内存中。
位置变换
将从dll里面拷贝的数据以特殊的方式进行调整位置。末尾是2FB的函数就是调整位置的函数。
解密shellcode算法
调整完位置之后在对数据进行解密。解密方式用的xor DL,DL中的内容根据循环次数和3做AND操作,为0就变换一次DL中的内容。DL中内容的变换规律是DL和DL相加,结果乘以3然后在右移5位,得到一个新的DL。
末尾是2CE的函数是解密函数。
第四段shellcode
接着申请空间,然后拷贝第四段shellcode的数据到新申请的空间。
拷贝依据
判断是否接着拷贝数据是根据之前第三段shellcode最终解密出来的数据。当值不为0的时候就继续执行拷贝。
释放空间
释放第三段shellcode申请的空间。
解密shellcode
和上面解密第三段shellcode使用的算法相同。
特殊处理
解密之后对数据进行了特殊的处理,处理之后变成了pe文件。
dll替换
修改内存页属性
更改1220000地址的内存页属性为可读可写,这个地址就是dll加载的地址。
替换dll内容
将上面处理的pe文件拷贝到刚才清空的空间当中。
修改对应段的内存页属性
代码段所在内存页修改为可读可执行。
执行替换之后的dll
之后retn返回到最初加载的dll文件里面,但是这个内存空间里面的数据都是被替换的新的数据,retn到的是新的dll文件的OEP。
hash加密
末尾为0510的函数的功能为对指定的字符串进行加密。
在0510函数内部调用的是13C0这个函数,函数内部通过移位异或等方式处理过后在循环0x100次之后加密完成。
加密之后的字符串和0x6AECC489异或之后如果为0xADC2B18也就是ntdll.dll就通过自己实现的GetProcAddress函数获取指定函数的地址。
末尾为4200的函数功能是根据传递的dll的地址和函数名加密后的hash获取函数的地址。这里为获取0xD047C681的地址,也就是RtlAddVectoredExceptionHandler函数。
遍历dll的导出表,然后对函数名进行加密,之后比对加密过后的值是不是自己需要的函数。
注册VEH异常
获取到需要的函数之后,3790函数作用为执行获取到的函数。这里执行RtlAddVectoredExceptionHandler为注册VEH异常,其中6A686CB0为异常处理函数。
GetProcAddress函数
注册完VEH异常之后获取kernel32.dll中的函数。
在3BB0函数里面判断字符串是不是kernel32.dll
函数44C0为GetProcAddress,传递进去的两个参数一个是dll的加载基址,另一个是函数名。这里0xADC2B18是ntdll,0x92E0E512是RtlCreateHeap函数,0xD084EC36是RtlDestroyHeap函数。
异常处理函数
之后获取0xCB389DFD RtlAllocateHeap函数的地址,获取之后判断是否获取成功,之后触发INT3 异常。
对异常进行处理,分析发现是直接修改线程上下文,跳过了INT3异常。
跳过异常之后通过retn执行RtlAllocateHeap函数。
通过异常retn执行RtlAllocateHeap循环申请内存空间
最终这里获取到ExitProcess函数的地址,然后退出了程序。不知道有什么地方的判断条件不满足,所以程序没有执行下去。