2

I'm injecting a DLL inside explorer.exe to hook CreateProcess, this way I can intercept when user open some executables (I choose this hook method because I'm trying to learn more about hooks, I know could be done using WMI, or other ways). The library I'm using to hook is: DDetours

The hook is working, and every app I execute popup the messagebox I set in the HookProc, but right after the messagebox, explorer.exe crashes. The code to inject DLL is working fine, and if I just inject an empty dll or a dll with just a messagebox everything works properly. So I believe the problem is somewhere in the hook setup. Here is the DLL code:

library DLL;

uses
  Windows, DDetours;

{$R *.res}

var
  CreateProcessHook: function(var lpApplicationName:String;
            lpCommandLine:String;
            lpProcessAttributes:IntPtr;
            lpThreadAttributes:IntPtr;
            bInheritHandles:Boolean;
            dwCreationFlags:Int32;
            lpEnvironment:IntPtr;
            lpCurrentDirectory:IntPtr;
            lpStartupInfo:STARTUPINFO;
            lpProcessInformation:PROCESS_INFORMATION): Boolean; stdcall = nil;

function InterceptCreateProcess(lpApplicationName:String;
            lpCommandLine:String;
            lpProcessAttributes:IntPtr;
            lpThreadAttributes:IntPtr;
            bInheritHandles:Boolean;
            dwCreationFlags:Int32;
            lpEnvironment:IntPtr;
            lpCurrentDirectory:IntPtr;
            lpStartupInfo:STARTUPINFO;
            lpProcessInformation:PROCESS_INFORMATION): Boolean; stdcall;
  begin
    MessageBoxA(0, 'Process created :)', 'Hooked', 0);
  end;

procedure DLLMain(dwReason: DWORD);
begin
  case dwReason of
  DLL_PROCESS_ATTACH:
  begin
    MessageBoxA(0,'Injected', 'Injected', MB_OK);
    @CreateProcessHook:= InterceptCreate(@CreateProcess, @InterceptCreateProcess);
  end;
  end;
end;

begin
 DLLProc := @DLLMain;
 DLLMain(DLL_PROCESS_ATTACH);
end.

As you can see, the InterceptCreateProcess just shows a message box, and this is working when I open some executable, but like said above, explorer crashes. I think that's something with the declaration of the CreateProcess function variables. Any tips? everything is 64bits

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
user3810691
  • 531
  • 5
  • 21

2 Answers2

3

Your signature for your CreateProcess detour is completely wrong. That function, a Win32 function, does not operate on Delphi strings. And the final two parameters are pointers to structs.

The first step is to fix these signatures. Use the signature from the Windows unit in the RTL.

It looks something like this:

function CreateProcessW(
  lpApplicationName: PWideChar;
  lpCommandLine: PWideChar;
  lpProcessAttributes: PSecurityAttributes;
  lpThreadAttributes: PSecurityAttributes;
  bInheritHandles: BOOL;
  dwCreationFlags: DWORD;
  lpEnvironment: Pointer;
  lpCurrentDirectory: PWideChar;
  const lpStartupInfo: STARTUPINFO;
  var lpProcessInformation: PROCESS_INFORMATION
): BOOL; stdcall;
David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Yes I tried to. But still crashing. Wait, I'll try again and paste here the signature. – user3810691 Jul 09 '14 at 01:45
  • Not quite. See my answer. – Remy Lebeau Jul 09 '14 at 01:52
  • No. You just need to do what I said in my answer. Use the exact same definition as in Windows unit. I rolled back your edit because it invalidated my answer. – David Heffernan Jul 09 '14 at 01:53
  • OK. No problem. I'll check the Windows unit. Thank's for help guys. – user3810691 Jul 09 '14 at 01:56
  • Well, like I said I'm just learning more about hook. I'm the kind of person that not quite good with programming (my maths logic is really bad since school days hehe). So I accepted your advice to not mess with windows critical processes. And I got the same point using explorer.exe, so that all good. – user3810691 Jul 09 '14 at 02:01
  • So do you need more help there? Or did I not answer the question. I actually wondered whether you did not yet know how to accept, you being new, and was gently leading you towards that knowledge. But it seems you do know how to accept. – David Heffernan Jul 09 '14 at 02:03
  • I can accept, but that answer was just vague about my question. I just thought could be "wrong" to accept an answer that is not really answering the question. If I could accept your comment "Almost anything other than a high integrity critical system process..." would be good. Anyway I'll accept the answer. – user3810691 Jul 09 '14 at 02:08
  • @user I don't agree that it didn't answer the Q. You stated that you had a 32 bit injector with a 64 bit target. And that always fails. I don't see any reason to look beyond that. The comment about csrss being a bad target was more general advice. – David Heffernan Jul 09 '14 at 02:10
  • 1
    Comments related to another question belong in that question, not this one. – Remy Lebeau Jul 09 '14 at 02:16
