hook技术--优化代码hook

.

1.简介

在代码hook中,由于频繁的进行hook和unhook,而且又加上多线程的一些不可靠的因素,会使程序执行效率降低而且可能会导致错误,即

多线程对其hook和unhook导致不稳定的可能性增加, 因此需要找一种不需要频繁进行hook和unhook的方法.

而windows的一些API提供了一种很好的优化方式. 即API代码以mov edi,edi 指令开头,这条执行占了2个字节,而且2个API之间

有5个nop指令,这些nop在一个ret和一个API基址之间,不会被执行到.所以前5个字节可以放下一个远跳转指令,开头2个字节可以存放

一个短跳转指令,通过短跳转指令跳到远跳转指令基址,即可实现hook,然后在hook函数中直接跳转或call到API基址+2的地方执行API.

2.以hook explorer.exe进程的CreateProcessW函数为例, 对于路径中存在qq(不区分大小写)的的进程不予执行的功能的实现

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <Windows.h>
#include <wchar.h>
#include <string.h>
#define FuncName "CreateProcessW"
#define DllName "kernel32.dll"


typedef BOOL (WINAPI *lpCreateProcessW)
(
    __in_opt    LPCWSTR lpApplicationName,
    __inout_opt LPWSTR lpCommandLine,
    __in_opt    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    __in_opt    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in        BOOL bInheritHandles,
    __in        DWORD dwCreationFlags,
    __in_opt    LPVOID lpEnvironment,
    __in_opt    LPCWSTR lpCurrentDirectory,
    __in        LPSTARTUPINFOW lpStartupInfo,
    __out       LPPROCESS_INFORMATION lpProcessInformation
);


BOOL MyCreateProcessW
(
    __in_opt    LPCWSTR lpApplicationName,
    __inout_opt LPWSTR lpCommandLine,
    __in_opt    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    __in_opt    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in        BOOL bInheritHandles,
    __in        DWORD dwCreationFlags,
    __in_opt    LPVOID lpEnvironment,
    __in_opt    LPCWSTR lpCurrentDirectory,
    __in        LPSTARTUPINFOW lpStartupInfo,
    __out       LPPROCESS_INFORMATION lpProcessInformation
);
DWORD hook(DWORD funcBase, DWORD fakeBase);
DWORD unhook(DWORD funcBase, DWORD fakeBase);

BYTE orgCode[7] = { 0 };
BYTE fakeCode[7] = { 0xe9 ,0,0,0,0, 0xeb,0xf9 };//短跳转部分直接硬编码
DWORD functionBase;


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    DWORD funcBase = (DWORD)GetProcAddress(GetModuleHandleA(DllName), FuncName);
    DWORD fakeBase = (DWORD)MyCreateProcessW;
    functionBase = funcBase + 2; //越过mov edi,edi 或者短跳转并不影响执行

    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:

        hook(funcBase, fakeBase);
        break;
    case DLL_PROCESS_DETACH:
        unhook(funcBase, fakeBase);
        break;
    }
    return TRUE;
}

DWORD hook(DWORD funcBase, DWORD fakeBase)
{
    if (*(BYTE*)funcBase==0xeb)
    {
        return 0;
    }
    DWORD page;
    DWORD opcode;
    VirtualProtect((LPVOID)(funcBase - 5), 7, PAGE_EXECUTE_READWRITE, &page);
    memcpy(orgCode , (LPVOID)(funcBase - 5), 7);
    opcode = fakeBase - funcBase;//fakeBase - (funcBase - 5) - 5=fakeBase - funcBase
    memcpy(fakeCode + 1, &opcode, 4);
    memcpy((LPVOID)(funcBase - 5), fakeCode, 7);
    VirtualProtect((LPVOID)(funcBase - 5), 7, page, &page);
    return 1;
}

DWORD unhook(DWORD funcBase, DWORD fakeBase)
{
    if (*(BYTE*)funcBase != 0xeb)
    {
        return 0;
    }
    DWORD page;
    VirtualProtect((LPVOID)(funcBase - 5), 7, PAGE_EXECUTE_READWRITE, &page);
    memcpy((LPVOID)(funcBase - 5), orgCode, 7);
    VirtualProtect((LPVOID)(funcBase - 5), 7, page, &page);
    return 1;
}
BOOL MyCreateProcessW
(
    __in_opt    LPCWSTR lpApplicationName,
    __inout_opt LPWSTR lpCommandLine,
    __in_opt    LPSECURITY_ATTRIBUTES lpProcessAttributes,
    __in_opt    LPSECURITY_ATTRIBUTES lpThreadAttributes,
    __in        BOOL bInheritHandles,
    __in        DWORD dwCreationFlags,
    __in_opt    LPVOID lpEnvironment,
    __in_opt    LPCWSTR lpCurrentDirectory,
    __in        LPSTARTUPINFOW lpStartupInfo,
    __out       LPPROCESS_INFORMATION lpProcessInformation
)
{
    WCHAR exeName[MAX_PATH] = { 0 };
    if (wcsstr(lpApplicationName,L"qq")|| wcsstr(lpApplicationName, L"QQ") || wcsstr(lpApplicationName, L"Qq")
        || wcsstr(lpApplicationName, L"qQ"))
    {
        wsprintfW(exeName, L"%s没交保护费,禁止启动", lpApplicationName);
        MessageBoxW(0, exeName, L"温馨提示", 0);
        return 0;
    }
    else
    {
        wsprintfW(exeName, L"%s交了保护费,予以启动", lpApplicationName);
        MessageBoxW(0, exeName, L"温馨提示", 0);
        return ((lpCreateProcessW)functionBase)( 
            lpApplicationName,
            lpCommandLine,
            lpProcessAttributes,
            lpThreadAttributes,
            bInheritHandles,
            dwCreationFlags,
            lpEnvironment,
            lpCurrentDirectory,
            lpStartupInfo,
            lpProcessInformation);
    }





}
原文地址:https://www.cnblogs.com/freesec/p/6561656.html