作者:wzt
原文鏈接:https://mp.weixin.qq.com/s/08KHfzVltDu3rwZefJ98-Q

NT內核在創建進程時,會將自身插入到nt!PsActiveProcessHead鏈表中,它保存的是當前系統中活躍的進程鏈表。

NTSTATUS

PspCreateProcess(

    OUT PHANDLE ProcessHandle,

    IN ACCESS_MASK DesiredAccess,

    IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

    IN HANDLE ParentProcess OPTIONAL,

    IN ULONG Flags,

    IN HANDLE SectionHandle OPTIONAL,

    IN HANDLE DebugPort OPTIONAL,

    IN HANDLE ExceptionPort OPTIONAL,

    IN ULONG JobMemberLevel

)

{

    PspLockProcessList (CurrentThread);

    InsertTailList (&PsActiveProcessHead, &Process->ActiveProcessLinks);

  PspUnlockProcessList (CurrentThread);

}

在kd查看下相關的數據結構信息:

0: kd> dt nt!_eprocess

    +0x2e8 UniqueProcessId  : Ptr64 Void

    +0x2f0 ActiveProcessLinks : _LIST_ENTRY

Win32 api就是通過調用nt!NtQueryInformationProcess函數獲取系統的進程列表,所以隱藏進程的一個思路就是將目標進程從nt!PsActiveProcessHead鏈表中摘除。

首先看下,如何編寫kd腳本,來輸出全部的進程列表:

r $t1=$proc;

r @$t2=@$t1;

.while (@$t1 != poi(@$t2+0x2f0)-0x2f0)

{

                .printf "%ma\n", @$t2+0x450;

                r @$t2=poi(@$t2+0x2f0)-0x2f0

}

PsActiveProcessHead是一個雙向循環列表,因此只要知道一個節點的地址,就能循環遍歷處所有的節點。

$proc 在kd環境中保存的是當前進程的eprocess地址。

Poi(@$t2+0x2f) 為Process->ActiveProcessLinks地址,poi函數用于取地址中的值,類似于c的取指針值操作。Poi(@$t2+0x2f)得到的就是當前節點的下一個節點地址。

那么刪除雙向鏈表中的節點,就可以使用如下腳本:

$$ 準備遍歷PsActiveProcessHead鏈表

r @$t1=nt!PsActiveProcessHead;

r @$t2=poi($t1);



.while (@$t2 != @$t1)

{

    $$ 判斷是否是需要隱藏的進程號

        .if (poi(@$t2-0x8) == 0n532)

                 {

                        .printf "start hide process %ma(%d)\n", @$t2-0x2f0+0x450,poi(@$t2-0x8) ;

      $$ 刪除鏈表節點


                          eq poi(@$t2)+0x8 poi(@$t2+0x8)

                          eq poi(@$t2+0x8) poi(@$t2)

                          .break

                  }

    $$ 獲取下一節點


                  r @$t2=poi(@$t2)

}

Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1611/