查看: 164|回复: 2

[原创图文] 内核学习-保护模式阶段性检测

[复制链接]

11

主题

30

帖子

1

精华

中级会员

Rank: 8Rank: 8

学币
63
荣耀
0
rank
0
违规
0
发表于 2020-7-16 11:25:17 | 显示全部楼层 |阅读模式
1. 给定一个线性地址,和长度,读取内容;
int ReadMemory(OUT BYTE* buffer,IN DWORD dwAddr,IN DWORD dwLeght)
要求:
1) 可以自己指定分页方式。
2) 页不存在,要提示,不能报错。
3) 可以正确读取数据。
#include <windows.h>
#include <stdio.h>

//eq 8003f090 0040EC05`000810
DWORD PTE;
DWORD PDE;
DWORD DwAddr;
DWORD DwLeght;
BYTE* Buff;
BOOL _MAXPage = 0;
BOOL _TockPage = 0;
BOOL _P_Flafge = 0;
BOOL _PAT_Flage = 0;
VOID _declspec(naked) Start()
{
        //获取参数
        __asm
        {
                lea eax, dword ptr ds : [esp+0x8]

                mov esi, dword ptr ds : [eax+0*4]
                mov dword ptr ds : [Buff],esi

                mov esi, dword ptr ds : [eax+1*4]
                mov dword ptr ds : [DwLeght],esi

                mov esi, dword ptr ds : [eax+2*4]
                mov dword ptr ds : [DwAddr],esi

                mov esi, dword ptr ds : [eax+3*4]
                mov dword ptr ds : [PTE],esi

                mov esi, dword ptr ds : [eax+4*4]
                mov dword ptr ds : [PDE],esi
        }
        __asm
        {
                mov eax, dword ptr ds : [PDE]
                mov ecx, dword ptr ds : [eax]

                //检测PDE P位
                test cl,0x1
                jz Pflage_Nop

                //检测PDE PS位
                test cl,0x80
                jz Nops
                                //检测是否跨页
                                mov dword ptr ds : [_MAXPage], 0x1
                                mov eax, dword ptr ds:[DwAddr]
                                and eax,0x00000FFF
                                mov ecx, dword ptr ds : [DwLeght]
                                add eax,ecx
                                cmp eax,0x00001000
                                jns steppage 
                                jmp nosteppage
                Nops: //小页
                                mov eax, dword ptr ds : [PTE]
                                mov ecx, dword ptr ds : [eax]

                                //检测PTE P位
                                test cl,0x1
                                jz Pflage_Nop

                                //检测PTE PAT位
                                test cl,0x80
                                jnz PatFlage_Code

                                //检测是否跨页
                                mov eax, dword ptr ds : [DwAddr]
                                and eax, 0x00000FFF
                                mov ecx, dword ptr ds : [DwLeght]
                                add eax, ecx
                                cmp eax, 0x00001000
                                jns steppage
                                jmp nosteppage

        }

steppage:  //读取的内存地址跨页执行代码
        __asm
        {
                //每读取1字节就检测P位,防止跨页的线性地址没有物理页导致CPU报错 -- 根据大页还是小页检测

                //大页:读取时只检测PDE P位
                mov eax, dword ptr ds : [_MAXPage]
                test al,0x1
                jz Small_Page_Code
                        push ebp
                        mov ebp, esp
                        sub esp, 0x20
                        mov dword ptr ss : [ebp - 0x4], 0x0
                        JMP while_b_F
                        while_a_F :
                                mov eax, dword ptr ds : [DwAddr]
                                mov esi, dword ptr ds : [ebp - 0x4]
                                mov edi,eax
                                add edi,esi
                                mov ecx,edi
                                shr ecx,0x12
                                and ecx,0X3FF8
                                sub ecx,0X3FA00000
                                mov dword ptr ss : [ebp-0x8],ecx
                                mov ecx,edi
                                shr ecx,0x9
                                and ecx,0x7FFFF8
                                sub ecx,0x40000000
                                mov dword ptr ss : [ebp-0xC],ecx
                                mov ecx, dword ptr ds : [ebp-0x8]
                                mov ecx, dword ptr ds : [ecx]
                                test cl,0x1  //检测PDE P位
                                jz _FL

                                mov eax, dword ptr ds : [DwAddr]
                                mov esi, dword ptr ds : [ebp - 0x4]
                                xor ecx,ecx
                                mov cl, byte ptr ds : [eax + esi]
                                mov eax, dword ptr ds : [Buff]
                                mov byte ptr ds : [eax + esi], cl
                                mov ecx, dword ptr ds : [ebp - 0x4]
                                add ecx, 0x1
                                mov dword ptr ds : [ebp - 0x4], ecx
                        while_b_F :
                                mov eax, dword ptr ds : [DwLeght]
                                mov ecx, dword ptr ds : [ebp - 0x4]
                                cmp ecx, eax
                                js while_a_F
                                jmp _FL
                        
                //小页:读取时检测PDE和PTE P位
                Small_Page_Code:
                                push ebp
                                mov ebp, esp
                                sub esp, 0x20
                                mov dword ptr ss : [ebp - 0x4], 0x0
                                JMP while_b_T
                        while_a_T :
                        mov eax, dword ptr ds : [DwAddr]
                                mov esi, dword ptr ds : [ebp - 0x4]
                                mov edi, eax
                                add edi, esi
                                mov ecx, edi
                                shr ecx, 0x12
                                and ecx, 0X3FF8
                                sub ecx, 0X3FA00000
                                mov dword ptr ss : [ebp - 0x8], ecx
                                mov ecx, edi
                                shr ecx, 0x9
                                and ecx, 0x7FFFF8
                                sub ecx, 0x40000000
                                mov dword ptr ss : [ebp - 0xC], ecx
                                mov ecx, dword ptr ds : [ebp - 0x8]
                                mov ecx, dword ptr ds : [ecx]
                                test cl, 0x1  //检测PDE P位
                                jz _FL
                                mov ecx, dword ptr ds : [ebp-0xC]
                                mov ecx, dword ptr ds : [ecx]
                                test cl,0x1        //检测PTE P位
                                jz _FL

                                xor ecx,ecx
                                mov eax, dword ptr ds : [DwAddr]
                                mov esi, dword ptr ds : [ebp - 0x4]
                                mov cl, byte ptr ds : [eax + esi]
                                mov eax, dword ptr ds : [Buff]
                                mov byte ptr ds : [eax + esi], cl
                                mov ecx, dword ptr ds : [ebp - 0x4]
                                add ecx, 0x1
                                mov dword ptr ds : [ebp - 0x4], ecx
                        while_b_T :
                                mov eax, dword ptr ds : [DwLeght]
                                mov ecx, dword ptr ds : [ebp - 0x4]
                                cmp ecx, eax
                                js while_a_T
                _FL:
                mov dword ptr ds : [_TockPage], 0x1
                mov eax, dword ptr ds : [ebp - 0x4]
                leave
                jmp _Retf
        }
nosteppage://读取的内存地址无需跨页执行代码
        __asm
        {
                //直接读取DwLeght个字节到缓冲区
                push ebp
                        mov ebp, esp
                        sub esp, 0x20
                        mov dword ptr ss : [ebp - 0x4], 0x0
                        JMP while_b
                while_a :
                mov eax, dword ptr ds : [DwAddr]
                        mov esi, dword ptr ds : [ebp - 0x4]
                        mov cl, byte ptr ds : [eax + esi]
                        mov eax, dword ptr ds : [Buff]
                        mov byte ptr ds : [eax + esi], cl
                        mov ecx, dword ptr ds : [ebp - 0x4]
                        add ecx, 0x1
                        mov dword ptr ds : [ebp - 0x4], ecx
                while_b :
                mov eax, dword ptr ds : [DwLeght]
                        mov ecx, dword ptr ds : [ebp - 0x4]
                        cmp ecx, eax
                        js while_a
                        mov eax, dword ptr ds : [ebp - 0x4]
                        leave
                        JMP _Retf
        }
Pflage_Nop: //P位无效
        __asm
        {
                mov dword ptr ds : [_P_Flafge],0x1
                xor eax,eax
                jmp _Retf
        }
PatFlage_Code: //PAT位为1执行代码
        __asm
        {
                mov dword ptr ds : [_PAT_Flage],0x1
                xor eax, eax
                jmp _Retf
        }


_Retf:
        __asm
        {
                retf 0x14
        }
}

