CreateWindowExW & Crashes

Jan 11, 2009 at 3:25 PM
At first I'd like to thank you for a great library!

I've injected my dll into my target process and have a successfull connect (IPC) to the host process, I've successfully hooked the "user32.dll" method "CreateWindowExW", however the target process (application) more or less crashes when this or "DestroyWindow" are hooked.

This is some of the code that is being executed.

run method;
----------------
                CreateWindowHook = LocalHook.Create(LocalHook.GetProcAddress("user32.dll", "CreateWindowExW"), new DCreateWindowEx(CreateWindowEx_Hooked), this);
                CreateWindowHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

            Interface.IsInstalled(RemoteHooking.GetCurrentProcessId());

                while (true)
                {
                    Thread.Sleep(500);

                    if (CreatedWindows.Count > 0)
                    {
                        string[] Package = null;

                        lock (CreatedWindows)
                        {
                            Package = CreatedWindows.ToArray();
                            CreatedWindows.Clear();
                        }

                        Interface.OnCreateWindow(RemoteHooking.GetCurrentProcessId(), Package);
                    }
                    else
                        Interface.Ping(RemoteHooking.GetCurrentProcessId());
                }


intercepting method
-------------------
        static IntPtr CreateWindowEx_Hooked(
           uint dwExStyle,
           string lpClassName,
           string lpWindowName,
           uint dwStyle,
           int x,
           int y,
           int nWidth,
           int nHeight,
           IntPtr hWndParent,
           IntPtr hMenu,
           IntPtr hInstance,
           IntPtr lpParam)
        {
                try
                {
                    Main This = (Main)HookRuntimeInfo.Callback;

                    lock (This.CreatedWindows)
                    {
                        This.CreatedWindows.Push(lpWindowName);
                    }
                }
                catch
                {
                }

            // call original API...
            return CreateWindowEx(
                dwExStyle,
                lpClassName,
                lpWindowName,
                dwStyle,
                x,
                y,
                nWidth,
                nHeight,
                hWndParent,
                hMenu,
                hInstance,
                lpParam);
        }

Does anyone have any ideas why the application might crash when this hook is created?
Coordinator
Jan 11, 2009 at 4:49 PM
sounds like wrong call signature... google for well tested PInvokes of the desired methods...
Jan 11, 2009 at 6:33 PM
yeah that was my first thought to, but i got the PInvoke from here;
http://www.pinvoke.net/default.aspx/user32/CreateWindowEx.html

My host application reports a few successfull create events before the application crashes and the target process writes an exception into the event log.
".NET Runtime version 2.0.50727.1433 - Fatal Execution Engine Error (79FFEE24) (80131506)"

doesn't say much :/
Jan 12, 2009 at 5:25 PM
Been googling, trying for endless of hours now, any other ideas why this might happend? any help would be greatly appriciated!

regards,
Richard


Beställ bläck före 19 för leverans nästa vardag inkClub
Coordinator
Jan 12, 2009 at 6:39 PM
There is not much you can do...

Put host and target in same process (by creating a desktop app) and hook your own process by using local hooks before any managed window is created.

If this works you can also debug two processes simulteneously. One is the host process, the other is the target process. Put a breakpoint in the managed injection loader, all of your remote interface methods (Run, Initialize and the hook) and see what happens...
Coordinator
Jan 12, 2009 at 6:41 PM
Of course the host and target process should be debugged by the multiprocess debugging feature of visual studio and you should also have the source code of both. Just create a dummy target with WinForms...
Jan 12, 2009 at 8:59 PM
I've made a dummy (dektop app) and injected the dll into it, it hooks all CreateWindowEx without any problems. very strange! i don't have the source code for the target process (only source for the dll to inject) , so i guess i can not take advantage of the multiprocess debugging feature.

Does this mean I've hit some kind of dead-end?
Jan 14, 2009 at 9:57 PM
Hi Christoph!

I started debugging the dll (attaching the debugger to the host dll - very nice feature btw!), steped through every line until it hung, catched the lpClassName and wrote an if statement and woila! the app didn't crash any more, i'll try to figure out what of the values are causing the crash and modify it later!

