我是靠谱客的博主 紧张犀牛,最近开发中收集的这篇文章主要介绍PRX 剖析Proxifer “远程域名解析”NSP工作原理,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Proxifer应该是SOCKS5协议代理客户端中最优秀与可靠的工具 但它只支持UDP同时不开放源代码 但好在Proxifer并没有对其应用程式进行混淆加壳 本文将深度剖析其“远程代理解析”的实现原理。

笔者对Proxifer NSP部分进行长达半月之久的研究拉锯战 成功吸收与实现了与Proxifer“远程域名解析”相类似的功能 它本身并不神奇而且Proxifer解决此问题的方式 应是出乎意料的简单,本文不介绍与Proxifer NSP的其它相关部分 只是探讨其NSP/DLL工作原理 至于“远程域名解析”其它的坑 不在本文中累赘;

那么什么是“远程域名解析 / Remote DNS Resovle ” ? 本质上是将域名提交给代理服务器 由代理服务器进行获取其A、AAAA地址 然后与对应服务器建立对应IP传输层协议的数据连接。

它解决了GFW(中国防火长城)对指定DNS数据包污染的问题 即客户端通过DNS查询类似Youtube、Google、facebook等外国受GFW屏蔽的网站时 GFW会不停地探测来自公网上所有流通的DNS协议数据包;一般DNS服务器端口为53;然后劫持客户端请求并伪造一个指向无效地址的DNS响应数据包,与DNS数据交换协议相关的内容 你可以参考RFC1035定义的标准;

远程域名解析,具备几种不同的方法

如:

1、将应用层解析DNS的行为传送至远程代理 由远程代理解析后返回地址到应用层

2、本地DNS服务器

3、Virtual DNS Resolve

很明显“Proxifer”它采取的是第三种方法 即“Virtual DNS Resolve”,一旦开启远程域名解析 那么应用层所有DNS解析将不再离开网卡 它是在应用层虚拟的DNS解析返回 即按照Proxifer的控制端定义为 从“127.8.0.0”地址开始“原子自增”。

“Proxifer”很明智的没有采取hook的方式 这是由于hook的方式容易被杀软拦截所导致 所以它采取了另一种方法来解决“DNS”解析的问题 即通过开发NSP(namespace service provider)名字服务器提供者

应用程式通过“PrexNsp”解析DNS时 它本身没有真正意义上的向DNS服务器查询域名解析结果 而是通过伪造一个struct WSAQUERYSETW分配一个唯一的虚拟IP(fuck ip)

给此域名返回上层 同时与RnR之间交互(SOCKET交互)而在笔者的轻量级实现内是剔除这些实现的。

下面列出“远程域名解析”实现的关键代码:

int WINAPI NSPLookupServiceNext(HANDLE hLookup, DWORD dwControlFlags, LPDWORD lpdwBufferLength, LPWSAQUERYSETW lpqsResults)
{
try {
PaperAirplaneConfiguration* conf = PaperAirplaneInteractive_Current.Configuration();
if (!(conf->EnableProxyClient && conf->ResolveDNSRemote))
{
return NamespaceServiceProvider_Current.NSP_ROUTINE.NSPLookupServiceNext(hLookup, dwControlFlags, lpdwBufferLength, lpqsResults);
}
NSPLookupContext* context = (NSPLookupContext*)hLookup;
if (context == NULL || IsBadReadPtr(context, sizeof(NSPLookupContext)) || context->behavior >= 1)
{
return SOCKET_ERROR;
}
LPCSTR hostaddr = StringExtension::W2A(context->hostname);
context->hostaddr = hostaddr;
if (hostaddr == NULL)
{
return SOCKET_ERROR;
}
else
{
strlwr((char*)hostaddr);
}
memset(lpqsResults, 0, sizeof(WSAQUERYSETW));
lpqsResults->dwSize = 120;
lpqsResults->dwNameSpace = NS_DNS;
lpqsResults->dwNumberOfProtocols = 0;
lpqsResults->dwNumberOfCsAddrs = 1;
lpqsResults->dwOutputFlags = 0;
lpqsResults->lpszQueryString = context->hostname;
lpqsResults->lpszServiceInstanceName = context->hostname;
lpqsResults->lpcsaBuffer = new CSADDR_INFO({ 0 });
struct sockaddr_in* localEP = new struct sockaddr_in({ 0 });
localEP->sin_family = AF_INET;
struct sockaddr_in* remoteEP = new struct sockaddr_in({ 0 });
remoteEP->sin_family = AF_INET;
ULONG address = 0;
if (NamespaceMappingTable_Current.ContainsKey(hostaddr))
{
address = NamespaceMappingTable_Current.Get(hostaddr);
remoteEP->sin_addr.s_addr = address;
}
else
{
address = InterlockedIncrement(&RAND_MAP_IPADDRESS_NUM);
address = ntohl(address);
remoteEP->sin_addr.s_addr = address;
NamespaceMappingTable_Current.Add(address, hostaddr);
}
CSADDR_INFO* addr = lpqsResults->lpcsaBuffer;
addr->iSocketType = SOCK_RAW;
addr->iProtocol = 23;
addr->RemoteAddr.iSockaddrLength = sizeof(struct sockaddr_in);
addr->LocalAddr.iSockaddrLength = sizeof(struct sockaddr_in);
addr->LocalAddr.lpSockaddr = (struct sockaddr*)localEP;
addr->RemoteAddr.lpSockaddr = (struct sockaddr*)remoteEP;
context->behavior = 1;
return NO_ERROR;
}
catch (...) {
return SOCKET_ERROR;
}
}
但“远程域名解析”需要处理的部分远远不止上述这些代码 它是一个很复杂的体系 上述代码只是伪造一个域名解析地址 同时记录在“名称服务映射表”中 但它不代表你可以使用

它就可以直接翻墙、只是说它可以规避掉被“DNS污染”的问题。

最后

以上就是紧张犀牛为你收集整理的PRX 剖析Proxifer “远程域名解析”NSP工作原理的全部内容,希望文章能够帮你解决PRX 剖析Proxifer “远程域名解析”NSP工作原理所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部