免杀断链

admin 2024年4月14日01:41:21评论6 views字数 8191阅读27分18秒阅读模式

想第一时间看到我们的大图推送吗?赶紧把我们设为星标吧!这样您就不会错过任何精彩内容啦!感谢您的支持!🌟

免责声明

      文章所涉及内容,仅供安全研究教学使用,由于传播、利用本文所提供的信息而造成的任何直接或间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任。

前言

在这篇文章中我们介绍PEB断链(R3层和R0层)
R3层隐藏模块

首先我们介绍一下PEB断链,相信各位读者大大对PEB这个结构体可以说相当熟悉了,这里我们简单描述一下,做一个介绍

在开始使用TEB/PEB 获取进程的模块信息之前,我想有必要解释一下这两个名词:PEB 指的是进程环境块(Process Environment Block),用于存储进程状态信息和进程所需的各种数据。每个进程都有一个对应的 PEB 结构体。TEB 指的是线程环境块(Thread Environment Block),用于存储线程状态信息和线程所需的各种数据。每个线程同样都有一个对应的 TEB 结构体。

PEB 中包含了进程的代码、数据段指针、进程的环境变量、进程启动参数信息以及加载的模块信息等。在 x86-32 体系下,FS 段寄存器偏移 0x30 处存放了索引,索引查找的指针指向当前进程的 PEB 结构体,在 x86-64 下该指针位于 FS 段寄存器偏移 0x60 处。其他进程可以通过访问自己的  PEB 结构体来获取自己的状态和信息。

TEB 中包含了线程的堆栈指针、TLS(线程本地存储)指针、异常处理链表指针、用户模式分页表指针等信息。在 x86-32体系下,FS 段寄存器偏移 0x18 处通常为指向 TEB 结构体的指针,在 x86-64 下该指针位于 FS 段寄存器偏移 0x30 处。其他线程可以通过访问自己的 TEB 结构体来获取自己的状态和信息。

而对于 PEB 结构体,微软是没有公开文档的,需要自己进行重定义(原始结构体定义中缺少我们需要的部分),经查阅逆向文献,得到如下的结构体定义(部分不需要用到的成员已经被截断):

typedef struct _PEB_LDR_DATA32

{

    ULONG Length; // +0x00

    BOOLEAN Initialized; // +0x04

    PVOID SsHandle; // +0x08

    LIST_ENTRY InLoadOrderModuleList; // +0x0c

    LIST_ENTRY InMemoryOrderModuleList; // +0x14

    LIST_ENTRY InInitializationOrderModuleList;// +0x1c

} PEB_LDR_DATA32, * PPEB_LDR_DATA32; // +0x24

typedef struct _PEB32

{

    UCHAR InheritedAddressSpace;                                            //0x0

    UCHAR ReadImageFileExecOptions;                                         //0x1

    UCHAR BeingDebugged;                                                    //0x2

    union

    {

        UCHAR BitField;                                                     //0x3

        struct

        {

            UCHAR ImageUsesLargePages : 1;                                    //0x3

            UCHAR IsProtectedProcess : 1;                                     //0x3

            UCHAR IsImageDynamicallyRelocated : 1;                            //0x3

            UCHAR SkipPatchingUser32Forwarders : 1;                           //0x3

            UCHAR IsPackagedProcess : 1;                                      //0x3

            UCHAR IsAppContainer : 1;                                         //0x3

            UCHAR IsProtectedProcessLight : 1;                                //0x3

            UCHAR IsLongPathAwareProcess : 1;                                 //0x3

        };

    };

    PVOID Mutant;                                                           //0x4

    PVOID ImageBaseAddress;                                                 //0x8

    PEB_LDR_DATA32* Ldr;                                              //0xc

    RTL_USER_PROCESS_PARAMETERS* ProcessParameters;                 //0x10

    PVOID SubSystemData;                                                    //0x14

    PVOID ProcessHeap;                                                      //0x18

    RTL_CRITICAL_SECTION* FastPebLock;                              //0x1c

    SLIST_HEADER* volatile AtlThunkSListPtr;                         //0x20

    PVOID IFEOKey;                                                          //0x24

} PEB32, * PPEB32;

typedef struct _STRING64

{

    USHORT Length;                                                          //0x0

    USHORT MaximumLength;                                                   //0x2

    ULONGLONG Buffer;                                                       //0x8

}STRING64, * LPSTRING64;

typedef struct _PEB_LDR_DATA64

{

    ULONG Length;                                                           //0x0

    UCHAR Initialized;                                                      //0x4

    PVOID SsHandle;                                                         //0x8

    LIST_ENTRY InLoadOrderModuleList;                               //0x10

    LIST_ENTRY InMemoryOrderModuleList;                             //0x20

    LIST_ENTRY InInitializationOrderModuleList;                     //0x30

    PVOID EntryInProgress;                                                  //0x40

    UCHAR ShutdownInProgress;                                               //0x48

    PVOID ShutdownThreadId;                                                 //0x50

}PEB_LDR_DATA64, *PPEB_LDR_DATA64;

