Connecting NtCreateFile API from ntdll.dll using EasyHook (C #)

This is the first time I'm trying to connect the windows API. My goal is to control all the files that the process is going to create / open / read / write. To be more detailed, I decided to connect the ntdll.dll API, such as NtCreateFile () and NtOpenFile (). So, in order to achieve this goal, I went for EasyHook, which seems simple and reliable. I carefully followed the FileMon example, modifying what I really wanted: the hooked function. When I try to read information about a file that will be opened, I try to read information from the OBJECT_ATTRIBUTES structure, such as ObjectName. These are integer pointers, so I expected to use the Marshal.PtrToStringAuto (attributes.objectName) function to get a string value. However, as a result, I can only have bad lines without any meaning. Also, file access does not seem to work. I think there is something wrong with this code, possibly in the DllImport signatures. Be careful, I had to replace SafeHandle with IntPtr, because EasyHook complained about their marshaling. Can anybody help me?

Here is my special nested DLL code:

Here is the code of the launch method

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(); } } 

Here's the constructor code:

 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(); } 

There is a Hook delegate here and a hook function

 public delegate int CreateFileDelegate(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); public int CreateFile_Hooked( 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) { //string s = Marshal.PtrToStringAuto(objectAttributes.ObjectName); int res = NtCreateFile(out handle, access,ref objectAttributes,out ioStatus, ref allocSize,fileAttributes, share,createDisposition,createOptions,eaBuffer,eaLength); return res; } 

There are built-in NtDll.Dll functions here:

 [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; } 
+1
winapi hook kernel32 ntdll easyhook
source share
1 answer

ObjectName is a pointer to a UNICODE_STRING structure. The managed equivalent is as follows:

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct UNICODE_STRING { public ushort Length; public ushort MaximumLength; [MarshalAs(UnmanagedType.LPWStr)] public String Buffer; } 

You need to use sorting to get a managed copy of the structure.

 var us = Marshal.PtrToStructure<UNICODE_STRING>(objectAttributes.ObjectName); 

Once you have a managed structure, you can access the Buffer field to get the name of the object.

0
source share

All Articles