12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 173|回复: 0

11.10-10-12分页(Win7 x86)

[复制链接]
发表于 2022-1-28 21:45:24 | 显示全部楼层 |阅读模式
章节介绍

  • Win7 x86 设置10-10-12分页.
  • windows与Intel管理物理页规则,以及Windows内存分区.
  • 10-10-12分页规则及其由来.
  • 通过线性地址查找对应物理地址.
  • 共享内存实现原理.
  • 0地址访问错误原因,常量区无法修改原因,高2G内存R3访问失败起因于物理页属性限定.
  • PDE,PTE属性探测,基址探测(MmIsAddressValid).
  • 代码示例0线性地址挂物理页,0线性地址实现SHELLCODE.
0.Win7 x86设置10-10-12分页

CMD:关闭指令(开启10-10-12分页)                         bcdedit /set pae ForceDisable  bcdedit /set nx AlwaysOff      开启指令(开启2-9-9-12分页)bcdedit /set pae forceEnablebcdedit /set nx OptIn 分页内核文件目录: C:\Windows\System32

x86下每个进程都有假造4GB内存空间(x86下线性地址宽度为32位4字节,2^32为4GB(线性地址有4G但未必都能访问 高2G内存为所有进程共享)),x86下假造地址分别为:
内存区范围空指针赋值区0x00000000 - 0x0000FFFF用户模式区 0x00010000 - 0x7FFEFFFF64KB禁入区0x7FFF0000 - 0x7FFFFFFF内核0x80000000 - 0xFFFFFFFFintel amd规定一个最小物理页为4KB(一个物理页4096byte遍历每一个字节2^12这也就是分页最后12由来)
Windows规定一个最小物理页为64KB.
1.10-10-12分页规则


x86下每个进程有4GB线性地址空间,但是有些地址无法访问,这是由于线性地址对应物理地址为空大概对应物理页属性限定.代码示例:MOV EAX, DWORD PTR DS:[0x12345678]有效地址: 0x12345678线性地址: DS.BASE + 0x12345678物理地址: 10-10-12分页 通过高31-22位定位PDE,通过21-12位定位PTE,通过PTE指向基址 + 11-00位定位页内偏移每个进程都有一个CR3(CR3是一个寄存器,每个核心一个) CR3指向一个物理页(4KB),10-10-12分页模式下CR3指向PDT分页规则物理页: 4KB(4096BYTE) 10: PDE(4BYTE),物理页(4KB),一张物理页可以存储 4096 / 4 (1024),要遍历每一个PDE 2^1010: PTE(4BYTE),物理页(4KB),一张物理页可以存储 4096 / 4 (1024),要遍历每一个PTE 2^1012: 物理页(4KB),要遍历每一个字节 2^1210-10-12线性地址上限: 1024 * 1024 * 4096 4GB10-10-12物理地址上限: 2^32(物理地址宽度)   4GB同一进程内相同物理页 MOV EAX, DWORD PTR DS:[0x12345FFF] MOV EAX, DWORD PTR DS:[0x12345EEE] 线性地址前20位(PDE PTE)决定在哪张物理页,后12位(OFFSET)决定页内偏移 PTE规则PTE可以没有物理页,且只能对应一个物理页.多个PTE也可以指向同一个物理页.  1.1 通过线性地址查找对应物理地址

#include #include int main(){        DWORD num = 0x64;        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num, num);        system("pause");        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num, num);        system("pause");        return 0;}
有效地址为: 0x0012ff44
线性地址为: 0x0012ff44 + SS.Base(0)
线性地址转为二进制: 0000 0000 0001 0010 1111 1111 0100 0100
10: 00 0000 0000 0h PDE
10: 01 0010 1111 12Fh PTE
12: 1111 0100 0100 F44h OFFSET
通过Windbg手动检察:
1).通过!process 0 0查找进程CR3

DirBase = Cr3 = PDT.Base = 0x28e43000
*2).查找PDE(巨细4字节)(PDT(页目录表基址) + PDI(页目录项索引) 4)**
!dd(4Byte方式)检察物理地址

