分享
 
 
 

My 802.1X Supplicant for FreeBSD

王朝system·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

mysupplicant是我自己写的一个FreeBSD下的802.1X认证客户端。上次提到了学校网络改用DHCP分配IP,而且增加了802.1X认证,于是打算为实验室的网关服务器(FreeBSD)写一个认证客户端。

程序基于BPF,所以在BSD下不需要libpcap和libnet就可以控制数据链路层的数据帧,关于怎么使用BPF,可以参考man手册(man bpf)。花了两天时间按照标准的协议写了个基本代码,md5加密。测试时告诉我认证失败,但用户名和密码没错,晕………于是抓了些windows下用锐杰的802.1X客户端Ruijie Supplican(学校网络中心给的,也就是我上次破解的那个)认证过程的数据包,发现认证交换机是实达的,而且它在EAPoL的数据帧后面附加了一些它自己的数据,附加的数据中还有几个字节变化,于是猜想可能实达还有它自己的一套认证机制,而且就藏在这些附加的数据里面。不管这么多,在我的程序里直接把抓包得到的附加数据也附加到EAPoL后面,再测试时认证成功,^_^可不一会就收到交换机发的Logoff的EAPoL帧。再仔细看抓的包,原来认证客户端每20秒给交换机发一个类型为0xBF的EAPoL帧。上网搜了下,找到个源代码mystar,使用libpcap+libnet写的认证客户端,里面有实达的认证机制。于是按照mystar中所了解的实达的认证机制修改了我的程序,包括标准EAPoL后面附加的数据,和每20秒发送的数据帧。再测试,这下连认证都通不过了。再改,把标准EAPoL帧后附加的数据改成我自己抓包得到的数据(想当然这样修改,至于这些附加的数据包到底起什么作用,我不知道,有时间的话我会详细逆向下Ruijie Supplican,希望自己也能从中分析透实达的认证机制,像mystar的作者一样),每20秒发送的数据帧用mystar的。成功了…………现在程序已在实验室用了1天,一切都正常,应该说可以正常工作了吧。

写最初的代码花了两天时间,调试也花了两天时间,还好看到了mystar才能调试成功。这里谢谢mystar的作者netxray@byhh,他对实达的认证机制分析得很透,佩服!!

程序参考了IEEE Std 802.1X-2001,RFC1994 PPP Challenge Handshake Authentication Protocol (CHAP)和RFC2284 PPP Extensible Authentication Protocol (EAP)。代码写的很烂,只能供自己使用,拿出来都感觉有点丢人^_^如有什么建议,感激不尽。(如需要所有源代码,可以给我邮件。我免费提供,还包括上面的3篇参考文献和mystarV0.1-src)下面贴出程序的主要代码mysupplicant.c:

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include "global.h"

#include "md5.h"

#define ETHERTYPE_8021X 0x888e

#define EAPOL_Packet 0x00

#define EAPOL_Start 0x01

#define EAPOL_Logoff 0x02

#define EAP_Request 1

#define EAP_Response 2

#define EAP_Success 3

#define EAP_Failure 4

#define EAP_TYPE_Identity 1

#define EAP_TYPE_MD5Challenge 4

typedef unsigned char int8;

typedef unsigned short int16;

typedef unsigned long int32;

struct bpf_insn insns[] = {

BPF_STMT(BPF_LD+BPF_H+BPF_ABS, 12),//加载halfword以太网链路层的type

BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ETHERTYPE_8021X, 0, 1),//判断是否是802.1X数据包,是则返回给本程序

BPF_STMT(BPF_RET+BPF_K, (u_int)-1),

BPF_STMT(BPF_RET+BPF_K, 0),

};

typedef struct EAPOLforEthernet//EAPOL在Ethernet上的帧格式

{

int16 ethertype;

int8 version;

int8 type;

int16 length;

}EAPOL;

typedef struct EAPformat//EAP的帧格式

