资源表
资源表地址在数据目录的数组下标为2的地方,定位到资源表后就可以遍历资源
资源是树形结构,一般有3层 根目录 子目录 文件
- 根目录结构结构体如下定义
typedef struct _IMAGE_RESOURCE_DIRECTORY {
DWORD Characteristics; 资源属性
DWORD TimeDateStamp; 时间戳
WORD MajorVersion; 资源大版本号
WORD MinorVersion; 资源小版本号
WORD NumberOfNamedEntries; 按照名称命名的数量
WORD NumberOfIdEntries; 按照ID命名的数量// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
} IMAGE_RESOURCE_DIRECTORY, *PIMAGE_RESOURCE_DIRECTORY; //只有后面两个字段是重要的
- 资源目录项(子目录)结构体定义如下
ypedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY
{
union
{
struct
{
DWORD NameOffset:31; 位段: 低31位位是偏移 定义了目录项的名称或者ID
DWORD NameIsString:1; 位段: 高位, 如果这位为1,则表示31位的偏移指向的是一个Unicode字符串的指针偏移
}; 这里列出结构体,自己去看,IMAGE_RESOURCE_DIR_STRING_U 里面是字符串长度还有字符串,不是\0结尾
DWORD Name;
WORD Id;
};
union
{
DWORD OffsetToData; 偏移RVA因为是联合体,所以有不同的解释
struct
{
DWORD OffsetToDirectory:31; 看高位,如果高位是1,那么RVA偏移指向的是新的(根目录)
DWORD DataIsDirectory:1;
};
};
} IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
注意点:如果第一4字节高位为0 表示是ID 但是ID有3种表示,如果在第一层目录,也就是根目录下则表示是资源类型,第二层目录(子目录)表示的是资源ID 第3层目录(文件)ID表示的是代码页
3.资源文件定义如下
typedef struct _IMAGE_RESOURCE_DATA_ENTRY {
DWORD OffsetToData; 资源数据的偏移RVA
DWORD Size; 大小
DWORD CodePage; 代码页缓冲(CMD设置窗口的时候就是这个,没用)
DWORD Reserved; 保留
} IMAGE_RESOURCE_DATA_ENTRY, *PIMAGE_RESOURCE_DATA_ENTRY;
注意点:只有文件的时候OffsetToData才是RVA ,其他都是节内偏移
宿主病毒
- 将整个PE文件当资源加载到宿主文件
- 当宿主文件启动后,释放PE文件的资源
- 通过资源表或者API获取PE文件所在内存位置
- 创建新文件,将PE文件拷贝的新的文件中
- 使用CreateProcess打开新文件,运行PE文件进程
使用API获取资源在内存的位置代码如下
// LoadResourse.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<windows.h>
#include <string>
#include <WinUser.h>
#include "resource.h"
using namespace std;
void ReportError(std::string strError)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR)&lpMsgBuf,
0,
NULL
);
printf("%s==>%s", strError.c_str(), (char*)lpMsgBuf);
LocalFree(lpMsgBuf);
}
int _tmain(int argc, _TCHAR* argv[])
{
//加载资源
HMODULE hMoudule = GetModuleHandle(NULL);
if (hMoudule == NULL)
{
ReportError("GetModuleHandle");
}
HRSRC hRes = FindResource(hMoudule, MAKEINTRESOURCE(IDR_MYEXE1), "myexe");
if (hRes == NULL)
{
ReportError("FindResource");
}
HGLOBAL hResData = LoadResource(hMoudule, hRes);
if (hResData == NULL)
{
ReportError("LoadResource");
}
LPVOID lpFileData = LockResource(hResData);
if (lpFileData == NULL)
{
ReportError("LockResource");
}
DWORD dwResSize = SizeofResource(hMoudule, hRes);
if (dwResSize == 0)
{
ReportError("SizeofResource");
}
//创建文件
HANDLE hFile = CreateFile(
"MyExeCopy.exe",
GENERIC_READ | GENERIC_WRITE,
NULL,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
ReportError("CreateFile");
}
DWORD dwRealWriteSize = 0;
DWORD dwTotalWriteSize = 0;
while (dwTotalWriteSize < dwResSize)
{
if (!WriteFile(hFile, lpFileData, dwResSize, &dwRealWriteSize, NULL))
{
ReportError("WriteFile");
}
dwTotalWriteSize += dwRealWriteSize;
}
if (!CloseHandle(hFile))
{
ReportError("CloseHandle");
}
TCHAR szExe[] = { "MyExeCopy"};
PROCESS_INFORMATION stProcessInformation = { 0 };
STARTUPINFO stStartupInfo = { 0 };
stStartupInfo.cb = sizeof(stStartupInfo);
BOOL bRet = CreateProcess(
NULL,
szExe,
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&stStartupInfo, //设置窗口的一些基本信息
&stProcessInformation); //传出参数
if (!bRet)
{
ReportError("CreateProcess");
}
system("pause");
return 0;
}