Problem with NTCreateProcess again

c++ / delphi package - dll injection and api hooking
Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Problem with NTCreateProcess again

Post by Runner »

I am sorry to bother this forum again with the same problem I did twice already but I just can't make it work. My hook based on example by Madshi which hooks all userland APIs that can start a process works perfectly, but I would like to hook NTCreateProcess and NTCreateProcessEx, but my code bellow is not working (crashes)

Code: Select all

library HookProcessCreation; 

{$IMAGEBASE $57000000} 

uses Windows, SysUtils, madCodeHook, JWaWinBase, JwaWinNT, JwaWinType, Native; 


var NtCreateProcessNextHook: function(ProcessHandle: PHANDLE; DesiredAccess: ACCESS_MASK; ObjectAttributes: POBJECT_ATTRIBUTES; InheritFromProcessHandle: HANDLE; InheritHandles: ByteBool; SectionHandle: HANDLE; DebugPort: HANDLE; ExceptionPort: HANDLE): NTSTATUS; stdcall;

var NtCreateProcessExNextHook: function(ProcessHandle: PHANDLE; DesiredAccess: ACCESS_MASK; ObjectAttributes: POBJECT_ATTRIBUTES; InheritFromProcessHandle: HANDLE; InheritHandles: ByteBool; SectionHandle: HANDLE; DebugPort: HANDLE; ExceptionPort: HANDLE; SafeFlags : DWORD): NTSTATUS; stdcall;


function NtCreateProcessCallbackProc(ProcessHandle: PHANDLE; DesiredAccess: ACCESS_MASK; ObjectAttributes: POBJECT_ATTRIBUTES; InheritFromProcessHandle: HANDLE; InheritHandles: ByteBool; SectionHandle: HANDLE; DebugPort: HANDLE; ExceptionPort: HANDLE): NTSTATUS; stdcall;
begin
   Result := NtCreateProcessNextHook(ProcessHandle, DesiredAccess, ObjectAttributes, InheritFromProcessHandle, InheritHandles, SectionHandle, DebugPort, ExceptionPort);
   MessageBox(0,'Hooked','Hooked',MB_OK);
end;

function NtCreateProcessExCallbackProc(ProcessHandle: PHANDLE; DesiredAccess: ACCESS_MASK; ObjectAttributes: POBJECT_ATTRIBUTES; InheritFromProcessHandle: HANDLE; InheritHandles: ByteBool; SectionHandle: HANDLE; DebugPort: HANDLE; ExceptionPort: HANDLE; SafeFlags : DWORD): NTSTATUS; stdcall;
begin
   Result := NtCreateProcessExNextHook(ProcessHandle, DesiredAccess, ObjectAttributes, InheritFromProcessHandle, InheritHandles, SectionHandle, DebugPort, ExceptionPortm, SafeFlags);
   MessageBox(0,'Hooked','Hooked',MB_OK);
end;

begin
  HookAPI('ntdll.dll', 'NtCreateProcess', @NtCreateProcessCallbackProc, @NtCreateProcessNextHook);
  HookAPI('ntdll.dll', 'NtCreateProcessEx', @NtCreateProcessExCallbackProc, @NtCreateProcessExNextHook);
end.
This code is the barebone and the NTCreateProcess hook works but NTCreateProcessEx crashes. Madshi said and I thought to, that the extra parameter should be a DWORD type. But that is not working. I tried some other 4 byte parameter types but none of them work.

The other problem is that I cannot get image name from ObjectAttributes parameter. The name us UNICODE_STRING. I though that in my callback the parameter is already initialized but it crashes if I access it. I wrote a little driver a while ago which read and wrote to Registry and I know unicode strings but I just can't make this work. I also saw that Object attributes is an optional parameter, so I guess it can be empty. Is there a way at all to get the path and exe name of the process to be created.

And one more thing. Is there a way to inject the hook from a kernel mode driver. Probably not becouse madCodeHook is user mode library, but madshi uses a driver for his internal purposes. Just curious.

Again sorry for bringing this up again. I like to solve my own problems but this proved to be a steel wall for me. :sorry:
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Re: Problem with NTCreateProcess again

