【病毒分析】——熊猫烧香 && 专杀工具C源码

最近忙里偷闲,将自己分析过的一些病毒记录一下,一是给刚入门的小白有个借鉴,二是不让自己写博客的习惯停下来。

 

一、基本信息

FileName

panda.exe

Type

感染型病毒

Size

30001 bytes

MD5

512301C535C88255C9A252FDF70B7A03

SHA-1

CA3A1070CFF311C0BA40AB60A8FE3266CFEFE870

加壳

fsg v2.0

 

二、样本简介

1、概述

该样本为经典的熊猫烧香病毒,是一款感染型病毒,能够感染全盘指定类型的文件,修改文件数据和图标,同时可以在局域网内进行横向传播以及作为Downloader下载恶意数据执行,并且具有对抗杀软和长久驻留系统的能力。

 

2、主要行为简述

1)感染全盘二进制文件(exe、src、PIF、com)、脚本文件(htm、html、asp、php、jsp、aspx)

2)添加spo0lsv.exe到注册表自启动项HKCU\~\Run

3)修改注册表CheckedValue=1强制系统隐藏文件不显示

4)局域网内横向传播,尝试弱口令登录

5)连接恶意C2下载数据并隐藏执行

6)关闭杀软、删除杀软服务、删除杀软自启动项

7)禁用注册表、任务管理器等系统管理软件

8)释放自启动脚本autorun.inf和setup.exe,每隔6执行

9)全盘全目录写入Desktop_.ini并写入感染日期

 

三、病毒流程图

【病毒分析】——熊猫烧香 && 专杀工具C源码_第1张图片

 

四、动态行为

1、进程和线程

退出当前进程后启动spo0lsv.exe继续执行

【病毒分析】——熊猫烧香 && 专杀工具C源码_第2张图片

spo0lsv.exe创建了大量线程

 

2、注册表

【病毒分析】——熊猫烧香 && 专杀工具C源码_第3张图片

添加注册表自启动项,同时禁用注册表。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第4张图片

设置系统隐藏目录和文件不显示。

 

3、文件操作

【病毒分析】——熊猫烧香 && 专杀工具C源码_第5张图片

全盘释放Desktop_.ini,释放setup.exe、autorun.inf

【病毒分析】——熊猫烧香 && 专杀工具C源码_第6张图片

Desktop_.ini写入当前感染日期

【病毒分析】——熊猫烧香 && 专杀工具C源码_第7张图片

C盘根目录下生成两个隐藏的病毒自启动文件setup.exe、autorun.inf

【病毒分析】——熊猫烧香 && 专杀工具C源码_第8张图片

感染全盘exe文件,修改图标

【病毒分析】——熊猫烧香 && 专杀工具C源码_第9张图片

EXE尾部感染特征

【病毒分析】——熊猫烧香 && 专杀工具C源码_第10张图片

感染HTML文件

【病毒分析】——熊猫烧香 && 专杀工具C源码_第11张图片

HTML尾部感染特征

【病毒分析】——熊猫烧香 && 专杀工具C源码_第12张图片

释放源文件到C:\Windows\System32\drivers\spo0lsv.exe

 

4、网络行为

【病毒分析】——熊猫烧香 && 专杀工具C源码_第13张图片

连接恶意C2

【病毒分析】——熊猫烧香 && 专杀工具C源码_第14张图片

尝试局域网横向传播

五、静态分析

1、脱fsg壳

脱fsg壳的关键在于最后修复错误的IAT地址。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第15张图片

硬件断点

【病毒分析】——熊猫烧香 && 专杀工具C源码_第16张图片

硬断断下向上找jmp大跳,F2断点执行过去

【病毒分析】——熊猫烧香 && 专杀工具C源码_第17张图片

dump点,OEP

【病毒分析】——熊猫烧香 && 专杀工具C源码_第18张图片

导入表不对,修复IAT,OD中跳转到4101E8,将错误的地址改为0

