安全中国首页 > 文章中心 > 入侵技术
 
安全中国网友投稿专用上传FTP空间:
Ftp服务器:download.anqn.com
Ftp端口:21
用户名:anqn
密 码:anqn.com
 

入侵检测技术介绍——目标探测

更新时间:2008-2-3 2:56:20
责任编辑:高远
热 点:

还有一个Tracert 命令,也非常有用,可以参考以前写的,这里就不再罗嗦了。 
关于ICMP协议的其他使用,比如,ICMP拒绝服务攻击等等,以后再讨论。 

由于现在一些防火墙对ICMP进行控制,所以,实际上用ping来做判断已经非常不可靠了。即使是个人防火墙,你也Ping不进去了。 
当然,我们有更多探测的方式,我们可以不使用ICMP协议,而使用更普通的TCP协议来进行探测,而且进行对方开放端口的扫描。普通的TCP探测是直接用connect()进行的,但是,在对方有防火墙情况下,Connect() 探测得出的结果也是不能确信的,如果熟悉更多关于TCP/IP协议的内容,我们就可以通过TCP/IP协议的特点尽可能地绕过防火墙。这就是大家所说得半开式扫描,其原理也就是不直接使用Connect进行对方端口得连接,而是发送TCP的标志位来实现,而且这样根本就不用同目标主机进行实际的连接。 
在X-Scanner也有使用SYN探测的一项,也就是通过下面这些原理来做的。 

SYN PING 
SYN位表示一个TCP连接的开始,也就是三次握手的第一步,向远端主机某端口发送一个只有SYN标志位的TCP数据报,如果主机反馈一个SYN || ACK数据包,那么,这个主机正在监听该端口,如果反馈的是RST数据包,说明,主机没有监听该端口。 

ACK PING 
在三次握手中,ACK来表示确认握手过程,但是,如果根本没有进行SYN的请求,而去确认连接,目标主机就会认为一个错误发生了,而发送RST位来中断会话。发送一个只有ACK标志的TCP数据报给主机,如果主机反馈一个TCP RST数据报来,那么这个主机是存在的。ACK探测更容易通过一些 stateless型的防火墙。 

FIN ping 
因为FIN标志表示一个结束,但是目标主机根本就没有这个连接记录,所以,根据TCP/IP协议,目标主机就要发送一个RST标志的数据包来中断这个会话。对某端口发送一个TCP FIN数据报给远端主机,如果主机没有任何反馈,那么这个主机是存在的,而且正在监听这个端口;主机反馈一个TCP RST回来,那么说明该主机是存在的,但是没有监听这个端口。 

NULL Ping 
即发送一个没有任何标志位的TCP包,根据RFC793,如果目标主机的相应端口是关闭的话,应该发送回一个RST数据包。 

后两种办法可以绕过一些防火墙,而得到防火墙后面的主机信息。即使在ICMP包被过滤的情况下,一般TCP探测还是能够成功的。当然,是在不被欺骗的情况下的。 

下面这段程序就是一个TCP/IP半开探测的例子,当然,并没有做得完美,因为没有接收部分,而在WIN2000下实际就是一个选择性的SNIFFER,呵呵,大家可以使用其他的SNIFFER来实现同样的目的。 

#include 
#include 
#include 

#define SOURCE_PORT 7234 
#define MAX_RECEIVEBYTE 255 

typedef struct ip_hdr //定义IP首部 

unsigned char h_verlen; //4位首部长度,4位IP版本号 
unsigned char tos; //8位服务类型TOS 
unsigned short total_len; //16位总长度(字节) 
unsigned short ident; //16位标识 
unsigned short frag_and_flags; //3位标志位 
unsigned char ttl; //8位生存时间 TTL 
unsigned char proto; //8位协议 (TCP, UDP 或其他) 
unsigned short checksum; //16位IP首部校验和 
unsigned int sourceIP; //32位源IP地址 
unsigned int destIP; //32位目的IP地址 
}IPHEADER; 

typedef struct tsd_hdr //定义TCP伪首部 

unsigned long saddr; //源地址 
unsigned long daddr; //目的地址 
char mbz; 
char ptcl; //协议类型 
unsigned short tcpl; //TCP长度 
}PSDHEADER; 

typedef struct tcp_hdr //定义TCP首部 

USHORT th_sport; //16位源端口 
USHORT th_dport; //16位目的端口 
unsigned int th_seq; //32位序列号 
unsigned int th_ack; //32位确认号 
unsigned char th_lenres; //4位首部长度/6位保留字 
unsigned char th_flag; //6位标志位 
USHORT th_win; //16位窗口大小 
USHORT th_sum; //16位校验和 
USHORT th_urp; //16位紧急数据偏移量 
}TCPHEADER; 

//CheckSum:计算校验和的子函数 
USHORT checksum(USHORT *buffer, int size) 

unsigned long cksum=0; 
while(size >1) 

cksum+=*buffer++; 
size -=sizeof(USHORT); 

if(size ) 

cksum += *(UCHAR*)buffer; 


cksum = (cksum >> 16) + (cksum & 0xffff); 
cksum += (cksum >>16); 
return (USHORT)(~cksum); 


void useage() 