DWORD MyReadMemory(OUT BYTE* Buff, IN DWORD DwAddr, IN DWORD DwLeght)
{
        unsigned int PDE = DwAddr >> 0X12;
        PDE &= 0X3FF8;
        PDE -= 0X3FA00000;
        unsigned int PTE = DwAddr >> 0x9;
        PTE &= 0x7FFFF8;
        PTE -= 0X40000000;
        BYTE RunCode[6] = { 0 };
        RunCode[4] = 0x93;
        BOOL RetCode;
        __asm
        {
                push PDE
                push PTE
                push DwAddr
                push DwLeght
                push Buff
                call fword ptr ds : [RunCode]
                mov dword ptr ds : [RetCode],eax
        }
        return RetCode;
}
VOID main()
{
        BYTE Buff[20] = { 0 };
        CHAR* Str = "Hello 你好?";
        DWORD _ReadSize = MyReadMemory(Buff, 0x8003fffe, 4);
        printf("是否大页:%X -- 是否跨段:%X -- P位:%X  PAT位:%X\r\n", _MAXPage, _TockPage, _P_Flafge, _PAT_Flage);
        if (_ReadSize)
        {

                printf("%X -- %d\r\n", *(DWORD*)Buff,_ReadSize);
        }
        else
        {
                printf("读取失败\r\n");
        }
        getchar();
}
2. 申请长度为100的DWORD的数组,且每项用该项的地址初始化;
把这个数组所在的物理页挂到0x1000的地址上;
定义一个指针,指向0x1000这个页里的数组所在的地址,用0x1000这个页的线性地址打印出这数组的值;

