我试图绕道而行使用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;
}
Run Code Online (Sandbox Code Playgroud)
所述cbCount的参数ExtTextOut()中被表示的字符,但输入参数malloc()中被表示字节.你正在挂钩ExtTextOut()(又名ExtTextOutW())的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);
}
Run Code Online (Sandbox Code Playgroud)