问题九:如何获取本机上正在使用的UDP端口?
钥匙在这里:
可以通过端口扫描技术实现。
端口扫描技术(port scanning)
端口扫描就是通过连接到目标系统的TCP或UDP端口,来确定什么服务正在运行。一般来说端口扫描有三个用途:
* 识别目标系统上正在运行的TCP和UDP服务。
* 识别目标系统的操作系统类型(Windows 9x, Windows NT,或UNIX,等)。
* 识别某个应用程序或某个特定服务的版本号。
端口扫描技术:
1. TCP connect scan:这种方法最简单,直接连到目标端口并完成一个完整的三次握手过程(SYN, SYN/ACK, 和ACK)。缺点是容易被目标系统检测到。
2. TCP SYN scan:这种技术也叫“半开式扫描”(half-open scanning),因为它没有完成一个完整的TCP连接。这种方法向目标端口发送一个SYN分组(packet),如果目标端口返回SYN/ACK,那么可以肯定该端口处于检听状态;否则,返回的是RST/ACK。这种方法比第一种更具隐蔽性,可能不会在目标系统中留下扫描痕迹。
3. TCP FIN scan:这种方法向目标端口发送一个FIN分组。按RFC793的规定(http://www.ietf.org/rfc/rfc0793.txt),对于所有关闭的端口,目标系统应该返回RST标志。这种方法通常用在基于UNIX的TCP/IP堆栈。
4. TCP Xmas Tree scan:这种方法向目标端口发送一个含有FIN, URG,和PUSH标志的分组。根据RFC793,对于所有关闭的端口,目标系统应该返回RST标志。
5. TCP Null scan:这种方法向目标端口发送一个不包含任何标志的分组。根据RFC793,对于所有关闭的端口,目标系统应该返回RST标志。
6. UDP scan:这种方法向目标端口发送一个UDP分组。如果目标端口以“ICMP port unreachable”消息响应,那么说明该端口是关闭的;反之,如果没有收到“ICMP port unreachable”响应消息,则可以肯定该端口是打开的。由于UDP协议是面向无连接的协议,这种扫描技术的精确性高度依赖于网络性能和系统资源。另外,如果目标系统采用了大量分组过滤技术,那么UDP扫描过程会变得非常慢。如果你想对Internet进行UDP扫描,那么你不能指望得到可靠的结果。
另外,有某种系统的IP协议是这样实现的,对于所有扫描的端口,不管他们处于关闭或者监听状态,都返回RST标志(我们知道,这不符合RFC793的规定)。因此,扫描这种系统时,用不同的扫描技术可能得到不同的扫描结果。
端口扫描工具:
* Strobe
Strobe是一个很古老的端口扫描工具,最快且最可靠的TCP扫描工具之一。缺点在于没有UDP扫描功能。
URL: ftp.win.or.jp/pub/network/misc/strobe-1.05.tar.gz
* Udp_scan
Udp_scan最初来自SATAN(Security Administrator Tool for Analyzing Networks, 安全管理员的网络分析工具,SATAN的新版本改称SAINT,由http://wwdsilx.wwdsi.com发布)。Udp_scan是最可靠的UDP扫描工具之一,但隐蔽性不好,容易被目标系统检测到。
URL: ftp://ftp.technotronic.com/unix/network-sanners/udpscan.c
* Netcat
Netcat是最有用的网络工具之一,功能很多,有网络安全工具包中的瑞士军刀之称。Netcat提供基本的TCP、UDP扫描功能。
URL: http://www.l0pht.com/netcat
* PortPro and Portscan
是Windows NT上最快的端口扫描工具之一。Portscan可以指定一个扫描范围,PortPro只能递增扫描,他们都不能一次扫描多个ip地址。
URL: PortPro: http://www.securityfocus.com
* Network Mapper(nmap)
Nmap是一个高级端口扫描工具,提供了多种扫描方法。Nmap有一些有趣的功能,如用分解(fragment)TCP头(就是把一个TCP头分解到多个分组中发送)的方法绕过一些具有简单分组过滤功能的防火墙。Nmap的另一个有趣功能是可以发送欺骗地址扫描。具体的实现方法是:以伪造的IP地址向目标系统发送大量SYN分组,并在其中混以真实地址的SYN分组,这会导致目标系统花大量时间去响应那些伪造分组,从而造成拒绝服务(denial of service),这就是所谓的SYN flood攻击。
URL: http://www.insecure.org/nmap
问题十:如何利用DirectoryEntry组件来查看网络
钥匙在这里:
DirectoryEntry组件提供了Path属性,根据文档,此属性指定了目录服务中用来访问对象的对象名,其格式如下: protocol://servername:port number/distinguished name
此语句的第一部分定义了访问将使用的协议,如
LDAP: (Lightweight Directory Access Protocol)
IIS: (提供IIS元数据来读及配置Internet Infomation Server)
WinNT: (提供在非常有限的性能下对Windows NT域的访问)
NDS: (提供对Novell Directory Service的访问)
等等(详细信息清参考MSDN)。
据此,我们构造了一个DirectoryEntry实例,将它的Path设为"WinNT:",以通过对它的所有子项的枚举来发现网络上的所有域(以及工作组)。这样,再对所发现的域(以及工作组)的子项进行枚举,就可以发现网络上的所有计算机。下面的一个控制台小程序演示了这一点。
using System; using System.DirectoryServices; class TempClass { static void Main() { EnumComputers(); } static void EnumComputers() { using(DirectoryEntry root = new DirectoryEntry("WinNT:")) { foreach(DirectoryEntry domain in root.Children) { Console.WriteLine("Domain | WorkGroup:\t"+domain.Name); foreach(DirectoryEntry computer in domain.Children) { Console.WriteLine("Computer:\t"+computer.Name); } } } } } |
上面代码中两个嵌套的foreach循环看起来并不是太好,并且控制台的显示效果也并不那么美观。下面,我将对代码进行一些改动,并将它移植到WinForm上。
新建一个Windows Application[C#],在Form上添加一个TreeView,命名为treeView1。
添加以下几个函数:
//用指定的文本构造一个节点,将其添加为参数parant的子节点,并返回刚构造的节点 private TreeNode AddNode(TreeNode parant,string text) { TreeNode node = new TreeNode(text); parant.Nodes.Add(node); return node; } //递归地找到参数entry的所有子节点,并在treeView1中显示;这里的entry与entryNode需相对应 private void EnumChildren(DirectoryEntry entry,TreeNode entryNode) { if(entry.Children!=null) file://如果无子节点则结束 { foreach(DirectoryEntry i in entry.Children) { file://将各子节点加入TreeView,并进行递归 EnumChildren(i,AddNode(entryNode,i.Name)); } } } //用给定的字符串构造根节点,并列出其所有子节点 private void Enumerate(string path) { try { using(DirectoryEntry root = new DirectoryEntry(path)) { TreeNode node = new TreeNode(root.Name); treeView1.Nodes.Add(node); EnumChildren(root,node); } } catch {} } |
这样,通过传递 "WinNT:" 给函数Enumerate(string),就可以在TreeView中看到网络上的所有计算机,以及每台计算机上的用户、组、服务等资源等。