From a415e9c2212ba077b69afa473599f049a9508105 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Tue, 3 Dec 2024 12:50:02 +0800 Subject: [PATCH] . --- cpp/LunaHook/LunaHook/engine32/Circus1.cpp | 171 ++++++++++++------- cpp/LunaHook/LunaHook/engine32/Circus1.h | 33 +++- cpp/LunaHook/LunaHook/enginecollection32.cpp | 1 + 3 files changed, 140 insertions(+), 65 deletions(-) diff --git a/cpp/LunaHook/LunaHook/engine32/Circus1.cpp b/cpp/LunaHook/LunaHook/engine32/Circus1.cpp index 4b4cd772..528db352 100644 --- a/cpp/LunaHook/LunaHook/engine32/Circus1.cpp +++ b/cpp/LunaHook/LunaHook/engine32/Circus1.cpp @@ -1,82 +1,137 @@ -#include"Circus1.h" - /******************************************************************************************** +#include "Circus1.h" +/******************************************************************************************** CIRCUS hook: - Game folder contains advdata folder. Used by CIRCUS games. - Usually has font caching issues. But trace back from GetGlyphOutline gives a hook - which generate repetition. - If we study circus engine follow Freaka's video, we can easily discover that - in the game main module there is a static buffer, which is filled by new text before - it's drawing to screen. By setting a hardware breakpoint there we can locate the - function filling the buffer. But we don't have to set hardware breakpoint to search - the hook address if we know some characteristic instruction(cmp al,0x24) around there. + Game folder contains advdata folder. Used by CIRCUS games. + Usually has font caching issues. But trace back from GetGlyphOutline gives a hook + which generate repetition. + If we study circus engine follow Freaka's video, we can easily discover that + in the game main module there is a static buffer, which is filled by new text before + it's drawing to screen. By setting a hardware breakpoint there we can locate the + function filling the buffer. But we don't have to set hardware breakpoint to search + the hook address if we know some characteristic instruction(cmp al,0x24) around there. ********************************************************************************************/ bool InsertCircusHook1() // jichi 10/2/2013: Change return type to bool { for (DWORD i = processStartAddress + 0x1000; i < processStopAddress - 4; i++) - if (*(WORD *)i == 0xa3c) //cmp al, 0xA; je - for (DWORD j = i; j < i + 0x100; j++) { + if (*(WORD *)i == 0xa3c) // cmp al, 0xA; je + for (DWORD j = i; j < i + 0x100; j++) + { BYTE c = *(BYTE *)j; if (c == 0xc3) break; - if (c == 0xe8) { - DWORD k = *(DWORD *)(j+1)+j+5; - if (k > processStartAddress && k < processStopAddress) { + if (c == 0xe8) + { + DWORD k = *(DWORD *)(j + 1) + j + 5; + if (k > processStartAddress && k < processStopAddress) + { HookParam hp; hp.address = k; - hp.offset=get_stack(3); - hp.split =get_reg(regs::esp); - hp.type = DATA_INDIRECT|USING_SPLIT; + hp.offset = get_stack(3); + hp.split = get_reg(regs::esp); + hp.type = DATA_INDIRECT | USING_SPLIT; ConsoleOutput("INSERT CIRCUS#1"); - - //RegisterEngineType(ENGINE_CIRCUS); + + // RegisterEngineType(ENGINE_CIRCUS); return NewHook(hp, "Circus1"); } } } - //break; - //ConsoleOutput("Unknown CIRCUS engine"); + // break; + // ConsoleOutput("Unknown CIRCUS engine"); ConsoleOutput("CIRCUS1: failed"); return false; } -namespace{ - //C.D.C.D.2~シーディーシーディー2~ - //https://vndb.org/v947 +namespace +{ + // C.D.C.D.2~シーディーシーディー2~ + // https://vndb.org/v947 bool circus12() { - BYTE sig[]={ - 0x3C,0x24, - 0x0F,0x85,XX4, - 0x8A,0x47,0x01, - 0x47, - 0x3C,0x6E, - 0x75,XX, - 0xA0,XX4, - 0xB9,XX4, - 0x84,0xC0, - 0x0F,0x84,XX4, - 0x88,0x06, - 0x8A,0x41,0x01, - 0x46, - 0x41, - 0x84,0xC0, - 0x75,XX, - 0xE9,XX4, - 0x3C,0x66, - 0x75,XX - }; - auto addr=MemDbg::findBytes(sig,sizeof(sig),processStartAddress,processStopAddress); - if(!addr)return false; - addr=MemDbg::findEnclosingAlignedFunction(addr,0x40); - if(!addr)return false; + BYTE sig[] = { + 0x3C, 0x24, + 0x0F, 0x85, XX4, + 0x8A, 0x47, 0x01, + 0x47, + 0x3C, 0x6E, + 0x75, XX, + 0xA0, XX4, + 0xB9, XX4, + 0x84, 0xC0, + 0x0F, 0x84, XX4, + 0x88, 0x06, + 0x8A, 0x41, 0x01, + 0x46, + 0x41, + 0x84, 0xC0, + 0x75, XX, + 0xE9, XX4, + 0x3C, 0x66, + 0x75, XX}; + auto addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress); + if (!addr) + return false; + addr = MemDbg::findEnclosingAlignedFunction(addr, 0x40); + if (!addr) + return false; HookParam hp; - hp.address =addr; - hp.offset=get_stack(2); - hp.type = USING_STRING|EMBED_ABLE|EMBED_AFTER_NEW|EMBED_DYNA_SJIS; - hp.embed_hook_font=F_GetGlyphOutlineA; + hp.address = addr; + hp.offset = get_stack(2); + hp.type = USING_STRING | EMBED_ABLE | EMBED_AFTER_NEW | EMBED_DYNA_SJIS; + hp.embed_hook_font = F_GetGlyphOutlineA; return NewHook(hp, "Circus1"); } } -bool Circus1::attach_function() { - - return InsertCircusHook1()|circus12(); -} \ No newline at end of file +bool Circus1::attach_function() +{ + + return InsertCircusHook1() | circus12(); +} + +bool Circus_old::attach_function() +{ + //[041213][CIRCUS]最終試験くじら + auto call = finddllfunctioncall((DWORD)GetGlyphOutlineA, processStartAddress, processStopAddress); + if (!call) + return false; + auto func = MemDbg::findEnclosingAlignedFunction(call); + if (!func) + return false; + BYTE sig[] = { + /* + .text:0041D1CD cmp edi, 8140h + .text:0041D1D3 jz loc_41D2D9 + .text:0041D1D9 cmp edi, 20h ; ' ' + .text:0041D1DC jz loc_41D2E1*/ + /* + if ( v14 == 33088 ) + { + gm.gmCellIncX = psizl.cx; + goto LABEL_46; + } + if ( v14 == 32 ) + goto LABEL_46; + if ( v43 == v14 ) + goto LABEL_44; + sub_41DC00(0); + v15 = pvBuffer; + if ( GetGlyphOutlineA(hdc, v14, 6u, &gm, cjBuffer, pvBuffer, &mat2) != -1 )*/ + 0x81, 0xFF, 0x40, 0x81, 0x00, 0x00, + 0x0F, 0x84, XX4, + 0x83, 0xFF, 0x20, + 0x0F, 0x84, XX4 + + }; + if (!MemDbg::findBytes(sig, sizeof(sig), func, call)) + return false; + auto refs = findxref_reverse_checkcallop(func, processStartAddress, processStopAddress, 0xe8); + if (refs.size() == 3) + { + func = MemDbg::findEnclosingAlignedFunction(refs[0]); + } + HookParam hp; + hp.address = func; + hp.offset = get_stack(4); + hp.split = get_stack(1); + hp.type = USING_STRING | USING_SPLIT; + return NewHook(hp, "Circus"); +} \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/engine32/Circus1.h b/cpp/LunaHook/LunaHook/engine32/Circus1.h index b0415e1d..f2292b7e 100644 --- a/cpp/LunaHook/LunaHook/engine32/Circus1.h +++ b/cpp/LunaHook/LunaHook/engine32/Circus1.h @@ -1,11 +1,30 @@ -class Circus1:public ENGINE{ - public: - Circus1(){ - - check_by=CHECK_BY::FILE; - check_by_target=L"AdvData\\DAT\\NAMES.DAT"; +class Circus1 : public ENGINE +{ +public: + Circus1() + { + + check_by = CHECK_BY::FILE; + check_by_target = L"AdvData\\DAT\\NAMES.DAT"; }; - bool attach_function(); + bool attach_function(); +}; + +class Circus_old : public ENGINE +{ +public: + Circus_old() + { + check_by = CHECK_BY::CUSTOM; + check_by_target = []() + { + //[041213][CIRCUS]最終試験くじら + auto _ = {L"Pack/Bg.pak", L"Pack/Bustup.pak", L"Pack/Cg.pak", L"Pack/Movie*.pak", L"Pack/Script.pak", L"Pack/Sound.pak", L"Pack/System.pak", L"Pack/Thumbnail.pak"}; + auto checkfile = std::all_of(_.begin(), _.end(), Util::CheckFile); + return checkfile && Util::SearchResourceString(L"Circus"); + }; + }; + bool attach_function(); }; \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/enginecollection32.cpp b/cpp/LunaHook/LunaHook/enginecollection32.cpp index 2cca24a4..4ebb2246 100644 --- a/cpp/LunaHook/LunaHook/enginecollection32.cpp +++ b/cpp/LunaHook/LunaHook/enginecollection32.cpp @@ -216,6 +216,7 @@ std::vector check_engines() new Wolf, new Circus1, new Circus2, + new Circus_old, new Cotopha, new Artemis, new CatSystem,