进程动态拦截注入API HOOK

最近工作中遇到一个问题,需要通过程序界面进行判断程序的运行状态,刚开始认为很简单,不就是一个窗体控件获取,获取Button的状态和Text。刚好去年干过该事情,就没太在意,就把优先级排到后面了,随着项目交付时间的临近,就准备开始解决问题,一下懵逼了,这次软件作者也聪明了,居然换了花样。

从图中可以发现,此处的按钮上的文字等信息不是通过Button信息进行操作。静想猜测是通过Windows API直接将信息进行写入,那么哪个API可以进行写入呢,想想不难发现,其实就是窗口程序中在窗口中写入文字的方法DrawText,同时隐约记得SetWindowsText也具备该功能。既然有猜想了那就实践看看,验证下猜想。

开干之前,还需要理理思路:

  1. 既然程序会调用DrawText方法,那我要获取文本,就必须截获到该方法
  2. 截获方法不就是使用Windows上大名鼎鼎的钩子(Hook)函数。
  3. 说到钩子函数,这又分钩窗口消息钩API函数。对于本文来说当然就是后者了。实现API HOOK主要有两个重要环节:
    • 如何把代码注入到目标地址空间
    • 如何让自己的代码被调用
  4. 稍稍查询下资料,发现钩窗口函数貌似就复杂了,如果要研究细节请参考该文
  5. 进一步资料查询,我发现以牛逼函数库(居然还是微软自己开发的):Detours(当然我会提供下载链接)Detours它用于实现拦截Win32二进制代码中的API函数。它使用一个JMP指令替换了目标函数的前面几个字节,使得控制直接调用实现的Detours函数。并通过一个trampoline函数保留了原来函数的功能调用。
  6. 到目前为止就是对该库的使用了。从文档上来看应该没什么问题了。但是文档上是通过创建进程进行注入DetourCreateProcessWithDll,对目前我的应用场景就不太匹配了。客户程序一直处于运行状态,我需要获取动态注入,那么问题来了,如何解决了?
BOOL WINAPI DetourCreateProcessWithDll(LPCSTR lpApplicationName,
                                        LPSTR lpCommandLine,
                                        ...);
  1. 能提出问题,基本上问题就解决了一般。果不然,通过百度和Google的不懈努力,终于发现原来Detours1.5版本中有个方法DetourContinueProcessWithDll该方法就是进行动态注入的,这下就可以开干了(至于Detours的原理本文就不再赘述,请大家自行查询资料,本文以解决实际问题问题主)
BOOL WINAPI DetourContinueProcessWithDll(HANDLE hProcess, LPCSTR lpDllName);

经过上面几个步骤下来,已经有了完整的思路,下文主要结合实践,进行代码实践。本文主要从如下几个方面进行时间:

  • 首先,居然是要截取函数DrawTextSetWindowText那么首先的先实现自己的函数(通过DLL封装)
  • 然后,就是动态注入我们的DLL文件指定进程
  • 最后,拿出来溜溜(本文为了简便,仅将相关信息打印到DebugView中)

实现HookWindowTextDll

首先,按照Detours的编程规范,需要在加载HookWindowTextDll时通过方法DetourFunctionWithTrampoline进行注册。在卸载的时候通过DetourRemove卸载。

该处主要分以下几步:

  1. 需要Hook的方法声明和实现
  2. 安装和卸载注入方法

Hook方法声明和实现

首先需要声明我们的方法

BOOL WINAPI MySetWindowTextA( HWND hWnd, LPCTSTR lpString );
BOOL WINAPI MySetWindowTextW( HWND hWnd, LPCWSTR lpString ); 

int WINAPI MyDrawTextA( HDC hDC, LPCTSTR lpString, int nCount, LPRECT lpRect, UINT uFormat );
int WINAPI MyDrawTextW( HDC hDC, LPCWSTR lpString, int nCount, LPRECT lpRect, UINT uFormat );