*3).查找PTE(巨细4字节)(PTT(页表基址) + PTI(页表项索引) 4)**
查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

5).修改物理页数据(!ed指令)


1.2 申请内存挂物理页过程

#include #include int main(){        PVOID lp = VirtualAlloc(NULL,0x64,MEM_COMMIT,PAGE_EXECUTE_READWRITE);        if (!lp)        {                printf("VirtualAlloc Fail \r\n");                getchar();        }        printf("mem addr -> 0x%08x \r\n",lp);        system("pause");        memset(lp,0xFF,4);        system("pause");        return 0;}
有效地址为: 0x001c0000
线性地址为: 0x001c0000 + SS.Base(0)
线性地址转为二进制: 0000 0000 0001 1100 0000 0000 0000 0000
10: 00 0000 0000 0h PDE
10: 01 1100 0000 1C0h PTE
12: 0000 0000 0000 0h OFFSET
通过Windbg手动检察:
1).通过!process 0 0查找进程CR3

DirBase = Cr3 = PDT.Base = 0x77990000
*2).查找PDE(巨细4字节)(PDT(页目录表基址) + PDI(页目录项索引) 4)**
!dd(4Byte方式)检察物理地址

*3).查找PTE(巨细4字节)(PTT(页表基址) + PTI(页表项索引) 4)**
查找需要将PDE后12位抹除(为PDE属性)

3).执行初始化内存代码

*4).查找PTE(巨细4字节)(PTT(页表基址) + PTI(页表项索引) 4)**
查找需要将PDE后12位抹除(为PDE属性)

6).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

使用virtualalloc函数在申请内存乐成情况下假如不初始化将不会被挂有效物理页
1.3 什么是共享内存?(多个线性地址共用一个或多个物理页)

进程A代码
#include #include int main(){        int num = 1;        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num , num);        system("pause");        printf("numaddr -> 0x%08x numdata -> 0x%08x \r\n",&num , num);        system("pause");        return 0;}进程B代码
#include #include int main(){        system("pause");        printf("0data -> 0x%08x \r\n",*(LPDWORD)(0 + 0xf44));        *(LPDWORD)(0 + 0xf44) = 0xffffffff;        system("pause");        return 0;}1).打开进程A检察变量所对应物理地址


2).打开进程B给0线性地址挂物理页

3).执行进程B剩余代码

4).执行进程A剩余代码
进程B代码执行后将会同时修改进程A变量数据,由于此时指向同一张物理页且页内偏移相同

数据被乐成修改
2.10-10-12分页PDE PTE属性探测

测试代码使用内核函数MmIsAddressValid实现原理后文将分析
假如代码执行后不生效TLB(后需章节介绍)没有刷新,切换进程或打开新进程后在运行


2.1 P位

P = 1 有效的物理页
P = 0 无效的物理页
#include #include DWORD g_Data = 0x12345678;DWORD g_offs = (DWORD)&g_Data & 0xFFF;DWORD g_PDE = 0;DWORD g_PTE = 0;_declspec(naked) VOID ChangePTEAttribute(){  __asm  {    //获取g_Data线性地址    lea ecx, g_Data    //获取PDE    mov eax, ecx    shr eax, 0x14    and eax, 0xFFC    sub eax, 0x3FD00000    mov eax, [eax]    mov g_PDE, eax    //PDE->P    test al, 1    jz END    //获取PTE    mov eax, ecx    shr eax, 0xA    and eax, 0x3FFFFC    sub eax, 0x40000000    mov eax, [eax]    mov g_PTE, eax    //PTE->P    test al, 1    jz END    //获取0线性地址    mov ecx, 0    //0线性地址挂PTE    mov eax, ecx    shr eax, 0xA    and eax, 0x3FFFFC    sub eax, 0x40000000    mov edx, g_PTE    mov [eax], edxEND:    iretd  }}int main(){        printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);        printf("ADDR [0x%08x]  DATA [0x%08x] OFFS [0x%03x]  \n",&g_Data, g_Data, g_offs);          system("Pause");        __asm        {                //通过中断门提权给0线性地址挂物理页                //eq 80b99500 0040ee00`00081005                INT 0x20        }        //中断门执行返回后 0线性地址与g_Data变量地址对应的为同一张物理页        *(LPDWORD)(0 + g_offs) = 0xFFFFFFFF;         printf("ADDR [0x%08x]  DATA [0x%08x] OFFS [0x%03x]  \n",&g_Data, g_Data, g_offs);        system("Pause");        return 0;}
变量地址为: 0x00412030 转换为二进制 0000 0000 0100 0001 0010 0000 0011 0000
按照10-10-12分页格式转换:
10:00 0000 0001 001h PDE
10:00 0001 0010 012h PTE
12:0000 0011 0000 030h OFFSET
通过Windbg手动检察:
1).通过!process 0 0查找进程CR3

