首页
社区
课程
招聘
[原创]逆向分析系统函数MmIsAddressValid
2023-7-31 23:03 3345

[原创]逆向分析系统函数MmIsAddressValid

2023-7-31 23:03
3345

逆向分析系统函数MmIsAddressValid(XP系统 10-10-12分页)

引言: 由于不能直接在代码中操作物理地址,因此系统提供了2个特殊的线性地址用于间接操作PDE和PTE。 PDT的线性地址 = 0xC0300000 + PDI*4 PTT的线性地址 = 0xC0000000  + PDI*4KB + PTI*4

.text:0040AF41 nop
.text:0040AF42 nop
.text:0040AF43 nop
.text:0040AF44 nop
.text:0040AF45 nop
.text:0040AF45
.text:0040AF46 ; Exported entry 685. MmIsAddressValid
.text:0040AF46
.text:0040AF46 ; =============== S U B R O U T I N E =======================================
.text:0040AF46
.text:0040AF46 ; Attributes: bp-based frame
.text:0040AF46
.text:0040AF46 ; BOOLEAN __stdcall MmIsAddressValid(PVOID VirtualAddress)
.text:0040AF46 public _MmIsAddressValid@4
.text:0040AF46 _MmIsAddressValid@4 proc near ; CODE XREF: MiMakeSystemAddressValidPfn(x)+C↓p
.text:0040AF46                               ; MiDecrementShareCount(x)-493↓p
.text:0040AF46                               ; MmFlushSection(x,x,x,x,x)+69↓p
.text:0040AF46                               ; MiMakeSystemAddressValidPfnWs(x,x):loc_41ACA8↓p
.text:0040AF46                               ; MiSegmentDelete(x)+D94B↓p
.text:0040AF46                               ; MmPurgeSection(x,x,x,x)+E9B↓p
.text:0040AF46                               ; MiMakeSystemAddressValidPfnSystemWs(x)+31↓p
.text:0040AF46                               ; MiGatherMappedPages(x,x)+84↓p
.text:0040AF46                               ; MiMovePageToEndOfStandbyList(x)+16↓p
.text:0040AF46                               ; MmDbgCopyMemory(x,x,x,x,x)+87↓p
.text:0040AF46                               ; MiSessionCommitImagePages(x,x)+19↓p
.text:0040AF46                               ; MiRestoreTransitionPte(x)+20↓p
.text:0040AF46                               ; MiCanFileBeTruncatedInternal(x,x,x,x)+2CEAC↓p
.text:0040AF46                               ; MiWaitForInPageComplete(x,x,x,x,x,x)+2BC9F↓p
.text:0040AF46                               ; MiMakeSystemAddressValidPfnSystemWs(x)+2B004↓p ...
.text:0040AF46
.text:0040AF46 VirtualAddress= dword ptr  8
.text:0040AF46
.text:0040AF46 ; FUNCTION CHUNK AT .text:0041EDB7 SIZE 00000007 BYTES
.text:0040AF46 ; FUNCTION CHUNK AT .text:0044F166 SIZE 00000019 BYTES
.text:0040AF46
.text:0040AF46 mov     edi, edi
.text:0040AF48 push    ebp                   ; mov edi, edi 是一种hot-patching
.text:0040AF49 mov     ebp, esp
.text:0040AF4B mov     ecx, [ebp+VirtualAddress] ; 取出线性地址
.text:0040AF4E mov     eax, ecx
.text:0040AF50 shr     eax, 14h              ; 取出线性地址的高12位
.text:0040AF53 mov     edx, 0FFCh            ; 12位 111111111100
.text:0040AF58 and     eax, edx              ; 保留线性地址的高10位(PDI),将剩余2位置零(eax<<2) -> eax = PDI*4
.text:0040AF5A sub     eax, 3FD00000h        ; 通过位运算结果发现,该指令执行后的结果 = 0xC0300000+eax
.text:0040AF5F mov     eax, [eax]            ; 取出PDE
.text:0040AF61 test    al, 1                 ; 判断PDE的P位
.text:0040AF63 jz      loc_41EDB7            ; P位!=1,则跳转到结束,返回0
.text:0040AF63
.text:0040AF69 test    al, al                ; 判断PDE的最高位是否为1
.text:0040AF6B js      short loc_40AF91      ; 结果为负,表示PS==1,则跳转到结束,返回1
.text:0040AF6B
.text:0040AF6D shr     ecx, 0Ah              ; 取出线性地址的高22位
.text:0040AF70 and     ecx, 3FFFFCh          ; 通过位运算结果发现,该指令执行后的结果=PDI>>12 + PEI>>2 = PDI*4096+PTI*4 = ecx
.text:0040AF76 sub     ecx, 40000000h        ; 通过位运算结果发现,该指令执行后的结果 = 0xC0000000+ecx
.text:0040AF7C mov     eax, ecx
.text:0040AF7E mov     ecx, [eax]            ; 取出PTE
.text:0040AF80 test    cl, 1                 ; 判断PTE的P位
.text:0040AF83 jz      loc_41EDB7            ; P位!=1,则跳转到return
.text:0040AF83
.text:0040AF89 test    cl, cl
.text:0040AF8B js      loc_44F166            ; 判断PTE的PAT位,跳转后还有一层判断,有效返回1,无效返回0
.text:0040AF8B
.text:0040AF91
.text:0040AF91 loc_40AF91:                   ; CODE XREF: MmIsAddressValid(x)+25↑j
.text:0040AF91                               ; MmIsAddressValid(x)+4422E↓j
.text:0040AF91 mov     al, 1                 ; 若线性地址有效,则通过eax返回1
.text:0040AF91
.text:0040AF93
.text:0040AF93 loc_40AF93:                   ; CODE XREF: MmIsAddressValid(x)+13E73↓j
.text:0040AF93 pop     ebp
.text:0040AF94 retn    4
.text:0040AF94
.text:0040AF94 _MmIsAddressValid@4 endp

