#include "Nitroplus.h" bool InsertNitroplusHook() { const BYTE bytes[] = {0xb0, 0x74, 0x53}; DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); if (!addr) { ConsoleOutput("Nitroplus: pattern not exist"); return false; } enum : WORD { sub_esp = 0xec83 }; // caller pattern: sub esp = 0x83,0xec BYTE b = *(BYTE *)(addr + 3) & 3; while (*(WORD *)addr != sub_esp) addr--; HookParam hp; hp.address = addr; hp.offset = -0x14 + (b << 2); hp.type = CODEC_ANSI_BE; ConsoleOutput("INSERT Nitroplus"); return NewHook(hp, "Nitroplus"); // RegisterEngineType(ENGINE_Nitroplus); } bool InsertNitroplus2Hook() { /* * Sample games: * https://vndb.org/v428 */ BYTE bytes[] = { 0x8D, 0xB4, 0x29, XX4, // lea esi,[ecx+ebp+0000415C] 0x74, 0x20, // je Django.exe+6126E 0x8D, 0xBC, 0xBD, XX4, // lea edi,[ebp+edi*4+0006410C] 0x8B, 0x56, 0xB0, // mov edx,[esi-50] 0xE8, XX4 // call Django.exe+51150 << hook here }; enum { addr_offset = sizeof(bytes) - 5 }; ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); if (!addr) { ConsoleOutput("Nitroplus2: pattern not found"); return false; } HookParam hp; hp.address = addr + addr_offset; hp.offset = get_reg(regs::edx); hp.type = CODEC_ANSI_BE; return NewHook(hp, "Nitroplus2"); } namespace { // DRAMAtical Murder re:connect 普及版 // https://vndb.org/v10895 bool dmmdrc() { // BYTE sig[]={ // 0xc7,0x04,0x24,0x24,0x53,0x59,0x53,//$SYS // 0xc7,0x44,0x24,0x04,0x54,0x45,0x4d,0x5f,//TEM_ // 0xc7,0x44,0x24,0x08,0x6c,0x61,0x73,0x74,//last // 0xc7,0x44,0x24,0x0c,0x5f,0x74,0x65,0x78,//_tex // }; BYTE sig[] = { 0x8d, 0x89, XX4, 0x8b, 0xc2, 0xc1, 0xe8, 0x08, 0x88, 0x01, 0x88, 0x51, 0x01, 0xc6, 0x41, 0x02, 0x00}; ULONG addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress); if (!addr) return false; HookParam hp; hp.address = *(DWORD *)(addr + 2); hp.type = DIRECT_READ; auto succ = NewHook(hp, "dmmdrc"); BYTE sig2[] = { //clang-format off 0x68, 0x00, 0x02, 0x00, 0x00, 0xba, XX4, 0xe8, XX4, //clang-format on }; memcpy(sig2 + 6, (void *)(addr + 2), 4); addr = MemDbg::findBytes(sig2, sizeof(sig2), addr, addr + 0x100); if (addr) { HookParam hp; hp.address = addr + sizeof(sig2); hp.type = USING_STRING; hp.user_value = 0; hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len) { *data = stack->edx; auto l = strlen((char *)*data); if (hp->user_value > l) hp->user_value = 0; *data += hp->user_value; *len = l - hp->user_value; hp->user_value = l; }; succ |= NewHook(hp, "dmmdrc2"); } return succ; } } bool Nitroplus::attach_function() { return InsertNitroplusHook() || InsertNitroplus2Hook() || dmmdrc(); } bool NitroplusSysFilter(LPVOID data, size_t *size, HookParam *) { auto text = reinterpret_cast(data); auto len = reinterpret_cast(size); if (*len <= 2) return false; StringFilter(text, len, "\x81@", 2); CharReplacer(text, len, '\r', ' '); if (cpp_strnstr(text, "<", *len)) { StringFilterBetween(text, len, "<", 1, ">", 1); } while (*len > 1 && ::isspace(*text)) { ::memmove(text, text + 1, --(*len)); } return true; } bool InsertNitroplusSysHook() { /* * Sample games: * https://vndb.org/r76679 */ const BYTE bytes[] = { 0x0F, 0x84, XX4, // je system.dll+5B8CA <- hook here 0xEB, 0x04, // jmp system.dll+5A791 0x8B, 0x44, 0x24, 0x20, // mov eax,[esp+20] 0x8B, 0x4C, 0x24, 0x24 // mov ecx,[esp+24] }; HMODULE module = GetModuleHandleW(L"system.dll"); auto [minAddress, maxAddress] = Util::QueryModuleLimits(module); ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), minAddress, maxAddress); if (!addr) return false; HookParam hp; hp.address = addr; hp.offset = get_reg(regs::eax); hp.type = USING_STRING; hp.filter_fun = NitroplusSysFilter; return NewHook(hp, "NitroplusSystem"); } bool Nitroplusplus::attach_function() { return InsertNitroplusSysHook(); }