zoukankan      html  css  js  c++  java
  • 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记录。

  • 相关阅读:
    系统进程
    Javascript中的常用事件
    进程信息库网址
    C#中使用临时存储过程
    Transactsql 中的 rollup 和cube的使用
    如何使用fckeditor在线编辑器(asp)
    微软将 jQuery IntelliSense整合到Visual Studio
    no such file to load openssl Anny
    Ubuntu 防火墙 ufw Anny
    Install Apache 2 from Source on Linux(转) Anny
  • 原文地址:https://www.cnblogs.com/hanawasakuraki/p/9642421.html
Copyright © 2011-2022 走看看