Questions about DLL Injection

c++ / delphi package - dll injection and api hooking
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

Where do you call MenuConstructor()?

OpenProcess() returns a handle to the process, not a window. You need to get the hwnd somehow else. FindWindow() perhaps?

-- David
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

Code: Select all

Procedure MenuConstructor(); stdcall
   var h: hWnd;
   mnu, nmnu: HMENU;
   begin
      h := FindWindow('uniquecls', nil);
      mnu := GetMenu(h);
      nmnu := CreatePopupMenu();
      AppendMenu(mnu, MF_POPUP, nmnu, '&Extra Menu');
      AppendMenu(nmnu, MF_STRING, $1000, '&Item #1');
      AppendMenu(nmnu, MF_STRING, $1001, 'I&tem #2');
      DrawMenubar(h);
      SetWindowLong(h, GWL_WNDPROC, LongInt(@WndProc));
      DrawMenuBar(h);
      end;
Youre right about the process handle returning but oddly enough it worked in one of my tests with a small modification. I was using FindWindow to get a hwnd return but that just seemed odd because I'm in the already inside the target process, nonetheless I will use FindWindow() as you suggested.
Where do you call MenuConstructor()?
I'm not. Should I add the procedure to the entrypoint and set the dwReason to 1? Maybe then do something like if dwReason = (1) then MenuConstructor(); Or is there an easier way to execute the procedure when the process attaches? It isnt an export procedure.
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

I have the menus created now via the dll injection. I called MenuConstructor() in entrypoint under process_attach and
it froze at first so I called this SetWindowLong(GetMenu(h).., ...); since the menu had been updated, maybe thats why it freeze? The only thing left is to get the callback to work, wndproc is not showing me any messageboxes when I click my menus. Maybe I should also supress unfiltered messages with wm_null or simply revert to the original window procedure for the unhandled messages?
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

Dracula wrote:I have the menus created now via the dll injection. I called MenuConstructor() in entrypoint under process_attach and
it froze at first so I called this SetWindowLong(GetMenu(h).., ...); since the menu had been updated, maybe thats why it freeze? The only thing left is to get the callback to work, wndproc is not showing me any messageboxes when I click my menus. Maybe I should also supress unfiltered messages with wm_null or simply revert to the original window procedure for the unhandled messages?
Yes, definitely call the original wndproc (use CallWindowProc() to do so), otherwise your window will not paint or anything else!

Call OutputDebugString() at the start of your wndproc and use sysinternals.com DbgView to see if the string appears indicating your wndproc is indeed being called.

I don't think it is. Again, make sure you're passing the right types to these API's. SetWindowLong(hwnd, ...) does not take a HMENU! :wink:

Cheers,
David
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

thanks david, I'll give it a go here in a few hrs. I appreciate all the help you've given me =) I definitely know it's a callback function (Window Procedure) callback issue as it's not reacting to menu item click events. I'll keep you informed.
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

Everything appears to be stable but I'm still not getting the wm_command notifications to launch the messageboxes. I've looked at other examples and I'm pretty sure I'm doing things right with this dll injection.

DLL

Code: Select all

library injct;

uses
  messages, windows;

var
PrevWndProc: Longint;
m_hWnd: hWnd;

Function NewWindowProc(handle: hWNd; msg: UINT; wp: Wparam; lp: Lparam): LRESULT; stdcall
begin
     case msg of
   WM_COMMAND:
    begin
        if (wP = $1001) then MessageBoxA(0, 'My appended Item Clicked', 'Extra', MB_OK);
        if (wP = $1002) then MessageBoxA(0, 'My appended Item #2 Clicked', 'Extra', MB_OK);
         end
  else
    result := CallWindowProc(@PrevWndProc, handle, Msg, wP, lP);
   end;
    end;

Procedure HookWndProc;
begin
  PrevWndProc := SetWindowLong(m_hWnd, GWL_WNDPROC, LongInt(@NewWindowProc));
end;

Procedure UnHookWndProc;
var tmp: Longint;
begin
  tmp := SetWindowLong(m_hWnd, GWL_WNDPROC, PrevWndProc)
end;

  Procedure MakeMenu;
  var
   mnu: HMENU;
   newmenu: HMENU;
   hnd: hWnd;
   begin
   hnd := FindWindow('notepad', nil);
   if hnd <> 0 then mnu := GetMenu(hnd);
    NewMenu := CreatePopupMenu();
    AppendMenu(mnu, MF_POPUP, NewMenu, '&Extra Menu');
    AppendMenu(NewMenu, MF_STRING, $1001, '&Item #1');
    AppendMenu(NewMenu, MF_STRING, $1002, 'I&tem #2');
    DrawMenubar(hnd);
    HookWndProc();
    end;

    Procedure DllEntry(dwReason: DWORD);
     begin
      Case dwReason of
        DLL_PROCESS_ATTACH:
      begin
        MakeMenu();
      end;
       DLL_PROCESS_DETACH:
       begin

       end;
     end;
   end;

begin
DllProc := @DLLEntry;
DllEntry(DLL_PROCESS_ATTACH);
end.

Loader

Code: Select all

uses MadCodeHook;
......
var h, pid: cardinal;
begin
pid := GetPid('notepad');
h := Openprocess(PROCESS_ALL_ACCESS, FALSE, PID);
if h <> NULL then InjectLibrary(h, 'injct.dll');
end;
....
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Looks pretty good

Post by dcsoft »

Looks good. The only thing I can see is m_hWnd doesn't get set anywhere, yet that is the window you're subclassing? Is your NewWindowProc() is called at all? Put the message box at the very start of the function to see.

You should CallWindowProc() any WM_COMMAND parameters you don't process yourself, or else Notepad's File:Save command, for example, will do nothing.

Also, you need to call UnHookWndProc() in the DLL_DETATCH case.

Cheers,
David
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

ty david you're the man. I have it all working now :)
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

one last ? for you,
You should CallWindowProc() any WM_COMMAND parameters you don't process yourself, or else Notepad's File:Save command, for example, will do nothing.
How should I do this?
Dracula
Posts: 27
Joined: Thu May 12, 2005 5:30 pm

Post by Dracula »

Ignore my last comment/question please. I created a RemoveMenu function on the process detachment and on the loader when i call UnInjectLibrary on form close and destroy. Works good. I changed the code handle the a few WM_ commands and then always make the result CallWindowProc() after Ive handled the messages i'm interested in. Speaking of that lets say there's a control and I click it or whatever and it redraws window killing my menu, should I handle more than just wm_command? Maybe wm_showwindow, wm_activate or whatever else is important.
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

Dracula wrote:Ignore my last comment/question please. I created a RemoveMenu function on the process detachment and on the loader when i call UnInjectLibrary on form close and destroy. Works good. I changed the code handle the a few WM_ commands and then always make the result CallWindowProc() after Ive handled the messages i'm interested in. Speaking of that lets say there's a control and I click it or whatever and it redraws window killing my menu, should I handle more than just wm_command? Maybe wm_showwindow, wm_activate or whatever else is important.
Glad it's working! :-)

Your menu shouldn't be killed by any of Notepad's functions. You shouldn't need to handle any more messages. Unless you want what the menu item does (display a message box, in your posted code) to also be done at other times beside when the user selects the menu item.

Take care,
David
Post Reply