高级注入技术小结

  • 本文主要总结了几种不太常见的高级注入技术
    • Module Stomping(LoadLibrary)
    • Module Stomping(NtMapViewOfSection)
    • AtomBombing
    • Process Hollowing
    • Process Doppelgänging
    • Transacted Hollowing
    • Process Ghosting等

0x01 Module Stomping(LoadLibrary)

  • Module Stomping 模块踩踏,通过加载一个合法的Dll模块,然后使用payload去覆盖dll
  • 优点:
    • 1) 有效载荷映射为 MEM_IMAGE,对于 EXE 或 DLL 来说看起来是合法的
    • 2)使用原始访问权限映射的部分(无RWX)
    • 3)冒充合法的Dll(进程模块界面无法检出)
  • 步骤:
    • 1)调用LoadLibrary函数加载合法dll,并得到基地址
    • 2)调用LoadLibrary函数或者NtMapViewOfSection获取非法dll,并得到基地址
    • 3)调用memset将合法dll的内存区域清空,并将非法dll内存复制到合法dll内存
    • 4) 根据pe信息,获取非法dll(覆盖后)的入口点
    • 5)根据入口点执行
  • https://github.com/Hagrid29/PELoader

0x02 Module Stomping(NtMapViewOfSection)

  • 通过NtMapViewOfSection函数为dll创建一个内存映射,然后使用payload覆盖dll
  • 优点:
    • 1) Module Stomping(LoadLibrary)全部
    • 2) 未连接到模块列表(对于Module32First/Module32Next 不可见)
  • 步骤:
    • 1) 调用NtMapViewOfSection函数加载合法dll,并得到基地址
    • 2)调用LoadLibrary函数或者NtMapViewOfSection获取非法dll,并得到基地址
    • 3)调用memset将合法dll的内存区域清空,并将非法dll内存复制到合法dll内存
    • 4) 根据pe信息,获取非法dll(覆盖后)的入口点
    • 5)根据入口点执行
  • https://github.com/Hagrid29/PELoader
  • https://github.com/hasherezade/module_overloading

0x03 GhostWriting

