• 驱动中获取PsActiveProcessHead变量地址的五种方法也可以获取KdpDebuggerDataListHead


    PsActiveProcessHead的定义:

    在windows系统中,所有的活动进程都是连在一起的,构成一个双链表,表头是全局变量PsActiveProcessHead,当一个进程被创建时,其ActiveProcessList域将被作为节点加入到此链表中;当进程被删除时,则从此链表中移除,如果windows需要枚举所有的进程,直接操纵此链表即可。



    方法一:从KdInitSystem函数地址处硬编码搜索
    方法二:从System进程(pid=4)的PEPROCESS地址获取
    方法三:从ntoskrnl.exe的导出变量PsInitialSystemProcess中获取
    方法四:从KPCR中获取
    方法五:调用NtSystemDebugControl函数获取

    注:操作系统 Windows XP SP3

    方法一:
    系统内核变量KdDebuggerDataBlock是一个KDDEBUGGER_DATA64类型的结构体,结构成员PsActiveProcessHead正是我们所找的地址。可在WinDDK的incapiWDBGEXTS.H文件中查看到此结构的定义。

    KdInitSystem函数中引用了KdDebuggerDataBlock,而ntoskrnl.exe的导出函数KdEnableDebugger调用了KdInitSystem函数。
    名称:  方法1找KdInitSystem.jpg查看次数: 61文件大小:  134.7 KB
    名称:  方法1找到KdDebuggerDataBlock.jpg查看次数: 61文件大小:  85.3 KB

    代码:
    ULONG FindPsActiveProcessHead1()
    {
      //1.从KdEnableDebugger地址找到KdInitSystem地址
      //nt!KdEnableDebugger   804f7810
      
      //804f7837 6a00            push    0
      //804f7839 6a00            push    0
      //804f783b c605ecab558001  mov     byte ptr [nt!PoHiberInProgress (8055abec)],1
      //804f7842 e8f7951600      call    nt!KdInitSystem (80660e3e)
      //804f7847 e8649a1600      call    nt!KdpRestoreAllBreakpoints (806612b0)
    
      ULONG i;
      PCALL_CODE pCall;
      PUCHAR pKdInitSystem=NULL;
      PUCHAR p=(PUCHAR)GetExportFuncAddress(L"KdEnableDebugger");
      KdPrint(("KdEnableDebugger地址=%x
    ",p));
      if (!p)
      {
        KdPrint(("获取KdEnableDebugger地址失败
    "));
        return 0;
      }
    
      for (i=0;i<100;i++,p++)
      {
        if ((*p==0x6a)&&
          (*(p+1)==0x00)&&
          (*(p+2)==0x6a)&&
          (*(p+3)==0x00)&&
          (*(p+4)==0xc6)&&
          (*(p+5)==0x05)&&
          (*(p+0xb)==0xe8)&&
          (*(p+0x10)==0xe8)  )
        {
          pCall=(PCALL_CODE)(p+0xb);
          pKdInitSystem=p+0xb+pCall->address+5;
          KdPrint(("KdInitSystem地址=%x
    ",pKdInitSystem));
          break;
        }
      }
      
      if (!pKdInitSystem)
      {
        KdPrint(("获取KdInitSystem地址失败
    "));
        return 0;
      }
    
      //2.从KdInitSystem地址找到KdDebuggerDataBlock地址
      //nt!KdInitSystem 80660e3e
    
      //80660e8e 6890020000      push    290h
      //80660e93 68606b5480      push    offset nt!KdDebuggerDataBlock (80546b60)
      //80660e98 be74926780      mov     esi,offset nt!KdpDebuggerDataListHead (80679274)
    
      p=pKdInitSystem;
      for (i=0;i<100;i++,p++)
      {
        if ((*p==0x68)&&
          (*(p+5)==0x68)&&
          (*(p+0xA)==0xbe))
        {
          pCall=(PCALL_CODE)(p+5);
          KdPrint(("KdDebuggerDataBlock地址=%x
    ",pCall->address));
          KdPrint(("PsActiveProcessHead地址=%x
    ",((PKDDEBUGGER_DATA64)pCall->address)->PsActiveProcessHead));
          return ((PKDDEBUGGER_DATA64)pCall->address)->PsActiveProcessHead;
        }
      }
      KdPrint(("获取KdDebuggerDataBlock地址失败
    "));
      return 0;
    }
    
    方法二:PsActiveProcessHead是活动进程链表头,理论上是第二个进程的EPROCESS结构成员ActiveProcessLinks的Blink,最后一个进程的EPROCESS结构成员ActiveProcessLinks的Flink。第二个进程即System进程,进程ID等于4。

    代码:
    NTSTATUS FindPsActiveProcessHead(ULONG *pPsActiveProcessHead)
    {
      PEPROCESS process;
      PLIST_ENTRY pList=NULL;
      NTSTATUS status=PsLookupProcessByProcessId((HANDLE)4,&process);
      if (!NT_SUCCESS(status))
      {
        KdPrint(("获取process失败
    "));
        return status;
      }
      //xp _EPROCESS +0x088 ActiveProcessLinks : _LIST_ENTRY
      pList=(PLIST_ENTRY)((PUCHAR)process+0x88);
      KdPrint(("PsActiveProcessHead地址=%x
    ",pList->Blink));
      *pPsActiveProcessHead=(ULONG)pList->Blink;
      ObDereferenceObject(process);
      return status;
    }
    
    方法三:ntoskrnl.exe导出了一个类型为PEPROCESS结构的变量PsInitialSystemProcess,它指向system进程(PID=4)的EPROCESS。这个方法与上一个方法类似。使用PsInitialSystemProcess在WinDDK中编译的话有链接ntoskrnl.lib。
    名称:  PsInitialSystemProcess.jpg查看次数: 60文件大小:  161.8 KB

    代码:
    ULONG FindPsActiveProcessHead3()
    {
      ULONG addr=*(PULONG)PsInitialSystemProcess;
      //xp _EPROCESS +0x088 ActiveProcessLinks : _LIST_ENTRY
      PLIST_ENTRY pList=(PLIST_ENTRY)(addr+0x88);
      KdPrint(("PsActiveProcessHead地址=%x
    ",pList->Blink));
      return (ULONG)pList->Blink;
    }
    
    方法四:每个CPU都有个KPCR结构,第一个KPCR结构的地址是固定的0xffdff000。KPCR结构偏移0x034位置的结构成员KdVersionBlock是一个DBGKD_GET_VERSION64类型的指针。此结构同样在WDBGEXTS.H中有定义。DBGKD_GET_VERSION64结构成员DebuggerDataList其实是KdpDebuggerDataListHead。而KdpDebuggerDataListHead.Flink=KdpDebuggerDataListHead.Blink=KdDebuggerDataBlock。
    名称:  KPCR1.jpg查看次数: 41文件大小:  198.5 KB
    名称:  KPCR2.jpg查看次数: 40文件大小:  139.1 KB
    名称:  KPCR3.jpg查看次数: 40文件大小:  125.6 KB

    代码:
    ULONG FindPsActiveProcessHead4()
    {
      PLIST_ENTRY pList;
      PKDDEBUGGER_DATA64 pKdDebuggerData;
      PDBGKD_GET_VERSION64 pKdVersionBlock=(PDBGKD_GET_VERSION64)(*(PULONG)(0xffdff000+0x34));
      KdPrint(("获取到DebuggerDataList地址=%x
    ",pKdVersionBlock->DebuggerDataList));
      pList=(PLIST_ENTRY)pKdVersionBlock->DebuggerDataList;
      KdPrint(("pList->Flink=%x,pList->Blink地址=%x
    ",pList->Flink,pList->Blink));
      pKdDebuggerData=(PKDDEBUGGER_DATA64)pList->Flink;
      KdPrint(("PsActiveProcessHead地址=%x
    ",pKdDebuggerData->PsActiveProcessHead));
      return pKdDebuggerData->PsActiveProcessHead;
    }
    
    方法五:调用SSDT表中的NtSystemDebugControl函数。


    代码:
    ULONG FindPsActiveProcessHead5()
    {
      PLIST_ENTRY pList;
      DBGKD_GET_VERSION64 KdVersionBlock;
      PKDDEBUGGER_DATA64 pKdDebuggerData;
      ZwSystemDebugControl NtSystemDebugControl;
      
      NtSystemDebugControl=(ZwSystemDebugControl)GetSSDTAddrFromIndex(255);
      KdPrint(("NtSystemDebugControl函数地址=%x
    ",NtSystemDebugControl));
      
      NtSystemDebugControl(SysDbgSysGetVersion,NULL,0,&KdVersionBlock,sizeof(DBGKD_GET_VERSION64),NULL);
      KdPrint(("DebuggerDataList=%x
    ",KdVersionBlock.DebuggerDataList));
      
      pList=(PLIST_ENTRY)KdVersionBlock.DebuggerDataList;
      KdPrint(("获取到KdDebuggerDataBlock地址=%x
    ",pList->Flink));
    
      pKdDebuggerData=(PKDDEBUGGER_DATA64)pList->Flink;
      KdPrint(("PsActiveProcessHead地址=%x
    ",pKdDebuggerData->PsActiveProcessHead));
    
      return pKdDebuggerData->PsActiveProcessHead;
    }
    
    jpg 改 rar
  • 相关阅读:
    Chino 操作系统开发日志 (1)
    将Asp.Net Core和corefx移植到.Net 4.0
    C++编写操作系统(1):基于 EFI 的 Bootloader
    第二次作业:支付宝手机软件分析
    第一次作业:以人为鉴 可以明得失
    个人附加作业
    个人作业3---个人总结
    结对编程2---单元测试
    个人作业2---必应词典案例分析
    结对编程作业1
  • 原文地址:https://www.cnblogs.com/kuangke/p/5597020.html
Copyright © 2020-2023  润新知