第五篇了,漏洞分析案例

漏洞利用的灵活程度让这门技术变得似乎没有什么原则可言,只有实践后总结提高才能挥洒自如。

漏洞分析方法

目标:弄清攻击原理、评估潜在利用方式及风险等级。扎实的漏洞利用技术是进行漏洞分析的基础,否则可能将 bug 误判成漏洞,也可以将高危漏洞误判成 DOS 型的中级漏洞。

漏洞来源:挖掘、已公开的漏洞、patch(对比分析打补丁前后的 PE 文件,MS 发布补丁后一周内漏洞还在部分范围存在)

分析方法:动态调试(OllyDbg 等)、静态分析(IDA 等)、指令追踪(对比分析正常运行时记录的指令序列和 poc 触发漏洞之后记录的指令序列)

运动中寻求突破:动态调试技术

调试的原则在于确认,调试的目的在于定位。动态调试通常针对没有源码的程序。

如果说漏洞调试是一门艺术,那么下断点就是这门艺术的精髓,需要深入研究和实践!

断点技巧(OllyDbg)

畸形 RetAddr 断点。将 poc 中溢出后覆盖的函数返回地址修改为一个非法地址,在调试 poc 时能够触发一个非法内存访问错误,使得调试器中断下来。这样的好处是,在调试器中断后,可以从当前栈中找到前一次的函数调用,而它往往就是触发漏洞的函数。这样一来,调试的第一个目的即定位漏洞位置就达到了。见 Yahoo!Messenger 栈溢出漏洞。

条件断点(Shift+F2)。在某个函数入口处下断点,可能会断的太频繁影响正常分析,若不设断点,又很难分析下去。条件断点正好解决这个问题。条件断点是带有条件表达式的普通 INT 3 断点。

例如调试 notepad.exe,要在 CreateFileW() @ kernel.32.dll 处下断点,则用 UNICODE [[esp+4]]=="c:\\test.txt",表示进入 CreateFileW() 后,如果第一个参数 lpFileName==UNICODE("c:\\test.txt") 则断点。等价的命令行:bp CreateFileW UNICODE[[esp+4]]=="c:\\test.txt"。这样,当记事本打开 c:\test.txt 时就会断点暂停。

* 10 表示 unsigned 0x10 (hex) 而 10. 表示 signed 10 (oct)
* 表达式 eax 会将 eax 中的内容解释为 unsigned 而 eax. 会解释为 signed
* 当带符号数于无符号数比较时,OllyDbg 会将带符号数转化为无符号数,例如 eax<0 恒为假,因为无符号数恒大于等于 ,应该用 eax.<0.
* MSG 只能设置在进程消息函数的条件断点内,如 msg==111 表示或消息为 WM_COMMAND(0x111)时为真
* 字符串比较不区分大小写和文本长度,即当 eax 指向的内容为 bRoWn FoXaaa 时 eax=="BROWN FOX” 为真

记录断点(Shift+F4)。也是一种条件断点,每当遇到此类断点或者满足条件时,OllyDbg 会记录已知函数表达式、参数的值。例如可以在一些窗口过程函数上设置记录断点并列出对该函数的所有调用。或者只对接收到的 WM_COMMAND 消息标识符设断,或者对创建文件的函数(CreateFile)设断,并且记录以只读方式打开的文件名等。从记录窗口中浏览几百条消息比按几百次 F9 轻松得多!

在 CreateFileW() 的入口处按 Shift+F4,会弹出设置条件记录断点的对话框:

如上图,意思是在 heap.0x01331309 处(假设这里就是要记录的函数位置)下记录断点,记录内容为 "FilePath=<esp+4 的值>",断点只记录不暂停执行(Pause program: Never)。

消息断点,条件断点的一种(用消息来作表达式),调试 GUI 程序的常用技巧,如分析单击按钮后的处理过程。设置方法有两种:一种用 OllyDbg 的界面导向设置,在 Windows 窗口中右键 Message Breakpoint on ClassProc,但是有时 OllyDbg 获取到的 WinProc 和 ClassProc 不正确,将会无法判断到正确的消息处理函数入口。

另一种方法是设置条件断点,需要在 TranslateMessage() 入口填写条件,然后配合主模块的内存访问断点来断到正确的消息处理函数入口。

GUI 程序创建一个窗口的流程基本如下:

  注册窗口类(RegisterClass),注册前先填写 RegisterClass 的参数 WNDCLASSEX 结构
