首页
社区
课程
招聘
[讨论]谁可以解读一下ProbeForWrite
发表于: 2012-11-28 01:13 10402

[讨论]谁可以解读一下ProbeForWrite

2012-11-28 01:13
10402
一直看网上说这是检测用户模式缓冲区是否可写的,但是看了WRK却发现自己没读懂多少。
希望有人能,系统的,具体的介绍一下ProbeForWrite的代码,以及其存在的必要:
ProbeForWrite (
    __inout_bcount(Length) PVOID Address,
    __in SIZE_T Length,
    __in ULONG Alignment
    )

/*++

Routine Description:

    This function probes a structure for write accessibility and ensures
    correct alignment of the structure. If the structure is not accessible
    or has incorrect alignment, then an exception is raised.

Arguments:

    Address - Supplies a pointer to the structure to be probed.

    Length - Supplies the length of the structure.

    Alignment - Supplies the required alignment of the structure expressed
        as the number of bytes in the primitive datatype (e.g., 1 for char,
        2 for short, 4 for long, and 8 for quad).

Return Value:

    None.

--*/

{

    ULONG_PTR EndAddress;
    ULONG_PTR StartAddress;

#define PageSize PAGE_SIZE

    //
    // If the structure has zero length, then do not probe the structure for
    // write accessibility or alignment.
    //

    if (Length != 0) {

        //
        // If the structure is not properly aligned, then raise a data
        // misalignment exception.
        //

        ASSERT((Alignment == 1) || (Alignment == 2) ||
               (Alignment == 4) || (Alignment == 8) ||
               (Alignment == 16));  //如果对齐值为其中的一个,则不产生断言

        StartAddress = (ULONG_PTR)Address;
        if ((StartAddress & (Alignment - 1)) == 0) {  //判断StartAddress是否为0地址打头(根据字节对齐指定多少位0)

            //
            // Compute the ending address of the structure and probe for
            // write accessibility.
            //

            EndAddress = StartAddress + Length - 1; //获得缓冲区的最后一个字节地址
            if ((StartAddress <= EndAddress) &&
                (EndAddress < MM_USER_PROBE_ADDRESS)) { //如果是合法用户地址

                //
                // N.B. Only the contents of the buffer may be probed.
                //      Therefore the starting byte is probed for the
                //      first page, and then the first byte in the page
                //      for each succeeding page.
                //
                // If this is a Wow64 process, then the native page is 4K, which
                // could be smaller than the native page size/
                //

                EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize; //这里开始就不懂了。PageSize = 0,(EndAddress & ~(0x1000 - 0x1)) -> (EndAddress & 0)   result = 0 + PageSize?EndAddress == 0x1000????。。。
                do {
                    *(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
                    StartAddress = (StartAddress & ~(PageSize - 1)) + PageSize;
                } while (StartAddress != EndAddress); //这里为什么死都要让StratAddress == EndAddress,那么不就等于Length = NULL了么。这样缓冲区的长度传进来代表什么。

                return;

            } else {
                ExRaiseAccessViolation();
            }

        } else {
            ExRaiseDatatypeMisalignment();
        }
    }

    return;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (9)
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
这样没错啊
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize; 正如其名,end,表示地址结束

*(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;这句的话,读入这个地址的内容
复制给自己,如果地址不存在,发生异常,地址存在的话,里面的数据什么也没变,因为是自己写自己啊

while (StartAddress != EndAddress);,查看起始地址是否等于结束地址,如果不等,就继续循环~
2012-11-28 09:54
0
雪    币: 558
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize; 


这个的意思是内存对齐,(如果 EndAddress大小为1个字节, PageSize为512字节,这样对齐以后,EndAddress 就等于512了)

至于这句
*(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;

你是不是写错了,没看明白什么意思,一直 *StartAddress = *StartAddress ?赋值没变化啊,不知道怎么退出while循环
2012-11-28 09:55
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize;初始化结束地址

while (StartAddress != EndAddress);对比当前地址指针是否指向结束地址,如果不等,继续循环
2012-11-28 09:58
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize; 这句我的理解是修正
结束地址,具体修正法,可能是要为页的倍数吧

*(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
这句你貌似理解错了,就是这样啊,StartAddress是地址指针,读入StartAddress的内容,再赋值给
他自己,如果这个StartAddress地址不存在,会触发异常,然后下面的就有捕获异常
,赋值不会变化的,如果变化了,那不是改写了内存,那么这个函数就不是试探内存是否可写了
2012-11-28 10:14
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
这里的对齐与我所学的结构对齐似乎有点不同,看您在线,可否举个通俗易懂的例子说明一下为什么需要这样对齐?
2012-11-28 11:16
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
7
嗯,这里的意思似乎是从StartAddress开始的地址一直读到本页的页尾,读到页尾以后指针自然指向下一个页的第一个字节,不明白这里传入的对齐值有何意义。
2012-11-28 11:25
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
8
还有就是
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize;
do {
*(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
StartAddress = (StartAddress & ~(PageSize - 1)) + PageSize;
} while (StartAddress != EndAddress);
那不是只访问了StartAddress的第一个字节StartAddress不就等于EndAddress了么。
为什么我总觉得这个函数是在测试缓冲区所在的几个页是否可写。
2012-11-28 11:55
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize;
do {
*(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
StartAddress = (StartAddress & ~(PageSize - 1)) + PageSize;
} while (StartAddress != EndAddress);

的确是在检测  StartAddress   到StartAddress   +length  所在那几个页面的 可写性(只检测每个页面的第一个字节,就代表了整个页面读写属性)

StartAddress 每次移动到下一个页面的第一个字节
2013-9-21 01:57
0
雪    币: 2332
活跃值: (3799)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
10
EndAddress = (EndAddress & ~(PageSize - 1)) + PageSize;
do {
*(volatile CHAR *)StartAddress = *(volatile CHAR *)StartAddress;
StartAddress = (StartAddress & ~(PageSize - 1)) + PageSize;
} while (StartAddress != EndAddress);
首先Windows管理分页内存,以页为单位,每个内存页都有自己的属性.
如果一个内存页的第一个字节可写,那么整个内存页就可写.

然后(xxx & ~(PageSize - 1)) + PageSize,为对齐内存页.
这个循环是有结束条件的,因为测试只需要以页为单位,所以内存需要以页的长度增长:
StartAddress = (StartAddress & ~(PageSize - 1)) + PageSize;
正好为当前页的起始地址 + 页长度.
这也就是为什么,死也要StartAddress != EndAddress.
因为如果内存是以页长度为增长单位,每一个页都要测试是否有读/写权限.那么很明显,肯定要测试到最后一页内存才可以.
2013-9-21 05:37
0
游客
登录 | 注册 方可回帖
返回
//