学习:远程代码注入

远程DLL注入:适用于代码量大且复杂的情况

远程DLL注入:需要先把注入代码放入某个DLL文件,再将整个DLL文件注入目标进程。DLL代码中使用的所有数据位于DLL的数据区域,整个DLL插入目标进程时,代码和数据是共存于内存,因而代码能够正常执行。


远程代码注入:适用于代码量少且简单的情况。

远程代码注入:仅向目标进程注入必要的代码,要想使注入代码正常运行,还必须将代码中使用的数据一同注入。

代码注入的优点为:占用内存少;难以查找痕迹;无需另外的DLL文件。


代码注入的流程:

1、申请对自己的进程进行提升权限的操作,如果权限不够的话,很容易造成 OpenProcess 失败

BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
	TOKEN_PRIVILEGES tp;
	HANDLE hToken;
	LUID luid;

	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		printf("OpenProcessToken Error: %u\n", GetLastError());
		return FALSE;
	}

	if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
		lpszPrivilege,  // privilege to lookup 
		&luid))        // receives LUID of privilege
	{
		printf("LookupPrivilegeValue Error: %u\n", GetLastError());
		return FALSE;
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	if (bEnablePrivilege)
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	else
		tp.Privileges[0].Attributes = 0;

	// Enable the privilege or disable all privileges.
	if (!AdjustTokenPrivileges(hToken,
		FALSE,
		&tp,
		sizeof(TOKEN_PRIVILEGES),
		(PTOKEN_PRIVILEGES)NULL,
		(PDWORD)NULL))
	{
		printf("AdjustTokenPrivileges Error: %u\n", GetLastError());
		return FALSE;
	}

	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
		printf("The token does not have the specified privilege. \n");
		return FALSE;
	}

	return TRUE;
}

2、当前进程中定义好自己的结构体,里面的内容为自己需要注入到对方程序中所需要的参数内容等

typedef struct {
	DWORD dwMessageAddr;
	HWND hWnd;
	LPCSTR lpText;
	LPCSTR lpCaption;
	UINT uType;
}MESSAGEBOX_PARAM;

//作为MessageBoxA函数地址的函数指针
typedef int (WINAPI *PMESSAGE)
(
	HWND hWnd,
	LPCSTR lpText,
	LPCSTR lpCaption,
	UINT uType
);

3、然后对对方的进程进行申请内存,再将自己定义好的结构体写入内存,最后通过创建远程线程进行注入的操作


DWORD WINAPI ThreadProc(LPVOID lpParameter) {
	MESSAGEBOX_PARAM* Mess = (MESSAGEBOX_PARAM*)lpParameter;
	PMESSAGE pMessage;
	pMessage = (PMESSAGE)Mess->dwMessageAddr;
	pMessage(
		Mess->hWnd,
		Mess->lpText,
		Mess->lpCaption,
		Mess->uType
	);
	return 0;
}


