首页
论坛
课程
招聘
雪    币: 81
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝

[原创]跨进程内存读取, 附源码

2009-6-26 21:24 49622

[原创]跨进程内存读取, 附源码

2009-6-26 21:24
49622
在科锐学习的第4阶段, 保护模式课后作业,跨进程内存读写的小工具.

第一次内核编程,代码写的比较乱,不免也有些错误.各位牛哥们,见笑乐,!时间仓促,也没对代码进程封装,和界面相关太多.
1.  切换目标进程的CR3
      通常,跨进程读写内存,用到ReadProcessMemory, WriteProcessMemory, 但需要进程句柄,如果目标进程受到保护,可能获得进程句柄会失败.
      ReadProcessMemory最后会调用到KeStackAttachProcess附加到目标进程上切换进程环境进行拷贝的, 所以想到拿到目标进程的虚拟内存内容,可以将目标进程的页目录基地址放入CR3中即可.

首先要获得目标进程的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
            }

            KdPrint(("EPROCESS: 0x%08x\n", uEprocess));
            LIST_ENTRY ListHead;
            InitializeListHead(&ListHead);

            ULONG uFirstEprocess = uEprocess;
            ULONG uCount = 0;
            PLIST_ENTRY pActiveProcessLinks;
            ProcessInfoList *pProcssList = NULL;

            ULONG uNameOffset = GetPlantformDependentInfo(FILE_NAME_OFFSET);
            ULONG uPidOffset = GetPlantformDependentInfo(PROCESS_ID_OFFSET);
            ULONG uLinkOffset = GetPlantformDependentInfo(PROCESS_LINK_OFFSET);
            ULONG uExitTime = GetPlantformDependentInfo(EXIT_TIME_OFFSET);
            // 遍历链表获得进程信息
            do 
            {
                
                pProcssList= 
                    (ProcessInfoList *)ExAllocatePool(PagedPool, sizeof(ProcessInfoList));
                if (pProcssList == NULL)
                {
                    status = STATUS_INSUFFICIENT_RESOURCES;
	            break;
                }

                PLARGE_INTEGER ExitTime;
                ExitTime = (PLARGE_INTEGER)(uEprocess + uExitTime);
                if (ExitTime->QuadPart == 0)
                {
                    if (*(int *)(uEprocess + uPidOffset) <= 0)
                    {
                        pProcssList->ProcInfo.uProcessId = 0;
                        pProcssList->ProcInfo.uEprocess = uEprocess;
                        pProcssList->ProcInfo.uCR3 = *(PULONG)(uEprocess + 0x18);
                        RtlCopyMemory(pProcssList->ProcInfo.pszImageFileName, "Idle", 16);
                        InsertHeadList(&ListHead, &pProcssList->ListEntry);
                        KdPrint(("PID: %d, EPROCESS: 0x%08x, FileName: %s, CR3: 0x%08x\n",
                            pProcssList->ProcInfo.uProcessId,
                            pProcssList->ProcInfo.uEprocess,
                            pProcssList->ProcInfo.pszImageFileName,
                            pProcssList->ProcInfo.uCR3));
                    }
                    else
                    {

                        pProcssList->ProcInfo.uEprocess = uEprocess;
                        pProcssList->ProcInfo.uCR3 = *(PULONG)(uEprocess + 0x18);
                        pProcssList->ProcInfo.uProcessId = *(PULONG)(uEprocess + uPidOffset);
                        RtlCopyMemory(pProcssList->ProcInfo.pszImageFileName, 
                            (PVOID)(uEprocess + uNameOffset), 
                            16);
                        InsertHeadList(&ListHead, &pProcssList->ListEntry);
                        KdPrint(("PID: %d, EPROCESS: 0x%08x, FileName: %s, CR3:  0x%08x\n",
                            pProcssList->ProcInfo.uProcessId,
                            pProcssList->ProcInfo.uEprocess,
                            pProcssList->ProcInfo.pszImageFileName,
                            pProcssList->ProcInfo.uCR3));


                    }
                    uCount++;
                }

                pActiveProcessLinks = (PLIST_ENTRY)(uEprocess + uLinkOffset);
                uEprocess = (ULONG)pActiveProcessLinks->Blink - uLinkOffset;


                if (uEprocess == uFirstEprocess)
                {
                    break;
                }
            } while (uEprocess != 0);

   引用了北极星2003大哥的GetPlantformDependentInfo 获取EPROCESS的成员偏移
  
   下面是读写内存的:
            _try
            {
                WriteMemoryInfo *pInfo = 
                    (WriteMemoryInfo *)ExAllocatePool(PagedPool, sizeof(WriteMemoryInfo));

                RtlCopyMemory(pInfo, pIoBuffer, sizeof(WriteMemoryInfo));

                PVOID pWrite =  ExAllocatePool(PagedPool, pInfo->nWriteSize);

                RtlCopyMemory(pWrite, pInfo->pData, pInfo->nWriteSize);
                //pInfo->pData = (PBYTE)ExAllocatePool(PagedPool, pInfo->nWriteSize);
                ULONG uOldCr3 = 0;
                ULONG uCurrentCr3 = *(PULONG)(pInfo->nEprocess + 0x18);
                if (pInfo->nMemoryAddr == 0)
                {
                    status = STATUS_UNSUCCESSFUL;
                    break;
                }
                __asm
                {
                    mov eax, cr3
                    mov uOldCr3, eax

                    mov eax, uCurrentCr3
                    mov cr3, eax
                }

                __asm
                {
                    cli
                    push eax
                    mov eax, cr0
                    and eax, not 10000h
                    mov cr0, eax
                }

                RtlCopyMemory((PVOID)pInfo->nMemoryAddr, 
                    pWrite, pInfo->nWriteSize);

                __asm

                {
                    mov eax, CR0
                    or eax, 10000h
                    mov cr0,eax
                    pop eax
                    sti

                }
                __asm
                {
                    mov eax, uOldCr3
                    mov cr3, eax
                }


                uOutSize = pInfo->nWriteSize;
                if (pInfo != NULL)
                {

                    ExFreePool(pInfo);
                    pInfo = NULL;
                }
                // Return success
                status = STATUS_SUCCESS;
            }
            __except(1)
            {
                status = STATUS_UNSUCCESSFUL;
            }


            __try
            {   
                ReadMemoryInfo *pInfo = 
                    (ReadMemoryInfo *)ExAllocatePool(PagedPool, sizeof(ReadMemoryInfo));
                RtlCopyMemory(pInfo, pIoBuffer, sizeof(ReadMemoryInfo));
                ULONG uOldCr3 = 0;
                ULONG uCurrentCr3 = *(PULONG)(pInfo->nEprocess + 0x18);
                if (pInfo->nMemoryAddr == 0)
                {
                    status = STATUS_UNSUCCESSFUL;
                    break;
                }
                __asm
                {
                    mov eax, cr3
                    mov uOldCr3, eax

                    mov eax, uCurrentCr3
                    mov cr3, eax

                }
                RtlCopyMemory(pIoBuffer, 
                    (PVOID)pInfo->nMemoryAddr ,pInfo->nReadSize);
                uOutSize = pInfo->nReadSize;
                __asm
                {
                    mov eax, uOldCr3
                    mov cr3, eax
                }

                if (pInfo != NULL)
                {
                    ExFreePool(pInfo);
                    pInfo = NULL;
                }
                // Return success
                status = STATUS_SUCCESS;
            }
            __except(1)
            {
                status = STATUS_UNSUCCESSFUL;
            }


