学习:远程代码注入
远程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;
}