--转载注明来源 http://www.cnblogs.com/sysnap/

0x1 背景

往HOST文件添加127.0.0.1  www.baidu.com, 可以劫持百度的域名。病毒经常篡改HOST文件来劫持域名,有没一种办法,不动HOST文件,又可以针对指定的域名使其不受HOST文件的影响?

0x02研究

通常进程调用gethostbyname来解析域名的IP,这个API内部会RPC到svchost里面去,由svchost来完成请求,最终调用R_ResolverQuery来完成解析工作,R_ResolverQuery的定义是int __stdcall R_ResolverQuery(unsigned __int16 *Handle, unsigned __int16 *pwsName, unsigned __int16 wType, unsigned int Flags, _DnsRecord **ppResultRecords),注意Flags,跟DnsQuery的fOptions是一样的,只要HOOK R_ResolverQuery, 判断pwsName是不是要保护的域名,然后给Flags或上DNS_QUERY_BYPASS_CACHE就可以了

0x03 R_ResolverQuery定位

定位R_ResolverQuery,这个函数是RPC IDL文件里面定义的,接口GUID为45776b01-5956-4485-9f80-f428f7d60129, 搜索dnsrslvr,找到45776b01-5956-4485-9f80-f428f7d60129特征就可以定位,具体的结构如下图所示

0x04 实现

一下是DLL的代码(XP测试通过,没测其它系统),需要找一个注入进程工具把DLL注入到svchost里面去,注意svchost是带-k NetWorkService的那个。HOOK函数会判断当前的域名解析请求是不是name_bypass_hostfile,是的话就不走缓存了

// dllmain.cpp : Defines the entry point for the DLL application.

#include "stdafx.h"

#include <windows.h>

#include <Rpc.h>

#include <rpcdcep.h>

#include <RpcNdr.h>

#define DNS_IF_GUID_LEN 16

unsigned char DNS_IF_GUID_[DNS_IF_GUID_LEN] = { 0x01, 0x6b, 0x77, 0x45, 0x56, 0x59, 0x85, 0x44, 0x9f, 0x80, 0xf4, 0x28, 0xf7, 0xd6, 0x01, 0x29};

static const wchar_t* name_bypass_hostfile = L"www.baidu.com";

typedef int (__stdcall * pfnR_ResolverQuery)(

unsigned __int16 *Handle,

unsigned __int16 *pwsName,

unsigned __int16 wType,

unsigned int Flags,

void **ppResultRecords

);

typedef long ( __stdcall * SERVER_ROUTINE)();

static pfnR_ResolverQuery g_old_pfnR_ResolverQuery = NULL;

static void** g_off = NULL;

void** get_R_ResolverQuery_off(void* Base, size_t Limit)

{

PRPC_SERVER_INTERFACE srv_if = NULL;

void** _R_ResolverQuery = NULL;

__try

{

unsigned char* s_ptr = (unsigned char*)Base;

for(size_t i = 0; i < Limit; i++, s_ptr++)

{

if( 0 == memcmp(DNS_IF_GUID_, s_ptr, DNS_IF_GUID_LEN) )

{

srv_if = (PRPC_SERVER_INTERFACE)(s_ptr - sizeof(unsigned int));

PMIDL_SERVER_INFO InterpreterInfo = (PMIDL_SERVER_INFO)srv_if->InterpreterInfo;

if(InterpreterInfo)

{

const SERVER_ROUTINE * DispatchTable = InterpreterInfo->DispatchTable;

_R_ResolverQuery = (void**)&DispatchTable[0x09];

}

break;

}

}

}__except(1)

{

;

}

return _R_ResolverQuery;

}

int __stdcall

fake_R_ResolverQuery(

unsigned __int16 *Handle,

unsigned __int16 *pwsName,

unsigned __int16 wType,

unsigned int Flags,

void **ppResultRecords

)

{

#define DNS_QUERY_BYPASS_CACHE 0x08

unsigned int _Flags = Flags;

if(_wcsicmp(name_bypass_hostfile, (const wchar_t *)pwsName) == 0)

{

OutputDebugStringW((LPCWSTR)pwsName);

OutputDebugStringW(L"\n");

_Flags |= DNS_QUERY_BYPASS_CACHE;

}

return g_old_pfnR_ResolverQuery(Handle, pwsName, wType, _Flags, ppResultRecords);

}

