Windows平台获取本地DNS缓存

#include "stdafx.h"

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <WinDNS.h>

//未公开结构体,通过逆向ipconfig.exe DoDisplayDns函数
typedef struct _DnsCacheW
{
    struct _DnsCacheW *     pNext;
    PWSTR                   pName;
    WORD                    wData0;
    WORD                    wData1;
    WORD                    wData2;
}DNS_CACHEW, *PDNS_CACHEW;

//未公开函数,dnsapi.dll导出
typedef DNS_STATUS (WINAPI* FDnsGetCacheDataTable)(
    __out PDNS_CACHEW* ppQueryResults
    );

typedef VOID (WINAPI* FDnsFree)(
    __inout     PVOID           pData,
    __in        DNS_FREE_TYPE   FreeType
    );

typedef DNS_STATUS (WINAPI* FDnsQuery_W)(
    __in                PCWSTR          pszName,
    __in                WORD            wType,
    __in                DWORD           Options,
    __inout_opt         PVOID           pExtra,
    __deref_out_opt     PDNS_RECORDW*   ppQueryResults,
    __deref_opt_out_opt PVOID*          pReserved
    );

FDnsGetCacheDataTable pfDnsGetCacheDataTable = NULL;
FDnsFree pfDnsFree = NULL;
FDnsQuery_W pfDnsQueryW = NULL;

DNS_STATUS DnsFreeRecord(PDNS_RECORDW pDnsRecord)
{
    if (!pDnsRecord)
        return 0;

    //xp版本上的dnsapi.dll没有DnsFree函数,需要调用LocalFree释放缓存
    if (pfDnsFree)
    {
        pfDnsFree(pDnsRecord, DnsFreeFlat);
    }
    else
    {
        LocalFree(pDnsRecord);
    }

    return 1;
}

DNS_STATUS DnsFreeCache(PDNS_CACHEW pDnsCache)
{
    if (!pDnsCache)
        return 0;

    //xp版本上的dnsapi.dll没有DnsFree函数,需要调用LocalFree释放缓存
    if (pfDnsFree)
    {
        pfDnsFree(pDnsCache->pName, DnsFreeFlat);
        pfDnsFree(pDnsCache, DnsFreeFlat);
    }
    else
    {
        LocalFree(pDnsCache->pName);
        LocalFree(pDnsCache);
    }

    return 1;
}

VOID PrintDnsInfo(PCWSTR pHostName, WORD wData)
{
    PDNS_RECORDW pResult = NULL;
    PDNS_RECORDW pDnsTmp = NULL;
    DNS_STATUS status = pfDnsQueryW(pHostName, wData, DNS_QUERY_NO_WIRE_QUERY | 0x8000, NULL, &pResult, NULL);
    if (status)
        return;

    while (pResult)
    {
        if (pResult->wType == DNS_TYPE_A)
        {
            DWORD dwIpv4 = pResult->Data.A.IpAddress;
            wprintf(L"ipv4:%d.%d.%d.%d\n", 
                    HIBYTE(HIWORD(dwIpv4)), 
                    LOBYTE(HIWORD(dwIpv4)), 
                    HIBYTE(LOWORD(dwIpv4)), 
                    LOBYTE(LOWORD(dwIpv4)), 
                    pResult->wType);
        }
        else if (pResult->wType == DNS_TYPE_CNAME)
        {
            wprintf(L"CName:%s\n", pResult->Data.CNAME.pNameHost);
        }
        
        pDnsTmp = pResult;
        pResult = pResult->pNext;

        DnsFreeRecord(pDnsTmp);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    HINSTANCE hLib = LoadLibrary(TEXT("DNSAPI.dll"));

    //获取函数地址
    pfDnsGetCacheDataTable = (FDnsGetCacheDataTable)GetProcAddress(hLib, "DnsGetCacheDataTable");
    pfDnsFree = (FDnsFree)GetProcAddress(hLib, "DnsFree");
    pfDnsQueryW = (FDnsQuery_W)GetProcAddress(hLib, "DnsQuery_W");

    if (!pfDnsGetCacheDataTable) 
    {
        printf("Can't locate address DnsGetCacheDataTable. \n");
        return 0;
    }
    if (!pfDnsQueryW)
    {
        printf("Can't locate address DnsQuery_W. \n");
        return 0;
    }
        
    PDNS_CACHEW pDnsCache = NULL;
    PDNS_CACHEW pDnsTmp = NULL;
    if (!pfDnsGetCacheDataTable(&pDnsCache))
    {
        printf("Query dns cache table failed. \n");
        return 0;
    }
    
    while(pDnsCache) 
    {
        wprintf(L"%s\n", pDnsCache->pName);

        if (pDnsCache->wData0)
            PrintDnsInfo(pDnsCache->pName, pDnsCache->wData0);
        if (pDnsCache->wData1)
            PrintDnsInfo(pDnsCache->pName, pDnsCache->wData1); 
        if (pDnsCache->wData2)
            PrintDnsInfo(pDnsCache->pName, pDnsCache->wData2); 

        pDnsTmp = pDnsCache;
        pDnsCache = pDnsCache->pNext;

        DnsFreeCache(pDnsTmp);
    }

    system("pause");
    return 1;
}

代码逆向分析自系统工具 ipconfig.exe,支持winxp - win10的记录查询。

目前打印出来的DNS记录只有A 和CName两种,发现win10以下版本获取的记录不全,win10系统能获取完整的A和CName记录。

原文地址:https://www.cnblogs.com/hanawasakuraki/p/9642421.html