Winapi 使用EasyHook(c#)从ntdll.dll挂接NtCreateFile API
这是我第一次尝试钩住windows API。我的目标是监视进程将要创建/打开/读取/写入的所有文件。 为了尽可能详细,我决定钩住ntdll.dll API,如NtCreateFile()和NtOpenFile()。所以,为了实现这个目标,我选择了EasyHook,它看起来简单而健壮。 我一直遵循FileMon示例,更改了我真正想要的:Hooked函数。 当我尝试读取有关将要打开的文件的信息时,我尝试从对象属性结构中读取信息,例如 对象名。这些是整数指针,因此我希望使用函数Marshal.PtrToStringAuto(attributes.objectName)来获取字符串值。然而,结果是我只能有坏字符串,没有任何意义。此外,文件访问似乎不起作用。我想这有点不对劲 代码,可能在DllImport签名中。我不得不用IntPtr替换SafeHandle,因为EasyHook正在抱怨对它们进行编组。 有人能帮我吗 以下是我的注入DLL的特定代码: 下面是Run方法代码Winapi 使用EasyHook(c#)从ntdll.dll挂接NtCreateFile API,winapi,hook,kernel32,ntdll,easyhook,Winapi,Hook,Kernel32,Ntdll,Easyhook,这是我第一次尝试钩住windows API。我的目标是监视进程将要创建/打开/读取/写入的所有文件。 为了尽可能详细,我决定钩住ntdll.dll API,如NtCreateFile()和NtOpenFile()。所以,为了实现这个目标,我选择了EasyHook,它看起来简单而健壮。 我一直遵循FileMon示例,更改了我真正想要的:Hooked函数。 当我尝试读取有关将要打开的文件的信息时,我尝试从对象属性结构中读取信息,例如 对象名。这些是整数指针,因此我希望使用函数Marshal.PtrT
public void Run(RemoteHooking.IContext InContext, String inChannelName)
{
// First of all, install all the hooks
try
{
// NtCreateFile
fileCreationHook = LocalHook.Create(
LocalHook.GetProcAddress("ntdll.dll", "NtCreateFile"),
new CreateFileDelegate(CreateFile_Hooked),
this
);
fileCreationHook = LocalHook.Create(
LocalHook.GetProcAddress("ntdll.dll", "NtOpenFile"),
new OpenFileDelegate(OpenFile_Hooked),
this
);
fileCreationHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });
remoteIf.Log("File creation Hook correctly installed on pid "+RemoteHooking.GetCurrentProcessId());
}
catch (Exception e)
{
remoteIf.Log(e.Message);
remoteIf.Log(e.StackTrace);
return;
}
// Wake up the process
remoteIf.Log("Waiking up process...");
RemoteHooking.WakeUpProcess();
while (true)
{
Thread.Sleep(500);
if (queue.Count > 0)
{
String[] package = null;
lock (queue)
{
package = queue.ToArray();
queue.Clear();
}
remoteIf.OnCreateFile(RemoteHooking.GetCurrentProcessId(), package);
}
else
remoteIf.Ping();
}
}
以下是承包商代码:
public InjectedDLL(RemoteHooking.IContext InContext, String inChannelName)
{
// Create the structure which will contain all the messages
queue = new Stack<string>();
// Initiate the connection to the Injector process, getting back its interface
remoteIf = RemoteHooking.IpcConnectClient<IPCInterface>(inChannelName);
// Try invocating a method to test the connection.
remoteIf.Ping();
}
以下是NtDll.Dll本机函数:
[DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
public static extern int NtCreateFile(
out IntPtr handle,
System.IO.FileAccess access,
ref OBJECT_ATTRIBUTES objectAttributes,
out IO_STATUS_BLOCK ioStatus,
ref long allocSize,
uint fileAttributes,
System.IO.FileShare share,
uint createDisposition,
uint createOptions,
IntPtr eaBuffer,
uint eaLength);
[DllImport("ntdll.dll", ExactSpelling = true, SetLastError = true)]
public static extern int NtOpenFile(
out IntPtr handle,
System.IO.FileAccess access,
ref OBJECT_ATTRIBUTES objectAttributes,
out IO_STATUS_BLOCK ioStatus,
System.IO.FileShare share,
uint openOptions
);
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct OBJECT_ATTRIBUTES
{
public Int32 Length;
public IntPtr RootDirectory;
public IntPtr ObjectName;
public uint Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct IO_STATUS_BLOCK
{
public uint status;
public IntPtr information;
}
ObjectName是指向UNICODE_字符串结构的指针。托管等效项如下所示:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
public String Buffer;
}
您需要使用封送处理来获取结构的托管副本
var us = Marshal.PtrToStructure<UNICODE_STRING>(objectAttributes.ObjectName);
var us=Marshal.PtrToStructure(objectAttributes.ObjectName);
拥有托管结构后,可以访问缓冲区字段以获取对象的名称。ObjectName是指向UNICODE字符串结构的指针。托管等效项如下所示:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct UNICODE_STRING
{
public ushort Length;
public ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
public String Buffer;
}
您需要使用封送处理来获取结构的托管副本
var us = Marshal.PtrToStructure<UNICODE_STRING>(objectAttributes.ObjectName);
var us=Marshal.PtrToStructure(objectAttributes.ObjectName);
一旦您拥有托管结构,您就可以访问缓冲区字段以获取对象的名称。您找到了吗?没有,我切换回了Microsoft DeTorus。您找到了吗?没有,我切换回了Microsoft DeTorus。