Post by madshi »

Runner wrote:This code is the barebone and the NTCreateProcess hook works but NTCreateProcessEx crashes.
What kind of crash is that?
Runner wrote:The other problem is that I cannot get image name from ObjectAttributes parameter. The name us UNICODE_STRING. I though that in my callback the parameter is already initialized but it crashes if I access it. I wrote a little driver a while ago which read and wrote to Registry and I know unicode strings but I just can't make this work.
It's not a unicode string (PWideChar), it's a UNICODE_STRING. That's a structure. Don't know whether you know that. Just wanted to clarify it.
Runner wrote:And one more thing. Is there a way to inject the hook from a kernel mode driver.
You mean you want to have the hook dll injected from driver land? But that's exactly what madCodeHook is doing (for newly created processes only, though)!
Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Post by Runner »

I know that UNICODE_STRING is a structure. As I said I wrote a little driver (nothing special) that writes and reads the Registry. I know that UNICODE_STRINGS need to be initialized. In C it worked OK, but here I am not sure if the string is already initialized when I read it in my callback function or I have to initialize manually. It should already contain the path to the image file or am I wrong?

For the DWORD parameter error in NTCreateProcessEx it just reports, "Wrong parameter type" after displaying the message box.
I don't know which type the last parameter is.

For the ObjectAttributes I can't remember the what exactly it was. When I get home I can try and see. I haven't posted the code where I try to read the UNICODE_STRING because I am not sure if it is correct.

I was hoping you could push me in the right direction. I am not sure if only reading the "ObjectAttributes.ObjectName.Buffer" is enough. Here the hook always crashes.What is the right way to read the UNICODE_STRING structure in Delphi. I am really lost here because of the constant errors.
If it is little work maybe you can add the two or three lines that you think would do the job. I would be really gratefull. Or maybe you can see my error.

For the driver injection : I know you hook newly created processes this way. The problem is that services start very late in Windows XP, after Gina completes initialization. You can manipulate service startup by adding you service into a group but it is still late. So I would like and try to inject my hook right after win32 subsystem in set up if that is possible.

Sorry if I sound confused, I am writing this from work. If you need more data I will be happy to provide it. :D
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Runner wrote:It should already contain the path to the image file or am I wrong?
I think it should.
Runner wrote:For the DWORD parameter error in NTCreateProcessEx it just reports, "Wrong parameter type" after displaying the message box.
I don't know which type the last parameter is.
That's strange. Windows complains in a message box about the parameter type!? Can you send me a screenshot?
Runner wrote:I was hoping you could push me in the right direction. I am not sure if only reading the "ObjectAttributes.ObjectName.Buffer" is enough. Here the hook always crashes.
Did you define the structures yourself or do you get them from somewhere? Maybe the definition is wrong? Not sure...
Runner wrote:What is the right way to read the UNICODE_STRING structure in Delphi.
I think just reading it... :-)
Runner wrote:If it is little work maybe you can add the two or three lines that you think would do the job. I would be really gratefull. Or maybe you can see my error.
I really don't have any time in the moment. Maybe I can see your error, but you didn't show me the source code which crashes yet.
Runner wrote:For the driver injection : I know you hook newly created processes this way. The problem is that services start very late in Windows XP, after Gina completes initialization. You can manipulate service startup by adding you service into a group but it is still late. So I would like and try to inject my hook right after win32 subsystem in set up if that is possible.
Right now it's not possible by using madCodeHook to inject your dll earlier than when your first win32 service loads. Maybe (maybe eventually possibly) this might be added in a future version, but not anytime soon, I guess.
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

P.S: Are you sure that ByteBool is correct? I'd suggest to replace all types with a simple "dword". Then theoretically nothing go wrong.
uall
Posts: 254
Joined: Sun Feb 20, 2005 1:24 pm

Post by uall »

Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Post by Runner »