2. 根据分页机制,进行手工转换,得到虚拟地址的映射的物理地址,读其物理地址得到目标进程虚拟地址的内容.详见附件分析.

获得了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的内存页



页目录项的第7位判断页大小
// 获得页大小
DWORD CReadMemoryDlg::GetPageSizeNoPAE(DWORD dwAddr)
{
    if ((dwAddr & 0x00000080) == 0x00000080)
    {
        return MBSIZE;
    }
    else
    {
        return KBSIZE;
    }
}


4KB时, 页目录项的高20位为页表基地址.线性地址的12位到21位作为选取页表的一个表项.(PTE)


dwPageTableIndex = (dwVirtualAddr & 0x0003ff000) >> 12;
DWORD dwPageTableBaseAddr = dwPageDirEntry & 0xfffff000;
// 获得页表
DWORD dwPageTable = ReadPageTableNoPAE(dwPageTableBaseAddr, 
                    		dwPageTableIndex);
if (dwPageTable == 0)
{
     return;
}
if (IsPresentNoPAE(dwPageTable) == FALSE)
{
     return;
}


取PTE的高20位,作为内存页的基地址,线性地址的低12作为页中偏移得到物理地址
// 页的基地址
DWORD dwPageBaseAddr = dwPageTable & 0xfffff000;
dwPageOffset = dwVirtualAddr & 0x00000fff;


