为什么 "RtlGetFullPathName_U "在ntdll.dll和reactos的文档中看起来不一样?

问题描述 投票:0回答:1

我把一个Windows API函数挂在了文档中 RtlGetFullPathName_U (驻留在ntdll.dll中),来检测游戏中的进程注入。然而,当在IDA中查看该函数时,该函数类型看起来不一样,而当通过我能找到的关于该函数的唯一信息(从ReactOS的文档中)查看该函数时,也不一样。

在IDA中查看时。

enter image description here

上面分析的文件是 ntdll.dll 通过x32dbg找到。

enter image description here

当在ReactOS的 文件我明白了 RtlGetFullPathName_U 看起来像这样。

ULONG
 NTAPI
 RtlGetFullPathName_U(
     IN PCWSTR FileName,
     IN ULONG Size,
     IN PWSTR Buffer,
     OUT PWSTR *ShortName
 );

使用ReactOS版本的 RtlGetFullPathName_U 钩子的时候可以用,但我注意到参数的数量有差别,这是为什么呢?我的意思是我的方法通常是通过IDA查看导出的函数,而不是通过ReactOS的文档。

最后一个问题;我还有没有其他相关的函数可以钩住来检测进程注入?除了LoadLibraryAWEx?

c++ winapi hook ntdll
1个回答
2
投票

正如你在拆解中所看到的,该函数使用的是 push ecx 早期,其次是将刚刚推送的值的地址保存在 eax. 地址在 eax 因此,你在反编译器输出中读到的内容在技术上并没有错:它将ecx的值存储在一个局部变量中,然后将该局部变量的地址传递给了 RtlGetFullPathName_UEx.为了捕获这一点,IDA假设传递给函数的值在 ecx 可能很重要,并将其作为一个参数。

然而,最可能的是,真正的目的是将 push ecx 的值,这里的指令是不保存 ecx,但只是在堆栈上为一个局部变量保留四个字节(一个更常见的习惯用语是 sub esp, 4). 使用 push 是一种优化。

要想明确证实这一点,你必须分析被调用的函数。RtlGetFullPathName_UEx,看看它是否曾经读取过它最后一个参数所指向的内存的内容。如果像我强烈怀疑的那样,它没有,而且这个参数只用于输出,那么调用器中的值可以简单地认为是未初始化的。

在你确认了这一点之后(或者如果出于其他原因,比如相信ReactOS的声明,你相信是这样的),你可以修改函数原型,使用 __stdcall 并去除 void *this 参数,它将显示出它(可能)是什么:传递一个指向未初始化的局部变量的指针。

© www.soinside.com 2019 - 2024. All rights reserved.