逆向工程核心原理——第三十四章

高级全局API钩取:IE链接控制

在上一章,API钩取虽然成功了,但是重新打开任务管理器,进程又会显示出来。

为了解决这个问题,书本引出了”高级全局API“这个概念。

​ 钩取常规API,我们需要在进程创建时钩取其API:

​ 全局API钩取,则是在创建进程之前就钩取API:

相对于低级API钩取,高级API钩取虽然可以保证效果,但是并不是万能的。

几位下来我们利用实验,进行IE浏览器的全局API钩取:

首先,我们先了解一下IE浏览器(包括现在大部分的浏览器)的选下卡,为了实现这个选项卡功能,IE浏览器使用了父子进程的运行形式(所有的选项卡都是子程序):

因此我们只需要钩取父进程的ntdll!ZwResumeThread()API,那么子程序都会被自动钩取:

cmd显示钩取成功,我们添加新的选项卡,在processxp中查看子程序是否钩取成功:

子程序成功钩取,那么我们输入书上给出的地址,看看选项卡是否可以转跳到我们特定的地址:

(转跳过程太快,只能截图到已经转跳过后的图片)

最后附上代码:

InjDll.cpp

// 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 system  
    pe.dwSize = sizeof(PROCESSENTRY32);
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
    if (hSnapshot == INVALID_HANDLE_VALUE)
    {
        _tprintf(L"GetProcName() : CreateToolhelp32Snapshot() failed!!! [%d]",
            GetLastError());
        return NULL;
    }

    // find process  
    bMore = 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 system  
    pe.dwSize = sizeof(PROCESSENTRY32);
    hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
    if (hSnapShot == INVALID_HANDLE_VALUE)
    {
        _tprintf(L"InjectDllToAll() : CreateToolhelp32Snapshot() failed!!! [%d]",
            GetLastError());
        return FALSE;
    }

    // find process  
    bMore = 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 Path  
    if (_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 Path  
    if (_taccess(szPath, 0) == -1)
    {
        _tprintf(L"There is no \"%s\" file!\n", szPath);
        return FALSE;
    }

    // change privilege  
    if (!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.cpp

// 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;
}

posted @ 2020-10-16 16:00  Kylimi  阅读(123)  评论(0编辑  收藏  举报