荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: michaelx (Tiger Lazy), 信区: Security
标  题: 高级扫描技术及原理介绍
发信站: 荔园晨风BBS站 (Thu Feb 21 11:00:01 2002), 转信

高级扫描技术及原理介绍

发布日期: 2002-1-29
内容:
------------------------------------------------------------------------
--------

作者:refdom (refdom@263.net)

    Scan,是一切入侵的基础,对主机的探测工具非常多,比如大名鼎鼎的nmap。
我这里没有什么新鲜技术,都是一些老东西老话题,即使参考的Phrack文档也甚至
是96年的老文档,我只是拾人牙慧而已。

    最基本的探测就是Ping,不过现在连基本的个人防火墙都对Ping做了限制,这
个也太基本了。如果透过防火墙,如何获得最理想的目标图,也是很多人整天思考
的问题。

一、高级ICMP扫描技术

    Ping就是利用ICMP协议走的,我们在这里主要是利用ICMP协议最基本的用途:
报错,根据网络协议,如果按照协议出现了错误,那么接收端将产生一个ICMP的错
误报文。这些错误报文并不是主动发送的,而是由于错误,根据协议自动产生。


    当IP数据报出现checksum和版本的错误的时候,目标主机将抛弃这个数据报,
如果是checksum出现错误,那么路由器就直接丢弃这个数据报了。有些主机比如
AIX、HP-UX等,是不会发送ICMP的Unreachable数据报的。

    我们利用下面这些特性:
1、向目标主机发送一个只有IP头的IP数据包,目标将返回Destination
Unreachable的ICMP错误报文。
2、向目标主机发送一个坏IP数据报,比如,不正确的IP头长度,目标主机将返回
Parameter Problem的ICMP错误报文。
3、当数据包分片但是,却没有给接收端足够的分片,接收端分片组装超时会发送
分片组装超时的ICMP数据报。

    向目标主机发送一个IP数据报,但是协议项是错误的,比如协议项不可用,那
么目标将返回Destination Unreachable的ICMP报文,但是如果是在目标主机前有
一个防火墙或者一个其他的过滤装置,可能过滤掉提出的要求,从而接收不到任何
回应。可以使用一个非常大的协议数字来作为IP头部的协议内容,而且这个协议数
字至少在今天还没有被使用,应该主机一定会返回Unreachable,如果没有
Unreachable的ICMP数据报返回错误提示,那么就说明被防火墙或者其他设备过滤
了,我们也可以用这个办法来探测是否有防火墙或者其他过滤设备存在。

    利用IP的协议项来探测主机正在使用哪些协议,我们可以把IP头的协议项改变
,因为是8位的,有256种可能。通过目标返回的ICMP错误报文,来作判断哪些协议
在使用。如果返回Destination Unreachable,那么主机是没有使用这个协议的,
相反,如果什么都没有返回的话,主机可能使用这个协议,但是也可能是防火墙等
过滤掉了。NMAP的IP Protocol scan也就是利用这个原理。

    利用IP分片造成组装超时ICMP错误消息,同样可以来达到我们的探测目的。当
主机接收到丢失分片的数据报,并且在一定时间内没有接收到丢失的数据报,就会
丢弃整个包,并且发送ICMP分片组装超时错误给原发送端。我们可以利用这个特性
制造分片的数据包,然后等待ICMP组装超时错误消息。可以对UDP分片,也可以对
TCP甚至ICMP数据包进行分片,只要不让目标主机获得完整的数据包就行了,当然
,对于UDP这种非连接的不可靠协议来说,如果我们没有接收到超时错误的ICMP返
回报,也有可能时由于线路或者其他问题在传输过程中丢失了。

    我们能够利用上面这些特性来得到防火墙的ACL(access list),甚至用这些
特性来获得整个网络拓扑结构。如果我们不能从目标得到Unreachable报文或者分
片组装超时错误报文,可以作下面的判断:
1、防火墙过滤了我们发送的协议类型
2、防火墙过滤了我们指定的端口
3、防火墙阻塞ICMP的Destination Unreachable或者Protocol Unreachable错误消
息。
4、防火墙对我们指定的主机进行了ICMP错误报文的阻塞。

二、高级TCP扫描技术

    最基本的利用TCP扫描就是使用connect(),这个很容易实现,如果目标主机能
够connect,就说明一个相应的端口打开。不过,这也是最原始和最先被防护工具
拒绝的一种。
    在高级的TCP扫描技术中主要利用TCP连接的三次握手特性来进行,也就是所谓
的半开扫描。这些办法可以绕过一些防火墙,而得到防火墙后面的主机信息。当然
,是在不被欺骗的情况下的。下面这些方法还有一个好处就是比较难于被记录,有
的办法即使在用netstat命令上也根本显示不出来。

SYN
    向远端主机某端口发送一个只有SYN标志位的TCP数据报,如果主机反馈一个
SYN || ACK数据包,那么,这个主机正在监听该端口,如果反馈的是RST数据包,
说明,主机没有监听该端口。在X-Scanner 上就有SYN的选择项。

ACK
    发送一个只有ACK标志的TCP数据报给主机,如果主机反馈一个TCP RST数据报
来,那么这个主机是存在的。

FIN
    对某端口发送一个TCP FIN数据报给远端主机。如果主机没有任何反馈,那么
这个主机是存在的,而且正在监听这个端口;主机反馈一个TCP RST回来,那么说
明该主机是存在的,但是没有监听这个端口。

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

FIN+URG+PUSH
    向目标主机发送一个Fin、URG和PUSH分组,根据RFC793,如果目标主机的相应
端口是关闭的,那么应该返回一个RST标志。

三、高级UDP扫描技术
    在UDP实现的扫描中,多是了利用和ICMP进行的组合进行,这在ICMP中以及提
及了。还有一些特殊的就是UDP回馈,比如SQL SERVER,对其1434端口发送‘x02’
或者‘x03’就能够探测得到其连接端口。


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

#include <stdio.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#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 usage()
{
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;

usage();

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;
}

-------------------------------------------

reference:

1、《Breaking into computer networks from the Internet》 Roelof Temmingh
 & SensePost (Pty) Ltd
2、Phrack #49,《Port Scanning without the SYN flag》
3、Phrack #51,《The Art of Port Scanning》
4、Sys-Security Group《ICMP Usage in Scanning》


--
M.X的FTP SERVER
ftp://192.168.55.18

※ 来源:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 203.93.19.1]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店