6.1 恶意程序剖析
恶意程序通常是指带有攻击意图的一段程序,主要包括木马、病毒和蠕虫等。恶意程序的编写是违反道德和法律的,我们这里只是进行学习。在前面的章节中说过,黑客编程和普通编程本质上都是编程,只是侧重点不同。我们为了学习编程,学习防御黑客编程攻击,就必须对恶意程序的编写要有所了解。
6.1.1 恶意程序的自启动
每当黑客们入侵了计算机以后,为了下次的登录都会安装一个后门或者木马。当计算机关机或重启时,所有的进程都将会被关闭。那么后门或者木马是如何在计算机重启以后仍然能继续运行呢?下面先来讨论如何实现恶意程序的自启动。
恶意程序的自启动的实现方法很多,下面只介绍几种常见的方法,至于其他方法大家可自己在网上搜集,然后通过编程实现即可。
一、启动文件夹
在Windows系统下,有一个文件夹是专门用来存放启动文件的。该文件夹的位置如图6-1所示。
在“启动”菜单处单击鼠标右键,然后选择“属性”命令,就可以看到启动文件夹在硬盘上的具体位置了,其位置如:“系统盘:\Documents and Settings\<用户名>\『开始』菜单\程序”。通常情况下<用户名>是当前用户的用户名,Windows为每个用户创建了一个文件夹。如果想要所有的用户在启动时都运行某个程序,需要使用的文件夹为“All Users”。那么,也就是把需要启动的程序放到“系统盘:\Documents and Settings\All Users\『开始』菜单\程序”这个位置下。该程序的实现方法非常的简单,因为基本上在前面已经介绍过该程序的实现方法了。下面给出它的部分代码,代码如下:
图6-1 启动文件夹的位置
打开All Users下的启动目录,也就是上面的“系统盘:\Documents and Settings\All Users\「开始」菜单\程序”这个位置,然后编译连接并运行程序,可以看到在启动目录下多了一个“test.exe”的程序。
二、注册表启动
注册表启动也是一种很常见的启动方法,而且在注册表中可以用来进行启动的位置非常多。这里给大家介绍几个在注册表中可以完成自启动的注册表位置。
- Run注册表键
HKCU \Software\Microsoft\Windows\CurrentVersion\Run
HKLM \Software\Microsoft\Windows\CurrentVersion\Run
- Boot Execute
HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute
HKLM\System\CurrentControlSet\Control\Session Manager\SetupExecute
HKLM\System\CurrentControlSet\Control\Session Manager\Execute
HKLM\System\CurrentControlSet\Control\Session Manager\SOInitialCommand
- Load注册表键
HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Load
当然,在注册表下绝对不只这么几个位置能够使程序跟随系统自动启动,这只是注册表下可以让程序随机启动位置的“冰山一角”。打开一个注册表项看一下,如图6-2所示。
图6-2 Run注册表键中的启动项
同样,下面来完成一个通过写入注册表进行自启动的例子程序,其部分代码如下:
将该代码编译连接并运行,然后打开注册表中写入的位置查看一下,会发现已经把它写入了注册表,当下次开机时,它就会随机启动了。
三、其他启动方法
除了使用上面两种方法外,还有很多启动方法,比如文件关联、创建服务、ActiveX启动、svchost.exe启动等。下面大概地介绍一下。
文件关联启动是通过修改注册表来完成的。比如,默认启动“文本文件”的程序是记事本程序,只要在注册表中把启动“文本文件”的关联程序改掉,也就是把记事本程序改掉,改成我们的木马程序,然后由木马去调用记事本来启动文本文件,这样,就达到了启动木马的效果。来看一下注册表,如图6-3所示。
图6-3 文本文件对应的文件关联
文本文件对应的文件关联的注册表位置为KHEY_CLASS_ROOT\txtfile\shell\ open\command。
创建系统服务的方法是使用CreateService()函数进行创建,然后通过服务来启动恶意程序。CreateService()函数的定义如下:
该函数的参数虽然很多,但是使用起来并不复杂,大部分参数可以使用NULL来表示。该函数的参数不进行说明,请大家自行参考MSDN进行使用。
关于恶意程序的启动就介绍这么多,还有其他更多的方法,大家可以自行查找相关的资料进行学习。最后给大家介绍一款工具,这款工具可以查看电脑上的所有启动项。也许大家会想到360、金山等一些工具,但是这里要介绍的这款工具是微软自己的工具,而且其功能相对来说非常的全面,该工具如图6-4所示。
图6-4 Autoruns工具界面
6.1.2 木马的配置生成与反弹端口
由于黑色产业链的供需关系,木马作为商品在网络上有着大量的交易,因此木马必须具备可配置性。当然了,即使是免费的木马,为了可以让广大网友使用,木马也是一定可以进行配置的。
木马要进行配置后才可以生成真正的服务端,看一下灰鸽子的配置界面,如图6-5所示。
从灰鸽子的配置界面中可以看出,灰鸽子支持的可配置的内容非常多,这里只显示了其中的一部分而已。灰鸽子在进行了服务端配置后会生成服务器端程序。下面就来介绍一下如何对木马进行配置生成,并介绍一下如何进行反弹连接。
一、反弹连接介绍
早期的防火墙只对连入主机的连接进行阻拦,而不对连出的连接进行阻拦。也就是说,当有人试图连接主机时,防火墙会给出提示有人要连接主机。而当主机向外连接其他主机时,防火墙是不会给出提示的。在这样的情况下,反弹木马诞生了。
图6-5 灰鸽子的配置界面
所谓的反弹木马是由攻击者监听一个端口,中木马的被攻击者主动向被攻击者发起连接。由于是被攻击者发起的连接,从而被攻击的防火墙不会给被攻击者任何安全提示。给出一个简单的示意图进行说明,如图6-6所示。
图6-6 反弹木马的示意图
从图6-6中看到了反弹木马的工作原理。通常情况下攻击者的IP地址是变动的,那么“小白”是如何连接到“黑客”的主机的呢?一般情况下黑客要把自己的IP地址动态地保存到某个固定的IP地址下(比如保存到网上FTP空间中),然后木马通过读取该IP地址下保存的黑客的IP地址进行连接,同样用图来说明,如图6-7所示。
从图6-7中可以看出,黑客开启木马客户端后,首先会更新服务器上保存着的自己的IP地址。“小白”会去读取服务器中保存着的黑客的IP地址,然后“小白”去连接“黑客”的主机,主动地让黑客去控制它,这就是木马中的“自动上线”。关于反弹端口的介绍就到这里。有了思路,通过前面学习的Winsock的知识自己可以试着实现一下,这里就不做更多的介绍了。
二、木马的配置生成与配置信息的保护
木马写好以后,通常会发布一个程序,在木马程序中通过配置一些相关的内容和参数后,会生成一个木马的服务器端程序。为什么木马的客户端会生成木马的服务端程序呢?其实木马的客户端和服务端本来就是两个程序,只是通过某种方式使其成为了一个文件而已。让木马的服务端和客户端成为一个文件可以有多种方法,常见的有资源法和文件附加数据法两种。
图6-7 木马动态获取黑客的IP地址
在PE文件结构中有一个数据目录称作资源,资源可以是图片、图标、音频、视频等内容。资源法也就是把服务端以资源的形式连接到客户端的程序中,然后客户端通过一些操作资源的函数将资源读取出来并生成文件。文件附加数据法是将服务端保存到客户端的末尾,然后通过文件操作函数,直接将服务端读取出来并生成新的文件。
反弹端口连接是要访问某个固定的IP地址去读取保存着黑客的动态IP地址的信息,而这个固定的IP地址是保存在木马程序中的。也就是说,我们的客户端在把服务端生成以后,会把一些配置信息写入服务端程序的指定位置中,服务端程序会读取指定位置的信息来进行使用。配置信息的写入与读出必须要一致,否则就没有意义了。
对于配置信息中往往会存在一些比较敏感的信息,比如邮箱账号、密码等内容。比如,我们在分析盗QQ的木马时会发现接收QQ密码的邮箱,由于现在很多邮箱都需要SMTP的验证,因此在配置信息中也会看到邮箱的账号及密码信息。这样配置信息中的这些敏感信息很容易被人获取到,甚至接收QQ密码邮箱的账号和密码也会被别人获取到,真是“偷鸡不成蚀把米”。对于此类情况,正确的做法是对配置信息进行加密。也就是说客户端往服务端中写配置信息前需要加密后再写入,而服务端在使用这些信息前需要先解密再使用。
关于配置生成客户端与配置信息的保护上面已经介绍得差不多了,接下来应该把重点放在代码的实现上了。我们的代码是模拟实现上面的内容,而不是真的去生成木马。
6.1.3 代码实现剖析
我们通过资源来生成木马,首先要写一个简单的被生成的程序,这个程序要去读取被写入的配置信息。客户端把配置信息写入服务端的文件末尾,服务端从文件的末尾将信息读入。下面来写一个简单的程序,来充当我们的服务端程序。需要设置的配置信息有IP地址和端口号,把这两个信息都写入服务器端程序。先来定义一个结构体,结构体如下:
下面写一个模拟的简单的服务端程序,具体代码如下:
上面的代码就是服务端读取配置文件的代码,把文件指针移动到配置信息处,然后直接读取出来,让服务端连接配置信息中的IP地址就可以了。这就是我们模拟的服务端。下面再来写一个模拟的客户端,用来对其进行配置。
创建一个MFC的对话框程序,然后对界面进行布局,界面布局如图6-8所示。
把模拟的服务端编译连接好以后添加入这个模拟客户端的资源里,添加方法是在VC中的资源选项卡中单击鼠标右键,在弹出的菜单中选择“Import…”命令,如图6-9所示。然后在弹出的对话框中选择编译好的模拟服务端程序,如图6-10所示。会出现一个输入自定义资源类型的对话框,输入“IDC_MUMA“,如图6-11所示。
图6-8 模拟客户端窗口布局
图6-9 添加资源
图6-10 选中编译好的程序
图6-11 自定义资源类型对话框
单击“OK”按钮,就将其添加入资源对话框中了,如图6-12所示。
图6-12 资源选项卡
做好这些准备工作以后,就可以开始写代码了。给“生成”按钮添加如下代码:
编译连接并运行这个程序,输入配置程序,单击“生成”按钮,会生成一个muma.exe的程序,然后运行这个程序就会输出配置信息的内容,如图6-13所示。
图6-13 程序运行结果
在这个程序中使用了4个以前没有使用过的函数,下面分别进行介绍。
(1) 查找资源FindResource()函数的定义如下:
①hModule:该参数表示要查找模块的句柄。
②lpName:该参数表示要查找资源的名称。
③lpType:该参数表示了要查找资源的类型。
(2) SizeofResource()函数用来计算被查找资源的大小,该函数的定义如下:
①hModule:该参数同FindResouce()相同。
②hResInfo: FindResouce()的返回值。
(3) LoadResource()函数用来将资源载入全局内存中,该函数的定义如下:
该函数参数的意义与SizeofResouce()的相同。
(4) LockResouce()函数的作用是将资源锁定,并返回其起始位置的指针,该函数定义如下:
上面介绍了关于使用资源来将两个程序合并为一个程序的方法。除此而外还有一种方法是使用附加数据法将两个程序合并为一个程序。何为附加数据法呢?PE文件在被载入内存时是按照节来映射的,没有被映射入内存的部分就是附加数据,虽然该部分占用文件大小,却不占用映像大小。关于配置信息的保护部分,只要使用简单的加密算法将配置信息加密就可以了,比如异或算法,这里就不进行介绍了。