BOOL RemoteMessage(DWORD PROCESSPID) {
	BOOL ret = 0;
	HANDLE hThread;
	HANDLE hProcess = 0;
	HINSTANCE DllModule;
	DWORD dwThread = 0;

	DWORD dwThreadFunSize = 0x800; //一个物理页
	
	HWND hWnd;
	LPCSTR lpText;
	LPCSTR lpCaption;
	UINT uType;

	//获取要注入的进程句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PROCESSPID);

	if (hProcess == NULL) {
		printf("OpenProcess Failed\n");
		return false;
	}

	LPVOID lpRemoteThreadAddr, lpRemoteParamAddr;
	
	
	lpRemoteThreadAddr = VirtualAllocEx(hProcess, NULL,dwThreadFunSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if (lpRemoteThreadAddr == NULL) {
		printf("VirtualAllocEx Failed\n");
		CloseHandle(hProcess);
		return false;
	}
	
	lpRemoteParamAddr = VirtualAllocEx(hProcess, NULL, sizeof(MESSAGEBOX_PARAM), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if (lpRemoteParamAddr == NULL) {
		printf("VirtualAllocEx Failed\n");
		CloseHandle(hProcess);
		return false;
	}


	MESSAGEBOX_PARAM MYMESSAGEBOX;
	MYMESSAGEBOX.hWnd = NULL;
	MYMESSAGEBOX.lpCaption = "This is Caption";
	MYMESSAGEBOX.lpText = "This is Text";
	MYMESSAGEBOX.uType = MB_OK;
	

	DllModule = LoadLibrary("User32.DLL");
	DWORD MessageFunc = (DWORD)GetProcAddress(DllModule, "MessageBoxA");
	
	MYMESSAGEBOX.dwMessageAddr = MessageFunc;
	printf("%x", GetProcAddress(DllModule, "MessageBoxA"));
	FreeLibrary(DllModule);

	DWORD dwFunAddr;

	dwFunAddr = (DWORD)ThreadProc;

	//CALL跳转需要进行修正地址
	if (*(BYTE*)dwFunAddr == 0xE9) {
		dwFunAddr = dwFunAddr + 5 + *(DWORD*)(dwFunAddr + 1); //下一行语句的地址加上当前语句E9后的地址再加5
	}

	//写入大小为0x400,内容的是  要在对方进程中进行执行的线程函数的地址
	if ((WriteProcessMemory(hProcess, lpRemoteThreadAddr, (LPVOID)dwFunAddr, dwThreadFunSize, 0)) == 0) {
		printf("WriteProcessMemory Failed\n");
		return false;
	}

	//写入大小为MESSAGEBOX_PARAM,内容是 一个结构体,包含了关于要在对方进程中进行运行的参数内容
	if ((WriteProcessMemory(hProcess, lpRemoteParamAddr, &MYMESSAGEBOX, sizeof(MESSAGEBOX_PARAM), 0)) == 0) {
		printf("WriteProcessMemory Failed\n");
		return false;
	}

	//进行进程注入,传入的是对方进程中的线程函数的地址 和 结构体的地址
	if (!(hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemoteThreadAddr, lpRemoteParamAddr,
		0, &dwThread))) {
		printf("CreateRemoteThread Error: %u\n", GetLastError());
		return false;
	}

	WaitForSingleObject(hThread, INFINITE);

	CloseHandle(hThread);

	return true;
}

完整代码:

#include<windows.h>
#include<Tlhelp32.h>
#include<stdio.h>


typedef struct {
	DWORD dwMessageAddr;
	HWND hWnd;
	LPCSTR lpText;
	LPCSTR lpCaption;
	UINT uType;
}MESSAGEBOX_PARAM;

//作为MessageBoxA函数地址的函数指针
typedef int (WINAPI *PMESSAGE)
(
	HWND hWnd,
	LPCSTR lpText,
	LPCSTR lpCaption,
	UINT uType
);


DWORD WINAPI ThreadProc(LPVOID lpParameter) {
	MESSAGEBOX_PARAM* Mess = (MESSAGEBOX_PARAM*)lpParameter;
	PMESSAGE pMessage;
	pMessage = (PMESSAGE)Mess->dwMessageAddr;
	pMessage(
		Mess->hWnd,
		Mess->lpText,
		Mess->lpCaption,
		Mess->uType
	);
	return 0;
}


BOOL RemoteMessage(DWORD PROCESSPID) {
	BOOL ret = 0;
	HANDLE hThread;
	HANDLE hProcess = 0;
	HINSTANCE DllModule;
	DWORD dwThread = 0;

	DWORD dwThreadFunSize = 0x800; 
	

	//获取要注入的进程句柄
	hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PROCESSPID);

	if (hProcess == NULL) {
		printf("OpenProcess Failed\n");
		return false;
	}

	LPVOID lpRemoteThreadAddr, lpRemoteParamAddr;
	
	
	lpRemoteThreadAddr = VirtualAllocEx(hProcess, NULL,dwThreadFunSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if (lpRemoteThreadAddr == NULL) {
		printf("VirtualAllocEx Failed\n");
		CloseHandle(hProcess);
		return false;
	}
	
	lpRemoteParamAddr = VirtualAllocEx(hProcess, NULL, sizeof(MESSAGEBOX_PARAM), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	if (lpRemoteParamAddr == NULL) {
		printf("VirtualAllocEx Failed\n");
		CloseHandle(hProcess);
		return false;
	}


	MESSAGEBOX_PARAM MYMESSAGEBOX;
	MYMESSAGEBOX.hWnd = NULL;
	MYMESSAGEBOX.lpCaption = "This is Caption";
	MYMESSAGEBOX.lpText = "This is Text";
	MYMESSAGEBOX.uType = MB_OK;
	

	DllModule = LoadLibrary("User32.DLL");
	DWORD MessageFunc = (DWORD)GetProcAddress(DllModule, "MessageBoxA");
	
	MYMESSAGEBOX.dwMessageAddr = MessageFunc;
	printf("%x", GetProcAddress(DllModule, "MessageBoxA"));
	FreeLibrary(DllModule);

	DWORD dwFunAddr;

	dwFunAddr = (DWORD)ThreadProc;

	//CALL跳转需要进行修正地址
	if (*(BYTE*)dwFunAddr == 0xE9) {
		dwFunAddr = dwFunAddr + 5 + *(DWORD*)(dwFunAddr + 1); //下一行语句的地址加上当前语句E9后的地址再加5
	}

	//写入大小为0x400,内容的是  要在对方进程中进行执行的线程函数的地址
	if ((WriteProcessMemory(hProcess, lpRemoteThreadAddr, (LPVOID)dwFunAddr, dwThreadFunSize, 0)) == 0) {
		printf("WriteProcessMemory Failed\n");
		return false;
	}

	//写入大小为MESSAGEBOX_PARAM,内容是 一个结构体,包含了关于要在对方进程中进行运行的参数内容
	if ((WriteProcessMemory(hProcess, lpRemoteParamAddr, &MYMESSAGEBOX, sizeof(MESSAGEBOX_PARAM), 0)) == 0) {
		printf("WriteProcessMemory Failed\n");
		return false;
	}

	//进行进程注入,传入的是对方进程中的线程函数的地址 和 结构体的地址
	if (!(hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemoteThreadAddr, lpRemoteParamAddr,0, &dwThread))) {
		printf("CreateRemoteThread Error: %u\n", GetLastError());
		return false;
	}

	WaitForSingleObject(hThread, INFINITE);

	CloseHandle(hThread);

	return true;
}

BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
	TOKEN_PRIVILEGES tp;
	HANDLE hToken;
	LUID luid;

	if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		printf("OpenProcessToken Error: %u\n", GetLastError());
		return FALSE;
	}

	if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
		lpszPrivilege,  // privilege to lookup 
		&luid))        // receives LUID of privilege
	{
		printf("LookupPrivilegeValue Error: %u\n", GetLastError());
		return FALSE;
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	if (bEnablePrivilege)
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	else
		tp.Privileges[0].Attributes = 0;

	// Enable the privilege or disable all privileges.
	if (!AdjustTokenPrivileges(hToken,
		FALSE,
		&tp,
		sizeof(TOKEN_PRIVILEGES),
		(PTOKEN_PRIVILEGES)NULL,
		(PDWORD)NULL))
	{
		printf("AdjustTokenPrivileges Error: %u\n", GetLastError());
		return FALSE;
	}

	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
		printf("The token does not have the specified privilege. \n");
		return FALSE;
	}

	return TRUE;
}

DWORD GetOneProcessPid(const char *FileName) {
	HANDLE hSnapShot;
	PROCESSENTRY32 pro32;

	pro32.dwSize = sizeof(PROCESSENTRY32);
	// 1、获得当前进程的快照

	hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	if (hSnapShot == INVALID_HANDLE_VALUE) {
		return -1;
	}

	bool bMore;
	// 2、遍历进程的名称是否为指定名称,获取指定进程名称的PID
	bMore = Process32First(hSnapShot, &pro32);
	while (bMore) {
		// 3、获取指定进程名称的PID
		if (!strcmp(pro32.szExeFile, FileName)) {
			return pro32.th32ProcessID;
		}
		bMore = Process32Next(hSnapShot, &pro32);       //遍历
	}

	// 4、释放资源
	CloseHandle(hSnapShot);

	return 0;
}


int main() {
	if (!SetPrivilege(SE_DEBUG_NAME, TRUE)) {
		return -1;
	}

	RemoteMessage(GetOneProcessPid("notepad.exe"));
	return 0;
}
posted @ 2020-02-04 22:19  zpchcbd  阅读(810)  评论(0编辑  收藏  举报