KingView 6.53漏洞学习研究

类别:堆溢出

描述:此漏洞存在于KingView6.53软件的HistorySvr.exe进程中,这个软件服务程序在TCP 777端口监听时收到一个超长请求,导致堆缓冲区溢出从而执行任何代码。

参考资料:《Metasploit魔鬼训练营》p225-p232

 

下载此漏洞的利用代码:http://downloads.securityfocus.com/vulnerabilities/exploits/45727.rb

发现这个利用代码中没有针对windows 2003的target,所以直接攻击不能成功

 但是查看靶机,会发现HistorySvr.exe这个进程已经消失了(如果没消失,多试几次exploit)。这说明应该是成功溢出了,只是没有顺利执行Shellcode。

 

为了解决这个问题,我们可以通过OllyDbg在系统默认的异常处理函数运行前,进入程序异常时的现场。

在OllyDbg中开启”Just-in-time debugging

重启HistorySvr.exe后,再次攻击,OllyDbg截获异常。发现此时eax寄存器的值正式源代码中对应target的Ret值!

                

再观察中断处的代码

通过view->log可以看到中断的地址和原因

这说明异常发生时这一块内存空间并没有被分配使用,因此触发了异常。

总的来说,这次攻击我们成功地用Ret值覆盖了eax寄存器,但是需要将Ret值改为针对windows 2003的值才能成功将程序劫持到Shellcode处。所以接下来应该寻找Shellcode在内存中的位置。

 

我们在攻击模块代码中增加一个target,Ret值先随便设一个:

 52                         [ 'Windows 2003 SP0 EN', {'Ret' => 0x00A1FB84} ], #New target    

    --snip--

85 elsif target.name =~ /2003 SP0/ 86 87 #sploit << make_nops(1024) 88 sploit << make_nops(1020) 89 sploit << "ABAC" #作为查找Shellcode的特殊标记 90 sploit << payload.encoded 91 sploit << "\x44"*(31752-payload.encoded.length) 92 sploit << [target.ret].pack('V')

在msfconsole中reload这个模块,靶机开启HistorySvr.exe,设置target为2后,再次攻击。

 

靶机OllyDbg截获异常,通过在内存中查找ASCII字符“ABAC”,成功找到我们Shellcode的地址。

可知shellcode地址位于0x00CD04C4

Ret地址改为0x00CD04B4(0x00CD04C0-0xC)

而在0x00CD04C0地址上的内存应是Shellcode的地址,代码中"ABAC"的位置相应改为"\xC4\x04\xCD\x00"。

修改源代码后,重新载入模块并exploit,试了3次,终于成功!

 

****************************************************************************************************************************

KingView堆溢出安全漏洞原理分析

由于操作系统对堆内存的管理在调试态和非调试态存在区别,所以不同于前面的攻击,这次先用OllyDbg附加HistorySvr.exe,同时启用HideOD插件,然后让程序运行起来,并在WSOCK32.dll模块的接收数据recv函数处下断点

为了方便调试,将攻击模块代码中的 sploit << "\xC4\x04\xCD\x00" 改为“ABCC”。

然后进行攻击。

OllyDbg加载程序在接受网络数据时就会中断,用“ctrl+f9”执行到返回,来到nettrans.dll模块。

这段代码的作用相当于  memcpy(destbuf, sourcebuf, size)。

就是将接收到的网络数据保存在buf中,然后按接收的长度,将buf 的数据复制到另外一段缓冲区中。

所以我们要得到的是这3个参数,destbuf, sourcebuf, size。

在0x00322A9E和0x00332AB9处下断点,从攻击机进行exploit

(但是从metasploit攻击后,在靶机OllyDbg上需要迅速按f9才能多次在nettrans.dll模块和wsock32.dll模块中跳转。慢的话按两三次f9就不动了。这样就不够时间观察了。.我猜可能是没被接收的数据包超时就被丢弃了吧。。我的解决办法就是通过录像软件来分析)

 

①攻击后程序会停在wsock32.recv函数的入口处,此时观察栈可以得到sourcebuf为0X00CCC0C4:

②按f9后程序来到nettrans模块的0x00332A9E处,此时eax寄存器为复制长度size

前两次是,最后一次是

③停在0x00322AB9时edi的值为destbuf的地址

第一次为;第二次为;第三次次为

程序分3次一共接收了0x800C字节数据。

 

找到源缓冲区起始地址之前的内容

这里块首的0x180B是堆空间大小。

结合这些我们可以算出目的缓冲区的最大大小为0x8000

也就是说而第三次的起始地址0x00CD80C4之后已经是超出目的缓冲区的边界,造成了溢出!

最后一次复制前时内存0x00CD80C4地址处的内容为

我们覆盖掉的函数地址是原本为 18 84 33 00 那里。意味着原来应该执行的是[0x00338418+C]处的代码。

 

这里有几个疑问:

1、不知道怎么确定堆块块首。块首与buffer地址相隔0x2c,不知道这0x2c怎么算的;

2、按书上说的,从蓝色的地方开始是堆块的数据部分起始地址,其中的数据和书上相似但不完全一样。我不清除这些蓝色部分的数据代表的是什么。

针对以上疑问的补充:

1、应该是直接从buffer地址往前分析内存中的内容,直到找到符合堆块块首结构的地方为止。这一步的目的主要是确定源缓冲区和目的缓冲区都在此堆块中,从而明确这是一个堆溢出漏洞。除此之外就和后续的分析没什么关系了。

2、可根据书中P187页的堆块结构来分析。 

总结

最后用书上的话来总结吧:

KingView堆溢出漏洞可以被成功利用的原因,是程序在分配堆块后在块尾维持了一个数据结构,而其中包括一个函数指针地址(也就是“ABCC”所在的位置),程序之后会根据这个地址去执行相应的函数,渗透利用代码通过堆溢出漏洞覆盖这个函数指针,使Shellcode得以执行。

调试的时候用ABCC去覆盖了函数指针地址,所以最后会显示错误:

 

posted @ 2016-03-10 14:21  燃烧少年的心  阅读(1495)  评论(3编辑  收藏  举报