zoukankan      html  css  js  c++  java
  • 高级全局API钩取

    @author: dlive

    @date: 2017/02/14

    0x01 调试IE进程

    常见网络连接库:ws2_32.dll(套接字),wininet.dll,winhttp.dll

    使用Process Explorer查看IE加载的DLL

    IE不仅加载了ws2_32.dll还加载了wininet.dll,wininet.dll中提供的API中有个名为InternetConnect()的API,这个API用来连接网站。

    HINTERNET InternetConnect(
      _In_ HINTERNET     hInternet,
      _In_ LPCTSTR       lpszServerName,
      _In_ INTERNET_PORT nServerPort,
      _In_ LPCTSTR       lpszUsername,
      _In_ LPCTSTR       lpszPassword,
      _In_ DWORD         dwService,
      _In_ DWORD         dwFlags,
      _In_ DWORD_PTR     dwContext
    );	
    

    使用OD附加IE进程,但是发现IE有两个进程,不知道该附加哪个,那就都附加上。

    在wininet!InternetConnect起始处下断点,使用IE访问www.zhihu.com

    可以看到OD断在InternetConnect函数开始处,修改栈上的www.zhihu.com为www.163.com,然后去掉断点

    可以看到最后访问的网站是www.163.com

    0x02 IE的进程结构

    IE的每个选项卡对应一个进程,统一由一个父进程管理。所以钩取API时需要使用全局钩取。

    这里通过钩取ntdll!ZwResumeThread钩取子进程

    0x03 全局钩取ntdll!ResumeThread API

    因为最终目的是控制IE的网络连接,所以dll注入时仅需向所有的iexplore.exe进程中注入即可,无需对其他无关进程注入dll。

    1.DllMain

    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
        char            szCurProc[MAX_PATH] = {0,};
        char            *p = NULL;
    
        switch( fdwReason )
        {
            case DLL_PROCESS_ATTACH : 
                DebugLog("DllMain() : DLL_PROCESS_ATTACH
    ");
    
                GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
                p = strrchr(szCurProc, '\');
                if( (p != NULL) && !_stricmp(p+1, "iexplore.exe") )
                {
                    DebugLog("DllMain() : current process is [iexplore.exe]
    ");
    
                    //为了防止在Dll注入时wininet.dll还未被加载,所以手动加载一下wininet.dll
                    if( NULL == LoadLibrary(L"wininet.dll") )
                    {
                        DebugLog("DllMain() : LoadLibrary() failed!!! [%d]
    ",
                                 GetLastError());
                    }
                }
    
                // hook
                hook_by_code("ntdll.dll", "ZwResumeThread", 
                             (PROC)NewZwResumeThread, g_pZWRT);
                hook_by_code("wininet.dll", "InternetConnectW", 
                             (PROC)NewInternetConnectW, g_pICW);
                break;
    
            case DLL_PROCESS_DETACH :
                DebugLog("DllMain() : DLL_PROCESS_DETACH
    ");
    
                // unhook
                unhook_by_code("ntdll.dll", "ZwResumeThread", 
                               g_pZWRT);
                unhook_by_code("wininet.dll", "InternetConnectW", 
                               g_pICW);
                break;
        }
    
        return TRUE;
    }
    

    2.NewInternetConnectW

    HINTERNET WINAPI NewInternetConnectW
    (
        HINTERNET hInternet,
        LPCWSTR lpszServerName,
        INTERNET_PORT nServerPort,
        LPCTSTR lpszUsername,
        LPCTSTR lpszPassword,
        DWORD dwService,
        DWORD dwFlags,
        DWORD_PTR dwContext
    )
    {
        HINTERNET hInt = NULL;
        FARPROC pFunc = NULL;
        HMODULE hMod = NULL;
    
        // unhook
        if( !unhook_by_code("wininet.dll", "InternetConnectW", g_pICW) )
        {
            DebugLog("NewInternetConnectW() : unhook_by_code() failed!!!
    ");
            return NULL;
        }
    
        // call original API
        hMod = GetModuleHandle(L"wininet.dll");
        if( hMod == NULL )
        {
            DebugLog("NewInternetConnectW() : GetModuleHandle() failed!!! [%d]
    ",
                      GetLastError());
            goto __INTERNETCONNECT_EXIT;
        }
    
        pFunc = GetProcAddress(hMod, "InternetConnectW");
        if( pFunc == NULL )
        {
            DebugLog("NewInternetConnectW() : GetProcAddress() failed!!! [%d]
    ",
                      GetLastError());
            goto __INTERNETCONNECT_EXIT;
        }
    	
      	//修改原API调用时的第二个参数
        if( !_tcsicmp(lpszServerName, L"www.naver.com") ||
            !_tcsicmp(lpszServerName, L"www.daum.net") ||
            !_tcsicmp(lpszServerName, L"www.nate.com") || 
            !_tcsicmp(lpszServerName, L"www.yahoo.com") )
        {
            DebugLog("[redirect] naver, daum, nate, yahoo => reversecore
    ");
            hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet,
                                               L"www.reversecore.com",
                                               nServerPort,
                                               lpszUsername,
                                               lpszPassword,
                                               dwService,
                                               dwFlags,
                                               dwContext);
        }
        else
        {
            DebugLog("[no redirect]
    ");
            hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet,
                                               lpszServerName,
                                               nServerPort,
                                               lpszUsername,
                                               lpszPassword,
                                               dwService,
                                               dwFlags,
                                               dwContext);
        }
    
    __INTERNETCONNECT_EXIT:
    
        // hook
        if( !hook_by_code("wininet.dll", "InternetConnectW", 
                          (PROC)NewInternetConnectW, g_pICW) )
        {
            DebugLog("NewInternetConnectW() : hook_by_code() failed!!!
    ");
        }
        
        return hInt;
    }
    

    3.NewZwResumeThread

    //ThreadHandle是要恢复运行的线程的句柄(即子进程的主线程)
    NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle, PULONG SuspendCount)
    {
        NTSTATUS status, statusThread;
        FARPROC pFunc = NULL, pFuncThread = NULL;
        DWORD dwPID = 0;
    	static DWORD dwPrevPID = 0;
        THREAD_BASIC_INFORMATION tbi;
        HMODULE hMod = NULL;
        TCHAR szModPath[MAX_PATH] = {0,};
    
        DebugLog("NewZwResumeThread() : start!!!
    ");
    
        hMod = GetModuleHandle(L"ntdll.dll");
        if( hMod == NULL )
        {
            DebugLog("NewZwResumeThread() : GetModuleHandle() failed!!! [%d]
    ",
                      GetLastError());
            return NULL;
        }
    
      	// 调用ntdll!ZwQueryInformationThread(),通过线程句柄获取其对应进程PID
        pFuncThread = GetProcAddress(hMod, "ZwQueryInformationThread");
        if( pFuncThread == NULL )
        {
            DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]
    ",
                      GetLastError());
            return NULL;
        }
    
        statusThread = ((PFZWQUERYINFORMATIONTHREAD)pFuncThread)
                       (ThreadHandle, 0, &tbi, sizeof(tbi), NULL);
        if( statusThread != STATUS_SUCCESS )
        {
            DebugLog("NewZwResumeThread() : pFuncThread() failed!!! [%d]
    ", 
                     GetLastError());
            return NULL;
        }
    	
      	//子进程PID
        dwPID = (DWORD)tbi.ClientId.UniqueProcess;
        if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) )
        {
            DebugLog("NewZwResumeThread() => call InjectDll()
    ");
    
            dwPrevPID = dwPID;
    
            // change privilege
          	// 打开SeDebugPrivilege特权
           	if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
                DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!
    ");
    
          	// 获取要注入的dll的路径
            GetModuleFileName(GetModuleHandle(STR_MODULE_NAME), 
                              szModPath, 
                              MAX_PATH);
    		// 注入dll
            if( !InjectDll(dwPID, szModPath) )
                DebugLog("NewZwResumeThread() : InjectDll(%d) failed!!!
    ", dwPID);
        }
    
        // call ntdll!ZwResumeThread()
        if( !unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT) )
        {
            DebugLog("NewZwResumeThread() : unhook_by_code() failed!!!
    ");
            return NULL;
        }
    
        pFunc = GetProcAddress(hMod, "ZwResumeThread");
        if( pFunc == NULL )
        {
            DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]
    ",
                      GetLastError());
            goto __NTRESUMETHREAD_END;
        }
    
        status = ((PFZWRESUMETHREAD)pFunc)(ThreadHandle, SuspendCount);
        if( status != STATUS_SUCCESS )
        {
            DebugLog("NewZwResumeThread() : pFunc() failed!!! [%d]
    ", GetLastError());
            goto __NTRESUMETHREAD_END;
        }
    
    __NTRESUMETHREAD_END:
    
        if( !hook_by_code("ntdll.dll", "ZwResumeThread", 
                          (PROC)NewZwResumeThread, g_pZWRT) )
        {
            DebugLog("NewZwResumeThread() : hook_by_code() failed!!!
    ");
        }
    
        DebugLog("NewZwResumeThread() : end!!!
    ");
    
        return status;
    }
    
  • 相关阅读:
    http2新特性
    SSL/TLS工作原理
    https工作原理解析
    k8s认证与鉴权
    grpc
    golang channel是线程安全的吗
    golang map是线程安全的吗
    k8s创建deployment的工作流
    Docker实践:部署漏洞扫描 AWVS + Nessus
    Python Peewee
  • 原文地址:https://www.cnblogs.com/dliv3/p/6398973.html
Copyright © 2011-2022 走看看