——网络安全系列教程自由分享创新协会论坛:网络安全编程基础一、Windows内部机制Windows是一个“基于事件的,消息驱动的”操作系统,在Windows下执行一个程序,只要用户进行了影响窗口的动作(如改变窗口大小或移动、单击鼠标等)该动作就会触发一个相应的“事件”。系统每次检测到一个事件时,就会给程序发送一个“消息”,从而使程序可以处理该事件。每个Windows应用程序都是基于事件和消息的,而且包含一个主事件循环,它不停地、反复地检测是否有用户事件发生。每次检测到一个用户事件,程序就对该事件做出响应,处理完再等待下一个事件的发生。1、八个基本概念窗口:窗口是Windows本身以及Windows环境下的应用程序的基本界面单位,但是很多人都误以为只有具有标题栏、状态栏、最大化、最小化按钮这样标准的方框才叫窗口。其实窗口的概念很广,例如按钮和对话框等也是窗口,只不过是一种特殊的窗口罢了。从用户的角度看,窗口就是显示在屏幕上的一个矩形区域,其外观独立于应用程序,事实上它就是生成该窗口的应用程序与用户间的直观接口;从应用程序的角度看,窗口是受其控制的一部分矩形屏幕区。应用程序生成并控制与窗口有关的一切内容,包括窗口的大小、风格、位置以及窗口内显示的内容等。用户打开一个应用程序后,程序将创建一个窗口,并在那里默默地等待用户的要求。每当用户选择窗口中的选项,程序即对此做出响应。程序:通常说的程序都是指一个能让计算机识别的文件,接触得最多的便是.exe型的可执行文件,这个不难理解。进程:说到进程,学过《操作系统》的人都很清楚,所谓进程就是应用程序的执行实例(或称一个执行程序)。需要注意的是:进程是程序动态的描述,而上面说到的程序是静态的描述,两者有本质的区别。举个例子,从网上Down了一个瑞星杀毒软件到C盘但没有运行,那个.exe可执行文件叫做程序,它是一个二进制码的文件。一旦双击了exe文件图标运行程序,那个“正在运行着的瑞星杀毒”便称为进程,它在双击的那一刻被系统创建,当你关机或者在任务栏的图标上单击鼠标右键选“退出”时,进程便消亡,彻底结束了生命。进程经历了由“创建”到“消亡”的生命期,而程序自始至终存在于你的硬盘上,不管你的机器是否启动。线程:线程是进程中的一个执行单元,同一个进程中的各个线程对应于一组CPU指令、一组CPU寄存器以及一堆栈。进程本来就具有动态的含义,然而实质上是通过线程来执行体现的,从这个意义上说,Windows中进程的动态性意义已经不是很明显了,只算是给程序所占的资源划定一个范围而已(个人观点,纯属个人理解,不必引起争议!),真正具有动态——网络安全系列教程自由分享创新协会论坛:性意义的是线程。以前在大二学习操作系统课的时候就有个同学跟笔者提起这点,笔者还跟他驳得面红耳赤呢!现在想想,觉得很有道理,不得不佩服那位同学对Windows内部机制了解得如此清楚。之所以在此花那么多的篇幅说线程,是因为下面将要介绍到多线程编程技巧,如果不理解这点,那就很难应用到实践上,希望大家明白。消息:我们几乎做每一个动作都会产生一个消息,在用鼠标指点江山的今天,鼠标被移动会产生WM_MOUSEMOVE消息,鼠标左键被按下会产生WM_LBUTTONDOWN的消息,鼠标右键按下便产生WM_RBUTTONDOWN消息等等。所有的这些都可以通过GetMessage,SendMessage等函数得到,以后的操作中我们会经常接触到这些函数。事件:何谓事件?从它的字面意思我们就可以明白它的含义,如在程序运行的过程中改变窗口的大小或者移动窗口等,都会触发相应的“事件”。句柄:单单一个“柄”字便可以解释它的意思了,我们天气热摇扇子的时候只要抓住扇柄便可以控制整个扇子的运动了,在程序中也差不多是这个意思。通常一个句柄就可以传递我们所要做的事情。有经验的读者肯定清楚,编写程序总是要和各种句柄打交道的,句柄是系统用来标识不同对象类型的工具,如窗口、菜单等,这些东西在系统中被视为不同类型的对象,用不同的句柄将他们区分开来。API与SDK:API是英文ApplicationProgrammingInterface的简称,意为“应用程序接口”,泛指系统为应用程序提供的一系列接口函数。其实质是程序内的一套函数调用,在编程的时候可以直接调用,而不必知道其内部实现的过程,只知道它的原型和返回值就可以了,此外,手头经常放着一本“WindowsAPI大全”之类的书也是必不可少的,不然你根本不知道哪些API是干什么用的,瞎编也编不出什么东西来。在后面我们会介绍调用API编程的例子,调用API编程工作虽然烦琐,但由于API函数都被封装在dll库里,程序只有在运行的时候才调用的,因此程序的体积小而且运行效率高。SDK是英文SoftwareDevelopmentKit的缩写,指“软件开发工具包”,在防火墙的设计中就经常涉及到SDK。案例1:简单的对话框程序:#includewindows.hintWINAPIWinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,PSTRszCmdLine,intiCmdShow){MessageBox(NULL,TEXT(Hello,Windows!),TEXT(HelloMsg),MB_OK);return0;}解释:WinMain(HINSTANCEhInstance,HINSTANCEhPrevInstance,PSTRszCmdLine,intiCmdShow)——网络安全系列教程自由分享创新协会论坛:参数一:hInstance是当前实例的句柄。在这里hInstance表示应用程序本身。参数二:hPrevInstance总是为NULL,在Windows早期版本中使用,在32位版本中,统一程序运行方式改变了,不在需要了!参数三:szCmdLine是运行程序的命令行参数四:iCmdShow用于指定程序窗口最初的显示模式,可以正常显示,也可以在初始化就最大化或者最小化。二、网络安全编程网络安全基础编程技术主要包括6个方面:Socket编程、注册表编程、文件系统编程、定时器编程、驻留程序编程、多线程编程。1、Socket编程:谈网络安全编程离开网络编程就会大失其味,凡是基于网络应用的程序都离不开Socket。Socket的意思是套接字,是计算机与计算机之间通信的接口。Socket网络编程一般采用服务器/客户机模式,有两种不同的套接字:流套接字和数据报套接字。案例2:利用Socket获得本机的IP地址和机器名#includewinsock.h//socket编程必须包含winsock.h头文件#includestdio.hvoidCheckIP(void);intmain(){CheckIP();//调用CheckIP()函数获得并输出IP地址return0;}voidCheckIP(void)//CheckIP函数,用于获取本机IP地址{WORDwVersionRequested;//用于存放Winsock版本的值/*WSADATA这个结构被用来存储被WSAStartup函数调用后返回的WindowsSockets数据。它包含Winsock.dll执行的数据。*/WSADATAwsaData;charname[255];//用于存放主机名PHOSTENThostinfo;wVersionRequested=MAKEWORD(2,0);//调用MAKEWORD()函数获得Winsock的版本,用于加载Winsock库if(WSAStartup(wVersionRequested,&wsaData)==0){//加载Winsock库,如果WSAStartup()函数的返回值为0,说明加载成功if(gethostname(name,sizeof(name))==0){//判断是否成功的将本地主机名存放入由name参数指定的缓冲区中if((hostinfo=gethostbyname(name))!=NULL){//如果获得主机名成功的话,调用inet_ntoa()函数取得IP地址LPCSTRip=inet_ntoa(*(structin_addr*)*hostinfo-h_addr_list);printf(本机的IP地址是:%s\n,ip);//输出IP地址printf(本机的名称是:%s\n,name);——网络安全系列教程自由分享创新协会论坛:}}WSACleanup();//卸载Winsock库,并释放所有资源}}案例3:利用Socket实现简单扫描器源码:#includewinsock2.h#include“stdio.h”#progmacomment(lib,”ws2_32”)#includestdlib.h#includewindows.hvoidmain(){WSADATAws;SOCKETs;structsockaddr_inaddr;intRESULT;longlRESULT;for(inti=1;i200;i++){lRESULT=WSAStartup(0x0101,&ws);s=socket(PF_INET,SOCK_STREAM,0);addr.sin_family=PF_INET;addr.sin_addr.s_addr=inet_addr(“162.105.195.158”);addr.sin_port=htons(i);if(s==INVALID_SOCKET)break;RESULT=connect(s,(structsockaddr*)&addr,sizeof(addr));//建立连接if(RESULT!=0)//连接失败,表明该端口没开放{printf(“162.105.195.158:%iinactive\n”,i);WSACleanup();}else{printf(“162.105.195.158:%iactive\n”,i);}Closesocket(s);}}2、注册表编程注册表在计算机中由键名和键值组成,注册表中存储了Window操作系统的所有配置。黑客90%以上对Windows的攻击手段都离不开读写注册表。注册表的句柄可以由调用RegOpenKeyEx()和RegCreateKeyEx()函数得到。通过函数RegQueryValueEx()可以查询注册表某一项的值;通过函数RegSetValueEx()可以设置注册表某一项的值案例4:#includestdio.h#includewindows.h——网络安全系列教程自由分享创新协会论坛:(){HKEYhKey1;DWORDdwDisposition;LONGlRetCode;//创建lRetCode=RegCreateKeyEx(HKEY_LOCAL_MACHINE,SOFTWARE\\Microsoft\\WindowsNT\\CurrentVersion\\IniFileMapping\\WebSecurity,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&hKey1,&dwDisposition);//如果创建失败,显示出错信息if(lRetCode!=ERROR_SUCCESS){printf(ErrorincreatingWebSecuritykey\n);return(0);}//设置第一个键值lRetCode=RegSetValueEx(hKey1,Hack_Name,0,REG_SZ,(byte*)sixage,100);//设置第二个键值lRetCode=RegSetValueEx(hKey1,Hack_Hobby,0,REG_SZ,(byte*)Running,100);//如果创建失败,显示出错信息if(l