在Delphi中挂钩LdrLoadDll时应用程序崩溃

时间:2014-08-09 10:50:19

标签: delphi dll hook

我挂钩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,并且完全期待这个!

有什么想法吗? {对不起我的英语不好}

1 个答案:

答案 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执行一项非常具体的任务,您必须小心避免破坏它。