模块A(a.dll),有一个函数f();
模块B(b.dll);
模块C(c.dll);
还有自己X(x.exe);
大家知道GetModuleHandle(NULL)可以返回创建进程的模块,这个例子里就是X。
但是当模块B或C调用模块A的f()函数时,f()函数体里如何得调用者模块的HMODULE?
23 个解决方案
#1
补充:f()是不知道B或C模块的名字(b.dll/c.dll)的,否则就可以用GetModuleHandle("b.dll")来获取了
#2
按我理解你的意思作一下回答
模块B/C调用f()函数,f()函数根本就不知道模块B/C的HMODULE,也不需要知道。只要模块B/C知道模块A的HMODULE就行了,也就是说模块A没必要知道模块B/C的HMODULE。除非你在你的DLL里面的DLLMAIN函数里面获取HINSTANCE也就是你所说的调用者的HMODULE了,只要
(HMODULE)Hinstance进行转换就行了
模块B/C调用f()函数,f()函数根本就不知道模块B/C的HMODULE,也不需要知道。只要模块B/C知道模块A的HMODULE就行了,也就是说模块A没必要知道模块B/C的HMODULE。除非你在你的DLL里面的DLLMAIN函数里面获取HINSTANCE也就是你所说的调用者的HMODULE了,只要
(HMODULE)Hinstance进行转换就行了
#3
_AFX_THREAD_STATE *pafxState = AfxGetThreadState();
CWinApp *pPreApp = pafxState->m_pModuleState->m_pCurrentWinApp;
其中pPreApp 就是前一个运行的程序的theapp,不过这个方法只是在mfc dll试验过
CWinApp *pPreApp = pafxState->m_pModuleState->m_pCurrentWinApp;
其中pPreApp 就是前一个运行的程序的theapp,不过这个方法只是在mfc dll试验过
#4
只有在进程载入dll时,或dll已被载入后进程里又创建了一个新线程的时候,以及线程退出、进程退出时才调用DllMain()
而DllMain()的这个hInstance只是dll自己被载入后的HMODULE,跟本不是其他模块的HMODULE。
所以 maijian(asmvc) 回答不正确,同样 holyeagle(一杯清茶) 答不对题。
而DllMain()的这个hInstance只是dll自己被载入后的HMODULE,跟本不是其他模块的HMODULE。
所以 maijian(asmvc) 回答不正确,同样 holyeagle(一杯清茶) 答不对题。
#5
我想如果有了theapp,得到相应的模块的句柄应该不是问题啊。CWinApp::m_hInstance就是app的模块的句柄。
#6
在B/C调用a中函数的时候,能不能把自己的句柄作为参数传过去?
#7
re: 我想如果有了theapp,得到相应的模块的句柄应该不是问题啊。CWinApp::m_hInstance就是app的模块的句柄。
不是问题?那到底怎么获得啊?又不知道b/c模块名。
不能传参数,因为b/c模块是别人写好的dll。
不是问题?那到底怎么获得啊?又不知道b/c模块名。
不能传参数,因为b/c模块是别人写好的dll。
#8
为什么不考虑把module handle作为参数传给f()呢
#9
theapp.m_hInstance就是实例句柄吧。
#10
如果是DEBUG版本,可以用StackWalk取得,Release版本有点难。
#11
to: msdn_user(蓝天)
其实f()模块是注入别人的进程里的,所以你要别人进程里的其他模块传module handle给f()是不可能的。
to: holyeagle(一杯清茶)
theApp.m_hInstance是进程实例句柄没错,也是进程exe文件模块句柄也没错,
但我不是要这个, 你怎么还不知道问题呢!
to: DentistryDoctor(牙科医生)
回答对口了,但是看来不简单,有没有简单点的?
其实f()模块是注入别人的进程里的,所以你要别人进程里的其他模块传module handle给f()是不可能的。
to: holyeagle(一杯清茶)
theApp.m_hInstance是进程实例句柄没错,也是进程exe文件模块句柄也没错,
但我不是要这个, 你怎么还不知道问题呢!
to: DentistryDoctor(牙科医生)
回答对口了,但是看来不简单,有没有简单点的?
#12
不是exe的,是上一级调用者的。比如在一级dll中可以得到的就是exe,二级就是上一级调用dll的句柄
#13
可以分析内存实例的PE结构,得到静态联编的各dll模块的HMODULE。但动态装载的,就没法了。不过还可以在进程地址空间内搜索“MZ”PE标志,再进一步得分析是否是一个PE模块。进程地址空间内,可以先分析内存块的属性,只分析只读和可执行的代码块。
总之,在知道了各模块的起始地址后,要得到F()函数是由哪个模块调用的,我想还是只有分析堆栈中的调用地址了,知道调用地址,就可以知道它此次调用属于哪个模块了。
总之,在知道了各模块的起始地址后,要得到F()函数是由哪个模块调用的,我想还是只有分析堆栈中的调用地址了,知道调用地址,就可以知道它此次调用属于哪个模块了。
#14
可能MS有特别的,或是未公开的(我反正不知道)函数,直接从系统数据结构中查到各个模块。但要得到调用模块,还是只有查堆栈,除非在EXE中有输出的调试信息内有。
#15
调用地址是调用者call时候被push进去的返回地址吗?
如何获得?如果能准确获得的话就一切ok了,
因为以下函数能根据地址得到地址所在的模块:
HMODULE ModuleFromAddress(LPVOID lpv)
{
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
return VirtualQuery(lpv, &mbi, sizeof(mbi)) ? (HMODULE)mbi.AllocationBase : NULL;
}
如何获得?如果能准确获得的话就一切ok了,
因为以下函数能根据地址得到地址所在的模块:
HMODULE ModuleFromAddress(LPVOID lpv)
{
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
return VirtualQuery(lpv, &mbi, sizeof(mbi)) ? (HMODULE)mbi.AllocationBase : NULL;
}
#16
是啊,不过要知道函数的调用约定才行,压栈会不一样。跟踪一下代码就行了,计算参数的地址,根据ESP和EBP就可以得到的
#17
f()是自己写的,当然知道调用约定和参数个数等了。。。
能给出一个具体的代码吗?
能给出一个具体的代码吗?
#18
偶先试试看
#19
用ModuleFromAddress可能直接得到HMOULE,很有意思,不用玫举模块了。
f是你自已写的,你当然知道调用方式和参数
插汇编,直接使用esp,加上参数,加上你的局部变量就可以得到调用函数地址了
f是你自已写的,你当然知道调用方式和参数
插汇编,直接使用esp,加上参数,加上你的局部变量就可以得到调用函数地址了
#20
void __stdcall f(int a)
{
struct {
int m1;
char *m2;
} v;
//这种情况下如何计算返回地址?
//麻烦给个sample code吧,asm我已经不熟了啊
}
{
struct {
int m1;
char *m2;
} v;
//这种情况下如何计算返回地址?
//麻烦给个sample code吧,asm我已经不熟了啊
}
#21
DLL2EXP void DLL_ShowMsg(DWORD *pParentWnd, BYTE dwSize)
{
LPDWORD pdwPtr = NULL;
// Get parent address
_asm
{
mov EAX, dword ptr [ebp+4]
mov dword ptr [ebp-4], EAX
}
HMODULE hParent = ModuleFromAddress((LPVOID)pdwPtr);
MessageBox(NULL,"Test", NULL, MB_OK);
}
注意LPDWORD pdwPtr = NULL;前不要加参数,不然pdwPtr得不到地址.
{
LPDWORD pdwPtr = NULL;
// Get parent address
_asm
{
mov EAX, dword ptr [ebp+4]
mov dword ptr [ebp-4], EAX
}
HMODULE hParent = ModuleFromAddress((LPVOID)pdwPtr);
MessageBox(NULL,"Test", NULL, MB_OK);
}
注意LPDWORD pdwPtr = NULL;前不要加参数,不然pdwPtr得不到地址.
#22
这个用很简单的方法就能实现,虽然不知道是b,还是c调用了f(),但是你可以在f()的入参里面指明是b模块还是c模块对它进行了调用。为什么一定要搞的这么复杂呢?
#23
我先试试
#1
补充:f()是不知道B或C模块的名字(b.dll/c.dll)的,否则就可以用GetModuleHandle("b.dll")来获取了
#2
按我理解你的意思作一下回答
模块B/C调用f()函数,f()函数根本就不知道模块B/C的HMODULE,也不需要知道。只要模块B/C知道模块A的HMODULE就行了,也就是说模块A没必要知道模块B/C的HMODULE。除非你在你的DLL里面的DLLMAIN函数里面获取HINSTANCE也就是你所说的调用者的HMODULE了,只要
(HMODULE)Hinstance进行转换就行了
模块B/C调用f()函数,f()函数根本就不知道模块B/C的HMODULE,也不需要知道。只要模块B/C知道模块A的HMODULE就行了,也就是说模块A没必要知道模块B/C的HMODULE。除非你在你的DLL里面的DLLMAIN函数里面获取HINSTANCE也就是你所说的调用者的HMODULE了,只要
(HMODULE)Hinstance进行转换就行了
#3
_AFX_THREAD_STATE *pafxState = AfxGetThreadState();
CWinApp *pPreApp = pafxState->m_pModuleState->m_pCurrentWinApp;
其中pPreApp 就是前一个运行的程序的theapp,不过这个方法只是在mfc dll试验过
CWinApp *pPreApp = pafxState->m_pModuleState->m_pCurrentWinApp;
其中pPreApp 就是前一个运行的程序的theapp,不过这个方法只是在mfc dll试验过
#4
只有在进程载入dll时,或dll已被载入后进程里又创建了一个新线程的时候,以及线程退出、进程退出时才调用DllMain()
而DllMain()的这个hInstance只是dll自己被载入后的HMODULE,跟本不是其他模块的HMODULE。
所以 maijian(asmvc) 回答不正确,同样 holyeagle(一杯清茶) 答不对题。
而DllMain()的这个hInstance只是dll自己被载入后的HMODULE,跟本不是其他模块的HMODULE。
所以 maijian(asmvc) 回答不正确,同样 holyeagle(一杯清茶) 答不对题。
#5
我想如果有了theapp,得到相应的模块的句柄应该不是问题啊。CWinApp::m_hInstance就是app的模块的句柄。
#6
在B/C调用a中函数的时候,能不能把自己的句柄作为参数传过去?
#7
re: 我想如果有了theapp,得到相应的模块的句柄应该不是问题啊。CWinApp::m_hInstance就是app的模块的句柄。
不是问题?那到底怎么获得啊?又不知道b/c模块名。
不能传参数,因为b/c模块是别人写好的dll。
不是问题?那到底怎么获得啊?又不知道b/c模块名。
不能传参数,因为b/c模块是别人写好的dll。
#8
为什么不考虑把module handle作为参数传给f()呢
#9
theapp.m_hInstance就是实例句柄吧。
#10
如果是DEBUG版本,可以用StackWalk取得,Release版本有点难。
#11
to: msdn_user(蓝天)
其实f()模块是注入别人的进程里的,所以你要别人进程里的其他模块传module handle给f()是不可能的。
to: holyeagle(一杯清茶)
theApp.m_hInstance是进程实例句柄没错,也是进程exe文件模块句柄也没错,
但我不是要这个, 你怎么还不知道问题呢!
to: DentistryDoctor(牙科医生)
回答对口了,但是看来不简单,有没有简单点的?
其实f()模块是注入别人的进程里的,所以你要别人进程里的其他模块传module handle给f()是不可能的。
to: holyeagle(一杯清茶)
theApp.m_hInstance是进程实例句柄没错,也是进程exe文件模块句柄也没错,
但我不是要这个, 你怎么还不知道问题呢!
to: DentistryDoctor(牙科医生)
回答对口了,但是看来不简单,有没有简单点的?
#12
不是exe的,是上一级调用者的。比如在一级dll中可以得到的就是exe,二级就是上一级调用dll的句柄
#13
可以分析内存实例的PE结构,得到静态联编的各dll模块的HMODULE。但动态装载的,就没法了。不过还可以在进程地址空间内搜索“MZ”PE标志,再进一步得分析是否是一个PE模块。进程地址空间内,可以先分析内存块的属性,只分析只读和可执行的代码块。
总之,在知道了各模块的起始地址后,要得到F()函数是由哪个模块调用的,我想还是只有分析堆栈中的调用地址了,知道调用地址,就可以知道它此次调用属于哪个模块了。
总之,在知道了各模块的起始地址后,要得到F()函数是由哪个模块调用的,我想还是只有分析堆栈中的调用地址了,知道调用地址,就可以知道它此次调用属于哪个模块了。
#14
可能MS有特别的,或是未公开的(我反正不知道)函数,直接从系统数据结构中查到各个模块。但要得到调用模块,还是只有查堆栈,除非在EXE中有输出的调试信息内有。
#15
调用地址是调用者call时候被push进去的返回地址吗?
如何获得?如果能准确获得的话就一切ok了,
因为以下函数能根据地址得到地址所在的模块:
HMODULE ModuleFromAddress(LPVOID lpv)
{
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
return VirtualQuery(lpv, &mbi, sizeof(mbi)) ? (HMODULE)mbi.AllocationBase : NULL;
}
如何获得?如果能准确获得的话就一切ok了,
因为以下函数能根据地址得到地址所在的模块:
HMODULE ModuleFromAddress(LPVOID lpv)
{
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
return VirtualQuery(lpv, &mbi, sizeof(mbi)) ? (HMODULE)mbi.AllocationBase : NULL;
}
#16
是啊,不过要知道函数的调用约定才行,压栈会不一样。跟踪一下代码就行了,计算参数的地址,根据ESP和EBP就可以得到的
#17
f()是自己写的,当然知道调用约定和参数个数等了。。。
能给出一个具体的代码吗?
能给出一个具体的代码吗?
#18
偶先试试看
#19
用ModuleFromAddress可能直接得到HMOULE,很有意思,不用玫举模块了。
f是你自已写的,你当然知道调用方式和参数
插汇编,直接使用esp,加上参数,加上你的局部变量就可以得到调用函数地址了
f是你自已写的,你当然知道调用方式和参数
插汇编,直接使用esp,加上参数,加上你的局部变量就可以得到调用函数地址了
#20
void __stdcall f(int a)
{
struct {
int m1;
char *m2;
} v;
//这种情况下如何计算返回地址?
//麻烦给个sample code吧,asm我已经不熟了啊
}
{
struct {
int m1;
char *m2;
} v;
//这种情况下如何计算返回地址?
//麻烦给个sample code吧,asm我已经不熟了啊
}
#21
DLL2EXP void DLL_ShowMsg(DWORD *pParentWnd, BYTE dwSize)
{
LPDWORD pdwPtr = NULL;
// Get parent address
_asm
{
mov EAX, dword ptr [ebp+4]
mov dword ptr [ebp-4], EAX
}
HMODULE hParent = ModuleFromAddress((LPVOID)pdwPtr);
MessageBox(NULL,"Test", NULL, MB_OK);
}
注意LPDWORD pdwPtr = NULL;前不要加参数,不然pdwPtr得不到地址.
{
LPDWORD pdwPtr = NULL;
// Get parent address
_asm
{
mov EAX, dword ptr [ebp+4]
mov dword ptr [ebp-4], EAX
}
HMODULE hParent = ModuleFromAddress((LPVOID)pdwPtr);
MessageBox(NULL,"Test", NULL, MB_OK);
}
注意LPDWORD pdwPtr = NULL;前不要加参数,不然pdwPtr得不到地址.
#22
这个用很简单的方法就能实现,虽然不知道是b,还是c调用了f(),但是你可以在f()的入参里面指明是b模块还是c模块对它进行了调用。为什么一定要搞的这么复杂呢?
#23
我先试试