是否可实现应用程序名与进程名不同? (100分)

  • 主题发起人 主题发起人 wzboy1984
  • 开始时间 开始时间
W

wzboy1984

Unregistered / Unconfirmed
GUEST, unregistred user!
可否通过编程手段或修改系统(设置、注册表等)实现:所编写的delphi应用程序名(指在资源管理器中显示的文件名)与进程名(windows任务管理器中显示的名称)不同?<br><br>或者如何实现当程序在运行时,在进程中看不到它?<br>或者如何实现在任务管理器中关不掉它?<br><br>&gt;&gt;To Another_eYes<br>除了rundll32,还可不可以通过其他系统进程调用?
 
写成dll,用rundll32.exe调用
 
转贴一个<br><br>JIURL玩玩Win2k进程线程篇 EPROCESS<br>&nbsp;<br>作者: JIURL <br>&nbsp;<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 主页: http://jiurl.yeah.net/ <br>&nbsp;<br>&nbsp; &nbsp; 日期: 2003-7-30 <br>&nbsp;<br><br><br>--------------------------------------------------------------------------------<br>&nbsp;<br><br>&nbsp; &nbsp; 每个进程都有一个 EPROCESS 结构,里面保存着进程的各种信息,和相关结构的指针。EPROCESS 结构位于系统地址空间,所以访问这个结构需要有ring0的权限。使用 Win2k DDK 的 KD (内核调试器)我们可以得到 EPROCESS 结构的定义。注意下面的是 Win2k Build 2195 下的 EPROCESS 结构定义。<br><br>kd&gt; !strct eprocess<br>!strct eprocess<br>struct _EPROCESS (sizeof=648)<br>+000 struct _KPROCESS Pcb<br>+000 struct _DISPATCHER_HEADER Header<br>+000 byte Type<br>+001 byte Absolute<br>+002 byte Size<br>+003 byte Inserted<br>+004 int32 SignalState<br>+008 struct _LIST_ENTRY WaitListHead<br>+008 struct _LIST_ENTRY *Flink<br>+00c struct _LIST_ENTRY *Blink<br>+010 struct _LIST_ENTRY ProfileListHead<br>+010 struct _LIST_ENTRY *Flink<br>+014 struct _LIST_ENTRY *Blink<br>+018 uint32 DirectoryTableBase[2]<br>+020 struct _KGDTENTRY LdtDescriptor<br>+020 uint16 LimitLow<br>+022 uint16 BaseLow<br>+024 union __unnamed9 HighWord<br>+024 struct __unnamed10 Bytes<br>+024 byte BaseMid<br>+025 byte Flags1<br>+026 byte Flags2<br>+027 byte BaseHi<br>+024 struct __unnamed11 Bits<br>+024 bits0-7 BaseMid<br>+024 bits8-12 Type<br>+024 bits13-14 Dpl<br>+024 bits15-15 Pres<br>+024 bits16-19 LimitHi<br>+024 bits20-20 Sys<br>+024 bits21-21 Reserved_0<br>+024 bits22-22 Default_Big<br>+024 bits23-23 Granularity<br>+024 bits24-31 BaseHi<br>+028 struct _KIDTENTRY Int21Descriptor<br>+028 uint16 Offset<br>+02a uint16 Selector<br>+02c uint16 Access<br>+02e uint16 ExtendedOffset<br>+030 uint16 IopmOffset<br>+032 byte Iopl<br>+033 byte VdmFlag<br>+034 uint32 ActiveProcessors<br>+038 uint32 KernelTime<br>+03c uint32 UserTime<br>+040 struct _LIST_ENTRY ReadyListHead<br>+040 struct _LIST_ENTRY *Flink<br>+044 struct _LIST_ENTRY *Blink<br>+048 struct _LIST_ENTRY SwapListEntry<br>+048 struct _LIST_ENTRY *Flink<br>+04c struct _LIST_ENTRY *Blink<br>+050 struct _LIST_ENTRY ThreadListHead<br>+050 struct _LIST_ENTRY *Flink<br>+054 struct _LIST_ENTRY *Blink<br>+058 uint32 ProcessLock<br>+05c uint32 Affinity<br>+060 uint16 StackCount<br>+062 char BasePriority<br>+063 char ThreadQuantum<br>+064 byte AutoAlignment<br>+065 byte State<br>+066 byte ThreadSeed<br>+067 byte DisableBoost<br>+068 byte PowerState<br>+069 byte DisableQuantum<br>+06a byte Spare[2]<br>+06c int32 ExitStatus<br>+070 struct _KEVENT LockEvent<br>+070 struct _DISPATCHER_HEADER Header<br>+070 byte Type<br>+071 byte Absolute<br>+072 byte Size<br>+073 byte Inserted<br>+074 int32 SignalState<br>+078 struct _LIST_ENTRY WaitListHead<br>+078 struct _LIST_ENTRY *Flink<br>+07c struct _LIST_ENTRY *Blink<br>+080 uint32 LockCount<br>+088 union _LARGE_INTEGER CreateTime<br>+088 uint32 LowPart<br>+08c int32 HighPart<br>+088 struct __unnamed3 u<br>+088 uint32 LowPart<br>+08c int32 HighPart<br>+088 int64 QuadPart<br>+090 union _LARGE_INTEGER ExitTime<br>+090 uint32 LowPart<br>+094 int32 HighPart<br>+090 struct __unnamed3 u<br>+090 uint32 LowPart<br>+094 int32 HighPart<br>+090 int64 QuadPart<br>+098 struct _KTHREAD *LockOwner<br>+09c void *UniqueProcessId<br>+0a0 struct _LIST_ENTRY ActiveProcessLinks<br>+0a0 struct _LIST_ENTRY *Flink<br>+0a4 struct _LIST_ENTRY *Blink<br>+0a8 uint32 QuotaPeakPoolUsage[2]<br>+0b0 uint32 QuotaPoolUsage[2]<br>+0b8 uint32 PagefileUsage<br>+0bc uint32 CommitCharge<br>+0c0 uint32 PeakPagefileUsage<br>+0c4 uint32 PeakVirtualSize<br>+0c8 uint32 VirtualSize<br>+0d0 struct _MMSUPPORT Vm<br>+0d0 union _LARGE_INTEGER LastTrimTime<br>+0d0 uint32 LowPart<br>+0d4 int32 HighPart<br>+0d0 struct __unnamed3 u<br>+0d0 uint32 LowPart<br>+0d4 int32 HighPart<br>+0d0 int64 QuadPart<br>+0d8 uint32 LastTrimFaultCount<br>+0dc uint32 PageFaultCount<br>+0e0 uint32 PeakWorkingSetSize<br>+0e4 uint32 WorkingSetSize<br>+0e8 uint32 MinimumWorkingSetSize<br>+0ec uint32 MaximumWorkingSetSize<br>+0f0 *VmWorkingSetList<br>+0f4 struct _LIST_ENTRY WorkingSetExpansionLinks<br>+0f4 struct _LIST_ENTRY *Flink<br>+0f8 struct _LIST_ENTRY *Blink<br>+0fc byte AllowWorkingSetAdjustment<br>+0fd byte AddressSpaceBeingDeleted<br>+0fe byte ForegroundSwitchCount<br>+0ff byte MemoryPriority<br>+100 union __unnamed13 u<br>+100 uint32 LongFlags<br>+100 struct _MMSUPPORT_FLAGS Flags<br>+100 bits0-0 SessionSpace<br>+100 bits1-1 BeingTrimmed<br>+100 bits2-2 ProcessInSession<br>+100 bits3-3 SessionLeader<br>+100 bits4-4 TrimHard<br>+100 bits5-5 WorkingSetHard<br>+100 bits6-6 WriteWatch<br>+100 bits7-31 Filler<br>+104 uint32 Claim<br>+108 uint32 NextEstimationSlot<br>+10c uint32 NextAgingSlot<br>+110 uint32 EstimatedAvailable<br>+114 uint32 GrowthSinceLastEstimate<br>+118 struct _LIST_ENTRY SessionProcessLinks<br>+118 struct _LIST_ENTRY *Flink<br>+11c struct _LIST_ENTRY *Blink<br>+120 void *DebugPort<br>+124 void *ExceptionPort<br>+128 struct _HANDLE_TABLE *ObjectTable<br>+12c void *Token<br>+130 struct _FAST_MUTEX WorkingSetLock<br>+130 int32 Count<br>+134 struct _KTHREAD *Owner<br>+138 uint32 Contention<br>+13c struct _KEVENT Event<br>+13c struct _DISPATCHER_HEADER Header<br>+13c byte Type<br>+13d byte Absolute<br>+13e byte Size<br>+13f byte Inserted<br>+140 int32 SignalState<br>+144 struct _LIST_ENTRY WaitListHead<br>+144 struct _LIST_ENTRY *Flink<br>+148 struct _LIST_ENTRY *Blink<br>+14c uint32 OldIrql<br>+150 uint32 WorkingSetPage<br>+154 byte ProcessOutswapEnabled<br>+155 byte ProcessOutswapped<br>+156 byte AddressSpaceInitialized<br>+157 byte AddressSpaceDeleted<br>+158 struct _FAST_MUTEX AddressCreationLock<br>+158 int32 Count<br>+15c struct _KTHREAD *Owner<br>+160 uint32 Contention<br>+164 struct _KEVENT Event<br>+164 struct _DISPATCHER_HEADER Header<br>+164 byte Type<br>+165 byte Absolute<br>+166 byte Size<br>+167 byte Inserted<br>+168 int32 SignalState<br>+16c struct _LIST_ENTRY WaitListHead<br>+16c struct _LIST_ENTRY *Flink<br>+170 struct _LIST_ENTRY *Blink<br>+174 uint32 OldIrql<br>+178 uint32 HyperSpaceLock<br>+17c struct _ETHREAD *ForkInProgress<br>+180 uint16 VmOperation<br>+182 byte ForkWasSuccessful<br>+183 byte MmAgressiveWsTrimMask<br>+184 struct _KEVENT *VmOperationEvent<br>+188 void *PaeTop<br>+18c uint32 LastFaultCount<br>+190 uint32 ModifiedPageCount<br>+194 void *VadRoot<br>+198 void *VadHint<br>+19c void *CloneRoot<br>+1a0 uint32 NumberOfPrivatePages<br>+1a4 uint32 NumberOfLockedPages<br>+1a8 uint16 NextPageColor<br>+1aa byte ExitProcessCalled<br>+1ab byte CreateProcessReported<br>+1ac void *SectionHandle<br>+1b0 struct _PEB *Peb<br>+1b4 void *SectionBaseAddress<br>+1b8 struct _EPROCESS_QUOTA_BLOCK *QuotaBlock<br>+1bc int32 LastThreadExitStatus<br>+1c0 struct _PAGEFAULT_HISTORY *WorkingSetWatch<br>+1c4 void *Win32WindowStation<br>+1c8 void *InheritedFromUniqueProcessId<br>+1cc uint32 GrantedAccess<br>+1d0 uint32 DefaultHardErrorProcessing<br>+1d4 void *LdtInformation<br>+1d8 void *VadFreeHint<br>+1dc void *VdmObjects<br>+1e0 void *DeviceMap<br>+1e4 uint32 SessionId<br>+1e8 struct _LIST_ENTRY PhysicalVadList<br>+1e8 struct _LIST_ENTRY *Flink<br>+1ec struct _LIST_ENTRY *Blink<br>+1f0 struct _HARDWARE_PTE_X86 PageDirectoryPte<br>+1f0 bits0-0 Valid<br>+1f0 bits1-1 Write<br>+1f0 bits2-2 Owner<br>+1f0 bits3-3 WriteThrough<br>+1f0 bits4-4 CacheDisable<br>+1f0 bits5-5 Accessed<br>+1f0 bits6-6 Dirty<br>+1f0 bits7-7 LargePage<br>+1f0 bits8-8 Global<br>+1f0 bits9-9 CopyOnWrite<br>+1f0 bits10-10 Prototype<br>+1f0 bits11-11 reserved<br>+1f0 bits12-31 PageFrameNumber<br>+1f0 uint64 Filler<br>+1f8 uint32 PaePageDirectoryPage<br>+1fc byte ImageFileName[16]<br>+20c uint32 VmTrimFaultValue<br>+210 byte SetTimerResolution<br>+211 byte PriorityClass<br>+212 byte SubSystemMinorVersion<br>+213 byte SubSystemMajorVersion<br>+212 uint16 SubSystemVersion<br>+214 void *Win32Process<br>+218 struct _EJOB *Job<br>+21c uint32 JobStatus<br>+220 struct _LIST_ENTRY JobLinks<br>+220 struct _LIST_ENTRY *Flink<br>+224 struct _LIST_ENTRY *Blink<br>+228 void *LockedPagesList<br>+22c void *SecurityPort<br>+230 struct _WOW64_PROCESS *Wow64Process<br>+238 union _LARGE_INTEGER ReadOperationCount<br>+238 uint32 LowPart<br>+23c int32 HighPart<br>+238 struct __unnamed3 u<br>+238 uint32 LowPart<br>+23c int32 HighPart<br>+238 int64 QuadPart<br>+240 union _LARGE_INTEGER WriteOperationCount<br>+240 uint32 LowPart<br>+244 int32 HighPart<br>+240 struct __unnamed3 u<br>+240 uint32 LowPart<br>+244 int32 HighPart<br>+240 int64 QuadPart<br>+248 union _LARGE_INTEGER OtherOperationCount<br>+248 uint32 LowPart<br>+24c int32 HighPart<br>+248 struct __unnamed3 u<br>+248 uint32 LowPart<br>+24c int32 HighPart<br>+248 int64 QuadPart<br>+250 union _LARGE_INTEGER ReadTransferCount<br>+250 uint32 LowPart<br>+254 int32 HighPart<br>+250 struct __unnamed3 u<br>+250 uint32 LowPart<br>+254 int32 HighPart<br>+250 int64 QuadPart<br>+258 union _LARGE_INTEGER WriteTransferCount<br>+258 uint32 LowPart<br>+25c int32 HighPart<br>+258 struct __unnamed3 u<br>+258 uint32 LowPart<br>+25c int32 HighPart<br>+258 int64 QuadPart<br>+260 union _LARGE_INTEGER OtherTransferCount<br>+260 uint32 LowPart<br>+264 int32 HighPart<br>+260 struct __unnamed3 u<br>+260 uint32 LowPart<br>+264 int32 HighPart<br>+260 int64 QuadPart<br>+268 uint32 CommitChargeLimit<br>+26c uint32 CommitChargePeak<br>+270 struct _LIST_ENTRY ThreadListHead<br>+270 struct _LIST_ENTRY *Flink<br>+274 struct _LIST_ENTRY *Blink<br>+278 struct _RTL_BITMAP *VadPhysicalPagesBitMap<br>+27c uint32 VadPhysicalPages<br>+280 uint32 AweLock<br><br>遍历所有进程<br><br>系统需要能够方便的遍历所有进程。所以进程的 EPROCESS 结构使用链表链在了一起。<br><br>所有进程(除了Idle进程)的 EPROCESS 通过 EPROCESS 结构偏移+a0处的 LIST_ENTRY ActiveProcessLinks 链在一起。<br>+0a0 struct _LIST_ENTRY ActiveProcessLinks<br>+0a0 struct _LIST_ENTRY *Flink<br>+0a4 struct _LIST_ENTRY *Blink<br><br>通过全局变量 PsActiveProcessHead 可以找到这个链。<br>PID 为 0 的 Idle 进程并没有链在这个链上。我们可以通过全局变量 PsIdleProcess 找到 Idle 进程的 EPROCESS。<br><br>使用 LIST_ENTRY 结构来组织链表在 Win2k 中非常常见。Flink,Blink指向的都是另一个 LIST_ENTRY 结构。<br><br>对于 Win2k Build 2195 来说,全局变量 PsActiveProcessHead 的地址是 0x8046a180,开始处就是一个 LIST_ENTRY 结构。顺着这个 LIST_ENTRY 结构的 Flink 或者 Blink,我们可以找到每一个进程(除了Idle)的EPROCESS 结构中的 LIST_ENTRY ActiveProcessLinks。这个 ActiveProcessLinks 地址偏移 -0a0 处就是 EPROCESS 结构的地址。从 PsActiveProcessHead 开始顺着这条链一直走下去,直到重新回到 PsActiveProcessHead ,链已经循环了,就说明已经遍历了整个链。<br><br>下面我们看实际的例子<br><br>kd&gt; ? PsActiveProcessHead<br>? PsActiveProcessHead<br>Evaluate expression: -2142854784 = 8046a180<br>// Win2k Build 2195 的 PsActiveProcessHead 位于地址 8046a180<br><br>kd&gt; dd 8046a180 l 2<br>dd 8046a180 l 2<br>8046a180 8141e0c0 82fa4b00<br>// 8046a180 处的 LIST_ENTRY,注意 PsActiveProcessHead 并不是某个进程的 +0a0 ActiveProcessLinks<br>// 我们看看 Flink 找到的进程<br><br>kd&gt; ? 8141e0c0-a0<br>? 8141e0c0-a0<br>Evaluate expression: -2126389216 = 8141e020<br>// ActiveProcessLinks 位于 EPROCESS 的 +0a0 处。<br>// 我们得到的是 ActiveProcessLinks 的地址,所以 EPROCESS 在得到地址 -0a0 处。<br><br>kd&gt; !process 8141e020 0<br>!process 8141e020 0<br>PROCESS 8141e020 SessionId: 0 Cid: 0008 Peb: 00000000 ParentCid: 0000<br>DirBase: 00030000 ObjectTable: 81452a68 TableSize: 46.<br>Image: System<br>// 是PID为8的进程 System<br>... <br>// 顺着 Flink 一直走下去,我们省去了中间的过程<br><br>kd&gt; dd 82fa4b00 l 2<br>dd 82fa4b00 l 2<br>82fa4b00 8046a180 807e90c0<br>// 看到了这个 ActiveProcessLinks 的 Flink 为 8046a180 ,就是 PsActiveProcessHead <br>// 说明已经遍历了整个 ActiveProcessLinks 链<br><br>对于 Win2k Build 2195 来说,全局变量 PsIdleProcess 的地址是 0x8046a1fc,是一个 EPROCESS 指针,直接指向 Idle 进程的 EPROCESS 结构。<br><br>kd&gt; ? PsIdleProcess<br>? PsIdleProcess<br>Evaluate expression: -2142854660 = 8046a1fc<br>// Win2k Build 2195 的 PsIdleProcess 位于地址 8046a1fc<br><br>kd&gt; dd 8046a1fc l 1<br>dd 8046a1fc l 1<br>8046a1fc 8046bb60<br>// PsIdleProcess 的值为 8046bb60<br><br>kd&gt; !process 8046bb60 0<br>!process 8046bb60 0<br>PROCESS 8046bb60 SessionId: 0 Cid: 0000 Peb: 00000000 ParentCid: 0000<br>DirBase: 00030000 ObjectTable: 81452a68 TableSize: 46.<br>Image: Idle<br>// 可以看到 8046bb60 是指向 EPROCESS 的,并且这个 EPROCESS 是 PID 为 0 的 Idle 进程的 EPROCESS。<br><br><br>进程名<br><br>EPROCESS 中保存着一个给人看的进程名,Windows 任务管理器中显示的进程名,就是从这里获得的。<br>更准确的叫法是映像名称。<br>+1fc byte ImageFileName[16]<br>ImageFileName[16] 是一个16个字节长的字节数组,保存着进程名。当进程名的长度大于等于16个字节时,在 ImageFileName[16] 只保存进程名的前15个字节,ImageFileName[16] 最后一个字节为0,字符串的结束符。<br>不同进程的进程名可以相同,比如打开多个记事本,那么每个记事本的 ImageFileName[16] 都是 "NOTEPAD.EXE",进程名只是给人看的,每个进程的 进程ID 都是不同的。<br><br>kd&gt; !process 200 0<br>!process 200 0<br>Searching for Process with Cid == 200<br>PROCESS 8105c2e0 SessionId: 0 Cid: 0200 Peb: 7ffdf000 ParentCid: 01f0<br>DirBase: 00564000 ObjectTable: 81090c48 TableSize: 298.<br>Image: Explorer.exe<br><br>kd&gt; db 8105c2e0+1fc l 10<br>db 8105c2e0+1fc l 10<br>8105c4dc 45 78 70 6c 6f 72 65 72-2e 65 78 65 00 00 00 00 Explorer.exe....<br><br><br>进程ID (PID)<br><br>+09c void *UniqueProcessId<br><br>父进程ID <br><br>+1c8 void *InheritedFromUniqueProcessId<br><br><br>页目录<br><br>+018 uint32 DirectoryTableBase[2]<br><br>每个进程有自己4G地址空间,当进程切换时,就需要切换地址空间。也就是切换页目录页表。所以每个进程都需要保存自己页目录的地址。每个进程的页目录所在物理页的物理地址,就保存在进程 EPROCESS 结构偏移 +018 处 DirectoryTableBase数组的第0项中,即 DirectoryTableBase[0]。对于执行地址转换的 CPU 来说需要知道页目录所在物理页的物理地址就可以进行地址转换。对于维护进程的页目录和页表的系统来说,需要把页目录和页表所在的物理页映射到地址空间中。<br><br>下面使用 SoftICE 来说明,进程 EPROCESS 中的 DirectoryTableBase数组,有2个元素,其中DirectoryTableBase[0] 就是该进程的页目录的物理地址,也就是该进程 CR3 的值。<br><br>:addr<br>CR3 LDT Base:Limit KPEB Addr PID Name<br>00030000 8141E020 0008 System<br>04E4B000 810F7580 008C smss<br>06582000 810E8D60 00A8 csrss<br>07607000 810CC2C0 00BC winlogon<br>07A49000 810C1500 00D8 services<br>0799A000 810BFD60 00E4 lsass<br>00AFD000 810A2D60 0174 svchost<br>00F21000 81092940 0190 svchost<br>007C4000 8105D600 0200 Explorer<br>024B9000 824D0020 0260 internat<br>042B2000 8423E860 0180 conime<br>*00030000 8046BB60 0000 Idle<br>// addr 列出当前进程,注意每个进程的 CR3 , SoftICE 显示的 KPEB Addr 就是 EPROCESS 的地址<br><br>// 转换到 explorer 的地址空间,EPROCESS 在 8105D600 <br>// 偏移 +018 处 是 uint32 DirectoryTableBase[2] 数组<br>:addr explorer<br>:dd 8105d600+18 l 10<br>0010:8105D618 007C4000 06165000 00000000 00000000 .@|..P..........<br>// DirectoryTableBase[0] 物理地址为 007C4000 看看这个物理地址,被映射到了哪些虚拟地址<br>:phys 7c4000<br>807C4000<br>C0300000<br>// C0300000 是进程页目录被映射到的地址空间<br>:phys 6165000<br>86165000<br>C0301000<br><br>// 情况一样<br>:addr internat<br>:dd 824d0020+18 l 10<br>0010:824D0038 024B9000 024BA000 00000000 00000000 ..K...K.........<br>:phys 24b9000<br>824B9000<br>C0300000<br>:phys 24ba000<br>824BA000<br>C0301000<br><br>// 情况一样<br>:addr csrss<br>:dd 810e8d60+18 l 10<br>0010:810E8D78 06582000 06563000 00000000 00000000 . X..0V.........<br>:phys 6582000<br>86582000<br>C0300000<br>:phys 6563000<br>86563000<br>C0301000<br><br>// 注意这是 System 进程<br>// System 的 DirectoryTableBase[0] 仍然映射到了 C0300000<br>// 但是 System 的 DirectoryTableBase[1] 情况和别的进程不一样<br>:addr system<br>:dd 8141e020+18 l 10<br>0010:8141E038 00030000 00000000 00000000 00000000 ................<br>:phys 30000<br>80030000<br>C0300000<br>C04FB000<br>EB3F1000<br>F09CA000<br>:phys 00000000<br>80000000<br>C0200000<br>EB3C1000<br>F09D4000<br><br>我们可以看到 DirectoryTableBase[0] 中就是页目录所在物理页的物理地址。每个进程 EPROCESS +18 处4个字节的值 和 该进程 CR3 中的值是一样的。 EPROCESS +18 处4个字节的物理地址都映射到了 C0300000,而 C0300000 正是页目录所在物理页映射到地址空间中的虚拟地址。我也检查了一个进程的 DirectoryTableBase[0] (EPROCESS +18 处4个字节的值)所指的物理页中的内容,里面的确是 该进程页目录的内容。<br><br>从 SoftICE 的输出中,我们可以看到 DirectoryTableBase[1] 中的物理地址所指的物理页,被映射到了地址空间 C0301000 处,也就是 C0301000-C0301FFF 这个页表,我们计算可以得到这个页表负责的是 C0400000-C07fffff 这 4M 虚拟地址空间的映射。我们知道每个进程的 Working Set 开始于 C0502000 ,就落在这个范围之内,而每个进程都有自己的 Working Set。<br><br>其实一个进程保存自己的页目录的物理地址就足够了。由于每个进程的 Working Set 在 C0400000-C07fffff 这个范围之内,每个进程的 Working Set 是不同的,所以负责这个范围的页表也是不同的,所以有理由多保存一个负责地址空间 映射的页表的物理地址。不过要注意的是,进程 System 的 DirectoryTableBase[1] 值为0,并不是对应地址空间范围 C0400000-C07fffff 的页表所在物理页的物理地址。<br><br><br>不切换进程,直接访问其他进程的地址空间<br><br>我们使用(驱动程序中使用)KeAttachProcess(),KeDetachProcess() 切换地址空间到一个指定进程的地址空间,然后访问这个进程地址空间中的内存。现在对于物理内存不超过 512M 的系统,我们有一种方法,可以不用切换地址空间,直接访问指定进程的地址空间中的内存。<br><br>我们知道 Win2k 把物理内存的前 512M 的每个物理页,一一对应的映射到地址空间的 80000000-9FFFFFFF 这一段 LargePage 区域中。物理内存不到512M的,有多少就映射多少。这样我们就可以访问所有不超过 512M 的物理内存(当然 80000000-9FFFFFFF 在系统地址空间中,访问需要 ring0 的权限)。对于一个小于512M的物理地址,我们可以用这个物理地址加上 80000000 ,得到该物理页映射的一页地址空间的虚拟地址,我们可以使用这个虚拟地址,来访问这个物理中的内容。从前面分析 DirectoryTableBase 时,SoftICE 的输出也可以看出这一点,比如,物理地址 7c4000 ,对应虚拟地址 807C4000 。<br><br>对于一个指定的进程,我们可以通过进程链表找到它,并计算出它的 EPROCESS 的地址。就可以找到 EPROCESS 中的该进程页目录所在物理页的物理地址,即 DirectoryTableBase[0] 的值。该进程页目录所在物理页的物理地址如果小于512M,我们就可以计算出这个物理页被映射到地址空间 80000000-9FFFFFFF 中的虚拟地址,就可以访问该进程的页目录。就可以找到该进程的所有页表的物理地址,同样我们根据页表的物理地址,可以算出页表在 80000000-9FFFFFFF 中的虚拟地址,就可以访问该进程的所有页表。就可以找到该进程所有页对应的物理页的物理地址。根据这个物理地址,我们可以算出该物理页在 80000000-9FFFFFFF 中的虚拟地址,从而访问改进程的某一页中的数据。<br><br>我们用 SoftICE 实际演示一下,读取进程 Explorer 地址空间 0x400000 中的内容。<br><br>:addr<br>CR3 LDT Base:Limit KPEB Addr PID Name<br>00030000 8141E020 0008 System<br>04E4B000 810F7580 008C smss<br>06582000 810E8D60 00A8 csrss<br>07607000 810CC2C0 00BC winlogon<br>07A49000 810C1500 00D8 services<br>0799A000 810BFD60 00E4 lsass<br>00AFD000 810A2D60 0174 svchost<br>00F21000 81092940 0190 svchost<br>007C4000 8105D600 0200 Explorer<br>024B9000 824D0020 0260 internat<br>06A45000 84090220 02A8 conime<br>*00030000 8046BB60 0000 Idle<br>// Explorer 的 EPROCESS 地址为 8105D600 ,我们通过进程链表也可以找到<br><br>:dd 8105d600+18 l 10<br>0010:8105D618 007C4000 06165000 00000000 00000000 .@|..P..........<br>// Explorer 的页目录所在物理页的地址为 007C4000 <br><br>:dd (80000000+7c4000)+(400000&gt;22)*4 l 10<br>0010:807C4004 028D4067 0268E067 01E35067 0219B067 g@..g.h.gP..g...<br>// (80000000+7c4000) 就是 Explorer 的页目录的虚拟地址<br>// (400000&gt;22) 取虚拟地址 400000 的高10bit,这是页目录索引。<br>// 一个页目录项大小为4个字节,所以 (400000&gt;22)*4 为 400000 对应页目录项在页目录中偏移地址<br>// 所以 400000 对应的页表的物理地址为 028D4000 (别忘了页目录项和页表项的低12位是标志)<br><br>:dd (80000000+28d4000)+((400000&amp;3ff000)&gt;12)*4 l 10<br>0010:828D4000 02963005 00612025 08332C34 02954025 .0..% a.4,3.%@..<br>// ((400000&amp;3ff000)&gt;12) ,取虚拟地址 400000 作为页表索引的10bit,<br>// ((400000&amp;3ff000)&gt;12)*4 为 400000 在对应页表项在页表中偏移地址<br>// 所以 400000 对应的物理页的物理地址为 02963000<br><br>:dd (80000000+2963000)+(400000&amp;fff) l 10<br>0010:82963000 00905A4D 00000003 00000004 0000FFFF MZ..............<br>// (400000&amp;fff),取虚拟地址 400000 的低12bit作为页内偏移。<br>// 最后得到进程 Explorer 虚拟地址 400000 处的4个字节值为 00905A4D ,就是"MZ.."<br><br>// 切换到 Explorer 地址空间,验证一下<br>:addr explorer<br>:dd 400000 l 10<br>0010:00400000 00905A4D 00000003 00000004 0000FFFF MZ..............<br>// 可以看到 Explorer 地址空间虚拟地址 00400000 处的值正是 00905A4D ,"MZ.."<br><br><br>进程的 HANDLE_TABLE<br><br>+128 struct _HANDLE_TABLE *ObjectTable<br><br>进程的 PEB<br><br>+1b0 struct _PEB *Peb<br><br>线程链表<br><br>进程的所有线程通过 LIST_ENTRY 结构链在了一个双向循环链表上。<br>一个链表是以 EPROCESS 结构的 KPROCESS Pcb 中的 ThreadListHead 为链表的链表头。链上的每一项是一个线程的 KTHREAD ETHREAD 结构的 Tcb 中的 ThreadListEntry 。<br>另一个链表是以 EPROCESS 结构中的 ThreadListHead 为链表的链表头。链上的每一项是一个线程的 ETHREAD 结构中的 ThreadListEntry 。<br>通过这两个链表中的任何一个,都可以找到一个进程的所有线程的 ETHREAD 结构,当然找到 ETHREAD 结构,就可以找到 ETHREAD 结构中的 KTHREAD。<br><br>KTHREAD 链表<br><br>struct _EPROCESS (sizeof=648)<br>+000 struct _KPROCESS Pcb<br>+050 struct _LIST_ENTRY ThreadListHead<br>+050 struct _LIST_ENTRY *Flink<br>+054 struct _LIST_ENTRY *Blink<br><br>struct _ETHREAD (sizeof=584)<br>+000 struct _KTHREAD Tcb<br>+1a4 struct _LIST_ENTRY ThreadListEntry<br>+1a4 struct _LIST_ENTRY *Flink<br>+1a8 struct _LIST_ENTRY *Blink<br><br>ETHREAD 链表<br><br>struct _EPROCESS (sizeof=648)<br>+270 struct _LIST_ENTRY ThreadListHead<br>+270 struct _LIST_ENTRY *Flink<br>+274 struct _LIST_ENTRY *Blink<br><br>struct _ETHREAD (sizeof=584)<br>+240 struct _LIST_ENTRY ThreadListEntry<br>+240 struct _LIST_ENTRY *Flink<br>+244 struct _LIST_ENTRY *Blink<br><br>VAD <br><br>+194 void *VadRoot<br>+198 void *VadHint<br><br>VadRoot 是进程 Vad 二叉树的根节点的指针。<br>通过反汇编和分析函数 MiLocateAddress() 可以知道 ,VadHint 是上一次 MiLocateAddress() 找到的 Vad 的指针。<br><br>WorkingSet<br><br>+0e0 uint32 PeakWorkingSetSize<br>+0e4 uint32 WorkingSetSize<br>+0e8 uint32 MinimumWorkingSetSize<br>+0ec uint32 MaximumWorkingSetSize<br>+0f0 *VmWorkingSetList<br><br>WorkingSet 的相关信息。<br>VmWorkingSetList 是指向 MMWSL 结构的指针。值总是 C0502000 。<br><br>Section<br><br>+1ac void *SectionHandle<br>+1b4 void *SectionBaseAddress<br><br>SectionHandle 是句柄,可以用这个句柄在句柄表中找到对应的对象。<br>SectionBaseAddress 是载入地址空间的基地址。<br><br><br>进程对象的对象体<br><br>需要说明的是 EPROCESS 就是进程对象的对象体,象其他类型的对象一样,EPROCESS 之前也有对象头。使用 kd 可以很容易看到这一点<br>kd&gt; !process 8 0<br>!process 8 0<br>Searching for Process with Cid == 8<br>PROCESS 8141e020 SessionId: 0 Cid: 0008 Peb: 00000000 ParentCid: 0000<br>DirBase: 00030000 ObjectTable: 81452a68 TableSize: 106.<br>Image: System<br><br>kd&gt; !object 8141e020<br>!object 8141e020<br>Object: 8141e020 Type: (814524e0) Process<br>ObjectHeader: 8141e008<br>HandleCount: 2 PointerCount: 36<br><br>根据 EPROCESS 的地址,kd 可以正确分析出对象类型是进程,说明了 EPROCESS 的确是对象体。<br><br><br>欢迎交流,欢迎交朋友,<br>欢迎访问 http://jiurl.yeah.net/ http://jiurl.cosoft.org.cn/forum <br><br><br><br><br><br><br><br><br>&nbsp;<br>
 
好象更改peb中的名称即可。<br>具体可参考pjf's blog上相关文章
 
后退
顶部