DirBase = Cr3 = PDT.Base = 0x0a207000
*2).查找PDE(巨细4字节)(PDT(页目录表基址) + PDI(页目录项索引) 4)**
!dd(4Byte方式)检察物理地址

*3).查找PTE(巨细4字节)(PTT(页表基址) + PTI(页表项索引) 4)**
查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

变量线性地址0x00412030对应物理地址为:#44c94030
0线性地址默认不可访问是由于没有挂有效物理地址

上述代码执行完毕后将0线性地址对应物理地址改为变量所对应物理地址,即0线性地址此时存在有效物理页
2.2 R/W位

R/W = 0 只读
R/W = 1 可读可写
#include #include CHAR* Data = "HHHHHH";DWORD g_PDE = 0;DWORD g_PTE = 0;_declspec(naked) VOID ChangePTEAttribute(){  __asm  {    //获取线性地址    mov ecx, Data    //获取PDE    mov eax, ecx    shr eax, 0x14    and eax, 0xFFC    sub eax, 0x3FD00000    mov eax, [eax]    mov g_PDE, eax    //PDE->P    test al, 1    jz END    //获取PTE    mov eax, ecx    shr eax, 0xA    and eax, 0x3FFFFC    sub eax, 0x40000000    mov edx, [eax]    mov g_PTE, edx    //PTE->P    test dl, 1    jz END    //页属性修改可读可写    or dl, 2    mov [eax], edxEND:    iretd  }}int main(){  printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);  printf("ADDR [0x%08X] DATA [%s] \n",Data, Data);    system("Pause");  __asm  {          //通过中断门提权修改页属性          //eq 80b99500 0040ee00`00081005          INT 0x20  }  //默认情况Data[0]对应物理页属性为只读 通过修改可以改写  Data[0] = 'A';  printf("DATA [%s] PDE [0x%08x]  PTE [0x%08x]  \n",Data, g_PDE,g_PTE);  system("Pause");  return 0;}
变量地址为: 0x0041010C 转换为二进制 0000 0000 0100 0001 0000 0001 0000 1100
按照10-10-12分页格式转换:
10:00 0000 0001 001h PDE
10:00 0001 0000 010h PTE
12:0001 0000 1100 10Ch OFFSET
通过Windbg手动检察:
1).通过!process 0 0查找进程CR3

DirBase = Cr3 = PDT.Base = 0x492e8000
*2).查找PDE(巨细4字节)(PDT(页目录表基址) + PDI(页目录项索引) 4)**
!dd(4Byte方式)检察物理地址

*3).查找PTE(巨细4字节)(PTT(页表基址) + PTI(页表项索引) 4)**
查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

变量线性地址0x0041010C对应物理地址为:#3fe1d10c

常量字符串不可以修改是由于物理页属性限定修改R/W即可改写
2.3 U/S位

