逆向工程核心原理读书笔记-API钩取之IE浏览器连接控制

来源:互联网 发布:sql2000数据库快速备份 编辑:程序博客网 时间:2024/05/21 15:06

我们通过一个示例来练习钩取IE8的InternetConnect函数,用IE8连接指定网站时,使之连接到另一个网站。和以前钩取CreateProcess不同,这次我们钩取更低级的ZwResumeThread来实现全局API钩取。


我们来分析一下源代码,看看是怎么实现的。
InjDll.cpp源代码与DLL注入的代码基本结构类似。

// InjDll.cpp// reversecore@gmail.com// www.reversecore.com#include "windows.h"#include "stdio.h"#include "tlhelp32.h"#include "io.h"#include "tchar.h"enum {INJECTION_MODE = 0, EJECTION_MODE};BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,               &hToken) )    {        _tprintf(L"OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system                              lpszPrivilege,  // privilege to lookup                               &luid) )        // receives LUID of privilege    {        _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        _tprintf(L"The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL IsVistaLater(){    OSVERSIONINFO osvi;    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    GetVersionEx(&osvi);    if( osvi.dwMajorVersion >= 6 )        return TRUE;    return FALSE;}typedef DWORD (WINAPI *PFNTCREATETHREADEX)(     PHANDLE                 ThreadHandle,    ACCESS_MASK             DesiredAccess,    LPVOID                  ObjectAttributes,    HANDLE                  ProcessHandle,    LPTHREAD_START_ROUTINE  lpStartAddress,    LPVOID                  lpParameter,    BOOL                CreateSuspended,    DWORD                   dwStackSize,    DWORD                   dw1,     DWORD                   dw2,     LPVOID                  Unknown ); BOOL MyCreateRemoteThread(    HANDLE hProcess,     LPTHREAD_START_ROUTINE pThreadProc,     LPVOID pRemoteBuf){    HANDLE      hThread = NULL;    FARPROC     pFunc = NULL;    if( IsVistaLater() )    // Vista, 7, Server2008    {        pFunc = GetProcAddress(GetModuleHandle(L"ntdll.dll"),                                "NtCreateThreadEx");        if( pFunc == NULL )        {            _tprintf(L"MyCreateRemoteThread() : "\                     L"GetProcAddress(\"NtCreateThreadEx\") failed!!! [%d]\n",                      GetLastError());            return FALSE;        }        ((PFNTCREATETHREADEX)pFunc)(&hThread,                                    0x1FFFFF,                                    NULL,                                    hProcess,                                    pThreadProc,                                    pRemoteBuf,                                    FALSE,                                    NULL,                                    NULL,                                    NULL,                                    NULL);        if( hThread == NULL )        {            _tprintf(L"MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]\n",                       GetLastError());            return FALSE;        }    }    else                    // 2000, XP, Server2003    {        hThread = CreateRemoteThread(hProcess, NULL, 0,                                      pThreadProc, pRemoteBuf, 0, NULL);        if( hThread == NULL )        {            _tprintf(L"MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]\n",                      GetLastError());            return FALSE;        }    }if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )    {        _tprintf(L"MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]\n",                  GetLastError());        return FALSE;    }    return TRUE;}LPCTSTR GetProcName(DWORD dwPID){HANDLE                  hSnapshot = INVALID_HANDLE_VALUE;PROCESSENTRY32          pe;    BOOL                    bMore = FALSE;// Get the snapshot of the systempe.dwSize = sizeof(PROCESSENTRY32);hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);    if( hSnapshot == INVALID_HANDLE_VALUE )    {        _tprintf(L"GetProcName() : CreateToolhelp32Snapshot() failed!!! [%d]",                   GetLastError());        return NULL;    }// find processbMore = Process32First(hSnapshot, &pe);for( ; bMore; bMore = Process32Next(hSnapshot, &pe) ){if( dwPID == pe.th32ProcessID )        {        CloseHandle(hSnapshot);            return pe.szExeFile;        }}CloseHandle(hSnapshot);    return NULL;}BOOL CheckDllInProcess(DWORD dwPID, LPCTSTR szDllPath){BOOL                    bMore = FALSE;HANDLE                  hSnapshot = INVALID_HANDLE_VALUE;MODULEENTRY32           me = { sizeof(me), };if( INVALID_HANDLE_VALUE ==         (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )    {        _tprintf(L"CheckDllInProcess() : CreateToolhelp32Snapshot(%d) failed!!! [%d]\n",                  dwPID, GetLastError());        return FALSE;    }bMore = Module32First(hSnapshot, &me);for( ; bMore ; bMore = Module32Next(hSnapshot, &me) ){if( !_tcsicmp(me.szModule, szDllPath) ||             !_tcsicmp(me.szExePath, szDllPath) )        {            CloseHandle(hSnapshot);return TRUE;        }}    CloseHandle(hSnapshot);    return FALSE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){HANDLE                  hProcess = NULL;    HANDLE                  hThread = NULL;LPVOID                  pRemoteBuf = NULL;DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);LPTHREAD_START_ROUTINE  pThreadProc = NULL;    BOOL                    bRet = FALSE;    HMODULE                 hMod = NULL;    DWORD                   dwDesiredAccess = 0;    TCHAR                   szProcName[MAX_PATH] = {0,};    dwDesiredAccess = PROCESS_ALL_ACCESS;    //dwDesiredAccess = MAXIMUM_ALLOWED;if ( !(hProcess = OpenProcess(dwDesiredAccess, FALSE, dwPID)) )    {        _tprintf(L"InjectDll() : OpenProcess(%d) failed!!! [%d]\n",                   dwPID, GetLastError());goto INJECTDLL_EXIT;    }pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    if( pRemoteBuf == NULL )    {        _tprintf(L"InjectDll() : VirtualAllocEx() failed!!! [%d]\n",                   GetLastError());        goto INJECTDLL_EXIT;    }if( !WriteProcessMemory(hProcess, pRemoteBuf,                            (LPVOID)szDllPath, dwBufSize, NULL) )    {        _tprintf(L"InjectDll() : WriteProcessMemory() failed!!! [%d]\n",                  GetLastError());        goto INJECTDLL_EXIT;    }    hMod = GetModuleHandle(L"kernel32.dll");    if( hMod == NULL )    {        _tprintf(L"InjectDll() : GetModuleHandle(\"kernel32.dll\") failed!!! [%d]\n",                  GetLastError());        goto INJECTDLL_EXIT;    }pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");    if( pThreadProc == NULL )    {        _tprintf(L"InjectDll() : GetProcAddress(\"LoadLibraryW\") failed!!! [%d]\n",                   GetLastError());        goto INJECTDLL_EXIT;    }    if( !MyCreateRemoteThread(hProcess, pThreadProc, pRemoteBuf) )    {        _tprintf(L"InjectDll() : MyCreateRemoteThread() failed!!!\n");        goto INJECTDLL_EXIT;    }    bRet = CheckDllInProcess(dwPID, szDllPath);INJECTDLL_EXIT:    wsprintf(szProcName, L"%s", GetProcName(dwPID));    if( szProcName[0] == '\0' )        _tcscpy_s(szProcName, L"(no_process)");    _tprintf(L"%s(%d) %s!!! [%d]\n", szProcName, dwPID, bRet ? L"SUCCESS" : L"-->> FAILURE", GetLastError());    if( pRemoteBuf )        VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    if( hThread )    CloseHandle(hThread);    if( hProcess )    CloseHandle(hProcess);return bRet;}BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath){BOOL                    bMore = FALSE, bFound = FALSE, bRet = FALSE;HANDLE                  hSnapshot = INVALID_HANDLE_VALUE;    HANDLE                  hProcess = NULL;    HANDLE                  hThread = NULL;MODULEENTRY32           me = { sizeof(me), };LPTHREAD_START_ROUTINE  pThreadProc = NULL;    HMODULE                 hMod = NULL;    DWORD                   dwDesiredAccess = 0;    TCHAR                   szProcName[MAX_PATH] = {0,};if( INVALID_HANDLE_VALUE ==         (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )    {        _tprintf(L"EjectDll() : CreateToolhelp32Snapshot(%d) failed!!! [%d]\n",                  dwPID, GetLastError());        goto EJECTDLL_EXIT;    }bMore = Module32First(hSnapshot, &me);for( ; bMore ; bMore = Module32Next(hSnapshot, &me) ){if( !_tcsicmp(me.szModule, szDllPath) ||             !_tcsicmp(me.szExePath, szDllPath) ){bFound = TRUE;break;}}if( !bFound ){        _tprintf(L"EjectDll() : There is not %s module in process(%d) memory!!!\n",                   szDllPath, dwPID);        goto EJECTDLL_EXIT;}    dwDesiredAccess = PROCESS_ALL_ACCESS;if( !(hProcess = OpenProcess(dwDesiredAccess, FALSE, dwPID)) ){_tprintf(L"EjectDll() : OpenProcess(%d) failed!!! [%d]\n",                   dwPID, GetLastError());goto EJECTDLL_EXIT;}    hMod = GetModuleHandle(L"kernel32.dll");    if( hMod == NULL )    {        _tprintf(L"EjectDll() : GetModuleHandle(\"kernel32.dll\") failed!!! [%d]\n",                   GetLastError());        goto EJECTDLL_EXIT;    }pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "FreeLibrary");    if( pThreadProc == NULL )    {        _tprintf(L"EjectDll() : GetProcAddress(\"FreeLibrary\") failed!!! [%d]\n",                   GetLastError());        goto EJECTDLL_EXIT;    }    if( !MyCreateRemoteThread(hProcess, pThreadProc, me.modBaseAddr) )    {        _tprintf(L"EjectDll() : MyCreateRemoteThread() failed!!!\n");        goto EJECTDLL_EXIT;    }    bRet = TRUE;EJECTDLL_EXIT:    _tcscpy_s(szProcName, GetProcName(dwPID));    _tprintf(L"%s(%d) %s!!! [%d]\n", szProcName, dwPID, bRet ? L"SUCCESS" : L"-->> FAILURE", GetLastError());    if( hThread )        CloseHandle(hThread);    if( hProcess )        CloseHandle(hProcess);    if( hSnapshot != INVALID_HANDLE_VALUE )        CloseHandle(hSnapshot);return bRet;}BOOL InjectDllToAll(int nMode, LPCTSTR szDllPath){DWORD                   dwPID = 0;HANDLE                  hSnapShot = INVALID_HANDLE_VALUE;PROCESSENTRY32          pe;    BOOL                    bMore = FALSE;// Get the snapshot of the systempe.dwSize = sizeof(PROCESSENTRY32);hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);    if( hSnapShot == INVALID_HANDLE_VALUE )    {        _tprintf(L"InjectDllToAll() : CreateToolhelp32Snapshot() failed!!! [%d]",                   GetLastError());        return FALSE;    }// find processbMore = Process32First(hSnapShot, &pe);for( ; bMore; bMore = Process32Next(hSnapShot, &pe) ){dwPID = pe.th32ProcessID;        if( dwPID < 100 ||            !_tcsicmp(pe.szExeFile, L"smss.exe") ||            !_tcsicmp(pe.szExeFile, L"csrss.exe") )        {            _tprintf(L"%s(%d) => System Process... DLL %s is impossible!\n",                    pe.szExeFile, dwPID, nMode==INJECTION_MODE ? L"Injection" : L"Ejection");            continue;        }        if( nMode == INJECTION_MODE )    InjectDll(dwPID, szDllPath);        else            EjectDll(dwPID, szDllPath);}CloseHandle(hSnapShot);return TRUE;}BOOL InjectDllToOne(LPCTSTR szProc, int nMode, LPCTSTR szDllPath){    int                     i = 0, nLen = (int)_tcslen(szProc);DWORD                   dwPID = 0;HANDLE                  hSnapShot = INVALID_HANDLE_VALUE;PROCESSENTRY32          pe;    BOOL                    bMore = FALSE;    // check if ProcName or PID    for(i = 0; i < nLen; i++)        if( !_istdigit(szProc[i]) )            break;    if( i == nLen )     // PID    {        dwPID = (DWORD)_tstol(szProc);                if( nMode == INJECTION_MODE )            InjectDll(dwPID, szDllPath);        else            EjectDll(dwPID, szDllPath);    }    else                // ProcName    {        // Get the snapshot of the system    pe.dwSize = sizeof(PROCESSENTRY32);    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);        if( hSnapShot == INVALID_HANDLE_VALUE )        {            _tprintf(L"InjectDllToOne() : CreateToolhelp32Snapshot() failed!!! [%d]",                       GetLastError());            return FALSE;        }    // find process    bMore = Process32First(hSnapShot, &pe);    for( ; bMore; bMore = Process32Next(hSnapShot, &pe) )    {    dwPID = pe.th32ProcessID;           if( dwPID < 100 )    continue;            if( !_tcsicmp(pe.szExeFile, szProc) )            {                if( nMode == INJECTION_MODE )            InjectDll(dwPID, szDllPath);                else                    EjectDll(dwPID, szDllPath);            }    }    CloseHandle(hSnapShot);    }    return TRUE;}BOOL Initialize(LPCTSTR szOption, LPCTSTR szDllPath){    // check Option (Injection/Ejection)    if( _tcsicmp(szOption, L"-i") &&        _tcsicmp(szOption, L"-e") )        return FALSE;    // check DLL Pathif( _taccess(szDllPath, 0) == -1 )        return FALSE;    return TRUE;}int _tmain(int argc, TCHAR *argv[]){    #define BUFSIZE         (1024)    int     nMode           = INJECTION_MODE;    TCHAR   szPath[BUFSIZE]   = L"";     if( (argc != 4) ||         ( _tcsicmp(argv[2], L"-i") && _tcsicmp(argv[2], L"-e")) ){    _tprintf(L"\n %s (Ver 1.1.1) - Dll Injection/Ejection Utility!!!\n"\                 L"   www.reversecore.com\n"\                 L"   reversecore@gmail.com\n"\                 L"\n USAGE  : %s <procname|pid|*> <-i|-e> <dll path>\n\n",                  argv[0], argv[0]);return 1;}        if( !GetFullPathName(argv[3], BUFSIZE, szPath, NULL) )        {        _tprintf(L"GetFullPathName() failed! [%d]", GetLastError());        return 1;    }    // check DLL Pathif( _taccess(szPath, 0) == -1 )    {        _tprintf(L"There is no \"%s\" file!\n", szPath);        return FALSE;    }// change privilegeif( !SetPrivilege(SE_DEBUG_NAME, TRUE) )        return 1;    // Mode (Injection/Ejection)    if( !_tcsicmp(argv[2], L"-e") )        nMode = EJECTION_MODE;    // Inject Dll    if( !_tcsicmp(argv[1], L"*") )        InjectDllToAll(nMode, szPath);    else        InjectDllToOne(argv[1], nMode, szPath);return 0;}
下面详细讲解redirect.dll的源代码(redirect.cpp)。
DLLMain的代码非常简单。若模块未加载就钩取其内部API,将导致失败。为防止出现这类问题,进程为iexplore.exe时,钩取InternetConnectW之前必须加载wininet.dll文件。
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\n");            GetModuleFileNameA(NULL, szCurProc, MAX_PATH);            p = strrchr(szCurProc, '\\');            if( (p != NULL) && !_stricmp(p+1, "iexplore.exe") )            {                DebugLog("DllMain() : current process is [iexplore.exe]\n");                // 钩取wininet!InternetConnectW() API之前                // 预先加载wininet.dll                if( NULL == LoadLibrary(L"wininet.dll") )                {                    DebugLog("DllMain() : LoadLibrary() failed!!! [%d]\n",                             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\n");            // unhook            unhook_by_code("ntdll.dll", "ZwResumeThread",                            g_pZWRT);            unhook_by_code("wininet.dll", "InternetConnectW",                            g_pICW);            break;    }    return TRUE;}
下面看看NewInternetConnect函数。函数的第二个参数lpszServerName字符串即是要连接的网站地址。监视该连接地址,IE连接特定网站时,就把连接地址修改为www.reversecore.com。
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!!!\n");        return NULL;    }    // call original API    hMod = GetModuleHandle(L"wininet.dll");    if( hMod == NULL )    {        DebugLog("NewInternetConnectW() : GetModuleHandle() failed!!! [%d]\n",                  GetLastError());        goto __INTERNETCONNECT_EXIT;    }    pFunc = GetProcAddress(hMod, "InternetConnectW");    if( pFunc == NULL )    {        DebugLog("NewInternetConnectW() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        goto __INTERNETCONNECT_EXIT;    }    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\n");        hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet,                                           L"www.reversecore.com",                                           nServerPort,                                           lpszUsername,                                           lpszPassword,                                           dwService,                                           dwFlags,                                           dwContext);    }    else    {        DebugLog("[no redirect]\n");        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!!!\n");    }        return hInt;}
接下来分析NewZwResumeThread函数,它用来对ZwResumeThread进行全局钩取。先调用ZwQueryInformationThread获取子进程的PID,然后使用该PID注入redirect.dll文件,最后正常调用ZwResumeThread将子进程的主线程恢复运行。
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!!!\n");    hMod = GetModuleHandle(L"ntdll.dll");    if( hMod == NULL )    {        DebugLog("NewZwResumeThread() : GetModuleHandle() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    // call ntdll!ZwQueryInformationThread()    pFuncThread = GetProcAddress(hMod, "ZwQueryInformationThread");    if( pFuncThread == NULL )    {        DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    statusThread = ((PFZWQUERYINFORMATIONTHREAD)pFuncThread)                   (ThreadHandle, 0, &tbi, sizeof(tbi), NULL);    if( statusThread != STATUS_SUCCESS )    {        DebugLog("NewZwResumeThread() : pFuncThread() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    dwPID = (DWORD)tbi.ClientId.UniqueProcess;    if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) )    {        DebugLog("NewZwResumeThread() => call InjectDll()\n");        dwPrevPID = dwPID;        // change privilege       if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )            DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!\n");        // get injection dll path        GetModuleFileName(GetModuleHandle(STR_MODULE_NAME),                           szModPath,                           MAX_PATH);        if( !InjectDll(dwPID, szModPath) )            DebugLog("NewZwResumeThread() : InjectDll(%d) failed!!!\n", dwPID);    }    // call ntdll!ZwResumeThread()    if( !unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT) )    {        DebugLog("NewZwResumeThread() : unhook_by_code() failed!!!\n");        return NULL;    }    pFunc = GetProcAddress(hMod, "ZwResumeThread");    if( pFunc == NULL )    {        DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        goto __NTRESUMETHREAD_END;    }    status = ((PFZWRESUMETHREAD)pFunc)(ThreadHandle, SuspendCount);    if( status != STATUS_SUCCESS )    {        DebugLog("NewZwResumeThread() : pFunc() failed!!! [%d]\n", GetLastError());        goto __NTRESUMETHREAD_END;    }__NTRESUMETHREAD_END:    if( !hook_by_code("ntdll.dll", "ZwResumeThread",                       (PROC)NewZwResumeThread, g_pZWRT) )    {        DebugLog("NewZwResumeThread() : hook_by_code() failed!!!\n");    }    DebugLog("NewZwResumeThread() : end!!!\n");    return status;}

