一文带你实现远程线程注入和卸载

1. 原理

主要通过API:CreateRemoteThread 来进行远程线程注入

2.远程线程注入Dll的步骤

1.通过进程Id打开指定的进程 2.在指定的进程,分配一段大小为要导入的dll文件名长度的一段内存空间,将dll的文件名写入到分配的内存中。 3.获取目的进程中的loadLibrary的函数地址。 4.创建远程线程,通过上一步获得的loadlibrary函数进行dll导入。 5.释放内存,卸载dll。

3.代码远程注入注意点

1.不能调用除kernel32和user32之外动态库中的api函数。 2.不能使用static字符串 3. 去掉编译器的/GZ编译选项。这个选项是默认的,不然注入进去被注入的程序会崩溃。 4. 要么把ThreadFunc和AfterThreadFunc声明为static,要么关闭编译器的“增量连接(incremental linking)”(看附录C)。 5. ThreadFunc中的局部变量总大小必须小于4k字节。注意,当degug编译时,这4k中大约有10个字节会被事先占用。 (注入64位的程序,那么也需要64位的dll,主要用的函数:NtCreateThreadEx)

4.代码实现

//提升权限
BOOL cRemoteThreadInject::grantPriviledge(char* priName)
{
	if(NULL == priName)
	{
		return FALSE;
	}
	TOKEN_PRIVILEGES tokenPriviledge, oldPriviledge;
	DWORD dwRetLength = sizeof(oldPriviledge);
	HANDLE tokenHandle = NULL;
	LUID uId;
	if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, FALSE, &tokenHandle))
	{
		if (ERROR_NO_TOKEN != GetLastError())
		{
			return FALSE;
		}
		if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle))
		{
			return FALSE;
		}
	}
	if (!LookupPrivilegeValue(NULL, priName, &uId))
	{
		CloseHandle(tokenHandle);
		tokenHandle = NULL;
		return FALSE;
	}
	tokenPriviledge.PrivilegeCount = 1;
	tokenPriviledge.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	tokenPriviledge.Privileges[0].Luid = uId;
	if (!AdjustTokenPrivileges(tokenHandle, FALSE, &tokenPriviledge, sizeof(TOKEN_PRIVILEGES), &oldPriviledge, &dwRetLength))
	{
		CloseHandle(tokenHandle);
		tokenHandle = NULL;
		return FALSE;
	}
	return TRUE;
}
/*
函数功能:通过进程名称获取进程PID
参数1:进程名称
参数2:返回的进程pid
*/
BOOL cRemoteThreadInject::GetProcessId(IN char* processName, OUT DWORD* processId)
{
	if(NULL == processName)
	{
		return FALSE;
	}
	
	HANDLE handle = NULL;
	PROCESSENTRY32 processTry32 ={0};
	
	processTry32.dwSize = sizeof(PROCESSENTRY32);
	handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if(INVALID_HANDLE_VALUE == handle)
	{
		return FALSE;
	}
	Process32First(handle, &processTry32);
	do{
		if(lstrcmpi(processTry32.szExeFile, processName) == 0)
		{
			*processId = processTry32.th32ProcessID;
			break;
		}
	}while(Process32Next(handle, &processTry32));
	CloseHandle(handle);
	handle = NULL;
	if(0 == *processId)
	{
		return FALSE;
	}
	return TRUE;
}
/*
功能:注入dll文件到进程
参数1:进程的名称
参数2:注入dll的路径
*/
BOOL cRemoteThreadInject::injectDll(char* processName, char* dllPath)
{
	if((NULL == processName)  || (NULL == dllPath))
	{
		return FALSE;
	}
	DWORD processId = 0;
	GetProcessId(processName, &processId);
	if(processId <= 0)
	{
		return FALSE;
	}
	grantPriviledge("SE_DEBUG_NAME");
	HANDLE handle = NULL;
	handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
	if(NULL == handle)
	{
		return FALSE;
	}
	
	int dllPathLen = sizeof(dllPath) +1;
	PVOID data = VirtualAllocEx(handle, NULL, dllPathLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if(NULL == data)
	{
		CloseHandle(handle);
		handle = NULL;
		return FALSE;
	}
	SIZE_T RetLength = 0;
	BOOL bWriteMem = WriteProcessMemory(handle, data, dllPath, strlen(dllPath)+1, &RetLength);
	if(FALSE == bWriteMem)
	{
		return FALSE;
	}
	LPTHREAD_START_ROUTINE LoadLibraryAddress = NULL;
#ifdef _UNICODE
	HMODULE  Kernel32Module = GetModuleHandle(L"Kernel32");
	LoadLibraryAddress =  (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryW");
#else
	HMODULE  Kernel32Module = GetModuleHandle(_T("Kernel32"));
	LoadLibraryAddress =  (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32Module, "LoadLibraryA");
#endif
	HANDLE  Threadhandle = CreateRemoteThread(handle, NULL, 0, LoadLibraryAddress, data, 0, NULL);
	if (NULL == Threadhandle)
	{
		CloseHandle(handle);
		handle = NULL;
		return FALSE;
	}
	if (WaitForSingleObject(Threadhandle, INFINITE) == WAIT_FAILED)
	{
		return FALSE;
	}
	CloseHandle(handle);
	handle = NULL;
	CloseHandle(Threadhandle);
	Threadhandle = NULL;
	return TRUE;
}
/*
函数功能:卸载注入到进程后的dll
参数1:进程的名称
参数2:要卸载的dll
*/
BOOL cRemoteThreadInject::unitInjectDll(char* processName, char* dllPath)
{
	if((NULL == processName) || (NULL == dllPath))
	{
		return FALSE;
	}
	DWORD processId = 0;
	GetProcessId(processName, &processId);
	if(processId <= 0)
	{
		return FALSE;
	}
	BOOL bMore = FALSE;
	BOOL bFound = FALSE;
	HANDLE hSnapshot, hProcess, hThread;
	HMODULE hModule = NULL;
	MODULEENTRY32 me = {sizeof(me)};
	LPTHREAD_START_ROUTINE pThreadProc;
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
	bMore = Module32First(hSnapshot, &me);
	for(; bMore; bMore = Module32Next(hSnapshot, &me))
	{
		if(!_tcsicmp(me.szModule, dllPath) || !_tcsicmp(me.szExePath, dllPath))
		{
			bFound = TRUE;
			break;
		}
	}
	if(!bFound)
	{
		CloseHandle(hSnapshot);
		return FALSE;
	}
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
	if(NULL == hProcess)
	{
		return FALSE;
	}
	hModule = GetModuleHandle("kernel32.dll");
	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hProcess);
	hProcess = NULL;
	CloseHandle(hThread);
	hThread = NULL;
	CloseHandle(hSnapshot);
	hSnapshot = NULL;
	return TRUE;
}

最后:

最近我整理了整套 《JAVA核心知识点总结》,说实话 ,作为一名Java程序员,不论你需不需要面试都应该好好看下这份资料。

版权申明:本站文章均来自网络,如有侵权,请联系01056159998 邮箱:itboby@foxmail.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

猜你还会喜欢下面的内容

    无相关信息

中国领先的互联网域名及云服务提供商

为您提供域名,比特币,P2P,大数据,云计算,虚拟主机,域名交易最新资讯报道

域名注册云服务器