Jump to content
  • Advertisement
Sign in to follow this  
HyperHacker

Adding menus to another program's window

This topic is 4606 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I want to add a menu item to the menu of another program's window, with my own program being notified when that item and those of its submenus are selected. I can add the menu, but it's proving to be quite a problem being notified when the options are selected. My first thought was to hijack the window procedure using SetWindowLong, but for some reason I can't imagine, you can't do this in WinNT/2K/XP if the window is created by another process. Same goes for the class window procedure. I tried registering the window's class before the other program does, thinking it should use the pre-registered class with my own handler, but it doesn't! O_o So now I'm working on trying to actually copy a function into the program's memory and spawn a thread to run it (since you can't spawn a thread in a remote process and have it run code in yours). I've successfully managed to copy the code into memory and spawn a thread in it, but there's still a problem: function pointers don't match, and for that matter, seem to be relative. That is, I copied my code in at 0x4F0000, but when this code calls printf() or MessageBox(), it jumps to somewhere around 0x4F01xx and causes an access violation. There must be some better way to do this than having to try to stick my own code in another program's memory? It's quite a hack and proving to be difficult.

Share this post


Link to post
Share on other sites
Advertisement
Sorry, I posted and then deleted my post because I didn't think it was helpful enough.
I had heard that using Hooks could do a lot of things, but I have never used them and could not provide code for it relating to menus. Thus, I deleted my post. Sorry.

Share this post


Link to post
Share on other sites
Ah, I thought that might have been it.

Actually, it looks like that might be useful. There are hooks that can view messages being sent to windows. :)

Share this post


