我想挂钩 win32API,但它不起作用 [关闭]

Posted

技术标签:

【中文标题】我想挂钩 win32API,但它不起作用 [关闭]【英文标题】:I want to hook the win32API ,but it doesn't work [closed] 【发布时间】:2016-09-14 03:58:12 【问题描述】:

我要挂钩WriteFile函数。目标进程是notepad.exe。但它不起作用。 代码。

#include<stdio.h>
#include<stdlib.h>
#include<Windows.h>
#include<TlHelp32.h>


DEBUG_EVENT de;
FARPROC g_pfTargetAPIAddress;  //save the address of WriteFile function
BYTE g_ReadAPIBuffer;          //save the original content of the first byte of WriteFile function
BYTE g_WriteAPIBuffer=0xCC;    //change the first byte of WriteFile function to 0xCC , so that it can throw a breakpoint exception 
HANDLE g_hTargetProcessHandle;   //the handle of the target process (notepad.exe)
HANDLE g_hTargetThreadHandle;  //the main thread of the target process
DWORD g_dwTargetProcessId;      
DWORD g_dwTargetThreadId;


DWORD GetTargetProcess()    //get the id of the target process (notepad.exe)


PROCESSENTRY32 pe32;
pe32.dwSize=sizeof(pe32);


HANDLE handle=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(handle==INVALID_HANDLE_VALUE)

    printf("get tool help handle error,the error code is:%u\n",GetLastError());
    system("PAUSE");
    return NULL;


BOOL bMore=::Process32First(handle,&pe32);
while(bMore)

    printf("the process name is:%ws\n",pe32.szExeFile);
    printf("the process id is %d\n",pe32.th32ProcessID);

    if(wcscmp(pe32.szExeFile,L"notepad.exe")==0)
    
        return pe32.th32ParentProcessID;
    

    bMore=::Process32Next(handle,&pe32);


return NULL;




BOOL OnProcessCreateDebug(LPDEBUG_EVENT de)


printf("now begin OnProcessCreateDebug\n");
g_hTargetProcessHandle=de->u.CreateProcessInfo.hProcess;
g_hTargetThreadHandle=de->u.CreateProcessInfo.hThread;
g_dwTargetThreadId=de->dwThreadId;

HMODULE hModule=::LoadLibrary(L"kernel32.dll");
if(hModule==INVALID_HANDLE_VALUE)

    printf("get the api handle error ,the error code is :%u\n",GetLastError());
    system("PAUSE");
    return FALSE;


char cTargetAPIName[]="WriteFile";
g_pfTargetAPIAddress=::GetProcAddress(hModule,(LPCSTR)cTargetAPIName);
if(g_pfTargetAPIAddress==NULL)

    printf("the getprocaddress in onprocesscreatedebug failes,the error code is:%u",GetLastError());
    system("PAUSE");
    return FALSE;



BOOL bReadResult=::ReadProcessMemory(de->u.CreateProcessInfo.hProcess,g_pfTargetAPIAddress,&g_ReadAPIBuffer,sizeof(BYTE),NULL);
if(!bReadResult)

    printf("read the first byte of target api fails,the error code is :%u\n",GetLastError());
    system("PAUSE");
    return FALSE;




BOOL bWriteResult=::WriteProcessMemory(de->u.CreateProcessInfo.hProcess,g_pfTargetAPIAddress,&g_WriteAPIBuffer,sizeof(BYTE),NULL);
if(!bWriteResult)

    printf("write the first byte of target api fails,the error code is :%u\n",GetLastError());
    system("PAUSE");
    return FALSE;



printf("now finish OnProcessCreateDebugEvent\n");

return TRUE;




BOOL OnExceptionDebugEvent(LPDEBUG_EVENT de)


printf("now go into the OnExceptionDebugEvent just now\n"); 
PEXCEPTION_RECORD per=&de->u.Exception.ExceptionRecord;

if(per->ExceptionCode==EXCEPTION_BREAKPOINT)


    printf("now it is in the first if\n");

    if(per->ExceptionAddress==g_pfTargetAPIAddress)
    

        printf("now has entered the OnExceptionDebugEvent\n");


        if(!WriteProcessMemory(g_hTargetProcessHandle,g_pfTargetAPIAddress,&g_WriteAPIBuffer,sizeof(BYTE),NULL))
        
            printf("onexecption write the first byte of target api fails,the error code is :%u\n",GetLastError());
            system("PAUSE");
            return FALSE;
        


        CONTEXT con;
        con.ContextFlags=CONTEXT_CONTROL;
        ::GetThreadContext(g_hTargetThreadHandle,&con);

        DWORD dwWriteFileBufferAddress;
        if(!::ReadProcessMemory(g_hTargetProcessHandle,(LPCVOID)(con.Esp+0x8),&dwWriteFileBufferAddress,sizeof(DWORD),NULL))
        
            printf("read the  the lpBaseAddress of target api  fails,the error code is :%u\n",GetLastError());
            system("PAUSE");
            return FALSE;
        


        printf("now after esp+8\n");

        DWORD dwSizeOfBuffer;
        if(!::ReadProcessMemory(g_hTargetProcessHandle,(LPCVOID)(con.Esp+0x10),&dwSizeOfBuffer,sizeof(DWORD),NULL))
        
            printf("read the lpBuffer of target api fails,the error code is :%u\n",GetLastError());
            system("PAUSE");
            return FALSE;
        


        LPBYTE lpBuffer=(LPBYTE)malloc(dwSizeOfBuffer+1);
        LPBYTE lppointer=lpBuffer;
        for(int i=0;i<=dwSizeOfBuffer;i++)
        
            *lppointer=0x1;
            lppointer++;
        
        *lppointer=0x0;

        if(!::WriteProcessMemory(g_hTargetProcessHandle,(LPVOID)dwWriteFileBufferAddress,lpBuffer,dwSizeOfBuffer+1,NULL))
        
            printf("overridewrite the  buffer of target api fails,the error code is :%u\n",GetLastError());
            system("PAUSE");
            return FALSE;
        

        free(lpBuffer);


        con.Eip=(DWORD)g_pfTargetAPIAddress;
        SetThreadContext(g_hTargetThreadHandle,&con);

        ContinueDebugEvent(g_dwTargetProcessId,g_dwTargetThreadId,DBG_CONTINUE);


        printf("now after the ContinueDebugEvent\n");

        Sleep(0);

        BYTE byte=0xcc;
        if(!::WriteProcessMemory(g_hTargetProcessHandle,g_pfTargetAPIAddress,&byte,sizeof(BYTE),NULL))
        
            printf("rewrite the first byte of target api fails,the error code is :%u\n",GetLastError());
            system("PAUSE");
            return FALSE;
        

    

    else 
        
            printf("not enter the second if\n");
        



