我正在研究如何在 Windows 中拦截 DNS 查询,
以一种不需要将 DLL 注入到每个进程中的方式,并且理想情况下能够根据发出查询的进程做出决策,因此简单的 DNS 代理服务器是不够的。
从表面上看,DNS 查询所采用的路径如下所示,
某些应用程序从 ws2_32.dll(或 dnsapi.dll 中的 DnsQuery)调用 gethostbyname
[dll 做了一些事情]
最终调用 dnsrslvr.dll 中的某些内容,该 dll 在 svshost 进程中作为名为“Dnscache”的服务运行,该服务根据 TaskExplorer 从 DNS 服务器在端口 53 上发送和接收 UDP 数据包
所以我想做的是在“Dnscache”服务之前拦截一些软件的 dns 查询,或者用自己的服务替换该服务。
所以我的问题是:这里的聪明人之一是否知道公共 DNS 查询 API 和 Dnscache 服务之间会发生什么,以及两者之间的最佳位置是什么?
你可以这样做标注驱动程序 https://learn.microsoft.com/en-us/windows-hardware/drivers/network/callout-driver。
您可以在 FWPM_LAYER_DATAGRAM_DATA_V4 的标注中捕获、解析和编辑 DNS 数据包。
这是FWPM_LAYER_DATAGRAM_DATA_V4回调的代码,用于获取DNS查询名称。
void NTAPI
CoDatagramDataV4(
IN const FWPS_INCOMING_VALUES* inFixedValues,
IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
IN VOID* packet,
IN const void* classifyContext,
IN const FWPS_FILTER* filter,
IN UINT64 flowContext,
OUT FWPS_CLASSIFY_OUT* classifyOut
){
classifyOut->actionType = FWP_ACTION_PERMIT;
if (inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8 != IPPROTO_UDP
inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_REMOTE_PORT].value.uint16 != 53 ||
inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].value.uint32 != FWP_DIRECTION_INBOUND)
{
// This can be filtered by FwpmFilterAdd in ring3.
return;
}
PNET_BUFFER pNetBuffer = NET_BUFFER_LIST_FIRST_NB((PNET_BUFFER_LIST)packet);
if (pNetBuffer == NULL)
{
PVOID pDataBuffer0 = ExAllocatePoolWithTag(NonPagedPool, nDataLength, TAG_NAME_CALLOUT);
if (pDataBuffer0)
{
PVOID pDataBuffer = NdisGetDataBuffer(pNetBuffer, nDataLength, pDataBuffer0, 1, 0);
if (pDataBuffer)
{
PCHAR pszQuery = (PCHAR)pDataBuffer + 12/*sizeof DNS header*/;
CHAR szQueryName[MAX_DOMAIN_NAME_LEN] = { 0 };
CHAR cbLabel = pQuery[0];
UINT32 nLen = 1;
while (cbLabel != 0)
{
for (CHAR i = 0; i < cbLabel; i++)
{
szQueryName[nLen - 1] = pszQuery[nLen]; nLen++;
}
cbLabel = pszQuery[nLen];
szQueryName[nLen - 1] = cbLabel != 0 ? '.' : 0;
nLen++;
}
// Here szQueryName is DNS query name such as 'www.google.com'.
}
}
ExFreePoolWithTag(pDataBuffer0, 'Tsnd');
}
}
And you can check the DNS structure by using wireshark like this.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)