mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 13:55:36 +08:00
Update CatSystem.cpp
This commit is contained in:
parent
5fa33f740c
commit
067b0c288b
@ -156,10 +156,17 @@ bool InsertCatSystemHook()
|
|||||||
// hp.type =CODEC_ANSI_BE|DATA_INDIRECT|USING_SPLIT|SPLIT_INDIRECT;
|
// hp.type =CODEC_ANSI_BE|DATA_INDIRECT|USING_SPLIT|SPLIT_INDIRECT;
|
||||||
// hp.length_offset=1;
|
// hp.length_offset=1;
|
||||||
|
|
||||||
enum { beg = 0xff6acccc }; // jichi 7/12/2014: beginning of the function
|
enum
|
||||||
enum { addr_offset = 2 }; // skip two leading 0xcc
|
{
|
||||||
|
beg = 0xff6acccc
|
||||||
|
}; // jichi 7/12/2014: beginning of the function
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
addr_offset = 2
|
||||||
|
}; // skip two leading 0xcc
|
||||||
ULONG addr = MemDbg::findCallerAddress((ULONG)::GetTextMetricsA, beg, processStartAddress, processStopAddress);
|
ULONG addr = MemDbg::findCallerAddress((ULONG)::GetTextMetricsA, beg, processStartAddress, processStopAddress);
|
||||||
if (!addr) {
|
if (!addr)
|
||||||
|
{
|
||||||
ConsoleOutput("CatSystem2: pattern not exist");
|
ConsoleOutput("CatSystem2: pattern not exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -170,7 +177,8 @@ bool InsertCatSystemHook()
|
|||||||
|
|
||||||
// jichi 12/23/2014: Modify split for new catsystem
|
// jichi 12/23/2014: Modify split for new catsystem
|
||||||
bool newEngine = Util::CheckFile(L"cs2conf.dll");
|
bool newEngine = Util::CheckFile(L"cs2conf.dll");
|
||||||
if (newEngine) {
|
if (newEngine)
|
||||||
|
{
|
||||||
// hp.text_fun = SpecialHookCatSystem3; // type not needed
|
// hp.text_fun = SpecialHookCatSystem3; // type not needed
|
||||||
// NewHook(hp, "CatSystem3");
|
// NewHook(hp, "CatSystem3");
|
||||||
// ConsoleOutput("INSERT CatSystem3");
|
// ConsoleOutput("INSERT CatSystem3");
|
||||||
@ -178,7 +186,9 @@ bool InsertCatSystemHook()
|
|||||||
hp.split = get_reg(regs::esi);
|
hp.split = get_reg(regs::esi);
|
||||||
ConsoleOutput("INSERT CatSystem3new");
|
ConsoleOutput("INSERT CatSystem3new");
|
||||||
return NewHook(hp, "CatSystem3new");
|
return NewHook(hp, "CatSystem3new");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
||||||
hp.split = get_reg(regs::edx);
|
hp.split = get_reg(regs::edx);
|
||||||
ConsoleOutput("INSERT CatSystem2");
|
ConsoleOutput("INSERT CatSystem2");
|
||||||
@ -205,8 +215,8 @@ bool InsertCatSystem2Hook()
|
|||||||
|
|
||||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||||||
if (!addr) {
|
if (!addr)
|
||||||
ConsoleOutput("CatSystem2new: pattern not found");
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,14 +224,21 @@ bool InsertCatSystem2Hook()
|
|||||||
hp.address = addr;
|
hp.address = addr;
|
||||||
hp.offset = get_reg(regs::eax);
|
hp.offset = get_reg(regs::eax);
|
||||||
hp.type = USING_STRING | CODEC_UTF8;
|
hp.type = USING_STRING | CODEC_UTF8;
|
||||||
ConsoleOutput("INSERT CatSystem2new");
|
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||||
|
{
|
||||||
|
static std::regex rx(R"(\[(.+?)/.+\])");
|
||||||
|
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
|
||||||
|
return write_string_overwrite(data, len, _);
|
||||||
|
};
|
||||||
return NewHook(hp, "CatSystem2new");
|
return NewHook(hp, "CatSystem2new");
|
||||||
}
|
}
|
||||||
namespace { // unnamed
|
namespace
|
||||||
namespace Patch {
|
{ // unnamed
|
||||||
|
namespace Patch
|
||||||
|
{
|
||||||
|
|
||||||
namespace Private {
|
namespace Private
|
||||||
|
{
|
||||||
// String in ecx
|
// String in ecx
|
||||||
// bool __fastcall isLeadByteChar(const char *s, DWORD edx)
|
// bool __fastcall isLeadByteChar(const char *s, DWORD edx)
|
||||||
// bool isLeadByteChar(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
// bool isLeadByteChar(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
||||||
@ -411,13 +428,15 @@ template <typename strT>
|
|||||||
strT ltrim(strT text)
|
strT ltrim(strT text)
|
||||||
{
|
{
|
||||||
strT lastText = nullptr;
|
strT lastText = nullptr;
|
||||||
while (*text && text != lastText) {
|
while (*text && text != lastText)
|
||||||
|
{
|
||||||
lastText = text;
|
lastText = text;
|
||||||
if (text[0] == 0x20)
|
if (text[0] == 0x20)
|
||||||
text++;
|
text++;
|
||||||
if ((UINT8)text[0] == 0x81 && (UINT8)text[1] == 0x40) // skip space \u3000 (0x8140 in sjis)
|
if ((UINT8)text[0] == 0x81 && (UINT8)text[1] == 0x40) // skip space \u3000 (0x8140 in sjis)
|
||||||
text += 2;
|
text += 2;
|
||||||
if (text[0] == '\\') {
|
if (text[0] == '\\')
|
||||||
|
{
|
||||||
text++;
|
text++;
|
||||||
while (::islower(text[0]) || text[0] == '@')
|
while (::islower(text[0]) || text[0] == '@')
|
||||||
text++;
|
text++;
|
||||||
@ -437,8 +456,10 @@ size_t rtrim(LPCSTR text)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ScenarioHook {
|
namespace ScenarioHook
|
||||||
namespace Private {
|
{
|
||||||
|
namespace Private
|
||||||
|
{
|
||||||
|
|
||||||
bool isOtherText(LPCSTR text)
|
bool isOtherText(LPCSTR text)
|
||||||
{
|
{
|
||||||
@ -473,33 +494,48 @@ static bool containsNamePunct_(const char *text)
|
|||||||
{
|
{
|
||||||
static const char *puncts[] = {
|
static const char *puncts[] = {
|
||||||
"\x81\x41" /* 、 */
|
"\x81\x41" /* 、 */
|
||||||
, "\x81\x43" /* , */
|
,
|
||||||
, "\x81\x42" /* 。 */
|
"\x81\x43" /* , */
|
||||||
|
,
|
||||||
|
"\x81\x42" /* 。 */
|
||||||
//, "\x81\x48" /* ? */
|
//, "\x81\x48" /* ? */
|
||||||
, "\x81\x49" /* ! */
|
,
|
||||||
, "\x81\x63" /* … */
|
"\x81\x49" /* ! */
|
||||||
, "\x81\x64" /* ‥ */
|
,
|
||||||
|
"\x81\x63" /* … */
|
||||||
|
,
|
||||||
|
"\x81\x64" /* ‥ */
|
||||||
|
|
||||||
//, "\x81\x79" /* 【 */
|
//, "\x81\x79" /* 【 */
|
||||||
//, "\x81\x7a" /* 】 */
|
//, "\x81\x7a" /* 】 */
|
||||||
, "\x81\x75" /* 「 */
|
,
|
||||||
, "\x81\x76" /* 」 */
|
"\x81\x75" /* 「 */
|
||||||
, "\x81\x77" /* 『 */
|
,
|
||||||
, "\x81\x78" /* 』 */
|
"\x81\x76" /* 」 */
|
||||||
|
,
|
||||||
|
"\x81\x77" /* 『 */
|
||||||
|
,
|
||||||
|
"\x81\x78" /* 』 */
|
||||||
//, "\x81\x69" /* ( */
|
//, "\x81\x69" /* ( */
|
||||||
//, "\x81\x6a" /* ) */
|
//, "\x81\x6a" /* ) */
|
||||||
//, "\x81\x6f" /* { */
|
//, "\x81\x6f" /* { */
|
||||||
//, "\x81\x70" /* } */
|
//, "\x81\x70" /* } */
|
||||||
//, "\x81\x71" /* 〈 */
|
//, "\x81\x71" /* 〈 */
|
||||||
//, "\x81\x72" /* 〉 */
|
//, "\x81\x72" /* 〉 */
|
||||||
, "\x81\x6d" /* [ */
|
,
|
||||||
, "\x81\x6e" /* ] */
|
"\x81\x6d" /* [ */
|
||||||
|
,
|
||||||
|
"\x81\x6e" /* ] */
|
||||||
//, "\x81\x83", /* < */
|
//, "\x81\x83", /* < */
|
||||||
//, "\x81\x84", /* > */
|
//, "\x81\x84", /* > */
|
||||||
, "\x81\x65" /* ‘ */
|
,
|
||||||
, "\x81\x66" /* ’ */
|
"\x81\x65" /* ‘ */
|
||||||
, "\x81\x67" /* “ */
|
,
|
||||||
, "\x81\x68" /* ” */
|
"\x81\x66" /* ’ */
|
||||||
|
,
|
||||||
|
"\x81\x67" /* “ */
|
||||||
|
,
|
||||||
|
"\x81\x68" /* ” */
|
||||||
};
|
};
|
||||||
for (size_t i = 0; i < sizeof(puncts) / sizeof(*puncts); i++)
|
for (size_t i = 0; i < sizeof(puncts) / sizeof(*puncts); i++)
|
||||||
if (::strstr(text, puncts[i]))
|
if (::strstr(text, puncts[i]))
|
||||||
@ -512,12 +548,16 @@ static bool containsNamePunct_(const char *text)
|
|||||||
}
|
}
|
||||||
bool guessIsNameText(const char *text, size_t size)
|
bool guessIsNameText(const char *text, size_t size)
|
||||||
{
|
{
|
||||||
enum { MaximumNameSize = 0x10 };
|
enum
|
||||||
|
{
|
||||||
|
MaximumNameSize = 0x10
|
||||||
|
};
|
||||||
if (!size)
|
if (!size)
|
||||||
size = ::strlen(text);
|
size = ::strlen(text);
|
||||||
return size < MaximumNameSize && !containsNamePunct_(text);
|
return size < MaximumNameSize && !containsNamePunct_(text);
|
||||||
}
|
}
|
||||||
LPSTR trimmedText;size_t trimmedSize;
|
LPSTR trimmedText;
|
||||||
|
size_t trimmedSize;
|
||||||
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
||||||
{
|
{
|
||||||
// static std::unordered_set<uint64_t> hashes_;
|
// static std::unordered_set<uint64_t> hashes_;
|
||||||
@ -556,7 +596,8 @@ static bool containsNamePunct_(const char *text)
|
|||||||
static ULONG minimumGroupId_ = -1; // I assume scenario thread to have minimum groupId
|
static ULONG minimumGroupId_ = -1; // I assume scenario thread to have minimum groupId
|
||||||
|
|
||||||
// if (session_.addText(groupId, Engine::hashCharArray(text))) {
|
// if (session_.addText(groupId, Engine::hashCharArray(text))) {
|
||||||
if (groupId <= minimumGroupId_) {
|
if (groupId <= minimumGroupId_)
|
||||||
|
{
|
||||||
minimumGroupId_ = groupId;
|
minimumGroupId_ = groupId;
|
||||||
|
|
||||||
*role = Engine::ScenarioRole;
|
*role = Engine::ScenarioRole;
|
||||||
@ -567,7 +608,6 @@ static bool containsNamePunct_(const char *text)
|
|||||||
else if (trimmedText == text && !trimmedText[trimmedSize] // no prefix and suffix
|
else if (trimmedText == text && !trimmedText[trimmedSize] // no prefix and suffix
|
||||||
&& guessIsNameText(trimmedText, trimmedSize))
|
&& guessIsNameText(trimmedText, trimmedSize))
|
||||||
*role = Engine::NameRole;
|
*role = Engine::NameRole;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +615,8 @@ static bool containsNamePunct_(const char *text)
|
|||||||
|
|
||||||
return write_string_overwrite(data, len, oldData);
|
return write_string_overwrite(data, len, oldData);
|
||||||
}
|
}
|
||||||
void hookafter(hook_stack*s,void* data, size_t len){
|
void hookafter(hook_stack *s, void *data, size_t len)
|
||||||
|
{
|
||||||
|
|
||||||
auto newData = std::string((char *)data, len);
|
auto newData = std::string((char *)data, len);
|
||||||
if (trimmedText[trimmedSize])
|
if (trimmedText[trimmedSize])
|
||||||
@ -749,7 +790,7 @@ static bool containsNamePunct_(const char *text)
|
|||||||
* 004985CC CC INT3
|
* 004985CC CC INT3
|
||||||
* 004985CD CC INT3
|
* 004985CD CC INT3
|
||||||
*/
|
*/
|
||||||
bool attach(ULONG startAddress, ULONG stopAddress)
|
bool attach(ULONG startAddress, ULONG stopAddress, HookParamType code)
|
||||||
{
|
{
|
||||||
const uint8_t bytes[] = {
|
const uint8_t bytes[] = {
|
||||||
0xe8, XX4, // 004b00dc e8 7f191300 call .005e1a60 ; jichi: hook after here
|
0xe8, XX4, // 004b00dc e8 7f191300 call .005e1a60 ; jichi: hook after here
|
||||||
@ -759,15 +800,20 @@ bool attach(ULONG startAddress, ULONG stopAddress)
|
|||||||
// XX2, XX, 0x00,0x00,0x00 // 004b00ea 8d9b 00000000 lea ebx,dword ptr ds:[ebx]
|
// XX2, XX, 0x00,0x00,0x00 // 004b00ea 8d9b 00000000 lea ebx,dword ptr ds:[ebx]
|
||||||
};
|
};
|
||||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||||
if(addr==0)return false;
|
if (addr == 0)
|
||||||
|
return false;
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
hp.address = addr + 5;
|
hp.address = addr + 5;
|
||||||
hp.type=USING_STRING|EMBED_ABLE|EMBED_DYNA_SJIS;
|
hp.type = USING_STRING | EMBED_ABLE;
|
||||||
|
if (code)
|
||||||
|
hp.type |= code;
|
||||||
|
else
|
||||||
|
hp.type |= EMBED_DYNA_SJIS;
|
||||||
hp.hook_before = Private::hookBefore;
|
hp.hook_before = Private::hookBefore;
|
||||||
hp.hook_after = Private::hookafter;
|
hp.hook_after = Private::hookafter;
|
||||||
hp.hook_font = F_GetGlyphOutlineA;
|
hp.hook_font = F_GetGlyphOutlineA;
|
||||||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||||
|
{
|
||||||
static std::regex rx(R"(\[(.+?)/.+\])");
|
static std::regex rx(R"(\[(.+?)/.+\])");
|
||||||
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
|
auto _ = std::regex_replace(std::string((char *)data, *len), rx, "$1");
|
||||||
return write_string_overwrite(data, len, _);
|
return write_string_overwrite(data, len, _);
|
||||||
@ -775,20 +821,31 @@ bool attach(ULONG startAddress, ULONG stopAddress)
|
|||||||
|
|
||||||
static ULONG p;
|
static ULONG p;
|
||||||
p = Patch::patchEncoding(startAddress, stopAddress);
|
p = Patch::patchEncoding(startAddress, stopAddress);
|
||||||
if(p){
|
if (p)
|
||||||
|
{
|
||||||
hp.type |= EMBED_DYNA_SJIS;
|
hp.type |= EMBED_DYNA_SJIS;
|
||||||
hp.hook_font = F_GetGlyphOutlineA;
|
hp.hook_font = F_GetGlyphOutlineA;
|
||||||
patch_fun=[](){
|
patch_fun = []()
|
||||||
|
{
|
||||||
ReplaceFunction((PVOID *)&p, (PVOID)(ULONG)Patch::Private::isLeadByteChar);
|
ReplaceFunction((PVOID *)&p, (PVOID)(ULONG)Patch::Private::isLeadByteChar);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewHook(hp, "EmbedCS2");
|
return NewHook(hp, "EmbedCS2");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace ScenarioHook
|
} // namespace ScenarioHook
|
||||||
bool CatSystem::attach_function() {
|
bool CatSystem::attach_function()
|
||||||
auto embed=ScenarioHook::attach(processStartAddress,processStopAddress);
|
{
|
||||||
return InsertCatSystemHook()||InsertCatSystem2Hook()||embed;
|
HookParamType code = CODEC_ANSI_LE;
|
||||||
|
auto b1 = InsertCatSystemHook();
|
||||||
|
if (!b1)
|
||||||
|
{
|
||||||
|
b1 |= InsertCatSystem2Hook();
|
||||||
|
code = CODEC_UTF8;
|
||||||
|
}
|
||||||
|
auto embed = ScenarioHook::attach(processStartAddress, processStopAddress, code);
|
||||||
|
|
||||||
|
b1 |= embed;
|
||||||
|
return b1;
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user