我挂钩LdrLoadDll
来检测程序中所有Dll的加载。
这是我的代码钩子部分:
var
Old_LdrLoadDll: function(szcwPath: PChar; pdwLdrErr: PULONG;
pUniModuleName: PUnicodeString; pResultInstance: PPointer)
: NTStatus; stdcall;
....
工作:
function New_LdrLoadDll(szcwPath:PChar ; pdwLdrErr: PULONG;
pUniModuleName: PUnicodeString; pResultInstance: PPointer): NTStatus; stdcall;
begin
OutputDebugString('New_LdrLoadDll');
Result := Old_LdrLoadDll(szcwPath, pdwLdrErr, pUniModuleName,
pResultInstance);
end;
但是当我在New_LdrLoadDll
应用程序中添加任何其他命令时,崩溃了!
我使用可持续钩子方法,我确定问题不是挂钩nethod,我测试了许多其他API,并且完全期待这个!
有什么想法吗? {对不起我的英语不好}
答案 0 :(得分:1)
据我所知(http://msdn.microsoft.com/en-us/magazine/cc301727.aspx),第二个参数实际上是DWORD
。
另一个明显的问题是第三个参数不是PUnicodeString
。这被声明为^UnicodeString
,指向Delphi Unicode字符串的指针。您需要以下内容:
type
PUNICODE_STRING = ^UNICODE_STRING;
UNICODE_STRING = packed record
Length: Word;
MaximumLength: Word;
Buffer: PWideChar;
end;
然后应该像这样声明函数:
var
Old_LdrLoadDll: function(szcwPath: PWideChar; dwFlags: DWORD; pUniModuleName:
PUNICODE_STRING; pResultInstance: PPointer): NTSTATUS; stdcall;
function LdrLoadDll(szcwPath: PWideChar; dwFlags: DWORD; pUniModuleName:
PUNICODE_STRING; pResultInstance: PPointer): NTSTATUS; stdcall;
begin
Result := Old_LdrLoadDll(szcwPath, pdwLdrErr, pUniModuleName, pResultInstance);
end;
当您尝试阅读pUniModuleName
时,可能会发生崩溃。
您可能遇到的另一个明显问题是,您最终可能会调用尚未加载且尚未准备好调用的模块中的代码。某些模块在运行时按需加载。例如,看看拨打ShowMessage
时会发生什么。
另一个问题是,如果LdrLoadDll
调用导致递归调用LdrLoadDll
的函数,则很容易导致堆栈溢出。我在调用MessageBox
时遇到了这个问题。
这里的底线是你可以安全地调用kernel32
中的函数,但可能没什么其他的。请记住,LdrLoadDll
执行一项非常具体的任务,您必须小心避免破坏它。