1、端口扫描基本原理端口扫描是指某些别有用心的人发送一组端口扫描消息,试图以此侵入某台计算机,并了解其提供的计算机网络服务类型(这些网络服务均与端口号相关) 。端口扫描是计算机解密高手喜欢的一种方式。攻击者可以通过它了解到从哪里可探寻到攻击弱点。实质上,端口扫描包括向每个端口发送消息,一次只发送一个消息。接收到的回应类型表示是否在使用该端口并且可由此探寻弱点。扫描器应该有三项功能:发现一个主机或网络的能力;一旦发现一台主机,有发现什么服务正运行在这台主机上的能力;通过测试这些服务,发现漏洞的能力。TCP connect() 扫描这是最基本的 TCP 扫描。操作系统提供的 connect()系统调用
2、,用来与每一个感兴趣的目标计算机的端口进行连接。如果端口处于侦听状态,那么 connect()就能成功。否则,这个端口是不能用的,即没有提供服务。这个技术的一个最大的优点是,你不需要任何权限。系统中的任何用户都有权利使用这个调用。另一个好处就是速度。如果对每个目标端口以线性的方式,使用单独的 connect()调用,那么将会花费相当长的时间,你可以通过同时打开多个套接字,从而加速扫描。使用非阻塞 I/O 允许你设置一个低的时间用尽周期,同时观察多个套接字。但这种方法的缺点是很容易被发觉,并且被过滤掉。目标计算机的logs 文件会显示一连串的连接和连接是出错的服务消息,并且能很快的使它关闭。TC
3、P SYN 扫描这种技术通常认为是“半开放”扫描,这是因为扫描程序不必要打开一个完全的 TCP 连接。扫描程序发送的是一个 SYN 数据包,好象准备打开一个实际的连接并等待反应一样(参考TCP 的三次握手建立一个 TCP 连接的过程) 。一个 SYN|ACK 的返回信息表示端口处于侦听状态。一个 RST 返回,表示端口没有处于侦听态。如果收到一个 SYN|ACK,则扫描程序必须再发送一个 RST 信号,来关闭这个连接过程。这种扫描技术的优点在于一般不会在目标计算机上留下记录。但这种方法的一个缺点是,必须要有 root 权限才能建立自己的SYN 数据包。TCP 的三次握手第一次第一次握手:建立连
4、接时,客户端发送 syn 包(syn=j)到服务器,并进入 SYN_SENT 状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers) 。第二次第二次握手:服务器收到 syn 包,必须确认客户的 SYN(ack=j+1) ,同时自己也发送一个SYN 包( syn=k) ,即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态;第三次第三次握手:客户端收到服务器的 SYN+ACK 包,向服务器发送确认包 ACK(ack=k+1) ,此包发送完毕,客户端和服务器进入 ESTABLISHED 状态,完成三次握手。TCP FIN 扫描有的时候有可能
5、 SYN 扫描都不够秘密。一些防火墙和包过滤器会对一些指定的端口进行监视,有的程序能检测到这些扫描。相反,FIN 数据包可能会没有任何麻烦的通过。这种扫描方法的思想是关闭的端口会用适当的 RST 来回复 FIN 数据包。另一方面,打开的端口会忽略对 FIN 数据包的回复。这种方法和系统的实现有一定的关系。有的系统不管端口是否打开,都回复 RST,这样,这种扫描方法就不适用了。并且这种方法在区分 Unix 和 NT 时,是十分有用的。IP 段扫描这种不能算是新方法,只是其它技术的变化。它并不是直接发送 TCP 探测数据包,是将数据包分成两个较小的 IP 段。这样就将一个 TCP 头分成好几个数据
6、包,从而过滤器就很难探测到。但必须小心。一些程序在处理这些小数据包时会有些麻烦。TCP 反向 ident 扫描ident 协议允许(rfc1413)看到通过 TCP 连接的任何进程的拥有者的用户名,即使这个连接不是由这个进程开始的。因此你能,举个例子,连接到 http 端口,然后用 identd 来发现服务器是否正在以 root 权限运行。这种方法只能在和目标端口建立了一个完整的 TCP 连接后才能看到。TCP Connect 扫描:第一步调用 WSAStartup()函数初始化网络第二步获得目标 IP 地址和端口第三步创建 socket 和 sockaddr,并填充sockaddr第四步调用
7、 connect()函数,判断端口是否开放第五步扫描结束,调用 WSACleanup 完成清理工作多线程控制线程是指进程内的一条执行线路,或者说是进程中可执行代码的单独单元,它是操作系统的基本调度单元。一个进程至少有一个线程,即主线程,也可以有多个线程协同工作。进程从主线程开始执行,进而可以创建一个或多个附加线程来执行该进程内的并发任务,这就是基于线程的多任务。基于线程的多任务允许一个程序的两个或多个部分同时执行,这样增加了程序的维数,用户可以通过定义分离的执行线路来管理程序的执行,使编写出来的程序更高效。例如,通常为后台计算创建一个线程。特别的,在多处理器系统中,多线程可以极大地提高系统效率
8、。线程互斥和线程同步技术同步多线程百科名片同步多线程(SMT)是一种在一个 CPU 的时钟周期内能够执行来自多个线程的指令的硬件多线程技术。本质上,同步多线程是一种将线程级并行处理(多 CPU)转化为指令级并行处理(同一 CPU)的方法。 同步多线程是单个物理处理器从多个硬件线程上下文同时分派指令的能力。同步多线程用于在商用环境中及为周期/指令(CPI)计数较高的工作负载创造性能优势。 处理器采用超标量结构,最适于以并行方式读取及运行指令。同步多线程使您可在同一处理器上同时调度两个应用程序,从而利用处理器的超标量结构性质。用事件(Event)来同步线程是最具弹性的了。一个事件有两种状态:激发状
9、态和未激发状态。也称有信号状态和无信号状态。事件又分两种类型:手动重置事件和自动重置事件。手动重置事件被设置为激发状态后,会唤醒所有等待的线程,而且一直保持为激发状态,直到程序重新把它设置为未激发状态。自动重置事件被设置为激发状态后,会唤醒“一个”等待中的线程,然后自动恢复为未激发状态。所以用自动重置事件来同步两个线程比较理想。MFC 中对应的类为 CEvent.。CEvent 的构造函数默认创建一个自动重置的事件,而且处于未激发状态。共有三个函数来改变事件的状态:SetEvent,ResetEvent 和 PulseEvent。用事件来同步线程是一种比较理想的做法,但在实际的使用过程中要注意
10、的是,对自动重置事件调用 SetEvent 和 PulseEvent 有可能会引起死锁1.临界区线程互斥,建立临界区,临界区内存放着多个线程共享的资源,任何时刻,只允许一个共享资源,被一个线程访问,先进入临界区,其他线程不能进行访问被挂起,知道临界区的线程退出2.互斥区与临界区类似,通过创建一个类似于令牌互斥量来实现,拿到令牌的线程才有权利对共享资源进程访问,反问结束后线程将“令牌”交出3.事件1. CreatEvent() 函数 创建一个事件对象CreateEvent 是一个 Windows API 函数。它用来创建或打开一个命名的或无名的事件对像。如果想为对象指定一个访问掩码,应当使用 C
11、reateEventEx 函数。HANDLECreateEvent(LPSECURITY_ATTRIBUTESlpEventAttributes,/ 安全属性BOOLbManualReset,/ 复位方式BOOLbInitialState,/ 初始状态LPCTSTRlpName / 对象名称);2. OpenEvent() 函数 根据 LpName 来打开一个已经创建的对象打开一个已经存在的命名事件对象函数原型HANDLEOpenEvent( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);3. SetEvent() 函数
12、 将一个事件对象设置为有信号状态设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用 ResetEvent,这种情况下将释放多个线程;如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记;如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。CEvent:SetEventBOOL SetEvent(HANDLE hEvent);其中 hEvent 表示句柄,返回值:如果操作成功,则返回非零值,否则为 0。Win32 系统编程 API,用于线程间通信。4. ReseEvent() 函数 重置一个事件对象为无信号状态Res
13、etEvent这个函数把指定的事件对象设置为无信号状态。BOOL ResetEvent(HANDLE hEvent);参数说明:hEvent in 指向事件对象的句柄.由 CreateEvent or OpenEvent 函数返回。 这个句柄需要拥有EVENT_MODIFY_STATE 访问权限. 函数成功,返回非 0 值,否则返回 0 值,可以调用 GetLastError 得到错误的详细信息。Remarks一个事件对象一直都保持在无信号状态,直到显式调用 SetEvent or PulseEvent 函数把它设置到有信号状态。 这些无信号的事件对象会阻塞任何在内部调用 wait 函数的线程
14、。这个函数用于手动重置的事件对象。手动重置的对象在线程释放后必须手动置为无信号状态。 自动重置的事件对象在一个等待它成功的线程释放后会自动变为无信号状态。重置一个无信号的事件对象没有任何效果。5. WaitForSignleObject ()函数 等待一个对象变为有信号状态函数原型为 DWORD WaitForSignleObject( HANDLE hHandle, DWORD dwMilliseconds );参数说明:hHandle 表示要等待检查的对象句柄;dwMillseconds 表示该函数等待的期限;函数功能说明:该函数是用来等待指定的对象被触发或函数超时。若 dwMillise
15、conds 设置为无限大 INFINITE 则该函数一直等待下去直到对象被触发。函数返回值:WAIT_OBJECT_0 表示函数成功执行且指定的对象被触发处于 signaled 有信号状态;WAIT_TIMEOUT 表示函数成功执行但超时且对象没有被触发处于 nonsignaled 无信号状态;WAIT_FAILED 表示函数执行失败,通常是由 hHandle 句柄不可用,可以调用GetLastError()查看。详细说明:该函数检测指定的对象的当前状态,若为 nonsignaled 则调用者线程将处于等待状态,在此状态下消耗少量的处理器时间直到对象状态改变为 signaled 或超时。值得注
16、意的是超时时限范围为 00x7FFF FFFF,上限是 0x7FFF FFFF 而不是无穷大 0xFFFF FFFF。若设定值为 0x8000 00000xFFFF FFFF 将等同于 0x7FFFF FFFF。若要使用大于上限值请使用无穷大。在函数返回之前,有一个等待函数会修改引起函数返回的对象的状态,比如将信号量减 1。目前该函数可以等待的对象包括事件 event、互斥体 mutex、信号量semaphore、进程 process 和线程 thread。 信号量1. CreateSemaphore()函数 创建一个信号量为对象2. OpenSemaphore()函数 根据 LpName 来打开一个已经创建的信号量对象3.ReleaseSemaphore()函数 释放信号量对象的计数