exploit writing tutorial 阅读笔记总结

近日阅读Corelan Team编写的exploit writing tutorial系列,大致了解了一下原理,记了一些笔记。此系列文章有中文翻译版,在看雪论坛上发表。

英文版地址:https://www.corelan.be/index.php/2009/07/19/exploit-writing-tutorial-part-1-stack-based-overflows/

中文版地址:http://bbs.pediy.com/showthread.php?t=101217

【文章目录】

1. 栈溢出

2. 栈溢出——跳转到shellcode

3. 基于SEH的利用

4. 编写Metasploit exploit

5. 利用调试器模块及插件加速exploit开发

6. 绕过Cookie, SafeSEH, HW DEP和ASLR

7. ASLR保护

8. Win32 Egg Hunting

9. Win32 shellcode编写入门

10. 用ROP束缚DEP

11. 堆喷射技术揭秘

一、栈溢出的利用方法

1. 修改EIP进行跳转

  通过在程序调用的dll中找到跳转语句的地址,将EIP改为这个地址,而ESP处放置shellcode。

  ①jmp/call a register

  ②pop return

  ③push return

  ④jmp [reg]+[offset]

  ⑤blind return(需要硬编码改变栈的值)

2. 基于SEH的利用

  使用异常处理来利用漏洞,通过改写SEH handler为shellcode地址完成跳转。

3. popad指令

  popad指令(0x61)会一次性从ESP指向的地址弹出32个字节,寄存器使用次序为:EDI, ESI, EBP, EBX, EDX, ECX and EAX。此时注意shellcode的起始位置。

4. 硬编码要跳转的地址

  改写寄存器并跳转到地址。关键是你要知道jmp [地址]的opcode是什么。可以灵活使用a和u命令。

二、使用工具辅助exploit开发

  1. 使用Metasploit framework中的工具编写exploit

  2. 利用调试器模块及插件加速exploit开发

  Windbg插件,Ollydbg插件,Immunity Debugger插件

三、绕过保护措施

1. 栈中的cookie/GS保护

  /GS 编译选项会在函数的开头和结尾添加代码来阻止对典型的栈溢出漏洞(字符串缓冲区)的利用。

    [buffer][cookie][saved EBP][saved EIP]

  在函数的结尾处,程序会把这个 cookie和保存在.data节中的cookie 进行比较。如果不相等,就说明进程栈被破坏,进程必须被终止。

  绕过方法:

  (1)检索/猜测/计算出cookie值。

Reducing the effective entropy of GS cookies

  (2)David Litchfield 2003 利用异常处理器绕过

  当原始cookie被覆盖时,程序依靠异常处理结构来处理,如果黑客能够覆盖掉一个异常处理结构,并在cookie检查前触发异常,就可以成功溢出。/GS的一个重要缺陷就是没有保护异常处理器。前提是没有开启/safeseh保护。如果有这个保护,那么还要绕过safeseh保护。

  (3)通过同时替换栈中和.data节中的cookie来绕过

  (4)利用未被保护的缓冲区来实现绕过

  利用漏洞代码不包含字符串缓冲区,因此堆栈中没有cookie

  (5)通过覆盖上层函数的栈数据绕过

  函数的参数如果是对象指针或结构指针,这些对象和结构存在于调用者的对战中,如果能够将这些指针指向一个用于欺骗的虚函数表,就可以重定向这个虚函数的调用。

  (6)基于静态cookie的绕过

  前提是每次cookie是相同的,溢出时可以简单地把这个值放在堆栈相应位置上。

2. SafeSEH

  通过启用/safeSEH编译选项来把这种机制应用到所有的执行模块上,可以阻止利用SEH的exploit。当SEH链被修改的时候,程序直接终止,而不会跳转到shellcode去执行。当异常处理器执行前,safeSEH会从头到尾遍历异常处理链表,验证其是否被修改过。

如何绕过:

  (1)在exploit中不利用SEH。

  (2)如果有程序编译的时候存在至少一个没启用safeseh的加载模块,就可以用这些模块中的pop/pop/ret指令地址来绕过保护。但注意不能把shellcode放在异常处理器之后。

  (3)利用加载模块之外的地址

  在加载模块之外找到包含pop/pop/ret指令的地址。需要针对特定的系统版本来编写利用程序。

3. DEP

  硬件DEP(数据执行保护)把需要保护的页面置成非可执行页,就是把堆栈设置为非可执行属性,这样之前将shellcode放在堆栈中执行的策略就不可行了。

  (1)ret2libc(no shellcode)

  不直接跳转到shellcode去执行,而是去执行库中的代码。可以在库中找到一段执行系统命令的代码,用这段库代码的地址覆盖返回地址,因此即使NX/XD 禁止在堆栈上执行代码,但库中的代码依然是可以执行的,我们可以利用这点,很显然,这种技术对执行的代码有很大的限制。

  (2)ZwProtectVirtualMemory

  基于ret2libc技术,实际上将多个ret2libc综合起来从而达到修改内存属性的目的。当一个函数返回的时候,程序会调用函数VirtualProtect,需要设置的一个参数是Virtual rotect的返回地址,如果你把类似jmpesp指令的地址设置成VirtualProtect的返回地址,当VirtualProtect返回后,esp应当正好指向你的shellcode,因此shellcode就可以获得执行了,其他的参数是 shellcode(需要设置成可执行的内存(如栈))的地址,shellcode的大小,等等.

  (3)关闭进程的DEP(NtSetInformationProcess)

  因为DEP可以设置不同的模式,操作系统需要能动态关闭DEP,因此系统肯定有例程/API来启用或关闭NX,如果黑客可以找到这个NTDLL中的 API,就能绕过硬件DEP保护。

David Kennedy 最近发表了一篇关于如何在 windows 2003 sp2上绕过 DEP保护的文章。实质上,这种 DEP绕过技术就是调用可以关闭 DEP的系统函数,然后返回到 shellcode,为了顺利达成这样目的,你需要对栈的布局进行针对性的设计。

  (4)利用SEH绕过DEP

  当DEP启用后,显然依然要覆盖seh结构,但是不能再用pop /pop/ret 的地址,而应该用pop reg/pop reg/pop esp/ret指令的地址,指令 pop esp可以改变堆栈指针,ret将执行流转移到nseh中的地址上。(现在不再用跳转指令,而是用关闭 NX例程的地址覆盖nseh,用指向 pop/pop/pop esp/ret指令的指针覆盖异常处理器,像这样的指令组合很难找到,pvefindaddr可以帮助你找到拥有这种指令的地址。

4. ASLR保护

  Windows Vista, 2008 server, and Windows 7 也构建了另一种保护技术,它使进程中的执行模块,dll,栈,和堆的加载地址随机化(事实上,系统从256个基地址中随机的选出一个来用于加载系统映像,并随机化每个线程的堆基址和栈基址)。这个技术就是ASLR(地址空间布局随机化)。这些地址在每次系统启动的时候会改变。

  绕过ASLR:

  (1)部分覆盖

ASLR只是随机了地址的一个部分,比如只对高字节随机。我们只需要在低字节所表示的地址范围内找到有趣的指令并用这些指令的地址替换掉栈中的低字节。

  (2)使用没有启用ASLR模块中的地址

  因为这些地址极可能不是随机的,在 EXE 模块的地址中一般包含一个 NULL 字节,这意味着即使你找到了一个能跳到 shellcode 的跳转指令的地址,你仍然需要解决 NULL 字节带来的问题,这是否是个难题取决于溢出发生时的堆栈布局和寄存器的状态。

  (3)利用堆

  (4)猜测随机地址

  (5)暴力破解

  (6)基于SEH的exploit

  要找到safeSEH和ASLR都没有启用的模块。

四、编写unicode exploit

五、Win32 Egg Hunting

  利用一小段代码在内存中寻找真正的shellcode。

  三个前置条件:

  1. 能够jmp, call, push/ret并执行一些shellcode

  2. shellcode在内存某个位置存在

  3. 在shellcode前放置唯一标识,搜索标识

六、Win32 shellcode编写入门

  如何写出自己的shellcode

七、用ROP束缚DEP

  Return Oriented Programming

  DEP:我们不能在栈上执行指令,只能在栈上弹出弹入数据(原本的exploit是把shellcode放在栈中/堆中,跳到shellcode执行)

  我们只能从已加载模块中执行现有的指令,或调用现有的函数用栈上数据作为这些函数/指令的参数。

  1. 执行命令:ret-to-libc

  2. 页面标记为可执行

  3. 数据拷贝到可执行区域然后跳转

  4. 改变当前进程的DEP设置

  生成ROP gadget(一系列以ret为结尾的指令集合)

  没有通用的方法打造一个exploit

八、堆喷射技术

  heap spraying

  一种payload传递技术,帮助将payload放置在可预测的内存地址,以便于跳转或返回payload地址。

  广泛运用在浏览器利用代码中。

  在劫持EIP前,先分配并填充堆内存块。

  关键在于能够在可预测的地址上分配内存,并将shellcode传输到正确的内存地址。

  1. 喷射堆块(分配内存)

  2. 触发漏洞

  3. 控制EIP并使其指向堆中

上一篇:5 -- Hibernate的基本用法 -- 要点


下一篇:转:Hibernate中Criteria和DetachedCriteria的完整用法