ACPI调试
Linux内核调试
Windows内核调试
 
  调试战役
调试原理
新工具观察
 
  Linux
Windows Vista
Windows
 
  Linux驱动
WDF
WDM
 
  PCI Express
PCI/PCI-X
USB
无线通信协议
 
  64位CPU
ARM
IA-32
  CPU Info Center
 
  ACPI标准
系统认证
Desktop
服务器
 
  Embedded Linux
嵌入式开发工具
VxWorks
WinCE
嵌入式Windows
沪ICP备05041459号
About AdvDbg Consult Train Services Products Tools Community Contact   登录 | 注册

fs:[00000000h]

    聊到DKOM却不聊进程相关的东西显然是说不过去的。

    长久以来一直在拿来主义“万王之王”Russinovich的函数 —— GetProcessNameOffset()、GetProcess()等等,要是不知道这些东西的原理:
        804e564f 64a124010000    mov     eax,dword ptr fs:[00000124h]
        804e5655 8b4044          mov     eax,dword ptr [eax+44h]
        804e5658 c3              ret
岂不遗憾?

    还有,现在越来越不喜欢《Rootkits - Subverting the Windows Kernel》这本书了。明明可以多讲个三两句话,把问题说的清楚些,可他就不。
    在DKOM一章的“驱动隐藏”里,您不会了解什么是“nt!_LDR_DATA_TABLE_ENTRY”,因为他只让你学习鸡肋数据结构“_MODULE_ENTRY”;关于DKOM进程,您也永远不会了解“0xFFDFF120 和 fs:[00000000h]”之间的关系 —— 取而代之的仅仅是5、6句无关痛痒的解释 —— 而这样的解释无法让你在 Windbg 上跟踪、实践。其实,我最受不了的是书的封面 —— 看着好像挺有个性 —— 那么听听作者的解释吧:“The kanji characters behind him mean "to gain knowledge." ”,我这就诧异了,这是日本字吗?这分明是我华夏5000年文明的结晶!膏药旗国度的人哪有什么光彩的历史?

    作为一个南京人我且先不谈中日感情,今天想聊的还是技术。

    问题是从这个内核函数开始的:nt!PsGetCurrentProcess。它是函数GetProcessNameOffset()、GetProcess()等的基石。

    [3790.1830] ntddk.h 在124行教导我们: "#define PsGetCurrentProcess()  IoGetCurrentProcess()" 验证一下:

kd> u nt!PsGetCurrentProcess
nt!PsGetCurrentProcess:
804e564f 64a124010000    mov     eax,dword ptr fs:[00000124h]
804e5655 8b4044          mov     eax,dword ptr [eax+44h]
804e5658 c3              ret
804e5659 90              nop
804e565a 90              nop

kd> u nt!IoGetCurrentProcess
nt!PsGetCurrentProcess:
804e564f 64a124010000    mov     eax,dword ptr fs:[00000124h]
804e5655 8b4044          mov     eax,dword ptr [eax+44h]
804e5658 c3              ret
804e5659 90              nop
804e565a 90              nop

    别名,看样子是没错了。可是这三句话为什么可以 "Get 到 CurrentProcess" 呢? 从字面上来看: (1) "64a124010000" 是取了一个关键地址偏移量的值(地址)到EAX寄存器; (2) "8b4044"是在刚才得出的新地址基础上再累加偏移、取值(地址);(3) "C3"最后返回那个地址 —— 即CurrentProcess的地址。

    如果您是“all the people in the world who never stopped asking Why”其中一员的话,您一定不会满足我的回答,您会追问“为什么它可以”?

    很好!Hoglund 的《Rootkits - Subverting the Windows Kernel》是这样解答我们的:
  "Why does this code work? Windows has what it calls the Kernel's Processor Control Block (KPRCB), which is unique and is located at 0xffdff120 in kernel space. The Assembly code for IoGetCurrentProcess goes to the offset 0x124 from the fs register. This is the pointer to the current ETHREAD."

    不明不白的四句话,然后你就只能开始猜测了 —— KPRCB 位于 0xFFDFF120,可这和 FS : 00000124有什么关系?  FS : 00000124 明显是一个偏移,那么 FS : 00000000 指向什么结构? 难道 FS : 00000000 指向了 KPRCB 的基址吗? 没办法只有再次验证,可 Windbg 的输出却让人更加疑惑 —— 上述假设都是假命题。 然后你会抱怨:KAO,这就叫 "Why does this code work?"?!


    好在Schreiber一直没有吝惜自己的研究成果 —— 在《Undocumented Windows 2000 Secrets - The Programmers Cookbook》中,我找到了这样的话语:
  "I have already mentioned that the FS refers to different segments in user- and kernel- mode."
  .........

  "Both Windows NT 4.0 and Windows 2000 set up FS to point to the linear address OXFFDFFOOO in kernel-mode."

    从这句话我们可以萃取出这样的知识点: FS:00000000h 在内核态是指向线性地址0xFFDFF000的(本文不打算讨论用户态),这一点在Win-XP下也一样。

    接下来:
  "The kernel-mode FS points to another thread-specific structure frequently accessed by the Windows 2000 kernel, named the Kernel's Processor Control Region(KPCR)."

    多有价值的解释啊! 醍醐灌顶一般。 现在手头的信息已经可以供实践验证了:


