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记录。

  • 相关阅读:
    nas存储服务器硬盘出现故障离线导致磁盘阵列失效、服务器无法访问的数据恢复案例
    【北亚vSAN数据恢复案例】异常断电导致vSAN底层数据损坏的数据恢复
    【Vsan数据恢复】供电不稳服务器非正常关机导致vsan架构中虚拟机磁盘文件丢失的数据恢复
    随机数
    字符串和数组截取.....某人可以看看这个,希望能帮到你,
    利用angular与后台的交互
    AngularJS 深入理解 $scope
    angular 后台交换实例
    alert()、confirm()和prompt()的区别与用法
    ReactJs入门教程
  • 原文地址:https://www.cnblogs.com/hanawasakuraki/p/9642421.html
Copyright © 2011-2022 走看看