mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-24 06:15:35 +08:00
265 lines
11 KiB
C++
265 lines
11 KiB
C++
|
#include"Escude.h"
|
|||
|
#include"embed_util.h"
|
|||
|
/** jichi 7/23/2015 Escude
|
|||
|
* Sample game: Re;Lord <EFBFBD><EFBFBD>ルフォルト<EFBFBD>魔女とぬぁ<EFBFBD>るみ * See: http://capita.tistory.com/m/post/210
|
|||
|
*
|
|||
|
* ENCODEKOR,FORCEFONT(5),HOOK(0x0042CB40,TRANS([[ESP+0x4]+0x20],PTRCHEAT,PTRBACKUP,SAFE),RETNPOS(SOURCE)),FONT(Malgun Gothic,-13)
|
|||
|
*
|
|||
|
* GDI functions: TextOutA, GetTextExtentPoint32A
|
|||
|
* It requires changing function to MS Gothic using configure.exe
|
|||
|
*
|
|||
|
* Text in arg1 + 0x20
|
|||
|
*
|
|||
|
* 0042CB3C CC INT3
|
|||
|
* 0042CB3D CC INT3
|
|||
|
* 0042CB3E CC INT3
|
|||
|
* 0042CB3F CC INT3
|
|||
|
* 0042CB40 56 PUSH ESI
|
|||
|
* 0042CB41 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
|||
|
* 0042CB45 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
|||
|
* 0042CB47 50 PUSH EAX
|
|||
|
* 0042CB48 E8 53FC0A00 CALL .004DC7A0
|
|||
|
* 0042CB4D 8B56 04 MOV EDX,DWORD PTR DS:[ESI+0x4]
|
|||
|
* 0042CB50 83C4 04 ADD ESP,0x4
|
|||
|
* 0042CB53 5E POP ESI
|
|||
|
* 0042CB54 85D2 TEST EDX,EDX
|
|||
|
* 0042CB56 74 7E JE SHORT .0042CBD6
|
|||
|
* 0042CB58 85C0 TEST EAX,EAX
|
|||
|
* 0042CB5A 74 07 JE SHORT .0042CB63
|
|||
|
* 0042CB5C 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CB5E 8B49 04 MOV ECX,DWORD PTR DS:[ECX+0x4]
|
|||
|
* 0042CB61 EB 02 JMP SHORT .0042CB65
|
|||
|
* 0042CB63 33C9 XOR ECX,ECX
|
|||
|
* 0042CB65 890A MOV DWORD PTR DS:[EDX],ECX
|
|||
|
* 0042CB67 85C0 TEST EAX,EAX
|
|||
|
* 0042CB69 74 07 JE SHORT .0042CB72
|
|||
|
* 0042CB6B 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CB6D 8B49 08 MOV ECX,DWORD PTR DS:[ECX+0x8]
|
|||
|
* 0042CB70 EB 02 JMP SHORT .0042CB74
|
|||
|
* 0042CB72 33C9 XOR ECX,ECX
|
|||
|
* 0042CB74 894A 04 MOV DWORD PTR DS:[EDX+0x4],ECX
|
|||
|
* 0042CB77 85C0 TEST EAX,EAX
|
|||
|
* 0042CB79 74 08 JE SHORT .0042CB83
|
|||
|
* 0042CB7B 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CB7D 0FB749 0E MOVZX ECX,WORD PTR DS:[ECX+0xE]
|
|||
|
* 0042CB81 EB 02 JMP SHORT .0042CB85
|
|||
|
* 0042CB83 33C9 XOR ECX,ECX
|
|||
|
* 0042CB85 0FB7C9 MOVZX ECX,CX
|
|||
|
* 0042CB88 894A 08 MOV DWORD PTR DS:[EDX+0x8],ECX
|
|||
|
* 0042CB8B 85C0 TEST EAX,EAX
|
|||
|
* 0042CB8D 74 19 JE SHORT .0042CBA8
|
|||
|
* 0042CB8F 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CB91 8379 04 00 CMP DWORD PTR DS:[ECX+0x4],0x0
|
|||
|
* 0042CB95 76 11 JBE SHORT .0042CBA8
|
|||
|
* 0042CB97 8B49 08 MOV ECX,DWORD PTR DS:[ECX+0x8]
|
|||
|
* 0042CB9A 85C9 TEST ECX,ECX
|
|||
|
* 0042CB9C 76 0A JBE SHORT .0042CBA8
|
|||
|
* 0042CB9E 49 DEC ECX
|
|||
|
* 0042CB9F 0FAF48 0C IMUL ECX,DWORD PTR DS:[EAX+0xC]
|
|||
|
* 0042CBA3 0348 04 ADD ECX,DWORD PTR DS:[EAX+0x4]
|
|||
|
* 0042CBA6 EB 02 JMP SHORT .0042CBAA
|
|||
|
* 0042CBA8 33C9 XOR ECX,ECX
|
|||
|
* 0042CBAA 894A 0C MOV DWORD PTR DS:[EDX+0xC],ECX
|
|||
|
* 0042CBAD 85C0 TEST EAX,EAX
|
|||
|
* 0042CBAF 74 16 JE SHORT .0042CBC7
|
|||
|
* 0042CBB1 8B48 0C MOV ECX,DWORD PTR DS:[EAX+0xC]
|
|||
|
* 0042CBB4 F7D9 NEG ECX
|
|||
|
* 0042CBB6 894A 10 MOV DWORD PTR DS:[EDX+0x10],ECX
|
|||
|
* 0042CBB9 8B00 MOV EAX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CBBB 83C0 28 ADD EAX,0x28
|
|||
|
* 0042CBBE 8942 14 MOV DWORD PTR DS:[EDX+0x14],EAX
|
|||
|
* 0042CBC1 B8 01000000 MOV EAX,0x1
|
|||
|
* 0042CBC6 C3 RETN
|
|||
|
* 0042CBC7 33C9 XOR ECX,ECX
|
|||
|
* 0042CBC9 F7D9 NEG ECX
|
|||
|
* 0042CBCB 894A 10 MOV DWORD PTR DS:[EDX+0x10],ECX
|
|||
|
* 0042CBCE 8B00 MOV EAX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CBD0 83C0 28 ADD EAX,0x28
|
|||
|
* 0042CBD3 8942 14 MOV DWORD PTR DS:[EDX+0x14],EAX
|
|||
|
* 0042CBD6 B8 01000000 MOV EAX,0x1
|
|||
|
* 0042CBDB C3 RETN
|
|||
|
* 0042CBDC CC INT3
|
|||
|
* 0042CBDD CC INT3
|
|||
|
* 0042CBDE CC INT3
|
|||
|
* 0042CBDF CC INT3
|
|||
|
* 0042CBE0 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+0x4]
|
|||
|
* 0042CBE4 8B48 10 MOV ECX,DWORD PTR DS:[EAX+0x10]
|
|||
|
* 0042CBE7 8B50 0C MOV EDX,DWORD PTR DS:[EAX+0xC]
|
|||
|
* 0042CBEA 51 PUSH ECX
|
|||
|
* 0042CBEB 8B48 08 MOV ECX,DWORD PTR DS:[EAX+0x8]
|
|||
|
* 0042CBEE 52 PUSH EDX
|
|||
|
* 0042CBEF 8B50 04 MOV EDX,DWORD PTR DS:[EAX+0x4]
|
|||
|
* 0042CBF2 8B00 MOV EAX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CBF4 51 PUSH ECX
|
|||
|
* 0042CBF5 52 PUSH EDX
|
|||
|
* 0042CBF6 50 PUSH EAX
|
|||
|
* 0042CBF7 E8 E4FD0A00 CALL .004DC9E0
|
|||
|
* 0042CBFC 83C4 14 ADD ESP,0x14
|
|||
|
* 0042CBFF C3 RETN
|
|||
|
* 0042CC00 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+0x4]
|
|||
|
* 0042CC04 8B48 10 MOV ECX,DWORD PTR DS:[EAX+0x10]
|
|||
|
* 0042CC07 8B50 0C MOV EDX,DWORD PTR DS:[EAX+0xC]
|
|||
|
* 0042CC0A 51 PUSH ECX
|
|||
|
* 0042CC0B 8B48 08 MOV ECX,DWORD PTR DS:[EAX+0x8]
|
|||
|
* 0042CC0E 52 PUSH EDX
|
|||
|
* 0042CC0F 8B50 04 MOV EDX,DWORD PTR DS:[EAX+0x4]
|
|||
|
* 0042CC12 8B00 MOV EAX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CC14 51 PUSH ECX
|
|||
|
* 0042CC15 52 PUSH EDX
|
|||
|
* 0042CC16 50 PUSH EAX
|
|||
|
* 0042CC17 E8 C4FF0A00 CALL .004DCBE0
|
|||
|
* 0042CC1C 83C4 14 ADD ESP,0x14
|
|||
|
* 0042CC1F C3 RETN
|
|||
|
* 0042CC20 8B4424 04 MOV EAX,DWORD PTR SS:[ESP+0x4]
|
|||
|
* 0042CC24 8B08 MOV ECX,DWORD PTR DS:[EAX]
|
|||
|
* 0042CC26 894C24 04 MOV DWORD PTR SS:[ESP+0x4],ECX
|
|||
|
* 0042CC2A E9 71FB0A00 JMP .004DC7A0
|
|||
|
* 0042CC2F CC INT3
|
|||
|
* 0042CC30 56 PUSH ESI
|
|||
|
* 0042CC31 8B7424 08 MOV ESI,DWORD PTR SS:[ESP+0x8]
|
|||
|
* 0042CC35 8B06 MOV EAX,DWORD PTR DS:[ESI]
|
|||
|
* 0042CC37 50 PUSH EAX
|
|||
|
* 0042CC38 E8 63FB0A00 CALL .004DC7A0
|
|||
|
* 0042CC3D D946 0C FLD DWORD PTR DS:[ESI+0xC]
|
|||
|
* 0042CC40 D91C24 FSTP DWORD PTR SS:[ESP]
|
|||
|
* 0042CC43 83EC 08 SUB ESP,0x8
|
|||
|
* 0042CC46 D946 08 FLD DWORD PTR DS:[ESI+0x8]
|
|||
|
* 0042CC49 D95C24 04 FSTP DWORD PTR SS:[ESP+0x4]
|
|||
|
* 0042CC4D D946 04 FLD DWORD PTR DS:[ESI+0x4]
|
|||
|
* 0042CC50 D91C24 FSTP DWORD PTR SS:[ESP]
|
|||
|
* 0042CC53 50 PUSH EAX
|
|||
|
* 0042CC54 E8 27680400 CALL .00473480
|
|||
|
* 0042CC59 83C4 10 ADD ESP,0x10
|
|||
|
* 0042CC5C B8 01000000 MOV EAX,0x1
|
|||
|
* 0042CC61 5E POP ESI
|
|||
|
* 0042CC62 C3 RETN
|
|||
|
* 0042CC63 CC INT3
|
|||
|
* 0042CC64 CC INT3
|
|||
|
* 0042CC65 CC INT3
|
|||
|
* 0042CC66 CC INT3
|
|||
|
* 0042CC67 CC INT3
|
|||
|
* 0042CC68 CC INT3
|
|||
|
* 0042CC69 CC INT3 *
|
|||
|
*/
|
|||
|
namespace { // unnamed
|
|||
|
/**
|
|||
|
* Handle new lines and ruby.
|
|||
|
*
|
|||
|
* そ<EFBFBD>日、彼の言葉に耳を傾ける<EFBFBD>ぁ<EFBFBD>かった<EFBFBD> * ザールラント歴丹<EFBFBD>〹<EFBFBD> 二ノ月二十日<r>グローセン州 ヘルフォルト区郊<EFBFBD> *
|
|||
|
* 僁<EFBFBD>な霋<EFBFBD>の後<EFBFBD>r><ruby text='まぶ<EFBFBD>>瞼</ruby>の裏を焼く陽光に気付いた<EFBFBD> *
|
|||
|
* 気<EFBFBD>く重<EFBFBD>ruby text='まぶ<EFBFBD>>瞼</ruby>を開け<EFBFBD><EFBFBD>r>見覚えのある輪郭が瞳に<EFBFBD>り込む<EFBFBD> *
|
|||
|
* そ<EFBFBD>日、彼の言葉に耳を傾ける<EFBFBD>ぁ<EFBFBD>かった。――尊厳を捨てて媚<EFBFBD>る。それが生きることか?――<EFBFBD><EFBFBD>ぁ<EFBFBD>敗北したのた誰しも少年の声を聞かず、蔑み、そして冷笑してぁ<EFBFBD>。安寧の世がぁ<EFBFBD>までも続くと信じてぁ<EFBFBD>から。それでも、私<EFBFBD>――。ザールラント歴丹<EFBFBD>〹<EFBFBD> 二ノ月二十日<r>グローセン州 ヘルフォルト区郊外僅かな霋<EFBFBD>の後<EFBFBD>r><ruby text='まぶ<EFBFBD>>瞼</ruby>の裏を焼く陽光に気付いた。気<EFBFBD>く重<EFBFBD>ruby text='まぶ<EFBFBD>>瞼</ruby>を開け<EFBFBD><EFBFBD>r>見覚えのある輪郭が瞳に<EFBFBD>り込む
|
|||
|
*/
|
|||
|
bool EscudeFilter(LPVOID data, size_t *size, HookParam *)
|
|||
|
{
|
|||
|
auto text = reinterpret_cast<LPSTR>(data);
|
|||
|
auto len = reinterpret_cast<size_t *>(size);
|
|||
|
StringCharReplacer(text, len, "<r>", 3, '\n');
|
|||
|
|
|||
|
if (cpp_strnstr(text, "<ruby", *len)) {
|
|||
|
StringFilter(text, len, "</ruby>", 7);
|
|||
|
StringFilterBetween(text, len, "<ruby", 5, "'>", 2);
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
LPCSTR _escudeltrim(LPCSTR text)
|
|||
|
{
|
|||
|
if (text && *text == '<')
|
|||
|
for (auto p = text; (signed char)*p > 0; p++)
|
|||
|
if (*p == '>')
|
|||
|
return p + 1;
|
|||
|
return text;
|
|||
|
}
|
|||
|
void SpecialHookEscude(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
|||
|
{
|
|||
|
DWORD arg1 = stack->stack[1];
|
|||
|
if (!arg1 || (LONG)arg1 == -1 || ::IsBadWritePtr((LPVOID)arg1, 4)) // this is indispensable
|
|||
|
return;
|
|||
|
LPCSTR text = (LPCSTR)*(DWORD *)(arg1 + 0x20);
|
|||
|
if (!text || ::IsBadWritePtr((LPVOID)text, 1) || !*text) // this is indispensable
|
|||
|
return;
|
|||
|
text = _escudeltrim(text);
|
|||
|
if (!text)
|
|||
|
return;
|
|||
|
*data = (DWORD)text;
|
|||
|
*len = ::strlen(text);
|
|||
|
*split = *(DWORD *)arg1;
|
|||
|
}
|
|||
|
struct HookArgument
|
|||
|
{
|
|||
|
ULONG split;
|
|||
|
//ULONG unknown1[3];
|
|||
|
//LPCSTR text1; // 0x10 only for old games
|
|||
|
ULONG unknown[7];
|
|||
|
LPCSTR text; // 0x20
|
|||
|
|
|||
|
bool isValid() const { return Engine::isAddressWritable(text) && *text; }
|
|||
|
|
|||
|
Engine::TextRole role() const
|
|||
|
{
|
|||
|
if (split >= 0xff)
|
|||
|
return Engine::OtherRole;
|
|||
|
static ULONG maxSplit_ = 0;
|
|||
|
if (split > maxSplit_)
|
|||
|
maxSplit_ = split;
|
|||
|
if (split == maxSplit_)
|
|||
|
return Engine::ScenarioRole;
|
|||
|
return Engine::NameRole; // scenario role is larger than name role
|
|||
|
}
|
|||
|
};
|
|||
|
LPCSTR trimmedText;
|
|||
|
bool hook_before(hook_stack*s,void* data, size_t* len,uintptr_t*role){
|
|||
|
|
|||
|
auto arg = (HookArgument *)s->stack[1];
|
|||
|
if ((long)arg == -1 || !Engine::isAddressWritable(arg) || !arg->isValid())
|
|||
|
return false;
|
|||
|
trimmedText = _escudeltrim(arg->text);
|
|||
|
* role = arg->role();
|
|||
|
strcpy((char*)data,trimmedText);
|
|||
|
*len=strlen(trimmedText);
|
|||
|
return true;
|
|||
|
}
|
|||
|
void hook_after(hook_stack*s,void* data, size_t len){
|
|||
|
static std::string data_;
|
|||
|
data_=std::string((char*)data,len);
|
|||
|
auto arg = (HookArgument *)s->stack[1];
|
|||
|
if(trimmedText!=arg->text)
|
|||
|
data_.insert(0,std::string(arg->text, trimmedText - arg->text));
|
|||
|
arg->text=data_.c_str();
|
|||
|
}
|
|||
|
} // unnamed namespace
|
|||
|
bool InsertEscudeHook()
|
|||
|
{
|
|||
|
const BYTE bytes[] = {
|
|||
|
0x76, 0x0a, // 0042cb9c 76 0a jbe short .0042cba8
|
|||
|
0x49, // 0042cb9e 49 dec ecx
|
|||
|
0x0f,0xaf,0x48, 0x0c // 0042cb9f 0faf48 0c imul ecx,dword ptr ds:[eax+0xc]
|
|||
|
};
|
|||
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
|||
|
//GROWL(addr);
|
|||
|
if (!addr) {
|
|||
|
ConsoleOutput("Escude: pattern not found");
|
|||
|
return false;
|
|||
|
}
|
|||
|
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
|||
|
if (!addr) {
|
|||
|
ConsoleOutput("Escude: enclosing function not found");
|
|||
|
return false;
|
|||
|
}
|
|||
|
HookParam hp;
|
|||
|
hp.address = addr;
|
|||
|
hp.hook_before=hook_before;
|
|||
|
hp.hook_after=hook_after;
|
|||
|
hp.hook_font=F_TextOutA|F_GetTextExtentPoint32A;
|
|||
|
hp.text_fun = SpecialHookEscude;
|
|||
|
hp.filter_fun = EscudeFilter;
|
|||
|
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT|EMBED_ABLE|EMBED_DYNA_SJIS; // NO_CONTEXT as this function is only called by one caller anyway
|
|||
|
hp.newlineseperator=L"<r>";
|
|||
|
ConsoleOutput("INSERT Escude");
|
|||
|
|
|||
|
return NewHook(hp, "Escude");
|
|||
|
}
|
|||
|
|
|||
|
bool Escude::attach_function() {
|
|||
|
return InsertEscudeHook();
|
|||
|
}
|