mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-27 15:54:03 +08:00
5ed44c223f
Update Nitroplus2.cpp Update CMakeLists.txt
543 lines
24 KiB
C++
543 lines
24 KiB
C++
#include "Nitroplus2.h"
|
||
|
||
/**
|
||
* Jazzinghen 23/05/2020: Add TokyoNecro hook
|
||
*
|
||
* [Nitroplus] 東京Necro 1.01 - Text boxes hook
|
||
*
|
||
* Hook code: HS-14*8@B5420:TokyoNecro.exe
|
||
*
|
||
* Debug method:
|
||
* Found memory location where the text was written, then used hardware break on write.
|
||
* After that found the function that writes the text in, found that the memory pointed
|
||
* contains more than just the text. Followed the call stack "upwards" until a function
|
||
* that handles only the text copy is found.
|
||
*
|
||
* Disassembled code:
|
||
* TokyoNecro.exe+B5420 - 55 - push ebp ; place to hook
|
||
* TokyoNecro.exe+B5421 - 8B EC - mov ebp,esp
|
||
* TokyoNecro.exe+B5423 - 6A FF - push -01
|
||
* TokyoNecro.exe+B5425 - 68 E8613000 - push TokyoNecro.exe+1961E8
|
||
* TokyoNecro.exe+B542A - 64 A1 00000000 - mov eax,fs:[00000000]
|
||
* TokyoNecro.exe+B5430 - 50 - push eax
|
||
* TokyoNecro.exe+B5431 - 64 89 25 00000000 - mov fs:[00000000],esp
|
||
* TokyoNecro.exe+B5438 - 83 EC 1C - sub esp,1C
|
||
* TokyoNecro.exe+B543B - 8B 55 08 - mov edx,[ebp+08]
|
||
* TokyoNecro.exe+B543E - 53 - push ebx
|
||
* TokyoNecro.exe+B543F - 56 - push esi
|
||
* TokyoNecro.exe+B5440 - 8B C2 - mov eax,edx
|
||
* TokyoNecro.exe+B5442 - 57 - push edi
|
||
* TokyoNecro.exe+B5443 - 8B D9 - mov ebx,ecx
|
||
* TokyoNecro.exe+B5445 - C7 45 EC 0F000000 - mov [ebp-14],0000000F
|
||
* TokyoNecro.exe+B544C - C7 45 E8 00000000 - mov [ebp-18],00000000
|
||
* TokyoNecro.exe+B5453 - C6 45 D8 00 - mov byte ptr [ebp-28],00
|
||
* TokyoNecro.exe+B5457 - 8D 70 01 - lea esi,[eax+01]
|
||
* TokyoNecro.exe+B545A - 8D 9B 00000000 - lea ebx,[ebx+00000000]
|
||
* TokyoNecro.exe+B5460 - 8A 08 - mov cl,[eax]
|
||
* TokyoNecro.exe+B5462 - 40 - inc eax
|
||
* TokyoNecro.exe+B5463 - 84 C9 - test cl,cl
|
||
* TokyoNecro.exe+B5465 - 75 F9 - jne TokyoNecro.exe+B5460
|
||
* TokyoNecro.exe+B5467 - 2B C6 - sub eax,esi
|
||
* TokyoNecro.exe+B5469 - 52 - push edx
|
||
* TokyoNecro.exe+B546A - 8B F8 - mov edi,eax ▷ Search
|
||
* TokyoNecro.exe+B546C - 8D 75 D8 - lea esi,[ebp-28] |
|
||
* TokyoNecro.exe+B546F - E8 6CE1F4FF - call TokyoNecro.exe+35E0 ▷
|
||
*
|
||
* Notes:
|
||
*
|
||
* There's more data above due to the fact that the start of the function is very
|
||
* common and it was hooking a wrong function.
|
||
*
|
||
* The text is contained into the memory location at [esp+04] when hooking the
|
||
* code at TokyoNecro.exe+B5420
|
||
*
|
||
* If the game is hooked right at the main menu it will also catch the real time clock
|
||
* rendered there.
|
||
*/
|
||
|
||
namespace
|
||
{
|
||
|
||
const BYTE funcSig[] = {0x55, 0x8b, 0xec};
|
||
|
||
bool TextHook()
|
||
{
|
||
|
||
const BYTE bytecodes[] = {
|
||
0x8B, 0xF8, // 8B F8 - mov edi,eax
|
||
0x8D, 0x75, 0xD8, // 8D 75 D8 - lea esi,[ebp-28]
|
||
0xE8, 0x6C, 0xE1, 0xF4, 0xFF, // E8 6CE1F4FF - call TokyoNecro.exe+35E0
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytecodes, sizeof(bytecodes), processStartAddress, processStopAddress);
|
||
if (addr == 0)
|
||
{
|
||
ConsoleOutput("TokyoNecro: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
// Look for the start of the function
|
||
const ULONG function_start = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (memcmp((void *)function_start, funcSig, sizeof(funcSig)) != 0)
|
||
{
|
||
ConsoleOutput("TokyoNecro: function start not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = function_start;
|
||
// The memory address is held at [ebp+08] at TokyoNecro.exe+B543B, meaning that at
|
||
// the start of the function it's right above the stack pointer. Since there's no
|
||
// way to do an operation on the value of a register BEFORE dereferencing (e.g.
|
||
// (void*)(esp+4) instead of ((void*)esp)+4) we have to go up the stack instead of
|
||
// using the data in the registers
|
||
hp.offset = get_stack(1);
|
||
hp.type = USING_STRING;
|
||
ConsoleOutput("INSERT TokyoNecroText");
|
||
return NewHook(hp, "TokyoNecroText");
|
||
}
|
||
|
||
/**
|
||
* [Nitroplus] 東京Necro 1.01 - Database/Encyclopedia hook
|
||
*
|
||
* Hook code: HS4*@B5380:tokyonecro.exe
|
||
*
|
||
* TokyoNecro.exe+B5380 - 55 - push ebp ; Location to hook
|
||
* TokyoNecro.exe+B5381 - 8B EC - mov ebp,esp
|
||
* TokyoNecro.exe+B5383 - 6A FF - push -01
|
||
* TokyoNecro.exe+B5385 - 68 E8618E00 - push TokyoNecro.exe+1961E8
|
||
* TokyoNecro.exe+B538A - 64 A1 00000000 - mov eax,fs:[00000000]
|
||
* TokyoNecro.exe+B5390 - 50 - push eax
|
||
* TokyoNecro.exe+B5391 - 64 89 25 00000000 - mov fs:[00000000],esp
|
||
* TokyoNecro.exe+B5398 - 83 EC 1C - sub esp,1C
|
||
* TokyoNecro.exe+B539B - 8B 55 08 - mov edx,[ebp+08]
|
||
* TokyoNecro.exe+B539E - 53 - push ebx
|
||
* TokyoNecro.exe+B539F - 56 - push esi
|
||
* TokyoNecro.exe+B53A0 - 8B C2 - mov eax,edx
|
||
* TokyoNecro.exe+B53A2 - 57 - push edi
|
||
* TokyoNecro.exe+B53A3 - 8B D9 - mov ebx,ecx
|
||
* TokyoNecro.exe+B53A5 - C7 45 EC 0F000000 - mov [ebp-14],0000000F
|
||
* TokyoNecro.exe+B53AC - C7 45 E8 00000000 - mov [ebp-18],00000000
|
||
* TokyoNecro.exe+B53B3 - C6 45 D8 00 - mov byte ptr [ebp-28],00
|
||
* TokyoNecro.exe+B53B7 - 8D 70 01 - lea esi,[eax+01]
|
||
* TokyoNecro.exe+B53BA - 8D 9B 00000000 - lea ebx,[ebx+00000000]
|
||
* TokyoNecro.exe+B53C0 - 8A 08 - mov cl,[eax]
|
||
* TokyoNecro.exe+B53C2 - 40 - inc eax
|
||
* TokyoNecro.exe+B53C3 - 84 C9 - test cl,cl
|
||
* TokyoNecro.exe+B53C5 - 75 F9 - jne TokyoNecro.exe+B53C0
|
||
* TokyoNecro.exe+B53C7 - 2B C6 - sub eax,esi
|
||
* TokyoNecro.exe+B53C9 - 52 - push edx
|
||
* TokyoNecro.exe+B53CA - 8B F8 - mov edi,eax ▷ Search
|
||
* TokyoNecro.exe+B53CC - 8D 75 D8 - lea esi,[ebp-28] |
|
||
* TokyoNecro.exe+B53CF - E8 0CE2F4FF - call TokyoNecro.exe+35E0 ▷
|
||
*
|
||
*
|
||
*/
|
||
|
||
bool DatabaseHook()
|
||
{
|
||
const BYTE bytecodes[] = {
|
||
0x8B, 0xF8, // 8B F8 - mov edi,eax
|
||
0x8D, 0x75, 0xD8, // 8D 75 D8 - lea esi,[ebp-28]
|
||
0xE8, 0x0C, 0xE2, 0xF4, 0xFF, // E8 6CE1F4FF - call TokyoNecro.exe+35E0
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytecodes, sizeof(bytecodes), processStartAddress, processStopAddress);
|
||
if (addr == 0)
|
||
{
|
||
ConsoleOutput("TokyoNecro: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
// Look for the start of the function
|
||
const ULONG function_start = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (memcmp((void *)function_start, funcSig, sizeof(funcSig)) != 0)
|
||
{
|
||
ConsoleOutput("TokyoNecro: function start not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = function_start;
|
||
hp.offset = get_stack(1);
|
||
hp.type = USING_STRING;
|
||
return NewHook(hp, "TokyoNecroDatabase");
|
||
ConsoleOutput("INSERT TokyoNecroDatabase");
|
||
}
|
||
|
||
bool InsertTokyoNecroHook()
|
||
{
|
||
DatabaseHook();
|
||
return TextHook();
|
||
}
|
||
} // namespace TokyoNecro
|
||
|
||
bool InsertNitroPlusHook()
|
||
{
|
||
// 機神咆吼デモンベイン
|
||
// みにくいモジカの子
|
||
BYTE bytes[] = {
|
||
0x55,
|
||
0x8b, 0xec,
|
||
0xff, 0x75, 0x10,
|
||
0xff, 0x75, 0x0c,
|
||
0xe8, XX, XX, 0xff, 0xff};
|
||
BYTE bytes2[] = {
|
||
0x55,
|
||
0x8b, 0xec,
|
||
0xff, 0x75, 0x0c,
|
||
0xe8, XX, XX, 0xff, 0xff};
|
||
auto addr1 = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
auto addr2 = MemDbg::findBytes(bytes2, sizeof(bytes2), processStartAddress, processStopAddress);
|
||
ConsoleOutput("NitroPlus %p", addr1);
|
||
ConsoleOutput("NitroPlus %p", addr2);
|
||
if (addr1 == 0 && addr2 == 0)
|
||
return false;
|
||
auto succ = false;
|
||
if (addr1)
|
||
{
|
||
HookParam hp;
|
||
hp.address = addr1;
|
||
hp.offset = get_stack(2);
|
||
hp.type = CODEC_UTF16;
|
||
succ |= NewHook(hp, "NitroPlus");
|
||
}
|
||
if (addr2)
|
||
{
|
||
HookParam hp;
|
||
hp.address = addr2;
|
||
hp.offset = get_stack(2);
|
||
hp.type = CODEC_UTF16;
|
||
succ |= NewHook(hp, "NitroPlus");
|
||
}
|
||
|
||
return succ;
|
||
}
|
||
namespace
|
||
{ // unnamed
|
||
namespace ScenarioHook
|
||
{
|
||
|
||
/**
|
||
* Sample game: 凍京NECRO 体験版
|
||
* Debug step:
|
||
* 1. find the text location that does not change
|
||
* 2. Use Ollydbg to find where the text is modified
|
||
* 3. Backtrack the stack to find proper caller.
|
||
*
|
||
* Issues: It cannot extract character name.
|
||
*
|
||
* File pattern: *.npk for new "Nitroplus" (p is lower case)
|
||
* btw, *.npa for old "Nitroplus"
|
||
*
|
||
* 00CF0E6A CC INT3
|
||
* 00CF0E6B CC INT3
|
||
* 00CF0E6C CC INT3
|
||
* 00CF0E6D CC INT3
|
||
* 00CF0E6E CC INT3
|
||
* 00CF0E6F CC INT3
|
||
* 00CF0E70 55 PUSH EBP ; jichi: text in arg1
|
||
* 00CF0E71 8BEC MOV EBP,ESP
|
||
* 00CF0E73 6A FF PUSH -0x1
|
||
* 00CF0E75 68 184BDC00 PUSH .00DC4B18
|
||
* 00CF0E7A 64:A1 00000000 MOV EAX,DWORD PTR FS:[0]
|
||
* 00CF0E80 50 PUSH EAX
|
||
* 00CF0E81 64:8925 00000000 MOV DWORD PTR FS:[0],ESP
|
||
* 00CF0E88 83EC 1C SUB ESP,0x1C
|
||
* 00CF0E8B 8B55 08 MOV EDX,DWORD PTR SS:[EBP+0x8]
|
||
* 00CF0E8E 53 PUSH EBX
|
||
* 00CF0E8F 56 PUSH ESI
|
||
* 00CF0E90 8BC2 MOV EAX,EDX
|
||
* 00CF0E92 57 PUSH EDI
|
||
* 00CF0E93 8BD9 MOV EBX,ECX
|
||
* 00CF0E95 C745 EC 0F000000 MOV DWORD PTR SS:[EBP-0x14],0xF
|
||
* 00CF0E9C C745 E8 00000000 MOV DWORD PTR SS:[EBP-0x18],0x0
|
||
* 00CF0EA3 C645 D8 00 MOV BYTE PTR SS:[EBP-0x28],0x0
|
||
* 00CF0EA7 8D70 01 LEA ESI,DWORD PTR DS:[EAX+0x1]
|
||
* 00CF0EAA 8D9B 00000000 LEA EBX,DWORD PTR DS:[EBX]
|
||
* 00CF0EB0 8A08 MOV CL,BYTE PTR DS:[EAX]
|
||
* 00CF0EB2 40 INC EAX
|
||
* 00CF0EB3 84C9 TEST CL,CL
|
||
* 00CF0EB5 ^75 F9 JNZ SHORT .00CF0EB0
|
||
* 00CF0EB7 2BC6 SUB EAX,ESI
|
||
* 00CF0EB9 52 PUSH EDX
|
||
* 00CF0EBA 8BF8 MOV EDI,EAX
|
||
* 00CF0EBC 8D75 D8 LEA ESI,DWORD PTR SS:[EBP-0x28]
|
||
* 00CF0EBF E8 0C0DF5FF CALL .00C41BD0
|
||
* 00CF0EC4 C745 FC 00000000 MOV DWORD PTR SS:[EBP-0x4],0x0 ; jichi: pattern start
|
||
* 00CF0ECB 8B8B 84030000 MOV ECX,DWORD PTR DS:[EBX+0x384]
|
||
* 00CF0ED1 8B01 MOV EAX,DWORD PTR DS:[ECX]
|
||
* 00CF0ED3 8B40 60 MOV EAX,DWORD PTR DS:[EAX+0x60]
|
||
* 00CF0ED6 8BD6 MOV EDX,ESI
|
||
* 00CF0ED8 52 PUSH EDX
|
||
* 00CF0ED9 FFD0 CALL EAX ;jichi: called here .00CAEF00
|
||
* 00CF0EDB 837D EC 10 CMP DWORD PTR SS:[EBP-0x14],0x10
|
||
* 00CF0EDF 5F POP EDI
|
||
* 00CF0EE0 5E POP ESI
|
||
* 00CF0EE1 5B POP EBX
|
||
* 00CF0EE2 72 0C JB SHORT .00CF0EF0
|
||
* 00CF0EE4 8B4D D8 MOV ECX,DWORD PTR SS:[EBP-0x28]
|
||
* 00CF0EE7 51 PUSH ECX
|
||
* 00CF0EE8 E8 ED060B00 CALL .00DA15DA
|
||
* 00CF0EED 83C4 04 ADD ESP,0x4
|
||
* 00CF0EF0 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-0xC]
|
||
* 00CF0EF3 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
|
||
* 00CF0EFA 8BE5 MOV ESP,EBP
|
||
* 00CF0EFC 5D POP EBP
|
||
* 00CF0EFD C2 0400 RETN 0x4
|
||
* 00CF0F00 8B89 84030000 MOV ECX,DWORD PTR DS:[ECX+0x384]
|
||
* 00CF0F06 8B01 MOV EAX,DWORD PTR DS:[ECX]
|
||
* 00CF0F08 8B50 64 MOV EDX,DWORD PTR DS:[EAX+0x64]
|
||
* 00CF0F0B FFE2 JMP EDX
|
||
* 00CF0F0D CC INT3
|
||
* 00CF0F0E CC INT3
|
||
* 00CF0F0F CC INT3
|
||
* 00CF0F10 55 PUSH EBP
|
||
* 00CF0F11 8BEC MOV EBP,ESP
|
||
* 00CF0F13 83EC 10 SUB ESP,0x10
|
||
* 00CF0F16 8B89 84030000 MOV ECX,DWORD PTR DS:[ECX+0x384]
|
||
* 00CF0F1C 8B01 MOV EAX,DWORD PTR DS:[ECX]
|
||
* 00CF0F1E 8B80 A0000000 MOV EAX,DWORD PTR DS:[EAX+0xA0]
|
||
* 00CF0F24 8D55 F0 LEA EDX,DWORD PTR SS:[EBP-0x10]
|
||
* 00CF0F27 52 PUSH EDX
|
||
* 00CF0F28 FFD0 CALL EAX
|
||
* 00CF0F2A 8D4D F8 LEA ECX,DWORD PTR SS:[EBP-0x8]
|
||
* 00CF0F2D FF15 7482DC00 CALL DWORD PTR DS:[0xDC8274] ; _1nput1_.1007E880
|
||
* 00CF0F33 66:0F6E45 F0 MOVD MM0,DWORD PTR SS:[EBP-0x10]
|
||
* 00CF0F38 66:0F6E4D F4 MOVD MM1,DWORD PTR SS:[EBP-0xC]
|
||
* 00CF0F3D 8B0D E046E000 MOV ECX,DWORD PTR DS:[0xE046E0]
|
||
* 00CF0F43 0F5B ??? ; Unknown command
|
||
* 00CF0F45 C0F3 0F SAL BL,0xF
|
||
* 00CF0F48 1145 F8 ADC DWORD PTR SS:[EBP-0x8],EAX
|
||
* 00CF0F4B 0F5B ??? ; Unknown command
|
||
* 00CF0F4D C9 LEAVE
|
||
* 00CF0F4E F3:0F114D FC MOVSS DWORD PTR SS:[EBP-0x4],XMM1
|
||
* 00CF0F53 8B41 54 MOV EAX,DWORD PTR DS:[ECX+0x54]
|
||
* 00CF0F56 F3:0F1180 500100>MOVSS DWORD PTR DS:[EAX+0x150],XMM0
|
||
* 00CF0F5E F3:0F1045 FC MOVSS XMM0,DWORD PTR SS:[EBP-0x4]
|
||
* 00CF0F63 F3:0F1180 540100>MOVSS DWORD PTR DS:[EAX+0x154],XMM0
|
||
* 00CF0F6B 0F57C0 XORPS XMM0,XMM0
|
||
* 00CF0F6E F3:0F1180 580100>MOVSS DWORD PTR DS:[EAX+0x158],XMM0
|
||
* 00CF0F76 F3:0F1180 5C0100>MOVSS DWORD PTR DS:[EAX+0x15C],XMM0
|
||
* 00CF0F7E 8BE5 MOV ESP,EBP
|
||
* 00CF0F80 5D POP EBP
|
||
* 00CF0F81 C3 RETN
|
||
* 00CF0F82 CC INT3
|
||
* 00CF0F83 CC INT3
|
||
* 00CF0F84 CC INT3
|
||
* 00CF0F85 CC INT3
|
||
* 00CF0F86 CC INT3
|
||
* 00CF0F87 CC INT3
|
||
* 00CF0F88 CC INT3
|
||
* 00CF0F89 CC INT3
|
||
* 00CF0F8A CC INT3
|
||
* 00CF0F8B CC INT3
|
||
* 00CF0F8C CC INT3
|
||
*
|
||
* If the function does not work, here's the common function that performing strcpy
|
||
* 00DA8E8A CC INT3
|
||
* 00DA8E8B CC INT3
|
||
* 00DA8E8C CC INT3
|
||
* 00DA8E8D CC INT3
|
||
* 00DA8E8E CC INT3
|
||
* 00DA8E8F CC INT3
|
||
* 00DA8E90 55 PUSH EBP
|
||
* 00DA8E91 8BEC MOV EBP,ESP
|
||
* 00DA8E93 57 PUSH EDI
|
||
* 00DA8E94 56 PUSH ESI
|
||
* 00DA8E95 8B75 0C MOV ESI,DWORD PTR SS:[EBP+0xC]
|
||
* 00DA8E98 8B4D 10 MOV ECX,DWORD PTR SS:[EBP+0x10]
|
||
* 00DA8E9B 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+0x8]
|
||
* 00DA8E9E 8BC1 MOV EAX,ECX
|
||
* 00DA8EA0 8BD1 MOV EDX,ECX
|
||
* 00DA8EA2 03C6 ADD EAX,ESI
|
||
* 00DA8EA4 3BFE CMP EDI,ESI
|
||
* 00DA8EA6 76 08 JBE SHORT .00DA8EB0
|
||
* 00DA8EA8 3BF8 CMP EDI,EAX
|
||
* 00DA8EAA 0F82 A0010000 JB .00DA9050
|
||
* 00DA8EB0 81F9 80000000 CMP ECX,0x80
|
||
* 00DA8EB6 72 1C JB SHORT .00DA8ED4
|
||
* 00DA8EB8 833D D470E000 00 CMP DWORD PTR DS:[0xE070D4],0x0
|
||
* 00DA8EBF 74 13 JE SHORT .00DA8ED4
|
||
* 00DA8EC1 57 PUSH EDI
|
||
* 00DA8EC2 56 PUSH ESI
|
||
* 00DA8EC3 83E7 0F AND EDI,0xF
|
||
* 00DA8EC6 83E6 0F AND ESI,0xF
|
||
* 00DA8EC9 3BFE CMP EDI,ESI
|
||
* 00DA8ECB 5E POP ESI
|
||
* 00DA8ECC 5F POP EDI
|
||
* 00DA8ECD 75 05 JNZ SHORT .00DA8ED4
|
||
* 00DA8ECF ^E9 0E9FFFFF JMP .00DA2DE2
|
||
* 00DA8ED4 F7C7 03000000 TEST EDI,0x3
|
||
* 00DA8EDA 75 14 JNZ SHORT .00DA8EF0
|
||
* 00DA8EDC C1E9 02 SHR ECX,0x2
|
||
* 00DA8EDF 83E2 03 AND EDX,0x3
|
||
* 00DA8EE2 83F9 08 CMP ECX,0x8
|
||
* 00DA8EE5 72 29 JB SHORT .00DA8F10
|
||
* 00DA8EE7 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI] ; jichi: modified here
|
||
* 00DA8EE9 FF2495 0090DA00 JMP DWORD PTR DS:[EDX*4+0xDA9000]
|
||
* 00DA8EF0 8BC7 MOV EAX,EDI
|
||
* 00DA8EF2 BA 03000000 MOV EDX,0x3
|
||
* 00DA8EF7 83E9 04 SUB ECX,0x4
|
||
* 00DA8EFA 72 0C JB SHORT .00DA8F08
|
||
* 00DA8EFC 83E0 03 AND EAX,0x3
|
||
* 00DA8EFF 03C8 ADD ECX,EAX
|
||
* 00DA8F01 FF2485 148FDA00 JMP DWORD PTR DS:[EAX*4+0xDA8F14]
|
||
* 00DA8F08 FF248D 1090DA00 JMP DWORD PTR DS:[ECX*4+0xDA9010]
|
||
* 00DA8F0F 90 NOP
|
||
* 00DA8F10 FF248D 948FDA00 JMP DWORD PTR DS:[ECX*4+0xDA8F94]
|
||
* 00DA8F17 90 NOP
|
||
* 00DA8F18 24 8F AND AL,0x8F
|
||
* 00DA8F1A DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8F1C 50 PUSH EAX
|
||
* 00DA8F1D 8F ??? ; Unknown command
|
||
* 00DA8F1E DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8F20 ^74 8F JE SHORT .00DA8EB1
|
||
* 00DA8F22 DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8F24 23D1 AND EDX,ECX
|
||
* 00DA8F26 8A06 MOV AL,BYTE PTR DS:[ESI]
|
||
* 00DA8F28 8807 MOV BYTE PTR DS:[EDI],AL
|
||
* 00DA8F2A 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1]
|
||
* 00DA8F2D 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL
|
||
* 00DA8F30 8A46 02 MOV AL,BYTE PTR DS:[ESI+0x2]
|
||
* 00DA8F33 C1E9 02 SHR ECX,0x2
|
||
* 00DA8F36 8847 02 MOV BYTE PTR DS:[EDI+0x2],AL
|
||
* 00DA8F39 83C6 03 ADD ESI,0x3
|
||
* 00DA8F3C 83C7 03 ADD EDI,0x3
|
||
* 00DA8F3F 83F9 08 CMP ECX,0x8
|
||
* 00DA8F42 ^72 CC JB SHORT .00DA8F10
|
||
* 00DA8F44 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
|
||
* 00DA8F46 FF2495 0090DA00 JMP DWORD PTR DS:[EDX*4+0xDA9000]
|
||
* 00DA8F4D 8D49 00 LEA ECX,DWORD PTR DS:[ECX]
|
||
* 00DA8F50 23D1 AND EDX,ECX
|
||
* 00DA8F52 8A06 MOV AL,BYTE PTR DS:[ESI]
|
||
* 00DA8F54 8807 MOV BYTE PTR DS:[EDI],AL
|
||
* 00DA8F56 8A46 01 MOV AL,BYTE PTR DS:[ESI+0x1]
|
||
* 00DA8F59 C1E9 02 SHR ECX,0x2
|
||
* 00DA8F5C 8847 01 MOV BYTE PTR DS:[EDI+0x1],AL
|
||
* 00DA8F5F 83C6 02 ADD ESI,0x2
|
||
* 00DA8F62 83C7 02 ADD EDI,0x2
|
||
* 00DA8F65 83F9 08 CMP ECX,0x8
|
||
* 00DA8F68 ^72 A6 JB SHORT .00DA8F10
|
||
* 00DA8F6A F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
|
||
* 00DA8F6C FF2495 0090DA00 JMP DWORD PTR DS:[EDX*4+0xDA9000]
|
||
* 00DA8F73 90 NOP
|
||
* 00DA8F74 23D1 AND EDX,ECX
|
||
* 00DA8F76 8A06 MOV AL,BYTE PTR DS:[ESI]
|
||
* 00DA8F78 8807 MOV BYTE PTR DS:[EDI],AL
|
||
* 00DA8F7A 83C6 01 ADD ESI,0x1
|
||
* 00DA8F7D C1E9 02 SHR ECX,0x2
|
||
* 00DA8F80 83C7 01 ADD EDI,0x1
|
||
* 00DA8F83 83F9 08 CMP ECX,0x8
|
||
* 00DA8F86 ^72 88 JB SHORT .00DA8F10
|
||
* 00DA8F88 F3:A5 REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
|
||
* 00DA8F8A FF2495 0090DA00 JMP DWORD PTR DS:[EDX*4+0xDA9000]
|
||
* 00DA8F91 8D49 00 LEA ECX,DWORD PTR DS:[ECX]
|
||
* 00DA8F94 F7 ??? ; Unknown command
|
||
* 00DA8F95 8F ??? ; Unknown command
|
||
* 00DA8F96 DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8F98 E4 8F IN AL,0x8F ; I/O command
|
||
* 00DA8F9A DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8F9C DC8F DA00D48F FMUL QWORD PTR DS:[EDI+0x8FD400DA]
|
||
* 00DA8FA2 DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8FA4 CC INT3
|
||
* 00DA8FA5 8F ??? ; Unknown command
|
||
* 00DA8FA6 DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8FA8 C48F DA00BC8F LES ECX,FWORD PTR DS:[EDI+0x8FBC00DA] ; Modification of segment register
|
||
* 00DA8FAE DA00 FIADD DWORD PTR DS:[EAX]
|
||
* 00DA8FB0 B4 8F MOV AH,0x8F
|
||
*
|
||
*/
|
||
bool attach(ULONG startAddress, ULONG stopAddress) // attach scenario
|
||
{
|
||
const uint8_t bytes[] = {
|
||
0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00, // 00cf0ec4 c745 fc 00000000 mov dword ptr ss:[ebp-0x4],0x0 ; jichi: pattern start
|
||
0x8b, 0x8b, 0x84, 0x03, 0x00, 0x00, // 00cf0ecb 8b8b 84030000 mov ecx,dword ptr ds:[ebx+0x384]
|
||
0x8b, 0x01, // 00cf0ed1 8b01 mov eax,dword ptr ds:[ecx]
|
||
0x8b, 0x40, 0x60, // 00cf0ed3 8b40 60 mov eax,dword ptr ds:[eax+0x60]
|
||
0x8b, 0xd6, // 00cf0ed6 8bd6 mov edx,esi
|
||
0x52, // 00cf0ed8 52 push edx
|
||
0xff, 0xd0 // 00cf0ed9 ffd0 call eax ;jichi: called here .00caef00
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||
if (!addr)
|
||
return false;
|
||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (!addr)
|
||
return false;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset = get_stack(1);
|
||
hp.type = USING_STRING | EMBED_ABLE | EMBED_BEFORE_SIMPLE | EMBED_AFTER_NEW | EMBED_DYNA_SJIS;
|
||
hp.filter_fun = all_ascii_Filter;
|
||
return NewHook(hp, "EmbedNitroplus");
|
||
}
|
||
|
||
} // namespace ScenarioHook
|
||
} // unnamed namespace
|
||
|
||
namespace
|
||
{
|
||
bool sayanouta()
|
||
{
|
||
// 沙耶の唄 The Best 10対応DL版
|
||
char tolang[] = "string too long";
|
||
auto tolangaddr = MemDbg::findBytes(tolang, sizeof(tolang), processStartAddress, processStopAddress);
|
||
auto lower = processStartAddress;
|
||
auto succ = false;
|
||
while (true)
|
||
{
|
||
auto addrX = MemDbg::findPushAddress(tolangaddr, lower, processStopAddress);
|
||
if (addrX == 0)
|
||
break;
|
||
lower = addrX + 0x100;
|
||
// clang-format off
|
||
|
||
const uint8_t bytes[] = {
|
||
0x55, 0x8b, 0xec,
|
||
0x53, 0x8b, 0x5d, 0x08,
|
||
0x56, 0x8b, 0xf1,
|
||
0x85, 0xdb,
|
||
0x74, XX,
|
||
0x8b, 0x4e, 0x14,
|
||
0x83, 0xf9, 0x10,
|
||
0x72,0x04,
|
||
0x8b,0x06,
|
||
0xeb,0x02,
|
||
};
|
||
// clang-format on
|
||
|
||
ULONG addr = reverseFindBytes(bytes, sizeof(bytes), addrX - 0x200, addrX);
|
||
if (!addr)
|
||
continue;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.type = USING_STRING | CODEC_UTF8 | NO_CONTEXT;
|
||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||
{
|
||
*data = (DWORD)stack->stack[1];
|
||
*len = stack->stack[2];
|
||
auto refaddr = stack->retaddr - (DWORD)GetModuleHandle(0);
|
||
if (refaddr < 0xb0000 || refaddr > 0xb1000)
|
||
*len = 0;
|
||
};
|
||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||
{
|
||
static const std::regex rx("#\\{(.*?)\\}(.*?)#", std::regex_constants::icase);
|
||
std::string result = std::string((char *)data, *len);
|
||
result = std::regex_replace(result, rx, "$2");
|
||
strReplace(result, u8" \n", "");
|
||
strReplace(result, u8"\n", "");
|
||
return write_string_overwrite(data, len, result);
|
||
};
|
||
succ |= NewHook(hp, "sayanouta");
|
||
}
|
||
return succ;
|
||
}
|
||
}
|
||
bool Nitroplus2::attach_function()
|
||
{
|
||
bool embed = ScenarioHook::attach(processStartAddress, processStopAddress);
|
||
bool b = InsertNitroPlusHook();
|
||
bool b2 = (Util::SearchResourceString(L"TOKYONECRO")) && InsertTokyoNecroHook();
|
||
b2 |= sayanouta();
|
||
return b || b2 || embed;
|
||
} |