挂接API,在user32.dll里居然没有找到MessageBoxA()的地址,为什么??

Milo米啊米啊米 2008-03-08 05:14:56
小弟照着《windows核心编程》的讲解做了一个挂接MessageBoxA()函数的例子。可是在用ReplaceIATEntryInOneMod()函数挂接时没有成功,ReplaceIATEntryInOneMod做的事情是找出本程序的输入节,然后找到输入节中user32.dll模块的MessageBoxA()函数的地址。ReplaceIATEntryInOneMod()执行完后我在本程序中调用了MessageBoxA()函数,却没有执行我挂接的函数。
我断点跟进去看,发现它的确是找到了user32.dll的地址,但是里面却没有MessageBoxA()函数的地址。只是为什么,难道MessageBoxA()函数不在user32.dll模块中??
ReplaceIATEntryInOneMod()函数我用的是书上的原码。代码如下:
void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,PROC pfnCurrent, PROC pfnNew, HMODULE hmodCaller) 
{
ULONG ulSize;
/*ReplaceIATEntryInOneMod函数要做的第一件事情是找出hmodCaller模块的输入节,方法是调用ImageDirectoryEntryToData函数,
给它传递IMAGE_DIRECTORY_ENTRY_IMPORT。如果该函数返回NULL,DataBase.exe模块就没有输入节,并且不进行任何操作。*/
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(hmodCaller, TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
if(pImportDesc == NULL)
return;
/*如果DataBase.exe有一个输入节,那么ImageDirectoryEntryToData就返回该输入节的地址,该地址是一个类型为PIMAGE_IMPORT_DESCRIPTOR的指针。现在 我们必须查看该模块的输入节,找出包含我们想要修改的输入函数的DLL。for循环负责扫描DLL模块的名字。注意,模块的输入节中的所有字符串都是用ANSI(决不能用Unicode)编写。这就是为什么要显式调用lstrcmpiA而不是lstrcmpi宏的原因。*/
for(; pImportDesc->Name; pImportDesc++)
{
PSTR pszModName = (PSTR)((PBYTE) hmodCaller + pImportDesc->Name);
if(lstrcmpiA(pszModName, pszCalleeModName) == 0)
break;
}

if(pImportDesc->Name == 0)
return;

/*如果该循环终止运行,但是没有找到对“Kernel32.dll”中的任何符号的引用,那么该函数就返回,并且仍然无所事事。*/
/*如果模块的输入节确实引用了“Kernel32.dll”中的符号,那么将得到包含输入符号信息的IMAGE_THUNK_DATA结构的数组的地址。然后,重复引用来自“Kernel32.dll”的所有输入符号,寻找与符号的当前地址相匹配的地址。*/

PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hmodCaller + pImportDesc->FirstThunk);
for(; pThunk->u1.Function; pThunk++)
{
PROC* ppfn = (PROC*) &pThunk->u1.Function;

// Is this the function we're looking for?
BOOL fFound = (*ppfn == pfnCurrent);

/*如果找到了一个匹配的地址,便调用WriteProcessMemory函数,以便改变替换函数的地址。使用WriteProcessMemory函数,而不是InterlockedExchangePointer函数是因为WriteProcessMemory能够改变字节,而不管这些字节拥有什么页面保护属性。*/
if(fFound)
{
WriteProcessMemory(GetCurrentProcess(), ppfn, &pfnNew, sizeof(pfnNew), NULL);
return;
}
}
}
...全文
610 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
这么多天了,还没解决,结了算了。谢谢楼上各位的讨论!
  • 打赏
  • 举报
回复
谢谢楼上,我知道你说的方法,但是我不想改内存地址,原因是怕别的程序调用MessageBoxW时也受到影响
nooning 2008-03-11
  • 打赏
  • 举报
回复
HOOK导入表不成功,可以直接改入口,把MessageBoxW开始的大于5字节代码完整复制到另一块内存,最后付上一句跳回,把MessageBoxW改成Jmp 你的函数 ,现在你就可以HOOK到所有的MessageBoxW调用了(除了部分加壳程序会复制代码外)
  • 打赏
  • 举报
回复
顶一个,别沉了。好几天了,那位大哥帮个忙啊。
  • 打赏
  • 举报
回复
这是书上的例子啊。难道没有人做过这个例子吗?
cnzdgs 2008-03-08
  • 打赏
  • 举报
回复
试这种程序先把防毒软件关了。
Y___Y 2008-03-08
  • 打赏
  • 举报
回复
不用IAT方式挂接不就行了
  • 打赏
  • 举报
回复
我不想用JUMP CPU指令改写函数内存地址,这样可能会影响到其他调用该函数的进程,所以才选用改变其输入节的。
  • 打赏
  • 举报
回复
我想做的就是在我调用MessageBoxA()时执行我挂接的函数,可是却不成功。怎样才能实现呢?希望大家能帮我,分数可以再加。
verybigbug 2008-03-08
  • 打赏
  • 举报
回复
只有显式的调用了MessageBoxA函数,ReplaceIATEntryInOneMod才能抓的。你用dumpbin看看你的程序有没有import MessageBoxA就知道了。
  • 打赏
  • 举报
回复
我在用ReplaceIATEntryInOneMod()挂接了MessaeBoxA()后就添加了一个按钮,点按钮就调用MessaeBoxA(),弹出一个消息框。如果我挂接成功的话是不会弹出的。
verybigbug 2008-03-08
  • 打赏
  • 举报
回复
这个只能说明DataBase.exe中没有显式的调用MessaeBoxA函数,不能说明user32中没有MessageBoxA函数。
本工具可以列出所有指定DLL文件中的所有导出函数和他们的虚拟内存地址。你可以很方便地复制所需函数的内存地址,粘贴到你的调试器中,并在这个内存地址中设置断点。当这个函数被调用时,调试器将会在函数开始时中断。例如:如果你想在每次显示信息对话框时进行中断,只需把断点设置在信息对话框函数的内存上:MessageBoxA, MessageBoxExA, 和MessageBoxIndirectA (对于Unicode程序则是 MessageBoxW, MessageBoxExW, 和MessageBoxIndirectW)。当其中一个信息对话框函数被调用时,你的调试器会在函数入口处中断,这样你就可以查看调用堆栈和倒退到初始化这个API函数的代码中。 DLL Export Viewer不需要任何安装过程或额外的DLL,为了开始使用它,只需运行可执行文件 - dllexp.exe DLL Export Viewer加载时,你要选择下列一个选项: *载入标准系统DLL(user32,kernel32等)中的所有函数:这是默认选项。如果你选择它,会导出Windows标准DLL(kernel32.dlluser32.dll,等等...)中的API函数。 *从指定的DLL文件中加载函数:如果您选择此选项时,您必须在下面的文本框中指定DLL。您也可以使用通配符指定多个DLL文件。如果你要查看你系统所有的API函数,您可以指定类似'c:\windows\system32\*.dll'的表达式 -但我必须提醒你...你会得到一个非常长的列表函数,可能超过五万个函数! *载入以下文本文档(回车分隔)中指定DLL中的函数:如果您选择此选项,指定文本文件应包含一个DLL文件列表中,回车字符(CR-LF)分隔。全部指定的DLL中的导出函数将被加载。 *载入与所选进程关联的全部 DLL 中的函数:这是本程序最有用的工具调试选项。选择你正在调试的进程,之后所以与选定的进程相关的DLL导出的函数都会被显示。

16,548

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • AIGC Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