printf("******************************************\n"); 
printf("TCPPing\n"); 
printf("\t Written by Refdom\n"); 
printf("\t Email: refdom@263.net\n"); 
printf("Useage: TCPPing.exe Target_ip Target_port \n"); 
printf("*******************************************\n"); 


int main(int argc, char* argv[]) 

WSADATA WSAData; 
SOCKET sock; 
SOCKADDR_IN addr_in; 
IPHEADER ipHeader; 
TCPHEADER tcpHeader; 
PSDHEADER psdHeader; 

char szSendBuf[60]={0}; 
BOOL flag; 
int rect,nTimeOver; 

useage(); 

if (argc!= 3) 
{ return false; } 

if (WSAStartup(MAKEWORD(2,2), &WSAData)!=0) 

printf("WSAStartup Error!\n"); 
return false; 


if ((sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_RAW,NULL,0,WSA_FLAG_OVERLAPPED))==INVALID_SOCKET) 

printf("Socket Setup Error!\n"); 
return false; 

flag=true; 
if (setsockopt(sock,IPPROTO_IP, IP_HDRINCL,(char *)&flag,sizeof(flag))==SOCKET_ERROR) 

printf("setsockopt IP_HDRINCL error!\n"); 
return false; 


nTimeOver=1000; 
if (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&nTimeOver, sizeof(nTimeOver))==SOCKET_ERROR) 

printf("setsockopt SO_SNDTIMEO error!\n"); 
return false; 

addr_in.sin_family=AF_INET; 
addr_in.sin_port=htons(atoi(argv[2])); 
addr_in.sin_addr.S_un.S_addr=inet_addr(argv[1]); 

// 
// 
//填充IP首部 
ipHeader.h_verlen=(4<<4 | sizeof(ipHeader)/sizeof(unsigned long)); 
// ipHeader.tos=0; 
ipHeader.total_len=htons(sizeof(ipHeader)+sizeof(tcpHeader)); 
ipHeader.ident=1; 
ipHeader.frag_and_flags=0; 
ipHeader.ttl=128; 
ipHeader.proto=IPPROTO_TCP; 
ipHeader.checksum=0; 
ipHeader.sourceIP=inet_addr("本地地址"); 
ipHeader.destIP=inet_addr(argv[1]); 

//填充TCP首部 
tcpHeader.th_dport=htons(atoi(argv[2])); 
tcpHeader.th_sport=htons(SOURCE_PORT); //源端口号 
tcpHeader.th_seq=htonl(0x12345678); 
tcpHeader.th_ack=0; 
tcpHeader.th_lenres=(sizeof(tcpHeader)/4<<4|0); 
tcpHeader.th_flag=2; //修改这里来实现不同的标志位探测,2是SYN,1是FIN,16是ACK探测 等等 
tcpHeader.th_win=htons(512); 
tcpHeader.th_urp=0; 
tcpHeader.th_sum=0; 

psdHeader.saddr=ipHeader.sourceIP; 
psdHeader.daddr=ipHeader.destIP; 
psdHeader.mbz=0; 
psdHeader.ptcl=IPPROTO_TCP; 
psdHeader.tcpl=htons(sizeof(tcpHeader)); 

//计算校验和 
memcpy(szSendBuf, &psdHeader, sizeof(psdHeader)); 
memcpy(szSendBuf+sizeof(psdHeader), &tcpHeader, sizeof(tcpHeader)); 
tcpHeader.th_sum=checksum((USHORT *)szSendBuf,sizeof(psdHeader)+sizeof(tcpHeader)); 

memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); 
memcpy(szSendBuf+sizeof(ipHeader), &tcpHeader, sizeof(tcpHeader)); 
memset(szSendBuf+sizeof(ipHeader)+sizeof(tcpHeader), 0, 4); 
ipHeader.checksum=checksum((USHORT *)szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader)); 

memcpy(szSendBuf, &ipHeader, sizeof(ipHeader)); 

rect=sendto(sock, szSendBuf, sizeof(ipHeader)+sizeof(tcpHeader), 
0, (struct sockaddr*)&addr_in, sizeof(addr_in)); 
if (rect==SOCKET_ERROR) 

printf("send error!:%d\n",WSAGetLastError()); 
return false; 

else 
printf("send ok!\n"); 

closesocket(sock); 
WSACleanup(); 

return 0; 


上面这个程序不光是一个Ping的程序,也可以更改成为一个比connect()更优秀的端口扫描器。 

上面这个程序实际上就是通过原始套接字发送自己构造的TCP和IP数据头,如果对这个程序作修改,也很容易改为一个SYN FLOOD的工具。SYN位前面说了,是三次握手过程的第一步,表示发出一个连接请求,这时目标主机同意的时候就会返回一个ACK SYN的数据报,来确认客户端的连接,然后需要客户端进行最后一次ACK的确认,来建立这个连接。但是,如果客户步发送一个ACK来确认,那么,服务器端就有一个缓冲来等待这个确认。当有大量的SYN缓冲等待的时候,正常的连接请求就会被放在一大堆队列中,从而影响正常用户的正常连接。同样相似的,就是RST拒绝服务了。 

进行上面的探测应该是探测的第一步,比如主机活动状态,端口。接来下应该针对相应端口进行更详细的判别,以及探测主机系统。 

上一页 1 2 3 

 
相关文章
一日一文章
 
一日一软件
一日一动画