Passing Parameters

c++ / delphi package - dll injection and api hooking
choochy2003
Posts: 88
Joined: Fri Mar 21, 2008 4:52 am
Location: Adelaide, South Australia
Contact:

Passing Parameters

Post by choochy2003 »

Is there a way to pass parameters to the Hook DLL without using the IPC? In my case I want to just pass some parameters that adjust the DLL's starting conditions.
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Passing Parameters

Post by madshi »

Sure, you can use CreateGlobalFileMapping() in your EXE before you start the injection, and then OpenGlobalFileMapping() in the initialization of your hook dll. Be careful, though: A malware might try to fool you by opening a file mapping with the same name before you do. So you should do some sanity checks. E.g. if the file map already exists when it shouldn't, there might be something wrong (or maybe a 2nd instance of your EXE is running).

Well, for "normal" applications security concerns like this are not an issue. But if you're writing a security sort of application (e.g. anti-virus or similar), it's good to be aware of such potential problems.
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Re: Passing Parameters

Post by dcsoft »

Besides the global file mapping, another method is to have a shared data section in the DLL. Your initial EXE would LoadLibrary() the DLL and call one of its exported functions which sets the data in some global variable stored in the shared data section. Then each instance of the DLL can read this global variable when it is injected into each other process.

This technique is described for Visual C++ here: https://msdn.microsoft.com/en-us/librar ... s.90).aspx
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Passing Parameters

Post by iconic »

Shared DLL sections have apparent issues, snippet below as an excerpt [citing http://bobmoore.mvps.org/Win32/W32Tip9.htm]
DLL Shared Sections

These require you to write a DLL of course, which seems like overkill just to get two processes talking. There is also a technical problem which can arise because Windows recognises DLLs by their path, not their name. So two copies of the same DLL from different paths can get loaded, and the loading processes won't see the same section. Bummer.

Another more serious problem arises because of changes to Windows made around the time of Windows 2000. Because of the rise in importance of virtualisation in general and terminal server in particular, sharing data across session boundaries was thought to be a security risk. Hence MS deliberately broke the operation of shared sections across sessions. Each session gets its own copy of the data, shared only within that session. This means that on Vista and Windows 7, with their service hardening feature that puts the services into their own session and the console in a different one, you can't share data between apps and services using a shared section. Fortunately Memory Mapped Files still work across sessions, so you can always use one of those. I recently converted a complex shared section DLL to use multiple MMFs and the job took just over a day, so... pretty easy. The downside is that if you're using MMFs for cross-session comms, the MMF itself has to be created by a high privilege process. I used a service to do this.
And MMF in the global namespace also requires the global name privilege (admin rights in order to enable this in your token) in order to create a section that can be seen by any less elevated process in other user sessions (LUA accounts etc. in terminal services or fast-user switched sessions). I use mailslots for IPC because you don't need any special privileges or account elevation. On a local machine (not remote over a network) mailslots are completely reliable and throughput is just as good as pipes, I've benchmarked them both. Mailslots are also simple to use, building a bi-directional reliable communication is more difficult but possible. Since the OP only cares about passing a parameter one-way (uni-directionally) I believe a mailslot is the simplest route without issues mentioned above. Just my 2 cents


--Iconic
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Re: Passing Parameters

Post by dcsoft »

@Iconic - thanks, I wasn't aware that shared data in DLL's did not work across sessions (e.g. to a service). But that may be OK for the OP. If it is, they are simpler than MMF. However, MMF are simple(r) because Madshi has made nice MCH API's for them. :D I don't think either mailslots or named pipes are suitable for the OP because he needs the data in DllMain().
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Passing Parameters

Post by madshi »

Usually the process which initiates the DLL injection has admin/higher rights, anyway. Otherwise it couldn't initiate system/session/user wide DLL injection. If the process does have admin rights, it should be no problem to create a global file mapping. And the DLLs need no special rights to open such a global file mapping, as long as it's created with appropriate access rights.
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Passing Parameters

Post by iconic »

Yup. Madshi is correct and DCSoft, you as well. I guess what I failed to illustrate is who can create such an IPC channel, the lesser privileged processes should be able to reliably, without the need for such higher rights and/or privileges. Easier said than done, but definitely possible, just depends on the IPC method used since several exist, all with their own advantages and disadvantages. madCodeHook does have excellent IPC functionality, as DCSoft mentioned :D Frankly, I'd have used it to solve the OP's inquiry but he mentioned no "IPC" so I assumed he wanted another method for whatever reason or another. Even MMF is still considered "IPC" so any time you communicate across process boundaries it's hard for me to digest what is not "IPC".

--Iconic
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Passing Parameters

Post by madshi »

Well, madCodeHook's IPC is mainly built for the opposite direction: Hook dlls trying to contact the application. The application trying to send information to the hook dlls is more difficult. There's only one application, but dozens of hook dlls (one in each process). So using madCodeHook's IPC would either require every hook dll to contact the application in DllMain. Which is possible, but delaying the DllMain processing by waiting for a reply from a different process sounds scary to me, to say the least. The other option would be for each dll to create its own IPC queue and then for the application to enumerate all processes and send a message to each hook dll separately. I highly recommend against that because creating an IPC queue (at least with madCodeHook's IPC functions) requires creating a thread. And creating threads in hook dlls is a risky business. So both options using madCodeHook's IPC functions are not very attractive, IMHO, for the purpose of sending information to the hook dlls for initialization in DllMain. I think MMF is really the most simple and most effective method for this specific purpose. It does require the application to have the right to create a global file map, though (unless you only inject DLLs into the current session, and also not into system processes / services).
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Passing Parameters