建立窗口 CreateWindow
显示窗口 ShowWindows
刷新窗口客户区 UpdateWindow
进入消息循环:GetMessage -> DispatchMessage,如果消息是 WM_QUIT 则退出循环

进入消息循环后 GetMessage() 会返回取到的消息,hWnd 参数指定要获取哪个窗口的消息,一般为 NULL,表示获取的是所有本程序所属窗口的消息,wMsgFilterMin 和 wMsgFilterMax 为 0 表示获取所有编号的消息。GetMessage() 从消息队列中取得消息,填写好 MSG 结构并返回。

接下来,TranslateMessage() 将 MSG 结构传给 Windows 进行一些键盘消息的转换,当有键盘按下和放开时,Windows 产生 WM_KEYDOWN / WM_KEYUP 或 WM_SYSKEYDOWN / WM_SYSKEYUP 消息,但这些消息的参数中包含的是按键的扫描码,转换成常用的 ASCII 码要经过查表,很不方便,TranslateMessage 遇到键盘消息则将扫描码换成 ASCII 码并在消息队列中插入 WM_CHAR 或 WM_SYSCHAR 消息,参数就是转换好的 ASCII 码,如此一来,要处理键盘消息的话只要处理 WM_CHAR 消息就好了。遇到别的消息则 TranslateMessage 不做处理。

最后,由 DispatchMessage 将消息发送到窗口对应的过程去处理。窗口过程返回后 DispatchMessage() 才返回,然后开始新一轮消息循环。

可见,每个消息要经历 GetMessage() - TranslateMessage() - DispatchMessage() 三个函数,也就是说只要在这三个函数中任何一个函数下断点,都可以截获相关按钮单击的消息。这是选择 TranslateMessage 作为条件断点的位置,条件用消息来表达。

下面演示如何找到 calc.exe 对于按钮 “1” 的响应代码,按钮 “1” 按下后松开的消息是 WM_LBUTTONUP,TranslateMessage() 原型为:

 BOOL TranslateMessage(
const MSG *lpMsg
};
typedef struct {
  HWND hwnd; // hwnd 不为 NULL 时表示需要处理该消息的窗口句柄,为 NULL 表示是线程消息
  UINT message; // 消息 ID,应用程序只能使用 message 的低 2 字节(low word),高 2 字节(high word)被系统保留
  WPARAM wParam;
  LPARAM lParam;
  DWORD time;
  POINT pt;
} MSG, *PMSG:

为了能拦截到按钮“1”按下后松开的消息(WM_LBUTTONUP),在 TranslateMessate() 入口设置如下条件断点,命令行输入:

a USER32.TranslateMessage                 // 跳转到 USER32.TranslateMessage() 入口处
bp TranslateMessage MSG==WM_LBUTTONUP // 设置条件断点

在 calc.exe UI 上用鼠标点下“1”,calc.exe 就会暂停,状态显示 Conditional breakpoint at USER32.TranslateMessage。

在 OllyDbg 调试面片上按下 ALT+F9,回到 calc.exe 主模块空间。下一处函数调用是 USER32.DispatchMessage(),该函数会调用窗口过程函数,为了拦截到窗口过程函数,需要配合使用内存访问断点。首先单步跟进 USER32.DispatchMessage() 的代码,然后打开 Memory 窗口,在 calc.exe 的 text 段上点击 F2 设置内存访问断点,然后直接 F9 继续执行,当 eip 指向 calc.exe 的 .text 时,程序就会暂停(该内存断点的一次性断点,断后就取消)。这时断在了 calc.exe 的主模块空间,所在的指令即是处理按钮“1”的窗口过程处理函数。可以使用 IDA 对该函数进行分析了。

内存断点

OllyDbg 可以设置内存访问断点和内存写入断点,设置方法很简单,在 Dump 窗口中点击要设置的地址,右键选择 Breakpoint - Memory on access / write 即可。对于内存数据也可以设置内存断点,方法类似。

硬件断点

硬件断点使用 4 个调试寄存器(DR0 / DR1 / DR2 / DR3)来设置地址,以及 DR7 设定状态,DR4、DR5 是保留的。可以在代码上设置硬件执行断点,也可以在内存数据上设置硬件访问/写入断点。

设置方法:在要下断点的代码窗口或内存数据窗口右键 - Breakpoint|Hardware on execution/write。