//该方法主要是用Real_SetWindowTextA保存原来函数SetWindowTextA地址,方便后面调用
DETOUR_TRAMPOLINE( BOOL WINAPI Real_SetWindowTextA( HWND a0, LPCTSTR a1 ), SetWindowTextA );
DETOUR_TRAMPOLINE( BOOL WINAPI Real_SetWindowTextW( HWND a0, LPCWSTR a1 ), SetWindowTextW );

DETOUR_TRAMPOLINE( int WINAPI Real_DrawTextA( HDC a0, LPCTSTR a1, int a2, LPRECT a3, UINT a4 ), DrawTextA );
DETOUR_TRAMPOLINE( int WINAPI Real_DrawTextW( HDC a0, LPCWSTR a1, int a2, LPRECT a3, UINT a4 ), DrawTextW );

//代码实现,限于篇幅,仅列出MySetWindowTextA
BOOL WINAPI MySetWindowTextA( HWND hWnd, LPCTSTR lpString )
{
#ifdef _DEBUG
    char strMsg[ 1024 ]={0};
    wsprintf( strMsg, "SetWindowTextA : %s. size = %ld\n", lpString, strlen(lpString) );
    OutputDebugString( strMsg );
#endif

    return Real_SetWindowTextA( hWnd, lpString );
}

Hook方法的安装和卸载

BOOL APIENTRY DllMain( HANDLE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved )
{
    if( DLL_PROCESS_ATTACH == ul_reason_for_call )//dll加载
    {
        InstallProbes();
    }
    else if( DLL_PROCESS_DETACH == ul_reason_for_call )//dll卸载
    {
        UninstallProbes();
    }
    else;

    return TRUE;
}

拦截注入通过方法DetourFunctionWithTrampoline进行,该方法原型如下:

BOOL  WINAPI DetourFunctionWithTrampoline(PBYTE pbTrampoline,
                                          PBYTE pbDetour);

这个函数有两个参数,pbTrampoline和一个指向pbDetour函数的指针。目标函数Target之所以没有作
为一个参数,是因为它已经编码到pbTrampoline函数之中(上文中进行编码DETOUR_TRAMPOLINE)。

BOOL InstallProbes()
{
    DetourFunctionWithTrampoline( (PBYTE)Real_SetWindowTextA, (PBYTE)MySetWindowTextA );
    DetourFunctionWithTrampoline( (PBYTE)Real_SetWindowTextW, (PBYTE)MySetWindowTextW );

    DetourFunctionWithTrampoline( (PBYTE)Real_DrawTextA, (PBYTE)MyDrawTextA );
    DetourFunctionWithTrampoline( (PBYTE)Real_DrawTextW, (PBYTE)MyDrawTextW );

    OutputDebugString("InstallProbesA ok.\n");
    return TRUE;
}

BOOL UninstallProbes()
{
    DetourRemove( (PBYTE)Real_SetWindowTextA, (PBYTE)MySetWindowTextA );
    DetourRemove( (PBYTE)Real_SetWindowTextW, (PBYTE)MySetWindowTextW );

    OutputDebugString("UNInstallProbesB ok.\n");
    return TRUE;
}

至此拦截注入的方法就完成。下一小节就是如何进行动态注入了。

动态注入HookWindowTextDll

既然要动态注入,那么就先要看看动态注入方法DetourContinueProcessWithDll方法的使用方法

//把一个动态链接库注入到一个新的进程中
BOOL WINAPI DetourContinueProcessWithDllA(HANDLE hProcess, LPCSTR lpDllName)

该方法有两个参数,一看看就明白了

  • hProcess:需要注入的原进程句柄
  • lpDllName:需要注入的Dll路径,本文即HookWindowTextDll.dll

那么此时应该先获取进程句柄,获取进程句柄通过如下方法即可:

通过进程名称获取进程ID

DWORD   GetProcessIdFromProcessName(std::string processname)
{
    DWORD dwRet = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(pe32);
    HANDLE hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap != INVALID_HANDLE_VALUE)
    {
        BOOL bMore = ::Process32First(hProcessSnap, &pe32);
        while (bMore)
        {
            if (boost::iequals(pe32.szExeFile, processname))
            {
                dwRet = pe32.th32ProcessID;
                 break;
            }
            bMore = ::Process32Next(hProcessSnap, &pe32);
        }
        ::CloseHandle(hProcessSnap);
    }
    return dwRet;
}

