你是否曾经在用别人开发的工具尝试“入侵”.你是否希望开发出自己的黑器……相信很多人有着这种近似相同的经历。本章将简单介绍黑客编程及工具开发。如果你是初学编程,如果你从来没有接触过黑客软件的开发,如果你急于想了解黑客编程方面的知识……那么就请继续往下阅读。
编程语言和开发环境的选择
初学者刚开始学习编程语言最头疼的问题就是如何选择编程语言及合适的开发环境,下面就来具体介绍一下。
有人认为学编程就是学编程语言,而vc、VB这样的开发环境只是工具,不需要学。这个想法是错误的,因为开发环境提供了很多开发工具,如vc这个集成开发环境就提供了与之对应的PSDK、MFC等。除了语言以外,要开发特定的软件是需要开发包和开发工具支持的。况且,编程语言也是一种工具,用于和计算机进行交流的工具。所以我们既要学习编程语言,也要学习开发工具。
对于选择哪种编程语言或者开发环境其实也没有特定的标准。有这样一句话,“真正的程序员用vc,聪明的程序员用Delphi,用VB的不是程序员”。笔者却并不这么认为,因为在很多编程的书籍上常常这样提醒并告诫学习者,编程的精髓是“算法”,而语言是用来描述算法的。因此,大家也不必因为无法选择而无从下手。
黑客一般都掌握多种编程语言,他们不但掌握着与底层相关的如汇编、C之类的编程语言,而且还掌握很多脚本语言,如Python、Perl、Ruby .......很多黑客在发现ODay以后用Perl或者Python来写POC; MSF使用的是Ruby来进行开发Exploit;有的黑客在反病毒时竟然写个批处理就搞定了……对于黑客来说,一切语言都是服务于自己的思想的,只要能快速实现自己的想法,能完成自己所要完成的功能就行,从不拘泥于任何语言和工具。在网上有很多学习不同编程语言的人们之间经常互相攻击,这其实是一种极端的行为,大家还是理性地对待这些问题比较好。
前面说了这么多,仿佛是在绕圈子,一直没有介绍到底应该选择什么编程语言和开发环境。我们这里选择使用c语言作为黑客编程的学习语言,选择VC6(Visual C++ 6.0的缩写)来作为我们的开发环境。VS 6 h相对于Visual Studi0 2005、VisuaJ Studi0 2008和Visual Studio2010之类的开发环境来说要小巧很多,当前是可以满足我们的开发需求的。选择C语言的原因是由下Windows的API都是用C语言定义的,相对于使用其他编程语言会方便很多。笔者认为在VB下使用API就非常不方便,尤其是涉及指针这个概念的时候。除了VC6以外,还需要下载新版的PSDK,因为VC6中包含的PSDK过于旧,有些新的API我们无法通过包含头文件而直接使用,因此这个也是必须的。
何为SDK、API和MFC
既然选择vC作为开发环境,那么先来了解一下 vc开发环境中今后会用到的一些工具的概念,这些概念都相对比较简单,常见的概念育SDK、Api和MFC。
SDK是Sofiware Develop Kits的缩写,即软件开发工具包。SDK是一个泛指,比如对视频采集卡进行二次开发,那么视频采集卡会提供SDK;再比如对动态令牌进行二次开发,那么动态令牌也会提供SDK。操作系统为了程序员在其平台下开发应用程序也会提供SDK,我们对系统提供的开发包称之为PSDK。PSDK是Platform SDK的意思,也就是平台SDK。对于我们来说,平台就是Windows操作系统。Windows下的PSDK包含了进行Windows软件开发的文档和API函数的输入库、头文件等一些与Windows开发相关的工具。PSDK是一个单独的开发包,不过每个不同版本的vc和其他一些开发环境中也已经包含了它。API是Application Programnung Interface的缩写,即应用程序接口。不同的SDK提供不同的API。PSDK提供的API就是操作系统提供的开发应用程序的接口.比如Windows系统下删除文件的APl函数是DeleteFile();再比如Windows系统下移动文件的API函数是MoveFile(),而其他一些供二次开发的SDK中附带的API,也是为了进行开发应用程序而提供的接口。
MFC是Microso:R Foundation Class的缩写,即微软基础类库。它是微软为了简化程序员的开发工作量所提供的基于c++类的一套面向对象的库,它封装了常见的API函数,使得开发较为方便。
我们在书中会用到API进行开发,也会使用MFC进行开发。不过对于MFC的使用,基本上用在与界面相关的部分,一般是简单地带过,不会进行过多的讨论。我们的重点是放在API函数的使用上。关于MFC的相关内容,还请大家自行参考学习。
VC6和SDK的配置
新版的PSDK(Windows Server 2003 SPl Platfo:rm SDK)的下载地址为/d ownloads/en/detaiLs.aspx?Fanulyl~ eba0 12 8f-a7 70-45fl - 86f3 -7ab010b398a3。如果此地址过期的话,请大家在网上自行搜索并下载。
SDK和VC6互相是独立的,不需要安装在同一个目录下.根据自己的实际情况安装就可以了。在安装好VC6和新版的SDK后,需要在VC6中进行相应的设置才能使用新版的SDK.否则VC6仍然使用其自带的旧的SDK。SDK和VC6的安装步骤这里就不介绍了(提示:请把VC6安装完整,VC6会提供一些代码,对我们的学习是非常有帮助的).下面介绍新版的SDK如何配置才能在VC6中使用。启动VC6,单击菜单“Tools”->“Options”命令,打开“Options”对话框,如图1-1
选择“directorie”选项卡,在show directories for下拉列表中选择“include files”选项并在“directories”列表框中添加新的SPDK头文件的目录,放在列表的最上面,如图1-2所示。
在“show directories for”下拉列表中选择“library files”选项,并在“directories”列表框中添加新的PSDK库文件的目录,放在列表的最上面,如图1-3所示。
切记要把所添加的目录放到列表的最上边,因为在VC编辑代码的时候会搜索这些目录里的文件,如果随便放,编译器会因为找不到相关的API函数定义而报函数未定义的错误。
另外,还必须下载一个MSDN。MSDN即Microsoft Developer network。他是微软开发的联机帮助文档,可以帮助我们在使用API的时候进行快速的查阅,以方便我们对API的使用和理解,但是MSDN里面的内容全部都是英文的,如果你英文不是太好的话可以借助搜索引擎来学习API的使用,本书只对所提到的API函数常用的参数进行介绍,其他参数需要大家自行进行学习。
应用程序的调试
在开发程序的过程中,除了编码以外还需要对程序进行调试,当编写的程序出现问题后就要对程序进行调试,调试不是仅仅使用一个printf()或者MessageBox()进行简单的输出来观察某个函数的返回值,也不是对某个变量,某一时间的具体值的输出,调试是由专业的调试分析工具的,VC6不但提供代码编辑,代码编译、编译连接等功能,还提供了一个非常好用的调试工具,在编写完代码后,如果程序输出的结构是未知的,或者是没有预测到的,都可以通过调试来对代码的逻辑进行分析,以找到问题的所在,掌握调试的技能,对软件的开发有非常大的帮助。掌握好的调试工具,对于调试者的来说,也同样会起到事半功倍的作用,下面通过一个简单的例子了解一下VC6提供的调试功能吧。
编写我们的第一个程序
下面介绍用VC6写一个控制台板的Helloworld来学习VC6的开发,也许大家日内这个程序很简单,但是请记住,我们的重点是要介绍VC6这个集成开发环境中提供的调试功能。
启动VC6单击菜单“file→New命令,在弹出的对话框中选择Projects选项卡,然后再左边的列表框中选择win32 console application选项,在project name文本框中填写helloworld,如图1-4所示。
单击OK按钮,出现如图1-5所示的窗口。
选择AN empty project单选项,单击finish按钮,然后再弹出的对话框中单击OK按钮
单击菜单file→new命令,选择files选项卡,在左边的列表中选择C++soureefile选项,在右边的file文本框中填写helloworld,如图1-6所示。
单击OK按钮就可以进行代码编辑了。
在代码编辑处录入如下代码:
按F7键进行编译链接,按Ctel+F5组合键进行运行,如图1-7所示。
这就是我们值得纪念的第一个程序,这个程序很简单,有C语言基础的读者应该都是能看懂的,这里我就不进行介绍了,如果看不懂,请先找本关于C语言入门的书本来看一下吧。
用VC6调试第一个程序
现在来学习如何使用VC6对第一个程序进行调试,在代码编辑状态下,按下键盘上的F10键,进入调试状态,如图1-8所示。
常用的调试窗口有两个,一个是Watch窗口,一个是Memory窗口,打开Watch窗口的方法是单击View→Debug windows→watch命令打开,打开Memory窗口的方法是单击View→debugwindows→memory命令打开,watch窗口用来监视我们感兴趣的变量,而当我们有时无法通过变量的值进行判断时候,就需要借助memory窗口的值,比如,指针的值来进行判断。
除了这两个窗口以外,还有Call、Stack、register和disassembly这3个窗口,分别如图1-9、图1-10和图1-11所示。
Call stack窗口是调用栈窗口,该窗口可以很方便的查看调用关系,很容易通过调用栈来找到上层,上上层的调用者,另外,也可以通过调用栈来定位错误,比如,有时程序会崩溃,但是发生崩溃的地方确实在系统提供的代码中,而不再我们编写的代码中,这种错误在通常情况下是我们的程序对于参数的输入有误造成的,我们可以通过调用栈查看是谁调用了该函数,以便进行进一步的分析。
Register窗口对用来观察寄存器的,有时需要观察返回值或者参数。
Disassembiy窗口是用来观察C代码对应的反汇编代码的,有时候在看C的代码无法解决的问题时候,需要查看在底层实现时候分析程序的问题。
以上就是VC6下常用的调试窗口,可根据实际情况使用,并不是每次调试都会用到这些窗口,下面在简单介绍一下常用的调试快捷键,以方便今后进行调试时使用。
VC6调试时候的常用快捷键如下。
F5键:运行程序。
F9键:设定端点/取消端点
F10键:单步步过,依次执行每一条代码。
F11键:单步步入,依次执行每一条代码,遇到函数调用时候则进入到被调用的函数中。
F7键:停止调试
在后面的章节中我们会用到这些快捷键来调试程序,让大家在学习的过程中真正的应用起这些调试功能。
专业的应用程序调试工具——OllyDbg
OllyDbg简称OD。是专业的应用程序调试工具,接触过破解,或者做过外挂开发的读者一定对这款工具不陌生,在这里,简单介绍一下这款工具。
让我们先看看他的界面吧。如图1-12所示
OD的大多数情况是在没有源代码的情况下对软件进行调试的,也许没有源代码也就不叫调试了,而叫做动态分析。OD的主界面中有6个主要的窗口。分别是反汇编窗口、寄存器窗口。提示信息窗口、数据窗口(也叫转存窗口)、栈密口和命令提示窗口。
下面逐个允绍一下各个窗口的作用。
(1)反汇编窗口:这是调试鼓动态分析时的主要窗口,我们主要是针对软件的功能实现一进行分析,因此主要需查看的就是反汇编窗口的内容。
(2)寄存器窗口:该窗口的作用是实时地显示寄存器的变化情况。寄存器也可以反映代码的执行情况。例如,我们常常查看返回值的eax的值。
( 3)提示信息窗口:这里往往会显示一些内存地址的值、寄存器的值、调用方的地址等信息。
(4)数据窗口:该窗口主要是用来显示数据的,单击右键可以把数据按照不同的方式进行解析,对于我们分析程序的过程是非常有用的。
(5)栈窗口:该窗口可以用来查看函数调用时参数的值。
(6)命令提示窗口:该窗口是用来输入调试命令的。
OD调试时的常用快捷键如下。
F8键:单步步过,依次执行每一条代码。
F7键:单步步入,依次执行每一条代码,遇到函数调用时则进入到被调用的函数中。
F4键:执行到选中的代码处(前提条件是该条代码在程序的流程中一定会被执行到)。
F2键:断点中断。
F9键:运行程序。
OD的介绍到此为止,在后面的内容中我们会再次提到OD,到那时会有一定的机会练习使用OD。如果有对OD感兴趣的读者,请另行阅读其他书籍。
简单API的介绍
下面介绍一些在黑客编程中会用到的API函数.尽量排一点简单易用的函数,用简单的几行代码来完成一定的功能.希望大家能在这里体会到编程乐趣。不至于被大段的代码影响了自己前进的心情。
复制自身程序到Windows目录和系统目录下
一般的病毒木马都有这种类似的功能,完成这个功能其实并不复杂,我们来拆解思考一下实现这段代码的步骤。
复制是一个拷贝的过程。既然是拷贝,就要知道拷贝的原位置和目的位置。也就是整个过程其实分3步,首先要得到自身程序所在的路径,然后获想Windows目录和系统目录,最后分别拷贝自身程序到这两个日录中。这3个步骤要如何完成,下面我们来看看完成这些功能的AII函数。
获得自身程序所在路径的API函数的定义:
该函数有3个参数,分别如下。
(1)Hmodale:该参数在获得自身程序时使用为Nuel。
(2)lpfilename:该参数指定一个字符型的缓冲区,用于保存程序自身所在的路径。
(3)ndize:该参数指定缓冲区的大小
获得Windows目录的API函数定义。
该函数有两个参数,分别如下。
(1)lpbuffer:该参数指定一个字符型的缓冲区,用于保存Windows目录的路径。
(2)usize:该参数指定缓冲区的大小。
获得系统目录的api函数的含义。
该函数有两个参数,分别如下:
(1)lpbuffer:该参数指定一个字符型的缓冲区,用于保存windows目录的路径。
(2)usize:该参数指定缓冲区的大小。
拷贝文件的API函数的定义:
该函数有3个参数,分别如下。
(1)lpexistingfilename:该参数指向一个已经存在的文件的路径,即原文件路径。
(2)lpNewFilrName:该参数指向一个新的文件的位置,即欲拷贝到的文件的目的路径。
(3)bFaillfExists:该参数是一个布尔型参数,如果参数为TRUE,若目的文件已经存在则返回,复制失败,如果参数为FALSE,若目的文件已经存在则强行覆盖原有的文件。
需要使用的API函数已经介绍完了,下面就来真正完成这个复制自身程序到Windows目录和系统目录下的程序,代码如下:
该函数需要包含Windows.h这个头文件,也就是在该段程序的最开始处加一句:
获得系统的相关信息
了解一个系统相关信息也是一项比较重要的内容,强大的扫描软件Nmap在对目标主机进行扫描时,也能对目标主机的系统等信息进行识别,真的是根强大。这里简单地获取一些与系统相关的信息,主要获取的内容有操作系统的版本、操作系统的名字及当前登录的用户名称。接下来逐个介绍这些API函数。
(1)获取操作系统版本代码如下:
该函数就一个参数,这个参数是指向一个OSVERSl01NFO结构的指针。看一下OSVERSIONINFO这个结构体。
dwPlatfonnld的取值有3个,而现在主要使用一个,即VER PLATFORM WIN32 NT。
(2)获取计算机名称代码如下:
该函数有两个参数,介绍如下。
(1)lpBuffer:保存计算机名称缓冲区。
(2)1pNSize:保存缓冲区的长度,该参数是一个输入,输出参数。
(3)获取当前用户名称代码如下:
该函数有两个参数,介绍如下。
(1)lpBuffer:保存当前用户名称的缓冲区。
(2)nSize:保存缓冲区的长度,该参数是一个输入/输出参数。
我们封装一个简单的函数来获取系统的这3个信息,代码如下:
这个程序完成了我们想要的功能,对于编程的部分就介绍到这里。下面介绍Debug和Release方面的内容。
Debug。和Release的编译方式
关于获取系统信息的程序,我们编写完成了,也编译连接并运行过了。找到刚才编译的程序,查看一下下它的文件大小,如图1-14所示。
从图l-14中可以看出,该程序竟然有153KB大小。是不是很惊人?我们一共写了不过十几行代码,但是却生成了如此大体积的程序,这是为什么呢?因为代码默认编译连接是Debug版本的,如图1-15所示。 从图I-15中可以看出,我们的代码是由Debug方式编译的。Debug被称为调试版本,在这种方式的编译下,可执行程序中会附带很多和调试相关的数据或代码,而且不做任何的优化,以此为开发人员提供大量的调试信息,从而方便了程序的调试工作。除了Debug方式编译以外,还有一种方式是Release方式编译,单击“Win32 Debug”右边的下拉箭头可以选择“Win32 Release”,如图1-16所示。
Release方式被称作发布版本,是为最终用户使用的,这种方式对伐码做了大量的优化工作,不再包含与调试相关的信息,从而使程序的运行效率更高,体积更小,如图1-17所示。
从图1-17可以看出,两个程序的文件大小发生了截然不同的变化。因此,当我们自己写程序调试时,应该使用调试版,以方便我们对程序进行调试。当我们的程序已经调试完毕,那么可以使用发布版来与大家进行交流。
查看函数定义
很多时候,我们都需要查看函数的定义,而函数的定义都在SDK的头文件中。虽然从MSDN中也能找到函数的定义,但是还是有略微的不同,而且对于查找自定义函数的函数定义也是很方便的。
回到我们的代码当中,随便选中一个API函数,比如GetComputerName0这个函数。加入要查看该函数的定义应该如何查看呢?我们在GetComputerName0这个函数上单击鼠标右键,在弹出的快捷菜单上选择“GeToDefinitionOfGetComputerName”(到GetComputerName函数的定义处)命令,如图1-18所示。当选择“Go To Definition Of GetComputerName”命令以后,会来到“Winbase.h”头文件中的GetComputerhlame0函数的定义处,如图1-19和图1-20所示。
从图1-20中可以看出,GetcompuerName是一个宏,其对应的函数为Getcompuernamea(),关于Getcompuername()和Getcompuernamea(),包括可以看到的Getcompuernamew(),我们都不在进行介绍了,通过图1-20的函数定义和前面介绍这个函数的定义来比较一下,可以看到,头文件中的定义比MSDN中的定义对于函数的描述更加的详细,比如Winapi标识函数的调用方式。
除了GO TO DEFINITION OF GETCOMPUTERNAME以外,还有一个GO TO REFERENCE TO GETCOMPUTERNAME,这个是查看何处引用了函数,大家可以自行学习一下。
总结
本书的编程内容主要以C语言为编程语言(本书部分内容会涉及其他语言,但C语言是主要的),以VC6为开发环境,着重介绍了VC6的基本概念及简单的使用,在此基础上带领大家认识了专业的应用程序的调试工具---OD。在最后的内容中介绍了一些简单的API-函数的使用。万丈高楼平地起,希望每一位初学者不要过于着急,在后面的章节中我们会慢慢地深入学习黑客编程的内容。希望在每学完一个知识后,大家多思考多动手,这样才能真正地起到学习的效果。