2

Your hook functions do not match the proper signature of CreateProcess(). Try this instead:

library DLL;

uses
  Windows, DDetours;

{$R *.res}

var
  CreateProcessHook: function(lpApplicationName: PChar;
            lpCommandLine: PChar;
            lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
            bInheritHandles: BOOL;
            dwCreationFlags: DWORD;
            lpEnvironment: Pointer;
            lpCurrentDirectory: PChar;
            const lpStartupInfo: STARTUPINFO;
            var lpProcessInformation: PROCESS_INFORMATION): BOOL; stdcall = nil;

function InterceptCreateProcess(lpApplicationName: PChar;
            lpCommandLine: PChar;
            lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
            bInheritHandles: BOOL;
            dwCreationFlags: DWORD;
            lpEnvironment: Pointer;
            lpCurrentDirectory: PChar;
            const lpStartupInfo: STARTUPINFO;
            var lpProcessInformation: PROCESS_INFORMATION): BOOL; stdcall;
begin
  Result := CreateProcessHook(lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation);    
  MessageBox(0, 'CreateProcess', 'Hooked', 0);
end;

procedure DLLMain(dwReason: DWORD);
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
    begin
      @CreateProcessHook := InterceptCreate(@CreateProcess, @InterceptCreateProcess);
      MessageBox(0, 'Injected', 'Injected', MB_OK);
    end;
    DLL_PROCESS_DETACH:
    begin
      InterceptRemove(@CreateProcessHook);
    end;
  end;
end;

begin
 DLLProc := @DLLMain;
 DLLMain(DLL_PROCESS_ATTACH);
end.
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Yes, that worked. Strange thing is that when I tried to use the exactly same signature from msdn (as I put in the main question), still crashing. – user3810691 Jul 09 '14 at 01:55
  • 1
    You weren't using the same signature as in msdn – David Heffernan Jul 09 '14 at 01:56
  • Right now I put the `Result := CreateProcessHook(lpApplicationName...` trying to open the process previously requested by me, but I got a Windows Error, saying something like: The system cannot find the file specified... with the correct path for the file I openned. Any idea on how to open the file? – user3810691 Jul 09 '14 at 03:10
  • Did you verify the path being received by your detour (not the path you pass to the intercepted `CreateProcess()`) is correct before passing it to the trampoline? – Remy Lebeau Jul 09 '14 at 05:43
  • Yes, because the path appear on the error box. And it's correctly. Maybe is something about Unicode and Ansi... But I tried to change for something like: `Result := CreateProcessHook(PAnsiChar(lpApplicationName)` but doesn't worked. – user3810691 Jul 09 '14 at 12:48
  • Still not working. Did few tests with MessageBox(lpApplicationName) and MessageBox(lpCommandLine), to see what parameters are being passed, everything is correct. Can't understand why I get this error. Is something like: The Windows could not find the file C:\windows\system32\notepad.exe ..... (when openning notepad). – user3810691 Jul 09 '14 at 14:13
  • To avoid any possible Ansi/Unicode issues, you should consider hooking `CreateProcessA()` and `CreateProcessW()` separately. But I don't think this is going to be an Ansi/Unicode issue. Are you SURE everything is compiled for 64bit only? The `system32` folder is subject to UAC/WOW64 redirection. – Remy Lebeau Jul 09 '14 at 16:54
  • @Remy turns out that in a now deleted question asker was still using the wrong signatures for CreateProcess. – David Heffernan Jul 10 '14 at 06:20