位运算分析:

.text:0040AF50 shr     eax, 14h              ; 取出线性地址的高12位
.text:0040AF53 mov     edx, 0FFCh            ; 12位 111111111100
.text:0040AF58 and     eax, edx              ; 保留线性地址的高10位(PDI),将剩余2位置零(eax<<2) -> eax = PDI*4
.text:0040AF5A sub     eax, 3FD00000h        ; 通过位运算结果发现,该指令执行后的结果 = 0xC0300000+eax

.text:0040AF50 shr     eax, 14h              ; eax==线性地址,将线性地址右移十进制20位,假设线性地址eax的所有位都是1
右移20位后的eax == 00000000000000000000111111111111
edx == 00000000000000000000111111111100
and eax, edx:00000000000000000000111111111100 -> 取出10位PDI,低两位为0表示PDI<<2,即eax == PDI*2^2
3FD00000h == 00111111110100000000000000000000
sub eax, 3FD00000h == 11000000001100000000111111111111 -> 运算结果
0xC0300000 == 11000000001100000000000000000000
运算结果:11000000001100000000111111111111 == 0xc0300000 + eax == 0xc0300000 + PDI*4

.text:0040AF6D shr     ecx, 0Ah              ; 取出线性地址的高22位
.text:0040AF70 and     ecx, 3FFFFCh          ; 通过位运算结果发现,该指令执行后的结果=PDI>>12 + PEI>>2 = PDI*4096+PTI*4 = ecx
.text:0040AF76 sub     ecx, 40000000h        ; 通过位运算结果发现,该指令执行后的结果 = 0xC0000000+ecx

.text:0040AF6D shr     ecx, 0Ah              ; ecx==线性地址,将线性地址右移十进制10位,假设线性地址ecx的所有位都是1
右移10位后的ecx == 00000000001111111111111111111111
3FFFFCh == 00000000001111111111111111111100
and ecx, 3FFFFCh == 00000000001111111111111111111100 -> 前10位PDI相当于左移12位,即PDI*2^12,低10位PTI相当于左移2位,即PTI*2^2
40000000h == 01000000000000000000000000000000
.text:0040AF76 sub ecx, 40000000h == 11000000001111111111111111111100 -> 运算结果
0xC0000000 == 11000000000000000000000000000000
运算结果:11000000001111111111111111111100 == 0xC0000000 + ecx == 0xC0000000 + PDI*4096 + PTI*4

总结: 系统函数MmIsAddressValid判断一个线性地址是有效: 首先通过线性地址的公式找到对应的PDE和PTE,然后判断PDE的P位和PS位,再判断PTE的P位和PAT位

逆向还原代码(未上机测试):

BOOLEAN __stdcall MmIsAddressValid(PVOID VirtualAddress)
{
   dword PDI = (VirtualAddress >> 20) & 0FFCh;
   dword PDE = *(dword*)(PDI - 3FD00000h);
   
   // 判断PDE的P位
   byte PDE_P = (byte)PDE & 0b00000001;
   if (PDE_P != 1) {
       return 0;
   }
   
   // 判断PDE的PS位
   byte PDE_PS = (PDE>>7) & 1;
   if (PDE_PS == 1) {
       return 1;
   }
   
   // 判断PTE的P位
   dword PTI = (VirtualAddress >> 10) & 3FFFFCh;
   dword PTE = *(dword*)(PTI - 40000000h);
   byte PTE_P = (byte)PTE & 0b00000001;
   if (PTE_P != 1) {
       return 0;
   }
   
   // 判断PTE的PAT位
   byte PDE_PS = (PTE>>7) & 1;
   if (PDE_PS == 1) {
       if (){
           return 0;
       }
       else {
           return 1;
       }
       return 1;
   }
 return 1;
}




[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2023-7-31 23:07 被ATrueMan编辑 ,原因: 格式
收藏
点赞0
打赏
分享
最新回复 (3)
雪    币: 197
活跃值: (292)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
卿卿吾吧 2023-8-1 01:15
2
0
太强了。不是很懂
雪    币: 2140
活跃值: (3538)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
R0g 2 2023-8-1 18:45
3
0
上分
雪    币: 19485
活跃值: (29158)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
秋狝 2023-8-2 11:40
4
1
感谢分享
游客
登录 | 注册 方可回帖
返回