That's strange. Windows complains in a message box about the parameter type!? Can you send me a screenshot?
I wrote it wrong. First my MessageBox which I call is shown and when I press OK on the messageBox the "Parameter type is incorrect" error is shown.
But NTCreateProcess Calback work fine and if I call the NtCreateProcessExNextHook from NtCreateProcessExCallbackProc it also works fine. I used Jedi declaration and function declaration in Native.pas
Maybe that is wrong and is also the cause of the UNICODE_STRING problem.

For the image name problem here is the code that crashes the computer

Code: Select all

function NtCreateProcessExCallbackProc(ProcessHandle : PHANDLE;
                                       DesiredAccess: ACCESS_MASK;
                                       ObjectAttributes: POBJECT_ATTRIBUTES;
                                       InheritFromProcessHandle: HANDLE;
                                       InheritHandles: ByteBool;
                                       SectionHandle: HANDLE;
                                       DebugPort: HANDLE;
                                       ExceptionPort: HANDLE;
                                       dwSaferFlags: DWORD): NTSTATUS; stdcall;
begin
   MessageBoxW(0, ObjectAttributes.ObjectName.Buffer, '', MB_OK);
   Result := NtCreateProcessExNextHook(ProcessHandle,
                                     DesiredAccess,
                                     ObjectAttributes,
                                     InheritFromProcessHandle,
                                     InheritHandles,
                                     SectionHandle,
                                     DebugPort,
                                     ExceptionPort,
                                     dwSaferFlags);
end;
It also crashes if I do it in NTCreateProcess Callback. The rest of the code is the same that I posted earlier. I think that error message is something about access violation. So I gues that the string is not initialized or something like that.

I can try and define UNICODE_STRING structure myself. Is callback code ok?
Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Post by Runner »

You were right. ByteBool was the problem. Weird but true. I replaced it with DWORD and it works :D Thanks guys

Now to solve the second one and I will be happy again :crazy:
uall
Posts: 254
Joined: Sun Feb 20, 2005 1:24 pm

Post by uall »

you can use dword (and there will be no problem) BUT its not the correct value, you should use

inherited: boolean;

like you see it in the header of kernel32.CreateProcess
also
http://undocumented.ntinternals.net/Use ... ocess.html
shows thats it should be a boolean

____
EDIT:
found on google:
http://www.hackhome.com/2005/3-19/11171552327.shtml
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

boolean = byteBool, so that won't work, either. You can use a LongBool, though. In C++, boolean is usually 4 bytes long.

How does the definition of POBJECT_ATTRIBUTES look like?
Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Post by Runner »

you can use dword (and there will be no problem) BUT its not the correct value, you should use

inherited: boolean;
I agree, I also read that prototypes. But it works with DWORD and it reports the earlier mentioned error with boolean. Sure there is a mistake somewhere : boolean is 1 byte and DWORD 4 bytes. Hardly equal :D

My code that still crashes lookes like this now. I defined everything myself

Code: Select all

library HookProcessCreation;

{$IMAGEBASE $57000000}

uses
  Windows,
  madCodeHook;
  
type 
  USHORT = WORD; 
  NTSTATUS = ULONG; 
  PVOID = Pointer; 

type
  TUnicodeString = packed record 
    Length: USHORT; 
    MaximumLength: USHORT; 
    Buffer: PWideChar; 
  end; 
  UNICODE_STRING = TUnicodeString; 
  PUNICODE_STRING = ^UNICODE_STRING; 

// DEFINE Native API OBJECT ATTRIBUTES 

  TObjectAttributes = packed record 
    Length: ULONG; 
    RootDirectory: THandle; 
    ObjectName: PUNICODE_STRING; 
    Attributes: ULONG; 
    SecurityDescriptor: PVOID;        // Points to type SECURITY_DESCRIPTOR 
    SecurityQualityOfService: PVOID;  // Points to type SECURITY_QUALITY_OF_SERVICE 
  end; 
  OBJECT_ATTRIBUTES = TObjectAttributes; 
  POBJECT_ATTRIBUTES = ^OBJECT_ATTRIBUTES; 