typedef struct _PEB64

{

    UCHAR InheritedAddressSpace;                                            //0x0

    UCHAR ReadImageFileExecOptions;                                         //0x1

    UCHAR BeingDebugged;                                                    //0x2

    union

    {

        UCHAR BitField;                                                     //0x3

        struct

        {

            UCHAR ImageUsesLargePages : 1;                                    //0x3

            UCHAR IsProtectedProcess : 1;                                     //0x3

            UCHAR IsImageDynamicallyRelocated : 1;                            //0x3

            UCHAR SkipPatchingUser32Forwarders : 1;                           //0x3

            UCHAR IsPackagedProcess : 1;                                      //0x3

            UCHAR IsAppContainer : 1;                                         //0x3

            UCHAR IsProtectedProcessLight : 1;                                //0x3

            UCHAR IsLongPathAwareProcess : 1;                                 //0x3

        };

    };

    UCHAR Padding0[4];                                                      //0x4

    ULONGLONG Mutant;                                                       //0x8

    ULONGLONG ImageBaseAddress;                                             //0x10

    PEB_LDR_DATA64* Ldr;                                                          //0x18

    ULONGLONG ProcessParameters;                                            //0x20

    ULONGLONG SubSystemData;                                                //0x28

    ULONGLONG ProcessHeap;                                                  //0x30

    ULONGLONG FastPebLock;                                                  //0x38

    ULONGLONG AtlThunkSListPtr;                                             //0x40

    ULONGLONG IFEOKey;                                                      //0x48

}PEB64, *PPEB64;

PEB_LDR_DATA结构体
以 x86-32 为例:PEB 结构体中偏移为 0xC 的成员变量是 Ldr 该变量是一个指向 PEB_LDR_DATA 结构体的指针。
该结构体的第一个变量 Length 表示链表长度信息,大小是结点数乘以当前范围的大小(x32 是0x4,x64 是 0x8),最后再减去 1。
然后从偏移 0xC 开始,就是三个 LIST_ENTRY 链表的头结点,链表中结点数据类型都是 LIST_ENTRY,只是链表的排序模式不同。
LIST_ENTRY结构体
LIST_ENTRY 结构是模块链表结构里的结点数据结构,它包含两个成员指针, Flink 指向下一个链表结点,Blink 指向前一个链表结点。模块链表属于一种双向链表的数据结构
LDR_DATA_TABLE_ENTRY结构体
对于每一个指针,它实际指向的数据结构并不是 LIST_ENTRY 结构体,而是 LDR_DATA_TABLE_ENTRY结构体,这是每一个结点指向的模块信息数据结构。
对于该结构中的 DllBase 是当前模块的基址,EntryPoint 是模块的入口地址,SizeOfImage 是映像大小,FullDllName 是模块完整路径字符串。
可以通过遍历链表结点的方式获取所有模块的信息:LDR_DATA_TABLE_ENTRY 结构中的 LIST_ENTRY 结构对应下一个 LDR_DATA_TABLE_ENTRY 结点中的 LIST_ENTRY 结构。
这些信息引用于其他大佬的文章下面是原文链接,这里只复制了我们需要的信息,想要了解的更全面,就可以阅读那篇文章
原文链接:https://blog.csdn.net/qq_59075481/article/details/135281393
这里我们了解到每一个结构体都有两个指针,分别指向其前后的结构体,并且每个结构体都带有该模块的信息,所以我们通过获取到需要的信息再进行判读,如果满足条件,就执行模块隐藏操作(让其前后指针都指向自己)。

实现的效果:

免杀断链

这里我们可以看到已经隐藏成功。

这是效果图

免杀断链

R0层隐藏进程

注:基于R0层进行隐藏进程,需要使用驱动,但是有个问题就是加载驱动需要带有有效签名,如果没有签名windows是不会将驱动加载起来的。

获取进程模块的步骤为:获取 _KPCR -> _KPRCB -> KTHREAD -> _KAPC_STATE -> _KPROCESS -> _EPROCESS

(1)KPCR 的获取方法为:fs:[0]

(2)KPCR 结构体中偏移0x120处有一个成员 _KPRCB 结构体,该结构体中偏移0x4处(即 fs:[0x124])有一个 CurrentThread 指针,指向 _KTHREAD 结构体

(3)_KTHREAD 结构体偏移0x34处有一个 ApcState 结构体,该结构体偏移0x10处有一个 Process 指针,指向 _KPROCESS

(4)_EPROCESS 结构体的第一个成员是 Pcb,是一个 _KPROCESS 结构体

