diff --git a/Plugin64/byte_pattern.cpp b/Plugin64/byte_pattern.cpp index 074acaa..82258cc 100644 --- a/Plugin64/byte_pattern.cpp +++ b/Plugin64/byte_pattern.cpp @@ -205,6 +205,8 @@ void BytePattern::get_module_ranges(memory_pointer module) PIMAGE_DOS_HEADER dosHeader = module.pointer(); PIMAGE_NT_HEADERS ntHeader = module.pointer(dosHeader->e_lfanew); + + for (int i = 0; i < ntHeader->FileHeader.NumberOfSections; i++) { auto sec = getSection(ntHeader, i); diff --git a/Plugin64/dll_main.cpp b/Plugin64/dll_main.cpp index f625183..ebc6565 100644 --- a/Plugin64/dll_main.cpp +++ b/Plugin64/dll_main.cpp @@ -66,10 +66,10 @@ BOOL APIENTRY DllMain(HMODULE hModule, e |= Date::Init(options); // IME - //e |= Ime::Init(options); + e |= Ime::Init(options); // 入力 - //e |= Input::Init(options); + e |= Input::Init(options); // 文字列順序入れ替え e |= Localization::Init(options); diff --git a/Plugin64/ime.cpp b/Plugin64/ime.cpp index cad5f34..d9ff930 100644 --- a/Plugin64/ime.cpp +++ b/Plugin64/ime.cpp @@ -5,6 +5,7 @@ namespace Ime { extern "C" { void imeProc1(); + void imeProc1V137(); void imeProc2(); void imeProc3(); uintptr_t imeProc1ReturnAddress1; @@ -13,6 +14,7 @@ namespace Ime { uintptr_t imeProc2CallAddress; uintptr_t imeProc2ReturnAddress1; uintptr_t imeProc2ReturnAddress2; + uintptr_t imeProc2ReturnAddress3; uintptr_t rectAddress; uintptr_t imeProc3ReturnAddress; uintptr_t imeProc3CallAddress1; @@ -38,10 +40,25 @@ namespace Ime { DllError e = {}; switch (options.version) { - case v1_36_0_0: - case v1_35_1_0: + case v1_29_3_0: + case v1_29_4_0: + case v1_30_1_0: + case v1_30_2_0: + case v1_30_3_0: + case v1_30_4_0: + case v1_30_5_0: + case v1_31_1_0: + case v1_31_2_0: + case v1_31_3_0: + case v1_31_4_0: + case v1_31_5_0: + case v1_31_6_0: + case v1_32_0_1: + case v1_33_0_0: + case v1_33_3_0: + case v1_34_2_0: // mov edx, r13d - BytePattern::temp_instance().find_pattern("41 8B D5 49 8B CC E8 ? ? ? ? 85 C0 0F 85 F1"); + BytePattern::temp_instance().find_pattern("41 8B D5 49 8B CC E8 ? ? ? ? 85 C0 0F 85"); if (BytePattern::temp_instance().has_size(1, u8"SDL_windowsevents.cの修正")) { uintptr_t address = BytePattern::temp_instance().get_first().address(); @@ -60,25 +77,10 @@ namespace Ime { e.ime.unmatchdImeProc1Injector = true; } break; - case v1_29_3_0: - case v1_29_4_0: - case v1_30_1_0: - case v1_30_2_0: - case v1_30_3_0: - case v1_30_4_0: - case v1_30_5_0: - case v1_31_1_0: - case v1_31_2_0: - case v1_31_3_0: - case v1_31_4_0: - case v1_31_5_0: - case v1_31_6_0: - case v1_32_0_1: - case v1_33_0_0: - case v1_33_3_0: - case v1_34_2_0: + case v1_35_1_0: + case v1_36_0_0: // mov edx, r13d - BytePattern::temp_instance().find_pattern("41 8B D5 49 8B CC E8 ? ? ? ? 85 C0 0F 85"); + BytePattern::temp_instance().find_pattern("41 8B D5 49 8B CC E8 ? ? ? ? 85 C0 0F 85 F1"); if (BytePattern::temp_instance().has_size(1, u8"SDL_windowsevents.cの修正")) { uintptr_t address = BytePattern::temp_instance().get_first().address(); @@ -97,6 +99,27 @@ namespace Ime { e.ime.unmatchdImeProc1Injector = true; } break; + case v1_37_0_0: + // mov edx, edi + BytePattern::temp_instance().find_pattern("8B D7 49 8B CC E8 ? ? ? ? 85 C0 0F 85 5B"); + if (BytePattern::temp_instance().has_size(1, u8"SDL_windowsevents.cの修正")) { + uintptr_t address = BytePattern::temp_instance().get_first().address(); + + // call {sub_xxxxx} + imeProc1CallAddress = Injector::GetBranchDestination(address + 0x5).as_int(); + + // cmp edi, 0FFh + imeProc1ReturnAddress1 = address + 0x12; + + // jz {xxxxx} + imeProc1ReturnAddress2 = address - 0x3A; + + Injector::MakeJMP(address, imeProc1V137, true); + } + else { + e.ime.unmatchdImeProc1Injector = true; + } + break; default: e.ime.versionImeProc1Injector = true; } @@ -112,6 +135,7 @@ namespace Ime { // https://github.com/matanki-saito/EU4dll/issues/19#issuecomment-423940649 DllError imeProc2Injector(RunOptions options) { DllError e = {}; + HMODULE handle = NULL; switch (options.version) { case v1_29_3_0: @@ -188,6 +212,63 @@ namespace Ime { else { e.ime.unmatchdImeProc2Injector = true; } + break; + case v1_37_0_0: + rectAddress = (uintptr_t)▭ + + // SDL_SetTextInputRectの関数を見つける + // add rsp, 20h + handle = GetModuleHandle(NULL); + imeProc2CallAddress = (uintptr_t)GetProcAddress(handle, "SDL_SetTextInputRect"); + + if (imeProc2CallAddress == NULL) { + e.ime.unmatchdImeProc2Injector = true; + } + + // WM_IME_STARTCOMPOSITIONでSDL_SetTextInputRectする + BytePattern::temp_instance().find_pattern("81 EA BC 00 00 00 0F 84 C3 02 00 00"); // sub edx, 0BCh + if (BytePattern::temp_instance().has_size(1, u8"SDL_windowskeyboard.cの修正")) { + uintptr_t address = BytePattern::temp_instance().get_first().address(); + + // jz {loc_xxxxx} + imeProc2ReturnAddress1 = Injector::GetBranchDestination(address + 0x6).as_int(); + + // jnz loc_xxxxx + imeProc2ReturnAddress2 = address + 0xF; + + Injector::MakeJMP(address, imeProc2, true); + } + else { + e.ime.unmatchdImeProc2Injector = true; + } + + // WM_IME_SETCONTEXTで*lParam = 0;をコメントアウトする(nopで埋める) + // mov [r9], r13 + BytePattern::temp_instance().find_pattern("4D 89 29 48 8B 5C 24 50"); + if (BytePattern::temp_instance().has_size(1, u8"SDL_windowskeyboard.cの修正")) { + uintptr_t address = BytePattern::temp_instance().get_first().address(); + Injector::WriteMemory(address, 0x90, true); + Injector::WriteMemory(address + 1, 0x90, true); + Injector::WriteMemory(address + 2, 0x90, true); + } + else { + e.ime.unmatchdImeProc2Injector = true; + } + + // WM_IME_COMPOSITIONのif文のIME_GetCompositionStringとIME_SendInputEventをコメントアウト(jmpさせる) + // mov r8d, 800h + // 二つ目のif文もスキップさせる + // https://github.com/matanki-saito/EU4dll/issues/19#issuecomment-423940364 + BytePattern::temp_instance().find_pattern("41 B8 00 08 00 00 48 89 7C 24 58"); + if (BytePattern::temp_instance().has_size(1, u8"SDL_windowskeyboard.cの修正")) { + // jnb short loc_1417613D8 + uintptr_t address = BytePattern::temp_instance().get_first().address(-2); + Injector::MakeJMP(address, address + 0x9D, true); + } + else { + e.ime.unmatchdImeProc2Injector = true; + } + break; default: e.ime.unmatchdImeProc2Injector = true; @@ -253,6 +334,38 @@ namespace Ime { e.ime.unmatchdImeProc3Injector = true; } break; + case v1_37_0_0: + // 直前の部分でjmpに使う14byteを確保することができなかった。 + // そのためWM_KEYDOWNのコードをすべて移植した + // mov rcx, [rbp+0C0h+hRawInput] + BytePattern::temp_instance().find_pattern("48 8B 8D E8 ? ? ? ? 8B D6 E8 ? ? ? ? 33"); + if (BytePattern::temp_instance().has_size(2, u8"SDL_windowsevents.cの修正")) { + uintptr_t address = BytePattern::temp_instance().get_first().address(); + + // call {sub_xxxxx} / WindowsScanCodeToSDLScanCode + imeProc3CallAddress1 = Injector::GetBranchDestination(address + 0xA).as_int(); + + // call {sub_xxxxx} / SDL_GetKeyboardState + imeProc3CallAddress2 = Injector::GetBranchDestination(address + 0x13).as_int(); + + // call {sub_xxxxx} / ShouldGenerateWindowCloseOnAltF4 + imeProc3CallAddress3 = Injector::GetBranchDestination(address + 0x36).as_int(); + + // call {sub_xxxxx} / SDL_SendWindowEvent + imeProc3CallAddress4 = Injector::GetBranchDestination(address + 0x50).as_int(); + + // call {sub_xxxxx} / SDL_SendKeyboardKey + imeProc3CallAddress5 = Injector::GetBranchDestination(address + 0x61).as_int(); + + // xor edi, edi + imeProc3ReturnAddress = address + 0x66; + + Injector::MakeJMP(address, imeProc3, true); + } + else { + e.ime.unmatchdImeProc3Injector = true; + } + break; default: e.ime.versionImeProc3Injector = true; } @@ -265,7 +378,7 @@ namespace Ime { result |= imeProc1Injector(options); result |= imeProc2Injector(options); - result |= imeProc3Injector(options); + //result |= imeProc3Injector(options); return result; } diff --git a/Plugin64/ime_asm.asm b/Plugin64/ime_asm.asm index a799c0e..a580bf6 100644 --- a/Plugin64/ime_asm.asm +++ b/Plugin64/ime_asm.asm @@ -48,6 +48,24 @@ imeProc1 ENDP ;-------------------------------------------; +imeProc1V137 PROC + mov edx, edi; + mov rcx, r12; + call imeProc1CallAddress; + test eax,eax; + jnz JMP_A; + + push imeProc1ReturnAddress1; + ret; + +JMP_A: + push imeProc1ReturnAddress2; + ret; + +imeProc1V137 ENDP + +;-------------------------------------------; + imeProc2 PROC sub edx, 0BCh; jz JMP_A; diff --git a/Plugin64/input.cpp b/Plugin64/input.cpp index 478c196..7df9cf1 100644 --- a/Plugin64/input.cpp +++ b/Plugin64/input.cpp @@ -7,6 +7,7 @@ namespace Input { extern "C" { void inputProc1(); void inputProc1V130(); + void inputProc1V137(); uintptr_t inputProc1ReturnAddress1; uintptr_t inputProc1ReturnAddress2; uintptr_t inputProc1CallAddress; @@ -93,6 +94,35 @@ namespace Input { e.input.unmatchdInputProc1Injector = true; } + break; + case v1_37_0_0: + // mov eax, dword ptr [rbp+120h+var_18C] + BytePattern::temp_instance().find_pattern("8B 45 BC 32 DB 3C 80 73 05 0F B6 D8 EB 12"); + if (BytePattern::temp_instance().has_size(1, u8"入力した文字をutf8からエスケープ列へ変換する1")) { + uintptr_t address = BytePattern::temp_instance().get_first().address(); + + inputProc1CallAddress = (uintptr_t)utf8ToEscapedStr3; + + // mov rax, [r15] + inputProc1ReturnAddress1 = address + 0x20; + + Injector::MakeJMP(address, inputProc1V137, true); + } + else { + e.input.unmatchdInputProc1Injector = true; + } + + // call qword ptr [rax+18h] + BytePattern::temp_instance().find_pattern("FF 50 18 E9 ? ? ? ? 49 8B 07 45 33 C9"); + if (BytePattern::temp_instance().has_size(1, u8"入力した文字をutf8からエスケープ列へ変換する2")) { + uintptr_t address = BytePattern::temp_instance().get_first().address(); + // jmp loc_{xxxxx} + inputProc1ReturnAddress2 = Injector::GetBranchDestination(address + 0x3).as_int(); + } + else { + e.input.unmatchdInputProc1Injector = true; + } + break; default: e.input.versionInputProc1Injector = true; @@ -149,7 +179,7 @@ namespace Input { DllError result = {}; result |= inputProc1Injector(options); - result |= inputProc2Injector(options); + //result |= inputProc2Injector(options); return result; } diff --git a/Plugin64/input_asm.asm b/Plugin64/input_asm.asm index fc78adc..e616871 100644 --- a/Plugin64/input_asm.asm +++ b/Plugin64/input_asm.asm @@ -193,6 +193,98 @@ inputProc1V130 ENDP ;-------------------------------------------; +inputProc1V137 PROC + ; eaxɂIMEutf8̕nĂ + mov eax, dword ptr [rbp + 60h - 0A4h]; + ; ah0ła-zȂǂ1byteŎ܂镶Ȃ̂ŁAϊ͕KvȂ + cmp ah, 0; + jnz JMP_A; + xor bl, bl; + + ; JMP_X,Yɂ‚Ă̐BMakeJMPŃR[hj󂳂Ă܂߁AۂƃRs[ĂĂB + ; 80hƔrĂ̂UTF8U+0000 c U+007FǂmF邽 + ; https://ja.wikipedia.org/wiki/UTF-8 + cmp al, 80h; + jnb JMP_X; + mov ebx, eax; + jmp JMP_Y; + +JMP_X: + cmp al, 0E0h; + jnb JMP_Y; + movzx ebx, al + movzx ebx, byte ptr [rbp + 60h - 0A4h + 1]; + and al, 3Fh; + shl bl, 6; + or bl, al; + +JMP_Y: + push inputProc1ReturnAddress1; + ret; + +JMP_A: + lea rcx,[rbp + 60h - 0A4h]; + call inputProc1CallAddress; + ; ϊGXP[vς݃eLXgAhXۑB 10 81 82̂悤ɂȂ + mov inputProc2Tmp, rax; + ;JE^ƂĎĝłƂƂ͕̂ۑ + mov inputProc1Tmp,rdi; + xor rdi,rdi; + +JMP_B: + ; ̂܂܃Rs[ + mov rax, [r15] + xor r9d, r9d + mov r8d, [rbp+60h-9Ch] + mov edx, 303h + mov rcx, r15 + call qword ptr [rax+20h] + + ; Pbyteo + mov rbx, inputProc2Tmp; + mov bl, byte ptr [rbx + rdi]; + + ; null`FbN + cmp bl,0; + jz JMP_C; + + ; JEg␳ + mov dword ptr [r14+44h] , 2 + + ; ȉ͂̂܂܃Rs[ + xorps xmm0, xmm0 + mov [rsp+160h-100h], bl + xorps xmm1, xmm1 + mov QWORD PTR [rsp+160h-0ECh], 0 + movdqu [rsp+160h-110h], xmm0 + mov [rsp+160h-0E4h], r12d + movdqu [rsp+160h-0FCh], xmm1 + mov DWORD ptr [rbp+60h-0C0h], 2 + movdqa xmm0, xmmword ptr [inputProc1Var1]; + lea rdx, [rsp+160h-110h] + mov rax, [r14] + mov rcx, r14 + mov [rbp+60h-0C8h], r12d + movdqu [rbp+60h-0E0h+8], xmm0 + mov qword ptr [rbp+60h-0E0h], r12 + mov [rbp+60h-0BCh], r12w + mov byte ptr [rbp+60h-0BAh], 0 + call qword ptr [rax+18h] + + ; 1bytei߂ + inc rdi; + jmp JMP_B; + +JMP_C: + ;߂ + mov rdi, inputProc1Tmp; + + push inputProc1ReturnAddress2; + ret; +inputProc1V137 ENDP + +;-------------------------------------------; + ; Lqword ptr [rax+138h];̊֐i40 57 48 83 EC 20 48 8B 01 48 8B F9 48 8B 90 68 01 00 00j犄o ; rdi+54h : Lbgʒu ; rdi+40h : 񒷂