Jump to content
View in the app

A better way to browse. Learn more.

Tuts 4 You

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Cross process calling?

Featured Replies

Posted

So the other day I learned about shared memory in dlls. I was wondering can a dll call a function in an external process that has the dll?

Process1|Dll

Process2|Dll

Process1 calls AnExport

AnExport(called from Process1) calls a callback in Process2

Is this possible?

Edited by high6

You can do that using CreateRemoteThread.

However, it only takes one additional param for the thread.

So you'll have to use a stub that takes a pointer to a struct with all the needed params.

The stub calls the actual function with the params taken from the struct.

Something like this:

DWORD Function1(DWORD Param1, DWORD Param2, DWORD Param3)
{
return 0;
}DWORD __stdcall SuperStub(Func1Struct * F1S)
{
return Function1(F1S->Param1, F1S->Param2, F1S->Param3);
}

Then you'll load the DLL into your own process (that requires an empty DllMain or a check for which process it's in) and get the address of the exported stub.

What's left is adjusting the address to take the different module base in the second process into account.

modProc2 = GetLoadedModuleBase(hProcess2, "my.dll");
mod = LoadLibrary("my.dll");
ULONG_PTR SuperStubAddr = (ULONG_PTR)GetProcAddress(mod, "SuperStub") - (ULONG_PTR)mod + modProc2;Func1Struct F1S;F1S.Param1 = 0;
F1S.Param2 = 2;
F1S.Param3 = 222;mem = VirtualAllocEx(hProcess2, 0, sizeof(Func1Struct), ....);WriteProcessMemory(hProcess2, mem, sizeof(Func1Struct), &F1S, ...);Thread = CreateRemoteThread(hProcess2, ...., SuperStubAddress, mem);
if(WAIT_0 == WaitForSingleObject(Thread, INFINITE))
{
DWORD Exitcode;
GetExitCodeThread(Thread, &Exitcode); // Return value
// Success
}

GetLoadedModuleBase could be implemented using CreateToolhelpSnapshot or psapi functions, there should be enough on google.

Edited by Killboy

  • Author

Just wondering if you can without CreateRemoteThread because if you were to call the function a lot, creating/destroying tons of threads doesn't seem effective.

I was thinking about Just having a thread loop and it checks a vector of callbacks and when there is a callback it calls it and removes it from the vector. Only problem with that personally is I don't know how to structure the loop.

while(true)

{

if (!TheVector.Empty())

{

//etc

}

sleep(1);

}

How do you properly do that loop? (That loop right there uses 10-20% of the cpu while idling).

You might wanna look into using WM_COPYDATA.

You just have to create an empty window in the Dll, create a message loop and in the window proc check for WM_COPYDATA.

Some example code:

Process1

	Event = CreateEvent(0, true, false, EventName);
if(!Event)
return false; if(!InjectDll(hProcess, DllPath)){
return false;
} if(WAIT_OBJECT_0 != WaitForSingleObject(Event, 5000)){
CloseHandle(Event);
return false;
}
CloseHandle(Event); DllWindow = FindWindow(WindowName, NULL);
if(!DllWindow){
return false;
} CallbackDataStruct CallbackData; CallbackData.Address = 0x1212363;
// ... COPYDATASTRUCT CDS; CDS.dwData = CALLBACK_ID;
CDS.cbData = sizeof(CallbackData);
CDS.lpData = &CallbackData; RetVal = SendMessage(DllWindow, WM_COPYDATA, (WPARAM)WndMain, (LPARAM)&CDS);

In the Dll in Process2:

BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, void * lpReserved)
{
switch(fdwReason)
{
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hModule);
HANDLE hThread;
hThread = CreateThread(0, 0, WindowThread, 0, 0, 0);
CloseHandle(hThread);
break;
} return true;
}DWORD CALLBACK WindowThread(void *){
HANDLE Event;
MSG msg; EmptyWindow = CreateEmptyWindow(WindowName, WndProc);
if(!EmptyWindow)
return false; Event = OpenEvent(EVENT_MODIFY_STATE, false, EventName);
SetEvent(Event);
CloseHandle(Event); while(GetMessage(&msg, NULL, 0, 0) == TRUE)
{
DispatchMessage(&msg);
} return 0;
}HWND CreateEmptyWindow(char * Name, WNDPROC WndProc)
{
WNDCLASS wc = {0}; wc.lpfnWndProc = WndProc;
wc.lpszClassName = Name; RegisterClass(&wc); return CreateWindow(Name, Name, WS_DISABLED, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
}LRESULT CALLBACK WndProc(HWND Window, UINT Message, WPARAM wParam, LPARAM lParam)
{
COPYDATASTRUCT * cds; switch(Message){
case WM_COPYDATA:
cds = (COPYDATASTRUCT *)lParam;
switch(cds->dwData)
{
case CALLBACK_ID:
if(cds->cbData == sizeof(CallbackDataStruct)){
CallbackDataStruct CB;
CB = *(CallbackDataStruct *)cds->lpData;
return CB.Address(CB.Param1, ...);
}
break;
}
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
} return DefWindowProc(Window, Message, wParam, lParam);
}
  • Author

I always have trouble with WM_COPYDATA not working between C#/C++.

Also in an older thread I was told not to use it.

I guess I could use shared memory and SendMessage.

Edited by high6

There shouldn't be any difference between WM_COPYDATA and a self-implemented version using SendMessage.

No idea why it doesn't work with C++/C# though, maybe a security issue.

If you're on Vista, this might work:

http://msdn.microsoft.com/en-us/library/ms632675.aspx

Dunno exactly though as it wouldn't validate and copy the data then anymore :/

  • 3 weeks later...

I just want you to note that applications are not syncronized in windows, sendmessage directly from 1 to 2 then from 2 to 1 is a recipe to lock your applications.

Edited by britedream

  • 7 months later...

Have you looked into Named Pipes for IPC? Namd pipes are very effective and quick, You could also use IPC with Registry Keys, but thats not good for what you want since you plan on transferring data.

With injection though, I would suggest staying away from pipes for extreme cases for data transfer between two processes. For work related testing, I put MMF and Named Pipes through some stress tests to see what their limits were, pipes died and locked up constantly as the data size pushed between the processes grew. MMF, if created and wrapped around your own handler, worked flawlessly. You will need to do a bit more work if you use MMFs though compared to pipes. (Just a suggestion.)

You could also try using WM_USER with SendMessage/PostMessage for handling specific messages between your processes, but for this topics purpose, calling shared memory, I would go with CreateRemoteThread with injected code to get the job done quickly.

If you use the WM_USER message method, check this API out for more info:
/>http://msdn.microsoft.com/en-us/library/ms644947(VS.85).aspx

Create an account or sign in to comment

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.