U/S = 0 特权用户
U/S = 1 普通用户
2G以上是内核才气访问的原因是U/S位的设置题目,假如将内核的某个页设置为1就可以在R3访问了.
0 1 2是系统环可以访问系统页和用户页0环是特权级环1, 2环固然不是特权级环 但是是系统环 3环是用户环 可以访问用户页.
#include #include DWORD g_PDE = 0;DWORD g_PTE = 0;_declspec(naked) VOID ChangePTEAttribute(){  __asm  {    //获取线性地址    mov ecx, 0x80b99008    //获取PDE    mov eax, ecx    shr eax, 0x14    and eax, 0xFFC    sub eax, 0x3FD00000    mov edx, [eax]    test dl, 1    jz END    or dl, 4    mov [eax], edx    mov g_PDE, edx    //获取PTE    mov eax, ecx    shr eax, 0xA    and eax, 0x3FFFFC    sub eax, 0x40000000    mov edx, [eax]    test dl, 1    jz END        //全局页修改G位        and edx, 0xFFFFFEFF    //修改U/S位    or dl, 4    mov [eax], edx    mov g_PTE, edxEND:    iretd  }}int main(){  printf("INTERRUPT ADDR [0x%08x]  \n",ChangePTEAttribute);  system("Pause");  __asm  {    //通过中断门提权修改页属性    //eq 80b99500 0040ee00`00081005    INT 0x20  }  printf("PDE [0x%08x]  PTE [0x%08x] \n",g_PDE,g_PTE);  //高2G空间默认为特权权限访问修改页属性后用户权限也可以访问  printf("DATA [0x%08x] \n",*(LPDWORD)0x80b99008);  system("Pause");  return 0;} 地址为: 0x80B99008 转换为二进制 1000 0000 1011 1001 1001 0000 0000 1000
按照10-10-12分页格式转换:
10:10 0000 0010 202h PDE
10:11 1001 1001 399h PTE
12:0000 0000 1000 008h OFFSET
通过Windbg手动检察:
1).通过!process 0 0查找进程CR3

DirBase = Cr3 = PDT.Base = 0x491ef000
*2).查找PDE(巨细4字节)(PDT(页目录表基址) + PDI(页目录项索引) 4)**
!dd(4Byte方式)检察物理地址

*3).查找PTE(巨细4字节)(PTT(页表基址) + PTI(页表项索引) 4)**
查找需要将PDE后12位抹除(为PDE属性)

4).查找线性地址对应物理地址(Physical Page + offset)
查找需要将PTE后12位抹除(为PTE属性)

线性地址0x80B99008对应物理地址为:#b99008

应用层不可以访问高2G内存是由于物理页属性限定修改U/S即可改写
2.4 PS位

只对PDE有意义
PS = 0 指向PTE

PS = 1 没有PTE 直接指向物理页 低22位是页内偏移 大页(2 ^ 22)4MB

2.5 A位

A = 0 未访问(读大概写)
A = 1 已访问(读大概写)
2.6 D位

D = 0 没有被写过
D = 1 被写过
3.PDT PTT基址


10-10-12分页模式1.页表被映射到了从0xC0000000到0xC03FFFFF的4M地址空间(1024PDE * 1024PTE * 4)2.在这1024个表中有一张特殊的表:页目录表3.页目录被映射到了0xC0300000开始处的4K地址空间0xc0300000 指向页目录表(PDT)0xc0000000 指向第一张页表(PTT)页目录表实在是一张特殊的页表,它是第0x300张页表。页目录表中每项PTE都指向一张页表,其中第0x300项指向了页目录表本身PDI(PDE INDEX) PTI(PTE INDEX)访问页目录表的公式:0xC0300000 + PDI * 4访问页表的公式:0xC0000000 + PDI * 4096 + PTI * 44.MmIsAddressValid(Win7 x86 10-10-12)

