linux c 编程之三 80banner 扫描器

linux c 编程之三  80banner 扫描器

一思路:

   平时用了扫描器,总能得到对方的服务和及服务器类型。
其实这个从80端口的www服务器是很容易完成。一个手工的方法。
就是 telnet  targetip 80  然后输入  HEAD / HTTP/1.0 
可以得到:
HTTP/1.1 400 Bad Request
Date: Tue, 29 Apr 2003 08:54:26 GMT
Server: Apache/1.3.26 (Unix) PHP/4.2.2
Connection: close
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
                                                  <HTML><HEAD>
                                                              <TITLE>400 Ba
uest</TITLE>
            </HEAD><BODY>
                         <H1>Bad Request</H1>
                                             Your browser sent a request th
is server could not understand.<P>
                                  The request line contained invalid charac
following the protocol string.<P>
                                 <P>
                                    <HR>
                                        <ADDRESS>Apache/1.3.26 Server at mi
u.com Port 80</ADDRESS>
                       </BODY></HTML>
这里就知道由什么提供和是什么样的服务器,不过这个也不一定很准确的。
原因?别人厉害咯!上面的就知道apache版本 apache/1.3.26  系统类型是unix 
php版本是php/4.2.2  域名miu.com
每次都这样手工完成还是比较麻烦的,好现在就用编程来做。

二,函数说明。

这个就要用到socket编程的知识.这方面要了解挺多的东西:
你也要找一些专门的资料来学,这里只是简单列示:
1.套接字的类型
SOCKET_STREAM
SOCKET_DGRAM
SOCKET_RAW
SOCKET_SEQPACKET
SOCKET_RDM

2.套接字的地址结构
sockaddr_in
sockaddr
in_addr

3.tcp套接字的实现过程:

服务器端

socket()
   |
bind()
   |                     客户端
listen()                 socket()
   |                        |
accept()<--协调连接---- connect()
   |                        |
recv()<---数据请求------ send()<--
   |     |                  |    |
send()<----数据响应----> recv()--
   |                        |
recv()<-----结束连接------close()
   |
close()

下面具体介绍几个重要的函数:


 1.socket():
1.1 原型:
#include<sys/types.h>
#incldue<sys/socket.h>
int socket(int domain,int type,int protocol);
1.2函数描述:
调用socket函数获得一个文件描述符
domain:协议簇和地址簇,最常用的有AF_INET(IPv4协议)和AF_INET6(IPv6协议)

type:通信类型 SOCK_STREAM(字节流套接口)、SOCK_DGRAM(数据报套接口)和
SOCK_RAW(原始套接口)

protocol:使用的协议,为0时系统自动选择。
1.3返回值:
成功返回非零,失败返回-1。

  2.connect():
2.1原型:
#include<sys/types.h>
#include<sys/socket.h>
int connect(int s,const struct sockaddr *name,int namelen);
2.2描述:
调用connect为这个套接字指明远程端的地址
s是socket()函数返回的套接字描述符
name是包含远程主机ip地址和端口号的指针
namelen是远程地址结构的长度
2.3返回值
成功返回0,失败返回-1

  3.send():
3.1原型:
#include<sys/types.h>
#include<sys/socket.h>
int send(int s,const void *msg,size_t len,int flags);
3.2描述:
s 是accept()返回的套接字描述符,对于客户是socket()返回的套接字描述符。
msg是指向一个包含传输信息的数据缓冲区。
len 指明传送数据缓冲区的大小
flags是传输控制标志,其定义如下:
0 常规操作
msg_ooB  带外数据
msg_DONTROUT  通过最直接的路径发送数据,而忽视底层协议的路由设置.
如果flags为0,则和read,write一样的操作
3.3返回值
成功返回发送数据的长度,以字节为单位,失败返回-1.

  4.recv():
4.1原型:
#include<sys/types.h>
#include<sys/socket.h>
int recv(int s,void *buf,size_t len,int flags);
4.2描述:
s 是accept()返回的套接字描述符,对于客户是socket()返回的套接字描述符。
buf是指向一个包含接受信息的数据缓冲区。
len 和 flags 同上。
4.3返回值
成功返回接受的数据长度,失败返回-1.

  5.gethostbyname():
5.1原型:
string gethostbyname(string hostname);
5.2描述:
本函数可返回某个机器名称 (Domain Name) 的 IP 网址 (IP Address)。若执行失败,则返回原来的机器名称。

 


  6.sockaddr_in 结构:
