首页
社区
课程
招聘
[旧帖] [求助]在dll中利用IAT HOOK其它进程函数,一个关于新函数地址的问题,请大侠指点,感激不尽 0.00雪花
发表于: 2011-8-22 02:37 1866

[旧帖] [求助]在dll中利用IAT HOOK其它进程函数,一个关于新函数地址的问题,请大侠指点,感激不尽 0.00雪花

2011-8-22 02:37
1866
第一次在看雪发帖求问,如果有什么不对的地方,多多包涵啊。。。我实在是糊涂了,不然也不会来劳烦各位大大。

修改user32.dll模块IAT 中的MessageBox的地址,换成自己的MyMessageBox的地址。恩,相信人尽皆知。
新建一个dll,关键代码如下:

int WINAPI MyMessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{  return MessageBox(hWnd, "新函数", "HookAPI", uType);}

BOOL APIENTRY DllMain( HANDLE hModule,   DWORD  ul_reason_for_call,   LPVOID lpReserved)
{
 if(ul_reason_for_call==DLL_PROCESS_ATTACH)
 {
        SetApiAddr(::GetModuleHandle(NULL),PrcMessage,(DWORD  *   ) MyMessageBox,"user32.dll");
 }
    return TRUE;
}

BOOL SetApiAddr(HMODULE hMod,PROC OrgAddr,DWORD *NewAddr,char dllName)///替换IAT表API地址函数

 。。。。省略中间一段,这一段代码就是在hMod的IAT中找到dllName的import descriptor
  if(pImportDesc->FirstThunk)
  {  // 一个IMAGE_THUNK_DATA结构就是一个双字,它指定了一个导入函数
       // 调入地址表其实是IMAGE_THUNK_DATA结构的数组,也就是DWORD数组
    IMAGE_THUNK_DATA* pThunk = (IMAGE_THUNK_DATA*)
        ((BYTE*)hMod + pImportDesc->FirstThunk);
    while(pThunk->u1.Function)
    {  // lpAddr指向的内存保存了函数的地址
      DWORD* lpAddr = (DWORD*)&(pThunk->u1.Function);
      if(*lpAddr == (DWORD)OrgAddr)
      {  
    DWORD dwOldProtect;
          MEMORY_BASIC_INFORMATION mbi;
          VirtualQuery(lpAddr, &mbi, sizeof(mbi));
          VirtualProtect(lpAddr, sizeof(DWORD), PAGE_READWRITE , &dwOldProtect);
          //修改IAT表项,使其指向我们自定义的函数,
           ::WriteProcessMemory(GetCurrentProcess(), lpAddr, &NewAddr, sizeof(DWORD),NULL);
        VirtualProtect(lpAddr, sizeof(DWORD), dwOldProtect, 0);
        return TRUE;
      }
      
  ....
  return FALSE;
}

这段代码在网上随处可见。问题在这句 ::WriteProcessMemory(GetCurrentProcess(), lpAddr, &NewAddr, sizeof(DWORD),NULL);
这句中的&NewAddr自然是参数传进来的(DWORD *)MyMessageBox。问题在这个MyMessageBox,这个函数存在于这个dll本身。当这段代码编译成一个dll之后,此处的MyMessageBox会成为一个32位的地址,这个地址是MyMessageBox相对这个dll的偏移(RVA)(这里是我自己的理解,不知道对不对)。这样的话,dll被加载到某个进程之后,程序就会用上面的那个32位RVA把真正的user32.dll中的MessageBox地址给替换。
当进程调用MessageBox时,本来是会jmp到user32.dll中去,现在却会直接jmp 到那个32位偏移。这不对啊,这个地址不应该还要加上dll的基地址才会是真正的MyMessageBox地址么???

不知道我的意思表达明白了没有。我的意思是 
::WriteProcessMemory(GetCurrentProcess(), lpAddr, &NewAddr, sizeof(DWORD),NULL);应为:
 ::WriteProcessMemory(GetCurrentProcess(), lpAddr, &NewAddr + 这个dll加载在某个进程后的实际基地址, sizeof(DWORD),NULL);
我迷惑了。如果您能给我指点,感激不尽!!

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 1
支持
分享
最新回复 (4)
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
2
什么叫重定位?DLL和EXE一样有个基址,但很多个DLL的默认基址都是一样的,当加载一个DLL时,系统会设法装DLL映射到它的默认基址。但是如果他的默认基址被占用,系统会就将它映射到其它进程空间。

也就是说你是对的  网上的很多代码都不严谨。。。
2011-8-22 09:49
0
雪    币: 473
活跃值: (178)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
谢谢回复哈。
不过事实证明直接写&NewAddr是正确的啊,不用自己加基址了。那个函数的编译后成为
SetApiAddr(::GetModuleHandle(NULL),PrcMessage,(DWORD *)MyMessageBox,"user32.dll");
68191424  push        offset string "user32.dll" (68196650h)
68191429  push        offset MyMessageBox (68191005h)
6819142E  mov         eax,dword ptr [PrcMessage (6819A004h)]
68191433  push        eax  
68191434  mov         esi,esp
68191436  push        0   
68191438  call        dword ptr [__imp__GetModuleHandleW@4 (681991C8h)]
6819143E  cmp         esi,esp
68191440  call        @ILT+305(__RTC_CheckEsp) (68191136h)
68191445  push        eax  
68191446  call        SetApiAddr (681910F0h)
。。。。。。。。。。
仍然感谢
2011-8-22 21:45
0
雪    币: 113
活跃值: (100)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
现在的地址都是平坦模型,不用加模块首地址的。

另外,如果这个模块被加载到其它的地方,这个地址还是可以直接用的,因为系统会帮你重定位的,当然这时的地址和上面的地址数值上会不一样的。

推荐你看下:函数的调用之迷

但我发现一个奇怪的问题,你传参数进来的时候已经是函数地址了,再加&,难道是二重指针嘛?
2011-8-23 13:28
0
雪    币: 159
活跃值: (80)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
MyMessageBox应该就是基地址,不是rva。
2011-8-23 14:16
0
游客
登录 | 注册 方可回帖
返回
//