分析故障以查找您应用程序中的安全漏洞访问冲突.doc_第1页
分析故障以查找您应用程序中的安全漏洞访问冲突.doc_第2页
分析故障以查找您应用程序中的安全漏洞访问冲突.doc_第3页
分析故障以查找您应用程序中的安全漏洞访问冲突.doc_第4页
分析故障以查找您应用程序中的安全漏洞访问冲突.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

分析故障以查找您应用程序中的安全漏洞 访问冲突分析故障以查找您应用程序中的安全漏洞访问冲突2010-04-16 22:32图1访问冲突分析路径(单击该图像获得较大视图)图1提供了该研究过程的图形路径,可帮助您确定特定故障是否可利用。有一点必须记住,这些只是指导原则,只有充分的根本原因分析才能确保您将该故障诊断为不可利用是正确的。人们总是不断发现新技术或现有攻击技术的变体。访问冲突当某指令或程序执行引发的内存访问不能满足由处理器体系结构或内存管理单元结构定义的特定条件时,现代处理器会产生访问冲突异常(0xc 0000005=STATUS_ACCESS_VIOLATION)。虽然单纯的故障只会产生拒绝服务的状况,但是不能贸然认为故障不会被用来产生更多的危险结果(包括代码执行)。在分析故障时,您应假设整个内存体(除了一些微小的例外)都在潜在攻击者的控制之下,因而访问冲突在大多数情况下都可以导致数据被攻击者所控制。这种假设适用于当指令读取或写入数据时发生的异常。如果访问冲突可导致您的数据被攻击者控制,那么从内存进行读取所引起的每次访问冲突都会转变为加载攻击者控制的数据。这类操作的安全效果并不总是很容易确定。您可以对二进制或源代码执行完整的数据流分析,找出源地址控制的范围以及在某些执行点向程序提供随机数据的后果。这是一项既耗时又艰巨的任务。为了应对这种情况,我们开发了简单的试探法以快速分析读取访问冲突故障并找到可能的代码执行。正如下面的示例所示,寄存器eax中无效的内存指针引起了故障。在这种情况下,对内存内容的控制会让攻击者完全控制程序流:复制代码Application!Function+0x133:3036a384 eb32 calleaxds:0023:6c7d890d=?0:000 ub mov eax,ebx-eax=invalid memory pointer.(instructions not affecting register eax)calleax-crash如果攻击者无法完全控制正在读取的地址,这种情况可被视为拒绝服务状况。例如,在典型的Windows用户模式环境下,在已初始化并且攻击者无法影响的NULL指针处所发生的故障本身不能导致代码执行。在下面的示例中,您可以看到故障是由引用零地址(通过寄存器eax中的值)引起的:复制代码Application!Function+0x133:3036a384 8b14 mov ecx,eaxds:0023:00000000=?0:000 ub xor eax,eax.(instructions not affecting register eax)cmp ebx,2 jne label123 mov ecx,eax-crash,eax=0(NULL)通过反汇编(使用Visual Studio命令行调试器中的ub命令),我们可以跟踪此寄存器中的数据流,直到确定恶意输入无法影响寄存器中的值为止。在此示例中,该寄存器实际上被XOR自身清零了,并且在到达故障指令之前没有使用它。有时候,缺陷的可利用性不会立即显现在出故障的指令中。例如,将下列指令反汇编以后,您可以看到它是一个控制流的结果,其中失败指令(在前一个段落中介绍过)后跟一个关键指令:复制代码(1258.1638):Access violation-code c0000005(second chance)Application!Function+0x123:3036a384 8b12 mov eax,ebxds:0023:6c7d890d=?0:000 umov eax,ebx-crash,ebx points to invalid memory.(instructions not affecting regist an example er eax)calleax-possibility of code execution本示例与第一个示例类似,但这次故障是发生在将数据加载到寄存器eax的指令处。尽管此操作本身没有显现出安全问题,但是反汇编清楚地表明,控制寄存器ebx的值就意味着控制寄存器eax的值,这可能会引发代码执行。其余情况可以在程序运行时通过模拟恶意数据注入来进行分析,可在调试器下手动分析,也可通过调试工具自动分析。到达引起访问冲突的指令后,我们可以更改源地址以指向有效内存地址并再次执行该指令,也可以将随机数据放入目标寄存器并跳过错误指令,继续执行。我们会对遇到的每一个访问冲突重复此过程,直到碰到可利用的情况。让我们来分析两个示例。首先来看一下我们更改源地址时的跟踪数据流:复制代码Application!Function+0xa70:3036a37e 8b4708 mov eax,dword ptredi+8ds:0023:040fd004=?这里的故障是由寄存器edi中错误的值引起的。我们要将其更改为指向正确的内存区域。虽然存在很多可能的选择,但实际上,我们通常都会使用寄存器eip的当前值。这可以确保edi的新值附近的相当大一部分内存都是正确的,并使捕获对(包含代码的)内存块进行任何后续写入成为可能,因为它始终都标记为只读:复制代码0:000 redi=eip 0:000 g将寄存器edi设置为寄存器eip的当前值后,我们继续执行,在寄存器esi上碰到另一个异常,在此重复这个过程:复制代码(1258.1638):Access violation-code c0000005(second chance)Application!Function+0xa76:3036a384 f60601 test byte ptresi,1 ds:0023:6c7d890d=?0:000 resi=eip 0:000 g继续执行,在尝试将数据写入代码段的指令上我们碰到一个写访问冲突异常。这意味着攻击者也可以将数据写入任何内存地址:复制代码(1258.1638):Access violation-code c0000005(second chance)Application!Function+0xbef:3036a4fd 894710 mov dword ptredi+10h,eax ds:0023:3036a38e=0c46f60d可以看出,最初的读取访问冲突最终成了真正的安全问题,存在代码执行的可能性。现在让我们通过设置目标数据并跳过指令来看一看跟踪数据流。像以前一样分析同一个故障,我们将继续更改目标数据。碰到最初的异常以后,我们可以将eax寄存器设置成任何易于跟踪的值,并在寄存器eip上加上当前指令的大小,以跳过它:复制代码Application!Function+0xa70:3036a37e 8b4708 mov eax,dword ptredi+8ds:0023:03f93004=?0:000 reax=deadbeef 0:000 reip=eip+3 0:000 g继续执行,我们碰到下一个异常,该异常没有目标,因此我们只要跳过该指令即可:复制代码(1258.1638):Access violation-code c0000005(second chance)Application!Function+0xa76:3036a384 f60601 test byte ptresi,1 ds:0023:deadbefb=?0:000 reip=eip+3 0:000 g进一步执行,我们遇到同一个写入访问冲突异常,表明有可能存在可利用问题:复制代码(1258.1638):Access violation-code c0000005(second chance)Application!Function+0xbef:3036a4fd 894710 mov dword ptredi+10h,eax ds:0023:03f9300c=0c46f60d两种模拟恶意数据注入的方法通常会产生相同的结果,从实践中我们可以看到,在很多情况下,它们会覆盖不同的代码路径,其中只有一种方法显现了问题的可利用性。至今为止讨论过的所有方法都可以非常快速地找到潜在的可利用读取访问冲突故障,但是我们必须记住一点,它们不会就某一故障不是可利用的问题提供最终验证。写入数据时的访问冲突数据写入过程中的访问冲突表明可能存在内存损坏,这几乎总是会引发可利用情况和潜在的代码执行。通常,这类写入是出现故障的程序中存在缓冲区溢出情况的信号。实际上,有些写入访问冲突故障可以显示为不可利用。但是,这样的情况要求您执行全面的数据流分析,以了解问题的根本原因。您需要确保该损坏不会导致攻击者能够覆盖数据并随意影响执行流。大多数有关数据写入的访问冲突都可以引发一些将导致恶意代码执行的可利用情形。通常,代码执行是通过覆盖堆栈或堆上的(任意)一部分内存实现的。在下面的示例中,当目标寄存器到达堆栈的上限,并遇到未分配的内存区域时,某个内存复制指令发生了故障。该复制操作的大小来自地址ebp-8处的变量,并且该故障表明它处于攻击者的控制之下:复制代码Application!Function+0x143:3036a384 f3a4 rep movsb es:0023:00140000=?ds:0023:0125432 c=41414141 0:000 ub mov esi,ebp-4mov edi,ebp+4mov ecx,ebp-8rep movsb-write access violation if value in ecx is big enough我们可以很自信地说,只有当攻击者控制的目标地址指向无效的内存或指向对程序执行没有影响的数据时,写入访问冲突才不会引发代码执行。实际上,只有小部分写入访问冲突能满足这个条件。在Windows用户模式环境下,对NULL指针或系统地址空间(通常是2GB以上的地址)的写入就是不可利用问题的一个示例(假设地址为0x 00000000的页面不可分配)。此外,在服务器情形中,该指令会引发拒绝服务,如果它由非管理员用户触发就可视为安全漏洞。此示例与前面关于读取访问冲突所讨论的情况相似。快速的反汇编表明,寄存器eax已初始化为零值,并且在到达故障指令之前没有发生更改:复制代码Application!Function+0x133:3036a384 8d14 moveax,ecx ds:0023:00000000=?0:000 ub xor eax,eax.(instructions not affecting register eax)cmp ebx,2 jne label123 moveax,ecx-crash,eax=0(NULL)不可利用的异常在用户模式下(不是在内核模式下),这类异常不可能用于单级利用。通常这些异常会导致拒绝服务。只有在某些情况下,当异常处理程序由于其他漏洞而被更改时,这些异常才可能引发恶意代码执行。拒绝服务在服务器平台中属于高优先级的bug,而在工作站中则是中等优先级的bug。这些异常的一个例子是静态/全局取消引用(读取和写入)。此示例中的进程无法对页面0x 310000进行读取访问,使读取访问冲突发生,也无法对同一页面进行写入访问从而触发写入访问冲突。复制代码mov ebp,310046 hmov eax,ebp+4hinc eax movebp+8h,eax前两种异常需要进行仔细的分析。如果静态/全局值指向内存中的地址(在这里恶意代码可以不限长度地写入,并可以覆盖其他结构以进行复杂的利用),那么这种情况必须标记为可利用。如果它只允许您在不属于任何控制结构组成部分的地址上存储单个DWORD,那么它就极有可能是不可利用的。但是,这种假设必须要通过运行程序并观察值(也称为运行时分析)来验证。如果存储的值后来未在代码中使用,它就不会引起另一个可利用的情况,可将其忽略。如果该值可用作内存地址或可用于内存复制操作,则为可利用的可能性就会比较高。在不可控制的地址空间(页面0和类似的情况)中的静态/全局地址上执行代码是另一个例子,在这里可利用性依赖于来自操作数的地址的内存页面对于写入是否为可控制:复制代码0040137 FB8 DE C0 AD DE mov eax,0DEADC0DEh 00401384 FF D0 call eax分析静态/全局地址上的代码执行有更多的意义。如果地址属于永远不会和普通进程执行相关联的页面(页面0或地址超过0x 80000000的页面),那它就是不可利用的。除零操作也会触发异常,但是它此时不可直接利用。这种情况需要进行额外的分析,才能确定此异常的结果是否可将CPU设为执行可导致成功利用的代码:复制代码004013 D6 33 C9 xor ecx,ecx 004013 D8 8B C1 mov eax,ecx 004013 DA 40 inc eax 004013 DB F7 F1 div ecx未处理的C+异常可能破坏进程的执行。运行时,它们将导致终止应用程序。在调试器下,在未处理的异常之后可以继续运行。当运行时库的异常引发函数被调用时则发生C+异常:复制代码00401902 movebp+var_4,1 00401909 push offset _TI1H 0040190 Elea eax,ebp+var_400401911 push eax 00401912 call _CxxThrowException8;_CxxThrowException(x,x)如果该异常的处理程序机制已被覆盖,那么这种情况就只能是可利用的。否则,未处理的C+异常就不是可利用的。此异常的堆栈跟踪如图2所示。Figure 2针对未处理C+错误的堆栈跟踪复制代码CommandLine:test.exe Symbol search path is:srv*c:Symbols*symbolssymbols Executable search path is:ModLoad:00400000 00405000 test.exe ModLoad:7c 900000 7c9b0000 ntdll.dll ModLoad:7c 800000 7c8f5000 C:WINDOWSsystem32kernel32.dll ModLoad:78130000 781cb000 C:WINDOWSWinSxSx86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_ 8.0.50727.762_x-ww_6b 128700MSVCR 80.dll ModLoad:77c10000 77c68000 C:WINDOWSsystem32msvcrt.dll(1494.14 c4):Break instruction exception-code 80000003(first chance)eax=00251eb4 ebx=7ffda000 ecx=00000004 edx=00000010 esi=00251f48 edi=00251eb4 eip=7c 901230 esp=0012fb20 ebp=0012fc94 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!DbgBreakPoint:7c 901230 cc int 30:000 g(1494.14 c4):C+EH exception-code e06d7363(first chance)(1494.14 c4):C+EH exception-code e06d7363(!second chance!)eax=0012fee0 ebx=00000000 ecx=00000000 edx=781c3c58 esi=0012ff68 edi=004033 a4 eip=7c812a5b esp=0012fedc ebp=0012ff30 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 kernel32!RaiseException+0x53:7c812a5b 5e pop esi 0:000 kb ChildEBP RetAddr Args to Child 0012ff30 78158e69 e06d7363 00000001 00000003 kernel32!RaiseException+0x53 0012ff68 00401917 0012ff78 004022 b8 00000001 MSVCR80!_CxxThrowException+0x46 0012ff7c 004011 b2 00000001 00353098 003530 d0 test!wmain+0x27 0012ffc0 7c816fd7 00011970 7c9118f1 7ffda000 test!_tmainCRTStartup+0x10f 0012fff0 00000000 004012 fb 00000000 78746341 kernel32!BaseProcessStart+0x23注意,堆栈溢出异常可能会隐藏运行时的其他问题,将代码流转向其他路径,禁用编译器生成的保护机制(例如/GS),或由于释放仍在使用的内存在应用程序中引入不一致。当堆栈空间几乎耗尽时,应用程序可能会在出现堆栈溢出异常的C+方法内部失败,而且重要的代码段将不会按顺序执行。在这种情况下将需要进行额外会审。/GS异常/GS(0xc 0000409=STATUS_STACK_BUFFER_OVERRUN)异常是指当Windows检测到保护返回地址的安全Cookie遭到篡改时所引发的异常。由于/GS的目标是将导致代码执行的缓冲区溢出转换成拒绝服务攻击,因此无论何时检测到这类故障,您都可以确定存在安全bug。(遗憾的是,由于存在错误的内存、时钟超过的母板、有故障的硬件和其他问题,有时候验证Cookie的代码会在没有真正缓冲区溢出的情况下犯错。)在Windows Vista中,当检测到STATUS_STACK_BUFFER_OVERRUN时(假设存在调试器),操作系统会引发一个int 3异常。在较早的Windows版本中,断点应放在kernel32!UnhandledExceptionFilter中以检测安全Cookie是否遭到了篡改(否则,进程会被终止,并且用户不会获得通知)。在图3中,函数foo通过将过多的数据复制到堆栈缓冲区来溢出缓冲区,这样会导致/GS Cookie被覆盖。Figure 3覆盖/GS Cookie NX异常一旦Windows在未标记为可执行的页面(换句话说,页面没有PAGE_EXECUTE、PAGE_EXECUTE_READ或其他相关标志)上检测到了代码执行,它就会引发NX(0xc 0000005=STATUS_ACCESS_VIOLATION)异常。NX在64位版本的操作系统中是强制实施的。诸如解包器和数字权限管理(DRM)的一些应用程序依赖堆上的执行代码,因此不是每个NX异常都应被视为安全漏洞。但是,了解bug的根本原因以确保它没有安全隐患仍然非常有意义。值得注意的是,这种类型的异常使用错误代码0xc 0000005,该错误代码并不特定于NX;任何行为异常(例如,从未分配的内存读取)的应用程序都可能引发此错误。为了解异常/错误代码是否确实与NX相关,我们需要查看页面上的保护设置。如果页面未标记为可执行,我们会遇到NX异常;否则会遇到其他类型的问题。例如,在图4中,出现了第一次异常,但是该指令似乎是有效的,并且引用了有效数据。Figure 4潜在的NX异常您可以看出,分析程序故障的安全隐患是一项非常复杂又容易出错的任务。我们已讨论了在分析故障时可能遇到的最常见异常,包括读取/写入访问冲突、除

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论