我想编写一个myHid.dll来劫持A程序对系统Hid.dll的函数调用,但是A程序运行后每次都崩溃,用OD跟踪发现是A程序调用myHid中的函数输入的参数没有出栈,导致栈数据错误。也就是A ---》压栈参数--》调用HidD_GetHidGuid(myHid函数)---》压栈参数--》调用jidD_GetHidGuid(对应系统Hid函数地址)--》jidD_GetHidGuid返回参数出栈---》HidD_GetHidGuid函数返回上述过程中缺少一个A压入参数的出栈过程,我加入汇编手动清栈才能正常,但是始终不明白是什么原因导致的,请各位大牛指点,谢谢。 __asm{
add esp,4
ret 4 //返回时清栈参数
}
函数大致如下:自定义函数的声名和定义:typedef void (__stdcall*JidD_GetHidGuid)(OUT LPGUID HidGuid);JidD_GetHidGuid jidD_GetHidGuid ;
导出函数:
extern "C" __declspec(dllexport) void HidD_GetHidGuid( OUT LPGUID HidGuid)
{
jidD_GetHidGuid( HidGuid); //须要加入如下汇编
__asm{
add esp,4
ret 4
} return ;
}在DllMain函数中载入系统的Hid.dll,并获取到对应的函数地址。
hinstance = LoadLibrary("c:\\windows\\system32\\hid.dll");
jidD_GetHidGuid = (JidD_GetHidGuid )GetProcAddress(hinstance, "HidD_GetHidGuid");栈汇编Hid.dll
add esp,4
ret 4 //返回时清栈参数
}
函数大致如下:自定义函数的声名和定义:typedef void (__stdcall*JidD_GetHidGuid)(OUT LPGUID HidGuid);JidD_GetHidGuid jidD_GetHidGuid ;
导出函数:
extern "C" __declspec(dllexport) void HidD_GetHidGuid( OUT LPGUID HidGuid)
{
jidD_GetHidGuid( HidGuid); //须要加入如下汇编
__asm{
add esp,4
ret 4
} return ;
}在DllMain函数中载入系统的Hid.dll,并获取到对应的函数地址。
hinstance = LoadLibrary("c:\\windows\\system32\\hid.dll");
jidD_GetHidGuid = (JidD_GetHidGuid )GetProcAddress(hinstance, "HidD_GetHidGuid");栈汇编Hid.dll
__stdcall调用约定用于调用Win32 API函数。采用__stdcal约定时,函数参数按照从右到左的顺序入栈,被调用的函数在返回前清理传送参数的栈,函数参数个数固定。由于函数体本身知道传进来的参数个数,因此被调用的函数可以在返回前用一条ret n指令直接清理传递参数的堆栈。是否可以这样理解,A程序调用Hid函数使用的是__stdcall 方式,即由被调用者释放参数栈,而我实现的myHId函数是__cdecl方式(即由调用者释放参数栈),导致参数栈错误,这些栈释放不是编译器自动搞定吗?如果是上述问题如何修改呢?
EXPORTS
HidD_GetAttributes @1
HidD_GetHidGuid @2 VS2008在链接器-》输入-》模块定义文件中增加对应的.def即可。 使用OD跟踪下堆栈参数释放正确:)