OllyDbg 常用断点速查表
拦截窗口 bp CreateWindowEx(A/W) 创建窗口   拦截时间 bp GetLocalTime 获取本地时间
bp ShowWindow 显示窗口   bp GetSystemTime 获取系统时间
bp UpdateWindow 更新窗口   bp GetFileTime 获取文件时间
bp GetWindowText(A/W) 获取窗口文本   bp GetTickCount 系统启动后的毫秒数
拦截
消息框
bp MessageBoxEx(A/W) 创建消息框   bp GetCurrentTime 当前时间(16位)
bp
MessageBoxIndirect(A/W)
创建定制消息框   bp SetTimer 创建定时器
bp
IsDialogMessage(A/W)
消息是否给指定对话框   bp TimerProc 定时器超时回调函数
拦截
对话框
bp DialogBox 创建模态对话框   GetDlgItemInt 指定输入框整数值
bp
DialogBoxParam(A/W)
创建模态对话框   GetDlgItemText 指定输入框字符串
bp
DialogBoxIndirect
创建模态对话框   GetDlgItemTextA 指定输入框字符串
bp
DialogBoxIndirectParam(A/W)
创建模态对话框   拦截文件 bp CreateFile(A/W) 创建或打开文件
bp
CreateDialog
创建非模态对话框   bp OpenFile 打开文件
bp
CreateDialogParam(A/W)
创建非模态对话框   bp ReadFile 读文件
bp
CreateDialogIndirect
创建非模态对话框   bp WriteFile 写文件
bp
CreateDialogIndirectParam(A/W)
创建非模态对话框   bp GetModuleFileName(A/W) 当前模块路径
bp
GetDlgItemText(A)
获取对话框文本   bp GetFileSize 文件大小
bp
GetDlgItemInt
获取对话框整数值   bp SetFilePointer 设置文件指针
拦截
注册表
bp RegOpenKeyEx(A/W) 打开子健   bp FindFirstFileEx(A/W) 搜索文件
bp
RegQueryValueEx(A/W)
查找子健   拦截驱动器 bp GetDriveType(A/W) 获取磁盘驱动器类型
bp
RegSetValue(A/W)
设置子健   bp GetLogicalDrives 获取逻辑驱动器符号
功能限制
拦截断点
bp EnableMenuItem 禁止或允许菜单项   bp GetLogicalDriveStrings(A/W) 根驱动器路径
bp
EnableWindow
禁止或允许窗口   剪贴板 bp GetClipboardData 获取剪贴板数据

栈回溯

观察和分析漏洞刚刚触发或快要触发时的栈帧,可以快速得到一个函数调用栈,即 Call Stack,通过对这个调用栈可以对漏洞分析的更加透彻,不仅可以看到函数的调用过程,还可以看到每个函数被调用时的参数值。

OllyDbg 中的 Call Stack 窗口(ALT+K)根据选定线程的栈,反向跟踪函数调用顺序及函数参数并显示出来。如果函数创建了标准的堆栈框架(push ebp; mov ebp,esp),则这个任务非常容易完成。现代编译器并不会为栈框架而操心,所以 OllyDbg 另辟蹊径,采用一个变通的方法。例如,跟踪代码到下一个返回处,并计算其中全部的入栈、出栈,及 esp 的修改。如果不成功,则尝试另一个风险更大也更慢的方法:移动栈,搜索所有可能的返回地址,并检查这个地址是否被先前的已分析的命令调用。如果还不行,则会采用启发式搜索。栈移动(Stack Walk)可能会非常慢。OllyDbg 仅在调用栈窗口打开时才会使用。

为了使 OllyDbg 调用栈中的函数(尤其是系统模块函数)地址显示出对应的符号名称,便于调试分析,需要通过 OllyDbg 的插件 StringOD 配置符号文件加载功能:

首先下载 StrongOd 插件(v0.2.6.413 以上版本),并将下载符号库的相关文件(6 个文件:dbgeng.dll、dbghelp.dll、srcsrv.dll、symbolcheck.dll、symsrv.dll、symsrv.yes)复制到 OllyDbg 的安装目录(可以从 WinDbg 目录下复制)。

打开 OllyDbg,选择 Debug | Select path for symbols,设置符号路径,可以准备一个空目录放置微软符号,也可以设成与 WinDbg 所使用的符号目录。

接着设置 StrongOD 选项,选择 Plugins | StringOD | Options,在出现的配置窗口中勾选 Load Symbols 选项。

之后 OllyDbg 就可以像 WinDbg 一样下载符号文件,此时再打开 Call Stack,就可以清楚地看到 Call Stack 中的系统模块函数名称。