【病毒分析】——熊猫烧香 && 专杀工具C源码_第19张图片

Import REC重新载入保存即可

 

2、代码功能分析

样本大致逻辑如下,前面为作者的自言自语、判断文件是否被修改过和变量初始化,图中标注的三个函数为病毒的恶意逻辑,也是下面要重点分析的部分。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第20张图片

 

1)恶意逻辑一:释放并执行spo0lsv.exe

病毒执行后释放文件到 C:\Windows\System32\drivers\spo0lsv.exe,并创建进程执行该文件,随后退出自身进程。其中病毒会有一个判断逻辑,如果当前进程的文件路径并非在System32目录下,则退出当前进程,释放spo0lsv.exe文件并执行之。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第21张图片

【病毒分析】——熊猫烧香 && 专杀工具C源码_第22张图片

【病毒分析】——熊猫烧香 && 专杀工具C源码_第23张图片

 

2)恶意逻辑二:感染

样本的感染功能通过3个函数实现,包括全盘感染和局域网感染,感染类型又分为二进制文件和脚本文件,同时定时函数会每隔6秒通过autorun.inf来启动setup.exe,实现病毒的定时执行。

 

  • sub_40A5B0:感染线程,感染的范围为全盘,目标针对两类文件如下表,核心感染逻辑如下图。

二进制文件

exe、src、pif、com

脚本文件

htm、html、asp、php、jsp、aspx

【病毒分析】——熊猫烧香 && 专杀工具C源码_第24张图片

 

感染逻辑开始执行时,首先会排除一些系统运行相关的重要目录不进行感染

【病毒分析】——熊猫烧香 && 专杀工具C源码_第25张图片

下列目录不进行感染

WINDOWS

WINNT 

system32 

Documents and Settings

System Volume Information

Recycled

Windows NT

WindowsUpdate

Windows Media Player

Outlook Express

Internet Explorer

NetMeeting

Common Files

ComPlus Applications

Common Files

Messenger

InstallShield Installation Information

Microsoft Frontpage

Movie Maker

MSN Gamin Zone

 

遍历到目录的时候,如果当前目录下存在Desktop_.ini文件,则将当前感染日期写入,如果不存在则新建该文件。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第26张图片

 

为防止用户通过GHO恢复系统,会删除目录下的GHO文件。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第27张图片

 

当判断文件的类型为二进制文件时,则执行二进制文件的感染逻辑。感染过程相对简单,具体步骤为:先将目标文件读入内存并保存其数据,然后将病毒源文件复制到内存同一地址覆盖目标文件,再将目标文件的源文件追加写入病毒数据的后面,最后添加感染标识,感染标识的格式为“.WhBoy文件名.后缀.后缀.随机数字(5-6位).”。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第28张图片

 

通过获取系统时间设置随机种子,获取目标文件。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第29张图片

 

具体感染步骤如下,已感染过的文件不会进行再次感染。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第30张图片

以exe文件来说,感染后的文件结构如下,大致分为三部分。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第31张图片

 

对脚本文件的感染相对来说简单的很,只是在文件尾部追加一句

【病毒分析】——熊猫烧香 && 专杀工具C源码_第32张图片

【病毒分析】——熊猫烧香 && 专杀工具C源码_第33张图片

以HTML文件举例来说,感染后的文件结构如下图。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第34张图片

  • sub_40C374:设置计时器,每隔6秒执行autorun.inf以启动病毒程序

为防止自身进程被关闭,病毒会通过定时执行脚本的方法来实现定时启动,实现的具体步骤为检查根目录下是否存在setup.exeautorun.inf,不存在则释放这俩文件并设置隐藏属性,然后向autorun文件中写入自启动脚本,定时执行。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第35张图片

【病毒分析】——熊猫烧香 && 专杀工具C源码_第36张图片

【病毒分析】——熊猫烧香 && 专杀工具C源码_第37张图片

 

  • sub_40BACC:局域网横向传播线程