这时获得的物理地址就是想要的目标进程虚拟地址的映射的物理地址
PVOID pReadBuf = new BYTE[dwReadSize];
                
BOOL bRet = ReadPageMemoryNoPAE(pReadBuf, 
                    dwPageOffset, 
                    dwReadSize, 
                    dwPageBaseAddr);
if (bRet == FALSE)
{
      return;
}


4MB时,页目录项的高10位作为页的基地址, 线性地址的低22位在物理地址在页中的偏移


// 线性地址的低22位是页内偏移
DWORD dwPageOffsetMB = dwVirtualAddr & 0x003fffff;
// 高10位,是页基地址
DWORD dwPageBaseAddr = dwPageDirEntry & 0xffc00000;


这时获得的物理地址就是想要的目标进程虚拟地址的映射的物理地址
PVOID pReadBuf = new BYTE[dwReadSize];

BOOL bRet = ReadPageMemoryPAE(pReadBuf, 
                    dwPageOffsetMB, 
                    dwReadSize, 
                    dwPageBaseAddr);
if (bRet == FALSE)
{
    return;
}


开启PAE情况
CR4中的物理地址扩展(PAE)标志可以开启PAE机制,将物理地址从32位扩展到36位.
当开始PAE机制后,处理器支持两种尺寸的页:4KB和2Mb的页.
增加了页目录指针表项.
表项的大小从32位增加到了64位
表项中的物理基地址扩展到了24位
寄存器CR3中的高位页目录基地址被换为27位的页目录指针表基地址



通过CR3寄存器定位到页目录指针表起始地址,取线性地址的高2位作为选取页目录指针表项的索引
DWORD dwDirPointerTableIndex = (dwVirtualAddr & 0xc0000000) >> 30;
DWORD dwDirPointerTableBaseAddr = m_nDirBase & 0xffffffe0;
// 获得页目录指针表
__int64 nPageDirPointerTable = ReadPageDirPAE(dwDirPointerTableIndex, 
                    dwDirPointerTableBaseAddr);
if (nPageDir == 0)
{
       return;
}


取线性地址的第21位到29位作为页目录索引,页目录指针表项的第12位到第35位为页目录基地址


// 页目录基地址
DWORD dwDirBaseAddr = (DWORD)(nPageDirPointerTable &0x0000000ffffff000);
// 页目录项索引
DWORD dwPageDirIndex = (dwVirtualAddr & 0x3fe00000) >> 21;

__int64 nPageDirEntry = ReadPageDirEntryPAE(dwPageDirIndex, dwDirBaseAddr);

if (nPageDirEntry == 0)
{
      return;
}


根据页目录项的第7位判断页大小,2MB,还是4KB
// 获得页大小
DWORD CReadMemoryDlg::GetPageSizePAE(__int64 nAddr)
{
    if ((nAddr & 0x0000000000000080) == 0x0000000000000080)
    {
        return MBSIZE;
    }
    else
    {
        return KBSIZE;
    }
}

4KB时,页目录项的第12位到35位作为页表基地址的高24位.取线性地址第12位到20位作为在页表中的偏移



