views:

254

answers:

2

Dears,

I've got a DLL for injection. This is injected via CBT-hook. Now, when the desired process is encountered via CBT, I've detoured WinAPI's ExtTextOutW with my own. The specification of ExtTextOutW is:


BOOL ExtTextOutW(HDC         hdc,
                 INT         x,
                 INT         y,
                 UINT        flags,
                 const RECT* lprect,
                 LPCWSTR     str,
                 UINT        count,
                 const INT*  lpDx)

In my detoured ExtTextOutW i'm trying to convert str (LPCWSTR) to multibyte with the following code:


BOOL Mine_ExtTextOutW(HDC         hdc,
                      INT         x,
                      INT         y,
                      UINT        flags,
                      const RECT* lprect,
                      LPCWSTR     str,
                      UINT        count,
                      const INT*  lpDx)
{
        BOOL rv = Real_ExtTextOutW(hdc, x, y, flags, lprect, str, count, lpDx);

        HANDLE h = ::WindowFromDC(hdc);

        if (!h || !str)
                return ev;

        CHAR *buffer = (CHAR *)::LocalAlloc(count + 1);

        int l = ::WideCharToMultiByte(CP_APC, 0, str, count, buffer, count, NULL, NULL);

        if (l > -1) {
                buffer[l] = '\0';

                g_pClient->SendViaIPC(buffer);
        }

        ::LocalFree(buffer);

        return rv;
}

Unfortunately, this doesn't work. WideCharToMultiByte hangs the injected process. Why?

A: 

I don't know why it is hanging your process, it looks like it should work correctly to me. Are you sure it is the WC2MB call that is causing it? Some possibilities:

  1. why are you using LocalAlloc? Is it not sufficient to use a buffer on the stack?
  2. maybe it is the "SendViaIPC" that is hanging?
  3. how big is the string you are converting? Maybe the buffer is of insufficient size?

What is the return value from WC2MB? The function returns 0 if it does not succeed.

What is the return value from LocalAlloc? Maybe the allocation is returning null indicating a failure to allocate memory? You would then be passing NULL for the buffer, but some number greater than 0 for the count which would probably lead to a crash.

1800 INFORMATION
If implement the buffer on the stack, this crashes. Also, the string is in varying size (up to 8192). Also, the process can send simultaneously several hundreds of ExtTextOutWs, so the stack can end up all of the sudden. SendViaIPC is not the issue. If I fill up the buffer with nonsense and remove WideCharToMultiByte, everything works (no crash).
nhaa123
@nhaa123 I'm seeing the same crash with a char buffer on the stack.
Plow
+2  A: 

Your code looks a little odd, does it compile?

LocalAlloc should have two parameters and did you mean CP_ACP. Anyway instead I would:

  • Ask WideCharToMultiByte for the correct size, just in case you change your code page in future.
  • Check for > 0 (failure is represented by 0 and not -1)
  • Use std strings just to make sure you don't have any memory leaks, exceptions etc.

So something like this:

int nMultiByteSize = ::WideCharToMultiByte( CP_ACP, NULL, str, count, NULL, 0, NULL, NULL );
if ( nMultiByteSize > 0 )
{
    std:string strMulti;
    strMulti.resize( nMultiByteSize );

    if ( ::WideCharToMultiByte( CP_ACP, NULL, str, count, &strMulti[0], (int)strMulti.size(), NULL, NULL ) > 0)
    {
        g_pClient->SendViaIPC(strMulti.c_str());
    }
}
snowdude