SPreadoc感染型还原代码

简要说明

前段时间遇见了一个被Spreadoc病毒感染的winrar安装包,样本运行后将自身还原然后执行其他恶意行为,由于样本代码量也比较大,我也只是分析了它exe还原的过程。它的还原过程还是比较有意思的,还运用了一些反沙箱反虚拟机的技术,因此就整理了一下。

自身还原过程

SHA1:d1b231e2c71248b61984f3052257d352b0846d8d

将样本重命名为1.exe,被感染的样本大小为2.33M

在这里插入图片描述

样本运行后,被恢复为原始样本,原始样本大小为1.54M
在这里插入图片描述
从行为上看,将自身复制到Roaming目录下并启动,将数据解密出原文件数据写回到1.exe中

在这里插入图片描述

代码分析

根据代码可知,样本会判断命令行参数个数,它会将被感染的原文件还原到第二个参数上(文件路径)

在这里插入图片描述

在分析的过程中发现了一个有意思的反沙箱的代码

在这里插入图片描述

一般在搭建的沙箱或虚拟机中都会模拟真实环境,也会模拟各种API返回值,正常执行CreateProcessA再调用GetLastError函数,正常返回值是5,而一般沙箱则会返回2(执行成功),如果在沙箱中返回值为2导致后续行为无法执行

接下来再回归代码的还原逻辑

被感染样本的原文件被放在了病毒样本的最后一个区段上

在这里插入图片描述

获取最后一个区段数据存放到开辟的内存空间,固定随机数种子为文件大小,生成的随机数序列依次与数据异或,最后调用zlib进行解压数据

在这里插入图片描述

解压后的数据根据偏移找到原文件dos头进行还原

在这里插入图片描述

代码还原

由于是获取样本中最后一个区段的数据,我没有在代码中体现,只是将最后一个区段的数据存放在了一个文件中,其余代码并不影响还原的逻辑

固定随机数种子为文件大小将数据异或

srand(dwFileSize);
int v3 = 0;
for (int i = 0; i < dwFileSize; i++)
{
    
    
	v3 = rand() % 256;
	lpBase[i] = lpBase[i] ^ v3;
}

使用zlib解压并根据偏移找到原文件dos头进行还原

int uncompressData(const char* loadFileName, char* lpBase, DWORD dwFileSize)
{
    
    
	char* de_text = NULL;
	uLong tlen = dwFileSize * 10;
	if ((de_text = (char*)malloc(sizeof(char) * dwFileSize * 10)) == NULL)
	{
    
    
		printf("no enough memory: ");
		printf("%s\n", loadFileName);
		return -1;
	}

	int number = uncompress((Bytef*)de_text, &tlen, (Bytef*)lpBase, dwFileSize);
	/* 解压缩 */
	if (number)
	{
    
    
		//Z_OK
		//Z_STREAM_END    1
		//Z_NEED_DICT     2
		//Z_ERRNO        (-1)
		//Z_STREAM_ERROR (-2)
		//Z_DATA_ERROR   (-3)
		//Z_MEM_ERROR    (-4)
		//Z_BUF_ERROR    (-5)
		//Z_VERSION_ERROR (-6)
		printf("uncompress failed: ");
		printf("%s\n", loadFileName);
		return -1;
	}

	//保存到文件
	FILE* p2file;
	char outFile[MAX_PATH];
	memset(outFile, 0, sizeof(outFile));
	//拼接字符串输出
	char str1[] = "_uncompress";

	strcat_s(outFile, strlen(loadFileName) + 1, loadFileName);
	int len2 = strlen(outFile) + strlen(str1) + 1;
	strcat_s(outFile, len2, str1);

	p2file = fopen(outFile, "wb");
	if (p2file == NULL)
	{
    
    
		printf("create file failed: ");
		printf("%s\n", loadFileName);
		if (de_text != NULL)
		{
    
    
			free(de_text);
			de_text = NULL;
		}
		return -1;
	}

	DWORD offsetA = *(DWORD*)(&de_text[0x100]);
	DWORD offset = 0x128 + offsetA;
	int a = fwrite(de_text+ offset, tlen, 1, p2file);
	fclose(p2file);
	/* 打印结果,并释放内存 */
	printf("succeed: ");
	printf("%s", loadFileName);
	printf(">>>>");
	printf("%s\n", outFile);
	if (de_text != NULL)
	{
    
    
		free(de_text);
		de_text = NULL;
	}
	return 0;
}

完整工程见:https://github.com/Iam0x17

猜你喜欢

转载自blog.csdn.net/weixin_44001905/article/details/106544958
今日推荐