kd> dt  nt!_KPCR 0xFFDFF000
   +0x000 NtTib            : _NT_TIB
   +0x01c SelfPcr          : 0xffdff000 _KPCR
   +0x020 Prcb             : 0xffdff120 _KPRCB
   +0x024 Irql             : 0 ''
   +0x028 IRR              : 0
   +0x02c IrrActive        : 0
   +0x030 IDR              : 0xffffffff
   +0x034 KdVersionBlock   : 0x8054d238
   +0x038 IDT              : 0x8003f400 _KIDTENTRY
   +0x03c GDT              : 0x8003f000 _KGDTENTRY
   +0x040 TSS              : 0x80042000 _KTSS
   +0x044 MajorVersion     : 1
   +0x046 MinorVersion     : 1
   +0x048 SetMember        : 1
   +0x04c StallScaleFactor : 0x7d1
   +0x050 DebugActive      : 0 ''
   +0x051 Number           : 0 ''
   +0x052 Spare0           : 0 ''
   +0x053 SecondLevelCacheAssociativity : 0x8 ''
   +0x054 VdmAlert         : 0
   +0x058 KernelReserved   : [14] 0
   +0x090 SecondLevelCacheSize : 0x80000
   +0x094 HalReserved      : [16] 0
   +0x0d4 InterruptMode    : 0
   +0x0d8 Spare1           : 0 ''
   +0x0dc KernelReserved2  : [17] 0
   +0x120 PrcbData         : _KPRCB


再对比的看一下:
kd> !strct  KPCR 0xFFDFF000
struct   _KPCR (sizeof=2832)
+000 struct   _NT_TIB NtTib
+000    struct   _EXCEPTION_REGISTRATION_RECORD *ExceptionList = F1CF3AF8
+004    void     *StackBase =                    F1CF3DF0
+008    void     *StackLimit =                   F1CF1000
+00c    void     *SubSystemTib =                 00000000
+010    void     *FiberData =                    00000000
+010    uint32   Version =                       00000000
+014    void     *ArbitraryUserPointer =         00000000
+018    struct   _NT_TIB *Self =                 7FFDF000
+01c struct   _KPCR *SelfPcr =                   FFDFF000
+020 struct   _KPRCB *Prcb =                     FFDFF120
+024 byte     Irql =                             00              .
+028 uint32   IRR =                              00000000
+02c uint32   IrrActive =                        00000000
+030 uint32   IDR =                              ffffffff
+034 uint32   Reserved2 =                        8054d238
+038 struct   _KIDTENTRY *IDT =                  8003F400
+03c struct   _KGDTENTRY *GDT =                  8003F000
+040 struct   _KTSS *TSS =                       80042000
+044 uint16   MajorVersion =                     0001
+046 uint16   MinorVersion =                     0001
+048 uint32   SetMember =                        00000001
+04c uint32   StallScaleFactor =                 000007d1
+050 byte     DebugActive =                      00      
..........................    


    _KPCR 的 "+020" 偏移处就是指向 _KPRCB 结构的指针 "Prcb" 目标地址是 0xFFDFF120 —— 这里才是 Greg Hoglund 在解释的东西。 继续往下分析:


kd> dt  nt!_KPRCB 0xFFDFF120
   +0x000 MinorVersion     : 1
   +0x002 MajorVersion     : 1
   +0x004 CurrentThread    : 0x84e3fb40 _KTHREAD  ; 那么,这里就是所谓的 fs:[00000124h] 了。
                                                  ; 即 _KTHREAD 结构的指针 CurrentThread。
                                                  ; ---------------------------------------
                                                  ; mov  eax, dword ptr fs:[00000124h] 的含义:
                                                  ; 就是取“当前线程”的地址:0x84E3FB40。

   +0x008 NextThread       : (null)
   +0x00c IdleThread       : 0x80559e20 _KTHREAD
   +0x010 Number           : 0 ''
   +0x011 Reserved         : 0 ''
   +0x012 BuildType        : 2
   +0x014 SetMember        : 1
   +0x018 CpuType          : 15 ''  
..........................


    还要说明的是,KTHREAD 结构是 ETHREAD 结构的一个子集,为了突出随笔的重点,我们暂且不深究:
kd> dt  nt!_ETHREAD
   +0x000 Tcb              : _KTHREAD
   +0x1c0 CreateTime       : _LARGE_INTEGER
   +0x1c0 NestedFaultCount : Pos 0, 2 Bits
   +0x1c0 ApcNeeded        : Pos 2, 1 Bit
   +0x1c8 ExitTime         : _LARGE_INTEGER
..........................


    继续分析,目标是 " [eax+44h]" 偏移:
kd> dt  nt!_KTHREAD 0x84E3FB40
   +0x000 Header           : _DISPATCHER_HEADER
   +0x010 MutantListHead   : _LIST_ENTRY [ 0x84e3fb50 - 0x84e3fb50 ]
   +0x018 InitialStack     : 0xf1b20000
   +0x01c StackLimit       : 0xf1b1b000
   +0x020 Teb              : 0x7ffdf000
   +0x024 TlsArray         : (null)
   +0x028 KernelStack      : 0xf1b1fcb0
   +0x02c DebugActive      : 0 ''
   +0x02d State            : 0x5 ''
   +0x02e Alerted          : [2]  ""
   +0x030 Iopl             : 0 ''
   +0x031 NpxState         : 0xa ''
   +0x032 Saturation       : 0 ''
   +0x033 Priority         : 9 ''
   +0x034 ApcState         : _KAPC_STATE
   +0x04c ContextSwitches  : 0x1d25b
   +0x050 IdleSwapBlock    : 0 ''
   +0x051 Spare0           : [3]  ""
   +0x054 WaitStatus       : 0
   +0x058 WaitIrql         : 0 ''
..........................


    已经定位到了 "ApcState" ,但是上面的输出不明了,我们再仔细看看:
