思路:
1.CreateProcess 创建进程 ,进程信息放在 PROCESS_INFORMATION pi 中。
2. GetSystemInfo 获取内存中的所有数据,放在 SYSTEM_INFO sysinfo; 中。
3.从 sysinfo.lpMinimumApplicationAddress 开始, 每一次的大小为 sysinfo.dwPageSize 到 sysinfo.lpMaximumApplicationAddress结束,遍历内存。
4.每次都 VirtualQueryEx 一次, 把当前页的内存信息放到 MEMORY_BASIC_INFORMATION mbi = {0}中。
5.当 VirtualQueryEx 出来的类型是 MEM_IMAGE 时,内存中的地址又是指定文件名的映射,就保存并返回这个地址。
6.用 CImage 的 AttachToProcess方法读取刚刚地址的内存头,保存在 PBYTE ImageBase中。
7.用 VirtualQueryEx 出来的内存地址 加 CImage结构体中的m_dwEntryPoint长度,就是程序内存中的入口点。
8.找到打开程序的程序入口点的地址,就可以准备要注入的code了。
typedef struct _INJECT_DATA64
{
BYTE ShellCode[0xC0];
/*Off=0x0C0*/HANDLE ModuleHandle; //Dll句柄
/*Off=0x0C8*/PUNICODE_STRING pDllPath;//PUNICODE_STRING DllPath
/*Off=0x0D0*/ULONG DllCharacteristics;
/*Off=0x0D8*/ULONG_PTR AddrOfLdrLoadDll;//LdrLoadDll地址
/*Off=0x0E0*/ULONG_PTR ProtectBase; //用于VirtualMemory
/*Off=0x0E8*/ULONG OldProtect; //用于VirtualMemory
/*Off=0x0F0*/SIZE_T ProtectSize;s
/*Off=0x0F8*/ULONG_PTR ExeEntry;//Exe入口点的地址
/*Off=0x100*/ULONG_PTR AddrOfZwProtectVirtualMemory;
/*Off=0x108*/BYTE SavedEntryCode[16];//保存exe入口点的前16字节
/*Off=0x118*/UNICODE_STRING usDllPath;//Dll路径
/*Off=0x128*/WCHAR wDllPath[256];//Dll路径,也就是usDllPath中的Buffer
}INJECT_DATA64;
9.用 VirtualAllocEx 分配出一块 0x1000 大小的内存,分给 之前打开的进程。
10.ReadProcessMemory 读取目标进程的前8个字节,并存到变量里。
11.用 VirtualProtectEx 修改目标进程的内存属性。
12.找到目标进程中32位 ntdll 的地址。
13.通过计算自己内存里ntdll中ZwProtectVirtualMemory和LdrLoadDll的偏移,来推测目标进程的相关函数的偏移。
14.获取 shellcode的内容,开始到偏移的内容。把内容放到 INJECT_DATA64 结构体的 ShellCode中。
15.填充 INJECT_DATA64 结构体的 其他内容。
16.用 WriteProcessMemory 把 INJECT_DATA64 结构体写道目标进程中,位置是之前用 VirtualAllocEx 分配的内存 。
17.编写Jmp xxxx指令,用 WriteProcessMemory 让程序在开头跳转到 shellcode 执行。
18.ResumeThread 让暂停的线程继续执行。
代码参考 加密解密 随书光盘中的 : chap12\10.CreateProcContextInject\CreateProcContextInject.cpp