Post by iconic »

Right. A controller app generally accepts commands or requests (something is returned) and that's the traditional and standard expectation, implying higher elevation and admin rights to some degree. I guess my point is, consider this strange scenario, say 2 LUA accounts are open at the same time and obviously logged in, how are they to communicate if you can't breach session boundaries to communicate with one another without implied higher elevation or admin rights in order to create such a channel or sink? That's like saying 2 "normal" or standard user accounts can't communicate unless there is some admin level jurisdiction. I mean, named pipes and mailslots for instance, rely on named objects, so given that "name" ahead of time they can find each other, even if it's some run-time algorithm to determine it dynamically. They should still be able to communicate despite the fact that it's a DLL or process issuing the communication. That's where session boundaries and admin rights with IPC pose a factor, leading to my initial response.

Susie Q in session 3 (LUA) can still "create" an IPC channel and r/w to this channel without the assistance of anything special, just a way of locating the channel (by name). Session 4 is the same way so they can reliably communicate. Is it common, no. But why I expect anything less? I don't assume that all end users possess admin rights in any account they are testing with, that would be a volatile assumption to make, speaking of IPC only and not system wide or session wide DLL injection, of course. It's why I use mailslots and nothing else for reliable IPC since it doesn't require anything special or need a hand with session restrictions, process elevation or rights etc.

--Iconic
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Passing Parameters

Post by madshi »

You do need some sort of listener for mailslots, too, don't you? Inside a hook dll you would have to create a thread which controls the receiving end of the communication, no?
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Passing Parameters

Post by iconic »

Yes, inside a DLL you'd create a "listener" posing as a "server" or reader and a client (any process client) can function as a client then write to it, it's similar to a broadcast mode. No thread needed in DLLMain, since new threads will not run inside DLLMain anyhow, only after DLLMain executes will newly created threads run due to the PE loader lock logic. You can create the mailslot and simply poll for messages based on API or wait for an event, if you want to use synchronous I/O or you can also do it asynchronously. CreateMailslot() and GetMailslotInfo() work well here, if you want sync I/O you can skip the 2nd API call, just wait on a blocking ReadFile() call with an event, events can also be created in the global namespace from a LUA process, contrary to popular belief. Mailslots are often overlooked and in this case it's hard for me to realize anything simpler, again just my 2 cents and nothing but respect to this forum.

--Iconic
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Passing Parameters

Post by madshi »

Ok, but if the dlls need information in DllMain, you'd have to wait in DllMain for the application to react, wouldn't you? Which means if the application is stalled for some reason, every new process in the OS would fail to start. Or at least be delayed, if you use a timeout. But if you use a timeout, the dll doesn't have the information it needs from the application. Correct?
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Passing Parameters

Post by iconic »

100% correct but that's the core nature of waiting on IPC information. If it's not there, and an application absolutely requires it (even from within a DLL which is merely a sub-component of a process since it's merely loaded), it waits. Ideally a smart wait or asynchronous behavior is desirable (GUI message processing etc) or a sleep loop etc. Nothing your IPC mechanism doesn't already do aka ProcessMessages: BOOL. Since this thread is merely about "passing parameters" it doesn't need too much depth, if the DLL was programmed to do this it could send the controller app or some other DLL a "ready" message to its own mailslot and then wait for this parameter within a given "timeout". I know that we're getting off topic however to accentuate my original post, doing so doesn't have session boundary issues or process elevation issues. All are equal in communication and reliable on a local machine (remotely as in over a network, no guarantee there at all). If passing a param to a separate process only involved basically 2 legacy API calls that have been around since Windows 95 and these APIs are still maintained through Windows 10 there may be a good reason to use such old APIs at times. I don't see anything more reliable, less problematic nor simple but that's just my humble opinion

--Iconic
madshi
Site Admin
Posts: 10754
Joined: Sun Mar 21, 2004 5:25 pm

Re: Passing Parameters

Post by madshi »

If we were talking about general IPC usage, I wouldn't argue here at all. But that's not what this thread is about. See first post. My understanding is that the original poster does not need any back-and-forth communication. He just needs to pass on some parameters from the application to DllMain.

In the context of this thread I simply think that a solution which requires a wait/timeout logic in *DllMain* (as you know, due to the loader lock DllMain is the worst place you could possibly choose to delay/wait) can not be a good solution. I would not recommend my own IPC here, either. MMFs seem like the only "good" choice here. Yes, there is the issue with needing higher privileges to create a global MMF. But within the context of this forum, 99% of all users are doing system/session/user wide DLL injection, so they need higher privileges to initiate the DLL injection, anyway. So this MMF specific "problem" should not apply in this context.
iconic
Site Admin
Posts: 1065
Joined: Wed Jun 08, 2005 5:08 am

Re: Passing Parameters

Post by iconic »

Hey Madshi,

Yeah, agreed. The context on this forum with your package is system-wide stuff and admin rights are generally implied. I realize that the OP only wants a one-way passing of param(s) so I mentioned this posts ago
Since the OP only cares about passing a parameter one-way (uni-directionally) I believe a mailslot is the simplest route without issues
Sorry for getting slightly off topic with the LUA and session boundaries talk :D

--Iconic
Post Reply