// 获得页表
DWORD dwPageTableBaseAddr = (DWORD)(nPageDirEntry & 0x0000000ffffff000);
DWORD dwPageTableIndex = (dwVirtualAddr & 0x001ff000) >> 12;
__int64 nPageTable = ReadPageTablePAE(dwPageTableIndex, dwPageTableBaseAddr);

if (nPageTable == 0)
{
     return;
}


通过页表项的第12位到第35位作为页基地址的高24位,线性地址的低12为作为在页中的偏移
// 读取页内容
DWORD dwPageBaseAddr = (DWORD)(nPageTable & 0x0000000ffffff000);
DWORD dwPageOffsetKb = dwVirtualAddr & 0x00000fff;
PVOID pReadBuf = new BYTE[dwReadSize];
BOOL bRet = ReadPageMemoryPAE(pReadBuf, 
                    dwPageOffsetKb, 
                    dwReadSize, 
                    dwPageBaseAddr);
if (bRet == FALSE)
{
     return;
}

所得到的内容就是目标进程虚拟地址内存的数据

2MB时, 页目录项的第21位到35位作为页的基地址的高位,取线性地址的第0位到第20位做为物理地址在页中的偏移


DWORD dwPageOffsetMB = dwVirtualAddr & 0x000fffff;
// 高-35位
DWORD dwDirBaseAddr = (DWORD)(nPageDirEntry & 0x00000007fff00000);
PVOID pReadBuf = new BYTE[dwReadSize];
BOOL bRet = ReadPageMemoryPAE(pReadBuf, 
                    dwPageOffsetMB, 
                    dwReadSize, 
                    dwDirBaseAddr);
if (bRet == FALSE)
{
return;
}   


所得到的内容就是目标进程虚拟地址内存的数据

     这里谢谢钱老师,这近一年的培养,祝钱老师的培训越办越好,!

[看雪官方培训]《安卓高级研修班(网课)》9月班开始招生!顶尖技术、挑战极限、工资翻倍!

上传的附件:
最新回复 (74)
雪    币: 321
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
haras 活跃值 2009-6-27 13:54
2
0
写得好学习一下
雪    币: 310
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
HaIlDuZ 活跃值 4 2009-6-27 14:11
3
0
很强,支持源码附带。
雪    币: 213
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xgang 活跃值 2009-6-27 17:40
4
0
很不错,下载学习,多谢楼主分享。
雪    币: 1415
活跃值: 活跃值 (52)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
loudy 活跃值 10 2009-6-27 17:42
5
0
支持楼主分享
雪    币: 104
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
sethseth 活跃值 2009-6-27 18:11
6
0
果真是瞌睡就有人送枕头 谢过LZ
雪    币: 42
活跃值: 活跃值 (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
nevergone 活跃值 3 2009-6-27 21:40
7
0
顶一下 有源代码看看
雪    币: 226
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
黄庆南 活跃值 2009-6-27 21:53
8
0
谢谢,支持一下.
雪    币: 221
活跃值: 活跃值 (10)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
himcrack 活跃值 6 2009-6-27 22:04
9
0
没仔细看 是指可以抛弃ReadProcessMemory, WriteProcessMemory了么?
雪    币: 81
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
StNOe 活跃值 2 2009-6-27 23:20
10
0
是这样的,,,
雪    币: 849
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:310 )
在线值:
发帖
回帖
粉丝
yuansunxue 活跃值 6 2009-6-27 23:22
11
0
好文章 顶之
雪    币: 205
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
neverqq 活跃值 2009-6-27 23:41
12
0
不错,好文,学习
雪    币: 25
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
overdb 活跃值 2009-6-28 01:20
13
0
呵呵 不错 是我学习的对象, ,哎 现在还看不懂 我才第二阶段,学完了希望能像你一样强!学习
雪    币: 514
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
xacker 活跃值 1 2009-6-28 06:24
14
0
好复杂呀...      直接 KeStackAttachProcess目标  不是很方便吗?
雪    币: 107
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
大色狼 活跃值 2009-6-28 07:22
15
0
学习下,楼主你辛苦啦
雪    币: 7063
活跃值: 活跃值 (21)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
achillis 活跃值 15 2009-6-28 07:39
16
0

