【DLL注入】C++远程DLL注入

这是个很古老的DLL注入技术,采用的是创建远程线程的方式。将LdadLibraryA的函数地址当做线程的回调地址,线程参数采用待注入DLL的绝对路径值。这个参数我们得采用VirtualAllocEx和WriteProcessMemory的方式在目标进程进行内存空间的申请和写入。废话不多说,贴上自己写的代码:

DLL注入函数:

 

bool Dll_Inject(DWORD& v_dwProcessId, const char* v_szDLLPath)
{
	bool bRet = false;
	HANDLE hProcess = NULL;
	PVOID pRemoteThread = NULL;
	HANDLE hRemoteThread = NULL;
	__try
	{
		//!<获取进程句柄
		printf("GetProcessHandle Start.\n");
		hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |   // Required by Alpha
			PROCESS_CREATE_THREAD     |   // For CreateRemoteThread
			PROCESS_VM_OPERATION      |   // For VirtualAllocEx/VirtualFreeEx
			PROCESS_VM_WRITE,
			FALSE,
			v_dwProcessId);             // For WriteProcessMemory, FALSE, v_dwProcessId);
		if (hProcess == NULL)
		{
			printf("GetProcessHandle Failed.<%d>\n", GetLastError());
			__leave;
		}
		printf("GetProcessHandle Success.\n");

		//!<在宿主进程中申请内存空间1024字节
		printf("VirtualAllocEx Start.\n");
		pRemoteThread = VirtualAllocEx(hProcess, NULL, THREAD_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
		if(pRemoteThread == NULL)
		{
			printf("VirtualAllocEx Failed.<%d>\n", GetLastError());
			__leave;
		}
		printf("VirtualAllocEx Success.\n");

		//!<将待加载的dll路径写入申请的内存空间
		printf("WriteProcessMemory Start.\n");
		DWORD dwWrite;
		if(WriteProcessMemory(hProcess, pRemoteThread, v_szDLLPath, THREAD_SIZE, &dwWrite))
		{
			if (dwWrite != THREAD_SIZE)
			{
				printf("WriteProcessMemory Failed.<%d>\n", GetLastError());
				VirtualFreeEx(hProcess, pRemoteThread, THREAD_SIZE, MEM_RELEASE);
				CloseHandle(hProcess);
				__leave;
			}
		}
		else
		{
			//VirtualFreeEx(hTaskMgr, pRemoteThread, THREAD_SIZE, MEM_RELEASE);
			printf("WriteProcessMemory Failed.<%d>\n", GetLastError());
			__leave;
		}
		printf("WriteProcessMemory Success.\n");

		//!<获取LoadLibraryA函数地址
		printf("CreateRemoteThread Start.\n");
		g_RemoteParam.dwLoadLibraryAddr = (DWORD)GetProcAddress(GetModuleHandle("Kernel32"), "LoadLibraryA");
		DWORD dwThreadId;
		hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)g_RemoteParam.dwLoadLibraryAddr, pRemoteThread, 0, &dwThreadId);
		if (hRemoteThread == NULL)
		{
			printf("CreateRemoteThread Failed.<%d>\n", GetLastError());
			__leave;
		}
		printf("CreateRemoteThread Success. Inject Success!\n");

		//!<等待线程退出
		WaitForSingleObject(hRemoteThread, INFINITE);
		bRet = true;
	}
	__finally
	{
		//!<释放资源	
		if (pRemoteThread != NULL)
		{
			VirtualFreeEx(hProcess, pRemoteThread, THREAD_SIZE, MEM_RELEASE);
		}

		if (hRemoteThread != NULL)
		{
			CloseHandle(hRemoteThread);
		}

		if (hProcess != NULL)
		{
			CloseHandle(hProcess);
		}
	}

	return bRet;
}


DLL卸载函数:

 

 