调用测试:

std::string str1 = "WireCut.EXE";
DWORD dwProcessId = GetProcessIdFromProcessName(str1);
std::cout << dwProcessId << std::endl; //

获取到了进程,那就进入下一节,获取句柄。

通过进程ID获取进程句柄

OpenProcess 函数用来打开一个已存在的进程对象,并返回进程的句柄

HANDLE OpenProcess(
        DWORD dwDesiredAccess,
        BOOL bInheritHandle,
        DWORD dwProcessId
);

参数:

  • dwDesiredAccess:想拥有的该进程访问权限

    • PROCESS_ALL_ACCESS:所有能获得的权限
    • PROCESS_CREATE_PROCESS:需要创建一个进程
    • PROCESS_CREATE_THREAD:需要创建一个线程
    • PROCESS_DUP_HANDLE:重复使用DuplicateHandle句柄
    • PROCESS_QUERY_INFORMATION:获得进程信息的权限,如它的退出代码、优先级
    • PROCESS_SET_INFORMATION :设置某些信息的权限,如进程优先级
    • PROCESS_SET_QUOTA :设置内存限制的权限,使用SetProcessWorkingSetSize
    • PROCESS_SUSPEND_RESUME :暂停或恢复进程的权限
    • PROCES_TERMINATE :终止一个进程的权限,使用TerminateProcess
    • PROCESS_VM_OPERATION :操作进程内存空间的权限(可用VirtualProtectEx和WriteProcessMemory)
    • PROCESS_VM_READ :读取进程内存空间的权限,可使用ReadProcessMemory
    • PROCESS_VM_WRITE :读取进程内存空间的权限,可使用WriteProcessMemory
    • SYNCHRONIZE :等待进程终止
  • bInheritHandle:表示所得到的进程句柄是否可以被继承
  • dwProcessId:被打开进程的PID

返回类型:

  • 如成功,返回值为指定进程的句柄。
  • 如失败,返回值为NULL,可调用GetLastError()获得错误代码。
HANDLE GetProcessHandle(DWORD nID)
{
    //PROCESS_ALL_ACCESS 所有能获得的权限
    return OpenProcess(PROCESS_ALL_ACCESS, FALSE, nID);
}
DWORD dwProcessId = GetProcessIdFromProcessName("WireCut.EXE");
if (dwProcessId != 0)
{
    bRet = DetourContinueProcessWithDllW(GetProcessHandle(dwProcessId), szDllFilePath);
}

到此就完成了所有工作,后面提供项目代码和库文件

链接:https://pan.baidu.com/s/1c09LWg9zo5NIVwR2htJYZA
提取码:f0kt

欢迎关注交流共同进步

博客地址:wqliceman.top

原文地址:https://www.cnblogs.com/wqliceman/p/10924958.html

时间: 2024-11-14 10:43:21

进程动态拦截注入API HOOK的相关文章

API HOOK及其注入技术详解

大家有没有想过,一些系统监控软件是如何得知我们所进行的操作的?杀软启发式分析是如何对病毒行为进行拦截和监控的?外挂又是如何读取到游戏的内部数据的?这些功能的实现,基本都有API HOOK存在.API HOOK分为ring0和ring3层,这里我们以ring3层API HOOK 进行讲解分析. API HOOK 在ring 3的实现,分为inline 和修改导入表2种方法,所谓inline,是指直接写入并覆盖函数开头字节汇编码的方法,这种方法有一个问题,便是他被杀软重点监控,成功率极低,而修改导入

Windows Dll Injection、Process Injection、API Hook

catalogue 1. 引言 2. 使用注册表注入DLL 3. 使用Windows挂钩来注入DLL 4. 使用远程线程来注入DLL 5. 使用木马DLL来注入DLL 6. 把DLL作为调试器来注入 7. 使用createprocess来注入代码 8. api拦截 9. Detours - Inline Hook 1.  引言 应用程序需要跨越进程边界来访问另一个进程的地址空间的情况如下 1. 我们想要从另一个进程创建的窗口派生子类窗口 2. 我们需要一些手段来辅助调试,例如我们需要确定另一个进