如果KeStackAttachProcess被XX了呢?光图方便可是不行的~
雪    币: 278
活跃值: 活跃值 (15)
能力值: ( LV12,RANK:470 )
在线值:
发帖
回帖
粉丝
zhuwg 活跃值 11 2009-6-28 08:36
17
0
进来学校1下PAE模式
雪    币: 290
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狼行wolf 活跃值 2009-6-28 09:42
18
0
好贴啊,占个位置仔细膜拜
雪    币: 40
活跃值: 活跃值 (31)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
creakerzgz 活跃值 1 2009-6-28 15:01
19
0
好文,顶之
雪    币: 253
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
o飘o 活跃值 1 2009-6-28 16:29
20
0
占位,方便查阅!
雪    币: 303
活跃值: 活跃值 (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
痞子辉 活跃值 1 2009-6-29 00:14
21
0
强大!!!!!
雪    币: 41
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
myyv 活跃值 2009-6-29 00:24
22
0
????????????????????????????
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bunker 活跃值 2009-6-29 00:29
23
0
看不懂..头
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kimpkok 活跃值 2009-6-29 15:23
24
0
不错的好文章,直接跳到内存分页去读取内存,好思路啊,学习学习
雪    币: 1372
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
binliao 活跃值 2009-6-29 15:59
25
0
有源码,练习一下。
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
CAPKI 活跃值 2009-7-1 10:23
26
0
支持一下,强烈支持!
雪    币: 194
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
gussing 活跃值 2009-7-1 12:54
27
0
我是初学者,有几个问题想请教:
                RtlCopyMemory((PVOID)pInfo->nMemoryAddr,
                    pWrite, pInfo->nWriteSize);
这一句之前已经用cli指令禁止中断了,那么执行内存拷贝过程中产生的page fault怎么处理?
另外,改变cr3前后的pInfo->nMemoryAddr同一个值代表的含义已经是不一样的吧?
我看Reacos里NtReadVirtualMemory的实现,它会在改变cr3前先生成一个MDL,改变后从该MDL里重新映射一个虚拟地址,所以改变cr3前后虽然虚拟地址的含义已经不同,但指向的物理地址还是同一个,
雪    币: 204
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
化学魔人 活跃值 2009-7-4 19:08
28
0
.......
自己切CR3是相当危险的,当page fault发生过后,关闭被读写的进程会memory management!!!!!!!
雪    币: 284
活跃值: 活跃值 (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jerrynpc 活跃值 2009-7-13 09:58
29
0
精品绝对的好文章 +1

Mark
雪    币: 144
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
modi 活跃值 2009-7-13 19:09
30
0
多谢共享...
雪    币: 1470
能力值: (RANK:210 )
在线值:
发帖
回帖
粉丝
bithaha 活跃值 5 2009-7-14 01:08
31
0
又一个悲剧
太针对了.
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
higher 活跃值 2009-7-14 08:37
32
0
比较深,不适合我,看不懂
雪    币: 206
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
artspring 活跃值 2009-7-14 21:45
33
0
写得不错,深入浅出,再怎么保护也不能对裸内存进行保护.
雪    币: 49
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
方圆科技 活跃值 3 2009-7-16 12:59
34
0
很不错。。。我先膜拜,再学习
雪    币: 177
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wormz 活跃值 2009-7-17 10:54
35
0
虚地址转换物理地址也在你的代码中没体现啊,
ReadPageDirEntryXPAE没给出来代码来啊,
实际上在没开启PAE的情况下PDE存放的线性地址是在0xC0300000
开启后PDE存放的地址是0xC0600000,可以通过高11位当索引直接查找
雪    币: 46
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
挂挂 活跃值 2009-7-17 11:02
36
0
支持!!!

辛苦
雪    币: 81
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
StNOe 活跃值 2 2009-7-17 16:48
37
0
源码里有阿!
雪    币: 81
活跃值: 活跃值 (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
StNOe 活跃值 2 2009-7-17 17:14
38
0
在R3代码中的OnBnClickedReadRing3 函数里实现了虚拟地址转换物理地址,
ReadPageDirEntryXPAE这组函数只是读取计算出的相关物理地址的内容,发帖时并没有将其贴出来,你可以去R3代码的源码里看看,
你说的没体现,应该另一种方法,直接切换CR3,读内存.而与这组ReadPageDirEntryXPAE相关的,是通过CR3的,转换虚拟地址到物理地址,读物理内存获得内容的.你再仔细看看源码.
雪    币: 509
活跃值: 活跃值 (10)
能力值: ( LV12,RANK:220 )
在线值:
发帖
回帖
粉丝
xiep 活跃值 5 2009-8-14 10:30
39
0
雪    币: 99
活跃值: 活跃值 (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
twoseconds 活跃值 2009-8-14 13:35
40
0
果然大年。。顶。。。
雪    币: 210
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
其他符号 活跃值 2009-8-14 15:50
41
0
谁能给个调用的源码~
雪    币: 251
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
leftup 活跃值 2009-8-15 17:27
42
0
#pragma alloc_text(PAGE, DispatchDeviceControl))
代码是 paged code
但是却进行 关中断  切换CR3等操作,最有可能的蓝屏代码是 Irql XXXX 或者 Paged Code in Nonpaged Area之类的

WriteMemoryInfo *pInfo =
                    (WriteMemoryInfo *)ExAllocatePool(PagedPool, sizeof(WriteMemoryInfo));
同样在关中断时访问paged pool

另外用户态的地址空间是随时会失效的,不能随便读写
写的时候,关了中断,exception handler 没意义,该蓝屏的时候照样蓝屏
读的时候发生缺页可能不会蓝屏,但是如果这个虚拟地址已经释放掉了,会发生异常,CR3不会被恢复回来,最好的结果是用户态的非法操作。

还有比较有意思的是,假如你刚切换完CR3系统就调度其他线程了,回来后你读的是自己的地址空间。

另外从2003SP1开始貌似\\Device\\PhysicalMemory不再能从用户态用名称打开了
只能由内核态弄个handle给用户态,打开PhysicalMemory还要注意不要造成cache种类不一致
不过对映射到用户态的内存一般没什么问题

还有些问题比如没检查用户态提供的Buffer长度就访问

总之感觉问题不少,主要是同步和Paged/Nonpaged 方面的问题
可以试试弄个checked build 的windows 或者driver verifier
看看 :)
雪    币: 532
活跃值: 活跃值 (15)
能力值: ( LV9,RANK:260 )
在线值:
发帖
回帖
粉丝
Fypher 活跃值 4 2009-8-18 08:30
43
0
看到过类似的,来个传送门:http://bbs.pediy.com/showthread.php?t=64938
雪    币: 244
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yuxuegong 活跃值 2009-9-1 01:03
44
0
虽然现在看不懂 但是我认为我一定会搞懂的
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
HUANGPAN 活跃值 2009-9-1 09:02
45
0
慢慢研究 先收藏了~~
我正开始做..就有成品咯·~感谢LZ
雪    币: 243
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
amour 活跃值 2009-9-6 22:12
46
0
顶楼主,看来科锐真不是盖的啊
雪    币: 201
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wudaicai 活跃值 2009-9-10 21:24
47
0
很长,很长,对不起啊我看不懂。
雪    币: 306
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
haiyazzff 活跃值 2009-9-12 20:47
48
0
很强,支持源码附带
雪    币: 112
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
不死小尧 活跃值 2009-9-12 21:29
49
0
狂暴膜拜中
雪    币: 204
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
化学魔人 活跃值 2009-9-13 17:54
50
0
会蓝的,ethread中的eprocess没切过来
游客
登录 | 注册 方可回帖
返回