http://www.vckbase.com/index.php/wv/1653
//为了简化代码,下面程序中去掉了对出错处理的代码,实际应用中应该考虑程序运行时可能的出错:
#include "stdafx.h"
static PIMAGE_NT_HEADERS nt_header;
#define IMAGESIZE (nt_header->OptionalHeader.SizeOfImage)
#define EXPORT_TABEL (nt_header->OptionalHeader.DataDirectory[0].VirtualAddress)
#define RELOC_TABEL (nt_header->OptionalHeader.DataDirectory[5].VirtualAddress)
static void RelocCode (PBYTE Image, LPBYTE InjectBase) // 完成代码的重定位
{
DWORD Rva = 0, RvaCount = 0, RelocOffset=0;
WORD *Offset = NULL;
LPBYTE RelocTable = Image + RELOC_TABEL; //重定位表位置
PIMAGE_BASE_RELOCATION basereloc= (PIMAGE_BASE_RELOCATION) RelocTable;
RelocOffset= (DWORD)InjectBase - nt_header ->OptionalHeader.ImageBase; //重定位表偏移
while(basereloc ->VirtualAddress != NULL)// 遍历重定位表,修正需要重定位的代码
{
Offset = (WORD*)(RelocTable + sizeof(IMAGE_BASE_RELOCATION));
RvaCount = (basereloc ->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2;
for(DWORD i=0; iVirtualAddress + (DWORD)Image;
*(DWORD*)Rva += RelocOffset;//RVA加上修正量进行修正
}
RelocTable += basereloc ->SizeOfBlock;//指向下一页重定位信息处
basereloc = (PIMAGE_BASE_RELOCATION) RelocTable;
}
}
int LoadAPI(LPBYTE InjectBase)// 用于完成API函数的导入,参数为要插入代码处地址
{
PIMAGE_DOS_HEADER dos_h = (PIMAGE_DOS_HEADER) InjectBase;
PIMAGE_NT_HEADERS nt_h = (PIMAGE_NT_HEADERS)(InjectBase + dos_h->e_lfanew);
PIMAGE_IMPORT_DESCRIPTOR import_d = (PIMAGE_IMPORT_DESCRIPTOR)
(InjectBase + nt_h->OptionalHeader.DataDirectory[1].VirtualAddress);
for( ; import_d->OriginalFirstThunk != 0; import_d++)//遍历导入表
{
HMODULE hDll = LoadLibrary((LPCSTR)(InjectBase + import_d->Name));
//上面能直接引用LoadLibrary是由于本地和远程进程中该函数地址都是相同的
if(hDll == NULL)
return 0;
PIMAGE_THUNK_DATA Origin = (PIMAGE_THUNK_DATA)(InjectBase +import_d->OriginalFirstThunk);
PIMAGE_THUNK_DATA First = (PIMAGE_THUNK_DATA)(InjectBase + import_d->FirstThunk);
LPCSTR Name = NULL;
PIMAGE_IMPORT_BY_NAME Import_name = NULL;
for(; Origin->u1.Ordinal != 0; Origin++, First++)
{
if(Origin->u1.Ordinal & IMAGE_ORDINAL_FLAG)
Name = (LPCSTR)IMAGE_ORDINAL(Origin->u1.Ordinal);
else
{
Import_name = (PIMAGE_IMPORT_BY_NAME)(InjectBase + (DWORD)( Origin->u1.AddressOfData));
Name = (LPCSTR)Import_name->Name;
}
First->u1.Function = (DWORD * )GetProcAddress(hDll, Name);
//上面能直接引用GetProcAddress是由于本地和远程进程中该函数地址都是相同的
if(First->u1.Function == NULL)
return 0;
}
}
return 1;
}
DWORD RemoteThread_Main(HINSTANCE hInstance) //远程要执行的代码,在这里只演示MessageBox
{
::MessageBox (0,"远程线程插入成功!","远程线程",0);
return 1;
}
DWORD ThreadEntry(LPBYTE ImageBase) /*** 远程线程入口 ***/
{
if(LoadAPI(ImageBase))//先完成API函数的导入工作
RemoteThread_Main ((HINSTANCE)ImageBase); //执行函数RemoteThread_Main中的代码
return 1;
}
static DWORD GetTargetProcessId() //获取远程进程 PID
{
DWORD ProcessId = 0;
HWND hWnd = FindWindow("Progman", "Program Manager");//获取资源管理器进程PID
if(hWnd != NULL)
GetWindowThreadProcessId(hWnd, &ProcessId);
return ProcessId;
}
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow)
{
LPBYTE InjectPoint = NULL, Module = NULL, NewModule = NULL,Param =NULL;
HANDLE hProcess = NULL, hThread = NULL;
DWORD ProcessId = 0, ImageSize = 0;
LPTHREAD_START_ROUTINE RemoteEntryPoint = NULL;
Module = (unsigned char *)GetModuleHandle(NULL);//获取自身句柄
nt_header = (PIMAGE_NT_HEADERS)(Module + ((PIMAGE_DOS_HEADER)Module)->e_lfanew);
ImageSize = IMAGESIZE ; //得到内存映象大小
//通过VirtualAllocEx申请存放自身代码的内存空间
NewModule =( LPBYTE )VirtualAlloc(NULL, ImageSize, MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
memcpy(NewModule, Module, ImageSize) ; //将自身复制到NewModule处
nt_header = (PIMAGE_NT_HEADERS)(NewModule + ((PIMAGE_DOS_HEADER)NewModule)->e_lfanew);
if( ProcessId = GetTargetProcessId() ) //获取远程进程 PID
if( hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessId)) //打开进程
//通过VirtualAllocEx在打开的远程进程中申请内存空间
if( InjectPoint = (LPBYTE)VirtualAllocEx(hProcess, 0, ImageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE) )
{
RelocCode (NewModule, InjectPoint); //重定位NewModule处的代码
RemoteEntryPoint = (LPTHREAD_START_ROUTINE)( InjectPoint +(DWORD) &ThreadEntry - Module );//得到ThreadEntry在远程进程中的地址
Param = InjectPoint; //将插入点地址作为参数传递给线程函数
//将重定位好的代码通过WriteProcessMemory写入远程进程的内存空间中
if(WriteProcessMemory(hProcess, InjectPoint, NewModule, ImageSize, NULL))
//通过CreateRemoteThread启动刚写入的代码,参数为Param
CreateRemoteThread(hProcess, NULL, 0, RemoteEntryPoint, Param, 0, NULL);
}
return 0;
}