原址:https://www.cnblogs.com/ndyxb/p/12751827.html 侵删
学习:远程代码注入
远程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; }
原文地址:http://www.cnblogs.com/chenyalin/p/16853101.html
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,请务用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性