void** hook_R_ResolverQuery(void* Base, size_t Limit, void** oldptr, pfnR_ResolverQuery hookptr)

{

void** rs = NULL;

pfnR_ResolverQuery* p_R_ResolverQuery = (pfnR_ResolverQuery*)get_R_ResolverQuery_off(Base, Limit);

if(p_R_ResolverQuery)

{

DWORD lpflOldProtect = 0;

BOOL result = VirtualProtect((void*)p_R_ResolverQuery, sizeof(PVOID),

PAGE_EXECUTE_READWRITE, &lpflOldProtect);

if(result)

{

rs = (void**)p_R_ResolverQuery;

*oldptr = (void*)*p_R_ResolverQuery;

*p_R_ResolverQuery = hookptr;

VirtualProtect((void*)p_R_ResolverQuery, sizeof(PVOID),

lpflOldProtect, &lpflOldProtect);

}

}

return (void**)rs;

}

void unhook_R_ResolverQuery(void** off, void* Oldptr)

{

DWORD lpflOldProtect = 0;

BOOL result = VirtualProtect((void*)off, sizeof(PVOID),

PAGE_EXECUTE_READWRITE, &lpflOldProtect);

if(result)

{

*off = Oldptr;

VirtualProtect((void*)off, sizeof(PVOID),

lpflOldProtect, &lpflOldProtect);

}

}

DWORD WINAPI hook_worker(

LPVOID lpParameter

)

{

if(lpParameter == (PVOID)1)

{

HMODULE hmod = ::GetModuleHandleA("dnsrslvr.dll");

if(hmod)

{

void* oldptr = NULL;

void** off = hook_R_ResolverQuery((void*)hmod, 45568, &oldptr, fake_R_ResolverQuery);

g_old_pfnR_ResolverQuery = (pfnR_ResolverQuery)oldptr;

g_off = off;

}

}else

{

(void)unhook_R_ResolverQuery(g_off, g_old_pfnR_ResolverQuery);

}

return 0;

}

BOOL APIENTRY DllMain( HMODULE hModule,

DWORD  ul_reason_for_call,

LPVOID lpReserved

)

{

//

//DllMain创建线程,只要没任何等待线程的操作就是安全的,不会死锁.

//

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

{

DWORD lpThreadId;

CreateThread(NULL, 0, hook_worker, (PVOID)1, 0, &lpThreadId);

}

break;

case DLL_THREAD_ATTACH:

break;

case DLL_THREAD_DETACH:

break;

case DLL_PROCESS_DETACH:

{

//

//暴力卸载是不安全的.

//

DWORD lpThreadId;

CreateThread(NULL, 0, hook_worker, (PVOID)0, 0, &lpThreadId);

}

break;

}

return TRUE;

}

