我正在尝试使用MSDN Detours 3.0进行绕行,以注册由第三方软件的 ExtTextOut()绘制的文本。我创建了一个DLL,并将其注入(inject)目标软件中。当我绕开ExtTextOut时,我尝试复制发送到该方法的字符串,并将文本读取为修改后的格式的文本文件。由于输入字符串是UTF-16,并且我只想将ASCII字符保持在127以下,因此我对此做了一些逻辑。

但问题是,我的程序在注入(inject)到目标中后会崩溃一段时间。我怀疑这可能与 malloc函数有关。

如果我使用malloc在进程中定位内存,我可以保证不会覆盖目标进程中的任何内存吗? 如果是这种情况,我该如何创建一个函数来确保我的malloc不会干扰目标进程。

编码:

BOOL WINAPI Mine_ExtTextOut(HDC hdc, int X, int Y, UINT options, RECT* lprc, LPCWSTR text, UINT cbCount, INT* lpSpacingValues)
{

    //
    if(reinterpret_cast<const char*>(text)[0] == '>'){

        //wstring_convert<codecvt_utf8_utf16<wchar_t>,wchar_t> convert;
        //string utf8_string = convert.to_bytes(text);
        //int n = utf8_string.length();

        int n = cbCount;

        char *buffer = (char*) malloc (n+1);
        char *bufferCopy = (char*) malloc (n+1);

        for (int i=0; i<n; i++){
            if((long) text[i] > 127){
                buffer[i] = ' ';
                continue;
            }
            buffer[i]= (char) text[i];
        }
        buffer[n]='\0';



        bool wasBlank = false;
        int ix = 0;
        for(int i = 0; i<n; ++i){
            if(buffer[i] == ' '){
                if(wasBlank || i < 2) continue;
                bufferCopy[ix++] = buffer[i];
                wasBlank = true;
                continue;
            }
            wasBlank = false;
            if(buffer[i] == '>') continue;
            bufferCopy[ix++] = buffer[i];
        }
        bufferCopy[ix]='\0';

        ofstream myFile;
        myFile.open("C:\\temp\\textHooking\\textHook\\example2.txt", ios::app);
        if(buffer[0] == '>'){
            //myFile.write(reinterpret_cast<const char*>(text), cbCount*sizeof(*text));
            myFile.write(bufferCopy, ix*sizeof(*bufferCopy));
            myFile << endl;
        }

        free(buffer);
        free(bufferCopy);

    }
    BOOL rv = Real_ExtTextOut(hdc, X, Y, options, lprc, text, cbCount, lpSpacingValues);
    return rv;
}

最佳答案

cbCountExtTextOut()参数以字符表示,但是malloc()的输入参数以字节表示。您正在钩住Unicode版本的ExtTextOut()(又名ExtTextOutW()),其中sizeof(WCHAR)是2个字节。您正在尝试将输入字符串视为Ansi,但并非如此,并且您也没有考虑UTF-16替代项。

要执行您要尝试的操作,您需要先实际将UTF-16数据解码为Unicode代码点,然后再决定保留哪些代码点,例如:

BOOL WINAPI Mine_ExtTextOut(HDC hdc, int X, int Y, UINT options, RECT* lprc, LPCWSTR text, UINT cbCount, INT* lpSpacingValues)
{
    if ((cbCount > 0) && (text != NULL) && (text[0] == L'>'))
    {
        // worse case, every UTF-16 character is ASCII and will be kept,
        // so allocate enough memory for at least that many characters
        std::string buffer(cbCount);
        std::string bufferCopy(cbCount);

        int ix1 = 0;
        for (UINT i = 0; i < cbCount;)
        {
            ULONG c;

            // is it a UTF-16 high surrogate?
            if ((text[i] >= 0xD800) && (text[i] <= 0xDBFF))
            {
                // is it at the end of the string?
                if ((i+1) == cbCount)
                {
                    // malformed surrogate
                    break;
                }

                // is it followed by a UTF-16 low surrogate?
                if ((text[i+1] < 0xDC00) || (text[i+1] > 0xDFFF))
                {
                    // malformed surrogate
                    break;
                }

                // decode the surrogate and skip past it
                c = ((ULONG(text[i] - 0xD800) << 10) | ULONG(text[i+1] - 0xDC00)) + 0x10000;
                i += 2;
            }

            // is it a UTF-16 low surrogate?
            else if (text[i] >= 0xDC00) && (text[i] <= 0xDFFF))
            {
                // malformed surrogate
                break;
            }

            // must be a non-surrogated character
            else
            {
                c = (ULONG) text[i];
                ++i;
            }

            // keep it?
            if( c > 127 )
                buffer[ix1] = ' ';
            else
                buffer[ix1] = (char) c;

            ++ix1;
        }

        bool wasBlank = false;
        int ix2 = 0;
        for(int i = 0; i < ix1; ++i)
        {
            if (buffer[i] == ' ')
            {
                if (wasBlank || (i < 2)) continue;
                bufferCopy[ix2++] = buffer[i];
                wasBlank = true;
                continue;
            }
            wasBlank = false;
            if (buffer[i] == '>') continue;
            bufferCopy[ix2++] = buffer[i];
        }

        ofstream myFile;
        myFile.open("C:\\temp\\textHooking\\textHook\\example2.txt", ios::app);
        if (myFile)
        {
            myFile.write(bufferCopy.c_str(), ix2);
            myFile << endl;
        }
    }

    return Real_ExtTextOut(hdc, X, Y, options, lprc, text, cbCount, lpSpacingValues);
}

07-24 14:31