Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/react-native/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当绕过C+;中的函数时,malloc会导致崩溃吗+;要在目标进程中从ExtTextOut复制数据字符串?_C++_Hook_Detours - Fatal编程技术网

C++ 当绕过C+;中的函数时,malloc会导致崩溃吗+;要在目标进程中从ExtTextOut复制数据字符串?

C++ 当绕过C+;中的函数时,malloc会导致崩溃吗+;要在目标进程中从ExtTextOut复制数据字符串?,c++,hook,detours,C++,Hook,Detours,我正在尝试使用MSDN Detours 3.0来注册由第三方软件ExtTextOut()绘制的文本。我已经创建了一个DLL,并将其注入到目标软件中。当我绕道ExtTextOut时,我尝试复制发送给该方法的字符串,并以修改后的格式将文本读取到文本文件中。由于输入字符串是UTF-16,我只对保持ASCII字符低于127感兴趣,因此我对此做了一些逻辑 但问题是,我的程序在注入目标后不久崩溃了。我怀疑它可能与malloc函数有关 如果我使用malloc定位进程中的内存,我可以保证这不会覆盖目标进程中的任

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

但问题是,我的程序在注入目标后不久崩溃了。我怀疑它可能与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;
}
BOOL WINAPI Mine_ExtTextOut(HDC HDC、int X、int Y、UINT选项、RECT*lprc、LPCWSTR text、UINT cbCount、int*lpspacingvalue)
{
// 
如果(重新解释强制转换(文本)[0]=='>'){
//wstring_convert;
//字符串utf8\u字符串=转换为字节(文本);
//int n=utf8_string.length();
int n=cbCount;
char*buffer=(char*)malloc(n+1);
char*bufferCopy=(char*)malloc(n+1);
对于(int i=0;i 127){
缓冲区[i]='';
继续;
}
缓冲区[i]=(字符)文本[i];
}
缓冲区[n]='\0';
bool wasBlank=false;
int ix=0;

对于(int i=0;i,根据这里的评论,您可以做一些事情来缩小范围:

替换malloc:改为使用
buffer=(char*)GlobalAlloc(GPTR,n+1);
GlobalFree(buffer)
。这将确保拥有多个c运行库不会有问题

或者,为了确保没有超出已分配缓冲区边界的情况,请尝试多次malloc,例如
buffer=malloc(n+1024);
并查看这是否解决了问题。如果解决了问题,如果超出缓冲区中的有效偏移量,则需要仔细检查代码


一种类似的方法(用于测试)是使用比您期望的输入更长的缓冲区堆栈版本,例如
char buffer[1024];
并像malloc缓冲区一样使用它们(当然不要释放它们),看看这有什么区别。

ExtTextOut()的
cbCount
参数
字符表示,但
malloc()
的输入参数以字节表示。您正在连接
ExtTextOut()
(又称
exttextouth()
)的Unicode版本,其中
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);
}
BOOL WINAPI Mine_ExtTextOut(HDC HDC、int X、int Y、UINT选项、RECT*lprc、LPCWSTR text、UINT cbCount、int*lpspacingvalue)
{
如果((cbCount>0)&&(text!=NULL)&&(text[0]==L'>'))
{ 
//更糟糕的情况是,每个UTF-16字符都是ASCII字符,将被保留,
//因此,为至少这么多的字符分配足够的内存
std::字符串缓冲区(cbCount);
std::string bufferCopy(cbCount);
intix1=0;
对于(UINT i=0;i=0xD800)和&(文本[i]0xDFFF))
{
//畸形代孕
打破
}
//解码代理并跳过它
c=((ULONG(文本[i]-0xD800)=0xDC00)和&(文本[i]127)
缓冲区[ix1]='';
其他的
缓冲区[ix1]=(字符)c;
++ix1;
}
bool wasBlank=false;
intix2=0;
对于(int i=0;imyFile尝试关闭myFile,然后在写入之前检查fail-flag。很好,您看到了这一点,但不幸的是,这并不能解决问题。实际上,如果我注释掉几乎所有内容,从malloc到原始调用除外。它仍然崩溃。但是,如果我注释掉所有内容,只将此函数重定向到其工作的原始名称当然。当它发生崩溃时,你会得到什么样的崩溃信息?目标软件只是冻结,windows说程序已经崩溃。不知何故,分配的内存似乎以某种方式覆盖了进程中已经存在的内存,因为如果我注释掉除malloc之外的所有代码,它仍然会崩溃。@steven:我也这么想……有两份c-运行库(在调用进程和DLL中)。请尝试buffer=GlobalAlloc(GPTR,n+1)而不是malloc(n+1);非常感谢您提供了非常好的输入。我将对此进行明确的测试。不过,有两个问题,如果您找到格式错误的代理项,为什么要中断for循环?后面的以下字符是否有可能有用?还有,if((I+1)==n)语句,我猜n=cbCount?好的,现在我知道for了