1.传统的远程线程注入方法:
#include<Windows.h>
#include<tlhelp32.h>
#include<stdio.h>
//由进程名获得进程id
DWORD
GetProcessIdByName(TCHAR *pProcess)
{
DWORD ProcessId = NULL;
PROCESSENTRY32 lppe;
//在使用这个结构前,先设置它的大小
lppe.dwSize = sizeof(lppe);
//给系统内所有的进程拍快照
HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printf("CreateToolhelp32Snapshot调用失败。\n");
return NULL;
}
//遍历进程快照,轮流显示每个进程的信息
BOOL bMore = ::Process32First(hProcessSnap, &lppe);
while (bMore)
{
if (strcmp(lppe.szExeFile, pProcess) == 0)
{
ProcessId = lppe.th32ProcessID;
break;
}
bMore = ::Process32Next(hProcessSnap, &lppe);
}
//清理hProcessSnap对象
::CloseHandle(hProcessSnap);
//返回匹配的进程id,如果没有匹配则返回NULL
return ProcessId;
}
//将pszDllFileName指定的模块注入到dwProcessId对应的进程中
BOOL
CreateRemoteThreadInjectDll(DWORD dwProcessId, char *pszDllFileName)
{
HANDLE hprocess = NULL;
DWORD dwSize = 0;
LPVOID pDllAddr = NULL;
FARPROC pFuncProcAddr = NULL;
//打开注入进程,获取进程句柄
hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (NULL == hprocess) {
return FALSE;
}
//在注入进程中申请内存
dwSize = strlen(pszDllFileName) + 1;
pDllAddr = ::VirtualAllocEx(hprocess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (NULL == pDllAddr) {
return FALSE;
}
//向申请的内存中写入数据
if (FALSE == ::WriteProcessMemory(hprocess, pDllAddr, pszDllFileName, dwSize, NULL)) {
return FALSE;
}
//获取loadlibray函数的地址
pFuncProcAddr = ::GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (pFuncProcAddr == NULL) {
return FALSE;
}
HANDLE hRemoteThread = CreateRemoteThread(hprocess, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, NULL);
if (NULL == hRemoteThread) {
return FALSE;
}
::CloseHandle(hRemoteThread);
return TRUE;
}
int
main(int argc, char *argv[])
{
DWORD processId = GetProcessIdByName((CHAR *)argv[1]);
CreateRemoteThreadInjectDll(processId, argv[2]);
return 0;
}
注意事项:如果注入失败的话,可以尝试以管理员权限运行程序。由于OpenProcess函数的原因,在打开高权限的进程时,会因为权限不足而打开失败。同时,如果用这种方法想要注入一些系统服务进程时会注入失败,这是由于系统从在SESSION 0隔离的安全机制,接下来所用方法可以成功突破SESSION 0的安全隔离,但是此时由于SESSION隔离,在系统服务程序中不能显示程序窗体(MessageBox弹窗不能正常工作),也不能用常规方法创建用户进程。
2.突破SESSION 0隔离的远程线程注入方法
BOOL
zwCreateThreadExInjectDll(DWORD dwprocess, char *pszDllFileName)
{
HANDLE hprocess = NULL;
DWORD dwSize = 0;
LPVOID pDllAddr = NULL;
FARPROC pFuncProcAddr = NULL;
HMODULE hNtdllDll = ::LoadLibrary("ntdll.dll");
if (NULL == hNtdllDll)
{
return FALSE;
}
//打开注入进程,获取进程句柄
hprocess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwprocess);
if (NULL == hprocess)
{
return FALSE;
}
//在注入进程中申请内存
dwSize = strlen(pszDllFileName) + 1;
pDllAddr = ::VirtualAllocEx(hprocess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (NULL == pDllAddr) {
return FALSE;
}
//向申请的内存中写入数据
if (FALSE == ::WriteProcessMemory(hprocess, pDllAddr, pszDllFileName, dwSize, NULL)) {
return FALSE;
}
//获取loadlibray函数的地址
pFuncProcAddr = ::GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (pFuncProcAddr == NULL) {
return FALSE;
}
typedef_ZwCreateThreadEx zwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
if (NULL == zwCreateThreadEx)
{
return FALSE;
}
HANDLE hRemoteThread;
DWORD dwStatus = zwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hprocess, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, 0, 0, 0, NULL);
if (NULL == hRemoteThread)
{
return FALSE;
}
::CloseHandle(hRemoteThread);
return TRUE;
}