分析来源:https://www.exploit-db.com/exploits/39008/
为什么去分析它呢,来源于k0shl在i春秋的课程
目录
在csdn用markdown写,也直接上传md文件吧
http://blog.csdn.net/u012763794/article/details/66970749
EFS Web Server是一个可以通过web端管理服务器文件的软件,发送GET请求长度过长会触发缓冲区溢出漏洞
分析来源:https://www.exploit-db.com/exploits/39008/
WinXP sp3 中文版
EFS Web Server7.2
immunity debugger
windbg
IDA
mona
由于作者使用的覆盖SEH程序的地址在ImageLoad.dll中,没ASLR,所以利用比较稳定,打开就弹出计算器
我们将payload该成全是A吧,buff = "A"*4500
windbg附加后运行,发送我们的4500个A
我们看到发生了一个应用异常,可以看到eax的值为0x41414141,那么eax的值我们是可以控制的咯,那具体是不知可以覆盖SEH,跟着这里引发异常,导致可以执行我们的shellcode呢
那我们看看eax的值来源于哪里呢,ida打开sqlite3.dll,定位到如下函数
看到这里只知道eax来源于上层函数
我们看看堆栈调用
根据第一个返回地址61c6286c
我们定位到_sqlite3LockAndPrepare函数
这里还是没看到eax的来源
那我们还是看fsws.exe的004968f4
吧
我们在sub_4968D0函数开头下断
第三次断下来就看到ecx指向我们的41414141
了
那这个0x41414141
是什么时候复制到栈上的呢
我们对02057058
下一个写入断点吧
在这里暂停了下来
我们用ida看看这个地址,分析多了,看到这个write_char,就会联想上层调用了sprintf
那我们看看堆栈信息
确实004f9698
在sprintf函数内
那我们继续看下一个返回地址
我们看看最后拼接的语句:bp 00497745
第一次断下来,我们执行到sprintf函数,看看栈上的参数
这么长的畸形字符串复制到栈上,使用sprintf格式化前有进行加成,这就造成栈溢出了
看看确实拼接成sql语句了
最后拿去给给sqlite3.dll处理的时候造成异常
具体路径如下,sprintf执行完下一条语句是调用sub_4968D0函数
sub_4968D0
->sqlite3_prepare_v2
->sqlite3LockAndPrepare
->sqlite3SafetyCheckOk(在这函数里面异常)
那么0154249c
上的畸形字符串哪里来,来源于sub_52DF03函数的memcpy函数的复制
作者使用的是覆盖SEH的方法,那是不是只能覆盖SEH呢?(是不是没执行到ret指令程序就崩溃掉了呢)
我们看看返回地址有多远
char v15; // [sp+20h] [bp-100Ch]@3
我们要溢出的buf距离ebp都㓟0x100c,即4108个字节
当然函数这里没有生成栈帧
那我们看看触发异常获取栈上02057058的值
那是可以覆盖返回地址的,我们尝试用4150个A
!mona pattern_create 4150
计算一下
!mona pattern_offset 0x38664637
地址是4073(为什么比v15距离ebp的4180字节要小呢,因为前面还有sql语句的长度啊,O(∩_∩)O哈哈~)
但是下面的payload没起作用,服务器也没崩,调试也正常返回了
buff = "A" * 4073 + jmp_esp + "\x90" * 20 + shellcode
那为什么之前eip会是0x38664637
呢
跟踪一下看看,确实会retn到0x38664637
是不是我们的payload有什么问题呢
通过调试进一步排查,是触发了异常,也是一开始我们所看到的异常,
我们向前回溯看看这个eax的值来源于02057058,值是391c5a09
我们再看看我们的shellcode,从倒数第二个字节起向前数4个字节,刚好是0x391c5a09
,那说明是我们的shellcode过长,覆盖到了上一函数栈帧的数据,导致异常的发生
那怎么解决?
对于第二点我发现过短了
buff = "A" * 4073 + jmp_esp + "\x90" * 12 + shellcode
调试发现没有复制0154249c
的0x41414141
而且也不是where name,应该后面的数据影响了
在后面加3个\x90
就会异常
最后排查测试,这样是可以执行jmp esp的
buff = "A" * 4073 + jmp_esp
那我们在后面搞个先前跳转不就行了?
最终exp:
当然你也可以将shellcode改为弹窗的(注可能有些shellcode不能执行,有些位置的某些字符可能影响程序的执行流程或者sql查询的结果)
下面看看我们弹窗效果
那使用覆盖SEH是不是没遇到这么多麻烦呢?
首先定位SEH
可以看到位置为4061,跟作者的exp写的是一样的,但这里是NEXT SEH的位置而已哦
我们先看看作者的思路
我们看到暂停下来后,确实到了我们伪造的SEH程序处理的位置
其实windbg比较难看
我们用od吧^_^
下面是在系统异常处理的时候获取我们伪造的SEH程序的位置
我们看看执行到10019798时,栈的情况,发现esp+8的位置就是我们之前NEXT SEH的位置
不信看图
最后在Next SEH的指令跳过了垃圾代码,从而执行shellcode
就是下面这一串,作者为什么加
如果不加,程序的执行流程有点变化有点问题,从而触发不了异常
那么是不是一定要加到4500那么长呢,肯定不是啊
我在最后加50个A也行啊,10个A也行,甚至4个A也行
3个就不行了(但是3个的时候又不是那个问题,调试了一下发现程序的执行的流程,拼接的sql语句没问题,问题是最后拼接3个A的话,竟然没导致异常,从而不能触发SEH,而是执行到了函数最后的ret指令,返回到了0x90909090处了,导致最后不能正确执行shellcode)
那怎么让后面接3个A也行呢,就是将payload中shellcode的前9-12个0x90替换为jmp esp的地址即可,不信看看下面是不是这样
但是为什么这样?,这是一个需要进一步探索的问题
下面这个是最后加50个A的payload,buf的值
使用安全的snprintf,或者对字符串长度进行限制
由于使用sprintf格式化sql语句查询的时候对长度没有严格限制,导致缓冲区溢出,漏洞利用无论是覆盖返回地址还是覆盖SEH都有一些坑
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课