bool Dll_Enject(DWORD& v_dwProcessId, const char* v_szDLLPath)
{
	BOOL bOk = FALSE;
	HANDLE hthSnapshot = NULL;
	HANDLE hProcess = NULL;
	HANDLE hThread = NULL;
	__try 
	{
		//!<查找出注入的dll模块的基地址
		hthSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, v_dwProcessId);
		if (hthSnapshot == INVALID_HANDLE_VALUE)
			__leave;

		MODULEENTRY32 me = { sizeof(me) };
		BOOL bFound = FALSE;
		BOOL bMoreMods = Module32First(hthSnapshot, &me);
		for (; bMoreMods; bMoreMods = Module32Next(hthSnapshot, &me)) 
		{
			bFound = (stricmp(me.szModule,  v_szDLLPath) == 0) || (stricmp(me.szExePath, v_szDLLPath) == 0);
			if (bFound) 
				break;
		}
		if (!bFound)
			__leave;

		//!<获取进程句柄
		hProcess = OpenProcess(
			PROCESS_QUERY_INFORMATION |   
			PROCESS_CREATE_THREAD     | 
			PROCESS_VM_OPERATION,  // For CreateRemoteThread
			FALSE, v_dwProcessId);
		if (hProcess == NULL) 
			__leave;

		//!<获取卸载dll函数地址
		PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE)
			GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "FreeLibrary");
		if (pfnThreadRtn == NULL)
			__leave;

		//!<直接创建远程进程,这里线程参数不需要再进行内存申请,是因为dll已经注入到目标进程当中,查找出来的dll基地址就是在目标进程当中
		hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, me.modBaseAddr, 0, NULL);
		if (hThread == NULL) 
			__leave;

		//!<等待线程退出
		WaitForSingleObject(hThread, INFINITE);

		bOk = TRUE;
	}
	__finally
	{ 
		//!<释放资源
		if (hthSnapshot != NULL) 
			CloseHandle(hthSnapshot);

		if (hThread != NULL) 
			CloseHandle(hThread);

		if (hProcess != NULL) 
			CloseHandle(hProcess);
	}

	return(bOk);
}


调用例子:

 

 

int _tmain(int argc, _TCHAR* argv[])
{	
	DWORD dwTaskMgr;
	printf("Input The Process ID:");
	scanf("%d", &dwTaskMgr);

	std::string szDLLPath = GetCurExePath() + "InjectDll.dll";

	//!<先进行提权操作
	printf("AdjustTokenPrivileges Start.\n");
	if (!EnableDebugPrivilege(TRUE))
	{
		printf("AdjustTokenPrivileges Failed.<%d>\n", GetLastError());
	}
	printf("AdjustTokenPrivileges Success.\n");

	if (Dll_Inject(dwTaskMgr, szDLLPath.c_str()))
	{
		Dll_Enject(dwTaskMgr, szDLLPath.c_str());
		printf("DLL Injection/Ejection successful.\n");
	}
	else
	{
		printf("DLL Injection/Ejection failed.\n");
	}

	system("pause");

	return 0;
}

还有一些工具函数的定义:

 

 

#define THREAD_SIZE 1024

typedef struct _REMOTE_PARAMETER 
{
	DWORD dwLoadLibraryAddr;
}REMOTE_PARAM, *PREMOTE_PARAM;

REMOTE_PARAM g_RemoteParam;

//!<提权操作
BOOL EnableDebugPrivilege( BOOL fEnable )
{
	// Enabling the debug privilege allows the application to see
	// information about service applications
	BOOL fOk = FALSE;    // Assume function fails
	HANDLE hToken;

	// Try to open this process's access token
	if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
	{
		// Attempt to modify the "Debug" privilege
		TOKEN_PRIVILEGES tp;
		tp.PrivilegeCount = 1;
		LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
		tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED : 0;
		AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
		//TRACE("AdjustTokenPrivileges:%d\n", GetLastError());
		fOk = (GetLastError() == ERROR_SUCCESS);
		CloseHandle(hToken);
	}
	return(fOk);
}

DWORD GetProcessIdByName(const char* v_szName)
{
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);  
	if (INVALID_HANDLE_VALUE == hSnapshot)   
	{  
		return NULL;  
	}  
	PROCESSENTRY32 pe = { sizeof(pe) };  
	BOOL fOk;  
	for (fOk = Process32First(hSnapshot, &pe); fOk; fOk = Process32Next(hSnapshot, &pe))   
	{  
		if (!stricmp(pe.szExeFile, v_szName))   
		{  
			CloseHandle(hSnapshot);  
			return pe.th32ProcessID;
		}  
	}  
	return NULL; 
}

std::string GetCurExePath()
{
	char szExePath[MAX_PATH] = {0};
	if (GetModuleFileNameA(NULL, szExePath, MAX_PATH) > 0)
	{
		LPSTR pos = strrchr(szExePath, '\\');
		if (pos)
		{
			*++pos = 0;
			return szExePath;
		}
	}
	else
	{
		printf("Get Exe Path Failed.");
	}
}

 

 

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值