完整的代码如下。

// redirect.cpp#include "windows.h"#include "wininet.h"#include "stdio.h"#include "tchar.h"#define STR_MODULE_NAME    (L"redirect.dll")#define STATUS_SUCCESS(0x00000000L) typedef LONG NTSTATUS;typedef struct _CLIENT_ID {HANDLE UniqueProcess;HANDLE UniqueThread;} CLIENT_ID;typedef struct _THREAD_BASIC_INFORMATION {NTSTATUS ExitStatus;PVOID TebBaseAddress;CLIENT_ID ClientId;ULONG AffinityMask;LONG Priority;LONG BasePriority;} THREAD_BASIC_INFORMATION;typedef NTSTATUS (WINAPI *PFZWRESUMETHREAD)(    HANDLE ThreadHandle,     PULONG SuspendCount);typedef NTSTATUS (WINAPI *PFZWQUERYINFORMATIONTHREAD)(    HANDLE ThreadHandle,     ULONG ThreadInformationClass,     PVOID ThreadInformation,     ULONG ThreadInformationLength,     PULONG ReturnLength);typedef HINTERNET (WINAPI *PFINTERNETCONNECTW)(    HINTERNET hInternet,    LPCWSTR lpszServerName,    INTERNET_PORT nServerPort,    LPCTSTR lpszUsername,    LPCTSTR lpszPassword,    DWORD dwService,    DWORD dwFlags,    DWORD_PTR dwContext);BYTE g_pZWRT[5] = {0,};BYTE g_pICW[5] = {0,};void DebugLog(const char *format, ...){va_list vl;FILE *pf = NULL;char szLog[512] = {0,};va_start(vl, format);wsprintfA(szLog, format, vl);va_end(vl);    OutputDebugStringA(szLog);}BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,               &hToken) )    {        DebugLog("OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,             // lookup privilege on local system                              lpszPrivilege,    // privilege to lookup                               &luid) )          // receives LUID of privilege    {        DebugLog("LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         DebugLog("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        DebugLog("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes){FARPROC pFunc = NULL;DWORD dwOldProtect = 0, dwAddress = 0;BYTE pBuf[5] = {0xE9, 0, };PBYTE pByte = NULL;    HMODULE hMod = NULL;    hMod = GetModuleHandleA(szDllName);    if( hMod == NULL )    {        DebugLog("hook_by_code() : GetModuleHandle(\"%s\") failed!!! [%d]\n",                  szDllName, GetLastError());        return FALSE;    }pFunc = (FARPROC)GetProcAddress(hMod, szFuncName);    if( pFunc == NULL )    {        DebugLog("hook_by_code() : GetProcAddress(\"%s\") failed!!! [%d]\n",                  szFuncName, GetLastError());        return FALSE;    }pByte = (PBYTE)pFunc;if( pByte[0] == 0xE9 )    {        DebugLog("hook_by_code() : The API is hooked already!!!\n");return FALSE;    }if( !VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect) )    {        DebugLog("hook_by_code() : VirtualProtect(#1) failed!!! [%d]\n", GetLastError());        return FALSE;    }memcpy(pOrgBytes, pFunc, 5);dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;memcpy(&pBuf[1], &dwAddress, 4);memcpy(pFunc, pBuf, 5);if( !VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect) )    {        DebugLog("hook_by_code() : VirtualProtect(#2) failed!!! [%d]\n", GetLastError());        return FALSE;    }return TRUE;}BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes){FARPROC pFunc = NULL;DWORD dwOldProtect = 0;PBYTE pByte = NULL;    HMODULE hMod = NULL;    hMod = GetModuleHandleA(szDllName);    if( hMod == NULL )    {        DebugLog("unhook_by_code() : GetModuleHandle(\"%s\") failed!!! [%d]\n",                  szDllName, GetLastError());        return FALSE;    }pFunc = (FARPROC)GetProcAddress(hMod, szFuncName);    if( pFunc == NULL )    {        DebugLog("unhook_by_code() : GetProcAddress(\"%s\") failed!!! [%d]\n",                  szFuncName, GetLastError());        return FALSE;    }pByte = (PBYTE)pFunc;if( pByte[0] != 0xE9 )    {        DebugLog("unhook_by_code() : The API is unhooked already!!!");        return FALSE;    }if( !VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect) )    {        DebugLog("unhook_by_code() : VirtualProtect(#1) failed!!! [%d]\n", GetLastError());        return FALSE;    }memcpy(pFunc, pOrgBytes, 5);if( !VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect) )    {        DebugLog("unhook_by_code() : VirtualProtect(#2) failed!!! [%d]\n", GetLastError());        return FALSE;    }return TRUE;}BOOL IsVistaLater(){    OSVERSIONINFO osvi;    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    GetVersionEx(&osvi);    if( osvi.dwMajorVersion >= 6 )        return TRUE;    return FALSE;}typedef DWORD (WINAPI *PFNTCREATETHREADEX)(     PHANDLE                 ThreadHandle,    ACCESS_MASK             DesiredAccess,    LPVOID                  ObjectAttributes,    HANDLE                  ProcessHandle,    LPTHREAD_START_ROUTINE  lpStartAddress,    LPVOID                  lpParameter,    BOOL                CreateSuspended,    DWORD                   dwStackSize,    DWORD                   dw1,     DWORD                   dw2,     LPVOID                  Unknown ); BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf){    HANDLE      hThread = NULL;    FARPROC     pFunc = NULL;    if( IsVistaLater() )    // Vista, 7, Server2008    {        pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx");        if( pFunc == NULL )        {            DebugLog("MyCreateRemoteThread() : GetProcAddress() failed!!! [%d]\n",                   GetLastError());            return FALSE;        }        ((PFNTCREATETHREADEX)pFunc)(&hThread,                                    0x1FFFFF,                                    NULL,                                    hProcess,                                    pThreadProc,                                    pRemoteBuf,                                    FALSE,                                    NULL,                                    NULL,                                    NULL,                                    NULL);        if( hThread == NULL )        {            DebugLog("MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]\n", GetLastError());            return FALSE;        }    }    else                    // 2000, XP, Server2003    {        hThread = CreateRemoteThread(hProcess, NULL, 0,                                      pThreadProc, pRemoteBuf, 0, NULL);        if( hThread == NULL )        {            DebugLog("MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]\n", GetLastError());            return FALSE;        }    }if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )    {        DebugLog("MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]\n", GetLastError());        return FALSE;    }    return TRUE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){HANDLE                  hProcess = NULL;    HANDLE                  hThread = NULL;LPVOID                  pRemoteBuf = NULL;    DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);LPTHREAD_START_ROUTINE  pThreadProc = NULL;    BOOL                    bRet = FALSE;    HMODULE                 hMod = NULL;if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )    {        DebugLog("InjectDll() : OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());goto INJECTDLL_EXIT;    }pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    if( pRemoteBuf == NULL )    {        DebugLog("InjectDll() : VirtualAllocEx() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }if( !WriteProcessMemory(hProcess, pRemoteBuf,                            (LPVOID)szDllPath, dwBufSize, NULL) )    {        DebugLog("InjectDll() : WriteProcessMemory() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }    hMod = GetModuleHandle(L"kernel32.dll");    if( hMod == NULL )    {        DebugLog("InjectDll() : GetModuleHandle() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");    if( pThreadProc == NULL )    {        DebugLog("InjectDll() : GetProcAddress() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }    if( !MyCreateRemoteThread(hProcess, pThreadProc, pRemoteBuf) )    {        DebugLog("InjectDll() : MyCreateRemoteThread() failed!!!\n");        goto INJECTDLL_EXIT;    }    bRet = TRUE;INJECTDLL_EXIT:    if( pRemoteBuf )        VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    if( hThread )    CloseHandle(hThread);    if( hProcess )    CloseHandle(hProcess);return bRet;}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!!!\n");    hMod = GetModuleHandle(L"ntdll.dll");    if( hMod == NULL )    {        DebugLog("NewZwResumeThread() : GetModuleHandle() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    // call ntdll!ZwQueryInformationThread()    pFuncThread = GetProcAddress(hMod, "ZwQueryInformationThread");    if( pFuncThread == NULL )    {        DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    statusThread = ((PFZWQUERYINFORMATIONTHREAD)pFuncThread)                   (ThreadHandle, 0, &tbi, sizeof(tbi), NULL);    if( statusThread != STATUS_SUCCESS )    {        DebugLog("NewZwResumeThread() : pFuncThread() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    dwPID = (DWORD)tbi.ClientId.UniqueProcess;    if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) )    {        DebugLog("NewZwResumeThread() => call InjectDll()\n");        dwPrevPID = dwPID;        // change privilege       if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )            DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!\n");        // get injection dll path        GetModuleFileName(GetModuleHandle(STR_MODULE_NAME),                           szModPath,                           MAX_PATH);        if( !InjectDll(dwPID, szModPath) )            DebugLog("NewZwResumeThread() : InjectDll(%d) failed!!!\n", dwPID);    }    // call ntdll!ZwResumeThread()    if( !unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT) )    {        DebugLog("NewZwResumeThread() : unhook_by_code() failed!!!\n");        return NULL;    }    pFunc = GetProcAddress(hMod, "ZwResumeThread");    if( pFunc == NULL )    {        DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        goto __NTRESUMETHREAD_END;    }    status = ((PFZWRESUMETHREAD)pFunc)(ThreadHandle, SuspendCount);    if( status != STATUS_SUCCESS )    {        DebugLog("NewZwResumeThread() : pFunc() failed!!! [%d]\n", GetLastError());        goto __NTRESUMETHREAD_END;    }__NTRESUMETHREAD_END:    if( !hook_by_code("ntdll.dll", "ZwResumeThread",                       (PROC)NewZwResumeThread, g_pZWRT) )    {        DebugLog("NewZwResumeThread() : hook_by_code() failed!!!\n");    }    DebugLog("NewZwResumeThread() : end!!!\n");    return status;}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!!!\n");        return NULL;    }    // call original API    hMod = GetModuleHandle(L"wininet.dll");    if( hMod == NULL )    {        DebugLog("NewInternetConnectW() : GetModuleHandle() failed!!! [%d]\n",                  GetLastError());        goto __INTERNETCONNECT_EXIT;    }    pFunc = GetProcAddress(hMod, "InternetConnectW");    if( pFunc == NULL )    {        DebugLog("NewInternetConnectW() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        goto __INTERNETCONNECT_EXIT;    }    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\n");        hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet,                                           L"www.reversecore.com",                                           nServerPort,                                           lpszUsername,                                           lpszPassword,                                           dwService,                                           dwFlags,                                           dwContext);    }    else    {        DebugLog("[no redirect]\n");        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!!!\n");    }        return hInt;}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\n");            GetModuleFileNameA(NULL, szCurProc, MAX_PATH);            p = strrchr(szCurProc, '\\');            if( (p != NULL) && !_stricmp(p+1, "iexplore.exe") )            {                DebugLog("DllMain() : current process is [iexplore.exe]\n");                // 钩取wininet!InternetConnectW() API之前                // 预先加载wininet.dll                if( NULL == LoadLibrary(L"wininet.dll") )                {                    DebugLog("DllMain() : LoadLibrary() failed!!! [%d]\n",                             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\n");            // unhook            unhook_by_code("ntdll.dll", "ZwResumeThread",                            g_pZWRT);            unhook_by_code("wininet.dll", "InternetConnectW",                            g_pICW);            break;    }    return TRUE;}




0 0
原创粉丝点击