(5)(3)中的 Process 指针指向的就是 _EPROCESS 中的一个成员 _KPROCESS 结构体,也是 _EPROCESS 结构体的首地址。这一点和PEB断链中,

ldr->Flink 与 _LDR_DATA_TABLE_ENTRY 首地址相等是一样的

(6)_EPROCESS 结构体中偏移0x88有一个 _LIST_ENTRY 结构体,该结构体保存了当前进程在进程链表中的位置信息

(7)节点指针指向的是 _LIST_ENTRY 结构体,该结构体存储了模块在链表中的位置信息

(8)通过 _EPROCESS 结构体中偏移0x174的 ImageFileName 确定所属进程, 并通过该结构体中的 _LIST_ENTRY结构体删除该节点在链表中的位置信息(双向循环链表删除节点),即可达到0环下的进程隐藏。

PPID Spoofing

PPID spoofing是一种攻击技术,用于欺骗系统和安全工具,使其认为恶意进程的父进程ID(PPID)是合法的。通过伪装父进程ID,攻击者可以隐藏恶意进程的真实来源,绕过安全监控和检测。这种技术可能被用于实施恶意活动,如隐藏恶意进程、绕过安全防护、进行横向移动等。在安全领域中,需要采取相应的防御措施来防范PPID spoofing攻击。

PPID Spoofing 原理概述

PPID Spoofing 是通过在 STARTUPINFOEXW 结构体中的 PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList 成员中,使用 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 来告诉最终调用调用的 CreateProcess 函数,将即将创建的进程,归入到指定的父进程之下。

PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList 成员是通过 InitializeProcThreadAttributeList分配内存,并由 UpdateProcThreadAttribute 函数设置其属性(设置成 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS),来达到偷换父进程的目的。

PPID Spoofing 原理概述

PPID Spoofing 是通过在 STARTUPINFOEXW 结构体中的 PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList 成员中,使用 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS 来告诉最终调用调用的 CreateProcess 函数,将即将创建的进程,归入到指定的父进程之下。

PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList 成员是通过 InitializeProcThreadAttributeList分配内存,并由 UpdateProcThreadAttribute 函数设置其属性(设置成 PROC_THREAD_ATTRIBUTE_PARENT_PROCESS),来达到偷换父进程的目的。

InitializeProcThreadAttributeList 函数

初始化用于创建进程和线程的指定属性列表。

BOOL InitializeProcThreadAttributeList(   [out, optional] LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,   [in]            DWORD                        dwAttributeCount,                   DWORD                        dwFlags,   [in, out]       PSIZE_T                      lpSize );

[out, optional] lpAttributeList

属性列表。此参数可以为 NULL,以确定支持指定数量的属性所需的缓冲区大小。

[in] dwAttributeCount

要添加到列表的属性计数。//这里我们只需要一个就行了,那就是PROC_THREAD_ATTRIBUTE_PARENT_PROCESS属性,用于创建指定的父进程。

dwFlags

此参数是保留的,必须为零。

[in, out] lpSize

如果 lpAttributeList 不为 NULL,则此参数指定输入时 lpAttributeList 缓冲区的大小(以字节为单位)。输出时,此参数接收初始化的属性列表的大小(以字节为单位)。

如果 lpAttributeList 为 NULL,则此参数接收所需的缓冲区大小(以字节为单位)。

UpdateProcThreadAttribute函数

BOOL UpdateProcThreadAttribute(   [in, out]       LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,   [in]            DWORD                        dwFlags,   [in]            DWORD_PTR                    Attribute,   [in]            PVOID                        lpValue,   [in]           SIZE_T                      cbSize,   [out, optional] PVOID                       lpPreviousValue,   [in, optional]  PSIZE_T                      lpReturnSize );

这里我们主要注意第三个参数,给定一个属性,这里有很多我们只使用其中的一个。

PROC_THREAD_ATTRIBUTE_PARENT_PROCESS:

lpValue

参数是指向要使用的进程的句柄的指针,而不是作为所创建进程的父进程的调用进程。要使用的进程必须具有

PROCESS_CREATE_PROCESS

访问权限。

从指定进程继承的属性包括句柄、设备映射、处理器相关性、优先级、配额、进程令牌和作业对象。(请注意,某些属性(如调试端口)将来自创建进程,而不是此 handle 指定的进程。)

那么思路明确,我们先声明结构体,然后对结构体第二个值进行大小以及属性的初始化。

接下来上代码:

免杀断链

下面是使用的方法和效果。

免杀断链

免杀断链

免杀断链

那么这里我就实验成功了,多研究研究就行。

原文始发于微信公众号(泾弦安全):免杀断链

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年4月14日01:41:21
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   免杀断链https://cn-sec.com/archives/2655206.html

发表评论

匿名网友 填写信息