Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C WinDivert问题-将DNS重定向回windows上的self_C_Windows_Networking_Dns_Packet - Fatal编程技术网

C WinDivert问题-将DNS重定向回windows上的self

C WinDivert问题-将DNS重定向回windows上的self,c,windows,networking,dns,packet,C,Windows,Networking,Dns,Packet,我在看basil00的torwall,为了好玩,我试着把它删减到只截取DNS。(为网络过滤、学习项目提供127.0.0.1的回复) 然而,在这一点上,我有它劫持的dns数据包,但它没有返回一个正确的地址。对于每个“被阻止”的域,它都是不同的 例如,我将cbc.ca放在hosts.deny文件(黑名单)中,它返回一个地址0.4.114.2 然后将slashdot列入黑名单,它将返回0.4.0.1 这是相当令人困惑和沮丧的,经过三天的研究,我的想法 下面是我的程序重定向部分的代码,这似乎是出错的地方

我在看basil00的torwall,为了好玩,我试着把它删减到只截取DNS。(为网络过滤、学习项目提供127.0.0.1的回复)

然而,在这一点上,我有它劫持的dns数据包,但它没有返回一个正确的地址。对于每个“被阻止”的域,它都是不同的

例如,我将cbc.ca放在hosts.deny文件(黑名单)中,它返回一个地址0.4.114.2

然后将slashdot列入黑名单,它将返回0.4.0.1

这是相当令人困惑和沮丧的,经过三天的研究,我的想法

下面是我的程序重定向部分的代码,这似乎是出错的地方。 (请注意,有些评论会很愚蠢,因为我正在为不同的目的编写一个程序,但还没有清理完)

