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