Jump to content
Tuts 4 You

WM_COPYDATA to dll injected in target?


high6

Recommended Posts

Posted

I want to send WM_COPYDATA messages to my dll injected in a exe. Sorta like how WPE Pro works.

I currently am trying this.

GMAptr GMATrampoline = 0;
GMAptr GMATarget = 0;
BOOL __stdcall GetMessageADetour(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
{
BOOL ret = GMATrampoline(lpMsg,hWnd,wMsgFilterMin,wMsgFilterMax);
if (lpMsg->message == WM_COPYDATA)
{
if (lpMsg->wParam == MessageNum)
{
COPYDATASTRUCT * data = (COPYDATASTRUCT*)lpMsg->lParam;
ParseCommand(data);
lpMsg->message = 0;
}
}
return ret;
}BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD Reason, LPVOID lpReserved)
{
HMODULE mod;
switch(Reason)
{
case DLL_PROCESS_ATTACH:
//MessageBoxA(0,"a",0,0);
mod = LoadLibraryA("user32.dll");
if (mod==0)
{
MessageBoxA(0,"Problem loading user32.dll",0,0);
return true;
}
GMATarget = (GMAptr)GetProcAddress(mod,"GetMessageA");
if (GMATarget==0)
{
MessageBoxA(0,"Problem finding GetMessageA",0,0);
return true;
}
GMATrampoline = (GMAptr)DetourFunction((PBYTE)GMATarget,(PBYTE)GetMessageADetour);
break;
case DLL_PROCESS_DETACH:
if (GMATrampoline == 0)
return true;
DetourRemove((PBYTE)GMATrampoline,(PBYTE)GetMessageADetour);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return true;
}

I tried using SetWindowsHook but I kept having trouble with it. Also with hooking GetMessageA I can make sure the target does not get my message. Only problem is this doesn't work. Should I change the hook to PeekMessageA?

I am trying to send WM_COPYDATA from a C# app. Although I don't think the sending is the problem.

Any help with this would be nice :D .

Posted

couldn't you have the injected dll create a window that will receive the messages? no need for hooks then.

Posted
couldn't you have the injected dll create a window that will receive the messages? no need for hooks then.

Well I rather stop the target from seeing the messages.

Computer_Angel
Posted

GetMessage ??? Maybe you hook the wrong function.

Posted
GetMessage ??? Maybe you hook the wrong function.

GetMessage is an api for windows messages...

Posted

Why use WM_COPYDATA when there are more suitable methods for this exact purpose? You should look into using named pipes or MMF's. They will work a lot faster, more reliable, and not depend on a window message to update.

Posted (edited)

I guess I will look at pipes. When you use a pipe does it notify the exe? Or does the exe constantly have to check the pipe? Also I noticed it uses the CreateFile api, does it actually use physical files for the pipes?

Pipes look better because I can easily send the client info. The only problem I have is that with pipes, it is like sockets. I very much dislike sockets :P . Every time I think of sockets I over think what to do about not receiving the full packet.

Edited by high6
Posted

The pipe doesn't work like UDP style packets when it comes to receiving the full buffer. You will receive the full thing. But yes, you need to read the pipe in a loop to handle incoming data and such. If you are worried about speed and such you could also use MMFs with a custom queue system. I can assure you that MMFs work great for this (and are more reliable then pipes). A project I have done for work involved pipes at first and after a few issues due to the speed and rate we needed to transfer data, we moved into a custom queued MMF system I wrote that is a ton faster and handled the data much more efficiently.

The file created that is used with pipes is created on physical memory which are "mounted" to the named pipe file system.

Inside your DLL you can create a thread using CreateThread to monitor the pipe like this:

DWORD __stdcall YourThreadName() 
{
HANDLE hPipe = INVALID_HANDLE_VALUE;
unsigned char btData[ MAX_PIPE_SIZE ];
DWORD dwBytesRead; while( true ) { hPipe = CreateNamedPipe( lpPipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, MAX_PIPE_SIZE, MAX_PIPE_SIZE, STDTIMEOUT, 0 );
if( hPipe != INVALID_HANDLE_VALUE ) {
if( ConnectNamedPipe( hPipe, 0 ) ? TRUE : ( GetLastError() == ERROR_PIPE_CONNECTED ) ) {
if( ReadFile( hPipe, btData, MAX_PIPE_SIZE, &dwBytesRead, 0 ) ) {
if( dwBytesRead > 0 ) {
//
// Do what you want with the data inside of btData here.
//
}
FlushFileBuffers( hPipe );
DisconnectNamedPipe( hPipe );
}
}
}else{
Sleep( 10 );
}
}
if( hPipe ) {
CloseHandle( hPipe );
hPipe = 0;
}
return 0;}

I cannot gaurantee this is the best method suitable for using pipes, but it is the method I used when myself and another developer wrote the hook we did for work.

I suggest you look into MMFs as well. They are very easy to work with, however they do not have a blocked writing/reading system like pipes so you need to create a queue method to handle reading and writing to the MMF. It is really not hard to do. You should setup a structure at the start of the MMF to handle validation and such, something like:

struct _MMF_HEADER {
DWORD dwCount; // Should be big enough if not use a custom datatype such as unsigned char [size]
unsigned char bHandled; // Boolean check to determine if the current data has been read and handled.
DWORD dwDataSize; // Size of the data inside the MMF (should include the header as part of its size.)
};

This is just an example of something you could do. With this, you can confirm the count by incrementing it by one each time it is handled and comparing it to the last count recorded. Also with this, your hook can create a queue by checking the bHandled byte in the header to ensure that the current data was handled already or not. If not, it can be pushed into a vector or something an stored to be added later.

This is the route I took when writing an IPC method that was fast and reliable. I can assure you that the MMF method can handle a lot more data faster then the pipes can if you need to do things at a very high rate.

When I wrote my queue handler, I wrote a test application to test the speed and such of the queue system, and it was 1:1 when it came to handling the data. The method we used to test was setting the max MMF size to 10k bytes and writing random data to it every 10 miliseconds. ( Sleep(10) ) The C# program was able to keep up reading from the MMF that the queue never got over 2. The nice part is you can handle losted connections as well. When the C# application disconnected the queue rapidly grew in size as the MMF was not read/handled. But as soon as the C# application reconnected, the queue instantly dropped back to 0/1/2 in size after pushing the queue to the MMF to be handled.

If you need any help, I would be glad to help you out. Just ask. :)

Posted
The pipe doesn't work like UDP style packets when it comes to receiving the full buffer. You will receive the full thing. But yes, you need to read the pipe in a loop to handle incoming data and such. If you are worried about speed and such you could also use MMFs with a custom queue system. I can assure you that MMFs work great for this (and are more reliable then pipes). A project I have done for work involved pipes at first and after a few issues due to the speed and rate we needed to transfer data, we moved into a custom queued MMF system I wrote that is a ton faster and handled the data much more efficiently.

The file created that is used with pipes is created on physical memory which are "mounted" to the named pipe file system.

Inside your DLL you can create a thread using CreateThread to monitor the pipe like this:

DWORD __stdcall YourThreadName() 
{
HANDLE hPipe = INVALID_HANDLE_VALUE;
unsigned char btData[ MAX_PIPE_SIZE ];
DWORD dwBytesRead; while( true ) { hPipe = CreateNamedPipe( lpPipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE|PIPE_WAIT, PIPE_UNLIMITED_INSTANCES, MAX_PIPE_SIZE, MAX_PIPE_SIZE, STDTIMEOUT, 0 );
if( hPipe != INVALID_HANDLE_VALUE ) {
if( ConnectNamedPipe( hPipe, 0 ) ? TRUE : ( GetLastError() == ERROR_PIPE_CONNECTED ) ) {
if( ReadFile( hPipe, btData, MAX_PIPE_SIZE, &dwBytesRead, 0 ) ) {
if( dwBytesRead > 0 ) {
//
// Do what you want with the data inside of btData here.
//
}
FlushFileBuffers( hPipe );
DisconnectNamedPipe( hPipe );
}
}
}else{
Sleep( 10 );
}
}
if( hPipe ) {
CloseHandle( hPipe );
hPipe = 0;
}
return 0; }

I cannot gaurantee this is the best method suitable for using pipes, but it is the method I used when myself and another developer wrote the hook we did for work.

I suggest you look into MMFs as well. They are very easy to work with, however they do not have a blocked writing/reading system like pipes so you need to create a queue method to handle reading and writing to the MMF. It is really not hard to do. You should setup a structure at the start of the MMF to handle validation and such, something like:

struct _MMF_HEADER {
DWORD dwCount; // Should be big enough if not use a custom datatype such as unsigned char [size]
unsigned char bHandled; // Boolean check to determine if the current data has been read and handled.
DWORD dwDataSize; // Size of the data inside the MMF (should include the header as part of its size.)
};

This is just an example of something you could do. With this, you can confirm the count by incrementing it by one each time it is handled and comparing it to the last count recorded. Also with this, your hook can create a queue by checking the bHandled byte in the header to ensure that the current data was handled already or not. If not, it can be pushed into a vector or something an stored to be added later.

This is the route I took when writing an IPC method that was fast and reliable. I can assure you that the MMF method can handle a lot more data faster then the pipes can if you need to do things at a very high rate.

When I wrote my queue handler, I wrote a test application to test the speed and such of the queue system, and it was 1:1 when it came to handling the data. The method we used to test was setting the max MMF size to 10k bytes and writing random data to it every 10 miliseconds. ( Sleep(10) ) The C# program was able to keep up reading from the MMF that the queue never got over 2. The nice part is you can handle losted connections as well. When the C# application disconnected the queue rapidly grew in size as the MMF was not read/handled. But as soon as the C# application reconnected, the queue instantly dropped back to 0/1/2 in size after pushing the queue to the MMF to be handled.

If you need any help, I would be glad to help you out. Just ask. :)

Thanks for all the info. What does MMF stand for or where can I find some examples? I googled "C++ MMF examples" and got nothing.

Also can you detect when the receiver is dropped in MMF so that it doesn't continue queuing up data?

Posted

MMF stands for Memory Mapped File.

You can create a memory mapped file using the following API:

- CreateFileMapping

- MapViewOfFile

- UnmapViewOfFile

- CloseHandle

You can read and write to the file using memcpy/memset once the file is created.

MapViewOfFile returns a pointer for the file object mapped into your process.

And no, MMFs have no blocking methods involved, they are simply a file mapping into memory that are used to hold data and that allow other processes to access them. Basically, it's like using VirtualAlloc to create a buffer and having other processes able to directly access the memory block.

You can obtain the object in other processes once its created by either inheriting the handle or by recreating the mapping with the same name. (The system checks the mappings for the same name and if its already found the object is created inside the calling process as a duplicate of the original mapping.)

Theres no restrictions to reading/writing to the MMF in the sense of a blocked communication. Anything is free to read and write to the MMF at any time. Which is why I suggest you setup a queue system with a header that the processes can check if the written data was handled. The example I showed is more or less so for a one way communication, but you can use the same mmf to do two way if needed. (It would be slower and not as safe as just using two.)

Some links that can help you with this subject:

http://msdn.microsoft.com/en-us/library/aa366542(VS.85).aspx
http://support.microsoft.com/kb/142377 <-- Class created by Microsoft to use MMFs. (I havent checked this out so I'm not sure how good it is.)
http://www.codeproject.com/KB/threads/ipc_tute.aspx
http://www.codeproject.com/KB/winsdk/cmemmap.aspx

CodeProject has a lot of examples, just search for "Memory Mapped File" and you should be able to find some useful stuff. Just post if you have any questions. :)

Posted

Thanks. I think I might try that with SendMessages.

Although pipes are very nice.

  • 2 weeks later...
Posted (edited)

So I guess MMF looks good. I guess I would have a Server file which the clients write to and the server reads and then a file for each client so the server has something to write too.

then probably a structure like

int size

fixed array based on size

and when I write, I go through the sizes until I hit a 0 and then append it.

A question about MMF though. I know that you have to define the size of it, so can you make it larger easily?

Edited by high6
  • 2 weeks later...
Posted

The overall MMF is a fixed size once it's created, you can't resize it without unmapping it and recreating it. Making a function to resize constantly is a bad idea as well as it will cause a major impact in performance as you will be constantly unmapping the heap. It also flushes everything so you need to maintain the data and such if needed as well.

The best bet with using an MMF is using a big enough block that you feel will never be used at full. Depending on what you need to send back and forth, just add a chunk onto the max you think you will use and go from there. So if you are sending small commands to a dll or something, you could limit the functions input inside the dll then just set the buffer limit within the MMF to the similar number. So you could end up having

[MMF_Header][MMF_Raw_Data]

So take into account how much info you need inside your header, this should be a static size that is used every single time the MMF is written to, to keep things easy to handle and consistent. Then you could do sizeof(MMF_Header) + 260 for the MMF size when it is created. (260 to give some whitespace and "bleed" room to prevent faults and all that fun jazz.)

Posted

APIENTRY and __stdcall are the same, also define your entry-point as a callback function !.

Posted

Heres an example to better help you out high6, should clear up some of the things I was trying to explain and should point you in the direction I was explaining. Keep in mind this is a very dumbed down version of the one I wrote for my more major project(s) so you should add onto this and do things a little different for checks and balances, then extend into something handling the incoming data.

This example was done on XP Pro w/SP3 using the default Minesweeper. I used DbgView to display the debug messages, which you can find via the first link in Google if you need it. (Just search dbgview.)

APIENTRY and __stdcall are the same, also define your entry-point as a callback function !.

CALLBACK, WINAPI, APIENTRY, APIPRIVATE, PASCAL are all _stdcall. So his entry point is fine.

MMFSender.rar

Posted

why not just subclass the window?

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...