当前位置:  开发笔记 > 编程语言 > 正文

如何在C/C++中挂钩Windows功能?

如何解决《如何在C/C++中挂钩Windows功能?》经验,为你挑选了3个好方法。

如果我有一个foo()windows已经在kernel32.dll中实现的函数并且它总是返回true,我可以使用我的程序:"bar.exe"挂钩/绕过Windows函数并使其为所有进程返回false吗?

所以,如果我的svchost,例如,调用foo(),它将返回false而不是true.对于当前运行的所有其他进程,应该应该执行相同的操作.

如果是这样,怎么样?我想我正在寻找一个系统范围的钩子或东西.



1> xian..:

看看Detours,它非常适合这类东西.


对于系统范围的挂钩,请阅读MSDN上的这篇文章.


首先,创建一个处理钩子函数的DLL.下面的示例挂钩套接字发送和接收函数.

#include 
#include 

#pragma comment( lib, "Ws2_32.lib" )
#pragma comment( lib, "detours.lib" )
#pragma comment( lib, "detoured.lib" )

int ( WINAPI *Real_Send )( SOCKET s, const char *buf, int len, int flags ) = send;
int ( WINAPI *Real_Recv )( SOCKET s, char *buf, int len, int flags ) = recv;  
int WINAPI Mine_Send( SOCKET s, const char* buf, int len, int flags );
int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags );

int WINAPI Mine_Send( SOCKET s, const char *buf, int len, int flags ) {
    // .. do stuff ..

    return Real_Send( s, buf, len, flags );
}

int WINAPI Mine_Recv( SOCKET s, char *buf, int len, int flags ) {
    // .. do stuff ..

    return Real_Recv( s, buf, len, flags );
}

BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
    switch ( dwReason ) {
        case DLL_PROCESS_ATTACH:       
            DetourTransactionBegin();
            DetourUpdateThread( GetCurrentThread() );
            DetourAttach( &(PVOID &)Real_Send, Mine_Send );
            DetourAttach( &(PVOID &)Real_Recv, Mine_Recv );
            DetourTransactionCommit();
            break;

        case DLL_PROCESS_DETACH:
            DetourTransactionBegin();
            DetourUpdateThread( GetCurrentThread() );
            DetourDetach( &(PVOID &)Real_Send, Mine_Send );
            DetourDetach( &(PVOID &)Real_Recv, Mine_Recv );
            DetourTransactionCommit(); 
        break;
    }

    return TRUE;
}

然后,创建一个程序以将DLL注入目标应用程序.

#include 
#include 
#include 

void EnableDebugPriv() {
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tkp;

    OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken );

    LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid );

    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = luid;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL );

    CloseHandle( hToken ); 
}

int main( int, char *[] ) {
    PROCESSENTRY32 entry;
    entry.dwSize = sizeof( PROCESSENTRY32 );

    HANDLE snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, NULL );

    if ( Process32First( snapshot, &entry ) == TRUE ) {
        while ( Process32Next( snapshot, &entry ) == TRUE ) {
            if ( stricmp( entry.szExeFile, "target.exe" ) == 0 ) {
                EnableDebugPriv();

                char dirPath[MAX_PATH];
                char fullPath[MAX_PATH];

                GetCurrentDirectory( MAX_PATH, dirPath );

                sprintf_s( fullPath, MAX_PATH, "%s\\DllToInject.dll", dirPath );

                HANDLE hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, entry.th32ProcessID );
                LPVOID libAddr = (LPVOID)GetProcAddress( GetModuleHandle( "kernel32.dll" ), "LoadLibraryA" );
                LPVOID llParam = (LPVOID)VirtualAllocEx( hProcess, NULL, strlen( fullPath ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );

                WriteProcessMemory( hProcess, llParam, fullPath, strlen( fullPath ), NULL );
                CreateRemoteThread( hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)libAddr, llParam, NULL, NULL );
                CloseHandle( hProcess );
            }
        }
    }

    CloseHandle( snapshot );

    return 0;
}

这应该足以让你入门!



2> RandomNickNa..:

EASYHOOK http://www.codeplex.com/easyhook

Dominate在简单性,灵活性和功能性方面的所有前述技术.

以前没有讨论Hook过程.我已经阅读了这篇文章的所有内容,并且凭借绝对的认可,EASYHOOK非常优秀.无论你使用C,C++,CLR还是其他什么.

我将从codeplex主页粘贴一点,以确保支付足够的图像.

以下是不完整的功能列表:

    在挂钩未知API时,所谓的"线程死锁障碍"将摆脱许多核心问题; 这项技术是EasyHook独有的

    您可以为非托管API编写托管钩子处理程序

    您可以使用所有方便的托管代码,例如NET Remoting,WPF和WCF

    一个文档化的,纯粹的非托管挂钩API

    支持32位和64位内核模式挂钩(还可以查看我的PatchGuard 3旁路驱动程序,可以在发布列表中找到)

    目标中没有剩余资源或内存泄漏

    实验性隐形注射机制不会引起任何当前AV软件的注意

    EasyHook32.dll和EasyHook64.dll是纯粹的非托管模块,无需安装任何.NET框架即可使用!

    所有挂钩均以稳定的方式安装并自动移除

    通过使用完全未记录的API支持Windows Vista SP1 x64和Windows Server 2008 SP1 x64,仍然允许挂钩到任何终端会话.

    钩子处理程序内的托管/非托管模块堆栈跟踪

    在钩子处理程序中调用托管/非托管模块

    在钩子处理程序内创建自定义堆栈跟踪

    您将能够编写为AnyCPU编译的注入库和主机进程,这将允许您通过在所有情况下使用相同的程序集将代码注入64位和32位进程的32位和64位进程.

    EasyHook支持64位目标的RIP相对寻址重定位.

    无需拆包/安装.

    Visual Studio Redistributable不是必需的.

我很高兴我的妓女仍然知道一些技巧比较让我保持他们.但是可以肯定的是,当你需要一个HOOK,99次100,EASYHOOK'r会让你更快.并且它得到了很积极的维护.


这更像是广告而不是答案.

3> beef2k..:

请提供您要挂钩的功能的更多详细信息!在这种情况下,有几种方法可以调用自己的代码,例如:

您可以构建一个假DLL,其名称与包含要挂钩的函数的DLL相同(并将其复制到文件夹中foo.exe).该库将公开与原始DLL完全相同的功能.除了要挂钩的函数之外,每个公开的函数都会绕过对原始DLL的调用.

您可以在运行时更改函数指针表,例如使用"kitchen"提到的(商业)Detour包.但是,这样的挂钩可以由您自己轻松完成,请参阅本文以了解如何操作.

您可以找到调用特定函数的位置foo.exe,只需用"返回true" 代码替换调用函数的汇编代码.基本上,你正在修补" foo.exe"..

对于特定功能,Windows提供自动挂钩,例如键和鼠标事件.检查函数SetWindowsHook.

推荐阅读
吻过彩虹的脸_378
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有