API Hook基本原理和实现

2009-03-14 20:09 windows系统下的编程,消息message的传递是贯穿其始终的.这个消息我们可以简单理解为一个有特定意义的整数,正如我们看过的老故事片中的“ 长江长江,我是黄河”一个含义.windows中定义的消息给初学者的印象似乎是“不计其数”的,常见的一部分消息在winuser.h头文件中定义. hook与消息有着非常密切的联系,它的中文含义是“钩子”,这样理解起来我们不难得出“hook是消息处理中的一个环节,用于监控消息在系统中的传递,并在这些消息到达最终的消息处理过

API Hook完全手册

文章来源: http://blog.csdn.net/atfield 原文作者: ATField 整理日期: 2008-07-16 发表评论 字体大小: 小 中 大 注:本文是根据我两年前写的一个系统行为监测程序写成(参考了一些书籍和文章).最近在论坛上看到有不少人在问关于API Hook的问题,便写成此文,希望能对朋友们在写API Hook代码的时候能够有所帮助. 1 基本原理 API Hook是什么我就不多说了,直接进入正题.API Hook技术主要有下面的技术难点: 如何将自己的的代码In

程序破解之 API HOOK技术 z

API HOOK,就是截获API调用的技术,在程序对一个API调用之前先执行你的函数,然后根据你的需要可以执行缺省的API调用或者进行其他处理,假设如果想截获一个进程对网络的访问,一般是几个socket API : recv,recvfrom, send, sendto等等,当然你可以用网络抓包工具,这里只介绍通过API HOOK的方式来实现, 主要原理是在程序运行中动态修改目标函数地址的内存数据,使用jmp语句跳转到你的函数地址,执行完后再恢复内存数据, 汇编代码是: mov eax, pNe

API HOOK介绍 【转】

什么是“跨进程 API Hook”? 众所周知Windows应用程序的各种系统功能是通过调用API函数来实现.API Hook就是给系统的API附加上一段小程序,它能监视甚至控制应用程序对API函数的调用.所谓跨进程也就是让自己的程序来控制别人程序的API调用了. API Hook 理论 通过对Win32 PE文件的分析(如果你还不熟悉PE文件格式,可以看看Iczelion的PE教程或者LUEVELSMEYER的<<The PE File Format>>).我们知道在PE文件中的

API HOOK

API HOOK技术是一种用于改变API执行结果的技术,Microsoft 自身也在Windows操作系统里面使用了这个技术,如Windows兼容模式等. API HOOK 技术并不是计算机病毒专有技术,但是计算机病毒经常使用这个技术来达到隐藏自己的目的. API HOOK解释 在windows系统下编程,应该会接触到api函数的使用,常用的api函数大概有2000个左右.今天随着控件,stl等高效编程技术的出现,api的使用概率在普通的用户程序上 就变得越来越小了.当诸如控件这些现成的手段不能

API HOOK技术

API HOOK技术是一种用于改变API执行结果的技术,Microsoft 自身也在Windows操作系统里面使用了这个技术,如Windows兼容模式等. API HOOK 技术并不是计算机病毒专有技术,但是计算机病毒经常使用这个技术来达到隐藏自己的目的. 外文名 API HOOK      用于 改变API执行结果的技术 应用 如Windows兼容模式等  目的 计算机病毒隐藏自己的技术                                                      

Windows API Hook

原文地址:http://blog.sina.com.cn/s/blog_628821950100xmuc.html 原文对我的帮助极大,正是因为看了原文,我才学会了HOOK,鉴于原文的排版不是很好, 又没有原工程例子源码下载,因此我决定对其重新整理,文章后面附有我测试时的工程源码下载地址. 注:我测试的环境为Win7+VS2008+MFC 原文出处,好像是这篇:http://blog.csdn.net/glliuxueke/article/details/2702608      //后来才看到