{

int8 code;

int8 id;

int16 length;

int8 type;

}__attribute__((packed)) EAP;

typedef union

{

u_int32_t ulValue;

u_int8_t btValue[4];

}ULONG_BYTEARRAY;

ULONG_BYTEARRAY m_serialNo; //序列号,收到第一个有效的Authentication-Success-packet时初始化

ULONG_BYTEARRAY m_key; //密码加密键值,在main()函数开始时初始化

char standardMAC[6]={0x01,0x80,0xc2,0x00,0x00,0x03};//标准802.1X组播MAC地址

char name[7]="1234567";//用户名

char pass[6]="123456";//密码

char * nic="lnc0";//网卡名

char pad[]={"\xff\xff\x37\x77x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\\xff\xff\xff\xff\xff\xf5\x71\x00\x00\x13\x11\x38\x30\x32\x31\x78\\x2e\x65\x78\x65\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x28\x00\x00\x00\x00\x00\x13\x11\x00\x28\x1a\x28\x00\x00\x13\x11\x17\x22\x60\x63\x67\x65\x91\x66\x92\x94\x68\x92\x91\x64\x96\x95\x67\x91\x93\x95\x94\x93\x63\x62\x64\x61\x67\x6b\x84\xae\x77\x97\x6c\x6b\x00\x00\x13\x11\x18\x06\x00\x00\x00\x01"};//每个本机发送的链路层帧后面附加这些字符,每帧1000byte,实达交换机自己的验证机制??

/*char pad[] = { //实达专有响应附加包

0xFF,0xFF,0x37,0x77,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x08,0x15,0x00,0x00,0x13,0x11,0x38,0x30,0x32,0x31,0x78,

0x2E,0x65,0x78,0x65,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x1F,0x00,0x00,0x00,

0x00,0x00,0x13,0x11,0x00,0x28,0x1A,0x28,0x00,0x00,0x13,0x11,0x17,0x22,0x92,0x68,

0x64,0x66,0x92,0x94,0x62,0x66,0x91,0x93,0x95,0x62,0x93,0x93,0x91,0x94,0x64,0x61,

0x64,0x64,0x65,0x66,0x68,0x94,0x98,0xA7,0x61,0x67,0x65,0x67,0x9C,0x6B,0x00,0x00,

0x13,0x11,0x18,0x06,0x00,0x00,0x00,0x01};*/

char echoPackaget = { //echo包,用于每20秒钟激活一次

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x88,0x8E,0x01,0xBF,

0x00,0x1E,0xFF,0xFF,0x37,0x77,0x7F,0x9F,0xF7,0xFF,0x00,0x00,0xFF,0xFF,0x37,0x77,

0x7F,0x9F,0xF7,0xFF,0x00,0x00,0xFF,0xFF,0x37,0x77,0x7F,0x3F,0xFF};

void sig_intr(int signo); //发送logoff包 on exit with Ctrl+C

char * buf;

char * p;

int8 dstMAC[6]={0,};

int bpf;

int blen;

unsigned char circleCheck[2]; //那两个鬼值

unsigned char Alog(unsigned char BForAlog)

{

int a=0,b=0,c=0,d=0,iRt;

a=BForAlog;

c=a;

d=a;

c&=0x40;

b=a;

d=2;

c|=d;

d=a;

c=2;

d&=0x20;

c|=d;

d=a;

c=2;

d&=0x10;

c|=d;

d=a;

d&=2;

b=1;

d= 8;

dx ^= bx;

bx = 0;

bx &= 0x00ff;

bx |= (ax&0xff)8);

circleCheck[1] = (unsigned char) (ax&0x00ff);

}

int main()

