//API函数的入口点地址改成我们构造的函数的地址
WriteProcessMemory(GetCurrentProcess(),lpAddr, &NewFunAddr, sizeof(DWORD), NULL);
问题是为什么这里要用&NewFunAddr ,而不是NewFunAddr呢,我看过了,用&NewFunAddr能挂钩,可是用NewFunAddr不行,NewFunAddr是我传入的函数指针变量,我附上源码的DLL
大家帮我看看。希望高手给我解释一下
#include "stdafx.h"
DWORD* lpAddr;
PROC OldProc;
BOOL  __stdcall  MyTerminateProcess(HANDLE hProcess,UINT uExitCode)
{
MessageBox(NULL,"没法结束进程了吧  http://www.ctt.cn/","API HOOK",0);
return 0;
}int  ApiHook(char *DllName,//DLL文件名
  PROC OldFunAddr,//要HOOK的函数地址
  PROC NewFunAddr//我们够造的函数地址
  )
{
//得到函数进程模块基地址
HMODULE lpBase = GetModuleHandle(NULL);
IMAGE_DOS_HEADER *dosHeader;
IMAGE_NT_HEADERS *ntHeader;
IMAGE_IMPORT_BY_NAME *ImportName;
//定位到DOS头
dosHeader=(IMAGE_DOS_HEADER*)lpBase;
//定位到PE头
ntHeader=(IMAGE_NT_HEADERS32*)((BYTE*)lpBase+dosHeader->e_lfanew);
//定位到导入表
IMAGE_IMPORT_DESCRIPTOR *pImportDesc=(IMAGE_IMPORT_DESCRIPTOR*)((BYTE*)lpBase+ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
//循环遍历IMAGE_IMPORT_DESCRIPTOR机构数组
while(pImportDesc->FirstThunk)
{
//得到DLL文件名
char* pszDllName = (char*)((BYTE*)lpBase + pImportDesc->Name);
//比较得到的DLL文件名是否和要HOOK函数所在的DLL相同
if(lstrcmpiA(pszDllName, DllName) == 0)
{
break;
}
pImportDesc++;
}
//定位到FirstThunk参数指向的IMAGE_THUNK_DATA,此时这个结构已经是函数入口点地址了
IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)
((BYTE*)lpBase + pImportDesc->FirstThunk);
//遍历这部分IAT表
while(pThunk->u1.Function)
{
lpAddr = (DWORD*)&(pThunk->u1.Function);
//比较函数地址是否相同
if(*lpAddr == (DWORD)OldFunAddr)
{
DWORD dwOldProtect;
//修改内存包含属性
VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE, &dwOldProtect);
//API函数的入口点地址改成我们构造的函数的地址
WriteProcessMemory(GetCurrentProcess(),lpAddr, &NewFunAddr, sizeof(DWORD), NULL);
}
pThunk++;
}
return 0;
}BOOL APIENTRY DllMain( HANDLE hModule, 
  DWORD  ul_reason_for_call, 
  LPVOID lpReserved
  )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
//得到TerminateProcess函数地址
OldProc = (PROC)TerminateProcess;
//定位,修改IAT表
ApiHook("kernel32.dll",OldProc,(PROC)MyTerminateProcess);
break;
case DLL_PROCESS_DETACH:
//恢复IAT表中API函数的入口点地址
WriteProcessMemory(GetCurrentProcess(),lpAddr, &OldProc, sizeof(DWORD), NULL);
break;
}
    return TRUE;
}

解决方案 »

  1.   

    WriteProcessMemory(GetCurrentProcess(),lpAddr, &OldProc, sizeof(DWORD), NULL); 
    lpAddr根据上面的代码应该是&(pThunk->u1.Function)的值,也不明白
      

  2.   

    高手们我看我理解对不对,想个一个晚上啊,累是lpAddr==PE文件找到那个函数在内存中的位置,pThunk->u1.Function只是函数在进程地址空间的位置,
    而NewFunAddr地址也是函数在进程中的位置,&NewFunAddr就是代表函数在内存中的位置,
    WriteProcessMemory只是改变了内存中函数对应的关系,而不是改变进程的地址空间函数对应的关系
      

  3.   

    根据你的代码,你进行的HOOK方法是,改变已经映射到进程空间的程序的IAT表。
    也就是改变pThunk->u1.Function中保存的函数地址。
    函数原型中lpBaseAddress和lpBuffer都是指针,
    1.我们要改变pThunk->u1.Function的值,因为u1.Function是DWORD类型,所以要取地址后&(pThunk->u1.Function)传给WriteProcessMemory作为参数lpBaseAddress
    2.我们要在pThunk->u1.Function中写入MyTerminateProcess函数的地址,而不是真正函数体指向的内容。如果不取地址的话直接讲NewFunAddr传给WriteProcessMemory,实际上写入的就是函数体的机器码;所以要取地址&NewFunAddr后传给WriteProcessMemory,这样写入的才是正真的函数地址。BOOL WriteProcessMemory(
      HANDLE hProcess,               // handle to process
      LPVOID lpBaseAddress,          // base of memory area
      LPVOID lpBuffer,               // data buffer
      DWORD nSize,                   // number of bytes to write
      LPDWORD lpNumberOfBytesWritten // number of bytes written
    );
      

  4.   

    WriteProcessMemory(GetCurrentProcess(),lpAddr, &NewFunAddr, sizeof(DWORD), NULL); 
    问题是为什么这里要用&NewFunAddr ,而不是NewFunAddr呢,我看过了,用&NewFunAddr能挂钩,可是用NewFunAddr不行如果:
    LPDWORD A=1
    LPDWORD B=2;B=A;
    结果是B=A如果是WriteProcessMemory(0,&B,A,sizeof(LPDWORD),NULL);
    结果是异常
    它会把A的值当成地址去访问,所以不行.
    WriteProcessMemory(0,&B,&A,sizeof(LPDWORD),NULL);结果就是你想要的B=A;所以你说的问题很简单,如果不加&,你就复制了NewFunAddr的指令,而不是NewFunAddr所指的函数地址。