0x04 AtomBombing

  • AtomBombing通过利用APC异步过程调用以及windows原子表(atom tables)实现的高级代码注入
  • AtomBombing主要实施x个阶段的工作

    • 1) 寻找一个处于警告状态的线程,因为APC注入需要一个处于Alertable状态的线程
    • 2) 构造一个ROP链【重点】
    • 3) 通过APC结合windows atom表,代替WriteProcessMemory的功能
    • 4)通过SetThreadContext和ResumeThread执行ShellCode
  • Step1:将ShellCode写入远程进程

    • Tal Liberman发现GlobalAddAtomGlobalGetAtomName代替WriteProcessMemory将Shellcode写入目标进程,通过调用GlobalAddAtom将ShellCode保存在全局原子表中,目标进程可以通过GlobalGetAtomName读取该表中的Shellcode。
    • 现在问题就是如何使得目标进程调用GlobalGetAtomName,通过APC异步过程调用的方式,使远程进程主动调用GlobalGetAtomName获取ShellCode。
  • Step2:保存并执行ShellCode

    • 目标进程保存执行Shellcode主要有两种方法:
      • 1) 寻找一段具有RWX的内存,这个可以通过Hook一个导出函数实现
      • 2) 调用VirtualAllocEx分配一段内存
    • Tal Liberman创造性的使用ROP链执行ShellCode,主要分3步:
      • 1)申请RWX内存
      • 2)将从GlobalGetAtomName获取的Shellcode拷贝到RWX内存
      • 3)执行
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        49
        50
        51
        52
        53
        54
        55
        56
        57
        58
        59
        60
        61
        62
        63
        64
        65
        66
        67
        68
        69
        70
        71
        72
        //ROP链
        typedef struct _ROPCHAIN
        {
        // Return address of Memcpy
        PVOID pvMemcpy;
        //
        // Params for ntdll!ZwAllocateMemory
        HANDLE ZwAllocateMemoryhProcess;
        PVOID ZwAllocateMemoryBaseAddress;
        ULONG_PTR ZwAllocateMemoryZeroBits;
        PSIZE_T ZwAllocateMemoryRegionSize;
        ULONG ZwAllocateMemoryAllocationType;
        ULONG ZwAllocateMemoryProtect;
        //
        //ret这个指令
        PVOID pvRetGadget;
        //
        // Params for ntdll!memcpy
        PVOID MemcpyDestination;
        PVOID MemcpySource;
        SIZE_T MemcpyLength;
        } ROPCHAIN, *PROPCHAIN;
        //构建ROP链函数
        ESTATUS main_BuildROPChain(
        PVOID pvROPLocation,
        PVOID pvShellcodeLocation,
        PROPCHAIN ptRopChain
        )
        {
        ESTATUS eReturn = ESTATUS_INVALID;
        ROPCHAIN tRopChain = { 0 };
        // Params for ntdll!ZwAllocateMemory
        tRopChain.ZwAllocateMemoryhProcess = GetCurrentProcess();
        tRopChain.ZwAllocateMemoryBaseAddress = (PUCHAR)pvROPLocation + FIELD_OFFSET(
        ROPCHAIN,
        MemcpyDestination
        );
        tRopChain.ZwAllocateMemoryZeroBits = NULL;
        tRopChain.ZwAllocateMemoryRegionSize = (PSIZE_T)((PUCHAR)pvROPLocation + FIELD_OFFSET(
        ROPCHAIN,
        MemcpyLength)
        );
        tRopChain.ZwAllocateMemoryAllocationType = MEM_COMMIT;
        tRopChain.ZwAllocateMemoryProtect = PAGE_EXECUTE_READWRITE;
        // Params for ntdll!ZwAllocateMemory
        tRopChain.MemcpyDestination = (PVOID)0x00;
        tRopChain.MemcpySource = pvShellcodeLocation;
        tRopChain.MemcpyLength = sizeof(SHELLCODE);
        //address of ntdll!memcpy
        eReturn = GetFunctionAddressFromDll(
        NTDLL,
        MEMCPY,
        &tRopChain.pvMemcpy
        );
        if (ESTATUS_FAILED(eReturn))
        {
        goto lblCleanup;
        }
        printf("ntdll!memcpy: 0x%X", tRopChain.pvMemcpy);
        //寻找Ret指令的字节码
        eReturn = main_FindRetGadget(&tRopChain.pvRetGadget);
        if (ESTATUS_FAILED(eReturn))
        {
        goto lblCleanup;
        }
        eReturn = ESTATUS_SUCCESS;
        *ptRopChain = tRopChain;
        //
        lblCleanup:
        //
        return eReturn;
        }
  • Step3:执行ShellCode

    • AtomBombing技术是通过SetThreadContext将EIP设置为ZwAllocateVirtualMemory,然后将ESP设置为ROP链实现Shellcode执行的。方法非常巧妙,以下必须要结合ROP链结构体_ROPCHAIN阅读

      1
      2
      3
      4
      5
      6
      7
      //将线程的EIP设置为ZwAllocateVirtualMemory
      tContext.Eip = (DWORD) GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwAllocateVirtualMemory");
      tContext.Ebp = (DWORD)(PUCHAR)pvRemoteROPChainAddress;
      tContext.Esp = (DWORD)(PUCHAR)pvRemoteROPChainAddress;
      //首先执行ZwAllocateVirtualMemory,根据堆栈关系最终执行ShellCode
      printf("[*] Hijacking the remote thread to execute the shellcode (by executing the ROP chain).\n\n\n");
      eReturn = main_ApcSetThreadContext(hProcess, hAlertableThread, &tContext, pvRemoteContextAddress);
    • 1) 执行ZwAllocateVirtualMemory,根据上文的_ROPCHAIN结构体ROP链,此时栈顶保存的是memcpy的地址,接下来是ZwAllocateVirtualMemory的参数

    • 2)执行ZwAllocateVirtualMemory完成后,因为栈顶是memcpy地址,ret后,执行流指向memcpy。此时栈顶保存的是搜索到的ret这个指令的地址,然后是memcpy的参数
    • 3)执行完ret之后,根据栈的信息,执行流指向ShellCode,此时完成注入
  • AtomBombing – A Brand New Code Injection Technique for Windows

  • https://github.com/BreakingMalwareResearch/atom-bombing
  • AtomBombing利用分析

0x05 Process Hollowing

  • 1) CreateProcess(“svchost.exe”, …, CREATE_SUSPENDED, …);
  • 2) NtUnmapViewOfSection(…);
  • 3)VirtualAllocEx(…);
  • 4) For each section{WriteProcessMemory(…, EVIL_EXE, …);}
  • 5) Relocate Image*
  • 6) Set base address in PEB*/PE
  • 7) SetThreadContext(…);
  • 8) ResumeThread(…);

