我这里有他的原理,楼主水平高的话连账号都能一并破解。
这里的认证过程仅适用于h3c的客户端,而且是固定IP的,其他的我没研究过,不清楚。H3c的版本号从
2.40-0328向下兼容。
客户端的上网认证过程大概是这样的,
第一步,咱们的电脑向服务器发送一条“开始认证”请求
第二步,服务器收到“开始认证”请求后,会给我们发送“通知要求”;然后我们回应“通知响应”。
第三步,服务器再向我们发送“用户名要求”,我们再发送“用户名响应”。
第四步,服务器向我们发送“密码要求”,我们回应“密码响应”。
第五步,服务器将向我们发送是否成功认证的报文。
若认证成功,服务器便会每15秒发一条“在线询问”,我们则要回应2条报文以维持在线状态,它们类似“用户
名回应”。若服务器60秒没有收到你的“在线回应”,服务器就把你的号做下线处理。
下面,详细讲下各个报文的内容。
第一个,“开始认证报文”。如下:
typedef struct{
u_char DES_MAC[6];
u_char SRC_MAC[6];
u_char16 PACKET_TYPE;//0x8e88
u_char _802x_version;//0x01
u_char _802x_type; //0x01 EAP_START
u_char16 _802x_length;//0x00
u_char USELESS[42]; //All are 0x00
} PACKET_START,*LPPKTSTR;
这是抓包内容:
0000 01 80 c2 00 00 03 ff ff ff ff ff ff 88 8e 01 01 ........ ..H.....
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
这就是开始认证的报文。大小为60字节,第0 ~ 5字节是目的地MAC(总是01-80-c2-00-00-03,具体是什么意思
?:D);接下来6个是咱们电脑的MAC;再接下来的2个字节是0x8e88,这两个字节代表这个报文是8021x认证报文
,此处要注意,当你在赋值时注意高低位,例如,unsigned short sign;sign=0x8e88,要是赋成sign=0x888e
就错了;下一个字节是8021x的版本号,现在来看总是0x01;再下一个字节是_802x_type(姑且先这么叫着),这
个字节在“开始认证”中为0x01,在“下线请求”中为0x02,其他报文为0x00;在下两个字节为数据区大小,
数据区是我自己的叫法,就是18个字节后内容的长度,在此处为0x00。
第二个,服务器将向我们发送“通知要求”,内容如下:
0000 ff ff ff ff ff ff 00 e0 fc 0a ac 47 88 8e 01 00 ....H... ...G....
0010 00 05 01 01 00 05 02 00 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
这个报文大小同样60B,具体前6个是目的地地址(这个报文是服务器发来的,所以此处指向我们自己);接下
来6个是服务器的MAC;接下来2个是0x8e88;接下来两个是版本号和type号,分别是0x01和0x00;再接下来是数
据区长度,即0x(00 05);再接下来的两个字节比较重要,我们要通过这两个字节来判断服务器告诉我们说呢么
,第一个字节若是0x01代表是服务器跟我们要东西(Request),同样我们在制作回应报文时,此处要做成0x02
,代表我们发回应,若是0x03,则表是我们认证成功,0x04表示认证失败;下一个子节表示服务器到底跟我们
要什么东西,0x01代表"通知",0x02代表“用户名”,0x03代表“密码”;接下来的0x(00 05) 和前面的数据
区大小是一个内容;接下来的0x02好像没太大用处。
说到这,我要说的是,我们的认证报文大多数都是这样的结构,
typedef unsigned char u_char;
typedef unsigned short u_char16;
typedef struct{
u_char DES_MAC[6];
u_char SRC_MAC[6];
u_char16 PACKET_TYPE;
u_char _802x_version;
u_char _802x_type;
u_char16 _802x_length; //EAP length
u_char EAP_CODE;
u_char EAP_ID;
u_char16 EAP_LENGTH;
u_char EAP_TYPE;
} PACKETHEAD,*LPPKTHDR; //一共 23 字节!当你a=sizeof(PACKETHEAD)时,a==24,
看EAP_CODE 那,这个就是上面说的“比较重要”的字节,
|EAP_CODE==0x01,EAP_ID==0x01,EAP_TYPE==0x02 要“通知”
|EAP_CODE==0x02,EAP_ID==0x01,EAP_TYPE==0x02 回“通知”
|EAP_CODE==0x01,EAP_ID==0x02,EAP_TYPE==0x14 要“用户名”
|EAP_CODE==0x02,EAP_ID==0x02,EAP_TYPE==0x01 回“用户名”
|EAP_CODE==0x01,EAP_ID==0x03,EAP_TYPE==0x04 要“密码”
|EAP_CODE==0x02,EAP_ID==0x03,EAP_TYPE==0x04 回“密码”
|EAP_CODE==0x03 “认证成功”
|EAP_CODE==0x04 “认证失败”
EAP_TYPE这个值好像不是非常重要,至少我没用上这个值。
EAP_ID 更像是一个计数器,当开始认证时,它为0x01,然后每完成一次对话就 +1。但注意一下,加到0xff后
变成多少呢?我是假设它变成0x05了,这个地方要注意,在鉴别报文时可能会用上。
第三个,我们要发送“通知回应”。如下:
typedef struct{
u_char DES_MAC[6];
u_char SRC_MAC[6];
u_char16 PACKET_TYPE;
u_char _802x_version;
u_char _802x_type;
u_char16 _802x_length; //EAP length
u_char EAP_CODE;
u_char EAP_ID;
u_char16 EAP_LENGTH;
u_char EAP_TYPE;
u_char fixed1;//总是0x01
u_char fixed2;//总是0x16
unsigned char info[20];
} PACKET_NOTI_RESPONSE,*LPPKTNOTIRES;
抓包的内容:
0000 00 e0 fc 0a ac 47 ff ff ff ff ff ff 88 8e 01 00 .....G.. ..H.....
0010 00 1b 02 01 00 1b 02 01 16 4a 0e 7c 67 03 72 72 ........ .J.|g.rr
0020 39 38 4c 1b 26 30 12 08 30 f2 e8 77 01 00 00 00 98L.&0.. 0..w....
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
注意sizeof(PACKET_NOTI_RESPONSE)是小于60B的,然而这块我们要回应60B,所以其余的补0x00.
那个20字节info是关键,2.40-0328以前的版本这20字节总是固定的,但0328后的就变了,具体我没有跟踪分析
,大概与“计算机时间”,“版本号”,“用户名”“IP”等有关。我直接修改了官方的Dll文件,以得到我们
想要的数据。
具体调用方法如下:
hinsDll=LoadLibrary("x1pt.dll");
FARPROC pp=GetProcAddress(hinsDll,"X1_CoMsg");
pp+=0x2280;
这样pp就指向了一个x1pt.dll中的一个地址,这是个函数入口地址,这个函数要三个参数,这三个参数都是指
针!
第一个参数指向结构体:
typedef struct {
u_char sign[8]; //
u_char administratorname[50]; //*******
u_char username[128]; //username;!!!!!!!!!!!!!!!
u_char unknown1[174]; //unknown ,and don't use;
int LPPOINT; //!!!!!!!!!!!!!!!!!!!!!!!!!
u_char unknown2[12]; //unknown ,
u_char TIMESTART[50]; //Time for start;
u_char TIMEEND[62]; //Time for end;
u_char password[64]; //Password;!!!!!!!!!!!!!!
char padding[16384];
}_STRUCT_PARA1,*LP_STRUCT_PARA1;
加了“!”的是比较重要的,username 就是上网时要输入的用户名,密码就是那个密码,LPPOINT是个指针,它
又指向一个结构体:
typedef struct{
u_char sign[16]; //all is Zero
u_char sign2[16]; //all is Zero
u_char sign3[8]; //{05 00 00 00 05 00 00 00}!!!
u_char sign4[4]; //{00 00 00 00}
u_char ip_pi[4]; //!!!
u_char sign5[8]; //{ff ff ff ff 00 00 00 00}!!!
u_char fakeip[8]; //!!!
int sign6; //0x04 for Noti and username
int sign7; //0x01 for Noti and 0x02 for Username!!!
char pading[16384];
}_PART_OF_PARA1,*LP_PART_OF_PARA1;
在这个结构体中,把sign3赋成“{05 00 00 00 05 00 00 00}”;
ip_pi要倒着写入你的Ip,例如你的Ip是125.221.180.256,那你这块要
ip_pi[0]=(char)256;
ip_pi[1]=(char)180;
ip_pi[2]=(char)221;
ip_pi[3]=(char)125;
;把sign5赋成“{ff ff ff ff 00 00 00 00}”;
fakeip那要这样写:
fakeip[0]=(char)125;
fakeip[1]=(char)180;
fakeip[2]=(char)221;
fakeip[3]=(char)125;
sign6赋成0x04;
当你为得到“通知回应”的数据时,sign7=0x01;若是要得到“用户名”(下面会说)的数据,则sign7=0x02,
并且将_STRUCT_PARA1+0xd8位置上的数据改成0x20;
在使用这两个结构体变量之前,用ZeroMemory()清零变量内存;padding要足够大!16384就可以了.
第二个参数指向一个 char [5],你可以这样用。
为获得“通知回应数据”则:
char aa[5];
aa[0]=01;
aa[1]=01;
aa[2]=00;
aa[3]=05;
aa[4]=02;
注意_PART_OF_PARA1的sign7!
为获得“用户名响应”,则:
aa[0]=01;
aa[1]=02;
aa[2]=00;
aa[3]=05;
aa[4]=0x14;
注意_PART_OF_PARA1的sign7!
第三个参数就是我们要的结果了,char rlt[100],把rlt传进去就可以了。
调用完那个x1pt.dll中的函数后,从rtl+7位置上取20字节,就把"通知回应"的数据取到了。
第四个,服务器将向我们发送“用户名请求”,内容如下:
0000 ff ff ff ff ff ff 00 e0 fc 0a ac 47 88 8e 01 00 ....H... ...G....
0010 00 05 01 02 00 05 14 00 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
不需要做说明了吧 哈哈哈
第五个,我们回应“用户名”。先看内容:
0000 00 e0 fc 0a ac 47 ff ff ff ff ff ff 88 8e 01 00 .....G.. ..H.....
0010 00 32 02 02 00 32 01 15 04 ff ff ff ff 06 07 48 .2...2.. .}..,..H
0020 51 35 37 59 67 5a 31 63 6d 35 76 54 42 77 6a 4e Q57YgZ1c m5vTBwjN
0030 52 55 49 5a 33 4c 61 41 51 45 3d 20 20 ff ff ff RUIZ3LaA QE= !!!
0040 ff ff ff ff !!!!
结构定义:
typedef struct{
u_char DES_MAC[6];
u_char SRC_MAC[6];
u_char16 PACKET_TYPE;
u_char _802x_version;
u_char _802x_type;
u_char16 _802x_length; //EAP length
u_char EAP_CODE;
u_char EAP_ID;
u_char16 EAP_LENGTH;
u_char EAP_TYPE;
u_char fixed1;//总是0x15
u_char fixed2;//总是0x04
u_char IP[4];//你的IP,例如IP[0]=125,IP[1]=221,IP[2]=180,IP[3]=256;!!!!!!!!
u_char fixed3;//总是0x06
u_char fixed7;//总是0x07
u_char info[28];
u_char blank1;//总是0x20 ,就是空格
u_char blank2;//总是0x20 ,就是空格
} PACKET_USERNAME_RESPONSE,*LPPKTUSERNAMERES;
把自己的IP填到IP[4]里;info的获得和Noti 的 一样,只是最后取结果时从+13 的位置上取,取28个出来。将
你的用户名补在后面,如果你要用sizeof()注意加减1.最后,算出大小填入EAP_LENGTH中,从第18个字节开始
,有多少个字节,大小就是多少。
第六个,服务器收到你的用户名后,就会跟你要密码,
内容如下:
0000 ff ff ff ff ff ff 00 e0 fc 0a ac 47 88 8e 01 00 ....H... ...G....
0010 00 16 01 03 00 16 04 10 43 1b 76 53 b7 82 7e 98 ........ C.vS..~.
0020 29 08 69 2f 75 86 06 34 00 00 00 00 00 00 00 00 ).i/u..4 ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
这个报文重要,你要获得一个字串。从0x19位置上开,读入0x10个字节,即“43 1b 76 53 b7 82 7e 98 29 08
69 2f 75 86 06 34”。
第七个,你将发回密码。先看内容:
0000 00 e0 fc 0a ac 47 ff ff ff ff ff ff 88 8e 01 00 .....G.. ..H.....
0010 00 1d 02 03 00 1d 04 10 d7 b1 5f e4 c2 e8 55 f4 ........ .._...U.
0020 14 26 ec 38 88 5f 4b 3a ff ff ff ff ff ff ff 00 .&.8._K: !!!!!!!.
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
数据定义:
typedef struct {
u_char DES_MAC[6];
u_char SRC_MAC[6];
u_char16 PACKET_TYPE;
u_char _802x_version;
u_char _802x_type;
u_char16 _802x_length; //EAP length
u_char EAP_CODE;
u_char EAP_ID;
u_char16 EAP_LENGTH;
u_char EAP_TYPE;
u_char lengthofPWD;//alway 0x10,16字节
u_char MD5VALU[16];
u_char OTHERINFO[20];//INCLUDE USERNAME
}PACKET_PASSWORD_RESPONSE,*LPPKTPWDRES;
这个报文比较简单,制作一个串,内容是0x03+密码串+交换码串(就是上个报文中,考出的16字节),然后将这
个符合串MD5 ComputeHash,得到MD5值,写入报文,补上用户名,填足60位,就可以了.
第8个,成功则服务器发回:
0000 ff ff ff ff ff ff 00 e0 fc 0a ac 47 88 8e 01 00 ....H... ...G....
0010 00 04 03 04 00 04 00 00 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
失败则:
0000 ff ff ff ff ff ff 00 e0 fc 0a ac 47 88 8e 01 00 ....H... ...G....
0010 00 07 04 08 00 07 08 01 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
对于在线保持,服务器发送:
0000 ff ff ff ff ff ff 00 e0 fc 0a ac 47 88 8e 01 00 ....H... ...G....
0010 00 05 01 db 00 05 14 00 00 00 00 00 00 00 00 00 ........ ........
0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0030 00 00 00 00 00 00 00 00 00 00 00 00 ........ ....
我们要做的是,回应两个报文,
回应1
0000 01 80 c2 00 00 03 ff ff ff ff ff ff 88 8e 01 00 ........ .F^.....
0010 00 35 02 cc 00 35 14 00 15 04 ff ff ff ff 06 07 .5...5.. ..}.....
0020 54 77 31 2f 62 77 74 78 63 54 77 39 54 78 67 75 Tw1/bwtx cTw9Txgu
0030 4f 42 45 4c 4e 58 6a 41 63 72 67 3d 20 20 ff ff OBELNXjA crg= !!
0040 ff ff ff ff ff ff ff !!!!!!!
回应2
0000 01 80 c2 00 00 03 ff ff ff ff ff ff 88 8e 01 00 ........ .F^.....
温馨提示:内容为网友见解,仅供参考