#include"CaramelBox.h" static void SpecialHookCaramelBox(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len) { DWORD reg_ecx = *(DWORD*)(stack->base + hp->offset); BYTE *ptr = (BYTE *)reg_ecx; buffer_index = 0; while (ptr[0]) if (ptr[0] == 0x28) { // Furigana format: (Kanji,Furi) ptr++; while (ptr[0]!=0x2c) //Copy Kanji text_buffer[buffer_index++] = *ptr++; while (ptr[0]!=0x29) // Skip Furi ptr++; ptr++; } else if (ptr[0] == 0x5c) ptr +=2; else { text_buffer[buffer_index++] = ptr[0]; if (LeadByteTable[ptr[0]] == 2) { ptr++; text_buffer[buffer_index++] = ptr[0]; } ptr++; } *len = buffer_index; *data = (DWORD)text_buffer; *split = 0; // 8/3/2014 jichi: use return address as split } // jichi 10/1/2013: Change return type to bool bool InsertCaramelBoxHook() { union { DWORD i; BYTE* pb; WORD* pw; DWORD *pd; }; DWORD reg = -1; for (i = processStartAddress + 0x1000; i < processStopAddress - 4; i++) { if (*pd == 0x7ff3d) // cmp eax, 7ff reg = 0; else if ((*pd & 0xfffff8fc) == 0x07fff880) // cmp reg, 7ff reg = pb[1] & 0x7; if (reg == -1) continue; DWORD flag = 0; if (*(pb - 6) == 3) { //add reg, [ebp+$disp_32] if (*(pb - 5) == (0x85 | (reg << 3))) flag = 1; } else if (*(pb - 3) == 3) { // add reg, [ebp+$disp_8] if (*(pb - 2) == (0x45 | (reg << 3))) flag = 1; } else if (*(pb - 2) == 3) { // add reg, reg if (((*(pb - 1) >> 3) & 7)== reg) flag = 1; } reg = -1; if (flag) { for (DWORD j = i, k = i - 0x100; j > k; j--) { if ((*(DWORD *)j & 0xffff00ff) == 0x1000b8) { // mov eax,10?? HookParam hp; hp.address = j & ~0xf; hp.text_fun = SpecialHookCaramelBox; hp.type = USING_STRING; for (i &= ~0xffff; i < processStopAddress - 4; i++) if (pb[0] == 0xe8) { pb++; if (pd[0] + i + 4 == hp.address) { pb += 4; if ((pd[0] & 0xffffff) == 0x04c483) hp.offset=get_stack(1); else hp.offset=get_reg(regs::ecx); break; } } if (hp.offset == 0) { ConsoleOutput("CaramelBox: failed, zero off"); return false; } ConsoleOutput("INSERT CaramelBox"); //RegisterEngineType(ENGINE_CARAMEL); return NewHook(hp, "CaramelBox"); } } } } ConsoleOutput("CaramelBox: failed"); return false; //_unknown_engine: //ConsoleOutput("Unknown CarmelBox engine."); } bool CaramelBox::attach_function() { return InsertCaramelBoxHook(); } bool CaramelBoxMilkAji::attach_function(){ //雨芳恋歌 //https://vndb.org/v6663 BYTE bytes[] = { 0x33,0xD2, 0xB9,0x8A,0x02,0x00,0x00, 0xF7,0xF1, 0x6B,0xC0,0x44, 0x6B,0xC0,0x03 }; auto addr=MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); if(addr==0)return false; addr=MemDbg::findEnclosingAlignedFunction(addr); if(addr==0)return false; HookParam hp; hp.address = addr; hp.type = USING_STRING; hp.offset=get_stack(1); return NewHook(hp, "CaramelBox"); } bool CaramelBox2::attach_function(){ //https://vndb.org/r19777 //Otoboku - Maidens Are Falling for Me! - Download Edition trigger_fun=[](LPVOID addr1, hook_stack* stack){ if(addr1!=TextOutA&& addr1!=GetTextExtentPoint32A)return false; auto addr=stack->retaddr; addr = MemDbg::findEnclosingAlignedFunction(addr); if (addr == 0)return false; HookParam hp; hp.address = addr; hp.type = USING_STRING|USING_SPLIT; hp.offset=get_stack(2); hp.split=get_stack(2); NewHook(hp, "CaramelBox"); return true; }; return true; }