吵吵   2011-11-12  阅读:3,757

有研究数据显示,在中国,父母的收入每增加10%,则子女的收入平均增加4.5%。这已经充分的说明了中国拼爹时代的来临,让我们无背景的小卒情何以堪。
考研比较忙,所以把以前一些资料翻出来发了。

H3C802.1x 兼容客户端编程技术详述
By thorqq(05.10.02)
从《H3C802_1x 协议解析》可以看到,交换机并没有检查代理、双网卡的功能。其实
这个功能都是由 H3C 客户端来实现的。客户端会检查流经网卡的所有数据,一旦检查到具
有代理或者 NAT 特征的数据包时,立刻会向交换机发送断线请求,并提示用户 IP 数据转发
的信息;当客户端检查到本机存在 2 块或者 2 块以上网卡时,拒绝认证连接。同时,在该文
中也可看到,本机的 IP 只是用户名的一个附属属性,交换机并不会检查本机的 IP,只需在
待发送的数据包中设置好用户名和绑定的 IP,即可在实现“一个帐号到处上网”的功能。
根据认证流程,利用 winpcap 提供的网卡操作函数,可以做出 H3C 客户端的简化版本,
该版本去除了代理、双网卡检查功能,IP 地址作为帐户的附属属性由用户手动输入,而不
是从系统中获得。
1. 获取网卡信息
利用 IP_ADAPTER_INFO 可以得到本机所有网卡的 name、description、MAC 等信息
2. 初始化待发送的各种数据包:认证请求包、断开连接包、版本信息包、用户名包(包含
Length 域、IP、用户名)、密码包(包含 Length 域、加密后的密码、用户名)、在线保持
包(包含 Length 域、IP、用户名)。
3. 打开网卡
pcap_t *fp;
fp = pcap_open_live(device, 128, 1, 20, errbuf);
device:网卡的 name
128:抓取的包的最大长度为 128
20: 抓到包之后延迟 20ms 再做出响应
errbuf 为字符数组 char errbuf[PCAP_ERRBUF_SIZE];
4. 启动包处理循环线程
pcap_loop(fp, 0, packet_handler, NULL);
packet_handler:包处理函数。
5. 分析包,并触发动作
void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char
*pkt_data)该函数将在下文中详细介绍。
6. 发送请求认证 或者 断开连接 数据包。
7. 断开连接后关闭网卡
pcap_close(fp);
下面将详细介绍 packet_handler 函数流程。
1. 判断是否为 802.1x 协议(88 8e 01 00)的数据包,目的 mac 是否为本机。如果不是退出
本函数;如果是,进入下面的判断。
2. 如果是第一次接收到数据包,从中得到交换机 mac,填入所有待发送的数据包。以后的
数据包收发都此 MAC 和本机 MAC 之间进行
3. 如果是版本查询包(判断 0x10-0x12,0x14-0x16 这六位,以下同),回复版本信息包
4. 如果是要求发送用户名数据包或者是在线查询包(这两个包内容相同)
如果已经成功认证,拷贝 Identifier,发送在线保持包;
,发送在线保持包;如果尚未成功认证,拷贝 Identifier,发送用户名包。
5. 如果是密码请求包,拷贝 Identifier,把密码做 MD5 加密后,发送密码包
6. 如果是成功认证包,通知界面上线
7. 如果是失败包,通知界面下线,并提示用户下线原因。
HWND Owner = 0; // 界面的窗体句柄(通知消息的时候需要)
// 判断这种包的类型的标志
u_char PType[4] = {0x88, 0x8e, 0x01, 0x00};
u_char SessionFlagA[3] = {0x00, 0x05, 0x01};
u_char SessionFlagB[3] = {0x00, 0x05, 0x01};
u_char SessionFlagC[3] = {0x00, 0x05, 0x14};
u_char UnknowFlagA[3] = {0x00, 0x05, 0x02};
u_char RequestPwdFlagA[3] = {0x00, 0x16, 0x01};
u_char RequestPwdFlagB[3] = {0x00, 0x16, 0x04};
u_char SuccessFlagA[3] = {0x00, 0x04, 0x03};
u_char SuccessFlagB[3] = {0x00, 0x04, 0x00};
u_char ByeFlagA[3] = {0x00, 0x06, 0x04};
u_char ByeFlagB[3] = {0x00, 0x07, 0x08};
void packet_handler(u_char *param,
const struct pcap_pkthdr *header,
const u_char *pkt_data)
{
//协议为 EAPOL 的包
if ( !memcmp(pkt_data + 0x0c, PType, 4) &&
!memcmp(pkt_data + 0x00, pData1->Mac, 6))
{
// 在此处我们获得以后我们所要回复的 MAC 地址
if (FirstPacket)
{
FirstPacket = false;
ChangeDestMac(pkt_data + 0x06);
}

// 判断是否为版本查询包
if (!memcmp(pkt_data + 0x10, SessionFlagA, 3) &&
!memcmp(pkt_data + 0x14, UnknowFlagA, 3))
{
// 发送对应的回复包
pcap_sendpacket(fp, UnknowBufA, 67);
return;
}
// 判断是否为对话维持包或要求发送用户名的包(这两种包的特征是一样的) if (!memcmp(pkt_data + 0x10, SessionFlagA, 3) &&
(!memcmp(pkt_data + 0x14, SessionFlagB, 3) ||
!memcmp(pkt_data + 0x14, SessionFlagC, 3)) )
{
// 如果发送过用户名则发送对话维持包
if (online)//已经上线,发送对话维持包
{
memcpy(SessionBuf + 0x13, pkt_data + 0x13, 1); //拷贝 Identifier
pcap_sendpacket(fp, SessionBuf, 60);
else // 否则就发送用户名
{
memcpy(SendUsernameBuf + 0x13, pkt_data + 0x13, 1);
pcap_sendpacket(fp, SendUsernameBuf, 60);
}
return;
}
// 判断是否为要求发送密码的包
if (!memcmp(pkt_data + 0x10, RequestPwdFlagA, 3) &&
!memcmp(pkt_data + 0x14, RequestPwdFlagB, 3))
{
memcpy(PasswordBuf + 0x13, pkt_data + 0x13, 1);
SetMd5Buf(pkt_data + 0x13, pkt_data + 0x18);//MD5 加密
pcap_sendpacket(fp, PasswordBuf, 60);
return;
}
// 判断是否为认证成功的包 code=3
if (!memcmp(pkt_data + 0x10, SuccessFlagA, 3) &&
!memcmp(pkt_data + 0x14, SuccessFlagB, 3))
{
if (online == false)
{
online = true;
SendMessage(Owner, WM_ONLINE, 0, 0);
}
return;
}
// failure 包 code=4
if (!memcmp(pkt_data + 0x10, ByeFlagA, 3))
{
// 判断是否为断线成功的包
if(!memcmp(pkt_data + 0x14, ByeFlagB, 3)) {
if (online == true)
{
online = false;
SendMessage(Owner, WM_OFFLINE, 0, 0);
popmsg = FALSE;
CloseOneX(); //关闭网卡
}
}
else// 其他离线包
{
SendMessage(Owner, WM_OFFLINE, 0, 0);
errorMsg.Format(“%s\0”, (pkt_data+0x18));
SendMessage(Owner, WM_TRAY, 0, 2);//提取出错信息,并向界面发送消息
CloseOneX();
}
return;
}
}
}
感谢 cshacker 的帮助

吵吵微信朋友圈,请付款实名加入:

吵吵 吵吵

一条回应:“802.1x客户端编程技术详述”

  1. 博客爪说道:

    看起来漂亮多了。本站域名备案中,暂时用此博客http://xiaomi.sinaapp.com。给您带来的不便请谅解

发表评论

电子邮件地址不会被公开。 必填项已用*标注