Archive for the ‘Windows’ Category

内存访问

代码访问内存是通过古老的段+偏移的方式确定内存地址(逻辑地址--->线性地址),保护模式下段寄存器中保存的并不是段的基址,而是16位的段选择子,由段描述符表的索引号(即高13位,低3位置0时就是偏移量了)+1位 TI+2位RPL组成。其中CS寄存器的低两位保存着当前正在执行的代码所在的段的特权级(CPL),而段描述符表中又保存着DPL,因此用户空间和系统空间得以分离。举例来说,Ring3下某进程访问Ring0中的数据,CPU会先从CS寄存器中取得CPL=3,然后比较要访问的数据所在段的段描述符DPL=0,当不满足CPL<=DPL时,为访问违例。

CPU取指也需要访问内存,但应该不会通过段寄存器--->段描述符表--->比较CPL和DPL这么复杂,而是由硬件完成,因此独立的一段代码段应该在一致CPL/RPL中。要跳转到非一致的代码段必须通过系统机制(【原创】rootkit ring3进ring0之门系列[一] -- 调用门【求助】关于异常发生后保护模式下权限转移疑惑)。

段选择子

用比喻类比说明CPU的特权级DPL - CPL - RPL

段描述符伪代码:

union
{
    struct
    {
        unsigned short Segment Limit 0...15
        unsigned short Base Address 0...15
    }
    int 32
}
union
{
    struct
    {
        unsigend char Base Address 16...23
        unsigend char TYPE 4bit/S 1bit/DPL 2bit/P 1bit (先定义的在低位)
        unsigend char Segment Limit 16...19 4bit/AVL 1bit/Reserved 1bit/D/B 1bit/G 1bit (先定义的在低位)
        unsigend char Base Address 24...31
    }
    int 32
}

段描述符

#逻辑地址—>线性地址—>物理地址

#逻辑地址--->线性地址--->物理地址
http://blog.csdn.net/do2jiang/article/details/4512417
http://hi.baidu.com/iaaie/blog/item/3b34ce26266c403cc9955900.html

逻辑地址--->线性地址:Intel为了向后兼容其段式内存管理而设计,Windows虚拟内存空间中的地址即逻辑地址,Windows将逻辑地址到线性地址的映射设计为线性关系,只使用段地址进行GDT和LDT的选择,及访问控制。其GDTR、LDTR寄存器中保存的是线性地址。

线性地址--->物理地址:Intel页式管理,CR3寄存器中保存的是物理地址。

一次转译过程:程序中访问某地址(逻辑地址)--->查GDT(假设是GDT),GDTR中保存的是线性地址,因此也要查询其物理地址--->CR3中是物理地址,因此能定位页目录表的物理地址--->PDE(前20位)中存放是PTE的物理地址,因此能查询到GDTR的物理地址。剩下的不写了。

关于句柄表

记得《Windows核心编程》中说过,一个进程的句柄直接给另一个进程使用很有可能会出错,因为句柄就是个索引值嘛,可能在另一个进程中这个索引值就指向它打开的其它内核对象了。

悲催的没仔细研究,想当然的认为句柄值应该是从小到大,根据打开内核对象的次序依次分配的。尤其是在父进程创建子进程的过程中,父进程可继承的句柄值应该先挑出来,然后在子进程中依次重新分配。结果不然。假设父进程有512个句柄值,只有第512个句柄值可继承,那么子进程中该句柄值还是512*4(之前我想当然的以为是子进程初始句柄值+4,即能分配的最小的句柄值)!也就是说从父进程中继承来的句柄,其索引值在子进程中是不会变的!

Debug

对调试目标进程是被其他进程拉起的时候很有效果,如IE、FireFox插件。

GetKeyState的疑惑

#include "stdafx.h"
#include <Windows.h>
int main()
{
    int i = 0;
    while(1)
    {
        if(GetKeyState('A') < 0)
        {
            //VK_CONTROL
            //printf("Ctrl down: %d!\n", ++i);
            printf("A down: %d!\n", ++i);
        }
        //Sleep(1000);
    }
    return 0;
}

用GetKeyState来截获密码等好像不太实际,如果在死循环中Sleep就可能漏掉信息,如果不Sleep你会发现按一次键能得到N次这个键的信息。

疑惑是GetKeyState好像取不到WH_KEYBOARD_LL Hook后的键信息?

无觅相关文章插件,快速提升流量