一、PE加载
在PE结构非常熟系的情况下,往往我们都会想要实现一套PE加载器,其基本流程可以分为以下几点:
- 将PE文件从磁盘中读出
- 根据PE结构获取镜像大小,再申请一段可读可写可执行的内存并填充为0
- 将读取数据映射到内存中
- 修复导出导入入表
- 修复重定位
- 跳转到PE入口点进行执行
相信各位对以上流程都非常熟悉,而且只有实现了PE加载才能真正掌握PE结构,作为抛砖引玉下面我们就聊聊一种DLL注入的方式——反射式注入。
#include "LoadPE.h"
using namespace std;
int main()
{
LOADPE m_pe;
char address[] = "G:\\VS文件\\HookMain\\Debug\\HookMain.exe";
PBYTE pBuf = m_pe.GetFile(address);
if (!pBuf)
{
cout << "打开文件错误 ! ! ! " << endl;
return 1;
}
else
{
if (!m_pe.LoadPE(pBuf))
{
return 1;
}
}
return 0;
}
#pragma once
#include <Windows.h>
#include <iostream>
typedef struct _PE_INFO
{
DWORD ImportTableRva;
DWORD ImportSize;
DWORD ExportTableRva;
DWORD ExportSize;
}PE_INFO, * PPE_INFO;
class LOADPE
{
public:
PBYTE GetFile(char* FileName);
BOOL LoadPE(PBYTE pBuf);
private:
PBYTE lpBuf;
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
private:
BOOL CheckPE();
DWORD AlignSection(DWORD dwSize, DWORD Align);
BOOL RepairIAT(LPBYTE pAllocMem);
void RepairRelocation(LPBYTE pAllocMem);
};
#include "LoadPE.h"
using namespace std;
typedef void(__stdcall* ProcMain)();
PBYTE LOADPE::GetFile(char* FileName)
{
FILE* fp = fopen(FileName, "rb+");
char* pBuf = NULL;
fseek