specify null length

This commit is contained in:
Akash Mozumdar 2019-03-27 23:35:22 -04:00
parent c6b7c6ba22
commit e8607e576d
6 changed files with 43 additions and 14 deletions

View File

@ -58,7 +58,10 @@ void TextThread::Flush()
std::vector<std::wstring> sentences;
queuedSentences->swap(sentences);
for (auto& sentence : sentences)
{
sentence.erase(std::remove(sentence.begin(), sentence.end(), L'\0'));
if (Output(*this, sentence)) storage->append(sentence);
}
std::scoped_lock lock(bufferMutex);
if (buffer.empty()) return;

View File

@ -27,6 +27,13 @@ namespace
}
RCode.erase(0, 1);
// [null_length<]
if (std::regex_search(RCode, match, std::wregex(L"^([0-9]+)<")))
{
hp.null_length = std::stoi(match[1]);
RCode.erase(0, match[0].length());
}
// [codepage#]
if (std::regex_search(RCode, match, std::wregex(L"^([0-9]+)#")))
{
@ -104,6 +111,13 @@ namespace
}
HCode.erase(0, 1);
// [null_length<]
if ((hp.type & USING_STRING) && std::regex_search(HCode, match, std::wregex(L"^([0-9]+)<")))
{
hp.null_length = std::stoi(match[1]);
HCode.erase(0, match[0].length());
}
// [N]
if (HCode[0] == L'N')
{
@ -181,10 +195,12 @@ namespace
if (hp.type & USING_UNICODE)
{
RCode << "Q";
if (hp.null_length != 0) RCode << hp.null_length << "<";
}
else
{
RCode << "S";
if (hp.null_length != 0) RCode << hp.null_length << "<";
if (hp.codepage != 0) RCode << hp.codepage << "#";
}
@ -213,6 +229,9 @@ namespace
else if (hp.type & BIG_ENDIAN) HCode << "A";
else HCode << "B";
}
if (hp.null_length != 0) HCode << hp.null_length << "<";
if (hp.type & NO_CONTEXT) HCode << "N";
if (hp.text_fun || hp.filter_fun || hp.hook_fun) HCode << "X"; // no AGTH equivalent
@ -287,7 +306,8 @@ namespace Util
std::optional<std::wstring> StringToWideString(const std::string& text, UINT encoding)
{
std::vector<wchar_t> buffer(text.size() + 1);
if (MultiByteToWideChar(encoding, 0, text.c_str(), -1, buffer.data(), buffer.size())) return buffer.data();
if (int length = MultiByteToWideChar(encoding, 0, text.c_str(), text.size() + 1, buffer.data(), buffer.size()))
return std::wstring(buffer.data(), length - 1);
return {};
}

View File

@ -29,7 +29,8 @@ struct HookParam
int offset, // offset of the data in the memory
index, // deref_offset1
split, // offset of the split character
split_index; // deref_offset2
split_index, // deref_offset2
null_length;
union
{
wchar_t module[MAX_MODULE_SIZE];

View File

@ -21,15 +21,16 @@ const char* CODE_INFODUMP = u8R"(Search for text
S[codepage#]text
OR
Enter read code
R{S|Q|V}[codepage#][*deref_offset]@addr
R{S|Q|V}[null_length<][codepage#][*deref_offset]@addr
OR
Enter hook code
H{A|B|W|S|Q|V}[N][codepage#]data_offset[*deref_offset1][:split_offset[*deref_offset2]]@addr[:module[:func]]
H{A|B|W|S|Q|V}[null_length<][N][codepage#]data_offset[*deref_offset1][:split_offset[*deref_offset2]]@addr[:module[:func]]
All numbers except codepage in hexadecimal
Default codepage is 932 (Shift-JIS) but this can be changed in settings
A/B: codepage char little/big endian
W: UTF-16 char
S/Q/V: codepage/UTF-16/UTF-8 string
null_length: length of null terminator used for string
Negatives for data/split offset refer to registers
-4 for EAX, -8 for ECX, -C for EDX, -10 for EBX, -14 for ESP, -18 for EBP, -1C for ESI, -20 for EDI
* means dereference pointer+deref_offset)";

View File

@ -229,14 +229,14 @@ DWORD WINAPI TextHook::Reader(LPVOID hookPtr)
{
TextHook* This = (TextHook*)hookPtr;
BYTE buffer[TEXT_BUFFER_SIZE] = {};
int changeCount = 0, dataLen = 0;
int changeCount = 0, dataLen = 1;
__try
{
uint64_t currentAddress = This->address;
while (WaitForSingleObject(This->readerEvent, 500) == WAIT_TIMEOUT)
{
if (This->hp.type & DATA_INDIRECT) currentAddress = *(uintptr_t*)This->address + This->hp.index;
if (memcmp(buffer, (void*)currentAddress, dataLen + 2) == 0)
if (memcmp(buffer, (void*)currentAddress, dataLen) == 0)
{
changeCount = 0;
continue;
@ -248,10 +248,8 @@ DWORD WINAPI TextHook::Reader(LPVOID hookPtr)
break;
}
if (This->hp.type & USING_UNICODE) dataLen = wcslen((wchar_t*)currentAddress) * 2;
else dataLen = strlen((char*)currentAddress);
if (dataLen > TEXT_BUFFER_SIZE - 2) dataLen = TEXT_BUFFER_SIZE - 2;
memcpy(buffer, (void*)currentAddress, dataLen + 2);
dataLen = min(This->HookStrlen((BYTE*)currentAddress), TEXT_BUFFER_SIZE);
memcpy(buffer, (void*)currentAddress, dataLen);
TextOutput({ GetCurrentProcessId(), This->address, 0, 0 }, buffer, dataLen);
}
}
@ -308,10 +306,7 @@ int TextHook::GetLength(uintptr_t base, uintptr_t in)
break;
//len == -1 then continue to case 0.
case 0:
if (hp.type & USING_UNICODE)
len = wcslen((const wchar_t *)in) << 1;
else
len = strlen((const char *)in);
len = HookStrlen((BYTE*)in);
break;
case 1:
if (hp.type & USING_UNICODE)
@ -328,4 +323,12 @@ int TextHook::GetLength(uintptr_t base, uintptr_t in)
return max(0, len);
}
int TextHook::HookStrlen(BYTE* data)
{
BYTE* orig = data;
for (int nullsRemaining = hp.null_length ? hp.null_length : hp.type & USING_UNICODE ? 2 : 1; nullsRemaining >= 0; ++data)
if (*data == 0) nullsRemaining -= 1;
return data - orig;
}
// EOF

View File

@ -34,6 +34,7 @@ private:
bool InsertReadCode();
void Send(uintptr_t dwDatabase);
int GetLength(uintptr_t base, uintptr_t in); // jichi 12/25/2013: Return 0 if failed
int HookStrlen(BYTE* data);
void RemoveHookCode();
void RemoveReadCode();