windows远程线程注入原理实践

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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值