DNS解析

//****************************************************************************************/
//获取DNS
 
#include "DNS.h"



//全局变量
PDNSADDRANDURL global_pwsadata;

NTSTATUS
DriverEntry(
    PDRIVER_OBJECT pDriverObj,
    PUNICODE_STRING pRegistryString
)
{
    NTSTATUS status = STATUS_SUCCESS;
    UNICODE_STRING ustrLinkName;
    UNICODE_STRING ustrDevName;
    PDEVICE_OBJECT pDevObj;

    int s_dns = 0;

    unsigned char hostname[100] = { "www.debugman.com" };

    //if (DBG)
    {
        //    __asm int 3 
    }



    dprintf("[hello] DriverEntry
");

    pDriverObj->MajorFunction[IRP_MJ_CREATE] = DispatchCreate;
    pDriverObj->MajorFunction[IRP_MJ_CLOSE] = DispatchClose;
    pDriverObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchIoctl;
    pDriverObj->DriverUnload = DriverUnload;


    RtlInitUnicodeString(&ustrDevName, DEVICE_NAME);
    status = IoCreateDevice(pDriverObj,
        0,
        &ustrDevName,
        FILE_DEVICE_UNKNOWN,
        0,
        FALSE,
        &pDevObj);

    if (!NT_SUCCESS(status)) {
        dprintf("[hello] IoCreateDevice = 0x%x
", status);
        return status;
    }

    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
     
    if (!NT_SUCCESS(status)) {
        dprintf("[hello] IoCreateSymbolicLink = 0x%x
", status);
        IoDeleteDevice(pDevObj);
        return status;
    }

    global_pwsadata = (PDNSADDRANDURL)ExAllocatePool(0, sizeof(DNSADDRANDURL));

    s_dns = ReadDnsServerFromRegistry();  //返回网络字节顺序
    global_pwsadata->serveur_dns = s_dns;
    gethostbyname(hostname);
    dprintf(" remote ip address is %x
", global_pwsadata->urladdr);

    return STATUS_SUCCESS;
}


VOID
DriverUnload(
    PDRIVER_OBJECT pDriverObj
)
{
    UNICODE_STRING strLink;
    RtlInitUnicodeString(&strLink, LINK_NAME);

    //
    // 添加卸载代码
    //



    IoDeleteSymbolicLink(&strLink);
    IoDeleteDevice(pDriverObj->DeviceObject);
    dprintf("[hello] Unloaded
");
}


NTSTATUS
DispatchCreate(
    PDEVICE_OBJECT pDevObj,
    PIRP pIrp
)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    dprintf("[hello] IRP_MJ_CREATE
");

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}


NTSTATUS
DispatchClose(
    PDEVICE_OBJECT pDevObj,
    PIRP pIrp
)
{
    pIrp->IoStatus.Status = STATUS_SUCCESS;
    pIrp->IoStatus.Information = 0;

    dprintf("[hello] IRP_MJ_CLOSE
");

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);
    return STATUS_SUCCESS;
}


NTSTATUS
DispatchIoctl(
    PDEVICE_OBJECT pDevObj,
    PIRP pIrp
)
{
    NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
    PIO_STACK_LOCATION pIrpStack;
    ULONG uIoControlCode;
    PVOID pIoBuffer;
    ULONG uInSize;
    ULONG uOutSize;

    pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
    uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;
    pIoBuffer = pIrp->AssociatedIrp.SystemBuffer;
    uInSize = pIrpStack->Parameters.DeviceIoControl.InputBufferLength;
    uOutSize = pIrpStack->Parameters.DeviceIoControl.OutputBufferLength;

    switch (uIoControlCode) {

    case IOCTL_HELLO: {

        dprintf("[hello] Hello
");
        status = STATUS_SUCCESS;
    }
                      break;
    }

    if (status == STATUS_SUCCESS)
        pIrp->IoStatus.Information = uOutSize;
    else
        pIrp->IoStatus.Information = 0;

    /////////////////////////////////////
    pIrp->IoStatus.Status = status;
    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return status;
}

/*
返回网络字节顺序
*/
int ReadDnsServerFromRegistry()
{
    //Variables locales
    NTSTATUS       status = STATUS_UNSUCCESSFUL;

    WCHAR       ChaineRegistre[] = L"\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces";
    UNICODE_STRING     usRegistryKey = { 0 };
    OBJECT_ATTRIBUTES     obNomClefRegistre = { 0 };
    HANDLE        RegHandle = 0;

    UNICODE_STRING     usRegistryKeySub = { 0 };
    OBJECT_ATTRIBUTES     obNomClefRegistreSub = { 0 };
    HANDLE        RegHandleSub = 0;

    WCHAR       ChaineEnableDHCP[] = L"EnableDHCP";
    WCHAR       ChaineNameServer[] = L"NameServer";
    WCHAR       ChaineDhcpNameServer[] = L"DhcpNameServer";    //有问题这个,注册表里好像没有   Win10下DhcpServer
                                                            //DhcpServer
    char        informations_lues[256];
    ULONG       size_lue = 0;

    KEY_VALUE_FULL_INFORMATION *KeyValue = NULL;
    char        adresses_ips_dns[40];

    int         compteur_subkey = 0;
    unsigned int       adresse = 0;

    ANSI_STRING AnsiString;
    UNICODE_STRING CurrentName;


    RtlInitUnicodeString(&usRegistryKey, ChaineRegistre);

    InitializeObjectAttributes(&obNomClefRegistre,
        &usRegistryKey,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        NULL,
        NULL);

    status = ZwOpenKey(&RegHandle, KEY_READ, &obNomClefRegistre);    
    //打开 L"\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces"

    if (status != STATUS_SUCCESS)
    {
        return -1;
    }

    compteur_subkey = 0;
    status = STATUS_SUCCESS;
    while (TRUE)
    {
        memset(informations_lues, 0, 256);
        status = ZwEnumerateKey(RegHandle,
            compteur_subkey,
            KeyBasicInformation,
            &informations_lues,
            256,
            &size_lue);


        if (status != STATUS_SUCCESS)
            break;


        RtlInitUnicodeString(&usRegistryKeySub,
            ((*(KEY_BASIC_INFORMATION*)&informations_lues).Name));

        InitializeObjectAttributes(&obNomClefRegistreSub,
            &usRegistryKeySub,
            OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
            NULL, NULL);


        obNomClefRegistreSub.RootDirectory = RegHandle;


        status = ZwOpenKey(&RegHandleSub,
            KEY_READ,
            &obNomClefRegistreSub);


        if (status != STATUS_SUCCESS)
        {
            compteur_subkey++;

            continue;
        }


        memset(informations_lues, 0, 256);

        RtlInitUnicodeString(&usRegistryKey,
            ChaineEnableDHCP);

        status = ZwQueryValueKey(RegHandleSub,
            &usRegistryKey,
            KeyValueFullInformation,
            &informations_lues,
            256,
            &size_lue);


        if (status != STATUS_SUCCESS)
        {
            compteur_subkey++;
            ZwClose(RegHandleSub);
            continue;
        }


        KeyValue = (KEY_VALUE_FULL_INFORMATION *)informations_lues;
        if (*(int*)(informations_lues + KeyValue->DataOffset))
        {

            RtlInitUnicodeString(&usRegistryKey,
                ChaineDhcpNameServer);
        }
        else
        {

            RtlInitUnicodeString(&usRegistryKey,
                ChaineNameServer);
        }


        memset(informations_lues, 0, 256);
        status = ZwQueryValueKey(RegHandleSub,
            &usRegistryKey,
            KeyValueFullInformation,
            &informations_lues,
            256,
            &size_lue);


        if (status != STATUS_SUCCESS)
        {
            compteur_subkey++;

            ZwClose(RegHandleSub);
            continue;
        }


        RtlZeroMemory(adresses_ips_dns, 40);

        RtlInitUnicodeString(&CurrentName, informations_lues + KeyValue->DataOffset);
        RtlUnicodeStringToAnsiString(&AnsiString, &CurrentName, TRUE);
        RtlCopyMemory(adresses_ips_dns, AnsiString.Buffer, 40);

        dprintf("DNS SERVICE IP %s
", adresses_ips_dns);

        ZwClose(RegHandleSub);

        adresse = inet_addr(adresses_ips_dns);
        if (adresse == 0)
        {
            compteur_subkey++;
            continue;
        }

        ZwClose(RegHandle);
        return adresse;

        compteur_subkey++;
    }
    ZwClose(RegHandle);
    return -1;
}



//获取了DNS的ip后问题就容易处理,剩下构造dns请求包和udp的相关东西~~
//因为dns请求的协议要求获得本机地址,要去取本机地址,代码如下

/*
返回网络字节顺序
*/
int ReadHostIPsFromRegistry()
{
    NTSTATUS        status = STATUS_UNSUCCESSFUL;
    int*            pHostentArray = NULL;
    char*            pHostentData = NULL;

    WCHAR            ChaineRegistre[] = L"\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces";

    UNICODE_STRING  usRegistryKey = { 0 };
    OBJECT_ATTRIBUTES        obNomClefRegistre = { 0 };
    HANDLE            RegHandle = 0;

    UNICODE_STRING     usRegistryKeySub = { 0 };
    OBJECT_ATTRIBUTES  obNomClefRegistreSub = { 0 };
    HANDLE               RegHandleSub = 0;

    WCHAR       ChaineEnableDHCP[] = L"EnableDHCP";
    WCHAR       ChaineIPAddress[] = L"IPAddress";
    WCHAR       ChaineDhcpIPAddress[] = L"DhcpIPAddress";

    char        informations_lues[256];
    ULONG       size_lue = 0;

    KEY_VALUE_FULL_INFORMATION *KeyValue = NULL;
    char        adresse_ip[20];

    int          compteur_subkey = 0;
    unsigned int adresse = 0;

    ANSI_STRING AnsiString;
    UNICODE_STRING CurrentName;

    RtlInitUnicodeString(&usRegistryKey,
        ChaineRegistre);

    InitializeObjectAttributes(&obNomClefRegistre,
        &usRegistryKey,
        OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
        NULL, NULL);

    status = ZwOpenKey(&RegHandle,//打开主键
        KEY_READ,
        &obNomClefRegistre);
    if (status != STATUS_SUCCESS)
    {
        return -1;
    }

    compteur_subkey = 0;//子键的个数
    status = STATUS_SUCCESS;
    while (TRUE)
    {
        memset(informations_lues, 0, 256);
        status = ZwEnumerateKey(RegHandle,
            compteur_subkey,
            KeyBasicInformation,
            &informations_lues,
            256,
            &size_lue);

        if (status != STATUS_SUCCESS)
            break;

        RtlInitUnicodeString(&usRegistryKeySub,
            ((*(KEY_BASIC_INFORMATION*)&informations_lues).Name));
        DbgPrint("subkey is  %ws", usRegistryKeySub.Buffer);

        InitializeObjectAttributes(&obNomClefRegistreSub,
            &usRegistryKeySub,
            OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
            NULL,
            NULL);

        obNomClefRegistreSub.RootDirectory = RegHandle;

        status = ZwOpenKey(&RegHandleSub,
            KEY_READ,
            &obNomClefRegistreSub);
        if (status != STATUS_SUCCESS)
        {
            compteur_subkey++;
            dprintf("[niveau socket] !! ReadHostIPsFromRegistry : Echec d'ouverture du registre sur sous-clef
");
            continue;
        }

        memset(informations_lues, 0, 256);
        RtlInitUnicodeString(&usRegistryKey, ChaineEnableDHCP);

        status = ZwQueryValueKey(RegHandleSub,
            &usRegistryKey,
            KeyValueFullInformation,
            &informations_lues,
            256,
            &size_lue);

        if (status != STATUS_SUCCESS)
        {
            compteur_subkey++;
            dprintf("[niveau socket] !! ReadHostIPsFromRegistry : Echec lecture valeur EnableDHCP
");
            ZwClose(RegHandleSub);
            continue;
        }

        KeyValue = (KEY_VALUE_FULL_INFORMATION *)informations_lues;
        if (*(int*)(informations_lues + KeyValue->DataOffset))
        {
            RtlInitUnicodeString(&usRegistryKey, ChaineDhcpIPAddress);
        }
        else
        {
            RtlInitUnicodeString(&usRegistryKey, ChaineIPAddress);
        }

        memset(informations_lues, 0, 256);
        status = ZwQueryValueKey(RegHandleSub,
            &usRegistryKey,
            KeyValueFullInformation,
            &informations_lues,
            256,
            &size_lue);
        if (status != STATUS_SUCCESS)
        {
            compteur_subkey++;
            ZwClose(RegHandleSub);
            continue;
        }

        RtlZeroMemory(adresse_ip, 20);
        RtlInitUnicodeString(&CurrentName, informations_lues + KeyValue->DataOffset);
        RtlUnicodeStringToAnsiString(&AnsiString, &CurrentName, TRUE);
        RtlCopyMemory(adresse_ip, AnsiString.Buffer, 20);

        dprintf("HOST IP %s", adresse_ip);

        ZwClose(RegHandleSub);

        adresse = inet_addr(adresse_ip);
        if (adresse == 0)
        {
            compteur_subkey++;
            continue;
        }
        else
        {
            return adresse;
        }
    }
    ZwClose(RegHandle);

    return adresse;
}

//下面开始贴具体DNS请求过程的代码了
//已经获取得到网络字节顺序
PHOSTENT gethostbyname(IN char *name)
{
    struct sockaddr_in  sockaddr_dns = { 0 };
    unsigned char* phostent_buf = NULL;

    if (global_pwsadata->serveur_dns == 0)
    {
        return NULL;
    }

    phostent_buf = ExAllocatePoolWithTag(0, 2048, 'doki');
    if (phostent_buf == NULL)
    {
        return NULL;
    }
    RtlZeroMemory(phostent_buf, 2048);

    sockaddr_dns.sin_family = AF_INET;
    sockaddr_dns.sin_addr.s_addr = global_pwsadata->serveur_dns;//DNS的主机地址
    sockaddr_dns.sin_port = HTONS(53);//dns 服务器固定端口

    if (query_dns(sockaddr_dns, name, phostent_buf, FALSE) != -1)
    {
        return (PHOSTENT)phostent_buf;
    }
    else
    {
        ExFreePool(phostent_buf);
        return NULL;
    }
}

int query_dns(IN  struct sockaddr_in sockaddr_dns,    
    IN  char* URL,    //www.DebugMan.com
    OUT char *hostent_buf,//返回的值
    IN  int rdns)//rdns 是否反向查询
{
    struct sockaddr_in    sockaddr_bind = { 0 }; //干什么用的?
    int            com_socket = 0;
    NTSTATUS    status = STATUS_UNSUCCESSFUL;

    int size_string_requete_format_dns = 0;
    int size_string_requete = 0;

    unsigned char * buf = NULL;//需要构造的缓冲区
    unsigned char * reader;  //读取的位置指针
    DNS_HEADER      *    dns = NULL;
    int                size_buffer_dns = 0;// sendto must be know length of databuf

    char *                res_record_crawler = NULL;
    CUSTOM_RES_RECORD * res_record = NULL;
    unsigned int *        adresse_ip = NULL;
    int                    compteur_reponses = 0;

    PHOSTENT    hostent = NULL;
    char*        hostent_content = NULL;
    char**        hostent_array = NULL;//指向指针的指针

    unsigned char * qname = NULL;
    QUESTION *   qinfo = NULL;

    int lock = 0, i, j, k;
    int stop, lenthqname;

    struct sockaddr_in a;//便于记录读取的IP 
    struct RES_RECORD answers[20], auth[20], addit[20];  //the replies from the DNS server

    PUCHAR returnaddr;//指针

    int lenth = sizeof(DNS_HEADER);

    buf = ExAllocatePoolWithTag(0, 2048, 'doki');
    if (buf == NULL)
    {
        return NULL;
    }
    RtlZeroMemory(buf, 2048);

    /*
    +---------------------+
    | Header              |
    +---------------------+
    | Question            | the question for the name server
    +---------------------+
    | Answer              | RRs answering the question
    +---------------------+
    | Authority           | RRs pointing toward an authority
    +---------------------+
    | Additional          | RRs holding additional information
    +---------------------+


    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    | ID                                            |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |QR| Opcode    |AA|TC|RD|RA| Z      |  RCODE    |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   QDCOUNT                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   ANCOUNT                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   NSCOUNT                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
    |                   ARCOUNT                     |
    +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

    */
    //1 Construction du message DNS 
    //buffer : DNS_HEADER | nom modifi?| QUESTION
    dns = (DNS_HEADER*)buf;

    dns->id = 1234;

    //Flags DNS
    dns->qr = 0; //This is a query
    dns->opcode = 0; //This is a standard query
    dns->aa = 0; //Not Authoritative
    dns->tc = 0; //This message is not truncated
    dns->rd = 1; //Recursion Desired
    dns->ra = 0; //Recursion not available! hey we dont have it (lol)
    dns->z = 0;
    dns->ad = 0;
    dns->cd = 0;
    dns->rcode = 0;

    dns->q_count = HTONS(1); //we have only 1 question
    dns->ans_count = 0;
    dns->auth_count = 0;
    dns->add_count = 0;

    //point to the query portion
    qname = (unsigned char*)&buf[sizeof(DNS_HEADER)];
    //www.google.com ==>> 3www6google3com  
    ChangetoDnsNameFormat(qname, URL);

    qinfo = (struct QUESTION*)&buf[sizeof(DNS_HEADER) + (strlen((const char*)qname) + 1)]; //fill it

    qinfo->qtype = HTONS(1);  //we are requesting the ipv4 address
    qinfo->qclass = HTONS(1); //its internet always is 1 

    size_buffer_dns = sizeof(DNS_HEADER) + strlen(qname) + 1 + sizeof(QUESTION);//33

    //com_socket = socket(AF_INET, SOCK_DGRAM ,IPPROTO_UDP);
    //udp 数据报查询
    com_socket = socket(2, 2, 17);
    if (com_socket == -1)
    {
        ExFreePool(buf);
        return -1;
    }

    status = sendto(com_socket, buf, size_buffer_dns, 0, &sockaddr_dns, sizeof(sockaddr_dns));
    if (status == -1)
    {

        ExFreePool(buf);
        status = close(com_socket);
        if (status == -1)
        {
            ;
        }
        return -1;
    }

    k = sizeof(sockaddr_dns);

    status = recvfrom(com_socket, buf, 1024 * 2, 0, &sockaddr_dns, &k);
    if (status == -1)
    {
        ExFreePool(buf);
        status = close(com_socket);
        if (status == -1)
        {
            ;
        }
        return -1;
    }
    dprintf("received ok 
 ");

    status = close(com_socket);
    if (status == -1)
    {
        return -1;
    }


    dns = (struct DNS_HEADER*)buf;

    if (dns->ans_count == 0)
    {
        ExFreePool(buf);
        return -1;
    }
    else
    {
        //http://www.codeproject.com/KB/IP/dns_query.aspx  如果你还不知道返回数据格式,可以参考这篇文章
        //move ahead of the dns header and the query field
        //从返回的数据开始读取,也就是去除自己的构造部分
        reader = &buf[sizeof(DNS_HEADER) + (strlen((const char*)qname) + 1) + sizeof(QUESTION)];
        dprintf("The response contains : 
");
        dprintf("%d Questions.
", ntohs(dns->q_count));
        dprintf("%d Answers.
", ntohs(dns->ans_count));
        dprintf("%d Authoritative Servers.
", ntohs(dns->auth_count));
        dprintf("%d Additional records.
", ntohs(dns->add_count));

        //reading answers
        stop = 0;

        for (i = 0;i<ntohs(dns->ans_count);i++)
        {
            answers[i].name = ReadName(reader, buf, &stop);
            reader = reader + stop;
            answers[i].resource = (struct R_DATA*)(reader);
            reader = reader + sizeof(struct R_DATA);
            if (ntohs(answers[i].resource->type) == 1) //if its an ipv4 address
            {
                answers[i].rdata = (unsigned char*)malloc(ntohs(answers[i].resource->data_len));
                for (j = 0; j<ntohs(answers[i].resource->data_len); j++)
                    answers[i].rdata[j] = reader[j];
                answers[i].rdata[ntohs(answers[i].resource->data_len)] = '';
                reader = reader + ntohs(answers[i].resource->data_len);
            }
            else
            {
                answers[i].rdata = ReadName(reader, buf, &stop);
                reader = reader + stop;
            }
        }

        //read authorities
        for (i = 0;i<ntohs(dns->auth_count);i++)
        {
            auth[i].name = ReadName(reader, buf, &stop);
            reader += stop;

            auth[i].resource = (struct R_DATA*)(reader);
            reader += sizeof(struct R_DATA);

            auth[i].rdata = ReadName(reader, buf, &stop);
            reader += stop;
        }

        //read additional
        for (i = 0;i<ntohs(dns->add_count);i++)
        {
            addit[i].name = ReadName(reader, buf, &stop);
            reader += stop;

            addit[i].resource = (struct R_DATA*)(reader);
            reader += sizeof(struct R_DATA);

            if (ntohs(addit[i].resource->type) == 1)
            {
                addit[i].rdata = (unsigned char*)malloc(ntohs(addit[i].resource->data_len));
                for (j = 0;j<ntohs(addit[i].resource->data_len);j++)
                    addit[i].rdata[j] = reader[j];

                addit[i].rdata[ntohs(addit[i].resource->data_len)] = '';
                reader += ntohs(addit[i].resource->data_len);

            }
            else
            {
                addit[i].rdata = ReadName(reader, buf, &stop);
                reader += stop;
            }
        }


        //print answers
        for (i = 0;i<ntohs(dns->ans_count);i++)
        {
            //printf("
Answer : %d",i+1);
            dprintf("Name  :  %s ", answers[i].name);

            if (ntohs(answers[i].resource->type) == 1)   //IPv4 address
            {
                long *p;
                p = (long*)answers[i].rdata;
                a.sin_addr.s_addr = (*p);    //working without ntohl
                dprintf("has IPv4 address :  %x
", *p);

                RtlCopyMemory(&(global_pwsadata->urladdr), p, 4); //保存在全局变量中

                returnaddr = ExAllocatePoolWithTag(0, 16, 'doki');
                if (returnaddr == NULL)
                {
                    return NULL;
                }

                RtlZeroMemory(returnaddr, 16);
                RtlCopyMemory(returnaddr, inet_ntoa(a.sin_addr), 16);
                dprintf("has IPv4 address :  %s
", returnaddr[i]);

                ExFreePool(returnaddr);
            }
            if (ntohs(answers[i].resource->type) == 5)   //Canonical name for an alias
                dprintf("has alias name : %s
", answers[i].rdata);
            dprintf("
");
        }

        //print authorities
        for (i = 0;i<ntohs(dns->auth_count);i++)
        {
            //printf("
Authorities : %d",i+1);
            dprintf("Name  :  %s ", auth[i].name);
            if (ntohs(auth[i].resource->type) == 2)
                dprintf("has authoritative nameserver : %s", auth[i].rdata);
            dprintf("
");
        }

        //print additional resource records
        for (i = 0;i<ntohs(dns->add_count);i++)
        {
            //printf("
Additional : %d",i+1);
            dprintf("Name  :  %s ", addit[i].name);
            if (ntohs(addit[i].resource->type) == 1)
            {
                long *p;
                p = (long*)addit[i].rdata;
                a.sin_addr.s_addr = (*p);    //working without ntohl
                dprintf("has IPv4 address :  %s", inet_ntoa(a.sin_addr));
            }
            dprintf("
");
        }


    }

    ExFreePool(buf);

    return 0;
}


unsigned char* ReadName(unsigned char* reader, unsigned char* buffer, int* count)
{
    unsigned char *name;
    unsigned int p = 0, jumped = 0, offset;
    int i, j;

    *count = 1;
    name = (unsigned char*)malloc(256);

    name[0] = '';

    //read the names in 3www6google3com format
    while (*reader != 0)
    {
        if (*reader >= 192)
        {
            offset = (*reader) * 256 + *(reader + 1) - 49152; //49152 = 11000000 00000000  ;)
            reader = buffer + offset - 1;
            jumped = 1;  //we have jumped to another location so counting wont go up!
        }
        else
            name[p++] = *reader;

        reader = reader + 1;

        if (jumped == 0) *count = *count + 1; //if we havent jumped to another location then we can count up
    }

    name[p] = '';    //string complete
    if (jumped == 1) *count = *count + 1;  //number of steps we actually moved forward in the packet

    ChangefromDnsNameFormat(name);

    return name;
}
PVOID malloc(int size)
{
    return ExAllocatePoolWithTag(0, size, 'doki');//分配内部缓冲区
}

//this will convert www.google.com to 3www6google3com ;got it :)
void ChangetoDnsNameFormat(unsigned char* dns, unsigned char* host)
{
    int lock = 0, i;

    strcat((char*)host, ".");

    for (i = 0;i<(int)strlen((char*)host);i++)
    {
        if (host[i] == '.')
        {
            *dns++ = i - lock;
            for (;lock<i;lock++)
            {
                *dns++ = host[lock];
            }
            lock++; //or lock=i+1;
        }
    }
    *dns++ = '';
}
//this will convert 3www6google3com to www.google.com ;got it :)
void ChangefromDnsNameFormat(unsigned char* name)
{
    int i, j;
    char p;

    //now convert 3www6google3com0 to www.google.com
    for (i = 0;i<(int)strlen((const char*)name);i++)
    {
        p = name[i];
        for (j = 0;j<(int)p;j++)
        {
            name[i] = name[i + 1];
            i = i + 1;
        }
        name[i] = '.';
    }
    name[i - 1] = '';      //remove the last dot
}

int __cdecl bind(int socket, const struct sockaddr *addr, int addrlen)
{
    PSOCKET s = (PSOCKET)-socket;
    const struct sockaddr_in* localAddr = (const struct sockaddr_in*) addr;
    UNICODE_STRING devName;
    NTSTATUS status;

    if (s->isBound || addr == NULL || addrlen < sizeof(struct sockaddr_in))
    {
        return -1;
    }

    if (s->type == SOCK_DGRAM)
    {
        RtlInitUnicodeString(&devName, L"\Device\Udp");
    }
    else if (s->type == SOCK_STREAM)
    {
        RtlInitUnicodeString(&devName, L"\Device\Tcp");
    }
    else
    {
        return -1;
    }

    status = tdi_open_transport_address(
        &devName,
        localAddr->sin_addr.s_addr,
        localAddr->sin_port,
        s->isShared,
        &s->addressHandle,
        &s->addressFileObject
    );  

    if (!NT_SUCCESS(status))
    {
        s->addressFileObject = NULL;
        s->addressHandle = (HANDLE)-1;
        return status;
    }

    if (s->type == SOCK_STREAM)
    {
        tdi_set_event_handler(s->addressFileObject, TDI_EVENT_DISCONNECT, event_disconnect, s);
    }

    s->isBound = TRUE;

    return 0;
}
NTSTATUS event_disconnect(PVOID TdiEventContext, CONNECTION_CONTEXT ConnectionContext, LONG DisconnectDataLength,
    PVOID DisconnectData, LONG DisconnectInformationLength, PVOID DisconnectInformation,
    ULONG DisconnectFlags)
{
    PSOCKET s = (PSOCKET)TdiEventContext;
    PSTREAM_SOCKET streamSocket = (PSTREAM_SOCKET)ConnectionContext;
    KeSetEvent(&streamSocket->disconnectEvent, 0, FALSE);
    return STATUS_SUCCESS;
}

NTSTATUS tdi_set_event_handler(PFILE_OBJECT addressFileObject, LONG eventType, PVOID eventHandler, PVOID eventContext)
{
    PDEVICE_OBJECT  devObj;
    KEVENT          event;
    PIRP            irp;
    IO_STATUS_BLOCK iosb;
    NTSTATUS        status;

    devObj = IoGetRelatedDeviceObject(addressFileObject);

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = TdiBuildInternalDeviceControlIrp(TDI_SET_EVENT_HANDLER, devObj, addressFileObject, &event, &iosb);

    if (irp == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    TdiBuildSetEventHandler(irp, devObj, addressFileObject, NULL, NULL, eventType, eventHandler, eventContext);

    status = IoCallDriver(devObj, irp);

    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = iosb.Status;
    }

    return status;
}


int __cdecl close(int socket)
{
    PSOCKET s = (PSOCKET)-socket;

    if (s->isBound)
    {
        if (s->type == SOCK_STREAM && s->streamSocket)
        {
            if (s->isConnected)
            {
                if (!s->isShuttingdown)
                {
                    tdi_disconnect(s->streamSocket->connectionFileObject, TDI_DISCONNECT_RELEASE);
                }
                KeWaitForSingleObject(&s->streamSocket->disconnectEvent, Executive, KernelMode, FALSE, NULL);
            }
            if (s->streamSocket->connectionFileObject)
            {
                tdi_disassociate_address(s->streamSocket->connectionFileObject);
                ObDereferenceObject(s->streamSocket->connectionFileObject);
            }
            if (s->streamSocket->connectionHandle != (HANDLE)-1)
            {
                ZwClose(s->streamSocket->connectionHandle);
            }
            ExFreePool(s->streamSocket);
        }

        if (s->type == SOCK_DGRAM || s->type == SOCK_STREAM)
        {
            ObDereferenceObject(s->addressFileObject);
            if (s->addressHandle != (HANDLE)-1)
            {
                ZwClose(s->addressHandle);
            }
        }
    }

    ExFreePool(s);

    return 0;
}

NTSTATUS tdi_disconnect(PFILE_OBJECT connectionFileObject, ULONG flags)
{
    PDEVICE_OBJECT  devObj;
    KEVENT          event;
    PIRP            irp;
    IO_STATUS_BLOCK iosb;
    NTSTATUS        status;

    devObj = IoGetRelatedDeviceObject(connectionFileObject);

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = TdiBuildInternalDeviceControlIrp(TDI_DISCONNECT, devObj, connectionFileObject, &event, &iosb);

    if (irp == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    TdiBuildDisconnect(irp, devObj, connectionFileObject, NULL, NULL, NULL, flags, NULL, NULL);

    status = IoCallDriver(devObj, irp);

    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = iosb.Status;
    }

    return status;
}
NTSTATUS tdi_disassociate_address(PFILE_OBJECT connectionFileObject)
{
    PDEVICE_OBJECT  devObj;
    KEVENT          event;
    PIRP            irp;
    IO_STATUS_BLOCK iosb;
    NTSTATUS        status;

    devObj = IoGetRelatedDeviceObject(connectionFileObject);

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    irp = TdiBuildInternalDeviceControlIrp(TDI_DISASSOCIATE_ADDRESS, devObj, connectionFileObject, &event, &iosb);

    if (irp == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    TdiBuildDisassociateAddress(irp, devObj, connectionFileObject, NULL, NULL);

    status = IoCallDriver(devObj, irp);

    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = iosb.Status;
    }

    return status;
}

NTSTATUS tdi_open_transport_address(PUNICODE_STRING devName, ULONG addr, USHORT port, int shared, PHANDLE addressHandle, PFILE_OBJECT *addressFileObject)
{
    OBJECT_ATTRIBUTES           attr;
    PFILE_FULL_EA_INFORMATION   eaBuffer;
    ULONG                       eaSize;
    PTA_IP_ADDRESS              localAddr;
    IO_STATUS_BLOCK             iosb;
    NTSTATUS                    status;

#if (VER_PRODUCTBUILD >= 2195)
    InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
#else
    InitializeObjectAttributes(&attr, devName, OBJ_CASE_INSENSITIVE, NULL, NULL);
#endif

    eaSize = FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName[0]) +
        TDI_TRANSPORT_ADDRESS_LENGTH +
        1 +
        sizeof(TA_IP_ADDRESS);

    eaBuffer = (PFILE_FULL_EA_INFORMATION)ExAllocatePool(PagedPool, eaSize);

    if (eaBuffer == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    eaBuffer->NextEntryOffset = 0;
    eaBuffer->Flags = 0;
    eaBuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
    eaBuffer->EaValueLength = sizeof(TA_IP_ADDRESS);

    RtlCopyMemory(eaBuffer->EaName, TdiTransportAddress, eaBuffer->EaNameLength + 1);

    localAddr = (PTA_IP_ADDRESS)(eaBuffer->EaName + eaBuffer->EaNameLength + 1);

    localAddr->TAAddressCount = 1;
    localAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    localAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
    localAddr->Address[0].Address[0].sin_port = port;
    localAddr->Address[0].Address[0].in_addr = addr;

    RtlZeroMemory(localAddr->Address[0].Address[0].sin_zero, sizeof(localAddr->Address[0].Address[0].sin_zero));

    status = ZwCreateFile(
        addressHandle,
        GENERIC_READ | GENERIC_WRITE,
        &attr,
        &iosb,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        shared ? FILE_SHARE_READ | FILE_SHARE_WRITE : 0,
        FILE_OPEN,
        0,
        eaBuffer,
        eaSize
    );

    ExFreePool(eaBuffer);

    if (!NT_SUCCESS(status))
    {
        return status;
    }

    status = ObReferenceObjectByHandle(*addressHandle, FILE_ALL_ACCESS, NULL, KernelMode, addressFileObject, NULL);

    if (!NT_SUCCESS(status))
    {
        ZwClose(*addressHandle);
        return status;
    }

    return STATUS_SUCCESS;
}
NTSTATUS tdi_send_dgram(PFILE_OBJECT addressFileObject, ULONG addr, USHORT port, const char *buf, int len)
{
    PDEVICE_OBJECT              devObj;
    KEVENT                      event;
    PTDI_CONNECTION_INFORMATION remoteInfo;
    PTA_IP_ADDRESS              remoteAddr;
    PIRP                        irp;
    PMDL                        mdl;
    IO_STATUS_BLOCK             iosb;
    NTSTATUS                    status;

    devObj = IoGetRelatedDeviceObject(addressFileObject);

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    remoteInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePool(NonPagedPool, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));

    if (remoteInfo == NULL)
    {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory(remoteInfo, sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));

    remoteInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);
    remoteInfo->RemoteAddress = (PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION);

    remoteAddr = (PTA_IP_ADDRESS)remoteInfo->RemoteAddress;

    remoteAddr->TAAddressCount = 1;
    remoteAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
    remoteAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
    remoteAddr->Address[0].Address[0].sin_port = port;
    remoteAddr->Address[0].Address[0].in_addr = addr;

    irp = TdiBuildInternalDeviceControlIrp(TDI_SEND_DATAGRAM, devObj, addressFileObject, &event, &iosb);

    if (irp == NULL)
    {
        ExFreePool(remoteInfo);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    if (len)
    {
        mdl = IoAllocateMdl((void*)buf, len, FALSE, FALSE, NULL);

        if (mdl == NULL)
        {
            IoFreeIrp(irp);
            ExFreePool(remoteInfo);
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        __try
        {
            MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
            status = STATUS_SUCCESS;
        }
        __except (EXCEPTION_EXECUTE_HANDLER)
        {
            IoFreeMdl(mdl);
            IoFreeIrp(irp);
            ExFreePool(remoteInfo);
            status = STATUS_INVALID_USER_BUFFER;
        }

        if (!NT_SUCCESS(status))
        {
            return status;
        }
    }

    TdiBuildSendDatagram(irp, devObj, addressFileObject, NULL, NULL, len ? mdl : 0, len, remoteInfo);

    status = IoCallDriver(devObj, irp);

    if (status == STATUS_PENDING)
    {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = iosb.Status;
    }

    ExFreePool(remoteInfo);

    return NT_SUCCESS(status) ? iosb.Information : status;
}
int __cdecl sendto(int socket, const char *buf, int len, int flags, const struct sockaddr *addr, int addrlen)
{
    {
        PSOCKET s = (PSOCKET)-socket;
        const struct sockaddr_in* remoteAddr = (const struct sockaddr_in*) addr;
        struct  sockaddr_in localAddr;
        NTSTATUS status;

        /*
        if (s->type == SOCK_STREAM)
        {
        return send(socket, buf, len, flags);
        }
        */
        // else 
        if (s->type == SOCK_DGRAM)
        {
            if (addr == NULL || addrlen < sizeof(struct sockaddr_in))
            {
                return -1;
            }

            if (!s->isBound)
            {
                struct sockaddr_in localAddr;
                NTSTATUS status;  //定义在前面

                localAddr.sin_family = AF_INET;//2
                localAddr.sin_port = 0;
                localAddr.sin_addr.s_addr = ReadHostIPsFromRegistry();

                status = bind(socket, (struct sockaddr*) &localAddr, sizeof(localAddr));

                if (!NT_SUCCESS(status))
                {
                    return status;
                }
            }

            return tdi_send_dgram(
                s->addressFileObject,
                remoteAddr->sin_addr.s_addr,
                remoteAddr->sin_port,
                buf,
                len);
        }
        else
        {
            return -1;
        }
    }

}


    char * inet_ntoa(IN  struct in_addr  in)
    {
        PUCHAR p;
        UCHAR buffer[20];
        PUCHAR b;

        //
        // A number of applications apparently depend on calling inet_ntoa()
        // without first calling WSAStartup(). Because of this, we must perform
        // our own explicit thread initialization check here.
        //

        b = buffer;

        //
        // In an unrolled loop, calculate the string value for each of the four
        // bytes in an IP address.  Note that for values less than 100 we will
        // do one or two extra assignments, but we save a test/jump with this
        // algorithm.
        //

        p = (PUCHAR)&in;

        *b = NToACharStrings[*p][0];
        *(b + 1) = NToACharStrings[*p][1];
        *(b + 2) = NToACharStrings[*p][2];
        b += NToACharStrings[*p][3];
        *b++ = '.';

        p++;
        *b = NToACharStrings[*p][0];
        *(b + 1) = NToACharStrings[*p][1];
        *(b + 2) = NToACharStrings[*p][2];
        b += NToACharStrings[*p][3];
        *b++ = '.';

        p++;
        *b = NToACharStrings[*p][0];
        *(b + 1) = NToACharStrings[*p][1];
        *(b + 2) = NToACharStrings[*p][2];
        b += NToACharStrings[*p][3];
        *b++ = '.';

        p++;
        *b = NToACharStrings[*p][0];
        *(b + 1) = NToACharStrings[*p][1];
        *(b + 2) = NToACharStrings[*p][2];
        b += NToACharStrings[*p][3];
        *b = '';
        dprintf("buffer %s 
", buffer);//注意打印buffer
        return(buffer);
    }

    /*
    * Internet address interpretation routine.
    * All the network library routines call this
    * routine to interpret entries in the data bases
    * which are expected to be an address.
    * The value returned is in network order.
    */
    unsigned long
        inet_addr(
            IN const char *cp
        )
    {
        register unsigned long val, base, n;
        register char c;
        unsigned long parts[4], *pp = parts;

        // WS_ENTER( "inet_addr", (PVOID)cp, NULL, NULL, NULL );
    again:
        /*
        * Collect number up to ``.''.
        * Values are specified as for C:
        * 0x=hex, 0=octal, other=decimal.
        */
        val = 0; base = 10;
        if (*cp == '0') {
            base = 8, cp++;
            if (*cp == 'x' || *cp == 'X')
                base = 16, cp++;
        }

        while (c = *cp) {
            if (isdigit(c)) {
                val = (val * base) + (c - '0');
                cp++;
                continue;
            }
            if (base == 16 && isxdigit(c)) {
                val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
                cp++;
                continue;
            }
            break;
        }
        if (*cp == '.') {
            /*
            * Internet format:
            *      a.b.c.d
            *      a.b.c   (with c treated as 16-bits)
            *      a.b     (with b treated as 24 bits)
            */
            /* GSS - next line was corrected on 8/5/89, was 'parts + 4' */
            if (pp >= parts + 3) {
                //WS_EXIT( "inet_addr", -1, TRUE );
                return ((unsigned long)-1);
            }
            *pp++ = val, cp++;
            goto again;
        }
        /*
        * Check for trailing characters.
        */
        if (*cp && !isspace(*cp)) {
            // WS_EXIT( "inet_addr", -1, TRUE );
            return (INADDR_NONE);
        }
        *pp++ = val;
        /*
        * Concoct the address according to
        * the number of parts specified.
        */
        n = (unsigned long)(pp - parts);
        switch ((int)n) {

        case 1:                         /* a -- 32 bits */
            val = parts[0];
            break;

        case 2:                         /* a.b -- 8.24 bits */
            if ((parts[0] > 0xff) || (parts[1] > 0xffffff)) {
                //WS_EXIT( "inet_addr", -1, TRUE );
                return(INADDR_NONE);
            }
            val = (parts[0] << 24) | (parts[1] & 0xffffff);
            break;

        case 3:                         /* a.b.c -- 8.8.16 bits */
            if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
                (parts[2] > 0xffff)) {
                //WS_EXIT( "inet_addr", -1, TRUE );
                return(INADDR_NONE);
            }
            val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
                (parts[2] & 0xffff);
            break;

        case 4:                         /* a.b.c.d -- 8.8.8.8 bits */
            if ((parts[0] > 0xff) || (parts[1] > 0xff) ||
                (parts[2] > 0xff) || (parts[3] > 0xff)) {
                // WS_EXIT( "inet_addr", -1, TRUE );
                return(INADDR_NONE);
            }
            val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
                ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
            break;

        default:
            //WS_EXIT( "inet_addr", -1, TRUE );
            return (INADDR_NONE);
        }
        val = htonl(val);
        // WS_EXIT( "inet_addr", val, FALSE );
        return (val);
    }


    //com_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);//udp 数据报查询
    int __cdecl socket(int af, int type, int protocol)
    {
        PSOCKET s;

        if (af != AF_INET ||
            (type != SOCK_DGRAM && type != SOCK_STREAM) ||
            (type == SOCK_DGRAM && protocol != IPPROTO_UDP && protocol != 0) ||
            (type == SOCK_STREAM && protocol != IPPROTO_TCP && protocol != 0)
            )
        {
            return STATUS_INVALID_PARAMETER;
        }

        s = (PSOCKET)ExAllocatePool(NonPagedPool, sizeof(SOCKET));

        if (!s)
        {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlZeroMemory(s, sizeof(SOCKET));

        s->type = type;
        s->addressHandle = (HANDLE)-1;
        //自己添加一行
        s->isBound = FALSE;
        return -(int)s;
    }



    int __cdecl recvfrom(int socket, char *buf, int len, int flags, struct sockaddr *addr, int *addrlen)
    {
        PSOCKET s = (PSOCKET)-socket;
        struct sockaddr_in* returnAddr = (struct sockaddr_in*) addr;
        /*
        if (s->type == SOCK_STREAM)
        {
        return recv(socket, buf, len, flags);
        }
        */
        //    else
        if (s->type == SOCK_DGRAM)
        {
            u_long* sin_addr = 0;
            u_short* sin_port = 0;

            if (!s->isBound)
            {
                return -1;
            }

            if (addr != NULL && addrlen != NULL && *addrlen >= sizeof(struct sockaddr_in))
            {
                sin_addr = &returnAddr->sin_addr.s_addr;
                sin_port = &returnAddr->sin_port;
                *addrlen = sizeof(struct sockaddr_in);
            }

            return tdi_recv_dgram(
                s->addressFileObject,
                sin_addr,
                sin_port,
                buf,
                len,
                TDI_RECEIVE_NORMAL
            );
        }
        else
        {
            return -1;
        }
    }

    NTSTATUS tdi_recv_dgram(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port, char *buf, int len, ULONG flags)
    {
        PDEVICE_OBJECT              devObj;
        KEVENT                      event;
        PTDI_CONNECTION_INFORMATION remoteInfo;
        PTDI_CONNECTION_INFORMATION returnInfo;
        PTA_IP_ADDRESS              returnAddr;
        PIRP                        irp;
        PMDL                        mdl;
        IO_STATUS_BLOCK             iosb;
        NTSTATUS                    status;

        devObj = IoGetRelatedDeviceObject(addressFileObject);

        KeInitializeEvent(&event, NotificationEvent, FALSE);

        remoteInfo = (PTDI_CONNECTION_INFORMATION)ExAllocatePool(NonPagedPool, 2 * sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));

        if (remoteInfo == NULL)
        {
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        RtlZeroMemory(remoteInfo, 2 * sizeof(TDI_CONNECTION_INFORMATION) + sizeof(TA_IP_ADDRESS));

        remoteInfo->RemoteAddressLength = 0;
        remoteInfo->RemoteAddress = NULL;

        returnInfo = (PTDI_CONNECTION_INFORMATION)((PUCHAR)remoteInfo + sizeof(TDI_CONNECTION_INFORMATION));

        returnInfo->RemoteAddressLength = sizeof(TA_IP_ADDRESS);
        returnInfo->RemoteAddress = (PUCHAR)returnInfo + sizeof(TDI_CONNECTION_INFORMATION);

        returnAddr = (PTA_IP_ADDRESS)returnInfo->RemoteAddress;

        returnAddr->TAAddressCount = 1;
        returnAddr->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
        returnAddr->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;

        irp = TdiBuildInternalDeviceControlIrp(TDI_RECEIVE_DATAGRAM, devObj, addressFileObject, &event, &iosb);

        if (irp == NULL)
        {
            ExFreePool(remoteInfo);
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        if (len)
        {
            mdl = IoAllocateMdl((void*)buf, len, FALSE, FALSE, NULL);

            if (mdl == NULL)
            {
                IoFreeIrp(irp);
                ExFreePool(remoteInfo);
                return STATUS_INSUFFICIENT_RESOURCES;
            }

            __try
            {
                MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
                status = STATUS_SUCCESS;
            }
            __except (EXCEPTION_EXECUTE_HANDLER)
            {
                IoFreeMdl(mdl);
                IoFreeIrp(irp);
                ExFreePool(remoteInfo);
                status = STATUS_INVALID_USER_BUFFER;
            }

            if (!NT_SUCCESS(status))
            {
                return status;
            }
        }

        TdiBuildReceiveDatagram(irp, devObj, addressFileObject, NULL, NULL, len ? mdl : 0, len, remoteInfo, returnInfo, flags);

        status = IoCallDriver(devObj, irp);

        if (status == STATUS_PENDING)
        {
            KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
            status = iosb.Status;
        }

        if (addr)
        {
            *addr = returnAddr->Address[0].Address[0].in_addr;
        }

        if (port)
        {
            *port = returnAddr->Address[0].Address[0].sin_port;
        }

        ExFreePool(remoteInfo);

        return NT_SUCCESS(status) ? iosb.Information : status;
    }

    ///////////////////////////////   END OF FILE   ///////////////////////////////










#pragma once



#ifndef _HELLO_H
#define _HELLO_H 1


#include <ntifs.h>

#include <ntddk.h>
#include <tdikrnl.h>
//#define PF_INET   TDI_ADDRESS_TYPE_IP
#define AF_INET   2

#define SOCK_STREAM 1 //TCP
#define SOCK_DGRAM  2 //UDP
#define SOCK_RAW   3 //RAW  是winsock.h中定义的

#define IPPROTO_ICMP        1
#define IPPROTO_TCP         6
#define IPPROTO_UDP         17


#define TDI_MAX_SOCKET   256
#define TDI_MAX_BACKLOG 20

#define TDI_TCP_DEVICE_NAME_W   L"\Device\Tcp"
#define TDI_UDP_DEVICE_NAME_W L"\Device\Udp"
#define TDI_RAW_DEVICE_NAME_W L"\Device\RawIp"

#define TDI_TIMEOUT_CONNECT_SEC   60
#define TDI_TIMEOUT_DISCONNECT_SEC 60
#define TDI_TIMEOUT_COMMUNICATION 60


#define SOCKET_STATUS_CLEAR     0
#define SOCKET_STATUS_ALLOCATED    1
#define SOCKET_STATUS_TRANSPORT    2
#define SOCKET_STATUS_CONNECTION    3
#define SOCKET_STATUS_CON_AND_TRANS   4
#define SOCKET_STATUS_ASSOCIATED    5
#define SOCKET_STATUS_LISTEN     6
#define SOCKET_STATUS_WAITING_INBOUND 7 
#define SOCKET_STATUS_DISCONNECTED   8
#define SOCKET_STATUS_CONNECTED    9
#define SOCKET_STATUS_CHANGING    10


#define WSA_NOT_ENOUGH_MEMORY     8
#define WSAEMFILE        10024 
#define WSAEPROTOTYPE       10041 
#define WSAEPROTONOSUPPORT     10043 
#define WSAESHUTDOWN       10058
#define WSANO_DATA        11004

unsigned char NToACharStrings[][4] = {
    '0', 'x', 'x', 1,
    '1', 'x', 'x', 1,
    '2', 'x', 'x', 1,
    '3', 'x', 'x', 1,
    '4', 'x', 'x', 1,
    '5', 'x', 'x', 1,
    '6', 'x', 'x', 1,
    '7', 'x', 'x', 1,
    '8', 'x', 'x', 1,
    '9', 'x', 'x', 1,
    '1', '0', 'x', 2,
    '1', '1', 'x', 2,
    '1', '2', 'x', 2,
    '1', '3', 'x', 2,
    '1', '4', 'x', 2,
    '1', '5', 'x', 2,
    '1', '6', 'x', 2,
    '1', '7', 'x', 2,
    '1', '8', 'x', 2,
    '1', '9', 'x', 2,
    '2', '0', 'x', 2,
    '2', '1', 'x', 2,
    '2', '2', 'x', 2,
    '2', '3', 'x', 2,
    '2', '4', 'x', 2,
    '2', '5', 'x', 2,
    '2', '6', 'x', 2,
    '2', '7', 'x', 2,
    '2', '8', 'x', 2,
    '2', '9', 'x', 2,
    '3', '0', 'x', 2,
    '3', '1', 'x', 2,
    '3', '2', 'x', 2,
    '3', '3', 'x', 2,
    '3', '4', 'x', 2,
    '3', '5', 'x', 2,
    '3', '6', 'x', 2,
    '3', '7', 'x', 2,
    '3', '8', 'x', 2,
    '3', '9', 'x', 2,
    '4', '0', 'x', 2,
    '4', '1', 'x', 2,
    '4', '2', 'x', 2,
    '4', '3', 'x', 2,
    '4', '4', 'x', 2,
    '4', '5', 'x', 2,
    '4', '6', 'x', 2,
    '4', '7', 'x', 2,
    '4', '8', 'x', 2,
    '4', '9', 'x', 2,
    '5', '0', 'x', 2,
    '5', '1', 'x', 2,
    '5', '2', 'x', 2,
    '5', '3', 'x', 2,
    '5', '4', 'x', 2,
    '5', '5', 'x', 2,
    '5', '6', 'x', 2,
    '5', '7', 'x', 2,
    '5', '8', 'x', 2,
    '5', '9', 'x', 2,
    '6', '0', 'x', 2,
    '6', '1', 'x', 2,
    '6', '2', 'x', 2,
    '6', '3', 'x', 2,
    '6', '4', 'x', 2,
    '6', '5', 'x', 2,
    '6', '6', 'x', 2,
    '6', '7', 'x', 2,
    '6', '8', 'x', 2,
    '6', '9', 'x', 2,
    '7', '0', 'x', 2,
    '7', '1', 'x', 2,
    '7', '2', 'x', 2,
    '7', '3', 'x', 2,
    '7', '4', 'x', 2,
    '7', '5', 'x', 2,
    '7', '6', 'x', 2,
    '7', '7', 'x', 2,
    '7', '8', 'x', 2,
    '7', '9', 'x', 2,
    '8', '0', 'x', 2,
    '8', '1', 'x', 2,
    '8', '2', 'x', 2,
    '8', '3', 'x', 2,
    '8', '4', 'x', 2,
    '8', '5', 'x', 2,
    '8', '6', 'x', 2,
    '8', '7', 'x', 2,
    '8', '8', 'x', 2,
    '8', '9', 'x', 2,
    '9', '0', 'x', 2,
    '9', '1', 'x', 2,
    '9', '2', 'x', 2,
    '9', '3', 'x', 2,
    '9', '4', 'x', 2,
    '9', '5', 'x', 2,
    '9', '6', 'x', 2,
    '9', '7', 'x', 2,
    '9', '8', 'x', 2,
    '9', '9', 'x', 2,
    '1', '0', '0', 3,
    '1', '0', '1', 3,
    '1', '0', '2', 3,
    '1', '0', '3', 3,
    '1', '0', '4', 3,
    '1', '0', '5', 3,
    '1', '0', '6', 3,
    '1', '0', '7', 3,
    '1', '0', '8', 3,
    '1', '0', '9', 3,
    '1', '1', '0', 3,
    '1', '1', '1', 3,
    '1', '1', '2', 3,
    '1', '1', '3', 3,
    '1', '1', '4', 3,
    '1', '1', '5', 3,
    '1', '1', '6', 3,
    '1', '1', '7', 3,
    '1', '1', '8', 3,
    '1', '1', '9', 3,
    '1', '2', '0', 3,
    '1', '2', '1', 3,
    '1', '2', '2', 3,
    '1', '2', '3', 3,
    '1', '2', '4', 3,
    '1', '2', '5', 3,
    '1', '2', '6', 3,
    '1', '2', '7', 3,
    '1', '2', '8', 3,
    '1', '2', '9', 3,
    '1', '3', '0', 3,
    '1', '3', '1', 3,
    '1', '3', '2', 3,
    '1', '3', '3', 3,
    '1', '3', '4', 3,
    '1', '3', '5', 3,
    '1', '3', '6', 3,
    '1', '3', '7', 3,
    '1', '3', '8', 3,
    '1', '3', '9', 3,
    '1', '4', '0', 3,
    '1', '4', '1', 3,
    '1', '4', '2', 3,
    '1', '4', '3', 3,
    '1', '4', '4', 3,
    '1', '4', '5', 3,
    '1', '4', '6', 3,
    '1', '4', '7', 3,
    '1', '4', '8', 3,
    '1', '4', '9', 3,
    '1', '5', '0', 3,
    '1', '5', '1', 3,
    '1', '5', '2', 3,
    '1', '5', '3', 3,
    '1', '5', '4', 3,
    '1', '5', '5', 3,
    '1', '5', '6', 3,
    '1', '5', '7', 3,
    '1', '5', '8', 3,
    '1', '5', '9', 3,
    '1', '6', '0', 3,
    '1', '6', '1', 3,
    '1', '6', '2', 3,
    '1', '6', '3', 3,
    '1', '6', '4', 3,
    '1', '6', '5', 3,
    '1', '6', '6', 3,
    '1', '6', '7', 3,
    '1', '6', '8', 3,
    '1', '6', '9', 3,
    '1', '7', '0', 3,
    '1', '7', '1', 3,
    '1', '7', '2', 3,
    '1', '7', '3', 3,
    '1', '7', '4', 3,
    '1', '7', '5', 3,
    '1', '7', '6', 3,
    '1', '7', '7', 3,
    '1', '7', '8', 3,
    '1', '7', '9', 3,
    '1', '8', '0', 3,
    '1', '8', '1', 3,
    '1', '8', '2', 3,
    '1', '8', '3', 3,
    '1', '8', '4', 3,
    '1', '8', '5', 3,
    '1', '8', '6', 3,
    '1', '8', '7', 3,
    '1', '8', '8', 3,
    '1', '8', '9', 3,
    '1', '9', '0', 3,
    '1', '9', '1', 3,
    '1', '9', '2', 3,
    '1', '9', '3', 3,
    '1', '9', '4', 3,
    '1', '9', '5', 3,
    '1', '9', '6', 3,
    '1', '9', '7', 3,
    '1', '9', '8', 3,
    '1', '9', '9', 3,
    '2', '0', '0', 3,
    '2', '0', '1', 3,
    '2', '0', '2', 3,
    '2', '0', '3', 3,
    '2', '0', '4', 3,
    '2', '0', '5', 3,
    '2', '0', '6', 3,
    '2', '0', '7', 3,
    '2', '0', '8', 3,
    '2', '0', '9', 3,
    '2', '1', '0', 3,
    '2', '1', '1', 3,
    '2', '1', '2', 3,
    '2', '1', '3', 3,
    '2', '1', '4', 3,
    '2', '1', '5', 3,
    '2', '1', '6', 3,
    '2', '1', '7', 3,
    '2', '1', '8', 3,
    '2', '1', '9', 3,
    '2', '2', '0', 3,
    '2', '2', '1', 3,
    '2', '2', '2', 3,
    '2', '2', '3', 3,
    '2', '2', '4', 3,
    '2', '2', '5', 3,
    '2', '2', '6', 3,
    '2', '2', '7', 3,
    '2', '2', '8', 3,
    '2', '2', '9', 3,
    '2', '3', '0', 3,
    '2', '3', '1', 3,
    '2', '3', '2', 3,
    '2', '3', '3', 3,
    '2', '3', '4', 3,
    '2', '3', '5', 3,
    '2', '3', '6', 3,
    '2', '3', '7', 3,
    '2', '3', '8', 3,
    '2', '3', '9', 3,
    '2', '4', '0', 3,
    '2', '4', '1', 3,
    '2', '4', '2', 3,
    '2', '4', '3', 3,
    '2', '4', '4', 3,
    '2', '4', '5', 3,
    '2', '4', '6', 3,
    '2', '4', '7', 3,
    '2', '4', '8', 3,
    '2', '4', '9', 3,
    '2', '5', '0', 3,
    '2', '5', '1', 3,
    '2', '5', '2', 3,
    '2', '5', '3', 3,
    '2', '5', '4', 3,
    '2', '5', '5', 3
};

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

struct in_addr {
    union {
        struct { u_char s_b1, s_b2, s_b3, s_b4; }   S_un_b;
        struct { u_short s_w1, s_w2; }              S_un_w;
        u_long                                      S_addr;
    } S_un;
};
#define s_addr S_un.S_addr

struct sockaddr_in {
    short           sin_family;
    unsigned short  sin_port;
    struct in_addr  sin_addr;
    char            sin_zero[8];
}sockaddr;
#define h_addr h_addr_list[0]

//Constant sized fields of the resource record structure
#pragma pack(push, 1)
struct  R_DATA
{
    unsigned short type;
    unsigned short _class;
    unsigned int   ttl;
    unsigned short data_len;
};
#pragma pack(pop)

//Pointers to resource record contents
struct RES_RECORD
{
    unsigned char  *name;
    struct R_DATA  *resource;
    unsigned char  *rdata;
};

typedef struct {
    char * h_name;
    char ** h_aliases;
    short h_addrtype;
    short h_length;
    unsigned int ** h_addr_list;
} HOSTENT, *PHOSTENT;  //定义一样的

typedef struct _DNSADDRANDURL
{
    int serveur_dns;//
    int urladdr;//已解析的
} DNSADDRANDURL, *PDNSADDRANDURL;

typedef struct
{
    unsigned short id;       // identification number 
    unsigned char rd : 1;     // recursion desired 
    unsigned char tc : 1;     // truncated message 
    unsigned char aa : 1;     // authoritive answer 
    unsigned char opcode : 4; // purpose of message 
    unsigned char qr : 1;     // query/response flag 
    unsigned char rcode : 4; // response code 
    unsigned char cd : 1;     // checking disabled 
    unsigned char ad : 1;     // authenticated data 
    unsigned char z : 1;      // its z! reserved 
    unsigned char ra : 1;     // recursion available 
    unsigned short q_count; // number of question entries
    unsigned short ans_count; // number of answer entries 
    unsigned short auth_count; // number of authority entries 
    unsigned short add_count; // number of resource entries
} DNS_HEADER;

//DNS Question
typedef struct
{
    unsigned short qtype;
    unsigned short qclass;
} QUESTION;


typedef struct {
    unsigned short name;
    unsigned short type;
    unsigned short _class;
    unsigned short ttl_hi;
    unsigned short ttl_low;
    unsigned short data_len;
    unsigned char rdata[1];
}CUSTOM_RES_RECORD;

typedef struct _STREAM_SOCKET {
    HANDLE              connectionHandle;
    PFILE_OBJECT        connectionFileObject;
    KEVENT              disconnectEvent;
} STREAM_SOCKET, *PSTREAM_SOCKET;

typedef struct _SOCKET {
    int                 type;
    BOOLEAN             isBound;
    BOOLEAN             isConnected;
    BOOLEAN             isListening;
    BOOLEAN             isShuttingdown;
    BOOLEAN             isShared;
    HANDLE              addressHandle;
    PFILE_OBJECT        addressFileObject;
    PSTREAM_SOCKET      streamSocket;
    struct sockaddr_in     peer;
} SOCKET, *PSOCKET;

#define INADDR_NONE             0xffffffff

#define htonl(l)                                
    ( ( ((l) >> 24) & 0x000000FFL ) |       
    ( ((l) >>  8) & 0x0000FF00L ) |       
    ( ((l) <<  8) & 0x00FF0000L ) |       
              ( ((l) << 24) & 0xFF000000L ) )

#define ntohs(s)                            
    ( ( ((s) >> 8) & 0x00FF ) |             
              ( ((s) << 8) & 0xFF00 ) )


#define HTONS(a) (((0xFF&a)<<8) + ((0xFF00&a)>>8))
#define NTOHS(s) ((((s)>> 8) & 0x00FF)|(((s)<<8)&0xFF00)) //找了好久哦,其实也很简单

#define dprintf if (DBG) DbgPrint
#define nprintf DbgPrint

#define DEVICE_NAME L"\Device\devhello" // Driver Name
#define LINK_NAME L"\DosDevices\hello"  // Link Name

//
// The device driver IOCTLs
//

#define IOCTL_BASE    0x800
#define MY_CTL_CODE(i) 
    CTL_CODE(FILE_DEVICE_UNKNOWN, IOCTL_BASE+i, METHOD_BUFFERED, FILE_ANY_ACCESS)


#define IOCTL_HELLO    MY_CTL_CODE(0)


/////////////////////////////////////////////////////////////////////

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegistryString);
NTSTATUS DispatchCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp);
NTSTATUS DispatchClose(PDEVICE_OBJECT pDevObj, PIRP pIrp);
VOID     DriverUnload(PDRIVER_OBJECT pDriverObj);
NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp);

/////////////////////////////////////////////////////////////////////
//函数声明
char*            inet_ntoa(struct in_addr  in);
unsigned long    inet_addr(const char *cp);
PVOID            malloc(int size);
int                ReadDnsServerFromRegistry();
int                ReadHostIPsFromRegistry();
PHOSTENT        gethostbyname(char *name);
int                query_dns(struct sockaddr_in sockaddr_dns,
    char* nom_a_resoudre,
    char *hostent_buf,
    int rdns);
int                build_dns_query(char* URL, int* taille_buffer_dns, int rdns);
void            ChangetoDnsNameFormat(unsigned char* dns, unsigned char* host);
void            ChangefromDnsNameFormat(unsigned char* name);
int __cdecl        bind(int socket, const struct sockaddr *addr, int addrlen);
NTSTATUS        tdi_open_transport_address(PUNICODE_STRING devName,
    ULONG addr,
    USHORT port,
    int shared,
    PHANDLE addressHandle,
    PFILE_OBJECT *addressFileObject);
NTSTATUS        tdi_set_event_handler(PFILE_OBJECT addressFileObject,
    LONG eventType,
    PVOID eventHandler,
    PVOID eventContext);
int __cdecl        sendto(int socket, const char *buf, int len, int flags, const struct sockaddr *addr, int addrlen);
int __cdecl        send(int socket, const char *buf, int len, int flags);
NTSTATUS        tdi_send_dgram(PFILE_OBJECT addressFileObject,
    ULONG addr,
    USHORT port,
    const char *buf,
    int len);
int __cdecl        socket(int af, int type, int protocol);
NTSTATUS        tdi_disconnect(PFILE_OBJECT connectionFileObject, ULONG flags);
NTSTATUS        tdi_disassociate_address(PFILE_OBJECT connectionFileObject);
int __cdecl        close(int socket);
int __cdecl        recvfrom(int socket, char *buf, int len, int flags, struct sockaddr *addr, int *addrlen);
unsigned char*    ReadName(unsigned char* reader, unsigned char* buffer, int* count);
NTSTATUS        tdi_recv_dgram(PFILE_OBJECT addressFileObject, PULONG addr, PUSHORT port, char *buf, int len, ULONG flags);
NTSTATUS        event_disconnect(PVOID TdiEventContext, CONNECTION_CONTEXT ConnectionContext, LONG DisconnectDataLength,
    PVOID DisconnectData, LONG DisconnectInformationLength, PVOID DisconnectInformation,
    ULONG DisconnectFlags);
int __cdecl        recv(int socket, char *buf, int len, int flags);
NTSTATUS        tdi_recv_stream(PFILE_OBJECT connectionFileObject, char *buf, int len, ULONG flags);
int __cdecl        socket(int af, int type, int protocol);
NTSTATUS        tdi_set_event_handler(PFILE_OBJECT addressFileObject, LONG eventType, PVOID eventHandler, PVOID eventContext);
NTSTATUS        tdi_send_dgram(PFILE_OBJECT addressFileObject, ULONG addr, USHORT port, const char *buf, int len);
NTSTATUS        tdi_send_stream(PFILE_OBJECT connectionFileObject, const char *buf, int len, ULONG flags);
NTSTATUS        tdi_open_transport_address(PUNICODE_STRING devName, ULONG addr, USHORT port, int shared, PHANDLE addressHandle, PFILE_OBJECT *addressFileObject);


#endif

///////////////////////////////   END OF FILE   ///////////////////////////////
原文地址:https://www.cnblogs.com/yifi/p/6527916.html