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;
    }
    
  • 相关阅读:
    PAT Advanced 1067 Sort with Swap(0, i) (25分)
    PAT Advanced 1048 Find Coins (25分)
    PAT Advanced 1060 Are They Equal (25分)
    PAT Advanced 1088 Rational Arithmetic (20分)
    PAT Advanced 1032 Sharing (25分)
    Linux的at命令
    Sublime Text3使用指南
    IntelliJ IDEA创建第一个Groovy工程
    Sublime Text3 安装ftp插件
    Sublime Text3配置Groovy运行环境
  • 原文地址:https://www.cnblogs.com/dliv3/p/6398973.html
Copyright © 2011-2022 走看看