为了最大化造成破坏,局域网传播也是此类病毒的惯用手法,最常被利用的就是139和445这两个TCP端口。139端口的通信过程是通过SMB(服务器信息块)协议实现的,其具体过程为:首先取得通信对象的IP地址,然后向通信对象发出开始通信的请求。如果对方充许进行通信,就会确立会话层,并使用它向对方发送用户名和密码信息,进行认证。如果认证成功,就可以访问对方的共享文件。445端口的协议尽管不同,但是作用相同,区别是当139和445端口同时打开的话,网络文件共享优先使用445端口。

该样本同样对139和445端口进行了检测,如果检测到端口开放,则尝试弱口令登录,一旦登陆成功则感染网络共享文件,可想而知该样本在当年安全意识薄弱的大环境下,传播速度是多么恶心。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第38张图片

 

3)恶意逻辑三:对抗杀软与自我保护

第三个恶意逻辑主要实现了一些自我保护手段,比如关闭杀软进程、删除杀软服务、设置注册表自启动、设置注册表隐藏项、下载恶意文件执行、停止网络共享等,基本功能函数如下图。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第39张图片

 

  • 设置注册表项SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL\\CheckedValue的值为1。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第40张图片

 

  • 创建线程对自身进程进行提权,提升至Debug权限,然后关闭杀软窗口和杀软进程。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第41张图片

遍历关闭杀毒软件窗口

【病毒分析】——熊猫烧香 && 专杀工具C源码_第42张图片

遍历关闭杀毒软件进程

禁用注册表和任务管理器

 

关闭杀毒软件窗口

防火墙、进程、VirusScan、NOD32、网镖、杀毒、毒霸、瑞星、江民、超级兔子、优化大师、木马清道夫、木馬清道夫、卡巴斯基反病毒、Symantec AntiVirus、Duba、esteem procs、绿鹰PC、密码防盗、噬菌体、木马辅助查找器、System Safety Monitor、Wrapped giftKiller、Winsock、Expert、msctls_statusbar32、超级巡警、游戏木马检测大师、pjf(ustc)、IceSword

关闭杀毒软件进程

Mcshield.exe、VsTskMgr.exe、naPrdMgr.exe、UpdaterUI.exe、TBMon.exe、scan32.exe、Ravmond.exe、Ccenterexe、RavTask.exe、Rav.exe、Ravmon.exe、RavmonD.exe、RavStub.exe、KVXP.kxp、KvMonXP.kxp、KVCenter.kxp、KVSrvXP.exe、KRegEx.exe、UIHost.exe、TrojDiekxp、FrogAgent.exe、Logo1_.exe、Logo_1.exe、Rundl132.exe、regedit.exe、msconfig.exe、taskmgr.exe

 

  • 构造请求头,访问C2下载包含恶意数据的txt文件,保存到Windows目录下并设置隐藏,再通过WinExec执行。最后一个函数和此函数的作用一致。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第43张图片

  • 删除系统根目录下的网络共享

【病毒分析】——熊猫烧香 && 专杀工具C源码_第44张图片

 

  • 关闭杀软服务、删除杀软服务、删除杀软注册表自启动项。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第45张图片

 

  • 对五个网站进行访问,应该是测试网络连通性,这也是很多需要网络连接的病毒常见的行为。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第46张图片

 

六、查杀方案

1、查杀思路(查杀功能)

  • 结束病毒进程spo0lsv.exe进程
  • 修复注册表,包括删除病毒自启动项svcshare、修复文件的隐藏显示
  • 删除C盘下的autorun.inf、setup.exe、spo0lsv.exe文件
  • 遍历全盘删除Desktop_.ini,修复受感染的文件,二进制文件和脚本文件要区别处理

 

2、编写专杀工具

专杀工具由C语言编写,大致逻辑对应了上述查杀思路,针对受感染文件根据上面分析得到的感染后结构图进行逆向处理,将原始文件剥离出来即可。