内核ntoskrnl.exe 10-10-12 分页
.text:0040A12A ; BOOLEAN __stdcall MmIsAddressValid(PVOID VirtualAddress).text:0040A12A                 public _MmIsAddressValid@4.text:0040A12A _MmIsAddressValid@4 proc near           ; CODE XREF: IopIsAddressRangeValid(x,x)+31↑p.text:0040A12A                                         ; IopGetMaxValidMemorySize(x,x)+29↓p ....text:0040A12A.text:0040A12A VirtualAddress  = dword ptr  8.text:0040A12A.text:0040A12A                 mov     edi, edi        ; 热补丁.text:0040A12C                 push    ebp.text:0040A12D                 mov     ebp, esp        ; 提升栈底.text:0040A12F                 mov     ecx, [ebp+VirtualAddress] ; ecx = 线性地址(Param).text:0040A132                 call    _MiIsAddressValid@8 ; MiIsAddressValid(x,x).text:0040A137                 pop     ebp             ; 恢复栈底.text:0040A138                 retn    4               ; 返回.text:0040A138 _MmIsAddressValid@4 endp.text:00489B98 ; __stdcall MiIsAddressValid(x, x).text:00489B98 _MiIsAddressValid@8 proc near           ; CODE XREF: MiMakeSystemAddressValidSystemWs(x,x)+E↑p.text:00489B98                                         ; MiMakeSystemAddressValidSystemWs(x,x)+10C↑p ....text:00489B98                 mov     eax, ecx        ; eax = 线性地址.text:00489B9A                 shr     eax, 14h        ; EAX右移20位 EAX >> 0x14.text:00489B9D                 and     eax, 0FFCh      ; (EAX >> 0x14) & 0xFFC(1111 1111 1100) == (EAX >> 0x16) * 4.text:00489BA2                 sub     eax, 3FD00000h  ; sub 0x3DF00000 = add 0xC0300000.text:00489BA2                                         ; 0xC0300000是页目录表被映射的起始线性地址.text:00489BA7                 mov     eax, [eax]      ; 取出PDE.text:00489BA9                 test    al, 1           ; 判断P位.text:00489BAB                 jnz     short loc_489BB0 ; 非0跳转即有效页.text:00489BAD.text:00489BAD loc_489BAD:                             ; CODE XREF: MiIsAddressValid(x,x)+32↓j.text:00489BAD                 xor     al, al          ; al置0.text:00489BAF                 retn                    ; 返回.text:00489BB0 ; ---------------------------------------------------------------------------.text:00489BB0.text:00489BB0 loc_489BB0:                             ; CODE XREF: MiIsAddressValid(x,x)+13↑j.text:00489BB0                 test    al, al          ; 判断PS.text:00489BB2                 jns     short loc_489BB7 ; al最高位是不为0跳转即小页跳转.text:00489BB4                 mov     al, 1           ; 大页al置1.text:00489BB6                 retn                    ; 返回.text:00489BB7 ; ---------------------------------------------------------------------------.text:00489BB7.text:00489BB7 loc_489BB7:                             ; CODE XREF: MiIsAddressValid(x,x)+1A↑j.text:00489BB7                 shr     ecx, 0Ah        ; ECX右移10位 ECX >> 0xA.text:00489BBA                 and     ecx, 3FFFFCh    ; (ECX >> 0xA) & 0x3FFFFC = PDI * 4096 + PTI * 4.text:00489BC0                 sub     ecx, 40000000h  ; sub 0x40000000 = add 0xC0000000.text:00489BC0                                         ; 0xC0000000是页表被映射的起始线性地址.text:00489BC6                 mov     eax, [ecx]      ; 取出PTE.text:00489BC8                 test    al, 1           ; 判断P位.text:00489BCA                 jz      short loc_489BAD ; P = 0无效页跳转返回.text:00489BCC                 and     al, 80h.text:00489BCE                 cmp     al, 80h ; '?'   ; //判断PAT位.text:00489BD0                 setnz   al              ; PAT == 1 ZF = 1 AL置0 无效.text:00489BD0                                         ; PAT != 1 ZF = 0 AL置1 有效.text:00489BD3                 retn.text:00489BD3 _MiIsAddressValid@8 endp5.代码示例

5.1 通过代码给0线性地址挂物理页并读写