要求:
数组所在的物理页,是同一个页;

#include <windows.h>
#include <stdio.h>

VOID _declspec(naked) Start()
{
        DWORD Address_1;
        DWORD Address_2;
        unsigned int _Address_1_PTE;
        unsigned int _Address_2_PTE;
        __asm
        {
                mov eax, dword ptr ds : [esp+0x8]
                mov dword ptr ds : [Address_1], eax
        }
        Address_2 = 0x1000;
        _Address_1_PTE = Address_1 >> 0x9;
        _Address_1_PTE &= 0x7FFFF8;
        _Address_1_PTE -= 0x40000000;
        _Address_2_PTE = Address_2 >> 0x9;
        _Address_2_PTE &= 0x7FFFF8;
        _Address_2_PTE -= 0x40000000;

        __asm
        {
                mov eax,dword ptr ds : [_Address_1_PTE]
                mov ecx, dword ptr ds : [eax]
                mov edx, dword ptr ds : [_Address_2_PTE]
                mov dword ptr ds : [edx],ecx
        }

        __asm
        {
                retf 0x4
        }

}
//eq 8003f090 0040EC01`00081000
VOID main()
{
        DWORD Address = (DWORD)VirtualAlloc(NULL, 400, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        BYTE RunCode[6] = {0};
        RunCode[4] = 0x93;
        if ((Address & 0x00000FFF) > 0x0)
        {
                printf("申请内存失败\r\n");
        }
        else
        {
                DWORD* Address_p = (DWORD*)Address;
                for (DWORD _index = 0; _index < 100; _index++)
                {
                        *(Address_p+_index) = _index;
                }
                __asm
                {
                        push Address;
                        call fword ptr ds : [RunCode]
                }

                DWORD* P = (DWORD*)0X1000;
                for (DWORD _index = 0; _index < 100; _index++)
                {
                        printf("%X\r\n",*(P + _index));
                }
        }

        VirtualFree((LPVOID)Address, 400, MEM_DECOMMIT);
        getchar();
}


温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的最好奖励,还可以获得学币奖励,请尊重作者的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
学逆向论坛-免费的逆向学习论坛

3

主题

13

帖子

2

精华

初级会员

Rank: 4

学币
39
荣耀
0
rank
122
违规
0
发表于 2020-7-20 00:58:09 | 显示全部楼层
超棒的哇,学习了。
学逆向论坛-免费的逆向学习论坛

0

主题

33

帖子

0

精华

中级会员

Rank: 8Rank: 8

学币
93
荣耀
0
rank
0
违规
0

    发表于 3 天前 | 显示全部楼层
    用心讨论,共获提升!
    学逆向论坛-免费的逆向学习论坛
    微信公众号
    快速回复 返回顶部 返回列表