冰河浅析 - 揭开木马的神秘面纱
作者: shotgun·yesky
前 言
在网上,大家最关心的事情之一就是木马:最近出了新的木马吗?木马究竟能实现哪些功能?木马如何防治?木马究竟是如何工作的?本文试图以我国最著名的木马之一 冰河为例,向大家剖析木马的基本原理,为大家揭开木马的神秘面纱。
木马冰河是用C++Builder写的,为了便于大家理解,我将用相对比较简单的VB来说明它,其中涉及到一些WinSock编程和Windows API的知识,如果你不是很了解的话,请去查阅相关的资料。
一、基础篇(揭开木马的神秘面纱)
无论大家把木马看得多神秘,也无论木马能实现多么强大的功能,木马,其实质只是一个网络客户/服务程序。那么,就让我们从网络客户/服务程序的编写开始。
1.基本概念:
网络客户/服务模式的原理是一台主机提供服务(服务器),另一台主机接受服务(客户机)。作为服务器的主机一般会打开一个默认的端口并进行监听(Listen), 如果有客户机向服务器的这一端口提出连接请求(Connect Request), 服务器上的相应程序就会自动运行,来应答客户机的请求,这个程序我们称为守护进程(UNIX的术语,不过已经被移植到了MS系统上)。对于冰河,被控制端就成为一台服务器,控制端则是一台客户机,G_server.exe是守护进程, G_client是客户端应用程序。(这一点经常有人混淆,而且往往会给自己种了木马!甚至还有人跟我争得面红耳赤,昏倒!!)
2.程序实现:
在VB中,可以使用Winsock控件来编写网络客户/服务程序, 实现方法如下:
(其中,G_Server和G_Client均为Winsock控件)
服务端:
G_Server.LocalPort=7626(冰河的默认端口,可以改为别的值)
G_Server.Listen(等待连接)
客户端:
G_Client.RemoteHost=ServerIP(设远端地址为服务器地址)
G_Client.RemotePort=7626 (设远程端口为冰河的默认端口,呵呵,知道吗?这是冰河的生日哦)
(在这里可以分配一个本地端口给G_Client, 如果不分配, 计算机将会自动分配一个, 建议让计算机自动分配)
G_Client.Connect (调用Winsock控件的连接方法)
一旦服务端接到客户端的连接请求ConnectionRequest,就接受连接
Private Sub G_Server_ConnectionRequest(ByVal requestID As Long)
G_Server.Accept requestID
End Sub
客户机端用G_Client.SendData发送命令,而服务器在G_Server_DateArrive事件中接受并执行命令(几乎所有的木马功能都在这个事件处理程序中实现)
如果客户断开连接,则关闭连接并重新监听端口
Private Sub G_Server_Close()
G_Server.Close (关闭连接)
G_Server.Listen (再次监听)
End Sub
其他的部分可以用命令传递来进行,客户端上传一个命令,服务端解释并执行命令......
二、控制篇(木马控制了这个世界!)
由于Win98开放了所有的权限给用户,因此,以用户权限运行的木马程序几乎可以控制一切,让我们来看看冰河究竟能做些什么(看了后,你会认同我的观点:称冰河为木马是不恰当的,冰河实现的功能之多,足以成为一个成功的远程控制软件)
因为冰河实现的功能实在太多,我不可能在这里一一详细地说明,所以下面仅对冰河的主要功能进行简单的概述, 主要是使用Windows API函数, 如果你想知道这些函数的具体定义和参数, 请查询WinAPI手册。
1.远程监控(控制对方鼠标、键盘,并监视对方屏幕)
keybd_event 模拟一个键盘动作(这个函数支持屏幕截图哦)。
mouse_event 模拟一次鼠标事件(这个函数的参数太复杂,我要全写在这里会被编辑骂死的,只能写一点主要的,其他的自己查WinAPI吧)
mouse_event(dwFlags,dx,dy,cButtons,dwExtraInfo)
dwFlags:
MOUSEEVENTF_ABSOLUTE 指定鼠标坐标系统中的一个绝对位置。
MOUSEEVENTF_MOVE 移动鼠标
MOUSEEVENTF_LEFTDOWN 模拟鼠标左键按下
MOUSEEVENTF_LEFTUP 模拟鼠标左键抬起
MOUSEEVENTF_RIGHTDOWN 模拟鼠标右键按下
MOUSEEVENTF_RIGHTUP 模拟鼠标右键按下
MOUSEEVENTF_MIDDLEDOWN 模拟鼠标中键按下
MOUSEEVENTF_MIDDLEUP 模拟鼠标中键按下
dx,dy:
MOUSEEVENTF_ABSOLUTE中的鼠标坐标
2.记录各种口令信息(出于安全角度考虑,本文不探讨这方面的问题,也请不要给我来信询问)
3.获取系统信息
a.取得计算机名 GetComputerName
b.更改计算机名 SetComputerName
c.当前用户 GetUserName函数
d.系统路径
Set FileSystem0bject = CreateObject("Scripting.FileSystemObject") (建立文件系统对象)
Set SystemDir = FileSystem0bject.getspecialfolder(1)
(取系统目录)
Set SystemDir = FileSystem0bject.getspecialfolder(0)
(取Windows安装目录)
(友情提醒: FileSystemObject是一个很有用的对象,你可以用它来完成很多有用的文件操作)
e.取得系统版本 GetVersionEx(还有一个GetVersion,不过在32位windows下可能会有问题,所以建议用GetVersionEx
f.当前显示分辨率
Width = screen.Width / screen.TwipsPerPixelX
Height= screen.Height / screen.TwipsPerPixelY
其实如果不用Windows API我们也能很容易的取到系统的各类信息,那就是Winodws的"垃圾站"-注册表
比如计算机名和计算机标识吧:
HKEY_LOCAL_MACHINE/System/CurrentControlSet/Services/VxD/VNETSUP
中的Comment,ComputerName和WorkGroup
注册公司和用户名:
HKEY_USERS/.DEFAULT/Software/Microsoft/MS Setup (ACME)/UserInfo
至于如何取得注册表键值请看第6部分
4.限制系统功能
a.远程关机或重启计算机,使用WinAPI中的如下函数可以实现:
ExitWindowsEx(ByVal uFlags,0)
当uFlags=0 EWX_LOGOFF 中止进程,然后注销
=1 EWX_SHUTDOWN 关掉系统电源
=2 EWX_REBOOT 重新引导系统
=4 EWX_FORCE 强迫中止没有响应的进程
b.锁定鼠标
ClipCursor(lpRect As RECT)可以将指针限制到指定区域,或者用ShowCursor(FALSE)把鼠标隐藏起来也可以
注:RECT是一个矩形,定义如下:
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
c.锁定系统 这个有太多的办法了,嘿嘿,想Windows不死机都困难呀,比如,搞个死循环吧,当然,要想系统彻底崩溃还需要一点技巧,比如设备漏洞或者耗尽资源什么的......
d.让对方掉线 RasHangUp......
e.终止进程 ExitProcess......
f.关闭窗口 利用FindWindow函数找到窗口并利用SendMessage函数关闭窗口
5.远程文件操作
无论在哪种编程语言里, 文件操作功能都是比较简单的, 在此就不赘述了,你也可以用上面提到的FileSystemObject对象来实现
6.注册表操作
在VB中只要Set RegEdit=CreateObject("WScript.Shell")
就可以使用以下的注册表功能:
删除键值:RegEdit.RegDelete RegKey
增加键值:RegEdit.Write RegKey,RegValue
获取键值:RegEdit.RegRead (Value)
记住,注册表的键值要写全路径,否则会出错的。
7.发送信息
很简单,只是一个弹出式消息框而已,VB中用MsgBox("")就可以实现,其他程序也不太难的。
8.点对点通讯
呵呵,这个嘛随便去看看什么聊天软件就行了
(因为比较简单但是比较烦,所以我就不写了,呵呵。又:我始终没有搞懂冰河为什么要在木马里搞这个东东,困惑......)
9.换墙纸
Call SystemParametersInfo(20,0,"BMP路径名称",&H1)
值得注意的是,如果使用了Active Desktop,换墙纸有可能会失败,遇到这种问题,请不要找冰河和我,去找比尔盖子吧。
三、潜行篇(Windows,一个捉迷藏的大森林)
木马并不是合法的网络服务程序(即使你是把木马装在女朋友的机子上,也是不合法的,当然,这种行为我可以理解,呵呵),因此,它必须想尽一切办法隐藏自己,好在,Windows是一个捉迷藏的大森林!
1、在任务栏中隐藏自己:
这是最基本的了,如果连这个都做不到......(想象一下,如果Windows的任务栏里出现一个国际象棋中木马的图标...@#$%!#@$...也太嚣张了吧!)
在VB中,只要把form的Visible属性设为False, ShowInTaskBar设为False, 程序就不会出现在任务栏中了。
2、在任务管理器中隐形:(就是按下Ctrl+Alt+Del时看不见那个名字叫做“木马”的进程)
这个有点难度,不过还是难不倒我们,将程序设为“系统服务”可以很轻松的伪装成比尔盖子的嫡系部队(Windows,我们和你是一家的,不要告诉别人我藏在哪儿...)。
在VB中如下的代码可以实现这一功能:
Public Declare Function RegisterServiceProcess Lib "kernel32" (ByVal ProcessID As Long, ByVal ServiceFlags As Long) As Long
Public Declare Function GetCurrentProcessId Lib "kernel32" () As Long
(以上为声明)
Private Sub Form_Load()
RegisterServiceProcess GetCurrentProcessId, 1 (注册系统服务)
End Sub
Private Sub Form_Unload()
RegisterServiceProcess GetCurrentProcessId, 0 (取消系统服务)
End Sub
3、如何悄没声息地启动:
你当然不会指望用户每次启动后点击木马图标来运行服务端,木马要做到的第二重要的事就是如何在每次用户启动时自动装载服务端(第一重要的是如何让对方中木马,嘿嘿,这部分的内容将在后面提到)
Windows支持多种在系统启动时自动加载应用程序的方法(简直就像是为木马特别定做的)启动组、win.ini、system.ini、注册表等等都是木马藏身的好地方。冰河采用了多种方法确保你不能摆脱它(怎么听起来有点死缠烂打呀....哎呦,谁呀谁呀,那什么黄鑫,不要拿鸡蛋扔我!)首先,冰河会在注册表的HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Run和RUNSERVICE键值中加上了/kernl32.exe(是系统目录), 其次如果你删除了这个键值,自以为得意地喝著茶的时候,冰河又阴魂不散地出现了...怎么回事?原来冰河的服务端会在c:/windows(这个会随你windows的安装目录变化而变化)下生成一个叫sysexplr.exe文件(太象超级解霸了,好毒呀,冰河!),这个文件是与文本文件相关联的,只要你打开文本(哪天不打开几次文本?), sysexplr.exe文件就会重新生成krnel32.exe, 然后你还是被冰河控制著。(冰河就是这样长期霸占著穷苦劳动人民宝贵的系统资源的,555555)
4、端口
木马都会很注意自己的端口(你呢?你关心你的6万多个端口吗?),如果你留意的话,你就会发现,木马端口一般都在1000以上,而且呈越来越大的趋势(netspy是1243....)这是因为,1000以下的端口是常用端口,占用这些端口可能会造成系统不正常,这样木马就会很容易暴露; 而由于端口扫描是需要时间的(一个很快的端口扫描器在远程也需要大约二十分钟才能扫完所有的端口),故而使用诸如54321的端口会让你很难发现它。在文章的末尾我给大家转贴了一个常见木马的端口表,你就对著这个表去查吧(不过,值得提醒的是,冰河及很多比较新的木马都提供端口修改功能,所以,实际上木马能以任意端口出现)
5.最新的隐身技术
目前,除了冰河使用的隐身技术外,更新、更隐蔽的方法已经出现,那就是-驱动程序及动态链接库技术(冰河3.0会采用这种方法吗?)。
驱动程序及动态链接库技术和一般的木马不同,它基本上摆脱了原有的木马模式-监听端口,而采用替代系统功能的方法(改写驱动程序或动态链接库)。这样做的结果是:系统中没有增加新的文件(所以不能用扫描的方法查杀)、不需要打开新的端口(所以不能用端口监视的方法查杀)、没有新的进程(所以使用进程查看的方法发现不了它,也不能用kill进程的方法终止它的运行)。在正常运行时木马几乎没有任何的症状,而一旦木马的控制端向被控端发出特定的信息后,隐藏的程序就立即开始运作......
事实上,我已经看到过几个这样类型的木马,其中就有通过改写vxd文件建立隐藏共享的木马...(江湖上又将掀起新的波浪)