Thanks for your time and effort!


Cheers!
Jun 27, 2009 at 12:31 AM

Anyone able to share the solution to this?  I am having the same exact problem...

Jul 10, 2009 at 8:00 PM
Edited Jul 10, 2009 at 8:06 PM

edit: sorry for making the post wider :)

I'm having a similar problem - any program where I hook CreateWindowExA/W (calc.exe, notepad.exe, textpad.exe, and own test exe tested) crashes the host application.  notepad.exe never calls the hooked method (breakpoint is not hit) and crashes; calc.exe calls the hooked method, but crashes after returning the original api call; my test application (simple win32 app creating a window - code from http://www.functionx.com/win32/Lesson01c.htm) calls the hooked method but hangs after returning the original api call - control is not returned to the test application.

I've been working on this all day - I'm thinking this is a function signature issue, but I can't seem to find a working example anywhere.

Any help is appreciated.  Code below.  Note DestroyWindow, MessageBoxA, and MessgaeBoxW are working and just there for comparison.  Taking out the file system IO did not change anything.

Thanks!

-Andrew


Launcher.exe

using System;
using System.Collections.Generic;
using System.Text;

using EasyHook;
using System.Diagnostics;

namespace Launcher {
    class Launcher {

        private const string LOGFILENAME = @"C:\Launcher.log";

        static void Main(string[] args) {
            LogNew();
            LogInfo("Start");

            //string EXEPath = @"C:\Program Files (x86)\TextPad 5\TextPad.exe";
            //string EXEPath = @"C:\Windows\notepad.exe";
            //string EXEPath = @"C:\Windows\System32\calc.exe";
            string EXEPath = @"C:\TestUnmanagedWindow.exe";

            // Register Hook in GAC
            Config.Register("Hook Description", "Hook.dll");
           
            // Launch Hooked EXE
            int pid;
            RemoteHooking.CreateAndInject(EXEPath, "", 0, "Hook.dll", "Hook.dll", out pid, "Test2");

            // Complete
            LogInfo("End");

            // Debug
            while (Console.KeyAvailable) Console.ReadKey(true);
            LogDebug("Press any key to exit");
            Console.ReadKey(true);
        }

        #region " Logging Methods "
        private static void LogNew() {
            System.IO.File.Delete(LOGFILENAME);
        }
        private static void LogInfo(String line) {
            Log("INFO - " + line);
        }
        private static void LogDebug(String line) {
            Log("DEBUG - " + line);
        }
        private static void Log(String line) {
            Console.WriteLine(DateTime.Now.ToString() + " - Launcher - " + line);
            using (System.IO.StreamWriter sw = new System.IO.StreamWriter(LOGFILENAME, true)) {
                sw.WriteLine(DateTime.Now.ToString() + " - Launcher - " + line);
            }
        }
        #endregion
    }
}


Hook.dll

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using EasyHook;
using System.Runtime.InteropServices;

namespace Hook {
    public class Hook : IEntryPoint {

        private const string LOGFILENAME = @"C:\Hook.log";

        LocalHook CreateWindowExAHook;
        LocalHook CreateWindowExWHook;
        LocalHook DestroyWindowHook;
        LocalHook MessageBoxAHook;
        LocalHook MessageBoxWHook;

        #region " IEntryPoint Members "

        public Hook(RemoteHooking.IContext context, string args) {
            LogNew();
            LogInfo("ctor");
        }

