Page 1 of 2

Fastest way to IPC from a DLL to an EXE

Posted: Tue Mar 30, 2021 4:32 am
by abalonge
I have an EXE that I have written in Delphi which calls a DLL which I have also written in Delphi. This DLL is also loaded by an interpreted language which can not use pointers or addresses (ie, can not pass the address of a function or assign a pointer to a variable) in it's script language. When this interpreted language calls a function in my DLL I want to notify my EXE (IL -> DLL -> EXE). In tests I have it working with Windows IPC SendMessage and also with madCodeHook SendIpcMessage...from my DLL to my EXE. I am wanting the fastest execution method, no payload aside from an integer and do not need replies.
I am looking to see if I can do it in a faster way then those because many notification per second are needed. I know a callback, that is not inter-process (just between my EXE and DLL alone), is the fastest of the three in my tests (although that might not be the case if it was possible to implement in my situation) but given that the goal is inter-process and the interpreted language limitations, maybe something else that I have not mentioned would be better?

Thanks!

Re: inter-process callback possible?

Posted: Tue Mar 30, 2021 5:58 am
by iconic
Why not simply export your “callback”? That would make the most sense to be honest. You can calculate the address rather easily, relative virtual address (RVA) of exported callback + load address (HMODULE) in the other process to call it.

In general though each process has a separate address space (NT) so the function can have a different virtual address. It varies process to process. Also, MMF and other IPC can fail for several reasons so I wouldn’t find it reliable for sharing a function address with other processes.

—Iconic

Re: inter-process callback possible?

Posted: Tue Mar 30, 2021 12:50 pm
by madshi
A "function address of a delphi program" sounds like you're talking about code that is located in an EXE file?

If so, no, you cannot easily make this available in other processes. Other processes would first have to load a module (DLL/EXE) file which contains the same code. Please understand that each process is completely separated in modern OSs. Which means that code which is available in process A is not available in process B. And a pointer in process A doesn't point to the same physical RAM as a pointer with the same value in process B.

Re: inter-process callback possible?

Posted: Tue Mar 30, 2021 3:37 pm
by abalonge
@iconic - I'll think on that idea.
@madshi - Yes an EXE. That seperation of process code can be inconvenient in my case.

Re: inter-process callback possible?

Posted: Tue Mar 30, 2021 4:02 pm
by abalonge
I'm thinking of replacing the callback with a madCodeHook IPC Message or a Windows IPC Message. I did a test with that and it works well, but I was wanting to use a callback because it would execute faster in my case.

Re: inter-process callback possible?

Posted: Tue Mar 30, 2021 4:30 pm
by madshi
I think you need to work on understanding the concepts of process isolation better. IPC will not magically make your EXE's code available to another process. If you want to call your EXE's code in the context of another process then you first have to get the other process to load your EXE's code somehow. Usually this is done by putting the code into a DLL and then make the other process load the DLL somehow. That's the cleanest solution, anyway.

How to actually "call" your code in the context of the other process is a whole different topic. It's a separate problem you also have to solve. But the first thing to solve is that any code you want to call must first be made available in the target process.

Maybe if you give us a full explanation of what you really want to do and for which purpose in great detail, then we can give you better advise.

Re: inter-process callback possible?

Posted: Tue Mar 30, 2021 8:34 pm
by iconic
Simple/Easiest steps:

Export your callback from your DLL

Inject your DLL into whichever processes you need to have callback execute remotely

In your process (which executes code in other processes) enumerate modules in the target process(es)
and add the module base address (HMODULE), if your module is found, to the relative virtual address (RVA) of the exported callback function

You can calculate the function's RVA by loading the DLL into your process and subtracting the base address (HMODULE) from the callback's virtual address (VA), and store the RVA, it won't change regardless of process, only the VA can change from process to process.

Create a new remote thread at this function address (your exported callback in the target process with Base + RVA which turns into VA)

Done.

That's the short end of it for the sake of brevity, there are things you'll need to pay attention to such as process bitness differences, the state of the process (suspended, debugged, uninitialized, initialized), process session isolation etc. It mostly pertains to if/when it's "safe" to execute a remote thread, but that's magic which Madshi and I already know too well and it's not a quick and easily understood post to elaborate upon.


--Iconic

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 3:17 am
by abalonge
@madshi - When I said I used IPC in a test to replace the callback, it was not to make my EXE's code available to another process but to accomplish the end goal in a different way...which you are correct, I will reword my original post and explain the purpose instead.

@iconic - Unfortunately, I found out that the other process can only load a DLL but can not handle pointers/addresses (I seem to work with many interpreted/script based languages). The callback is in my process and the executing code would be in the interpreted process.

Sorry for any confusion, hopefully I can clear things up with a rewording.

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 3:25 am
by iconic
the other process can only load a DLL but can not handle pointers/addresses
If the other process can load a DLL which exports a function it needs no knowledge of what is going on, it's only loaded some .dll file that exports an API, "remotely" callable from any other process. That's why Windows is built on modularization with DLL's, the main .EXE can't perform everything on its own with(out) additional resources, eg: other DLL dependencies.

If you tell Madshi and I more we can help.

--Iconic

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 3:44 am
by abalonge
Thanks. I reworded my question, if it is not clear please ask whatever.

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 6:53 am
by madshi
A simple "callback" won't work across process boundaries. I think the easiest way to solve this is to simply use PostMessage(). It's surprisingly fast and very easy to use. E.g. in your DLL (when loaded inside of the script process) do:

PostMessage(YourExesMainFormWindowHandle, WM_USER + 123, param1, param2);

You can send 2 parameters this way, param1 and param2. And in your Delphi EXE, simply add a message handler for WM_USER + 123.

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 8:28 am
by iconic
You've reworded your initial question, so that led to confusion. My response was solely based on how to remotely "execute" code without any other library assistance. Now that we have a better context of what you mean, it seems to be you may want to simply "notify" your EXE of a function call and not actually execute any code in remote processes.

As Madshi said with PostMessage():

You can use PostMessage() (It's fast and doesn't wait like SendMessage) from your scripted program that loads your DLL and needs to inform your EXE for (IPC) means, however it only works with non-service processes, so be careful of this. madCodeHook's SendIpcMessage() works in both services and GUI apps regardless of session. There's a BIG difference, but if speed is a factor for "notification" PostMessage() is very fast, it's governed below user32.dll by Win32k.sys as a direct system call (e.g: NtUserXxX).

Perhaps, if I understand what you mean, you should have titled your post "Fastest way to IPC from a DLL to an EXE" - actually mailslots are VERY quick too, but that's another rant :D

--Iconic

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 8:51 am
by madshi
Yes, iconic is right, of course, about services. PostMessage may not work if the other process is a service. Considering abalonge talked about a script process, I thought it would be a normal user process. But it might not be.

@iconic, calling PostMessage does not internally make the thread handle messages or put the thread into an alertable state, does it? I don't think it does, just wondering...

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 8:54 am
by iconic
PostMessage() doesn't touch the alertable state of any thread, the request sits in the queue of the target window that received it until it's processed asynchronously.

--Iconic

Re: inter-process callback possible?

Posted: Wed Mar 31, 2021 9:02 am
by madshi
I was mainly worried about the alertable state of the thread calling PostMessage. But good to know it doesn't change the alertable state of any thread, thanks!