一、 *实验目标*

(1) 了解SEH攻击及虚函数攻击的基本原理

(2) 通过调试SEH攻击代码,理解Windows异常处理机制,掌握针对SEH的攻击方式,并利用OllyDbg跟踪异常状态。

(3) 调试虚函数攻击代码,理解虚函数工作机制与内存分布方式,掌握基本的虚函数攻击与计算方式,并可以用OllyDbg追踪。

二、 *测试步骤与结果*

(一)实验一:通过调试SEH攻击代码,理解Windows异常处理机制,掌握针对SEH的攻击方式,并利用OllyDbg跟踪异常状态。

  1. 阅读代码

img

  1. 为了能触发int 3断点时启动OllyDbg,我们选择选项中的实时调试设置选择设置OllyDbg为实时调试器,然后当我们运行exe文件时,int 3 断点触发后就会启动OllyDbg:

img

  1. 运行SEH.exe,发现要求创建UDD目录:

img
按照要求创建UDD目录:
img

  1. 两个路径设置成功后,重新运行SEH.exe程序,成功在int 3上启动OllyDbg:

img

  1. 在strcpy函数处设置断点,程序运行到此处时观察右下角缓冲区数据,可以看到在执行strcpy函数之前,shellcode的起始地址为0x0012FE48:

img
img

  1. 点击查看菜单中的S.E.H链,可以看到S.E.H链的情况:

img

  1. 查看地址0x0012FF18的记录,发现其指向下一个SEH指针,接着是异常处理程序, 只需要把0x0012FF1C这个地址的内容改成shellcode起始地址即可:

img

  1. 由于shellcode的起始地址为 0x0012FE48,第一个S.E.H地址为 0x0012FF18(指向下一个S.E.H的指针) 0x0012FF1C(异常处理地址),因此shellcode需要使用0x0012FF1C-0x0012FE48=212个字节进行填充,且注释掉__asm int 3。修改后的程序如下:

img

  1. 运行程序,成功出现弹框:

img
此时shellcode已经被执行,但是点击确定却没有反应,这是因为shellcode已经被当作系统异常处理来进行了,所以点击确定不会退出程序。

(二)实验二:调试虚函数攻击代码,理解虚函数工作机制与内存分布方式,掌握基本的虚函数攻击与计算方式,并可以用OllyDbg追踪。

  1. 代码分析如下:

img

  1. 设置VC6的build版本为release:

img

  1. 在strcpy函数处设置断点,程序运行到此处时观察右下角缓冲区数据,可以看到在执行strcpy函数之前,shellcode的起始地址为0x0042E27C:

imgimg

  1. 根据shellcode起始地址0042E27C改写shellcode,shellCode长度为 216 Bytes,换算成十六进制为D8,故shellcode的末尾后四个字节地址是0x0042E27C+0xD8–0x4=0x0042E350。修改后的程序如下:

imgimg

  1. 启动程序,成功出现弹框,shellcode植入成功:

img

三、 *测试结论*

通过本次实验,对SEH的初步理解,S.E.H结构体存放在系统栈中。

如果程序源代码中使用了__try{}__except{}或者Assert宏等异常处理机制,编译器将最终通过向当前函数栈帧中安装一个S.E.H来实现异常处理。栈中的多个S.E.H通过链表指针在栈内由栈顶向栈底串成单向链表,位于链表最顶端的S.E.H通过T.E.B(线程环境块)0字节偏移处的指针标识,FS寄存器指向TEB的位置。当异常发生时,操作系统会中断程序,并首先从T.E.B的0字节偏移处取出距离栈顶最近的S.E.H,使用异常处理函数句柄所指向的代码来处理异常。因此S.E.H存放在栈内,溢出缓冲区的数据有可能淹没S.E.H。精心制造的溢出数据可以把S.E.H中异常处理函数的入口地址更改为shellcode的起始地址。当Windows开始处理溢出后的异常时,会错误地把shellcode当做异常处理函数而执行,从而达到攻击效果。

对于虚函数攻击,一般在一个类中一旦有多态产生就会有虚函数表存在,该表一般位于类的成员变量上方。当实例化一个类时,成员函数与静态成员都不算在类对象内部。只算成员变量的大小,所以也可以那么认为: 存储类实例化对象上方就是虚函数表的地址。在这种情况下,假设类中有栈内有分配了空间,那我们用指针就可以寻找到该空间的上面4字节(32位)就可以修改对应的虚表指针转到自己的shellcode上了,在调用了对应的虚表指针指向的虚函数,就相当于调用了自己的shellcode了。

四、 *思考题*

针对Arrayindexerror数组索引思考题程序,在不修改源代码的情况下,研究如何攻击目标代码,并调用bar函数。

  1. 查看源码发现,需要传入两个参数

img

  1. 尝试传入参数 1 2 ,步进查看返回信息

img
需要将转跳地址改为0x00401005才能实现bar转跳。

  1. 返回地址位置打断点,查看返回指针位置

img
找到返回地址0x00430068
img

  1. 因此要回溯到bar地址

img
即0x0012FFC4-0x00430068=0xFFCF FF5C。由于输入信息为int型,因此计算是按照四倍计算,需要除4得到结果,即0xFFCF FF5C/4 = -786514。
第二个参数为bar的地址10进制0x00401005 = 4198405。因此传入参数 -786514 4198405
img

  1. 重新运行程序

img
运行成功
img