CTS感染型病毒还原算法解密文件

前言

这是最近遇到的一个感染型病毒,感染可移动设备和前用户目录下的exe文件,被感染的文件,病毒母体会首先写入文件中,然后将原始文件加密后和感染标记、加密密钥一同存放在附加数据上。对此,我决定分析算法还原文件。

样本信息

名称:CTS.exe
SHA1:cb54a305a566c00742fb972c4ee62266e880ea78

样本简要分析

样本的主函数很短

在这里插入图片描述
在这里插入图片描述

向windows目录和temp目录下释放CTS.exe文件,设置自启动

在这里插入图片描述
开启线程感染可移动设备文件

在这里插入图片描述
在本地只感染当前用户目录下的exe文件

在这里插入图片描述

判断是否是exe文件

获取0x10位密钥进行加密读取到缓冲区的文件,病毒母体会首先写入文件中,然后将原始文件加密后和感染标记、加密密钥一同存放在附加数据上

在这里插入图片描述

使用010editor对比两个被感染的文件,发现两个文件的前0x6800都是相同的,并且结尾处都有相同的标志

在这里插入图片描述

经过分析,文件结尾处最后0x18个字节分别是标志,文件大小和密钥

在这里插入图片描述

加密算法分析

加密算法并不多,只有不到100行的汇编代码

.text:00405060 encrypt_file_buffer proc near           ; CODE XREF: relase_file+55↓p
.text:00405060                                         ; infect_file+74↓p
.text:00405060
.text:00405060 var_109         = byte ptr -109h
.text:00405060 byte_100        = byte ptr -108h
.text:00405060 pe_start_addr   = dword ptr -8
.text:00405060 pe_file_size    = dword ptr -4
.text:00405060 crypt_key       = dword ptr  8
.text:00405060
.text:00405060                 push    ebp
.text:00405061                 mov     ebp, esp
.text:00405063                 sub     esp, 108h
.text:00405069                 mov     [ebp+pe_file_size], edx
.text:0040506C                 mov     [ebp+pe_start_addr], ecx
.text:0040506F                 xor     eax, eax
.text:00405071
.text:00405071 loc_405071:                             ; CODE XREF: encrypt_file_buffer+1E↓j
.text:00405071                 mov     [ebp+eax+byte_100], al
.text:00405078                 inc     eax
.text:00405079                 cmp     eax, 100h
.text:0040507E                 jb      short loc_405071
.text:00405080                 push    ebx
.text:00405081                 mov     ebx, [ebp+crypt_key]
.text:00405084                 push    esi
.text:00405085                 push    edi
.text:00405086                 xor     edi, edi
.text:00405088                 xor     esi, esi
.text:0040508A                 lea     ebx, [ebx+0]
.text:00405090
.text:00405090 loc_405090:                             ; CODE XREF: encrypt_file_buffer+69↓j
.text:00405090                 mov     dl, [ebp+esi+byte_100]
.text:00405097                 mov     eax, esi
.text:00405099                 and     eax, 0Fh       
.text:0040509C                 movzx   ecx, dl
.text:0040509F                 movzx   eax, byte ptr [eax+ebx]
.text:004050A3                 add     edi, eax
.text:004050A5                 add     edi, ecx
.text:004050A7                 and     edi, 0FFh      
.text:004050AD                 inc     esi
.text:004050AE                 mov     al, [ebp+edi+byte_100]
.text:004050B5                 mov     [ebp+esi+var_109], al
.text:004050BC                 mov     [ebp+edi+byte_100], dl
.text:004050C3                 cmp     esi, 100h
.text:004050C9                 jb      short loc_405090
.text:004050CB                 xor     ebx, ebx
.text:004050CD                 xor     esi, esi
.text:004050CF                 xor     edi, edi
.text:004050D1                 cmp     [ebp+pe_file_size], ebx
.text:004050D4                 jbe     short loc_40512D
.text:004050D6
.text:004050D6 loc_4050D6:                             ; CODE XREF: encrypt_file_buffer+CB↓j
.text:004050D6                 inc     esi
.text:004050D7                 and     esi, 0FFh
.text:004050DD                 inc     edi
.text:004050DE                 mov     dl, [ebp+esi+byte_100]
.text:004050E5                 movzx   eax, dl
.text:004050E8                 add     ebx, eax
.text:004050EA                 and     ebx, 0FFh
.text:004050F0                 movzx   eax, [ebp+ebx+byte_100]
.text:004050F8                 mov     [ebp+esi+byte_100], al
.text:004050FF                 mov     [ebp+ebx+byte_100], dl
.text:00405106                 movzx   ecx, [ebp+esi+byte_100]
.text:0040510E                 movzx   eax, dl
.text:00405111                 add     ecx, eax
.text:00405113                 and     ecx, 0FFh
.text:00405119                 movzx   eax, [ebp+ecx+byte_100]
.text:00405121                 mov     ecx, [ebp+pe_start_addr]
.text:00405124                 xor     [edi+ecx-1], al
.text:00405128                 cmp     edi, [ebp+pe_file_size]
.text:0040512B                 jb      short loc_4050D6
.text:0040512D
.text:0040512D loc_40512D:                             ; CODE XREF: encrypt_file_buffer+74↑j
.text:0040512D                 pop     edi
.text:0040512E                 pop     esi
.text:0040512F                 pop     ebx
.text:00405130                 mov     esp, ebp
.text:00405132                 pop     ebp
.text:00405133                 retn    4
.text:00405133 encrypt_file_buffer endp