#包括
#包括
#包括
#包括
#包括“windivert.h”
#包括“domain.h”
#包括“main.h”
#包括“重定向.h”
#定义最大数据包4096
#定义NUM_WORKERS 4
//DNS头
#定义DNS_MAX_名称254
结构dnshdr
{
uint16_t id;
uint16_t选项;
uint16_t qdcount;
uint16统计;
uint16_t nscount;
uint16_t arcount;
}_uuu属性_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
结构dnsq
{
uint16_t型;
uint16级;
}_uuu属性_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
结构dnsa
{
uint16_t名称;
uint16_t型;
uint16级;
uint32_t ttl;
uint16_t长度;
uint32地址;
}_uuu属性_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;
静态DWORD重定向_工作者(LPVOID arg);
静态int handle_dns(handle handle,PWINDIVERT_addr,
pIndivert_IPHDR IPHDR,pIndivert_UDPHDR UDPHDR,char*数据,
尺寸(数据长度);
//声明:
静态bool redirect_on=false;
静态句柄=无效的句柄值;
静态句柄工作者[NUM_工作者]={NULL};//工作线程
//异步发送数据包:
静态无效发送数据包(句柄、无效*数据包、大小数据包长度、,
PWINDIVERT_地址地址(addr)
{
addr->Direction=WINDIVERT\u Direction\u INBOUND;
WinDiverThelperCalc校验和(数据包,数据包长度,0);
if(!WinDivertSend(句柄、数据包、数据包长度、地址、空))
调试(“发送数据包失败(错误=%d)\n”,(int)GetLastError();
}
//通过Tor启动流量重定向:
外部无效重定向\u启动(无效)
{
调试(“DNS转移启动\n”);
if(句柄!=无效的句柄值)
返回;
handle=WinDivertOpen(
“出站和udp.DstPort==53或入站和udp.DstPort=53”,0,0,0);
//启动线程:
重定向_on=true;
对于(大小i=0;iDstPort)==53)
dnshandle=handle\u dns(handle,&addr,iphdr,udphdr,data,data\u len);
如果(dnshandle!=1)
{
if(!WinDivertSend(句柄、数据包、数据包长度和地址、NULL))
{
}
}
}
返回0;
}
//处理DNS请求。
//注:
//-如果出现任何问题,我们只需无误地丢弃数据包。
//-另一种方法是让Tor解决地址问题,
//这会很慢。
静态int handle_dns(handle handle,PWINDIVERT_addr,
pIndivert_IPHDR IPHDR,pIndivert_UDPHDR UDPHDR,char*数据,
尺寸(数据长度)
{
结构dnshdr*dnshdr=(结构dnshdr*)数据;
数据+=sizeof(结构dnshdr);
数据长度-=sizeof(结构dnshdr);
字符名[DNS_MAX_name+8];//额外增加8字节。
尺寸i=0;
而(i=DNS\u MAX\u NAME)
返回-1;
名称[i++]=';
对于(大小j=0;j512)//最大DNS数据包大小。
返回-1;
len+=sizeof(WINDIVERT_IPHDR)+sizeof(WINDIVERT_UDPHDR)+len;
char buf[len+8];//额外增加8字节。
PWINDIVERT_IPHDR riphdr=(PWINDIVERT_IPHDR)buf;
PWINDIVERT_UDPHDR rudphdr=(PWINDIVERT_UDPHDR)(riphdr+1);
结构dnshdr*rdnshdr=(结构dnshdr*)(rudphdr+1);
char*rdata
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>


#include "windivert.h"

#include "domain.h"
#include "main.h"
#include "redirect.h"

#define MAX_PACKET          4096
#define NUM_WORKERS         4

// DNS headers
#define DNS_MAX_NAME    254
struct dnshdr
{
    uint16_t id;
    uint16_t options;
    uint16_t qdcount;
    uint16_t ancount;
    uint16_t nscount;
    uint16_t arcount;
} __attribute__((__packed__));

struct dnsq
{
    uint16_t type;
    uint16_t class;
} __attribute__((__packed__));

struct dnsa
{
    uint16_t name;
    uint16_t type;
    uint16_t class;
    uint32_t ttl;
    uint16_t length;
    uint32_t addr;
} __attribute__((__packed__));


static DWORD redirect_worker(LPVOID arg);
static int handle_dns(HANDLE handle, PWINDIVERT_ADDRESS addr,
    PWINDIVERT_IPHDR iphdr, PWINDIVERT_UDPHDR udphdr, char *data,
    size_t data_len);


// State:
static bool redirect_on = false;
static HANDLE handle = INVALID_HANDLE_VALUE;
static HANDLE workers[NUM_WORKERS] = {NULL};    // Worker threads



// Send a packet asynchronously:
static void send_packet(HANDLE handle, void *packet, size_t packet_len,
    PWINDIVERT_ADDRESS addr)
{
    addr->Direction = WINDIVERT_DIRECTION_INBOUND;
    WinDivertHelperCalcChecksums(packet, packet_len, 0);
    if (!WinDivertSend(handle, packet, packet_len, addr, NULL))
        debug("Send packet failed (err=%d)\n", (int)GetLastError());
}


// Start traffic redirect through Tor:
extern void redirect_start(void)
{
    debug("DNS divert START\n");

    if (handle != INVALID_HANDLE_VALUE)
        return;

    handle = WinDivertOpen(
        "outbound and udp.DstPort == 53 or inbound and udp.DstPort = 53", 0, 0, 0);



    // Launch threads:
    redirect_on = true;
    for (size_t i = 0; i < NUM_WORKERS; i++)
    {
        workers[i] = CreateThread(NULL, MAX_PACKET*3,
            (LPTHREAD_START_ROUTINE)redirect_worker, (LPVOID)handle, 0, NULL);
        if (workers[i] == NULL)
        {
            exit(EXIT_FAILURE);
        }
    }
}

// Stop traffic redirect through Tor:
extern void redirect_stop(void)
{
    debug("DNS divert STOP\n");

    if (handle == INVALID_HANDLE_VALUE)
        return;

    // Close the WinDivert handle; will cause the workers to exit.
    redirect_on = false;
    if (!WinDivertClose(handle))
    {
        exit(EXIT_FAILURE);
    }
    handle = INVALID_HANDLE_VALUE;

    for (size_t i = 0; i < NUM_WORKERS; i++)
    {
        WaitForSingleObject(workers[i], INFINITE);
        workers[i] = NULL;
    }

}

// Redirect worker thread:
static DWORD redirect_worker(LPVOID arg)
{
    HANDLE handle = (HANDLE)arg;

    // Packet processing loop:
    char packet[MAX_PACKET];
    UINT packet_len;
    WINDIVERT_ADDRESS addr;

    while (redirect_on)
    {
        if (!WinDivertRecv(handle, packet, sizeof(packet), &addr, &packet_len))
        {
            // Silently ignore any error.
            continue;
        }

        PWINDIVERT_IPHDR iphdr = NULL;
        PWINDIVERT_TCPHDR tcphdr = NULL;
        PWINDIVERT_UDPHDR udphdr = NULL;
        PVOID data = NULL;
        UINT data_len;
        WinDivertHelperParsePacket(packet, packet_len, &iphdr, NULL, NULL,
            NULL, &tcphdr, &udphdr, &data, &data_len);

        int dnshandle = 0;
        if (udphdr != NULL && ntohs(udphdr->DstPort) == 53)
            dnshandle = handle_dns(handle, &addr, iphdr, udphdr, data, data_len);


        if(dnshandle != 1)
        {
            if (!WinDivertSend(handle, packet, packet_len, &addr, NULL))
            {


            }
        }
    }
    return 0;
}



// Handle DNS requests.
// NOTES:
// - If anything goes wrong, we simply drop the packet without error.
// - An alternative approach would be to let Tor resolve the address, however,
//   this would be slow.
static int handle_dns(HANDLE handle, PWINDIVERT_ADDRESS addr,
    PWINDIVERT_IPHDR iphdr, PWINDIVERT_UDPHDR udphdr, char *data,
    size_t data_len)
{

    struct dnshdr *dnshdr = (struct dnshdr *)data;
    data += sizeof(struct dnshdr);
    data_len -= sizeof(struct dnshdr);

    char name[DNS_MAX_NAME + 8];            // 8 bytes extra.
    size_t i = 0;
    while (i < data_len && data[i] != 0)
    {
        size_t len = data[i];
        if (i + len >= DNS_MAX_NAME)
            return -1;
        name[i++] = '.';
        for (size_t j = 0; j < len; j++, i++)
            name[i] = data[i];
    }

    name[i++] = '\0';

    // Generate a fake IP address and associate it with this domain name:
    uint32_t fake_addr = domain_lookup_addr(name);
    if (fake_addr == 0)
    {

        // This domain is blocked; so ignore the request.
        // Construct a query response:
    size_t len = sizeof(struct dnshdr) + data_len + sizeof(struct dnsa);
    if (len > 512)                          // Max DNS packet size.
        return -1;
    len += sizeof(WINDIVERT_IPHDR) + sizeof(WINDIVERT_UDPHDR) + len;

    char buf[len + 8];                      // 8 bytes extra.
    PWINDIVERT_IPHDR riphdr = (PWINDIVERT_IPHDR)buf;
    PWINDIVERT_UDPHDR rudphdr = (PWINDIVERT_UDPHDR)(riphdr + 1);
    struct dnshdr *rdnshdr = (struct dnshdr *)(rudphdr + 1);
    char *rdata = (char *)(rdnshdr + 1);


    UINT local_ip;
    DivertHelperParseIPv4Address("127.0.0.1",&local_ip);

    memset(riphdr, 0, sizeof(WINDIVERT_IPHDR));
    riphdr->Version   = 4;
    riphdr->HdrLength = sizeof(WINDIVERT_IPHDR) / sizeof(uint32_t);
    riphdr->Length    = htons(len);
    riphdr->Id        = htons(0xF00D);
    WINDIVERT_IPHDR_SET_DF(riphdr, 1);
    riphdr->TTL       = 64;
    riphdr->Protocol  = IPPROTO_UDP;
    riphdr->SrcAddr   = iphdr->DstAddr;
    riphdr->DstAddr   = iphdr->SrcAddr;

    memset(rudphdr, 0, sizeof(WINDIVERT_UDPHDR));
    rudphdr->SrcPort  = htons(53);          // DNS
    rudphdr->DstPort  = udphdr->SrcPort;
    rudphdr->Length   = htons(len - sizeof(WINDIVERT_IPHDR));

    rdnshdr->id = dnshdr->id;
    rdnshdr->options = htons(0x8180);       // Standard DNS response.
    rdnshdr->qdcount = htons(0x0001);
    rdnshdr->ancount = htons(0x0001);
    rdnshdr->nscount = 0;
    rdnshdr->arcount = 0;

    memcpy(rdata, data, data_len);
    struct dnsa *rdnsa = (struct dnsa *)(rdata + data_len);
    rdnsa->name   = htons(0xC00C);
    rdnsa->type   = htons(0x0001);          // (A)
    rdnsa->class  = htons(0x0001);          // (IN)
    rdnsa->ttl    = htonl(0x00000258) ;              // 1 second
    rdnsa->length = htons(0x0004);
    rdnsa->addr   = htonl(local_ip);       // Fake address

    send_packet(handle, &buf, len, addr);



    debug("address: %u\n",addr->Direction);
    debug("Intercept DNS %s\n", (name[0] == '.'? name+1: name));
    return 1;
    }
    // Re-inject the matching packet.


    /*
    /
    */
    return 0;
}
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#include "domain.h"
#include "main.h"

#define RATE_LIMIT                  8000

#define rand16()                    \
    (rand() & 0xFF) | ((rand() & 0xFF) << 8)

// Domain blacklist:
struct blacklist
{
    size_t size;
    size_t len;
    char **names;
};
static struct blacklist *blacklist = NULL;

// State:
static struct name *names[UINT16_MAX] = {NULL};

static HANDLE names_lock = NULL;

// Prototypes:
static struct blacklist *domain_blacklist_read(const char *filename);
static bool domain_blacklist_lookup(struct blacklist *blacklist,
    const char *name);
static int __cdecl domain_blacklist_compare_0(const void *x, const void *y);
static int domain_blacklist_compare(const char *name0, size_t len,
    const char *name1);



// Initialize this module:
extern void domain_init(void)
{
    // Load the domain blacklist.
    blacklist = domain_blacklist_read("hosts.deny");

}

// Lookup an address given a domain name.  If the name does not exist then
// create one.
extern uint32_t domain_lookup_addr(const char *name0)
{
    if (name0[0] == '.')
        name0++;

    if (domain_blacklist_lookup(blacklist, name0))
    {
        debug("Block %s\n", name0);

        return 0;       // Blocked!
    }
    return;
}



// Read the blacklist file:
static struct blacklist *domain_blacklist_read(const char *filename)
{
    struct blacklist *blacklist =
        (struct blacklist *)malloc(sizeof(struct blacklist));
    if (blacklist == NULL)
    {

        exit(EXIT_FAILURE);
    }
    blacklist->size = 0;
    blacklist->len = 0;
    blacklist->names = NULL;

    FILE *stream = fopen(filename, "r");
    if (stream == NULL)
    {
        return blacklist;
    }

    // Read blocked domains:
    int c;
    char buf[256];
    while (true)
    {
        while (isspace(c = getc(stream)))
            ;
        if (c == EOF)
            break;
        if (c == '#')
        {
            while ((c = getc(stream)) != '\n' && c != EOF)
                ;
            continue;
        }
        size_t i = 0;
        while (i < sizeof(buf)-1 && (c == '-' || c == '.' || isalnum(c)))
        {
            buf[i++] = c;
            c = getc(stream);
        }
        if (i >= sizeof(buf)-1 || !isspace(c))
        {

            exit(EXIT_FAILURE);
        }
        buf[i] = '\0';
        if (blacklist->len >= blacklist->size)
        {
            blacklist->size = (blacklist->size == 0? 32: 2 * blacklist->size);
            blacklist->names = (char **)realloc(blacklist->names,
                blacklist->size * sizeof(char *));
            if (blacklist->names == NULL)
            {

                exit(EXIT_FAILURE);
            }
        }
        size_t size = (i+1) * sizeof(char);
        char *name = (char *)malloc(size);
        if (name == NULL)
        {

            exit(EXIT_FAILURE);
        }
        for (size_t j = 0; j < i; j++)
            name[j] = buf[i - 1 - j];
        name[i] = '\0';
        blacklist->names[blacklist->len++] = name;
    }

    fclose(stream);

    qsort(blacklist->names, blacklist->len, sizeof(char *),
        domain_blacklist_compare_0);
    return blacklist;
}

// Check if a domain matches the blacklist or not:
static bool domain_blacklist_lookup(struct blacklist *blacklist,
    const char *name)
{
    if (blacklist->len == 0)
        return false;

    size_t len = strlen(name);
    ssize_t lo = 0, hi = blacklist->len-1;
    while (lo <= hi)
    {
        ssize_t mid = (lo + hi) / 2;
        int cmp = domain_blacklist_compare(name, len, blacklist->names[mid]);
        if (cmp > 0)
            hi = mid-1;
        else if (cmp < 0)
            lo = mid+1;
        else
            return true;
    }
    return false;
}

// Domain compare function(s):
static int __cdecl domain_blacklist_compare_0(const void *x, const void *y)
{
    const char *name0 = *(const char **)x;
    const char *name1 = *(const char **)y;
    return strcmp(name0, name1);
}
static int domain_blacklist_compare(const char *name0, size_t len,
    const char *name1)
{
    size_t i = 0;
    ssize_t j = (ssize_t)len - 1;
    for (; j >= 0 && name1[i] != '\0'; i++, j--)
    {
        int cmp = (int)name1[i] - (int)name0[j];
        if (cmp != 0)
            return cmp;
    }
    if (j < 0 && name1[i] != '\0')
        return 1;
    return 0;
}