[补] winpcap编程——EAPSOCKET实现校园网锐捷登录(mentohust)

EAP SOCKET Implement Mentohust

时间20161115

对于EAP协议不了解,可参考上一篇随笔。

通过抓包分析校园网的锐捷登录流程,我在上一篇随笔中实现了EAPSOCKET这个类,

准备

原因

  • 周末尝试了一下windows(自带?)的虚拟机Hyper-V(它的虚拟机好像必须通过虚拟机的网卡才能上网),多次尝试后蛋疼的锐捷疯狂断网,于是我很气啊!!!!!!

  • 但是那天觉得破解锐捷不如自实现锐捷认证,于是有了以下内容。

实现

  • wires hark

  • 能看出锐捷的验证方式是802.1x的EAP协议,其实校园网所采用的认证方式大部分都是802.1x认证的eap协议。

  • 根据mentohust源码了解锐捷登录具体细节

代码

只是个例子
原先的代码因为一些原因丢失了,最近用go重写了一个过几天发

思考

Mentohust Security

写代码时看了mentohust的源码,因而引发了一些对于安全的思考,在mentohust中由于pcap_handle函数没有对EAP包做过多判断,因而攻击者可在内网中伪造数据包精确地让目标断网。

mentohust : https://github.com/hyrathb/mentohust/tree/master/src
mentohust.c

static void pcap_handle(u_char *user, const struct pcap_pkthdr *h, const u_char *buf)
{
	static unsigned failCount = 0;
#ifndef NO_ARP
	if (buf[0x0c]==0x88 && buf[0x0d]==0x8e) {
#endif
		if (memcmp(destMAC, buf+6, 6)!=0 && startMode>2)	/* 服务器MAC地址不符 */
			return;
		capBuf = buf;
		if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x01) {	/* 验证用户名 */
			if (startMode < 3) {
				memcpy(destMAC, buf+6, 6);
				printf(_("** 认证MAC:	%s
"), formatHex(destMAC, 6));
				startMode += 3;	/* 标记为已获取 */
			}
			switchState(ID_IDENTITY);
		}
		else if (buf[0x0F]==0x00 && buf[0x12]==0x01 && buf[0x16]==0x04)	/* 验证密码 */
			switchState(ID_CHALLENGE);
		else if (buf[0x0F]==0x00 && buf[0x12]==0x03) {	/* 认证成功 */
			printf(_(">> 认证成功!
"));
			failCount = 0;
			if (!(startMode%3 == 2)) {
				getEchoKey(buf);
				showRuijieMsg(buf, h->caplen);
			}
			if (dhcpMode==1 || dhcpMode==2)	/* 二次认证第一次或者认证后 */
				switchState(ID_DHCP);
			else if (startMode%3 == 2)
				switchState(ID_WAITECHO);
			else
				switchState(ID_ECHO);
		}
		else if (buf[0x0F]==0x00 && buf[0x12]==0x04) {  /* 认证失败或被踢下线 */
			if (state==ID_WAITECHO || state==ID_ECHO) {
				printf(_(">> 认证掉线,开始重连!
"));
				switchState(ID_START);
			}
			else if (buf[0x1b]!=0 || startMode%3==2) {
				printf(_(">> 认证失败!
"));
				if (startMode%3 != 2)
					showRuijieMsg(buf, h->caplen);
				if (maxFail && ++failCount>=maxFail) {
					printf(_(">> 连续认证失败%u次,退出认证。
"), maxFail);
					exit(EXIT_SUCCESS);
				}
				restart();
			}
			else
				switchState(ID_START);
		}
}

mystate.c

static int sendChallengePacket()
{
	int nameLen = strlen(userName);
	if (startMode%3 == 2)	/* 赛尔 */
	{
		if (sendCount == 0)
		{
			printf(_(">> 发送密码...
"));
			*(u_int16_t *)(sendPacket+0x0E) = htons(0x0100);
			*(u_int16_t *)(sendPacket+0x10) = *(u_int16_t *)(sendPacket+0x14) = htons(nameLen+22);
			sendPacket[0x12] = 0x02;
			sendPacket[0x13] = capBuf[0x13];
			sendPacket[0x16] = 0x04;
			sendPacket[0x17] = 16;
			memcpy(sendPacket+0x18, checkPass(capBuf[0x13], capBuf+0x18, capBuf[0x17]), 16);
			memcpy(sendPacket+0x28, userName, nameLen);
			setTimer(timeout);
		}
		return pcap_sendpacket(hPcap, sendPacket, nameLen+40);
	}
	if (sendCount == 0)
	{
		printf(_(">> 发送密码...
"));
		//fillMd5Packet(capBuf+0x18);
		fillEtherAddr(0x888E0100);
		*(u_int16_t *)(sendPacket+0x14) = *(u_int16_t *)(sendPacket+0x10) = htons(nameLen+22);
		sendPacket[0x12] = 0x02;
		sendPacket[0x13] = capBuf[0x13];
		sendPacket[0x16] = 0x04;
		sendPacket[0x17] = 16;
		memcpy(sendPacket+0x18, checkPass(capBuf[0x13], capBuf+0x18, capBuf[0x17]), 16);
		memcpy(sendPacket+0x28, userName, nameLen);

		memcpy(sendPacket+0x28+nameLen, pkt_md5, sizeof(pkt3));
		memcpy(sendPacket + 0x90 + nameLen, computePwd(capBuf+0x18), 0x10);
		//memcpy(sendPacket + 0xa0 +nameLen, fillBuf + 0x68, fillSize-0x68);
		memcpy(sendPacket + 0x108 + nameLen, computeV4(capBuf+0x18, capBuf[0x17]), 0x80);
		//sendPacket[0x77] = 0xc7;
		setTimer(timeout);
	}
	return pcap_sendpacket(hPcap, sendPacket, 569);
}

END

原文地址:https://www.cnblogs.com/tr3e/p/6850249.html