mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-24 06:15:35 +08:00
584 lines
21 KiB
C++
584 lines
21 KiB
C++
#include"Silkys.h"
|
||
#include"util/textunion.h"
|
||
|
||
/** jichi: 6/17/2015
|
||
* Sample games
|
||
* - 堕ちてぁ<E381A6>新妻 trial
|
||
* - 根雪の幻影 trial
|
||
*
|
||
* This function is found by backtracking GetGlyphOutlineA.
|
||
* There are two GetGlyphOutlineA, which are in the same function.
|
||
* That function are called by two other functions.
|
||
* The second function is hooked.
|
||
*
|
||
* 堕ちてぁ<E381A6>新妻
|
||
* baseaddr = 08e0000
|
||
*
|
||
* 0096652E CC INT3
|
||
* 0096652F CC INT3
|
||
* 00966530 55 PUSH EBP
|
||
* 00966531 8BEC MOV EBP,ESP
|
||
* 00966533 83EC 18 SUB ESP,0x18
|
||
* 00966536 A1 00109F00 MOV EAX,DWORD PTR DS:[0x9F1000]
|
||
* 0096653B 33C5 XOR EAX,EBP
|
||
* 0096653D 8945 FC MOV DWORD PTR SS:[EBP-0x4],EAX
|
||
* 00966540 53 PUSH EBX
|
||
* 00966541 8B5D 0C MOV EBX,DWORD PTR SS:[EBP+0xC]
|
||
* 00966544 56 PUSH ESI
|
||
* 00966545 8B75 08 MOV ESI,DWORD PTR SS:[EBP+0x8]
|
||
* 00966548 57 PUSH EDI
|
||
* 00966549 6A 00 PUSH 0x0
|
||
* 0096654B 894D EC MOV DWORD PTR SS:[EBP-0x14],ECX
|
||
* 0096654E 8B0D FCB7A200 MOV ECX,DWORD PTR DS:[0xA2B7FC]
|
||
* 00966554 68 90D29D00 PUSH .009DD290 ; ASCII "/Config/SceneSkip"
|
||
* 00966559 895D F0 MOV DWORD PTR SS:[EBP-0x10],EBX
|
||
* 0096655C E8 2F4A0100 CALL .0097AF90
|
||
* 00966561 83F8 01 CMP EAX,0x1
|
||
* 00966564 0F84 E0010000 JE .0096674A
|
||
* 0096656A 8B55 EC MOV EDX,DWORD PTR SS:[EBP-0x14]
|
||
* 0096656D 85DB TEST EBX,EBX
|
||
* 0096656F 75 09 JNZ SHORT .0096657A
|
||
* 00966571 8B42 04 MOV EAX,DWORD PTR DS:[EDX+0x4]
|
||
* 00966574 8B40 38 MOV EAX,DWORD PTR DS:[EAX+0x38]
|
||
* 00966577 8945 F0 MOV DWORD PTR SS:[EBP-0x10],EAX
|
||
* 0096657A 33C0 XOR EAX,EAX
|
||
* 0096657C C645 F8 00 MOV BYTE PTR SS:[EBP-0x8],0x0
|
||
* 00966580 33C9 XOR ECX,ECX
|
||
* 00966582 66:8945 F9 MOV WORD PTR SS:[EBP-0x7],AX
|
||
* 00966586 3946 14 CMP DWORD PTR DS:[ESI+0x14],EAX
|
||
* 00966589 0F86 BB010000 JBE .0096674A
|
||
*
|
||
* Scenario stack:
|
||
*
|
||
* 002FF9DC 00955659 RETURN to .00955659 from .00966530
|
||
* 002FF9E0 002FFA10 ; jichi: text in [arg1+4]
|
||
* 002FF9E4 00000000 ; arg2 is zero
|
||
* 002FF9E8 00000001
|
||
* 002FF9EC 784B8FC7
|
||
*
|
||
* Name stack:
|
||
*
|
||
* 002FF59C 00930A76 RETURN to .00930A76 from .00966530
|
||
* 002FF5A0 002FF5D0 ; jichi: text in [arg1+4]
|
||
* 002FF5A4 004DDEC0 ; arg2 is a pointer
|
||
* 002FF5A8 00000001
|
||
* 002FF5AC 784B8387
|
||
* 002FF5B0 00000182
|
||
* 002FF5B4 00000000
|
||
*
|
||
* Scenario and Name are called by different callers.
|
||
*
|
||
* 根雪の幻影
|
||
*
|
||
* 00A1A00E CC INT3
|
||
* 00A1A00F CC INT3
|
||
* 00A1A010 55 PUSH EBP
|
||
* 00A1A011 8BEC MOV EBP,ESP
|
||
* 00A1A013 83EC 18 SUB ESP,0x18
|
||
* 00A1A016 A1 0050AA00 MOV EAX,DWORD PTR DS:[0xAA5000]
|
||
* 00A1A01B 33C5 XOR EAX,EBP
|
||
* 00A1A01D 8945 FC MOV DWORD PTR SS:[EBP-0x4],EAX
|
||
* 00A1A020 53 PUSH EBX
|
||
* 00A1A021 56 PUSH ESI
|
||
* 00A1A022 8B75 0C MOV ESI,DWORD PTR SS:[EBP+0xC]
|
||
* 00A1A025 57 PUSH EDI
|
||
* 00A1A026 8B7D 08 MOV EDI,DWORD PTR SS:[EBP+0x8]
|
||
* 00A1A029 6A 00 PUSH 0x0
|
||
* 00A1A02B 894D F0 MOV DWORD PTR SS:[EBP-0x10],ECX
|
||
* 00A1A02E 8B0D C434AE00 MOV ECX,DWORD PTR DS:[0xAE34C4]
|
||
* 00A1A034 68 F816A900 PUSH .00A916F8 ; ASCII "/Config/SceneSkip"
|
||
* 00A1A039 8975 EC MOV DWORD PTR SS:[EBP-0x14],ESI
|
||
* 00A1A03C E8 7F510100 CALL .00A2F1C0
|
||
* 00A1A041 83F8 01 CMP EAX,0x1
|
||
* 00A1A044 0F84 3A010000 JE .00A1A184
|
||
* 00A1A04A 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-0x10]
|
||
* 00A1A04D 85F6 TEST ESI,ESI
|
||
* 00A1A04F 75 09 JNZ SHORT .00A1A05A
|
||
* 00A1A051 8B41 04 MOV EAX,DWORD PTR DS:[ECX+0x4]
|
||
* 00A1A054 8B40 38 MOV EAX,DWORD PTR DS:[EAX+0x38]
|
||
* 00A1A057 8945 EC MOV DWORD PTR SS:[EBP-0x14],EAX
|
||
* 00A1A05A 33C0 XOR EAX,EAX
|
||
* 00A1A05C C645 F8 00 MOV BYTE PTR SS:[EBP-0x8],0x0
|
||
* 00A1A060 33DB XOR EBX,EBX
|
||
* 00A1A062 66:8945 F9 MOV WORD PTR SS:[EBP-0x7],AX
|
||
* 00A1A066 3947 14 CMP DWORD PTR DS:[EDI+0x14],EAX
|
||
* 00A1A069 0F86 15010000 JBE .00A1A184
|
||
* 00A1A06F 90 NOP
|
||
* 00A1A070 837F 18 10 CMP DWORD PTR DS:[EDI+0x18],0x10
|
||
* 00A1A074 72 05 JB SHORT .00A1A07B
|
||
* 00A1A076 8B47 04 MOV EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A079 EB 03 JMP SHORT .00A1A07E
|
||
* 00A1A07B 8D47 04 LEA EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A07E 803C18 00 CMP BYTE PTR DS:[EAX+EBX],0x0
|
||
* 00A1A082 0F84 FC000000 JE .00A1A184
|
||
* 00A1A088 837F 18 10 CMP DWORD PTR DS:[EDI+0x18],0x10
|
||
* 00A1A08C 72 05 JB SHORT .00A1A093
|
||
* 00A1A08E 8B47 04 MOV EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A091 EB 03 JMP SHORT .00A1A096
|
||
* 00A1A093 8D47 04 LEA EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A096 8A0418 MOV AL,BYTE PTR DS:[EAX+EBX]
|
||
* 00A1A099 3C 81 CMP AL,0x81
|
||
* 00A1A09B 72 04 JB SHORT .00A1A0A1
|
||
* 00A1A09D 3C 9F CMP AL,0x9F
|
||
* 00A1A09F 76 06 JBE SHORT .00A1A0A7
|
||
* 00A1A0A1 04 20 ADD AL,0x20
|
||
* 00A1A0A3 3C 0F CMP AL,0xF
|
||
* 00A1A0A5 77 40 JA SHORT .00A1A0E7
|
||
* 00A1A0A7 837F 18 10 CMP DWORD PTR DS:[EDI+0x18],0x10
|
||
* 00A1A0AB 72 05 JB SHORT .00A1A0B2
|
||
* 00A1A0AD 8B47 04 MOV EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A0B0 EB 03 JMP SHORT .00A1A0B5
|
||
* 00A1A0B2 8D47 04 LEA EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A0B5 837F 18 10 CMP DWORD PTR DS:[EDI+0x18],0x10
|
||
* 00A1A0B9 8A0418 MOV AL,BYTE PTR DS:[EAX+EBX]
|
||
* 00A1A0BC 8845 F8 MOV BYTE PTR SS:[EBP-0x8],AL
|
||
* 00A1A0BF 72 13 JB SHORT .00A1A0D4
|
||
* 00A1A0C1 8B47 04 MOV EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A0C4 C645 F7 02 MOV BYTE PTR SS:[EBP-0x9],0x2
|
||
* 00A1A0C8 8A4418 01 MOV AL,BYTE PTR DS:[EAX+EBX+0x1]
|
||
* 00A1A0CC 83C3 02 ADD EBX,0x2
|
||
* 00A1A0CF 8845 F9 MOV BYTE PTR SS:[EBP-0x7],AL
|
||
* 00A1A0D2 EB 30 JMP SHORT .00A1A104
|
||
* 00A1A0D4 8D47 04 LEA EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A0D7 C645 F7 02 MOV BYTE PTR SS:[EBP-0x9],0x2
|
||
* 00A1A0DB 8A4418 01 MOV AL,BYTE PTR DS:[EAX+EBX+0x1]
|
||
* 00A1A0DF 83C3 02 ADD EBX,0x2
|
||
* 00A1A0E2 8845 F9 MOV BYTE PTR SS:[EBP-0x7],AL
|
||
* 00A1A0E5 EB 1D JMP SHORT .00A1A104
|
||
* 00A1A0E7 837F 18 10 CMP DWORD PTR DS:[EDI+0x18],0x10
|
||
* 00A1A0EB 72 05 JB SHORT .00A1A0F2
|
||
* 00A1A0ED 8B47 04 MOV EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A0F0 EB 03 JMP SHORT .00A1A0F5
|
||
* 00A1A0F2 8D47 04 LEA EAX,DWORD PTR DS:[EDI+0x4]
|
||
* 00A1A0F5 8A0418 MOV AL,BYTE PTR DS:[EAX+EBX]
|
||
* 00A1A0F8 43 INC EBX
|
||
* 00A1A0F9 8845 F8 MOV BYTE PTR SS:[EBP-0x8],AL
|
||
* 00A1A0FC C645 F9 00 MOV BYTE PTR SS:[EBP-0x7],0x0
|
||
* 00A1A100 C645 F7 01 MOV BYTE PTR SS:[EBP-0x9],0x1
|
||
* 00A1A104 807F 48 01 CMP BYTE PTR DS:[EDI+0x48],0x1
|
||
* 00A1A108 75 21 JNZ SHORT .00A1A12B
|
||
* 00A1A10A 8B49 08 MOV ECX,DWORD PTR DS:[ECX+0x8]
|
||
* 00A1A10D 8D47 38 LEA EAX,DWORD PTR DS:[EDI+0x38]
|
||
* 00A1A110 50 PUSH EAX
|
||
* 00A1A111 FF77 28 PUSH DWORD PTR DS:[EDI+0x28]
|
||
* 00A1A114 8B47 24 MOV EAX,DWORD PTR DS:[EDI+0x24]
|
||
* 00A1A117 03C0 ADD EAX,EAX
|
||
* 00A1A119 50 PUSH EAX
|
||
* 00A1A11A 8D47 20 LEA EAX,DWORD PTR DS:[EDI+0x20]
|
||
* 00A1A11D 50 PUSH EAX
|
||
* 00A1A11E 8D47 1C LEA EAX,DWORD PTR DS:[EDI+0x1C]
|
||
* 00A1A121 50 PUSH EAX
|
||
* 00A1A122 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-0x8]
|
||
* 00A1A125 50 PUSH EAX
|
||
* 00A1A126 E8 85220000 CALL .00A1C3B0
|
||
* 00A1A12B FF77 34 PUSH DWORD PTR DS:[EDI+0x34]
|
||
* 00A1A12E 8B4D EC MOV ECX,DWORD PTR SS:[EBP-0x14]
|
||
* 00A1A131 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-0x8]
|
||
* 00A1A134 FF77 4C PUSH DWORD PTR DS:[EDI+0x4C]
|
||
* 00A1A137 FF77 30 PUSH DWORD PTR DS:[EDI+0x30]
|
||
* 00A1A13A FF77 2C PUSH DWORD PTR DS:[EDI+0x2C]
|
||
* 00A1A13D FF77 20 PUSH DWORD PTR DS:[EDI+0x20]
|
||
* 00A1A140 FF77 1C PUSH DWORD PTR DS:[EDI+0x1C]
|
||
* 00A1A143 50 PUSH EAX
|
||
* 00A1A144 E8 1733FFFF CALL .00A0D460
|
||
* 00A1A149 0FBE45 F7 MOVSX EAX,BYTE PTR SS:[EBP-0x9]
|
||
* 00A1A14D 0FAF47 24 IMUL EAX,DWORD PTR DS:[EDI+0x24]
|
||
* 00A1A151 0147 1C ADD DWORD PTR DS:[EDI+0x1C],EAX
|
||
* 00A1A154 807F 48 00 CMP BYTE PTR DS:[EDI+0x48],0x0
|
||
* 00A1A158 8B47 1C MOV EAX,DWORD PTR DS:[EDI+0x1C]
|
||
* 00A1A15B 75 1B JNZ SHORT .00A1A178
|
||
* 00A1A15D 3947 40 CMP DWORD PTR DS:[EDI+0x40],EAX
|
||
* 00A1A160 7F 16 JG SHORT .00A1A178
|
||
* 00A1A162 8B47 38 MOV EAX,DWORD PTR DS:[EDI+0x38]
|
||
* 00A1A165 8B4F 28 MOV ECX,DWORD PTR DS:[EDI+0x28]
|
||
* 00A1A168 014F 20 ADD DWORD PTR DS:[EDI+0x20],ECX
|
||
* 00A1A16B 8947 1C MOV DWORD PTR DS:[EDI+0x1C],EAX
|
||
* 00A1A16E 8B47 20 MOV EAX,DWORD PTR DS:[EDI+0x20]
|
||
* 00A1A171 03C1 ADD EAX,ECX
|
||
* 00A1A173 3B47 44 CMP EAX,DWORD PTR DS:[EDI+0x44]
|
||
* 00A1A176 7D 0C JGE SHORT .00A1A184
|
||
* 00A1A178 8B4D F0 MOV ECX,DWORD PTR SS:[EBP-0x10]
|
||
* 00A1A17B 3B5F 14 CMP EBX,DWORD PTR DS:[EDI+0x14]
|
||
* 00A1A17E ^0F82 ECFEFFFF JB .00A1A070
|
||
* 00A1A184 8B4D FC MOV ECX,DWORD PTR SS:[EBP-0x4]
|
||
* 00A1A187 5F POP EDI
|
||
* 00A1A188 5E POP ESI
|
||
* 00A1A189 33CD XOR ECX,EBP
|
||
* 00A1A18B 5B POP EBX
|
||
* 00A1A18C E8 87600200 CALL .00A40218
|
||
* 00A1A191 8BE5 MOV ESP,EBP
|
||
* 00A1A193 5D POP EBP
|
||
* 00A1A194 C2 0C00 RETN 0xC
|
||
* 00A1A197 CC INT3
|
||
* 00A1A198 CC INT3
|
||
*/
|
||
static void SpecialHookSilkys(hook_stack* stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
//DWORD arg1 = *(DWORD *)(esp_base + 0x4);
|
||
DWORD arg1 = stack->stack[1],
|
||
arg2 = stack->stack[2];
|
||
|
||
int size = *(DWORD *)(arg1 + 0x14);
|
||
if (size <= 0)
|
||
return;
|
||
|
||
enum { ShortTextCapacity = 0x10 };
|
||
|
||
DWORD text = 0;
|
||
//if (arg2 == 0) {
|
||
if (size >= ShortTextCapacity) {
|
||
text = *(DWORD *)(arg1 + 4);
|
||
if (text && ::IsBadReadPtr((LPCVOID)text, size)) // this might not be needed though
|
||
text = 0;
|
||
}
|
||
if (!text) { // short text
|
||
text = arg1 + 4;
|
||
size = min(size, ShortTextCapacity);
|
||
}
|
||
*len = size;
|
||
*data = text;
|
||
|
||
*split = arg2 == 0 ? 1 : 2; // arg2 == 0 ? scenario : name
|
||
}
|
||
bool hookBefore(hook_stack*s,void* data1, size_t* len,uintptr_t*role)
|
||
{
|
||
auto arg = (TextUnionA *)(s->stack[0] + sizeof(DWORD)); // arg1
|
||
if (!arg || !arg->isValid())
|
||
return 0;
|
||
|
||
// FIXME: I am not able to distinguish choice out
|
||
* role =
|
||
s->stack[1] ? Engine::NameRole : // arg2 != 0 for name
|
||
//s->ebx > 0x0fffffff ? Engine::ChoiceRole : // edx is a pointer for choice
|
||
Engine::ScenarioRole;
|
||
|
||
std::string oldData(arg->getText(), arg->size);
|
||
return write_string_overwrite(data1,len,oldData);
|
||
}
|
||
TextUnionA *arg_,
|
||
argValue_;
|
||
void hookafter1(hook_stack*s,void* data1, size_t len){
|
||
auto newData=std::string((char*)data1,len);
|
||
auto arg = (TextUnionA *)(s->stack[0] + sizeof(DWORD)); // arg1
|
||
arg_ = arg;
|
||
argValue_ = *arg;
|
||
static std::string data_;
|
||
data_ = newData;
|
||
arg->setText(data_);
|
||
}
|
||
|
||
bool hookAfter(hook_stack*s,void* data1, size_t* len,uintptr_t*role)
|
||
{
|
||
if (arg_) {
|
||
*arg_ = argValue_;
|
||
arg_ = nullptr;
|
||
}
|
||
return 0;
|
||
}
|
||
bool InsertSilkysHook()
|
||
{
|
||
const BYTE bytes[] = {
|
||
0x66,0x89,0x45, 0xf9, // 00a1a062 66:8945 f9 mov word ptr ss:[ebp-0x7],ax
|
||
0x39,0x47, 0x14 // 00a1a066 3947 14 cmp dword ptr ds:[edi+0x14],eax
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
if (!addr) {
|
||
ConsoleOutput("Silkys: pattern not found");
|
||
return false;
|
||
}
|
||
|
||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||
if (!addr) {
|
||
ConsoleOutput("Silkys: function not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.text_fun = SpecialHookSilkys;
|
||
hp.type = USING_STRING|NO_CONTEXT; // = 9
|
||
|
||
ConsoleOutput("INSERT Silkys");
|
||
auto succ=NewHook(hp, "SilkysPlus");
|
||
auto fun = [](ULONG addr) -> bool {
|
||
auto succ_=false;
|
||
{
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.type = USING_STRING|NO_CONTEXT|EMBED_ABLE|EMBED_DYNA_SJIS;
|
||
hp.hook_before=hookBefore;
|
||
hp.hook_after=hookafter1;
|
||
hp.hook_font=F_GetGlyphOutlineA;
|
||
succ_|=NewHook(hp,"EmbedSilkys");
|
||
}
|
||
{
|
||
HookParam hp;
|
||
hp.address = addr+5;
|
||
hp.type = HOOK_EMPTY|EMBED_ABLE;
|
||
hp.hook_before=hookAfter;
|
||
succ_|=NewHook(hp,"EmbedSilkys");
|
||
}
|
||
return succ_; // replace all functions
|
||
};
|
||
succ|=MemDbg::iterNearCallAddress(fun, addr, processStartAddress, processStopAddress);
|
||
return succ;
|
||
}
|
||
bool InsertSilkysHook2()
|
||
{
|
||
//[230825] [コンフィチュールソフト] ギャル×オタ ~織川きららはお世話したい~
|
||
auto addr = MemDbg::findCallerAddressAfterInt3((DWORD)GetCharacterPlacementW, processStartAddress, processStopAddress);
|
||
if(addr==0)return false;
|
||
BYTE sig[]={
|
||
0x8b,0x80,XX4,
|
||
0xff,0xd0,
|
||
0x8b,0xf0
|
||
};
|
||
addr=MemDbg::findBytes(sig,sizeof(sig),addr,addr+0x100);
|
||
if(addr==0)return false;
|
||
HookParam hp;
|
||
hp.address = addr+8;
|
||
hp.type = CODEC_UTF16|USING_STRING;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||
static int idx=0;
|
||
idx+=1;
|
||
return (bool)(idx%2);
|
||
};
|
||
return NewHook(hp, "SilkysPlus2");
|
||
}
|
||
namespace{
|
||
bool _s(){
|
||
///https://vndb.org/r68491
|
||
//徒花異譚 / Adabana Odd Tales
|
||
BYTE sig[]={
|
||
0xBA,0x00,0x01,0x00,0x00,
|
||
0xC7,0x45,0x08,0x14,0x20,0x00,0x00,
|
||
0x8D,0x49,0x00
|
||
};
|
||
auto addr=MemDbg::findBytes(sig,sizeof(sig),processStartAddress, processStopAddress);
|
||
if(addr==0)return false;
|
||
addr = findfuncstart(addr);
|
||
if (!addr) return 0;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_stack(1);
|
||
hp.newlineseperator=L"\\n";
|
||
hp.type = USING_STRING|CODEC_UTF16|EMBED_ABLE|EMBED_BEFORE_SIMPLE|EMBED_AFTER_NEW;
|
||
return NewHook(hp,"EmbedSilkysX");
|
||
}
|
||
}
|
||
namespace{
|
||
bool Silkys2Filter(LPVOID data, size_t *size, HookParam *)
|
||
{
|
||
auto text = reinterpret_cast<LPWSTR>(data);
|
||
auto len = reinterpret_cast<size_t *>(size);
|
||
|
||
StringCharReplacer(text, len, L"\\i", 2, L'\'');
|
||
|
||
return true;
|
||
}
|
||
|
||
bool InsertSilkys2Hook()
|
||
{
|
||
//https://vndb.org/r89173
|
||
//同级生Remake
|
||
const BYTE bytes[] = {
|
||
// (unsigned __int16)v13 < 0x100u || (_WORD)v13 == 8212
|
||
0xC7,0x45,XX,0x00,0x01,0x00,0x00,
|
||
0xC7,0x45,XX,0x14,0x20,0x00,0x00
|
||
};
|
||
const BYTE bytes2[] = {
|
||
//v6 = (_WORD *)(*v8 + *(_DWORD *)(v7 + 4 * v27));
|
||
//hook v6
|
||
0x8b,0x4d,0xf4,
|
||
0x8b,0x3c,0x8f,
|
||
0x03,0x38
|
||
};
|
||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
if (!addr) return false;
|
||
addr = reverseFindBytes(bytes2, sizeof(bytes2), addr-0x100, addr);
|
||
if (!addr) return false;
|
||
HookParam hp;
|
||
hp.address = addr + sizeof(bytes2);
|
||
hp.offset=get_reg(regs::edi);
|
||
hp.filter_fun = Silkys2Filter;
|
||
hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT;
|
||
return NewHook(hp, "Silkys2");
|
||
}
|
||
}
|
||
namespace{
|
||
bool saiminset(){
|
||
//[230929][1237052][シルキーズSAKURA] 催眠奪女Set パッケージ版
|
||
auto addr1=finddllfunctioncall((DWORD)GetGlyphOutlineA,processStartAddress, processStopAddress);
|
||
if(addr1==0)return false;
|
||
auto func1=MemDbg::findEnclosingAlignedFunction(addr1);
|
||
if(func1==0)return false;
|
||
BYTE check[]={
|
||
0x80,0xf9,0x81,XX2,//cmp cl, 81h
|
||
0x80,0xf9,0x9f,XX2,// cmp cl, 9Fh
|
||
};
|
||
if(MemDbg::findBytes(check,sizeof(check),func1,addr1)==0)return false;
|
||
auto xrefs=findxref_reverse_checkcallop(func1,processStartAddress,processStopAddress,0xe8);
|
||
if(xrefs.size()==0)return false;
|
||
auto addr2=xrefs[0];
|
||
auto addr=MemDbg::findEnclosingAlignedFunction(addr2);
|
||
if(addr==0)return false;
|
||
HookParam hp;
|
||
hp.address = addr ;
|
||
hp.offset=get_stack(1);
|
||
hp.index=0;
|
||
hp.split=get_stack(6);
|
||
hp.type = USING_SPLIT|DATA_INDIRECT;
|
||
return NewHook(hp, "Silkys3");
|
||
}
|
||
}
|
||
namespace{
|
||
//言の葉舞い散る夏の風鈴
|
||
//https://vndb.org/v23466
|
||
bool silkys4(){
|
||
BYTE check[]={
|
||
0x80,0xFA,0x81,
|
||
0x72,XX,
|
||
0x80,0xFA,0x9F,
|
||
0x76,XX
|
||
};
|
||
auto addr=MemDbg::findCallerAddress((ULONG)GetGlyphOutlineA, 0xec8b55,processStartAddress, processStopAddress);
|
||
if(addr==0)return false;
|
||
if(MemDbg::findBytes(check,sizeof(check),addr,addr+0x100)==0)return false;
|
||
HookParam hp;
|
||
hp.address=addr;
|
||
hp.type=USING_CHAR|DATA_INDIRECT|USING_SPLIT;
|
||
hp.split=get_stack(1);
|
||
hp.offset=get_stack(1);//thiscall arg1
|
||
hp.filter_fun=[](LPVOID data, size_t *size, HookParam *)
|
||
{
|
||
static int idx=0;
|
||
return (bool)((idx++)%2);
|
||
};
|
||
return NewHook(hp, "Silkys4");
|
||
}
|
||
}
|
||
bool Silkys::attach_function() {
|
||
auto b1=InsertSilkys2Hook();
|
||
return InsertSilkysHook()||InsertSilkysHook2()||_s()||b1||saiminset()||silkys4();
|
||
}
|
||
|
||
|
||
bool SilkysOld::attach_function(){
|
||
//愛姉妹・蕾…汚してください
|
||
auto addr=MemDbg::findCallerAddressAfterInt3((DWORD)TextOutA,processStartAddress,processStopAddress);
|
||
if(addr==0)return false;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.offset=get_stack(3);
|
||
hp.type=DATA_INDIRECT;
|
||
return NewHook(hp, "SilkysOld");
|
||
}
|
||
|
||
|
||
bool Siglusold::attach_function(){
|
||
//女系家族
|
||
//https://vndb.org/v5650
|
||
// int __cdecl sub_410C20(char *a1, _DWORD *a2)
|
||
// {
|
||
// unsigned __int16 v2; // dx
|
||
// int v3; // edi
|
||
// int result; // eax
|
||
// int v5; // eax
|
||
|
||
// HIBYTE(v2) = *a1;
|
||
// LOBYTE(v2) = a1[1];
|
||
// v3 = *a1;
|
||
// *a2 = 24 * (v2 & 0xF);
|
||
// if ( v2 < 0x8140u || v2 > 0x84FFu )
|
||
// {
|
||
// if ( v2 < 0x8740u || v2 > 0x879Fu )
|
||
// {
|
||
// if ( v2 < 0x8890u || v2 > 0x88FFu )
|
||
// {
|
||
// if ( v2 < 0x8940u || v2 > 0x9FFFu )
|
||
// {
|
||
// if ( v2 < 0xE040u || v2 > 0xEAA4u )
|
||
// {
|
||
// if ( v2 < 0xFA40u || v2 > 0xFAFCu )
|
||
// {
|
||
// if ( v2 < 0xFB40u || v2 > 0xFBFCu )
|
||
// {
|
||
// if ( v2 < 0xFC40u || v2 > 0xFC4Bu )
|
||
// {
|
||
BYTE bytes[]={
|
||
0x66,XX,0x40,0x87,
|
||
XX2,
|
||
0x66,XX,0x9f,0x87,
|
||
};
|
||
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
if(addr==0)return false;
|
||
addr=MemDbg::findEnclosingAlignedFunction_strict(addr);
|
||
if(addr==0)return false;
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.type=USING_CHAR|DATA_INDIRECT;
|
||
hp.offset=get_stack(1);
|
||
auto succ= NewHook(hp, "Siglusold_slow");//文本速度是慢速时这个有用,调成快速以后有无法过滤的重复
|
||
auto addrs=findxref_reverse_checkcallop(addr,addr-0x1000,addr+0x1000,0xe8);
|
||
for(auto addr:addrs){
|
||
//寻找调用者,速度为快速时调用者有正确的文本
|
||
addr=MemDbg::findEnclosingAlignedFunction_strict(addr);
|
||
if(addr==0)continue;
|
||
HookParam hpref;
|
||
hpref.address=addr;
|
||
hpref.text_fun=[](hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len){
|
||
auto a2=(DWORD*)stack->stack[2];
|
||
|
||
auto len1=stack->stack[3];//慢速时是1
|
||
auto len2=a2[7]-a2[6];
|
||
if(len1==0||len2==0)return;
|
||
|
||
if(len1==1){//慢速
|
||
hp->type=USING_CHAR;
|
||
*data=a2[5]+a2[6];
|
||
*data=*(WORD*)*data;
|
||
auto check=(BYTE)*data;//换行符
|
||
*len=1+IsDBCSLeadByteEx(932,check);
|
||
}
|
||
else{//快速&&慢速下立即显示
|
||
*data=a2[5];
|
||
*len=len1;
|
||
}
|
||
};
|
||
hpref.type=USING_STRING;
|
||
succ|= NewHook(hpref, "Siglusold_fast");
|
||
}
|
||
return succ;
|
||
}
|
||
|
||
bool Silkyssakura::attach_function(){
|
||
auto addr=MemDbg::findCallerAddressAfterInt3((DWORD)GetGlyphOutlineW,processStartAddress,processStopAddress);
|
||
if(addr==0)return false;
|
||
HookParam hp;
|
||
hp.address=addr;
|
||
hp.offset=get_stack(3);
|
||
hp.split=get_stack(5);
|
||
hp.type=DATA_INDIRECT|USING_CHAR|USING_SPLIT|CODEC_UTF16;
|
||
|
||
auto xrefs=findxref_reverse_checkcallop(addr,processStartAddress,processStopAddress,0xe8);
|
||
if(xrefs.size()==1){
|
||
addr=MemDbg::findEnclosingAlignedFunction(xrefs[0]);
|
||
if(addr){
|
||
xrefs=findxref_reverse_checkcallop(addr,processStartAddress,processStopAddress,0xe8);
|
||
if(xrefs.size()==1){
|
||
addr=MemDbg::findEnclosingAlignedFunction(xrefs[0]);
|
||
if(addr){
|
||
HookParam hp_embed;
|
||
hp_embed.address=addr;
|
||
hp_embed.offset=get_stack(2);
|
||
hp_embed.type=USING_STRING|EMBED_ABLE|EMBED_AFTER_NEW|EMBED_BEFORE_SIMPLE|CODEC_UTF16;
|
||
hp_embed.hook_font=F_GetGlyphOutlineW;
|
||
return NewHook(hp_embed,"embedSilkyssakura");//这个是分两层分别绘制文字和阴影,需要两个都内嵌。
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return NewHook(hp,"Silkyssakura");
|
||
} |