病毒名称:熊猫烧香
所属家族:感染型蠕虫病毒
MD5值: 512301C535C88255C9A252FDF70B7A03
SHA1值: CA3A1070CFF311C0BA40AB60A8FE3266CFEFE870
CRC32: E334747C
测试环境:虚拟机Windows 7 32位
测试工具:火绒剑、PCHunter、PEiD、OllyDbg、IDA
分析病毒具体行为,找到病毒行为的具体实现代码,了解病毒实现原理,评估病毒的威胁程度。
病毒行为:
①自我复制样本到C:\Windows\driver\spo0lsv.exe目录下,运行spo0lsv.exe(样本)
②在每个目录下创建了Desktop_.ini,内容为当前日期
③在C盘根目录下创建autorun.inf文件,该文件指定了自动启动的文件为根目录下的setup.exe(即样本)
④对程序目录下的exe进行了感染,图标变为熊猫烧香,打开exe时自动打开病毒
⑤设置注册表启动项为C:\Windows\driver\spo0lsv.exe
⑥删除杀毒软件注册表启动项,关闭服务
⑦访问网站,下载恶意代码
第三部分:自我保护
通过火绒剑和PCHunter监视病毒,发现病毒具有以下行为:
①自我复制样本到C:\Windows\System32\drivers\spo0lsv.exe目录下,运行spo0lsv.exe(样本)
②在每个目录下创建了Desktop_.ini,内容为当前日期
③在C盘根目录下创建autorun.inf文件,该文件指定了自动启动的文件为根目录下的setup.exe(即样本)
④通过火绒剑对程序目录下的文件进行了感染,图标变为熊猫烧香,通过PEID工具感染后exe文件和病毒文件信息相同,运行exe时会自动打开病毒文件。
⑤设置注册表启动项为C:\Windows\System32\drivers\spo0lsv.exe
⑥删除杀毒软件注册表启动项
②遍历文件,感染特定类型的文件,包括可执行文件,网页文件以及备份文件。
修改文件图标,修改PE文件内容,起始部分是病毒文件,中间插入了部分代码,末尾添加感染标识:“whboy”+原文件名+".exe"+原文件大小,修改原文件图标为熊猫烧香图标。
PE文件感染后
③设置第一个定时器
判断C盘的根目录下是否存在autorun.inf和setup.exe文件,若不存在则创建文件,并向autorun.inf文件写入内容,指定setup.exe为自启动文件,并且隐藏文件。
④第三个关键函数内有六个定时器
(1)修改病毒的注册表启动项,设置隐藏
(2)检测杀毒软件,关闭杀软进程,删除杀毒软件注册表自启动项
病毒会检测系统的安全服务和当时流行的杀毒软件,如防火墙、金山毒霸、卡巴斯基、江民等杀毒软件。
通过遍历进程,查找窗口等方式定时检测杀毒软件,检测到杀毒软件结束杀毒软件进程。
大部分使用结束进程API,发WM_QUIT消息结束杀软进程,针对某些杀毒软件使用虚拟按键的方式关闭进程,例如Pjf(ustc)冰刃。
(3)通过cmd命令删除共享
(4)网络异常,下载恶意代码
下载恶意代码行为
①病毒特征:字符串
xboy 、whboy、武汉男生感染下载者**
②Yara规则
rule vir_3601
{
strings:
$text_1="xboy "
$text_2="whboy"
$text_3="***武*汉*男*生*感*染*下*载*者***"
condition:
$text_1 or $text_2 or $text_3
}
(1)利用PCHunter工具结束进程,并删除spo0lsv.exe文件
(2)清除启动项,关闭svcshare启动项
(3)删除autorun.inf和setup.exe
(4)清除每个盘符下的Desktop_.ini文件
(5)打开注册表,HKLM\Microsoft\Windows\CurrentVersion\Explore
Advanced\Folder\Hidden\SHOWALL\CheckValue,将CheckValue的值设为1。
熊猫烧香病毒感染文件只是做了一定的修改,并没有对文件进行加密,所以可以编写专杀工具清除病毒,恢复感染文件。其实就是将手工查杀步骤利用程序自动化完成。
专杀工具源码如下:
#include "pch.h"
#include
#include
#include
#include
#include
#define VIRSIZE 0x7531 //熊猫病毒大小
//************************************
// 功能: 查找熊猫病毒进程
//************************************
BOOL FindVirProcess(CString nProcessName,LPDWORD lpPid)
{
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(pe32);
HANDLE nSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
BOOL nRet = Process32First(nSnapShot, &pe32);
while (nRet)
{
if (nProcessName == CString(pe32.szExeFile))
{
*lpPid = pe32.th32ProcessID;
return TRUE;
}
nRet = Process32Next(nSnapShot, &pe32);
}
return FALSE;
}
//************************************
// 功能: 删除病毒文件
//************************************
VOID DeleteVirFile(CString szPath)
{
SetFileAttributes(szPath, FILE_ATTRIBUTE_NORMAL);
DeleteFile(szPath);
}
//************************************
// 功能: 获取PC盘符列表
//************************************
VOID GetDriverList(vector &DiverList)
{
TCHAR szDrive[MAX_PATH];
TCHAR szRootPath[MAX_PATH] = {};
GetLogicalDriveStrings(MAX_PATH - 1, szDrive);
TCHAR* lpPath = szDrive;
while (*lpPath != 0) {
_tcscpy_s(szRootPath, lpPath);
szRootPath[2] = _T('\0');
//szRootPath[-2] = L'\0';
DiverList.push_back(szRootPath); //取出第一个盘符路径
lpPath += _tcslen(lpPath) + 1;
}
}
//************************************
// 功能: 扫描文件
//************************************
VOID ScanFile(CString lpPath)
{
//删除文件Desktop_.ini
DeleteConfig(lpPath);
//1. 构造路径
CString szFilePath = lpPath;
szFilePath += _T("\\*");
//WCHAR szFilePath[MAX_PATH];
//StringCbCopy(szFilePath, MAX_PATH, lpPath);
//StringCbCat(szFilePath, MAX_PATH, L"\\*");
//2. 第一次遍历
WIN32_FIND_DATA wfd = { 0 };
HANDLE hFile = FindFirstFile(szFilePath, &wfd);
if (hFile != INVALID_HANDLE_VALUE)
{
do
{
CString szFullPath = lpPath;
//3.1 判断是否是本级目录或上级目录
if (!lstrcmp(wfd.cFileName, L".") || !lstrcmp(wfd.cFileName, L".."))continue;
szFullPath += _T("\\");
szFullPath += wfd.cFileName;
//3.4 如果不是目录,获取详细信息
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
ScanFile(szFullPath);
}
else
{
//恢复文件
RecoveryFile(szFullPath, wfd.cFileName);
}
} while (FindNextFile(hFile, &wfd));
}
}
//************************************
// 功能: 恢复感染文件
//************************************
void RecoveryFile(CString nFilePath, CString nFileName)
{
int nVirType = 0;
CString nLastName;
nLastName = PathFindExtension(nFileName);
nLastName.MakeUpper();
if (nLastName == ".EXE" || nLastName == ".SCR" || nLastName == ".PIF" || nLastName == ".COM")
nVirType = 1;
else if (nLastName == ".HTML" || nLastName == ".HTM" || nLastName == ".ASP" || nLastName == ".ASPX" || nLastName == ".JSP" || nLastName == ".PHP")
nVirType = 2;
else return;
//exe,scr,pif,com,htm,html,asp,php,jsp,aspx
// 1.读取文件到内存
HANDLE hFile = CreateFile(nFilePath,
GENERIC_READ, FALSE, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("打开文件 %s 失败--%s\n", (CStringA)nFileName.GetBuffer(),
(CStringA)nFilePath.GetBuffer());
printf("错误代码--%d\n", GetLastError());
return;
}
// 获取文件大小
DWORD dwSize = GetFileSize(hFile, NULL);
CHAR* pFile = new CHAR[dwSize]{};
// 读取文件内容
DWORD dwRead;
SetFilePointer(hFile, 0, NULL, FILE_BEGIN); //设置文件指针
ReadFile(hFile, pFile, dwSize, &dwRead, NULL); //读取文件
// 关闭文件句柄
CloseHandle(hFile);
//恢复文件 病毒感染标识:whboy+原文件名+0x2E+(exe/PIF等)+0x02+原文件大小+0x01
int i = 0;
if (nVirType == 1) //可执行文件恢复
{
//获取原文件大小
for (i = 0; i < 13; i++)
{
if (*(pFile + dwSize - 13 + i) == (char)0x02)break; //0x02是分隔符
}
if (i == 13 || * (pFile + dwSize - 1) != (char)0x01) //0x01是结束符
{
//printf("未感染文件!%s\n", (CStringA)nFilePath.GetBuffer());
delete[]pFile;
return;
}
char nTemp[13]{};
DWORD nExeSize = 0;
size_t nCopySzie = 13 - i - 2;
memcpy_s(nTemp, 13, (pFile + dwSize - 13 + i + 1), nCopySzie);
sscanf_s(nTemp, "%d", &nExeSize);
if (nExeSize <= 0)
{
delete[]pFile;
return;
}
printf("感染文件类型:%s,尺寸:%d\n", (CStringA)nLastName.GetBuffer(), nExeSize);
char *NewFile = new char[nExeSize] {};
memcpy_s(NewFile, nExeSize, (pFile + VIRSIZE), nExeSize);
if (!DeleteFile(nFilePath))
{
printf("修复%s失败!%s\n", (CStringA)nLastName.GetBuffer(),
(CStringA)nFilePath.GetBuffer());
delete[]NewFile;
delete[]pFile;
return;
}
// 1.写入文件
HANDLE hFile = CreateFile(nFilePath,
GENERIC_WRITE, FALSE, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("写入文件失败\n");
return;
}
DWORD dwWrite;
WriteFile(hFile, NewFile, nExeSize, &dwWrite, NULL); //读取文件
CloseHandle(hFile);
if (dwWrite == nExeSize)
{
delete[]NewFile;
printf("修复%s成功!%s\n", (CStringA)nLastName.GetBuffer(),
(CStringA)nFilePath.GetBuffer());
}
}
else //网页文件恢复
{
CStringA nFileCode(pFile);
if (nFileCode.Find("www.ac86.cn/66/index.htm") != -1)
{
int nHtmlSize = dwSize - 76;
char *NewFile = new char[nHtmlSize] {};
memcpy_s(NewFile, nHtmlSize, pFile, nHtmlSize);
if (!DeleteFile(nFilePath))
{
printf("修复%s失败!%s\n", (CStringA)nLastName.GetBuffer(),
(CStringA)nFilePath.GetBuffer());
delete[]NewFile;
delete[]pFile;
return;
}
HANDLE hFile = CreateFile(nFilePath,
GENERIC_WRITE, FALSE, NULL, CREATE_NEW,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("创建网页文件失败--%s\n", (CStringA)nFilePath.GetBuffer());
return;
}
DWORD dwWrite;
WriteFile(hFile, NewFile, nHtmlSize, &dwWrite, NULL); //写入文件
CloseHandle(hFile);
if (dwWrite == nHtmlSize)
{
delete[] NewFile;
printf("修复%s成功!%s\n", (CStringA)nLastName.GetBuffer(),
(CStringA)nFilePath.GetBuffer());
}
}
}
delete[] pFile;
pFile = nullptr;
}
//************************************
// 功能: 删除配置文件
//************************************
void DeleteConfig(CString szPath)
{
// 1.构造路径
CString szFilePath = szPath;
szFilePath += _T("\\Desktop_.ini");
// 2.删除文件
WIN32_FIND_DATA wfd = { 0 };
HANDLE hFile = FindFirstFile(szFilePath, &wfd);
if (hFile == INVALID_HANDLE_VALUE)
{
return; //文件不存在
}
FindClose(hFile);
DeleteVirFile(szFilePath);
printf("删除Desktop_.ini成功--%ls\n", szFilePath.GetBuffer());
}
int main()
{
// 1.结束病毒进程,删除文件
DWORD dwPid = 0;
FindVirProcess("spo0lsv.exe", &dwPid);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
TerminateProcess(hProcess, 0);
DeleteVirFile("C:\\Windows\\System32\\drivers\\spo0lsv.exe");
printf("完成----结束病毒进程\n");
// 2.删除病毒自启动项
//HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run\svcshare
HKEY hKey = NULL;
int nError = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\", &hKey);
if (nError != ERROR_SUCCESS) MessageBoxA(NULL, "打开注册表失败1", "提示", MB_ICONWARNING);
RegDeleteValueA(hKey, "svcshare");
RegCloseKey(hKey);
printf("完成----删除病毒自启动项\n");
// 3.恢复注册表CheckValue值
//HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Folder\Hidden\SHOWALL\\CheckedValue
nError = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL\\", &hKey);
if (nError != ERROR_SUCCESS) MessageBoxA(NULL, "打开注册表失败2", "提示", MB_ICONWARNING);
DWORD nVal = 1;
RegSetValueExA(hKey, "CheckedValue", 0, REG_DWORD, (CONST BYTE*)&nVal, sizeof(DWORD));
RegCloseKey(hKey);
printf("完成----恢复注册表CheckValue值\n");
// 4.删除autorun.inf和setup.exe
DeleteVirFile("C:\\autorun.inf");
DeleteVirFile("C:\\setup.exe");
printf("完成----删除autorun.inf和setup.exe\n");
// 5.遍历文件夹,清除Desktop_.ini,恢复感染文件
vector DiverList;
GetDriverList(DiverList);
for (UINT i=0;i