2024年3月29日发(作者:)
跨进程内存空间的读写
通常,跨进程读写内存,用到ReadProcessMemory, WriteProcessMemory, 但需要进程句柄,
如果目标进程受到保护,可能获得进程句柄会失败.不同的进程的虚拟地址被映射到了物理内
存中不同的页面.每个进程的虚拟地址的范围是相同的,但是实际的映射却是物理内存内中的
不同部分.假如我们直接读取目标进程的虚拟地址映射的物理地址,是否可以达到预期的要求.
当然这是肯定的,!
首先要获得目标进程的cr3寄存器,即页目录基地址(开启PAE, 页目录指针表),
每个进程在内核里都有一个EPROCESS结构.
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x06c ProcessLock : _EX_PUSH_LOCK
+0x070 CreateTime : _LARGE_INTEGER
+0x078 ExitTime : _LARGE_INTEGER
+0x080 RundownProtect : _EX_RUNDOWN_REF
…….
Pcb中就有我们想要得到的CR3
nt!_KPROCESS
+0x000 Header : _DISPATCHER_HEADER
+0x010 ProfileListHead : _LIST_ENTRY
+0x018 DirectoryTableBase : [2] Uint4B
+0x020 LdtDescriptor : _KGDTENTRY
+0x028 Int21Descriptor : _KIDTENTRY
………
那只需要获得目标进程EPROCESS就可以得到CR3了
假定目标进程就是当前进程, 可以遍历EPROCESS里的ActiveProcessLinks 的链表获取指
定进程的EPROCESS
// 获得EPROCESS信息
ULONG uEprocess = 0;
__asm
{
mov eax, fs:[0x124] // _ethread
mov eax, [eax+0x44] // _kprocess
mov uEprocess, eax
}
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
…..
nt!_KTHREAD
+0x000 Header : _DISPATCHER_HEADER
……
+0x034 ApcState : _KAPC_STATE
nt!_KAPC_STATE
+0x000 ApcListHead : [2] _LIST_ENTRY
+0x010 Process : Ptr32 _KPROCESS 这就是我们需要的ERPOCESS了
……
获得了CR3,,接下来,就是根据分页机制,把虚拟地址转换为物理地址勒.
在转换之前要判断是否开启PAE,非PAE和开启PAE的转换有所不同
控制寄存器CR4的第5位标记是否开启PAE
// 获得CR4的值
__asm
{
_emit 0x0F
_emit 0x20
_emit 0xE0
mov uCR4, eax
}
未开启PAE情况
通过CR3寄存器定位到页目录的基地址
线性地址的高10位作为获取页目录表项的索引, 获得一个页目录的一个表项
注: windows的保护实现基本不使用分段机制,主要是通过分页机制来实现保护,这里的就
线性地址等于虚拟地址,这是我的一点理解,可能有误,!
// 获得页目录表项(PDE)
dwPageDirIndex = (dwVirtualAddr & 0xffc00000) >> 22;
DWORD dwPageDirEntry = ReadPageDirEntryNoPAE(dwPageDirIndex);
if (dwPageDirEntry == 0)
{
return;
}
根据PDE获得页表基地址或者页基地址
当没有开启PAE时,有两种PDE格式, 分别指向4KB的页表,和4MB的内存页


发布评论