使用方法:运行KillPanda.exe后选择病毒源文件点击确定即可,等待杀毒完毕,可查看简单的杀毒情况,如下演示。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第47张图片

 

如下为测试文件,包含了样本会感染的所有文件类型。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第48张图片

测试文件

 

首先执行病毒,让其运行一段时间,可见所有测试文件均被感染。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第49张图片

 

然后运行专杀工具KillPanda.exe,选择病毒源文件,点击确定开始查杀。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第50张图片

查杀过程

【病毒分析】——熊猫烧香 && 专杀工具C源码_第51张图片

查杀结果

【病毒分析】——熊猫烧香 && 专杀工具C源码_第52张图片

修复效果

 

注意:

由于时间问题该工具并未提供太多的交互细节,默认的是遍历C、D盘进行查杀,有需要可以自行修改代码添加其他盘符执行修复,源码见附。

 

七、样本溯源

熊猫烧香原作者为湖北李俊,后被捕入狱,该样本也衍生了大量的新版本,但核心恶意逻辑基本相同,在如今的电脑上基本逃不过主流杀软的检测。

执行下载的网址为www.ac86.cn,IP为15.164.151.80,归属地韩国首尔。

【病毒分析】——熊猫烧香 && 专杀工具C源码_第53张图片

 

相关MD5

c971a9426b79e58174c986d1d83652e4

c2ab3350ffa681753851820cf6783ee3

9aaff9869da5d3201dc3d34d3455acee

b4bf0edae88010e9e3d2061941cd28d0

ca0ea7b2a7002715071cc6954c5adbd0

539af15ae47eb7eee5adb634a6eef1af

5e4ed60fad58151a9e315fb6f70f4e37

e2ccfeb6bb4efb30fe5318f2480140e2

0ca507a964adfac44d39cd692a2f3e08

0fa38dbb42e670da3dadd8b62400117e

91350bf5502c67fa8d2bb25027788def

9083de14e99885968080cbec9429f2eb

1ebb3a636cbeaadbfdd403f4421001e5

9eea3b1ae8801e501527eaadc529dc61

26bc4086ff2fb55883b621fd3b2f56c5

a81c5fb25c80a01faf5512eb9387cab2

2d5e2810b08b83d1b4240fe59ccf25ae

3144d3a3f3fcfd82cc8766c34b681b1e

33543e14b5237a53d5b49154ae545ab1

 

八、总结

       病毒本身很简单,没啥分析难度,其特点在于感染之后的顽固性,能够实现系统的长久驻留,在此提醒用户安装正规厂商的杀毒软件,不要随意下载和执行来历不明的文件,定期杀毒并且允许自动更新病毒库,重视自身的数据安全。

 

附:

#include 
#include 
#include 
#include 
#pragma warning(disable : 4996)

// 3个全局变量用于最后的杀毒报告
int FixBinaryFileNumber = 0;
int FixScriptFileNumber = 0;
int DelDesktop_iniFileNumber = 0;
int SizeOfVirusFile_Bytes = 0;
char path[MAX_PATH];														// 保存病毒文件路径

																			// 结束指定进程,参数为目标进程字符串
BOOL KillPandaProcess(const char *pszProcessName)
{
	BOOL bKill = FALSE;
	HANDLE hProcess;
	HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hProcessSnap == INVALID_HANDLE_VALUE)									// 如果获取进程快照失败,返回 FALSE
	{
		return bKill;
	}
	PROCESSENTRY32 pe = { 0 };
	pe.dwSize = sizeof(pe);
	BOOL bRet = Process32First(hProcessSnap, &pe);								// 获取第一个进程
	while (bRet)
	{
		if (strcmp(pe.szExeFile, pszProcessName) == 0)
		{
			bKill = TRUE;
			hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
			int ret = TerminateProcess(hProcess, 1);							// 终止进程
			if (ret)
			{
				printf("Yeah!Panda's Process is dead!\n\n");
			}
			else
			{
				printf("OMG!Panda is still alive!\n\n");
			}
			break;
		}
		bRet = Process32Next(hProcessSnap, &pe);
	}
	CloseHandle(hProcessSnap);
	return bKill;
}

