Xcon2003_funnywei

Similar documents
linux 下的缓冲区溢出 裴士辉 QQ:

Linux kernel exploit研究和探索

C 1

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

格式化字符串 Weifeng Sun School of Software, DLUT

<4D F736F F D20B5DAC8FDCBC4D5C2D7F7D2B5B4F0B0B82E646F63>

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

NOWOER.OM m/n m/=n m/n m%=n m%n m%=n m%n m/=n 4. enum string x1, x2, x3=10, x4, x5, x; 函数外部问 x 等于什么? 随机值 5. unsigned char *p1; unsigned long *p

《C语言程序设计》第2版教材习题参考答案

zt

幻灯片 1

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

《C语言程序设计》教材习题参考答案

今天刚发现的, 比较简单, 于是就来简单分析下吧 该感染样本很简单, 新加了个区段放病毒执行代码, 执行病毒代码, 最后跳回原入口点来执行原文件 下面就是感染后的代码的简单分析 : ; =============== S U B R O U T I N E =====================

ROP_bamboofox.key

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

C++ 程式設計


1 CPU interrupt INT trap CPU exception

untitled

,768 32,767 32K JMP Jnnn (386+) LOOP CALL [Label:] JMP short/near/far address L10: jmp jmp L20: L10 L20

一 学 校 基 本 情 况 目 录 二 部 门 预 算 报 表 ( 一 ) 收 支 总 表 ( 二 ) 收 入 总 表 ( 三 ) 支 出 总 表 ( 四 ) 财 政 拨 款 支 出 表 三 部 门 预 算 报 表 说 明 ( 一 ) 收 支 总 表 说 明 ( 二 ) 收 入 总 表 说 明 (

目 录 一 学 校 基 本 情 况 二 2016 年 预 算 报 表 ( 一 ) 中 南 大 学 收 支 预 算 总 表 ( 二 ) 中 南 大 学 收 入 预 算 表 ( 三 ) 中 南 大 学 支 出 预 算 表 ( 四 ) 中 南 大 学 财 政 拨 款 支 出 预 算 表 三 2016 年

信息参考

Microsoft Word - 15dbtb007

Microsoft PowerPoint - 05-第五讲-寻址方式.pptx

静态分析 投放文件 行为分析 互斥量 (Mutexes) 执行的命令 创建的服务 启动的服务 进程 cmd.exe PID: 2520, 上一级进程 PID: 2556 cmd.exe PID: 2604, 上一级进程 PID: 2520 访问的文件 C:\Users\test\AppData\Lo

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

untitled

chap07.key

untitled

BOOL EnumWindows(WNDENUMPROC lparam); lpenumfunc, LPARAM (Native Interface) PowerBuilder PowerBuilder PBNI 2

OOP with Java 通知 Project 3: 3 月 29 日晚 9 点 4 月 1 日上课

OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac)

第3章.doc

Linux 操作系统分析 Chapter 9-2 Linux 中程序的执行 陈香兰 苏州研究院中国科学技术大学 Fall 2014 November 4,

<4D F736F F D20CEC4BCFEBCB6B6F1D2E2B4FAC2EBC9A8C3E8D2FDC7E6D6D0B5C4BCD3BFC7CAB6B1F0BCBCCAF52E646F6378>

Guava学习之Resources


mvc

Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式]


CC213

SDK 概要 使用 Maven 的用户可以从 Maven 库中搜索 "odps-sdk" 获取不同版本的 Java SDK: 包名 odps-sdk-core odps-sdk-commons odps-sdk-udf odps-sdk-mapred odps-sdk-graph 描述 ODPS 基

<4D F736F F F696E74202D ABE1A4A420A4A4C2E5BEC7B7A7BDD720C2E5BEC7B7BDAC79BB50B56FAE6920ADD9B0B7AFE82E BACDBAE65BCD2A6A15D>

CC213

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

OOP with Java 通知 Project 4: 5 月 2 日晚 9 点

新版 明解C++入門編


考 試 日 期 :2016/04/24 教 室 名 稱 :602 電 腦 教 室 考 試 時 間 :09: 二 技 企 管 一 胡 宗 兒 中 文 輸 入 四 技 企 四 甲 林 姿 瑄 中 文 輸 入 二 技 企 管 一

新・明解C言語入門編『索引』

Converting image (bmp/jpg) file into binary format

_汪_文前新ok[3.1].doc