kd> !strct  KTHREAD 0x84E3FB40
struct   _KTHREAD (sizeof=432)
+000 struct   _DISPATCHER_HEADER Header
+000    byte     Type =                          06                       .
+001    byte     Absolute =                      00                       .
+002    byte     Size =                          70                       p
+003    byte     Inserted =                      00                       .
+004    int32    SignalState =                   00000000
+008    struct   _LIST_ENTRY WaitListHead
+008       struct   _LIST_ENTRY *Flink =         84E3FB48
+00c       struct   _LIST_ENTRY *Blink =         84E3FB48
+010 struct   _LIST_ENTRY MutantListHead
+010    struct   _LIST_ENTRY *Flink =            84E3FB50
+014    struct   _LIST_ENTRY *Blink =            84E3FB50
+018 void     *InitialStack =                    F1B20000
+01c void     *StackLimit =                      F1B1B000
+020 void     *Teb =                             7FFDF000
+024 void     *TlsArray =                        00000000
+028 void     *KernelStack =                     F1B1FCB0
+02c byte     DebugActive =                      00                       .
+02d byte     State =                            05                       .
+02e byte     Alerted[2] =                       00 00                    . .
+030 byte     Iopl =                             00                       .
+031 byte     NpxState =                         0a                       .
+032 char     Saturation =                       00                       .
+033 char     Priority =                         09                       .
+034 struct   _KAPC_STATE ApcState
+034    struct   _LIST_ENTRY ApcListHead[2]
+034              ApcListHead[0]
+034               struct   _LIST_ENTRY *Flink =                84E3FB74
+038               struct   _LIST_ENTRY *Blink =                84E3FB74
+03c              ApcListHead[1]
+03c               struct   _LIST_ENTRY *Flink =                84E3FB7C
+040               struct   _LIST_ENTRY *Blink =                84E3FB7C
+044    struct   _KPROCESS *Process =            85076B98
+048    byte     KernelApcInProgress =           00                       .
+049    byte     KernelApcPending =              00                       .
+04a    byte     UserApcPending =                00                       .
+04c uint32   ContextSwitches =                  0001d25b
+050 int32    WaitStatus =                       00000000
..........................

    Good! 现在你能理解 "mov  eax, dword ptr [eax+44h]" 的含义了吗? 和上面取“当前线程”的指令类似这里就是取“当前进程”的地址。两句指令结束后, "c3  ret" 指令负责返回 EAX 中保存的地址。怎么样,多么优美的代码啊! 不是吗?



和上面“KTHREAD 结构是 ETHREAD 结构的一个子集”一样,KPROCESS 结构也是 EPROCESS 结构的一个子集:
kd> dt nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER
   +0x078 ExitTime         : _LARGE_INTEGER
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : Ptr32 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY
   +0x090 QuotaUsage       : [3] Uint4B
   +0x09c QuotaPeak        : [3] Uint4B
..........................