// 修复注册表
void FixReg()
{
	// 删除svcshare
	char RegRun[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Run";
	HKEY hKeyHKCU = NULL;
	LONG lSize = MAXBYTE;
	char cData[MAXBYTE] = { 0 };
	long lRet = RegOpenKey(HKEY_CURRENT_USER, RegRun, &hKeyHKCU);
	if (lRet == ERROR_SUCCESS)
	{
		lRet = RegQueryValueEx(hKeyHKCU, "svcshare", NULL, NULL, (unsigned char *)cData, (unsigned long *)&lSize);
		if (lRet == ERROR_SUCCESS)
		{
			if (strcmp(cData, "C:\\WINDOWS\\system32\\drivers\\spo0lsv.exe") == 0)
			{
				printf("Find virus AutorunRegInfo!\n\n");
			}
			lRet = RegDeleteValue(hKeyHKCU, "svcshare");
			if (lRet == ERROR_SUCCESS)
			{
				printf("Panda's RegItem has beed deleted!\n\n");
			}
			else
			{
				printf("Panda's RegItem is still alive or is gone!\n\n");
			}
		}
		else
		{
			printf("Reg is clear!\n\n");
		}
		RegCloseKey(hKeyHKCU);
	}
	else
	{
		printf("Open Reg failed!\n\n");
	}
	// 修复文件的隐藏显示,将CheckedValue的值设置为1
	char RegHide[] = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Folder\\Hidden\\SHOWALL";
	HKEY hKeyHKLM = NULL;
	DWORD dwFlag = 1;
	long lRetHide = RegOpenKey(HKEY_LOCAL_MACHINE, RegHide, &hKeyHKLM);
	if (lRetHide == ERROR_SUCCESS)
	{
		if (ERROR_SUCCESS == RegSetValueEx(
			hKeyHKLM,             //subkey handle  
			"CheckedValue",       //value name  
			0,                    //must be zero  
			REG_DWORD,            //value type  
			(CONST BYTE*)&dwFlag, //pointer to value data  
			4))                   //length of value data
		{
			printf("Reg fixed!\n\n");
		}
		else
		{
			printf("Can't fix RegHiddenItem or it's clear!\n\n");
		}
	}

}

// 删除指定文件
BOOL DelSPacificFile(const char * FileName)
{
	// 去除文件的隐藏、系统以及只读属性
	DWORD dwFileAttributes = GetFileAttributes(FileName);						// 获取文件属性
	dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;									// &=~ 是去掉属性,| 是增加属性 ==== 这里就是去掉隐藏、系统、只读3个属性
	dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
	dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
	SetFileAttributes(FileName, dwFileAttributes);

	int delRet = DeleteFile(FileName);											// 删除文件
	if (delRet)
	{
		printf("File %s has been Deleted!\n\n", FileName);
		return TRUE;
	}
	else
	{
		printf("File %s is still alive! MayBe it has been deleted!\n\n", FileName);
		return FALSE;
	}
}

// 判断文件是否为指定二进制文件
bool IsEXE(const char* pFileName)
{
	const char* pTemp = pFileName;								// 从第一个字符开始,不断比对剩下的字符串
	while (*pTemp != 0x00)										// 注意PIF为大写
	{
		if (!strcmp(pTemp, ".exe") || !strcmp(pTemp, ".PIF") || !strcmp(pTemp, ".com") || !strcmp(pTemp, ".src"))
		{
			return true;
		}
		++pTemp;
	}
	return false;
}

// 判断文件是否为指定脚本
bool IsHTML(const char* pFileName)
{
	const char* pTemp = pFileName;
	while (*pTemp != 0x00)
	{
		if (!strcmp(pTemp, ".html") || !strcmp(pTemp, ".htm") || !strcmp(pTemp, ".asp") || !strcmp(pTemp, ".php") || !strcmp(pTemp, ".jsp") || !strcmp(pTemp, ".aspx"))
		{
			return true;
		}
		++pTemp;
	}
	return false;
}

// 根据路径名返回文件名
char *GetFilename(char *p)
{
	int x = strlen(p);
	char ch = '\\';
	char *q = strrchr(p, ch) + 1;
	return q;
}

// 修复感染二进制文件
BOOL FixBinaryFile(char* pStrFilePath)
{
	CHAR* pFilebuf = NULL;
	HANDLE hFile = CreateFile(pStrFilePath,									// 打开受感染文件
		GENERIC_READ | GENERIC_WRITE,
		FALSE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		MessageBoxA(NULL, "Open infected file failed!", "WTF!", NULL);
		return 0;
	}

	DWORD FileSize = GetFileSize(hFile, NULL);								// 获取感染后文件大小
	pFilebuf = new CHAR[FileSize]{};										// 申请个数组用来保存
	DWORD dwCount = 1;
	BOOL bRet = ReadFile(hFile, pFilebuf, FileSize, &dwCount, NULL);		// 将感染文件读入内存
	if (!bRet)																// 读取出现错误
	{
		CloseHandle(hFile);
		delete pFilebuf;
		return FALSE;
	}
	char* pFileOffset = pFilebuf + SizeOfVirusFile_Bytes;									// 被感染文件的前面,0x7531为病毒源文件大小,1ffff字节为病毒脱壳后的文件
	char *p = pStrFilePath;
	int FileNameLength = strlen(GetFilename(p));							// 获取文件名长度

	SetFilePointer(hFile, 0, 0, FILE_BEGIN);								// 0x7531是病毒的大小
	WriteFile(hFile, pFileOffset, FileSize - SizeOfVirusFile_Bytes - FileNameLength - 2, &dwCount, NULL);	// 感染标志的长度影响因子为目标文件的文件名长度
	SetEndOfFile(hFile);
	FixBinaryFileNumber++;													// 计数器统计修复个数
	CloseHandle(hFile);

	delete[] pFilebuf;
	return TRUE;
}

// 修复感染脚本文件
bool FixScriptFile(const char* pstrFilePath)
{
	CHAR* pFilebuf = NULL;
	HANDLE hFile = CreateFile(pstrFilePath,
		GENERIC_READ | GENERIC_WRITE,
		FALSE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		MessageBoxA(NULL, "Open file failed!", "WTF", NULL);
		return 0;
	}
	DWORD FileSize = GetFileSize(hFile, NULL);
	pFilebuf = new CHAR[FileSize]{};
	DWORD dwCount = 1;
	BOOL bRet = ReadFile(hFile, pFilebuf, FileSize, &dwCount, NULL);		// 文件读入内存
	if (!bRet)
	{
		CloseHandle(hFile);
		delete pFilebuf;
		return FALSE;
	}
	char* pFileOffset = pFilebuf;
	SetFilePointer(hFile, 0, 0, FILE_BEGIN);
	WriteFile(hFile, pFilebuf, FileSize - 76, &dwCount, NULL);				// 删除最后75个字节
	SetEndOfFile(hFile);
	FixScriptFileNumber++;													// 计数器统计修复个数
	CloseHandle(hFile);
	delete[] pFilebuf;
	return TRUE;
}

// 将文件读入内存并获取大小
char* GetFileBuf(char* pstrFilePath, _Out_ DWORD* FileSize)
{
	char* pFilebuf = NULL;
	//打开文件获取句柄
	HANDLE hFile = CreateFile(pstrFilePath,
		GENERIC_READ,
		FALSE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("File Open Faild!\n\n");
		return 0;
	}

	//获取文件大小
	*FileSize = GetFileSize(hFile, NULL);

	pFilebuf = new char[*FileSize]{};
	//读文件
	DWORD dwCount = 1;
	BOOL bRet = ReadFile(hFile, pFilebuf, *FileSize, &dwCount, NULL);

	if (bRet)
	{
		CloseHandle(hFile);
		return pFilebuf;
	}
	//释放资源
	CloseHandle(hFile);
	delete pFilebuf;
	return 0;

}

// 是否是被感染的二进制文件,被感染文件最后一个字节为01,向前找到00的后五个字节是WhBoy
bool IsInfectedBinaryFile(char* pstrFilePath)
{
	CHAR* pFileBuf = NULL;
	DWORD dwFileSize = 0;
	pFileBuf = GetFileBuf(pstrFilePath, &dwFileSize);
	if (pFileBuf == 0)
	{
		return false;
	}
	BYTE* pFileOffset = (BYTE*)pFileBuf;
	*pFileOffset;
	pFileOffset += (dwFileSize - 1);

	if (*pFileOffset != 0x01)									// 判断是否为0x01,不是的话就没感染
	{
		delete[] pFileBuf;
		return  false;
	}
	while (*pFileOffset != 0x00)
	{
		--pFileOffset;
	}
	pFileOffset++;
	CHAR temp[6] = { 0 };
	memcpy_s(temp, 5, pFileOffset, 5);
	if (!strcmp(temp, "WhBoy"))
	{
		delete[] pFileBuf;
		return  true;
	}
	delete[] pFileBuf;
	return  false;
}

// 是否是被感染的脚本文件
bool IsInfectedScriptFIle(char* pstrFilePath)
{
	CHAR* pFileBuf = NULL;
	DWORD dwFileSize = 0;
	pFileBuf = GetFileBuf(pstrFilePath, &dwFileSize);
	if (pFileBuf == 0)
	{
		return 0;
	}
	BYTE* pFileOffset = (BYTE*)pFileBuf;
	*pFileOffset;
	pFileOffset += (dwFileSize - 64);

	CHAR temp[32] = { 0 };
	memcpy_s(temp, 31, pFileOffset, 31);
	if (!lstrcmp(temp, "http://www.ac86.cn/66/index.htm"))
	{
		delete[] pFileBuf;
		return  TRUE;
	}
	delete[] pFileBuf;
	return  FALSE;
}

// 遍历全盘修复文件
DWORD WINAPI Delini_FixInfectedFiles(const char* lpszPath)
{
	WIN32_FIND_DATA stFindFile;
	HANDLE hFindFile;

	char szPath[MAX_PATH];
	char szFindFile[MAX_PATH];
	char szSearch[MAX_PATH];
	const char *szFilter;
	int len;
	int ret = 0;

	szFilter = "*.*";
	strcpy(szPath, lpszPath);
	len = lstrlen(szPath);
	if (szPath[len - 1] != '\\')
	{
		szPath[len] = '\\';
		szPath[len + 1] = '\0';
	}
	strcpy(szSearch, szPath);
	strcat(szSearch, szFilter);

	hFindFile = FindFirstFile(szSearch, &stFindFile);
	if (hFindFile != INVALID_HANDLE_VALUE)
	{
		do
		{
			strcpy(szFindFile, szPath);
			strcat(szFindFile, stFindFile.cFileName);

			if (stFindFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
			{
				if (stFindFile.cFileName[0] != '.')
				{
					Delini_FixInfectedFiles(szFindFile);
				}
			}
			else
			{
				if (!strcmp(stFindFile.cFileName, "Desktop_.ini"))						// 删除Desktop_.ini
				{

					DWORD dwFileAttributes = GetFileAttributes(szFindFile);				// 去除文件的隐藏、系统以及只读属性
					dwFileAttributes &= ~FILE_ATTRIBUTE_HIDDEN;
					dwFileAttributes &= ~FILE_ATTRIBUTE_SYSTEM;
					dwFileAttributes &= ~FILE_ATTRIBUTE_READONLY;
					SetFileAttributes(szFindFile, dwFileAttributes);

					BOOL bRet = DeleteFile(szFindFile);
					if (bRet)
					{
						printf("\"%s\"_____deleted!\n", szFindFile);
						DelDesktop_iniFileNumber++;										// 计数器统计个数
					}
					else
					{
						printf("Deleted \"%s\" failed!\n", szFindFile);
					}
				}
				else if (IsEXE(stFindFile.cFileName))									//判断是否是二进制文件
				{
					if (IsInfectedBinaryFile(szFindFile))
					{
						// printf("%s infected!\n", szFindFile);
						if (FixBinaryFile(szFindFile))
						{
							printf("\"%s\"_____fixed!\n", szFindFile);
						}
						else
						{
							printf("Fix \"%s\" failed!\n", szFindFile);
						}
					}
					else
					{
						printf("\"%s\"_____healthy!\n\n", szFindFile);
					}
				}
				else if (IsHTML(stFindFile.cFileName))									//判断是否是脚本文件
				{
					if (IsInfectedScriptFIle(szFindFile))
					{
						// printf("%s infected!\n", szFindFile);
						if (FixScriptFile(szFindFile))
						{
							printf("\"%s\"_____fixed!\n", szFindFile);
						}
						else
						{
							printf("Fix \"%s\" failed!!!!!\n", szFindFile);
						}
					}
					else
					{
						printf("\"%s\"_____healthy!\n", szFindFile);
					}
				}
			}
			ret = FindNextFile(hFindFile, &stFindFile);
		} while (ret != 0);
	}

	FindClose(hFindFile);
	return 0;
}

// 选择病毒源文件,获取病毒源文件大小
void SelectVirusFile_GetVirusSize()
{
	// 选择Virus文件
	OPENFILENAMEA ofn;
	memset(path, 0, MAX_PATH);
	memset(&ofn, 0, sizeof(ofn));
	ofn.lStructSize = sizeof(ofn);
	ofn.lpstrFile = path;																	// path
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFilter = "*.exe\0*.exe\0";
	ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
	if (!GetOpenFileName(&ofn)) {															// 如果打开文件错误
		MessageBox(NULL, "Open file failed!", NULL, MB_OK);
		exit(0);																			// 退出所有进程
	}
	// 获取文件句柄,映射到内存
	HANDLE hFile = CreateFileA(path, GENERIC_ALL, 3u, NULL, OPEN_EXISTING, 0x80u, 0);		// path,第一个3u表示共享读写
	DWORD dwFileSize = GetFileSize(hFile, NULL);											// 获取文件大小
	SizeOfVirusFile_Bytes = dwFileSize;
}

int main()
{
	SelectVirusFile_GetVirusSize();											// 选择病毒文件,获取其大小

	FixReg();																// 修复注册表
	KillPandaProcess("spo0lsv.exe");										// 结束病毒进程

	DelSPacificFile("C:\\autorun.inf");										// 删除C盘根目录下的文件
	DelSPacificFile("C:\\setup.exe");
	DelSPacificFile("C:\\Windows\\System32\\drivers\\spo0lsv.exe");

	Delini_FixInfectedFiles("C:");											// 执行C盘感染修复
	Delini_FixInfectedFiles("D:");											// 执行D盘感染修复
																			// Delini_FixInfectedFiles("C:");										// 自行添加

	printf("\n==================YOUR PC IS CLEAR !=====================\n");
	printf("\n*********************** REPORT **************************\n");// 修复报告
	printf("The size of Virus file is %d bytes\n", SizeOfVirusFile_Bytes);
	printf("Fix binary files :%d \n", FixBinaryFileNumber);
	printf("Fix script files :%d \n", FixScriptFileNumber);
	printf("Del Desktop_.ini :%d \n", DelDesktop_iniFileNumber);
	printf("*********************** REPORT **************************\n\n");// 修复报告

	system("pause");
	return 0;
}

 

你可能感兴趣的:(病毒分析,熊猫烧香,病毒,分析,逆向,专杀)