        public void Run(RemoteHooking.IContext context, string args) {
            System.Windows.Forms.MessageBox.Show("attach debugger if wanted");
            LogInfo("Run");

            // Hook methods
            try {
                // DestroyWindow
                DestroyWindowHook = LocalHook.Create(
                    LocalHook.GetProcAddress("user32.dll", "DestroyWindow"),
                    new DDestroyWindow(DestroyWindow_Hooked), this);
                DestroyWindowHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

                // CreateWindowExA
                CreateWindowExAHook = LocalHook.Create(
                    LocalHook.GetProcAddress("user32.dll", "CreateWindowExA"),
                    new DCreateWindowExA(CreateWindowExA_Hooked),
                    this);
                CreateWindowExAHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

                // CreateWindowExW
                CreateWindowExWHook = LocalHook.Create(
                    LocalHook.GetProcAddress("user32.dll", "CreateWindowExW"),
                    new DCreateWindowExW(CreateWindowExW_Hooked),
                    this);
                CreateWindowExWHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

                // MessageBoxA
                MessageBoxAHook = LocalHook.Create(
                    LocalHook.GetProcAddress("user32.dll", "MessageBoxA"),
                    new DMessageBoxA(MessageBoxA_Hooked), this);
                MessageBoxAHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });

                // MessageBoxW
                MessageBoxWHook = LocalHook.Create(
                    LocalHook.GetProcAddress("user32.dll", "MessageBoxW"),
                    new DMessageBoxW(MessageBoxW_Hooked), this);
                MessageBoxWHook.ThreadACL.SetExclusiveACL(new Int32[] { 0 });


            } catch (Exception ExtInfo) {
                LogError(ExtInfo.ToString());
                return;
            }

            // Resume loading
            RemoteHooking.WakeUpProcess();
            
            while (true) {
                System.Threading.Thread.Sleep(1000);
                LogInfo("... Running...");
            }
        }

        #endregion

        #region " Hooks "

        // DestroyWindow
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        delegate bool DDestroyWindow(IntPtr hWnd);
        [DllImport("user32.dll")]
        static extern bool DestroyWindow(IntPtr hWnd);
        static bool DestroyWindow_Hooked(IntPtr hWnd) {
            LogInfo("DestroyWindow");
            return DestroyWindow(hWnd);
        }

        
        // CreateWindowExA
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)]
        delegate IntPtr DCreateWindowExA(uint dwExStyle, string lpClassName, string lpWindowName,
            uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
            IntPtr hInstance, IntPtr lParam);
        [DllImport("user32.dll", CharSet = CharSet.Ansi, SetLastError = true,
            CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr CreateWindowExA(uint dwExStyle, string lpClassName, string lpWindowName,
            uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
            IntPtr hInstance, IntPtr lParam);
        static IntPtr CreateWindowExA_Hooked(uint dwExStyle, string lpClassName, string lpWindowName,
            uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
            IntPtr hInstance, IntPtr lParam) {

            // Hooked Code Here
            LogInfo("CreateWindowExA");

            // Call original
            return CreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight,
                hWndParent, hMenu, hInstance, lParam);
        }

        // CreateWindowExW
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
        delegate IntPtr DCreateWindowExW(uint dwExStyle, string lpClassName, string lpWindowName,
            uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
            IntPtr hInstance, IntPtr lParam);
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true,
                CallingConvention = CallingConvention.StdCall)]
        static extern IntPtr CreateWindowExW(uint dwExStyle, string lpClassName, string lpWindowName,
            uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
            IntPtr hInstance, IntPtr lParam);
        static IntPtr CreateWindowExW_Hooked(uint dwExStyle, string lpClassName, string lpWindowName,
            uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
            IntPtr hInstance, IntPtr lParam) {

            // Hooked Code Here
            LogInfo("CreateWindowExW");

            // Call original
            IntPtr ret = CreateWindowExW(dwExStyle, lpClassName, lpWindowName, dwStyle, x, y, nWidth, nHeight,
                hWndParent, hMenu, hInstance, lParam);
            return ret;
        }
        // MessageBoxA
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)]
        delegate int DMessageBoxA(IntPtr hWnd, String text, String caption, uint options);
        [DllImport("user32.dll", CharSet = CharSet.Ansi)]
        static extern int MessageBoxA(IntPtr hWnd, String text, String caption, uint options);
        static int MessageBoxA_Hooked(IntPtr hWnd, String text, String caption, uint options) {
            LogInfo("MessageBoxA");
            return MessageBoxA(hWnd, text, caption, options);
        }

        // MessageBoxW
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = true)]
        delegate int DMessageBoxW(IntPtr hWnd, String text, String caption, uint options);
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        static extern int MessageBoxW(IntPtr hWnd, String text, String caption, uint options);
        static int MessageBoxW_Hooked(IntPtr hWnd, String text, String caption, uint options) {
            LogInfo("MessageBoxW");
            return MessageBoxW(hWnd, text, caption, options);
        }
