zoukankan      html  css  js  c++  java
  • 绕过本机DNS缓存

    --转载注明来源 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" ");

            _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;

    }

  • 相关阅读:
    辅助随笔:因知识点不足暂时错过的题目
    NOIP2019翻车前写(and 抄)过的代码
    NOIP2019翻车前计划以及日记
    Luogu P3706 [SDOI2017]硬币游戏
    Luogu P5296 [北京省选集训2019]生成树计数
    Luogu P3307 [SDOI2013]项链
    Gaussian整数
    Problem. S
    LOJ6696 复读机 加强版
    数据库约束
  • 原文地址:https://www.cnblogs.com/sysnap/p/4462215.html
Copyright © 2011-2022 走看看