6.1结构:
sockaddr_in在netinet/in.h中定义:
struct sockaddr_in {
short int sin_family; /*协议*/
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* 网络地址 */
unsigned char sin_zero[8]; /* 保持和sockaddr结构大小 */
};
6.2描述:
使用sockaddr_in这个结构来设置/获取地址信息。
sin_family指代协议族,在socket编程中只能是AF_INET
sin_port存储端口号(使用网络字节顺序)
sin_addr存储IP地址,使用in_addr这个数据结构
struct in_addr {
unsigned long s_addr;
};
这个数据结构是由于历史原因保留下来的,主要用作与以前的格式兼容。
s_addr按照网络字节顺序存储IP地址
sin_zero是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。
6.3示例:
struct sockaddr_in sa;
sa.sin_family = AF_INET;
sa.sin_port = htons(3490); /* short, NBO*/
sa.sin_addr.s_addr = inet_addr("132.241.5.10");
bzero(&(sa.sin_zero), 8);
注意:如果sa.sin_addr.s_addr = INADDR_ANY,则不指定IP地址


  7.hostent 结构
7.1结构:
该数据结构定义如下:
struct hostent{
char *h_name; /*主机的正式名称*/
char **h_aliases; /* 主机的别名*/
int h_addrtype; /*返回的地址类型,一般是AF_INET*/
int h_length; /* 地址的字节长度*/
char **h_addr_list /*主机的网络地址*/
}


ok 了解上面那些,就差不多可以开始写程序拉,不十分了解也没问题。能用就先用。以后慢
慢了解每样的用法。其实还有很多东西要了解的。我只是列出我程序里面基本用到的罢了

三.程序设计:

linux下:
建立一个文件80banner
nightcat@nightcat$vi 80banner.c
编辑以下内容:
/* the www banner scanner .80scanner version 1.0
 *
 * check for the enter ip or daemon to get the banner
 *
 *to complie:
 *user$gcc -o 80scaner 80scanner.c
 *
 *to use:
 *user$./80scanner somedomain.com (i.e. ./80scanner  antionline.com)
 *
 *coded by nightcat
 *march 2004
 *
 * */


#include<sys/types.h>
#include<netinet/in.h>
#include<string.h>
#include<netdb.h>
#include<ctype.h>
#include<arpa/nameser.h>
#include<strings.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>


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

int s;
struct in_addr addr;
struct sockaddr_in victem;
struct hostent *bad;
char buffer[1024];

if (argc!=2)
{
exit(printf("/nUsage:%s domain.com /n",argv[0]));
}

if ((bad=gethostbyname(argv[1]))==NULL)
{
exit(printf("Error getting hostname/n"));
}


printf("check  web server version/n");
printf("coded by nighcat/n");

system("sleep 2");

s=socket(AF_INET,SOCK_STREAM,0);
if(s<0) exit(printf("socket error/n"));

bcopy(bad->h_addr,(char *)&victem.sin_addr,bad->h_length);
victem.sin_family=AF_INET;
victem.sin_port=htons(80);

if(connect(s,(struct sockaddr*)&victem,sizeof(victem))<0)
{
exit(printf("connect error/n"));
}
printf("/ngetting http version/n/n");
send(s,"HEAD / HTTP/1.0/n/n",17,0);
recv(s,buffer,sizeof(buffer),0);
printf("version:/n%s",buffer);
close(s);

}
保存文件
:wq
编译执行:
nightcat@nightcat$gcc -o 80scaner 80scanner.c
nightcat@nightcat$./80scanner somedomain.com 
结果就会在xterm下输出。因为输出的缓冲区只有1024字节。
可以得到结果如下:
HTTP/1.1 400 Bad Request
Date: Tue, 29 Apr 2003 08:54:26 GMT
Server: Apache/1.3.26 (Unix) PHP/4.2.2
Connection: close
Content-Type: text/html; charset=iso-8859-1

四.后言:
 
  这一篇涉及了socket编程,难度就高了点。不过其实熟悉几个步骤也不过如此罢了。
也可以扩充成多线程和把结果记到文件里面去,那就更象个好的扫描器.里面也要注意一下
htons(80) 这是字节顺序的转换的,详细的看看资料!


五.联系我:

nickname:nightcat
e-mail:ncnynl@hotmail.com
qq:1043931
icq:153436005

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值