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記錄。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM