• 学习:远程代码注入


    远程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
    ", GetLastError());
    		return FALSE;
    	}
    
    	if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
    		lpszPrivilege,  // privilege to lookup 
    		&luid))        // receives LUID of privilege
    	{
    		printf("LookupPrivilegeValue Error: %u
    ", 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
    ", GetLastError());
    		return FALSE;
    	}
    
    	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
    		printf("The token does not have the specified privilege. 
    ");
    		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
    ");
    		return false;
    	}
    
    	LPVOID lpRemoteThreadAddr, lpRemoteParamAddr;
    	
    	
    	lpRemoteThreadAddr = VirtualAllocEx(hProcess, NULL,dwThreadFunSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	if (lpRemoteThreadAddr == NULL) {
    		printf("VirtualAllocEx Failed
    ");
    		CloseHandle(hProcess);
    		return false;
    	}
    	
    	lpRemoteParamAddr = VirtualAllocEx(hProcess, NULL, sizeof(MESSAGEBOX_PARAM), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	if (lpRemoteParamAddr == NULL) {
    		printf("VirtualAllocEx Failed
    ");
    		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
    ");
    		return false;
    	}
    
    	//写入大小为MESSAGEBOX_PARAM,内容是 一个结构体,包含了关于要在对方进程中进行运行的参数内容
    	if ((WriteProcessMemory(hProcess, lpRemoteParamAddr, &MYMESSAGEBOX, sizeof(MESSAGEBOX_PARAM), 0)) == 0) {
    		printf("WriteProcessMemory Failed
    ");
    		return false;
    	}
    
    	//进行进程注入,传入的是对方进程中的线程函数的地址 和 结构体的地址
    	if (!(hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemoteThreadAddr, lpRemoteParamAddr,
    		0, &dwThread))) {
    		printf("CreateRemoteThread Error: %u
    ", 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
    ");
    		return false;
    	}
    
    	LPVOID lpRemoteThreadAddr, lpRemoteParamAddr;
    	
    	
    	lpRemoteThreadAddr = VirtualAllocEx(hProcess, NULL,dwThreadFunSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	if (lpRemoteThreadAddr == NULL) {
    		printf("VirtualAllocEx Failed
    ");
    		CloseHandle(hProcess);
    		return false;
    	}
    	
    	lpRemoteParamAddr = VirtualAllocEx(hProcess, NULL, sizeof(MESSAGEBOX_PARAM), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    
    	if (lpRemoteParamAddr == NULL) {
    		printf("VirtualAllocEx Failed
    ");
    		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
    ");
    		return false;
    	}
    
    	//写入大小为MESSAGEBOX_PARAM,内容是 一个结构体,包含了关于要在对方进程中进行运行的参数内容
    	if ((WriteProcessMemory(hProcess, lpRemoteParamAddr, &MYMESSAGEBOX, sizeof(MESSAGEBOX_PARAM), 0)) == 0) {
    		printf("WriteProcessMemory Failed
    ");
    		return false;
    	}
    
    	//进行进程注入,传入的是对方进程中的线程函数的地址 和 结构体的地址
    	if (!(hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpRemoteThreadAddr, lpRemoteParamAddr,0, &dwThread))) {
    		printf("CreateRemoteThread Error: %u
    ", 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
    ", GetLastError());
    		return FALSE;
    	}
    
    	if (!LookupPrivilegeValue(NULL,           // lookup privilege on local system
    		lpszPrivilege,  // privilege to lookup 
    		&luid))        // receives LUID of privilege
    	{
    		printf("LookupPrivilegeValue Error: %u
    ", 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
    ", GetLastError());
    		return FALSE;
    	}
    
    	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
    		printf("The token does not have the specified privilege. 
    ");
    		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;
    }
    
  • 相关阅读:
    javascript中的this指向
    面向对象和面向过程、对象、类、实例
    javascript
    实例011:养兔子
    day13匿名函数
    实例010:给人看的时间
    python基础学习day12 生成器与推导式
    实例009:暂停一秒输出
    python基础学习day11函数的进阶
    第一部分:趣味算法入门;第八题:冒泡排序(并与选择排序对比)
  • 原文地址:https://www.cnblogs.com/zpchcbd/p/12261785.html
Copyright © 2020-2023  润新知