绕过本机DNS缓存的更多相关文章

  1. 查看和清除本机DNS缓存记录

    Windows上查看和清除本机DNS缓存记录: ipconfig /displaydns  查看ipconfig /flushdns  清除 貌似Time To Live的单位是秒.

  2. 如何清除本机DNS缓存

    如何清除本机DNS缓存 在实际应用过程中可能会遇到DNS解析错误的问题,就是说当我们访问一个域名时无法完成将其 解析到IP地址的工作,而直接输入网站IP却可以正常访问,这就是因为DNS解析出现故障造成 ...

  3. windows刷新本机DNS缓存

    ipconfig /flushdns

  4. Vista/Win7以上系统查看和清除本地DNS缓存新方法

    你是否因修改网站DNS解析后,却因本机DNS缓存而需要等待... 你是否遇到修改了本机的hosts文件后,必须重起firefox和ie才起作用... 其实只要清空DNS缓存这些问题都可以解决. 查看D ...

  5. 利用DNS缓存和TLS协议将受限SSRF变为通用SSRF

    本文首发于先知社区 前言 这是今年BlackHat上的一个议题:When TLS Hacks You,作者是latacora的Joshua Maddux 议题提出了一个新的ssrf攻击思路,利用DNS ...

  6. 刷新DNS命令 如何刷新DNS缓存(flushdns)

    运行:ipconfig /displaydns这个命令,查看一下本机已经缓存了那些的dns信息的,然后输入下面的命令 ipconfig /flushdns               这时本机的dns ...

  7. 如何清除DNS缓存,使用cmd命令清理DNS缓存方法

    如何清除DNS缓存,使用cmd命令清理DNS缓存方法 有时候电脑突然上不了网,或者存在某些网站打不开的情况,但别的网站又可以打开,解决办法需要清除DNS缓存,那么如何清除DNS缓存呢,最常用的方法就是 ...

  8. 一次dns缓存引发的惨案

    时间2015年的某个周六凌晨5点,公司官方的QQ群有用户反馈官网打不开了,但有的用户反馈可以打开,客服爬起来自己用电脑试了一下没有问题,就给客户反馈说,可能是自己网络的问题,请过会在试试.早点8点,越 ...

  9. dns缓存刷新时间是多久?dns本地缓存时间介绍

    原文: http://www.winwin7.com/JC/4742.html dns缓存刷新时间是多久?一般来说,我们只知道DNS解析是互联网绝大多数应用的实际寻址方式,在我们打开某站点,DNS返回 ...

随机推荐

  1. windows下监控进程的脚本

    相信大家都有这样的需求,某程序(进程)在运行的时候可能挂掉,需要去监控该程序,并在它挂掉的时候重启之,确保该程序能一直运行.比如土net就经常挂,需要监控程序去监控.Linux下面似乎有守护进程的概念 ...

  2. 【shell脚本】$ 在shell脚本中的使用

    shell脚本中 '$' 与不同的符号搭配其表示的意义也会不同 特殊标志符 含义 $0 当前脚本的文件名 $n 传递给脚本或函数的参数.n 是一个数字,表示第几个参数. 例如,第一个参数是$1,第二个 ...

  3. K2 BPM_K2受邀出席QAD 2019年亚太区用户大会_全业务流程管理专家

    6月12-13日,K2受邀参加了以“云聚创新,智造未来”为主题的QAD 2019年亚太区用户大会.会议上K2同与会嘉宾们共商制造业数字化转型,就如何用流程赋能企业实现智能制造进行了精彩分享. 近期发布 ...

  4. python自定义小工具:密码匿名化、毫秒时间显示、人类易读字节

    import base64 import time def timestamp2datems(timestamp): ''' 时间戳转为日期字串,精确到ms.单位s :param timestamp: ...

  5. MySQL基础部分(一)

    一.MySQL简介 1.什么是数据库 ? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,它产生于距今六十多年前,随着信息技术和市场的发展,特别是二十世纪九十年代以后,数据管理不 ...

  6. 【问题】XShell连接不上Debian root用户

    类似文章:https://www.lianst.com/3231.html 修改此文件 重启ssh服务 ssh restart有问题,换一条命令OK 你的Linux发行版可能不一样,针对CentOS参 ...

  7. 学习使用Django一 安装虚拟环境

    以上环境可以先在虚拟机上操作,熟练之后再正式机操作!!! 再学习Djangj之前,先讲个小概念,虚拟环境     记得刚刚开始学习Python的时候,往往是用的那个包,就Cmd 上 直接输入“pip ...

  8. CentOS6.9 Python环境配置(python2.7、pip、virtualenv)

    python2.7 yum install -y zlib zlib-devel openssl openssl-devel mysql-devel gcc gcc-c++ wget https:// ...

  9. glPixelStorei 详解 包括像素传输

    3.glPixelStore 像glPixelStorei(GL_PACK_ALIGNMENT, 1)这样的调用,通常会用于像素传输(PACK/UNPACK)的场合.尤其是导入纹理(glTexImag ...

  10. 关闭安装包更新使用YUM在Linux中(RHEL / CentOS / Fedora)

    YUM (Yellowdog Updater Modified)  是一个开源的命令行工具,以及基于图形的软件包管理工具, 用于基于 RPM (RedHat Package Manager) 的 Li ...