Untitled

untitled

"\x33\x31\x43\x17\x83\xeb\xfc\x03\x6b\x0c\xa6\x2b\x97\xda\xaf" "\xd4\x67\x1b\xd0\x5d\x82\x2a\xc2\x3a\xc7\x1f\xd2\x49\x85\x93" "\x99\x1c\x3d\x27\xef\x8

Microsoft PowerPoint - 微原-第3章2.ppt [兼容模式]

untitled

untitled

C6_ppt.PDF

ChinaBI企业会员服务- BI企业

}; "P2VTKNvTAnYNwBrqXbgxRSFQs6FTEhNJ", " " string imagedata; if(0!= read_image("a.jpg",imagedata)) { return -1; } string rsp; ytopen_sdk m_sd

Microsoft PowerPoint - XCon2010_win7_cn.ppt [兼容模式]

且编写我们的利用程序, 到最后, 会简单讲一下, 这个漏洞的修补. 首先我们来了解下溢出产生的原因. 打开 windbg, 附加到 msue 进程上, 然后在 kernel!readfile 处下断点, 再用 muse 打开我们之前做好的 test.m3u( 注 : 在这个过程中, 会多次断在 Re

Microsoft Word - 实用案例.doc

《计算概论》课程 第十九讲 C 程序设计语言应用

数据库系统概论

Microsoft PowerPoint - Ch3-8086CPUæ„⁄令系ç»�(3)-æŁ°æ“®ä¼€é•†æ„⁄令

Microsoft Word - 〈出師表〉補充講義-1214.doc

本次习题课中提到的 课本, 均指机械工业出版社的 Intel 微处理器 ( 原书第八版 ) 中文版, 使用其他版本课本的同学需要自己对应

ebook8-30

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

Microsoft Word - 永政发〔2016〕48号.doc

06721 main() lock pick proc() restart() [2][4] MINIX minix2.0 GDT, IDT irq table[] CPU CPU CPU CPU (IDTR) idt[] CPU _hwint00:! Interrupt

目 录 一 学 校 概 况... 3 ( 一 ) 学 校 基 本 情 况... 3 ( 二 ) 部 门 决 算 单 位 构 成... 7 二 2015 年 部 门 决 算 报 表...7 表 1: 高 等 学 校 收 支 决 算 总 表... 8 表 2: 高 等 学 校 收 入 决 算 表...

untitled

中 国 银 行 江 西 省 分 行 九 江 市 分 行 江 西 分 行 九 江 市 分 行 修 水 支 行 营 业 部 江 西 省 修 水 赣 北 钨 业 有 限 公 司 中 国 银 行 江 西 省 分 行 九 江 市 分 行 江 西 分 行 九 江 市 分 行 修 水 支 行 营 业 部 深 圳

动画光标文件(

提纲. 1 实验准备. 2 从实模式进入保护模式. 3 小结 陈香兰 ( 中国科学技术大学计算机学院 ) 软件综合实验之操作系统 July 1, / 11

华恒家庭网关方案

<4D F736F F D20C7B6C8EBCABDCFB5CDB3C9E8BCC6CAA6B0B8C0FDB5BCD1A75FD1F9D5C22E646F63>

> u eip l 3 002f2aa9 90 nop 002f2aaa 90 nop >!chkimg -d -lo 1 ping // 检查文件是否被篡改? 002f2aa7-002f2aaa 4 bytes - ping!maincrtstartup [ e :f0 cc 9

<4D F736F F D20D1A7C9FACAD6B2E1B8C4D7EED6D5A3A8B4F8B1EDB8F1BCD3D2B3C2EBB0E6A3A9372E3239>

桂林市劳动和社会保障局关于

第三章 維修及管理

Microsoft Word 年度选拔硕博连读研究生的通知.doc

01

无类继承.key

PowerPoint Presentation

國立臺東高級中學102學年度第一學期第二次期中考高一國文科試題

Page 2 of 12

Microsoft Word - Sunday

鎶ョ焊0

秘密大乘佛法(下)

!! :!!??!!?!??!!!... :... :'?'?! :' ' :'?' :'?' :'!' : :? Page 2

Transcription:

缓冲区溢出漏洞发掘模型 作者 :funnywei 日期 :2003.12

内容摘要 简介 (Introduction) 相关工作 (Related Work) 我们的模型 (Our Model) 总结 (Conclusion)

简介 研究的必要性 C 和 C++ 语言仍然是开发的主要工具 缓冲区溢出攻击已成为主要攻击手段

相关工作 (Related Work) 静态检测 (Static Detection) 动态检测 (Dynamic Detection) 主要分为动态和静态检测两种方法, 其中静态检测工具主要针对源码做相应检测, 而动态检测工具主要从对二进制程序运行时保护的角度出发

静态检测工具 第一代 :lint 第二代 :Splint 和 LClint 第三代 :Flowfinder,RATS,ITS4

动态检测工具 FIST(Fault Injection Security Tool) Libsafe 和 Libverify Stack Shield

我们的检测模型 静态分析 动态分析和测试

静态分析 目的 : 得到子过程调用的关系图, 以便后续的分析 每一个子过程作为图中的一个节点, 同时不安全的函数也作为一个节点存在 方法 : call 和 ret 指令搜索 编译器优化和特征码匹配 缓冲区边界的定位 辅助 : 基于污点传播的双向数据流分析

有向图举例 : fun(char * arg) { char src[100] = { This is a test }; strcpy(arg, src); printf( %s \n, arg); } main() { char dest[100]; fun(dest); printf( %s\n, dest); }

有向图节点记录 子函数的起始位置 函数所分配的堆栈大小 函数局部变量的使用情况 调用者传递给函数的参数 调用者调用本函数的地址 ( 即函数调用的返回地址 )

call 和 ret 指令搜索 采用深度优先或者广度优先的搜索算法

编译器优化和特征码匹配 编译器对程序进行了优化以提高执行速度, 有些函数 ( 如 strcpy,strcat) 被硬编码到程序中 如 :strcpy() main() { } char dest[100]; char src[100]; gets(src); strcpy(dest,src); return;

VC 6.0 编译器 思想 : 只要在程序中以 ECX 为核心对指令进行匹配, 同时配合这三条字符串操作指令, 就可以定位 strcat 和 strcpy repne scas byte ptr [edi] ; 扫描源字符串, 长度存放在 ecx 中 not ecx... mov EnX, ECX... shr ecx, 2 rep movs mov ecx, and ecx, 3... rep movs dword ptr [edi],dword ptr [esi] Enx byte ptr [edi],byte ptr [esi]

VC 7.0 编译器 strcpy 函数也会被硬编码到程序中去, 但是它产生的二进制码却和 VC6.0 产生的二进制码有很大的区别 strcpy 硬编码如下 : 00401041 mov cl,byte ptr [esp+eax] 00401045 mov byte ptr [esp+eax+14h],cl 00401049 inc eax 0040104A test cl,cl 0040104C jne 00401041 因为在这些硬编码的代码中使用了相对基址变址寻址方式, 所以在 VC7.0 下简单提取 strcpy 的固定二进制特征码比较难, 但是我们可以结合指令的语义进行分析, 来构建 strcpy 函数的特征码

缓冲区边界的定位 Libsafe 对缓冲区估算采用最大化到栈帧的方法 本文思想 : 根据指令对内存单元访问情况来界定缓冲区 边界 方法 : (1) 通过分析未直接访问的堆栈单元来确定目标缓冲区长度 (2) 根据局部变量的访问方式来确定目标缓冲区的长度 (3) 通过其他方法判断缓冲区长度

通过分析未直接访问的堆栈单元来确定目标缓冲区长度 对于普通的变量, 如果没有在程序中被使用, 那么程序将不会为其在堆栈中保留地址空间 但是对于数组字符数组来说, 只要数组中有一个成员被访问, 程序就会在堆栈中为整个数组保留地址空间 然而在编译后的程序中没有任何一条指令对其余的地址空 间进行访问 int main(int argc, char* argv[]){ char dest[100] = { this is me }; printf("%s", dest); strcpy(dest, "this is a test"); return 0;}

首先, sub esp,64h 在堆栈中保留 0x64 个字节的空间 其次, 根据 特征码匹配和非安全函数调用匹配找到字符缓冲区的起始位置 : 0040101E 56 push esi 0040101F 57 push edi... 0040105D 8D 54 24 08 lea edx,[esp+8]... 00401065 8B FA mov edi,edx... 0040106A F3 A5 rep movs dword ptr [edi],dword ptr [esi] 由此, 我们可以认为字符缓冲区的起始位置为 esp+8 由于有压栈的 操作,ESP 的值不固定, 我们用 base 来代表程序开始时 sub esp,64h 所指向的位置 esp+8 所指向的位置其实就是 base

然后可以分析以 ESP,EBP 为基址寄存器的指令 : 00401015 89 44 24 00 mov dwordptr [esp],eax 0040101E 56 push esi 0040101F 57 push edi 00401020 89 4C 24 0C mov dword ptr [esp+0ch],ecx 00401024 88 44 24 12 mov byte ptr [esp+12h],al 00401033 66 89 54 24 10 mov word ptr [esp+10h],dx 由上可以看出在程序保留的变量中, 有很大一部分都没有被指令所访 问, 只是通过 rep stos dword ptr [edi] 将其设为 0, 而通过前面的分析 已经知道对于普通变量来说, 如果没有被指令直接访问就不会为其在 堆栈中保留地址空间, 所以, 我们就可以认为, 这些地址空间都在字 符数组中

根据局部变量的访问方式来确定目标缓冲区的长度 main() { } char dest[36] = { this is a test }; int a = 1; printf( %s,%d,dest, &a); 对于普通变量来说, 如果只是作为目的操作数而从来没有作为源操 作数使用, 那么它将肯定被编译器优化掉 但是对于数组来说, 即 使其某个成员从头到尾都作为目的操作数而存在, 它也不会被编译 器优化掉 通过这个特性, 我们就可以确定缓冲区的边界

在这个程序的汇编代码中没有出现 rep stos 指令, 字符数组的初始化都是通过 mov 指令来完成的, 所以, 我们不能通过查找没有直接使用的地址来判断缓冲区的长度 在这个程序中, 只有两条指令用堆栈中的变量作为源操作数, 0040103B 8D 54 24 00 lea edx,[esp] ; 取变量 a 地址... 00401043 8D 44 24 04 lea eax,[esp+4] ; 取字符串首址对于堆栈中其他的地址空间来说, 它们都没有被用作源操作数, 所以根据我们对编译器优化局部变量原则的分析, 我们可以认为这些地址所指向的存储单元都位于字符缓冲区中

通过其他方法判断缓冲区长度 有些程序来说, 在分配了缓冲区后首先调用函数对其进行初始化 只要找到相应的 API 函数调用就很容易判断出目标缓冲区的大小和起始位置 char dest[100];... ZeroMemory(dest, 100);... memset() 函数在 Release 版本的程序中会被编译成一条汇编语句 rep stos

基于污点传播的双向数据流分析 思想 : 来源于 Perl 中称为 tainting 的机制 监控所谓的 不可信数据, 通常是由用户输入的, 将这些输入标记为 tainted 污点数据通过程序语句进行传播 污点来源 : 环境变量, 参数, 文件, 网络输入 污点传播在源码检测中的运用 在二进制代码中的应用 双向数据流分析方法

污点传播在源码检测中的运用 在数据类型前, 加一个 tainted 类型限定词表示该数据来源于一个不可信数据源 例如 : int main(int argc, tainted char *argv[]); 例 :wuftpd 2.6.0 的格式化字符串漏洞 ----site_exec ----lreply ----vreply

简化看作 : while(fgets(buf, sizeof buf, f)){ lreply(200, buf);} void lreply(int n, char *fmt, ){ vsnprintf(buf, sizeof buf, fmt, ap); } 现实中 format string 的例子并不太可能是显式的使用 prinft(buf) 这么容易检测 而且多数情况下, 真正出错的地方很有可能与最终调用 vsnprinft,prinft 的函数并不在一个源文件中 例如, 上面所举的 wuftp site exec 例子, 其 分别在 ftpcmd.y 文件中 ftpd.c 文件中

偏序关系考虑例子 : void f(tainted int); untainted int a; f(a) f 期望的是 tainted 数据, 而传入的是 untainted 的参数 允许! 考虑第二个例子 : void g(untainted int); tainted int b; g(b); 在这种情况下,g 期望 untainted 而得到 tainted 的数据, 不允许! 把两个例子结合起来, 我们得到下面的偏序关系 : untainted int < tainted int

在二进制代码中的应用 双向数据流分析方法 一是从污点数据流开始分析, 自上而下形成一棵传播树 (Propagation Tree) 二是从 strcpy 等可能出错的函数开始, 向上回溯 找到两者相交的位置, 从而产生污染流路径 (Tainted Flow Path) 当然相交的位置可能不止一处, 那么将产生多条污染流路径

动态分析及测试过程 思想 : 动态拦截所有可疑的函数, 在拦截时创建当前调用的虚拟栈列表 在栈列表中, 记录所有函数缓冲区的情况 对于可疑函数所使用的缓冲区, 先分析它是位于堆中还是在栈中 接着, 获得相应的数值化描述信息, 最后与限制条件相比, 得到分析结果

虚拟栈 虚拟栈用来记录栈的调用情况 同样, 在分析的过程中还可以很方便的定位出所分析的字符缓冲区在堆栈中的位置, 生存周期 等

缓冲区数值化技术及限制条件的产生 David Wagner 等人在参考文献 [1] 中将缓冲区溢出的检测问题规范化为整数限制的问题, 并定义了限制语言 (Constraint Language)

限制条件的产生 符号 len(s) 表示当前使用的长度 ( 包含结束字符 \0 ), 范围属性为 [a, b] Alloc(s) 表示 buffer 实际分配的大小, 范围属性为 [c, d] 在对所有的变量进行了范围推断之后, 再进行安全属性检查 : 如果 b<c, 溢出不可能发生 如果 a>d, 那么肯定发生 如果 d>b>c>a, 那么溢出有可能发生

堆指针检测的红黑树结构及魔数定位法 思想 : 拦截堆内存的分配函数 ( 例如,Windows 下拦截 RtlHeapAlloc,Linux 下拦截 malloc) 在每次成功分配堆内存的时候, 采用红黑树记录堆指针, 或者在刚分配的堆内存的起始位置记录 Meta Data 信息

红黑树 (Red/Black Tree) 检测 树中的每个节点对应于一个已分配内存, 其关键字包含 block 的起始和结束地址 其插入和删除的时间复杂度为 O(logn), 采用红黑树而不采用二叉树主要是为了避免最坏情况的产生 导致时间复杂度为 O(n) 例子 :addr(a1)<addr(a2)< <addr(a5)

魔数定位法 (Magic Number Location) 思想 : 使用一个特殊的数据结构记录在动态内存的开始地址, 叫做 Meta Data 采用魔术定位法可以减少插入和删除的复杂度 其搜索时间为 O(1), 即线性时间

在每个分配的动态内存块的开始部分插入一个头部, 来存储特定的元数据 元数据包含两个部分, 一个是魔数, 一个是表的索引值 魔数是元数据的第一部分, 它是精心选择的一个数, 在正常的用户程序里不太可能出现 表的每条记录包含了已分配块的地址和大小 对于指针 p, 搜索其前面的内存来匹配魔数 如果没有匹配, 就不可能是一个内存块的起始位置 反之, 如果匹配, 那么就有可能是我们找到了起始点 当然, 很有可能魔数在用户区域里巧合 在魔数相匹配后, 再根据 index 查找表中的相应位置存储的 Start 值来比较起始地址是不是和分配块的地址一致

进程跟踪与调试 捕获函数调用异常 ( 对于 Windows 而言 ) DebugActiveProcess attach 到一个活动进程 终止调试使用 DebugActiveProcessStop 任何时候, 被调试的进程发生发生异常都会产生 EXCEPTION_DEBUG_EVENT 事件, 可能的异常包括试图访问不可访问的内存, 执行断点指令, 试图被 0 除, 或者任何其他 SEH 处理的异常 Ptrace 跟踪,LKM 拦截异常 ( 对于 Linux) *NIX 系统下可以采用可加载内核模块 (LKM) 拦截系统的异常中断 具体方法可以参考 Phrack 61 的 Hijacking Linux Page Fault Handler Exception Table

发生异常时的现场数据保护 现场记录的信息包括 : 线程上下文 程序加载的模块信息 调用栈信息 虚拟栈信息 线程上下文 GetThreadContext 被监视进程的符号表 SymInitialize 加载 遍历被监测进程的堆栈 StackWalk 遍历 程序加载的模块信息 EnumerateLoadedModules 虚拟栈信息 -- 保存, 便于定位出错

总结 试图提出一个针对缓冲区溢出的发掘模型, 但还有很多工作没有做 包括 Fuzzer 的自动化教本引擎等工作 同时, 本文所叙述的工作中, 仍有许多并没有进行效率的测试和在实践中进行检测 这都需要在将来进行完善和测试

Thanks!