0x06 Process Doppelgänging

  • Process Doppelgänging其本质是利用TxF的回滚特性,将恶意载荷通过Section创建创建,并根据回滚特性恢复原样的一个技术,关注Process Doppelgänging技术细节之前,首先应该关注NtCreateProcessEx函数。该函数第6个参数是一个SectionHandle句柄。该句柄来自于transacted file

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    NTSTATUS
    NTAPI
    NtCreateProcessEx(OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
    IN HANDLE ParentProcess,
    IN ULONG Flags,
    IN HANDLE SectionHandle OPTIONAL,
    IN HANDLE DebugPort OPTIONAL,
    IN HANDLE ExceptionPort OPTIONAL,
    IN BOOLEAN InJob)
  • 原理流程,以下过程第一步在验证概念中没有显示

    • 1) 先用恶意程序写覆盖白程序
    • 2)然后将覆盖后的文件加载到内存
    • 3)加载完成后回滚磁盘上的文件为写覆盖之前的文件
    • 4)最后利用(2)加载到内存中的Section创建进程,最终达到执行恶意程序并绕过杀软检查的目的。
  • 实现过程

    • 1)调用NtCreateTransaction创建transaction

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      //The ZwCreateTransaction routine creates a transaction object.
      __kernel_entry NTSYSCALLAPI NTSTATUS NtCreateTransaction(
      [out] PHANDLE TransactionHandle,
      [in] ACCESS_MASK DesiredAccess,
      [in, optional] POBJECT_ATTRIBUTES ObjectAttributes,
      [in, optional] LPGUID Uow,
      [in, optional] HANDLE TmHandle,
      [in, optional] ULONG CreateOptions,
      [in, optional] ULONG IsolationLevel,
      [in, optional] ULONG IsolationFlags,
      [in, optional] PLARGE_INTEGER Timeout,
      [in, optional] PUNICODE_STRING Description
      );
    • 2) 调用CreateFileTransactedWriteFileNtCreateSection等在这个transaction内填入payload

    • 3)调用NtRollbackTransaction设置事务回滚

      1
      2
      3
      4
      5
      //The ZwRollbackTransaction routine initiates a rollback operation for a specified transaction.
      __kernel_entry NTSYSCALLAPI NTSTATUS NtRollbackTransaction(
      [in] HANDLE TransactionHandle,
      [in] BOOLEAN Wait
      );
    • 4) 调用NtCreateProcessExRtlCreateProcessParametersEx以内存Section创建进程。

    • 5)根据PEB读取入口点,调用NtCreateThreadEx执行入口点函数
  • 弱点:最终还是要依赖NtCreateThreadEx

  • 来自BlackHat新姿势:Process Doppelgänging攻击技术与贴身防护

  • Process-Doppelganging利用介绍
  • https://github.com/3gstudent/Inject-dll-by-Process-Doppelganging/blob/master/inject.c

0x07 Transacted Hollowing

  • Transacted Hollowing是一种集合了Process HollowingProcess Doppelgänging之间的混合体。
  • 1) 首先使用Process Doppelgänging中的NTFS函数得到一个Section
    • 1) CreateTransaction
    • 2) CreateFileTransactedW
    • 3) NtCreateSection
    • 4) RollbackTransaction
  • 2) 然后以挂起方式创建目标进程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    CreateProcessInternalW(hToken,
    NULL, //lpApplicationName
    (LPWSTR)cmdLine, //lpCommandLine
    NULL, //lpProcessAttributes
    NULL, //lpThreadAttributes
    FALSE, //bInheritHandles
    CREATE_SUSPENDED | DETACHED_PROCESS | CREATE_NO_WINDOW, //dwCreationFlags
    NULL, //lpEnvironment
    startDir, //lpCurrentDirectory
    &si, //lpStartupInfo
    &pi, //lpProcessInformation
    &hNewToken
    )
  • 3) 类似Process Hollowing,使用NtMapViewOfSection将Section映射入挂起的进程

  • 4)通过Wow64GetThreadContext/Wow64SetThreadContext设置入口点

  • https://github.com/hasherezade/transacted_hollowing/blob/main/main.cpp

  • https://www.freebuf.com/articles/system/181971.html