{

int tmp;

char challengelen;

struct ifreq ifr;

struct bpf_program bpf_pro={4,insns};

struct timeval timeout={5,0};//设置BPF 5秒的超时

char * bufmd5;

int8 id;

char md5Hash[16];

MD5_CTX context;

fd_set readset;

ULONG_BYTEARRAY uTemp;

printf(" My 802.1X Supplicant for FreeBSD\n");

printf(" Coded by xdkui 5/22/2005\n");

printf(" E-mail:xdkui@sina.com.cn\n");

if((bpf=open("/dev/bpf1",O_RDWR))==-1)

{

perror("open /dev/bpf1 error");

exit(1);

}

strcpy(ifr.ifr_name,nic);//设置BPF的网络接口

if((-1==ioctl(bpf,BIOCGBLEN,&blen))||(-1==ioctl(bpf,BIOCSETIF,&ifr))||

(-1==ioctl(bpf,BIOCSETF,&bpf_pro))||(-1==ioctl(bpf,BIOCFLUSH))||(-1==ioctl(bpf,BIOCSRTIMEOUT,&timeout)))

{

perror("ioctl error");

close(bpf);

exit(1);

}

m_serialNo.ulValue = 0x1000002a; //the initial serial number, a magic number!

InitializeBlog();

//FillNetParamater( &pad[0x05] );

if((buf=(char *)malloc(blen))==NULL)

{

perror("malloc buf error");

close(bpf);

exit(1);

}

signal(SIGINT,sig_intr); //exit with Ctrl+C

signal(SIGTERM,sig_intr); //关机时发logoff EAPOL

retry:

//构造802.1X的EAPOL-Start帧

printf("send EAPOL_Start packet!\n");

memset(buf,0,blen);

memcpy(buf,standardMAC,6);

((EAPOL *)(buf+12))-ethertype=htons(0x888E);

((EAPOL *)(buf+12))-version=1;

((EAPOL *)(buf+12))-type=EAPOL_Start;

((EAPOL *)(buf+12))-length=0;

memcpy(buf+12+sizeof(EAPOL),pad,sizeof(pad));

if(1000!=write(bpf,buf,1000)) //发送802.1X的EAPOL-Start帧

{

perror("write EAPOL_Start error");

goto retry;

}

//读取EAP Request Identity帧

FD_ZERO(&readset);

FD_SET(bpf, &readset);

ioctl(bpf,BIOCFLUSH);

if(1!=(tmp=select(bpf+1,&readset,NULL,NULL,&timeout)))

{

perror("select read EAP Request Identiry");

goto retry;

}

if(-1==read(bpf,buf,blen))

{

perror("read EAP Request Identity error");

goto retry;

}

p=buf+((struct bpf_hdr *)buf)-bh_hdrlen;

if((((EAPOL *)(p+12))-type!=EAPOL_Packet)||(((EAP *)(p+12+sizeof(EAPOL)))-code!=EAP_Request)

||(((EAP *)(p+12+sizeof(EAPOL)))-type!=EAP_TYPE_Identity))

{

printf("EAP Request Identity format error!\n");

goto retry;

}

id=((EAP *)(p+12+sizeof(EAPOL)))-id;

memcpy(dstMAC,p+6,6);

//构造EAP Response Identity帧

printf("send EAP Response Identity packet!\n");

memset(buf,0,blen);

memcpy(buf,dstMAC,6);

((EAPOL *)(buf+12))-ethertype=htons(0x888E);

((EAPOL *)(buf+12))-version=1;

((EAPOL *)(buf+12))-type=EAPOL_Packet;

((EAPOL *)(buf+12))-length=htons(sizeof(EAP)+sizeof(name));

((EAP *)(buf+12+sizeof(EAPOL)))-code=EAP_Response;

((EAP *)(buf+12+sizeof(EAPOL)))-id=id;

((EAP *)(buf+12+sizeof(EAPOL)))-length=htons(sizeof(EAP)+sizeof(name));

((EAP *)(buf+12+sizeof(EAPOL)))-type=EAP_TYPE_Identity;

memcpy(buf+12+sizeof(EAPOL)+sizeof(EAP),name,sizeof(name));

memcpy(buf+12+sizeof(EAPOL)+sizeof(EAP)+sizeof(name),pad,sizeof(pad));

if(1000!=write(bpf,buf,1000)) //发送EAP Response Identity帧

{

perror("write EAP Response Identity error");

goto retry;

}

//读取EAP Request MD5-Challenge帧

FD_ZERO(&readset);

FD_SET(bpf, &readset);

ioctl(bpf,BIOCFLUSH);

if(1!=select(bpf+1,&readset,NULL,NULL,&timeout))

{

perror("select read EAP Request MD5-Challenge");

goto retry;

}

if(-1==read(bpf,buf,blen))

{

perror("read EAP Request MD5-Challenge errorr");

goto retry;

}

p=buf+((struct bpf_hdr *)buf)-bh_hdrlen;

if((((EAPOL *)(p+12))-type!=EAPOL_Packet)||(((EAP *)(p+12+sizeof(EAPOL)))-code!=EAP_Request)

||(((EAP *)(p+12+sizeof(EAPOL)))-type!=EAP_TYPE_MD5Challenge))

{

printf("EAP Request MD5-Challenge format error!\n");

goto retry;

}

id=((EAP *)(p+12+sizeof(EAPOL)))-id;

challengelen=*((char *)(p+12+sizeof(EAPOL)+sizeof(EAP)));

//printf("challengelen %d\n",challengelen);

if((bufmd5=(char *)malloc(1+challengelen+sizeof(pass)))==NULL)

{

perror("malloc bufmd5 error");

close(bpf);

exit(1);

}

/*The Response Value is the one-way hash calculated over a stream of

octets consisting of the Identifier, followed by (concatenated

with) the "secret", followed by (concatenated with) the Challenge

Value. The length of the Response Value depends upon the hash

algorithm used (16 octets for MD5).见RFC1994*/

memset(bufmd5,0,1+challengelen+sizeof(pass));

*bufmd5=id;

memcpy(bufmd5+1,pass,sizeof(pass));

memcpy(bufmd5+1+sizeof(pass),p+12+sizeof(EAPOL)+sizeof(EAP)+1,challengelen);

MD5Init(&context);//计算md5值

MD5Update(&context, bufmd5, 1+challengelen+sizeof(pass));

MD5Final(md5Hash, &context);

//构造EAP Response MD5-Challenge帧

printf("send EAP Response MD5-Challenge packet!\n");

memset(buf,0,blen);

memcpy(buf,dstMAC,6);

((EAPOL *)(buf+12))-ethertype=htons(0x888E);

((EAPOL *)(buf+12))-version=1;

((EAPOL *)(buf+12))-type=EAPOL_Packet;

((EAPOL *)(buf+12))-length=htons(sizeof(EAP)+sizeof(name)+challengelen+1);//这里的1是EAP里的value-size

((EAP *)(buf+12+sizeof(EAPOL)))-code=EAP_Response;

((EAP *)(buf+12+sizeof(EAPOL)))-id=id;

((EAP *)(buf+12+sizeof(EAPOL)))-length=htons(sizeof(EAP)+sizeof(name)+challengelen+1);

((EAP *)(buf+12+sizeof(EAPOL)))-type=EAP_TYPE_MD5Challenge;

*(char *)(buf+12+sizeof(EAPOL)+sizeof(EAP))=16;//md5 hash长度

memcpy(buf+12+sizeof(EAPOL)+sizeof(EAP)+1,md5Hash,16);

memcpy(buf+12+sizeof(EAPOL)+sizeof(EAP)+1+16,name,sizeof(name));

memcpy(buf+12+sizeof(EAPOL)+sizeof(EAP)+1+16+sizeof(name),pad,sizeof(pad));

if(1000!=write(bpf,buf,1000))

//发送EAP Response MD5-Challenge帧

{

perror("write EAP Response MD5-Challenge error");

goto retry;

}

//读取EAP success或fail帧

FD_ZERO(&readset);

FD_SET(bpf, &readset);

ioctl(bpf,BIOCFLUSH);

if(1!=select(bpf+1,&readset,NULL,NULL,&timeout))

{

perror("select read EAP authentication result");

goto retry;

}

if(-1==read(bpf,buf,blen))

{

perror("read EAP authentication result errorr");

goto retry;

}

p=buf+((struct bpf_hdr *)buf)-bh_hdrlen;

if((((EAPOL *)(p+12))-type!=EAPOL_Packet)||(((EAP *)(p+12+sizeof(EAPOL)))-id!=id))

{

printf("EAP result packet error!\n");

goto retry;

}

if(((EAP *)(p+12+sizeof(EAPOL)))-code==EAP_Success)

{

printf("EAP authentication success!\n");

tmp=ntohs( *((int16*)(p+0x10)) );

uTemp.ulValue = *((int32 *)(p+(0x11+tmp)-0x08));

m_key.btValue[0] = Alog(uTemp.btValue[3]);

m_key.btValue[1] = Alog(uTemp.btValue[2]);

m_key.btValue[2] = Alog(uTemp.btValue[1]);

m_key.btValue[3] = Alog(uTemp.btValue[0]);

printf("Keeping sending echo every 20s... \n");

while(1)

{

sleep(20);

ULONG_BYTEARRAY uCrypt1,uCrypt2,uCrypt1_After,uCrypt2_After;

m_serialNo.ulValue++;

//m_serialNo is initialized at the beginning of main() of mystar.c, and

//m_key is initialized in mystar.c when the 1st Authentication-Success packet is received.

uCrypt1.ulValue = m_key.ulValue + m_serialNo.ulValue;

uCrypt2.ulValue = m_serialNo.ulValue;

memcpy( echoPackage, dstMAC, 6 );

uCrypt1_After.ulValue = htonl( uCrypt1.ulValue );

uCrypt2_After.ulValue = htonl( uCrypt2.ulValue );

echoPackage[0x18] = Alog(uCrypt1_After.btValue[0]);

echoPackage[0x19] = Alog(uCrypt1_After.btValue[1]);

echoPackage[0x1a] = Alog(uCrypt1_After.btValue[2]);

echoPackage[0x1b] = Alog(uCrypt1_After.btValue[3]);

echoPackage[0x22] = Alog(uCrypt2_After.btValue[0]);

echoPackage[0x23] = Alog(uCrypt2_After.btValue[1]);

echoPackage[0x24] = Alog(uCrypt2_After.btValue[2]);

echoPackage[0x25] = Alog(uCrypt2_After.btValue[3]);

while(write(bpf,echoPackage, 0x2d)!=0x2d) ;

ioctl(bpf,BIOCFLUSH);

}

}

else

{

printf("EAP authentication fail!\n");

goto retry;

}

//sleep(3600);

//goto retry; //睡眠1小时后重新认证

close(bpf);//不会到这

return 0;

}

void sig_intr(int signo)

{

if(buf!=NULL)

{

//构造802.1X的EAPOL-Logoff帧

memset(buf,0,blen);

if((dstMAC[0]==0)&&(dstMAC[1]==0)&&(dstMAC[2]==0))

memcpy(buf,standardMAC,6);

else

memcpy(buf,dstMAC,6);

((EAPOL *)(buf+12))-ethertype=htons(0x888E);

((EAPOL *)(buf+12))-version=1;

((EAPOL *)(buf+12))-type=EAPOL_Logoff;

((EAPOL *)(buf+12))-length=0;

if((12+sizeof(EAPOL))!=write(bpf,buf,12+sizeof(EAPOL))) //发送802.1X的EAPOL-Logoff帧

{

perror("write EAPOL_Logoff error");

}

}

_exit(0);

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有