else printf("not enter the first if\n");

return TRUE;



BOOL HookAPI()

while(WaitForDebugEvent(&de,INFINITE))

    if(de.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT)
    
        if(!OnProcessCreateDebug(&de)) return FALSE;

    


    else if(de.dwDebugEventCode==EXCEPTION_DEBUG_EVENT)
    
        printf("now it is going to call the OnExceptionDebugEvent\n");
        if(!OnExceptionDebugEvent(&de)) return FALSE;
    
    else if(de.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT)
    
        break;
    


    ::ContinueDebugEvent(de.dwProcessId,de.dwThreadId,DBG_CONTINUE);


return TRUE;



int main()

g_dwTargetProcessId=GetTargetProcess();
if(g_dwTargetProcessId==NULL)

    printf("the value of dProcessId is null\n");
    system("PAUSE");
    return -1;



BOOL b=DebugActiveProcess(g_dwTargetProcessId);
if(!b)

    printf("DebugActiveProcess fails,the last error is : %u\n",GetLastError());
    system("PAUSE");
    return -1;


HookAPI();

return 0;

我想钩住WriteFile函数,它把WriteFile函数的第一个字节改成0xCC,但是不起作用。我可以使用 notepad.exe 正常保存文件。我猜0xCC 不能抛出断点异常。 谁能告诉我问题出在哪里?

【问题讨论】:

看起来你确信 notepad.exe 是 32 位的,但现在这很少是真的。在 64 位程序中挂钩 API 有所不同。 AFAIK notepad.exe 将您正在编辑的文件映射到内存中,因此它可能不经常使用WriteFile @Havenard 我正在学习,这个程序我只在 32 位 Windows Xp sp3 上运行 【参考方案1】:

此代码只能在x86 环境中编译,因为CONTEXT 结构对于x64 处理器将具有完全不同的字段集。由于x64 操作系统现在盛行,notepad.exe 很可能是x64 应用程序,因此您的x86 应用程序甚至无法附加到它。 DebugActiveProcess 将返回 FALSEGetLastError == ERROR_NOT_SUPPORTED。如果我们暂时忽略这个琐碎的事情(或假设记事本是x86 应用程序),那么您的代码中有一些需要改进的地方。

首先。此错误验证码无效:

HMODULE hModule = ::LoadLibrary(L"kernel32.dll");
if (hModule == INVALID_HANDLE_VALUE)

    printf("get the api handle error ,the error code is :%u\n", GetLastError());
    system("PAUSE");
    return FALSE;

LoadLibrary 出错时返回 NULLINVALID_HANDLE_VALUE 为 -1,因此永远不会调用您的错误处理程序。虽然kernel32.dll 缺席是完全不可能的,但对于其他 dll,应该考虑这一点。

第二。如果您无法使用PROCESS_ALL_ACCESS 访问掩码打开其句柄,则无法调试其他进程。设置SE_DEBUG_NAME 权限也有帮助。要启用此权限,您的帐户应具有管理员权限(或应在组策略中启用此权限)。即使帐户有SE_DEBUG_NAME,应用程序也应该明确请求它。有关详细信息,请参阅this MSDN 示例。

第三。 Dll 代码页受到保护,无法写入。所以你必须使用VirtualProtectEx将内存保护改为PAGE_EXECUTE_READWRITE

第四。你不能假设,同一个 dll 在不同的进程中会有相同的加载地址。如果与其他一些 dll 基本加载地址发生冲突,则可以根据加载重新设置 dll。此外,自 Windows Vista 以来的所有现代 Windows 操作系统都具有称为地址空间布局随机化 (ASLR) 的安全功能。因此,您必须使用 ToolHelp API 枚举目标进程中的 dll,而不是仅调用 GetProcAddress

【讨论】:

WriteProcessMemory 实际上确实更改了页面保护(暂时)。 我在 Windows XP sp3 上运行这个程序,它没有 ASLR。而且我认为ASLR只在重新启动计算机时重新加载dll和其他进程的基地址。但是系统中所有dll的基地址都是一样的。

以上是关于我想挂钩 win32API,但它不起作用 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Win32 C++ 中的 GetWindowText() 不起作用

我正在尝试更新状态,但它不起作用[重复]

Cloudinary REST api 销毁不起作用? [关闭]

使用win32api检查背景上是否按下了键

我正在使用 Jena 导入 skos 词库,但它不起作用 [重复]

关联(pivot,belongsToMany)中的续集挂钩(afterCreate.afterUpdate)不起作用