0x08 Process Ghosting

  • 现代Windows创建进程的基本流程是这样的:

    • 1)打开可执行文件,获取文件句柄hFile = CreateFile(“C:\Windows\System32\svchost.exe”)
    • 2) 为文件创建映像,即将文件部分内容映射入内存hSection = NtCreateSection(hFile, SEC_IMAGE)
    • 3) 使用映像部分创建一个进程,hProcess = NtCreateProcessEx(hSection)
    • 4) 为进程设置环境变量
    • 5)为进程创建一个主线程NtCreateThreadEx
  • Process Ghosting,顾名思义,进程是一个幽灵一般,没有实体部分。即没有文件。

  • windows中删除文件的方法(并不是实际上的Del)

    • 1)使用CreateFile/NtOpenFile创建文件的时候,将OpenOptions设置为FILE_DELETE_ON_CLOSE,FILE_SUPERSEDE,FILE_FLAG_DELETE_ON_CLOSE
    • 2) 当通过NtSetInformationFile调用FileDispositionInformation文件信息类时,将FILE_DISPOSITION_INFORMATION结构中的 DeleteFile 字段设置为 TRUE 。
  • 但是,只有当Section映射入进程,并关闭句柄,删除标志才能生效。

  • 攻击流程:

    • 1)创建一个文件
    • 2)使用NtSetInformationFile(FileDispositionInformation)将文件置于删除挂起状态。注意:尝试使用 FILE_DELETE_ON_CLOSE 不会删除文件。
    • 3)将负载可执行文件写入文件。内容不会保留,因为文件已处于删除挂起状态。删除挂起状态还会阻止外部文件打开尝试。
    • 4)为文件创建图像部分。
    • 5)关闭删除挂起句柄,删除文件。
    • 6)使用图像部分创建一个进程。
    • 7)分配流程参数和环境变量。
    • 8)创建一个线程在进程中执行。
  • Process Doppelgänging技术本质上都是将文件进行删除,Process Ghosting利用文件删除标志实现,而Process Doppelgänging技术是利用NTFS的回滚机制

  • https://github.com/hasherezade/process_ghosting

  • hat you need to know about Process Ghosting, a new executable image tampering attack

0x09 Ghostly Hollowing

0x10 Process Herpaderping

  • 背景:基于现有安全软件更高效的检测恶意软件,在程序运行期间提供了两层保护

    • 利用PsSetCreateProcessNotifyRoutinsEx回调函数,该回调函数在进程通过NtThreadEx创建主线程的时候被调用。该回调函数针对磁盘文件进行检测,但是在回调函数被调用之前,可以通过修改磁盘文件内容,从而规避这种检测。
    • 利用驱动程序在接收到IRP_MJ_CLEANUP(对应关闭文件句柄)时,检查文件内容是否发生改变。
  • 原理:综上描述,安全软件在进程创建主线程之后触发PsSetCreateProcessNotifyRoutinsEx回调函数进行检查,但是在之前对磁盘文件进行修改,修改为一个正常的文件,安全软件会认为进程是一个正常文件映射的,从而绕过检查。

  • 步骤:

    • 1)将二级制文件payload写入磁盘,并获取文件句柄
    • 2)将文件映射入内存
    • 3)使用映像部分创建一个进程,hProcess = NtCreateProcessEx(hSection)
    • 4)使用1)中的文件句柄,修改文件,此时为正常文件。此时安全软件的文件检查得以绕过
    • 5)创建进程的主线程

0x11 Herpaderply Hollowing

  • Herpaderply Hollowing是Process HollowingProcess Herpaderping的混合体。
    mark

  • 步骤:

    • 1)将二级制文件payload写入磁盘,并获取文件句柄
    • 2)将文件映射入内存
    • 3)使用映像部分创建一个进程,hProcess = NtCreateProcessEx(hSection)
    • 4)使用1)中的文件句柄,修改文件,此时为正常文件。此时安全软件的文件检查得以绕过
    • 5)以挂起方式创建进程
    • 6)将Section映射入挂起的进程
    • 7)运行payload
  • https://github.com/Hagrid29/herpaderply_hollowing

0x12 Process Lockering

  • 步骤:
    • 1)读取payload
    • 2)将payload写入一个另外一个空文件,用于Lock。
    • 3)通过DuplicateHandle复制一个文件句柄,并返回新文件的句柄,此时文件处于锁定状态
    • 4)通过3)中获取的文件句柄,创建一个新的section
    • 5)通过NtCreateProcessEx(HSection)创建进程
    • 6)通过PEB寻找入口点,执行payload

0x13 Locker Hollowing

参考文献