简要说明
前段时间遇见了一个被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
转载:https://blog.csdn.net/weixin_44001905/article/details/106544958