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