从代码上看,一共有三个循环

首先看第一个循环,直接看汇编指令就很明显的看出是在创建一个0x100字节大小的数组,并给数组赋值从0x00到0xFF

在这里插入图片描述

可转成C代码

char key_table[256] = {
    
     0 };
for (int i = 0; i < 256; i++)
{
    
    
	key_table[i] = i;
}

第二个循环,更新数组数据

在这里插入图片描述

这里主要关注谁给数组赋值,给数组的那个部分赋值即可

.text:004050B5                 mov     [ebp+esi+var_109], al
.text:004050BC                 mov     [ebp+edi+byte_100], dl

首先看[ebp+esi+var_109],esi从1开始,每次循环只自增1,所以它是key_table[i]

al是从key_table[edi]([ebp+edi+byte_100])中取出的,edi = (edi + key[i]+key_table[i])& 0xFF

dl是key_table[i+1]

可转化成C代码

int esi = 0;
int edi = 0;
int edx = 0;
int eax = 0;
int ecx = 0;
int ebx = 0;
for (int i = 0; i < 256; i++)
{
    
    
	edx = key_table[esi];
	eax = esi;
	eax = eax & 0xF;
	ecx = edx;
	eax = key[eax];
	edi = (edi + eax + ecx) & 0xFF;
	esi += 1;
	eax = key_table[edi];
	key_table[esi - 1] = eax;
	key_table[edi] = edx;
}

最后一个循环,异或加密数据

在这里插入图片描述

同样,只关注重点即可

xor     [edi+ecx-1], al

然后得到C代码

ebx = 0;
esi = 0;
edi = 0;
for (int i = 0; i < ecrypt_file_size; i++)
{
    
    
	esi += 1;
	esi = esi & 0xFF;
	edi += 1;
	edx = key_table[esi];
	eax = edx;
	ebx = (ebx + eax) & 0xFF;
	eax = key_table[ebx];
	key_table[esi] = eax;
	key_table[ebx] = edx;
	ecx = key_table[esi];
	eax = edx;
	ecx = (ecx + eax) & 0xFF;
	eax = key_table[ecx];
	buffer[0x6800 + edi - 1] = buffer[0x6800 + edi - 1] ^ eax;
}

所以,完整的加解密代码如下:

void encrypt_file_buffer()
{
    
    
	int esi = 0;
	int edi = 0;
	int edx = 0;
	int eax = 0;
	int ecx = 0;
	int ebx = 0;
	char key_table[256] = {
    
     0 };

	for (int i = 0; i < 256; i++)
	{
    
    
		key_table[i] = i;
	}
	for (int i = 0; i < 256; i++)
	{
    
    
		edx = key_table[esi];
		eax = esi;
		eax = eax & 0xF;
		ecx = edx;
		eax = key[eax];
		edi = (edi + eax + ecx) & 0xFF;
		esi += 1;
		eax = key_table[edi];
		key_table[esi - 1] = eax;
		key_table[edi] = edx;
	}
	ebx = 0;
	esi = 0;
	edi = 0;
	for (int i = 0; i < ecrypt_file_size; i++)
	{
    
    
		esi += 1;
		esi = esi & 0xFF;
		edi += 1;
		edx = key_table[esi];
		eax = edx;
		ebx = (ebx + eax) & 0xFF;
		eax = key_table[ebx];
		key_table[esi] = eax;
		key_table[ebx] = edx;
		ecx = key_table[esi];
		eax = edx;
		ecx = (ecx + eax) & 0xFF;
		eax = key_table[ecx];
		buffer[0x6800 + edi - 1] = buffer[0x6800 + edi - 1] ^ eax;
	}
}

总结

虽然写出的还原看起来有点绕,但其实这个算法并不难。刚开始还原这个算法的时候,我把变量的名字定义的规规矩矩,然后看着看着就把值给对应混了,磕磕绊绊,花了好久才写好。后来才感觉这样做是真的蠢,直接推平之前的还原代码,变量直接对应寄存器,无脑对应汇编,很快就搞定了。算是自己踩的小坑,分享给大家。

源码获取:
https://github.com/Iam0x17

猜你喜欢

转载自blog.csdn.net/weixin_44001905/article/details/104325103