Jul 16, 2009 at 11:12 AM

I don't know if you have even read this post, I've posted the solution or atleast how i solved the problem,

"I started debugging the dll (attaching the debugger to the host executable where the dll was injected - very nice feature btw!), steped through every line until it hung, wrote an if statement that altered "lpClassName"'s value, this was the parameter that hung my return and woila!


Good Luck

Jul 16, 2009 at 3:03 PM
Edited Jul 16, 2009 at 3:04 PM

Of course I've read the post :) - your solution just did not work for me (yet).  I am stepping through the hooked method in the dll and the lpClassName and lpWindowName look fine (I have seen a problem in the past with unmanaged hooks with invalid class/window names, but that is not the case here).  I do not want to modify them as that would not create the correct window.

So one problem I was having was using 64-bit processes like notepad and calc.  Fixed now that testing is only using 32-bit apps.

The 2 test apps I'm using are textpad.exe (32 bit) and the above-linked simple CreateWindow example (using CreateWindowExA and CreateWindowExW).

With Textpad, CreateWindowExA works fine all the way through but CreateWindowExW does not.  The CreateWindowExW hooked method is never called (breakpoint is not hit), and the application is hung.

With TestUnmanagedWindow.exe (linked example using CreateWindowExA OR W and all the related calls/structures matching A/W), the hook gets called and returns without error, the window is created but the app hangs.  Stepping through WndProcedure looking at the Msg's I see it hangs on the DefWindowProcA call when sending a WM_ACTIVATE message.  I don't know how to debug this further.

It would be most helpful to see a working example using CreateWindowExW (and even A too).

Thanks for reading.

-Andrew

Jul 17, 2009 at 2:53 PM

OK, found the problem and fixed it.  It was what Corename was describing but here's some more detail on why it happens.

According to MSDN (http://msdn.microsoft.com/en-us/library/ms632680(VS.85).aspx), CreateWindowEx's lpClassName variable can be either a pointer to a string or an ATOM.  As long as it's a string the .net definition of

IntPtr DCreateWindowExW(uint dwExStyle, string lpClassName, string lpWindowName,
    uint dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu,
    IntPtr hInstance, IntPtr lParam);

works fine.  However if in a particular call lpClassName is an ATOM, .net Interop will apparently freak out (technical terms here, feel free to explain actually why) and not even call the hooked method.

Changing lpClassName's type to IntPtr (need to test more on 64-bit) worked fine for 32-bit apps.  You can test if lpClassName is an ATOM by looking at the HIWORD and checking if it equals 0, if it does, you've got yourself an ATOM.  It's been a while since I've looked into ATOM's but I think you can do a lookup on this value to get more info (again, fill in more info if you know how to do this).

So, thank you for the help, pointing me in the right direction, even if it took me a while to get there.

:) -Andrew

Jul 19, 2009 at 7:46 PM

Glad you found a solution at last and shared some information about the underlying problem, thanks! :)

Jul 27, 2010 at 2:15 AM
Edited Jul 27, 2010 at 4:53 AM

I run a 32bit application injecting code into a 32bit application under 64bit OS, failing to have the remoting hold up when I get an lpClassName that is an ATOM.

Did you guys get it to work handling both atom and string requests with the same hook?
If so:

1: What signature did you use for the configured Hook/Delegate of CreateWindowExW?
When hooked up and getting a lpClassName that is a 
2: ATOM or
3: string,
what DllImport'ed CreateWindowExW signature did you use to redirect the call?

When I use a IntPtr to be able to get my hooked method to run on the ATOM call, .NET remoting throws exception after calling the original CreateWindowExW function in my Hook function.