OD: Vulnerabilities Analyze Skills的更多相关文章

  1. OD: Kernel Vulnerabilities Analyze

    内核漏洞大多出没于 ring3 到 ring0 的交互中.从 ring3 进入 ring0 的通道,以及操作系统提供的 API 都有可能存在漏洞.例如:驱动程序中 IoControl 的处理函数,SS ...

  2. OD: Kernel Vulnerabilities

    内核漏洞概述 内核漏洞的分类 运行在 Ring0 上的操作系统内核.设备驱动.第三方驱动能共享同一个虚拟地址空间,可以完全访问系统空间的所有内存,而不像用户态进程那样拥有独立私有的内存空间.由于内核程 ...

  3. OD: ActiveX Vulnerabilities

    通过一个精心构造的页面 exploit 第三方软件中的 ActiveX 已经成为一种惯用攻击手段,众多知名软件公司都曾被发现其注册的 ActiveX 中存在严重的缓冲区溢出漏洞,一个被广泛使用的第三方 ...

  4. OD: File Vulnerabilities & Protocols & Fuzz

    IE.Office 等软件有个共同点,即用文件作为程序的主要输入,但攻击者往往会挑战程序员的假定和假设. 文件格式 Fuzz 就是利用畸形文件测试软件的稳健性,其流程一般包括: * 以一个正常文件作为 ...

  5. OD脚本指令集

    声明: 1.本指令集搜集自各论坛.博客,欢迎补充讨论 OD脚本指令集 在后面的文档中, “源操作数” 和 “目的操作数”表示以下含义: - 十六进制常数,既没有前缀也没有后缀. (例如:是00FF, ...

  6. Summary of Critical and Exploitable iOS Vulnerabilities in 2016

    Summary of Critical and Exploitable iOS Vulnerabilities in 2016 Author:Min (Spark) Zheng, Cererdlong ...

  7. Oracle索引梳理系列(十)- 直方图使用技巧及analyze table操作对直方图统计的影响(谨慎使用)

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  8. Linux之od命令详解

    功能说明:输出文件内容.语 法:od [-abcdfhilovx][-A <字码基数>][-j <字符数目>][-N <字符数目>][-s <字符串字符数&g ...

  9. 基本shell编程【3】- 常用的工具awk\sed\sort\uniq\od

    awk awk是个很好用的东西,大量使用在linux系统分析的结果展示处理上.并且可以使用管道, input | awk ''  | output 1.首先要知道形式 awk 'command' fi ...

随机推荐

  1. IOS“多继承”

    转自念茜的博客: 当单继承不够用,很难为问题域建模时,我们通常都会直接想到多继承.多继承是从多余一个直接基类派生类的能力,可以更加直接地为应用程序建模.但是Objective-C不支持多继承,由于消息 ...

  2. 应用mysql(Linux中安装)

    当前 mysql 官网的安装教程,指明可以使用 yum 方式. 若在Ubuntu中安装,参考“Linux(Ubuntu)下MySQL的安装与配置”. MySQL YUM Repository MySQ ...

  3. Mysql中类似于nvl()函数的ifnull()函数

    IFNULL(expr1,expr2) 如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2.IFNULL()返回一个数字或字符串值,取决于它被使用的上下文环境. mysq ...

  4. Netty4.0学习笔记系列之二:Handler的执行顺序(转)

    http://blog.csdn.net/u013252773/article/details/21195593 Handler在netty中,无疑占据着非常重要的地位.Handler与Servlet ...

  5. 【HDOJ】2319 Card Trick

    水题,STL双端队列. /* 2319 */ #include <iostream> #include <cstdio> #include <cstring> #i ...

  6. Linux下高并发网络编程

      Linux下高并发网络编程 1.修改用户进程可打开文件数限制 在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时, 最高的并发数量都要受到系统对用户单一进程同时可打 ...

  7. 2015第37周一struts2 jstl 标签

    1.在jstl中使用struts2  <c:forEach var="ee" items="${requestScope.serviceList}" &g ...

  8. 数据结构——UVA 1600 机器人巡逻

    描述 A robot has to patrol around a rectangular area which is in a form of mxn grid (m rows and n colu ...

  9. HDU1050(Moving Tables:贪心算法)

    解题思路: 这种做法是基于hdu2037的做法上考虑的,找出所有可以同时搬运的桌子,然后就很方便求出最短总时间. 还有一种更简单的做法是直接遍历一遍找出与别的重复次数最多的那片区域,重复次数*10就可 ...

  10. Linus:为何对象引用计数必须是原子的

    Linus大神又在rant了!这次的吐槽对象是时下很火热的并行技术(parellism),并直截了当地表示并行计算是浪费所有人时间(“The whole “let’s parallelize” thi ...