#include #include //读写物理页地址LPDWORD g_lp = NULL;//记录PDE PTEDWORD dwPDE = 0;DWORD dwPTE = 0;//0环权限修改PDE PTEVOID _declspec(naked)Fun(){  __asm  {    pushad    pushfd    //获取物理页    mov ecx, g_lp    //PDE    mov eax, ecx    shr eax, 0x14    and eax, 0x0FFC    sub eax, 0x3FD00000    mov eax, [eax]    mov dwPDE, eax    //PTE    mov eax, ecx    shr eax, 0xA    and eax, 0x3FFFFC    sub eax, 0x40000000    mov eax, [eax]    mov dwPTE, eax    //获取0物理页    xor ecx, ecx    //PDE    mov eax, ecx    shr eax, 0x14    and eax, 0x0FFC    sub eax, 0x3FD00000    //备份对应线性地址    mov edx, eax    mov eax, [eax]    //判断是否存在PDE    and eax, eax    jnz Flag    mov ebx, dwPTE    mov [edx], ebxFlag:    //PTE    mov eax, ecx        shr eax, 0xA        and eax, 0x3FFFFC        sub eax, 0x40000000        mov edx, dwPTE        mov [eax], edx        popfd        popad        retf  }}int main(){        //Get Page        g_lp = (LPDWORD)VirtualAlloc(NULL,0x100,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);        if (!g_lp)        {                MessageBox(NULL,"VirtualAlloc Fail !","ERROR",MB_OK|MB_ICONERROR);                exit(0);        }        g_lp[0] = 0x12345678;        printf("Data = %08x \n",g_lp[0]);        system("Pause");        //CALL GATE        printf("Function Addr = %08x \n",Fun);        system("Pause");        CHAR calldata[6] = {0,0,0,0,0x48,0};        __asm        {                call fword ptr [calldata]        }        printf("PDE = %08X  PTE = %08X \n",dwPDE,dwPTE);        *(LPDWORD)0 = 0xFFFFFFFF;        printf("Data = %08x \n",g_lp[0]);        system("Pause");        return 0;}
5.2 0线性地址实现SHELLCODE

#include #include //PTE PDEDWORD dwCodePDE = 0;DWORD dwCodePTE = 0;DWORD dwZeroPDE = 0;DWORD dwZeroPTE = 0;//SHELLCODECHAR Data[] ={  0x6a,0x00,0x6a,0x00,0x6a,0x00,0x6a,0x00,//PUSH  0xE8,0x00,0x00,0x00,0x00,        //CALL  0xc3                  //ret};VOID _declspec(naked)Fun(){  __asm  {    //保留寄存器数据    pushad    pushfd    //获取CODE PAGE    lea ecx, Data    //PDI    shr eax, 0x14    and eax, 0x00000FFC    sub eax, 0x3FD00000    mov eax, [eax]    mov dwCodePDE, eax    //获取LP PTI    shr ecx, 0xA    and ecx, 0x003FFFFC    sub ecx, 0x40000000    mov eax, [ecx]    mov dwCodePTE, eax    //0线性地址挂物理页    xor ecx, ecx    mov eax, ecx    //PDI    shr eax, 0x14    and eax, 0x00000FFC    sub eax, 0x3FD00000      mov edx, eax    mov eax, [eax]    mov dwZeroPDE, eax    //判断PDE是否为0    and eax, eax    jnz FLAG    mov eax, edx    mov ebx, dwCodePDE    mov [eax], ebx    mov dwZeroPDE, ebxFLAG:    //修改0 PTE    shr ecx, 0xA        and ecx, 0x003FFFFC        sub ecx, 0x40000000        mov edx, dwCodePTE        mov [ecx], edx        mov ecx, [ecx]        mov dwZeroPTE, ecx        //恢复寄存器数据        popfd        popad        retf  }}int main(){        //获取函数地址        DWORD dwAddr = (DWORD)MessageBox;        //修正SHELLCODE        DWORD dwOffset = (DWORD)Data & 0xFFF;        *(LPDWORD)&Data[9] = dwAddr - (dwOffset + 13);        printf("Function Addr = %08x \n", Fun);        system("Pause");        //CALL GATE        CHAR calldata[6] = {0,0,0,0,0x48,0};        __asm        {                call fword ptr [calldata]                call [dwOffset]        }        printf("Code PDE = %08x  PTE = %08x \n",dwCodePDE,dwCodePTE);        printf("Zero PDE = %08x  PTE = %08x \n",dwZeroPDE,dwZeroPTE);        system("Pause");        return 0;}
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-4-19 22:10 , Processed in 0.093750 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表