这次我们采用 EPROCESS 结构来分析地址 0x85076B98:
kd> dt  nt!_EPROCESS 0x85076B98
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER 0x1c7d996`86268d46
   +0x078 ExitTime         : _LARGE_INTEGER 0x0
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : 0x00000bdc
   +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x84ee9e28 - 0x84ec1c00 ]

   +0x090 QuotaUsage       : [3] 0x57a8
   +0x09c QuotaPeak        : [3] 0x5cc8
   +0x0a8 CommitCharge     : 0x51bb
   +0x0ac PeakVirtualSize  : 0x9b5441b
   +0x0b0 VirtualSize      : 0x9a0841b
   +0x0b4 SessionProcessLinks : _LIST_ENTRY [ 0x84ee9e54 - 0x84ec1c2c ]
   +0x0bc DebugPort        : (null)
   +0x0c0 ExceptionPort    : 0xe1aa4c90
   +0x0c4 ObjectTable      : 0xe1fe51e8 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : 0x3ac4b
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   +0x110 HyperSpaceLock   : 0
   +0x114 ForkInProgress   : (null)
   +0x118 HardwareTrigger  : 0
   +0x11c VadRoot          : 0x855c0fa8
   +0x120 VadHint          : 0x84dd8628
   +0x124 CloneRoot        : (null)
   +0x128 NumberOfPrivatePages : 0x4e78
   +0x12c NumberOfLockedPages : 0
   +0x130 Win32Process     : 0xe2536a20
   +0x134 Job              : (null)
   +0x138 SectionObject    : 0xe1975528
   +0x13c SectionBaseAddress : 0x01000000
   +0x140 QuotaBlock       : 0x84fbace0 _EPROCESS_QUOTA_BLOCK
   +0x144 WorkingSetWatch  : (null)
   +0x148 Win32WindowStation : 0x000007d8
   +0x14c InheritedFromUniqueProcessId : 0x00000bcc
   +0x150 LdtInformation   : (null)
   +0x154 VadFreeHint      : (null)
   +0x158 VdmObjects       : (null)
   +0x15c DeviceMap        : 0xe1ee32a0
   +0x160 PhysicalVadList  : _LIST_ENTRY [ 0x855a4db8 - 0x855a4db8 ]
   +0x168 PageDirectoryPte : _HARDWARE_PTE
   +0x168 Filler           : 0
   +0x170 Session          : 0xf7c9b000
   +0x174 ImageFileName    : [16]  "windbg.exe"
   +0x184 JobLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x18c LockedPagesList  : (null)
   +0x190 ThreadListHead   : _LIST_ENTRY [ 0x84e3fd6c - 0x8567bd2c ]
   +0x198 SecurityPort     : (null)
   +0x19c PaeTop           : (null)
   +0x1a0 ActiveThreads    : 6
   +0x1a4 GrantedAccess    : 0x1f0fff
   +0x1a8 DefaultHardErrorProcessing : 0
   +0x1ac LastThreadExitStatus : 0
   +0x1b0 Peb              : 0x7ffd3000 _PEB
   +0x1b4 PrefetchTrace    : _EX_FAST_REF
   +0x1b8 ReadOperationCount : _LARGE_INTEGER 0x4e95
   +0x1c0 WriteOperationCount : _LARGE_INTEGER 0x69
   +0x1c8 OtherOperationCount : _LARGE_INTEGER 0x765c
   +0x1d0 ReadTransferCount : _LARGE_INTEGER 0x3ac277e
   +0x1d8 WriteTransferCount : _LARGE_INTEGER 0xbfa20
   +0x1e0 OtherTransferCount : _LARGE_INTEGER 0x123423
   +0x1e8 CommitChargeLimit : 0
   +0x1ec CommitChargePeak : 0x51ef
   +0x1f0 AweInfo          : (null)
   +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x1f8 Vm               : _MMSUPPORT
   +0x238 LastFaultCount   : 0
   +0x23c ModifiedPageCount : 0x27cb
   +0x240 NumberOfVads     : 0x225
   +0x244 JobStatus        : 0
   +0x248 Flags            : 0xd0a00
   +0x248 CreateReported   : 0y0
   +0x248 NoDebugInherit   : 0y0
   +0x248 ProcessExiting   : 0y0
   +0x248 ProcessDelete    : 0y0
   +0x248 Wow64SplitPages  : 0y0
   +0x248 VmDeleted        : 0y0
   +0x248 OutswapEnabled   : 0y0
   +0x248 Outswapped       : 0y0
   +0x248 ForkFailed       : 0y0
   +0x248 HasPhysicalVad   : 0y1
   +0x248 AddressSpaceInitialized : 0y10
   +0x248 SetTimerResolution : 0y0
   +0x248 BreakOnTermination : 0y0
   +0x248 SessionCreationUnderway : 0y0
   +0x248 WriteWatch       : 0y0
   +0x248 ProcessInSession : 0y1
   +0x248 OverrideAddressSpace : 0y0
   +0x248 HasAddressSpace  : 0y1
   +0x248 LaunchPrefetched : 0y1
   +0x248 InjectInpageErrors : 0y0
   +0x248 VmTopDown        : 0y0
   +0x248 Unused3          : 0y0
   +0x248 Unused4          : 0y0
   +0x248 VdmAllowed       : 0y0
   +0x248 Unused           : 0y00000 (0)
   +0x248 Unused1          : 0y0
   +0x248 Unused2          : 0y0
   +0x24c ExitStatus       : 259
   +0x250 NextPageColor    : 0x936f
   +0x252 SubSystemMinorVersion : 0 ''
   +0x253 SubSystemMajorVersion : 0x4 ''
   +0x252 SubSystemVersion : 0x400
   +0x254 PriorityClass    : 0x2 ''
   +0x255 WorkingSetAcquiredUnsafe : 0 ''
   +0x258 Cookie           : 0x89bb4ac6


    好庞大!我们先看看这个结构的大小:
kd> !strct EPROCESS 0x85076B98
struct   _EPROCESS (sizeof=648)
+000 struct   _KPROCESS Pcb
..........................


    大于1K了呢,但是好东西可真多!随便看看您就能发现:UniqueProcessId、ActiveProcessLinks、ObjectTable、Token、ImageFileName等有用的东西。不难看出当前的这个 EPROCESS 结构的进程名是:"windbg.exe",PID是:"3036"。


+0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x84ee9e28 - 0x84ec1c00 ] 告诉我前一个链的地址在:0x84ee9e28,那么,其EPROCESS 基址明显就在 "0x84ee9e28 - 0x88 = 0x84ee9da0" 这里了。
    所以,怎么都想遍历一下 ActiveProcessLinks:                  //  ^_^  //


    前一链:
kd> dt  nt!_EPROCESS 0x84ee9da0
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER 0x1c7d996`8be59830
   +0x078 ExitTime         : _LARGE_INTEGER 0x0
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : 0x00000a6c                               ; PID == 2668
   +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x85120d80 - 0x85076c20 ]

   +0x090 QuotaUsage       : [3] 0xd40
   +0x09c QuotaPeak        : [3] 0x1448
   ..........................
   +0x168 Filler           : 0
   +0x170 Session          : 0xf7c9b000
   +0x174 ImageFileName    : [16]  "usnsvc.exe"
   +0x184 JobLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   ..........................



    后一链:
kd> dt  nt!_EPROCESS 0x84ec1b78
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER 0x1c7d996`849ac6ea
   +0x078 ExitTime         : _LARGE_INTEGER 0x0
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : 0x00000bcc                               ; PID == 3020
   +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x85076c20 - 0x84eaa0b8 ]

   +0x090 QuotaUsage       : [3] 0x9b0
   +0x09c QuotaPeak        : [3] 0xe28
   ..........................
   +0x168 Filler           : 0
   +0x170 Session          : 0xf7c9b000
   +0x174 ImageFileName    : [16]  "livekd.exe"
   +0x184 JobLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   ..........................


    用 Windbg 跟踪的结果和我用工具输出的结果完全吻合:
   ..........................
   Process: livekd.exe : 3020
   Process: windbg.exe : 3036
   Process: usnsvc.exe : 2668
   ..........................



    差不多了,聊到这可以说说 Russinovich 的函数 —— GetProcessNameOffset()、GetProcess()了:
    //----------------------------------------------------------------------
    //
    // GetProcessNameOffset
    //
    // In an effort to remain version-independent, rather than using a
    // hard-coded into the KPEB (Kernel Process Environment Block), we
    // scan the KPEB looking for the name, which should match that
    // of the GUI process
    //
    //----------------------------------------------------------------------

    ULONG GetProcessNameOffset()
    {
        PEPROCESS curproc;
        int i;
        DbgPrint(("GetProcessNameOffset\n"));
        curproc = PsGetCurrentProcess();    // 获取 _EPROCESS 结构的基址 //

        //
        // Scan for 12KB, hopping the KPEB never grows that big!
        //

        for( i = 0; i < 3*PAGE_SIZE; i++ ) {

            if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {

                return i;
            }
        }

        //
        // Name not found - oh, well         // 我在“无数人”代码中看到过这句话  唉... //
        //

        return 0;
    }


    Mark 的这个函数为的就是找到“ImageFileName”偏移诚然,您可以将程序硬编码写成这样:

char* GetProcessName()
{
    if(g_uMajVer!=5) return NULL;

    switch(g_uMinVer)
    {
        case 0:
            return (char*)PsGetCurrentProcess() + 0x1FC;        // Win-2K //
        case 1:
            return (char*)PsGetCurrentProcess() + 0x174;        // Win-XP //
        case 2:
            return (char*)PsGetCurrentProcess() + 0x154;        // Win-2003 //
        default:
            if(g_uPNameOff) return (char*)PsGetCurrentProcess() + g_uPNameOff;
            break;
    }

    return NULL;
}

    可是人家大师不屑一顾 "In an effort to remain version-independent, rather than using a hard-coded"。 因为人家有独创的技术:“暴力搜索 System 法” —— 而这个方法必定是建立在大量反汇编基础上的。

    正如你看到的那一样,Mark 疯狂搜索了3个页的内存空间以此做到“一劳永逸”,并辅以注释 —— "hopping the KPEB never grows that big!"哈哈,多么有趣的人啊!

    为了让您看的更清楚些,我把这个 Buffer(EPROCESS) 16进制打印了1个页(3个页实在没必要 :P ),如下:

                                 -*> MEMORY DUMP <*-  
                           (keenjoy95's HexPrint  0.01v)
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ 0000h:  03 00 1b 00 00 00 00 00  98 74 fb 85 98 74 fb 85    .........t...t.. ┃
┃ 0010h:  a0 74 fb 85 a0 74 fb 85  00 90 03 00 00 00 00 00    .t...t.......... ┃
┃ 0020h:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ................ ┃
┃ 0030h:  ac 20 00 00 00 00 00 00  a1 12 00 00 00 00 00 00    . .............. ┃
┃ 0040h:  d0 74 fb 85 d0 74 fb 85  00 00 00 00 00 00 00 00    .t...t.......... ┃
┃ 0050h:  b8 73 fb 85 58 4f e3 84  00 00 00 00 01 00 00 00    .s..XO.......... ┃
┃ 0060h:  33 00 08 06 00 00 00 00  00 00 00 00 00 00 00 00    3............... ┃
┃ 0070h:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ................ ┃
┃ 0080h:  00 00 00 00 04 00 00 00  d8 57 4d 85 d8 16 56 80    .........WM...V. ┃
┃ 0090h:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ................ ┃
┃ 00a0h:  00 00 00 00 00 00 00 00  07 00 00 00 00 c0 2f 00    ............../. ┃
┃ 00b0h:  00 80 1c 00 00 00 00 00  00 00 00 00 00 00 00 00    ................ ┃
┃ 00c0h:  00 00 00 00 f0 0b 00 e1  86 17 00 e1 01 00 00 00    ................ ┃
┃ 00d0h:  ac ca b2 f7 00 00 00 00  01 00 04 00 00 00 00 00    ................ ┃
┃ 00e0h:  70 75 fb 85 70 75 fb 85  00 00 00 00 00 00 00 00    pu..pu.......... ┃
┃ 00f0h:  01 00 00 00 b0 ca b2 f7  00 00 00 00 01 00 04 00    ................ ┃
┃ 0100h:  00 00 00 00 94 75 fb 85  94 75 fb 85 00 00 00 00    .....u...u...... ┃
┃ 0110h:  00 00 00 00 00 00 00 00  00 00 00 00 98 07 fb 85    ................ ┃
┃ 0120h:  98 07 fb 85 00 00 00 00  03 00 00 00 00 00 00 00    ................ ┃
┃ 0130h:  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00    ................ ┃
┃ 0140h:  80 17 56 80 00 00 00 00  00 00 00 00 00 00 00 00    ..V............. ┃
┃ 0150h:  00 00 00 00 00 00 00 00  00 00 00 00 30 54 00 e1    ............0T.. ┃
┃ 0160h:  f0 75 fb 85 f0 75 fb 85  00 00 00 00 00 00 00 00    .u...u.......... ┃
0170h:  00 00 00 00 53 79 73 74  65 6d 00 00 00 00 00 00    ....System...... ┃
 ................................................................................
 ................................................................................
┃ 0ff0h:  00 00 00 00 3f 00 3f 00  3e 00 2b 0a 50 63 69 42    ....?.?.>.+.PciB ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛


    OK,现在看清楚了吗?   ^_^

    Mark E, Russinovich 用这样的方法定位"ImageFileName",当年必定是天才的想法!而这也必定是建立在扎实反汇编功底基础上的(NuMega!!) —— 因为他早已恒定 DriverEntry 是由 System 调用的了。

    看到这样优美的代码您会想到什么? 我只有感叹,只有回味......

    >> B.E.Y.O.N.D <<



NUPT  - WANG yu









posted on Wednesday, August 08, 2007 5:20 PM 由 WANGyu

# re: fs:[00000000h] @ Tuesday, August 21, 2007 5:26 PM

够深入的。关于KPCR结构的地址,对于XP系统, 如果
是多CPU,那么第二个CPU的KPCR地址是不一样的。
0: kd> !pcr 1
KPCR for Processor 1 at f7b1f000:
...
Vista这方面做了较大改动,不过KPRCB和CurrentThread在结构内的偏移没有变。
0: kd> dt nt!_KPCR 85616000
+0x000 NtTib : _NT_TIB
+0x000 Used_ExceptionList : 0xffffffff _EXCEPTION_REGISTRATION_RECORD
+0x004 Used_StackBase : (null)
+0x008 Spare2 : (null)
+0x00c TssCopy : 0x856180c0
+0x010 ContextSwitches : 0x4d
+0x014 SetMemberCopy : 2
+0x018 Used_Self : (null)
+0x01c SelfPcr : 0x85616000 _KPCR
+0x020 Prcb : 0x85616120 _KPRCB
+0x024 Irql : 0x1f ''
+0x028 IRR : 0
+0x02c IrrActive : 0
+0x030 IDR : 0xffffffff
+0x034 KdVersionBlock : (null)
+0x038 IDT : 0x8561d8e0 _KIDTENTRY
+0x03c GDT : 0x8561d4e0 _KGDTENTRY
+0x040 TSS : 0x856180c0 _KTSS
+0x044 MajorVersion : 1
+0x046 MinorVersion : 1
+0x048 SetMember : 2
+0x04c StallScaleFactor : 0xae9
+0x050 SpareUnused : 0 ''
+0x051 Number : 0x1 ''
+0x052 Spare0 : 0 ''
+0x053 SecondLevelCacheAssociativity : 0x8 ''
+0x054 VdmAlert : 0
+0x058 KernelReserved : [14] 0
+0x090 SecondLevelCacheSize : 0x100000
+0x094 HalReserved : [16] 1
+0x0d4 InterruptMode : 0
+0x0d8 Spare1 : 0 ''
+0x0dc KernelReserved2 : [17] 0
+0x120 PrcbData : _KPRCB
0: kd> dt nt!_KPCR 818ec700
+0x000 NtTib : _NT_TIB
+0x000 Used_ExceptionList : 0x84c0341c _EXCEPTION_REGISTRATION_RECORD
+0x004 Used_StackBase : (null)
+0x008 Spare2 : (null)
+0x00c TssCopy : 0x80139000
+0x010 ContextSwitches : 0x3c
+0x014 SetMemberCopy : 1
+0x018 Used_Self : (null)
+0x01c SelfPcr : 0x818ec700 _KPCR
+0x020 Prcb : 0x818ec820 _KPRCB
+0x024 Irql : 0x1f ''
+0x028 IRR : 0
+0x02c IrrActive : 0
+0x030 IDR : 0xffffffff
+0x034 KdVersionBlock : 0x818ebc18
+0x038 IDT : 0x822ae400 _KIDTENTRY
+0x03c GDT : 0x822ae000 _KGDTENTRY
+0x040 TSS : 0x80139000 _KTSS
+0x044 MajorVersion : 1
+0x046 MinorVersion : 1
+0x048 SetMember : 1
+0x04c StallScaleFactor : 0xae9
+0x050 SpareUnused : 0 ''
+0x051 Number : 0 ''
+0x052 Spare0 : 0 ''
+0x053 SecondLevelCacheAssociativity : 0x8 ''
+0x054 VdmAlert : 0
+0x058 KernelReserved : [14] 0
+0x090 SecondLevelCacheSize : 0x100000
+0x094 HalReserved : [16] 0
+0x0d4 InterruptMode : 0
+0x0d8 Spare1 : 0 ''
+0x0dc KernelReserved2 : [17] 0
+0x120 PrcbData : _KPRCB

Raymond

# re: fs:[00000000h] @ Thursday, September 20, 2007 9:07 AM

落后了落后了...
我要赶紧去买Vista的机器了...

向Raymond老师学习! 嘿嘿

WANGyu

 
Legal Notice Privacy Statement Corporate Governance Corporate Governance
(C)2004-2005 Advanced Debugging Ltd. All Rights Reserved.