我想挂钩 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
将返回 FALSE
,GetLastError
== 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
出错时返回 NULL
,INVALID_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 销毁不起作用? [关闭]