var NtCreateProcessNextHook: function(ProcessHandle : PHANDLE;
                                      DesiredAccess: ACCESS_MASK;
                                      ObjectAttributes: POBJECT_ATTRIBUTES;
                                      InheritFromProcessHandle: DWORD;
                                      InheritHandles: DWORD;
                                      SectionHandle: DWORD;
                                      DebugPort: DWORD;
                                      ExceptionPort: DWORD): NTSTATUS; stdcall;

var NtCreateProcessExNextHook: function(ProcessHandle : PHANDLE;
                                        DesiredAccess: ACCESS_MASK;
                                        ObjectAttributes: POBJECT_ATTRIBUTES;
                                        InheritFromProcessHandle: DWORD;
                                        InheritHandles: DWORD;
                                        SectionHandle: DWORD;
                                        DebugPort: DWORD;
                                        ExceptionPort: DWORD;
                                        dwSaferFlags: DWORD): NTSTATUS; stdcall;

function NtCreateProcessCallbackProc(ProcessHandle : PHANDLE;
                                     DesiredAccess: ACCESS_MASK;
                                     ObjectAttributes: POBJECT_ATTRIBUTES;
                                     InheritFromProcessHandle: DWORD;
                                     InheritHandles: DWORD;
                                     SectionHandle: DWORD;
                                     DebugPort: DWORD;
                                     ExceptionPort: DWORD): NTSTATUS; stdcall;
begin
   Result := NtCreateProcessNextHook(ProcessHandle,
                                     DesiredAccess,
                                     ObjectAttributes,
                                     InheritFromProcessHandle,
                                     InheritHandles,
                                     SectionHandle,
                                     DebugPort,
                                     ExceptionPort);
   MessageBox(0,'Hooked','Hooked',MB_OK);
end;

function NtCreateProcessExCallbackProc(ProcessHandle : PHANDLE;
                                       DesiredAccess: ACCESS_MASK;
                                       ObjectAttributes: POBJECT_ATTRIBUTES;
                                       InheritFromProcessHandle: DWORD;
                                       InheritHandles: DWORD;
                                       SectionHandle: DWORD;
                                       DebugPort: DWORD;
                                       ExceptionPort: DWORD;
                                       dwSaferFlags: DWORD): NTSTATUS; stdcall;
begin
   MessageBoxW(0, ObjectAttributes^.ObjectName^.Buffer, '', MB_OK);
   Result := NtCreateProcessExNextHook(ProcessHandle,
                                     DesiredAccess,
                                     ObjectAttributes,
                                     InheritFromProcessHandle,
                                     InheritHandles,
                                     SectionHandle,
                                     DebugPort,
                                     ExceptionPort,
                                     dwSaferFlags);
end;

begin
  HookAPI('ntdll.dll', 'NtCreateProcess', @NtCreateProcessCallbackProc, @NtCreateProcessNextHook);
  HookAPI('ntdll.dll', 'NtCreateProcessEx', @NtCreateProcessExCallbackProc, @NtCreateProcessExNextHook);
end.
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Well, then seemingly NtCreateProcess is called before without a filled in name. Don't know why, though...
Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Post by Runner »

It seems that way. Too bad though I hoped to solve the problem this way and that that i was my error in there. I will explorer a little more but I can't see any more paths to solve the problem right now.
madshi
Site Admin
Posts: 10766
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Theoretically the section handle can tell you the name of the executable. At least in driver land. Don't know whether it's possible in application land. I'd say: Give out the section handle and check with the process monitor from sysinternals whether the handle is listed in the handle table of the process which called NtCreateProcess(Ex).
Runner
Posts: 90
Joined: Tue Dec 14, 2004 1:04 pm

Post by Runner »

From the undocumented NT api functions. Reference from NTOpenProcess :
ObjectAttributes :

For standard processes, all fields of ObjectAttributes should be NULL.
Thats why I get acess violations. Because the object is not initialized at all. I will look at the possibility that Madshi mentioned but I must say I see little chance of succeding here. Probably will be stuck with my current solution which is not bad but has to many ways of a process being created and it is hard to find a good solution to check the process paths for all the APIs.

Anyway thanks for the help, both of you. If you have any more ideas please let me know. :wink:
Post Reply