Link to post
Share on other sites
Alright, once again I've been plunged into the abysmal hell that is typecasting in C++. Because of memory sharing issues, hooks for another process have to be handled by a DLL. Apparently, using a DLL in C++ is impossible for one simple reason: GetProcAddress() returns FARPROC. If I define the function pointers as FARPROC Something and then try to call them, it complains that I've given too many arguments (unless I use none, but that's not very useful). To prevent this I have to specify the actual number and type of arguments each function takes, which means declaring them like HHOOK (*DLLAddHook)(int) = NULL;. And therein lies the problem - there doesn't seem to be any way at all to cast the FARPROC returned by GetProcAddress() to this obscure type. (For that matter, it's not even a FARPROC anymore.) I've actually managed such errors as "invalid conversion from HHOOK (*)(int) to HHOOK (*)(int)". The only solution I've yet to find is to cast both to void* and use memcpy() for the assignment, and as you might imagine, that doesn't work so well.

The biggest problem seems to be that the hook procedure is executed in the context of the process that's hooked (if it crashes, it takes out that program instead of mine). From there if I want to call a function within the EXE that loads this DLL, something I can usually do, it fails (and crashes) because the memory that was occupied by my program is now instead that of the one being hooked. Is this possible at all? The only methods I can think of are to put all of these functions in the DLL and have the EXE call them, or use some sort of FIFO stack that the EXE processes every so often, but neither of these are really viable options right now. Moving everything to the DLL means having to work out that type casting problem (or do more hackish memcpy() stuff), and also, I desparately need debug output (to the console) from within the hook procedure, and this doesn't seem to be possible. (printf() just doesn't do anything, probably since the hooked app has no console.) As for a FIFO stack, it's just not something I want to try right now. Maybe tomorrow.

Share this post


Link to post
Share on other sites
Quote:
Original post by HyperHacker
Alright, once again I've been plunged into the abysmal hell that is typecasting in C++. Because of memory sharing issues, hooks for another process have to be handled by a DLL. Apparently, using a DLL in C++ is impossible for one simple reason: GetProcAddress() returns FARPROC. If I define the function pointers as FARPROC Something and then try to call them, it complains that I've given too many arguments (unless I use none, but that's not very useful). To prevent this I have to specify the actual number and type of arguments each function takes, which means declaring them like HHOOK (*DLLAddHook)(int) = NULL;. And therein lies the problem - there doesn't seem to be any way at all to cast the FARPROC returned by GetProcAddress() to this obscure type. (For that matter, it's not even a FARPROC anymore.) I've actually managed such errors as "invalid conversion from HHOOK (*)(int) to HHOOK (*)(int)". The only solution I've yet to find is to cast both to void* and use memcpy() for the assignment, and as you might imagine, that doesn't work so well.


HHOOK (*DLLAddHook)(int) = NULL;.

This is a function pointer variable declaration not a typedef, so you can't cast with it. It's like trying the following

int x = 0;
int y = (x)SomeFunk(args);

Just use (void*) and be done with it. eg.

DLLAddHook = (void*)GetProcAddress(module, "funk");

The alternative is to declare the function pointer as a type.

typedef HHOOK (*DLLAddHookT)(int);

then declare a pointer instance

DLLAddHookT DLLAddHook = NULL;

then use that type to cast

DLLAddHook = (DLLAddHookT)GetProcAddress(mod, "funk");

you might have difficulties with the typedef if the calling convention is omitted - as in the above. When omitted the default is cdecl - at least it is in C, probably so in C++.

Here are two versions of the typedef with the calling convention included.

typedef HHOOK (_stdcall *DLLAddHookT)(int);

typedef HHOOK (WINAPI *DLLAddHookT)(int);

check your compiler docs for calling convention particulars, some compilers might use two preceeding underscores for stdcall. Most Win32 API functions are stdcall. Exceptions to that are variable argument functions like sprintf.

I don't know how you'd use memcpy to do this. GetProcAddress really only returns a 32 bit value - an address in the address space of the process just like any other. You could save this address as a DWORD if you wanted. It's the compiler that wants to treat that value as a FARPROC, not the CPU.

Quote:
Original post by HyperHacker
The biggest problem seems to be that the hook procedure is executed in the context of the process that's hooked (if it crashes, it takes out that program instead of mine). From there if I want to call a function within the EXE that loads this DLL, something I can usually do, it fails (and crashes) because the memory that was occupied by my program is now instead that of the one being hooked. Is this possible at all? The only methods I can think of are to put all of these functions in the DLL and have the EXE call them, or use some sort of FIFO stack that the EXE processes every so often, but neither of these are really viable options right now. Moving everything to the DLL means having to work out that type casting problem (or do more hackish memcpy() stuff), and also, I desparately need debug output (to the console) from within the hook procedure, and this doesn't seem to be possible. (printf() just doesn't do anything, probably since the hooked app has no console.) As for a FIFO stack, it's just not something I want to try right now. Maybe tomorrow.


You can use file mapping to create shared memory. See Creating Named Shared Memory. This should resolve your problem (the memory that was occupied by my program is now instead that of the one being hooked)

It seems to me that the menu resource - you are still trying to pop a menu in a target process yes? - would have to be stored in the dll - and for that matter any other resources used by routines slated to execute in the target process.

Console output? Which process would the console belong to? I suppose you could call AllocConsole in the target process. Try it and see what happens. You can use "freopen" to redirect windows console handles to stdio. See Creating a debug console.

If you haven't done much window hooking before, it's probably better to start with a target program of your own rather than trying to hijack some third party app right out of the gate. Interprocess communication takes a bit of getting used to. Here's some code I crafted a while back to demonstrate a global message hook: GlobalMessageHook. This captures WM_PAINT messages throughout the system. YMMV.

Share this post


Link to post
Share on other sites
Just a little bit of technical trivia: the reason you can't do this under NT-based versions of Windows is process sandboxing. Under Windows 95, 98, ME, and even 3.x/older, every process on the system was running in the same virtual memory space. This made it possible for every process on the system to use the same memory addresses, Windows handles and identifiers, and so on. So if a window had a handle of 0x85f0 in one process, it had the same handle in any other process. It was easy to go off and muck around with stuff in another process, because it was, under the surface, basically one giant program running in a single memory space. (This is a vast oversimplification. The 386Enhanced mode of Windows 3.x, which carried forward into 9x/ME, did do some pretty sophisticated virtual memory management. It just didn't do it in a way that kept programs separated from each other.)

This is clearly a security problem; I remember doing stuff like writing little viruses that would randomly "steal" controls from one window and place them on another. The bizarre thing was, they would often still work! Subclassing controls from another process was also a lot of fun, and gave rise to a lot of keyloggers, password sniffers, and other nastiness. In any case, though, there were more devious implications of this: any one program was free to go pick around in the memory of another, meaning that there was basically no data security whatsoever.

The NT kernel set out to fix this by doing proper process sandboxing. In this model, every process gets a virtual memory address space. This space is more or less the same for every program, based on a few things like the program's code size and requested stack size. Additionally, Windows keeps track of its handles and IDs on a per-process basis (for the most part). This means that, while HWND 0x85f0 may very well exist in process A, it doesn't exist in B. Processes are separated from each other, and have no way to directly communicate by direct memory access or Windows handle sorcery. There are a lot of very powerful inter-process communication technologies available, but they all require deliberate effort; there isn't a simple way to just take over another process's stuff anymore.


Now, the reason a DLL can do this is because each DLL a process loads is loaded into the process's virtual memory space. However, DLLs have different address constraints than the EXE they are loaded by, and there are other subtle changes, as you found out. These problems can be gotten around, though; if you're interested in more on how all of that works, and how to use DLL injection to do some really fun stuff, check out the book Reversing.

Share this post


Link to post
Share on other sites
Alright, I'll try the typedef thing. Hope it works. :) For memcpy, I just put the return value from GetProcAddress() into a long, and passed it as the source and the function pointer I wanted to assign it to as the destination to memcpy() (both casted to void*) with the size being the size of the pointer. It worked, but of course it's pretty system-dependant.

I am still trying to add a menu, though I'm actually making it at runtime because I can't find any good resource editors I can make one with. :(

For console output, the console belongs to my own process. The other doesn't have one, and even if I launch it from one, it just goes back to a command prompt after opening it, so there's no way the program would be able to print to it. I guess I'll have to create a new one.

ApochPiQ: I have actually successfully 'stolen' a control from another window in XP. It's surprisingly simple - find its handle, use SetParent to add it to my own window, and pass on any messages for it to the original window. I never got around to trying to put it back in place (the button was actually in my window instead of the old one) but I imagine making the original window my window's parent (with the stolen button its child) would work.

Share this post


Link to post
Share on other sites
Interesting... you're right, it does work, just as easily as Ye Olden Days. For some reason I'd developed the impression that this was not as trivial as it used to be.

In any case, the cross-process security is definitely better under NT, but obviously still not perfect [grin]

Share this post


Link to post
Share on other sites
Quote:
Original post by HyperHacker
Alright, I'll try the typedef thing. Hope it works. :) For memcpy, I just put the return value from GetProcAddress() into a long, and passed it as the source and the function pointer I wanted to assign it to as the destination to memcpy() (both casted to void*) with the size being the size of the pointer. It worked, but of course it's pretty system-dependant.


Sounds like overkill to me. If the typedef thing doesn't work, then you're doing something wrong. You can always typecast the return from GetProcAddress as (void*).

Quote:
Original post by HyperHacker
I am still trying to add a menu, though I'm actually making it at runtime because I can't find any good resource editors I can make one with. :(


Hand crafting menu resources is easy. Building them at runtime isn't too difficult either. I suppose that a runtime build also allows for not overwritting the menu codes already being used by the target process and it's WM_COMMAND handler.

Quote:
Original post by HyperHacker
For console output, the console belongs to my own process. The other doesn't have one, and even if I launch it from one, it just goes back to a command prompt after opening it, so there's no way the program would be able to print to it. I guess I'll have to create a new one.


I see. Well, it seems to me WM_COPYDATA works well enough to pass data back to the targetting process. You might also consider using redirected named pipes: Creating a Child Process with Redirected Input and Output.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!