mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-10-22 23:18:16 +08:00
...
This commit is contained in:
parent
a5986fe7dd
commit
44ad71eb81
@ -109,8 +109,8 @@
|
||||
* 0012ed64 00951d88 ascii "2015/01/18"
|
||||
*/
|
||||
|
||||
namespace { // unnamed
|
||||
|
||||
namespace
|
||||
{ // unnamed
|
||||
|
||||
void SpecialHookWillPlus(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
@ -118,14 +118,16 @@ void SpecialHookWillPlus(hook_stack* stack, HookParam *hp, uintptr_t *data, uin
|
||||
// if (detect_offset)
|
||||
// return;
|
||||
DWORD i, l;
|
||||
union {
|
||||
union
|
||||
{
|
||||
DWORD retn;
|
||||
WORD *pw;
|
||||
BYTE *pb;
|
||||
};
|
||||
retn = stack->retaddr; // jichi 1/18/2015: dynamically find function return address
|
||||
i = 0;
|
||||
while (*pw != 0xc483) { // add esp, $
|
||||
while (*pw != 0xc483)
|
||||
{ // add esp, $
|
||||
l = ::disasm(pb);
|
||||
if (++i == 5)
|
||||
// ConsoleOutput("Fail to detect offset.");
|
||||
@ -133,7 +135,8 @@ void SpecialHookWillPlus(hook_stack* stack, HookParam *hp, uintptr_t *data, uin
|
||||
retn += l;
|
||||
}
|
||||
// jichi 2/11/2015: Check baddaddr which might crash the game on Windows XP.
|
||||
if (*pw == 0xc483 && !::IsBadReadPtr((LPCVOID)(pb + 2), 1) && !::IsBadReadPtr((LPCVOID)(*(pb + 2) - 8), 1)) {
|
||||
if (*pw == 0xc483 && !::IsBadReadPtr((LPCVOID)(pb + 2), 1) && !::IsBadReadPtr((LPCVOID)(*(pb + 2) - 8), 1))
|
||||
{
|
||||
ConsoleOutput("WillPlus1 pattern found");
|
||||
// jichi 1/18/2015:
|
||||
// By studying [honeybee] RE:BIRTHDAY SONG, it seems the scenario text is at fixed address
|
||||
@ -147,8 +150,9 @@ void SpecialHookWillPlus(hook_stack* stack, HookParam *hp, uintptr_t *data, uin
|
||||
*data = (DWORD)str;
|
||||
*len = ::strlen(str);
|
||||
*split = 0; // 8/3/2014 jichi: use return address as split
|
||||
|
||||
} else { // jichi 1/19/2015: Try willplus2
|
||||
}
|
||||
else
|
||||
{ // jichi 1/19/2015: Try willplus2
|
||||
ConsoleOutput("WillPlus1 pattern not found, try WillPlus2 instead");
|
||||
hp->offset = 4 * 8; // arg8, address of text
|
||||
hp->type = USING_STRING | NO_CONTEXT | USING_SPLIT; // merge different scenario threads
|
||||
@ -166,9 +170,13 @@ void SpecialHookWillPlus(hook_stack* stack, HookParam *hp, uintptr_t *data, uin
|
||||
bool InsertOldWillPlusHook()
|
||||
{
|
||||
//__debugbreak();
|
||||
enum { sub_esp = 0xec81 }; // jichi: caller pattern: sub esp = 0x81,0xec byte
|
||||
enum
|
||||
{
|
||||
sub_esp = 0xec81
|
||||
}; // jichi: caller pattern: sub esp = 0x81,0xec byte
|
||||
ULONG addr = MemDbg::findCallerAddress((ULONG)::GetGlyphOutlineA, sub_esp, processStartAddress, processStopAddress);
|
||||
if (!addr) {
|
||||
if (!addr)
|
||||
{
|
||||
ConsoleOutput("WillPlus: function call not found");
|
||||
return false;
|
||||
}
|
||||
@ -185,8 +193,10 @@ const char *_willplus_trim_a(const char *text, size_t *size)
|
||||
{
|
||||
int textSize = ::strlen(text);
|
||||
int prefix = 0;
|
||||
if (text[0] == '%') {
|
||||
while (prefix < textSize - 1 && text[prefix] == '%' && ::isupper(text[prefix+1])) {
|
||||
if (text[0] == '%')
|
||||
{
|
||||
while (prefix < textSize - 1 && text[prefix] == '%' && ::isupper(text[prefix + 1]))
|
||||
{
|
||||
prefix += 2;
|
||||
while (::isupper(text[prefix]))
|
||||
prefix++;
|
||||
@ -194,7 +204,8 @@ const char *_willplus_trim_a(const char *text, size_t *size)
|
||||
}
|
||||
{
|
||||
int pos = textSize;
|
||||
for (int i = textSize - 1; i >= prefix; i--) {
|
||||
for (int i = textSize - 1; i >= prefix; i--)
|
||||
{
|
||||
char ch = text[i];
|
||||
if (::isupper(ch))
|
||||
;
|
||||
@ -214,8 +225,10 @@ const wchar_t *_willplus_trim_w(const wchar_t *text, size_t *size)
|
||||
{
|
||||
int textSize = ::wcslen(text);
|
||||
int prefix = 0;
|
||||
if (text[0] == '%') {
|
||||
while (prefix < textSize - 1 && text[prefix] == '%' && ::isupper(text[prefix+1])) {
|
||||
if (text[0] == '%')
|
||||
{
|
||||
while (prefix < textSize - 1 && text[prefix] == '%' && ::isupper(text[prefix + 1]))
|
||||
{
|
||||
prefix += 2;
|
||||
while (::isupper(text[prefix]))
|
||||
prefix++;
|
||||
@ -223,7 +236,8 @@ const wchar_t *_willplus_trim_w(const wchar_t *text, size_t *size)
|
||||
}
|
||||
{
|
||||
int pos = textSize;
|
||||
for (int i = textSize - 1; i >= prefix; i--) {
|
||||
for (int i = textSize - 1; i >= prefix; i--)
|
||||
{
|
||||
wchar_t ch = text[i];
|
||||
if (::isupper(ch))
|
||||
;
|
||||
@ -253,7 +267,8 @@ void SpecialHookWillPlusA(hook_stack* stack, HookParam *hp, uintptr_t *data, ui
|
||||
*data = (DWORD)text;
|
||||
*split = FIXED_SPLIT_VALUE << index;
|
||||
}
|
||||
bool WillPlus_extra_filter(void* data, size_t* size, HookParam*) {
|
||||
bool WillPlus_extra_filter(void *data, size_t *size, HookParam *)
|
||||
{
|
||||
|
||||
auto text = reinterpret_cast<LPWSTR>(data);
|
||||
StringFilter(text, size, L"%XS", 5); // remove %XS followed by 2 chars
|
||||
@ -278,7 +293,8 @@ bool InsertWillPlusAHook()
|
||||
const BYTE bytes2[] = {0x8B, 0x00, 0xFF, 0x76, 0xFC, 0x8B, 0xCF, 0x50};
|
||||
ULONG range2 = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||
ULONG addr2 = MemDbg::findBytes(bytes2, sizeof(bytes2), processStartAddress, processStartAddress + range2);
|
||||
if (addr2) {
|
||||
if (addr2)
|
||||
{
|
||||
HookParam myhp;
|
||||
myhp.address = addr2 + 2;
|
||||
|
||||
@ -296,7 +312,8 @@ bool InsertWillPlusAHook()
|
||||
0x81, 0xec, 0x14, 0x08, 0x00, 0x00 // 0042B5E0 81EC 14080000 SUB ESP,0x814 ; jichi: text in eax, name in eax - 1024, able to copy
|
||||
};
|
||||
DWORD addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||
if (!addr) {
|
||||
if (!addr)
|
||||
{
|
||||
ConsoleOutput("WillPlusA: pattern not found");
|
||||
return false;
|
||||
}
|
||||
@ -322,14 +339,16 @@ void SpecialHookWillPlusW(hook_stack* stack, HookParam *hp, uintptr_t *data, ui
|
||||
|
||||
bool InsertWillPlusWHook()
|
||||
{
|
||||
const BYTE bytes1[] = { // scenario
|
||||
const BYTE bytes1[] = {
|
||||
// scenario
|
||||
0x83, 0xc0, 0x20, // 00452b02 83c0 20 add eax,0x20 ; jichi: hook before here, text in ecx
|
||||
0x33, 0xd2, // 00452b05 33d2 xor edx,edx
|
||||
0x8b, 0xc1, // 00452b07 8bc1 mov eax,ecx
|
||||
0xc7, 0x84, 0x24, 0xe0, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00 // 00452b09 c78424 e0010000 07000000 mov dword ptr ss:[esp+0x1e0],0x7
|
||||
// 00452b14 c78424 dc010000 00000000 mov dword ptr ss:[esp+0x1dc],0x0
|
||||
};
|
||||
const BYTE bytes2[] = { // name
|
||||
const BYTE bytes2[] = {
|
||||
// name
|
||||
0x33, 0xdb, // 00453521 33db xor ebx,ebx ; jichi: hook here, text in ecx
|
||||
0x33, 0xd2, // 00453523 33d2 xor edx,edx
|
||||
0x8b, 0xc1, // 00453525 8bc1 mov eax,ecx
|
||||
@ -339,9 +358,11 @@ bool InsertWillPlusWHook()
|
||||
const BYTE *bytes[] = {bytes1, bytes2};
|
||||
const size_t sizes[] = {sizeof(bytes1), sizeof(bytes2)};
|
||||
auto succ = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
DWORD addr = MemDbg::findBytes(bytes[i], sizes[i], processStartAddress, processStopAddress);
|
||||
if (!addr) {
|
||||
if (!addr)
|
||||
{
|
||||
ConsoleOutput("WillPlusW: pattern not found");
|
||||
return false;
|
||||
}
|
||||
@ -450,7 +471,8 @@ static bool InsertNewWillPlusHook()
|
||||
|
||||
BYTE byte = *(BYTE *)(addr + 1);
|
||||
regs offset = regs::invalid;
|
||||
switch (byte) {
|
||||
switch (byte)
|
||||
{
|
||||
case 0xf9:
|
||||
offset = regs::ecx;
|
||||
break;
|
||||
@ -473,7 +495,8 @@ static bool InsertNewWillPlusHook()
|
||||
offset = regs::edi;
|
||||
break;
|
||||
};
|
||||
if (offset!=regs::invalid) {
|
||||
if (offset != regs::invalid)
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = addr + 8;
|
||||
hp.type = CODEC_UTF16;
|
||||
@ -481,7 +504,8 @@ static bool InsertNewWillPlusHook()
|
||||
found |= NewHook(hp, "WillPlus3");
|
||||
}
|
||||
}
|
||||
if (!found) ConsoleOutput("WillPlus: failed to find instructions");
|
||||
if (!found)
|
||||
ConsoleOutput("WillPlus: failed to find instructions");
|
||||
return found;
|
||||
}
|
||||
|
||||
@ -493,9 +517,12 @@ bool InsertWillPlusHook()
|
||||
ok = InsertWillPlusWHook() || InsertNewWillPlusHook() || InsertWillPlusAHook() || ok;
|
||||
return ok;
|
||||
}
|
||||
namespace will3{
|
||||
namespace will3
|
||||
{
|
||||
|
||||
int kp = 0;int lf=0;int lc=0;
|
||||
int kp = 0;
|
||||
int lf = 0;
|
||||
int lc = 0;
|
||||
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
||||
{
|
||||
// DOUT(QString::fromUtf16((LPWSTR)s->stack[6]));//"MS UI Gothic"
|
||||
@ -507,17 +534,21 @@ bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
||||
auto split = s->stack[0]; // retaddr
|
||||
|
||||
std::wstring str = ((LPWSTR)s->stack[7]);
|
||||
kp=0;lf=0;
|
||||
if (endWith(str,L"%K%P")){
|
||||
kp = 0;
|
||||
lf = 0;
|
||||
if (endWith(str, L"%K%P"))
|
||||
{
|
||||
kp = 1;
|
||||
|
||||
str = str.substr(0, str.size() - 4);
|
||||
}
|
||||
if(startWith(str,L"%LF")){
|
||||
if (startWith(str, L"%LF"))
|
||||
{
|
||||
lf = 1;
|
||||
str = str.substr(3);
|
||||
}
|
||||
if(startWith(str,L"%LC")){
|
||||
if (startWith(str, L"%LC"))
|
||||
{
|
||||
lc = 1;
|
||||
str = str.substr(3);
|
||||
}
|
||||
@ -530,35 +561,41 @@ bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
||||
write_string_overwrite(data, len, str);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
void hookafter(hook_stack*s,void* data, size_t len){
|
||||
void hookafter(hook_stack *s, void *data, size_t len)
|
||||
{
|
||||
auto data_ = std::wstring((wchar_t *)data, len / 2); // EngineController::instance()->dispatchTextWSTD(innner, Engine::ScenarioRole, 0);
|
||||
if (kp) {
|
||||
if (kp)
|
||||
{
|
||||
data_.append(L"%K%P");
|
||||
}
|
||||
if(lf){
|
||||
if (lf)
|
||||
{
|
||||
data_ = L"%LF" + data_;
|
||||
}if(lc){
|
||||
}
|
||||
if (lc)
|
||||
{
|
||||
data_ = L"%LC" + data_;
|
||||
}
|
||||
s->stack[7] = (ULONG)(data_.c_str());
|
||||
}
|
||||
}
|
||||
bool InsertWillPlus4Hook() {
|
||||
bool InsertWillPlus4Hook()
|
||||
{
|
||||
// 星の乙女と六華の姉妹
|
||||
const BYTE bytes[] = {
|
||||
0xc7, 0x45, 0xfc, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0xc9,
|
||||
0xc7,0x47,0x78,0x00,0x00,0x00,0x00
|
||||
};
|
||||
0xc7, 0x47, 0x78, 0x00, 0x00, 0x00, 0x00};
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||
|
||||
if (addr == 0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
|
||||
addr = MemDbg::findEnclosingFunctionBeforeDword(0x83dc8b53, addr, MemDbg::MaximumFunctionSize, 1);
|
||||
|
||||
if (addr == 0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.offset = get_stack(7);
|
||||
@ -569,15 +606,15 @@ bool InsertWillPlus4Hook() {
|
||||
hp.hook_after = will3::hookafter;
|
||||
return NewHook(hp, "EmbedWillplus3");
|
||||
}
|
||||
bool InsertWillPlus5Hook() {
|
||||
bool InsertWillPlus5Hook()
|
||||
{
|
||||
// ensemble 29th Project『乙女の剣と秘めごとコンチェルト』オフィシャルサイト 体验版
|
||||
|
||||
const BYTE bytes[] = {
|
||||
0x3d, XX2, 0x00, 0x00,
|
||||
0x72, XX,
|
||||
0x3d, XX2, 0x00, 0x00,
|
||||
0x77
|
||||
};
|
||||
0x77};
|
||||
/*if (v26 >= 0xE63E)
|
||||
{
|
||||
if (v26 <= 0xE757)*/
|
||||
@ -589,7 +626,8 @@ bool InsertWillPlus5Hook() {
|
||||
|
||||
bool ok = false;
|
||||
auto addrs = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStopAddress);
|
||||
for (auto addr : addrs) {
|
||||
for (auto addr : addrs)
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.offset = get_reg(regs::eax);
|
||||
@ -599,7 +637,8 @@ bool InsertWillPlus5Hook() {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
bool insertwillplus6(){
|
||||
bool insertwillplus6()
|
||||
{
|
||||
|
||||
/* 0x00492870
|
||||
0: 50 push eax
|
||||
@ -636,11 +675,11 @@ f: 6a 01 push 0x1
|
||||
0x8b, 0xd6,
|
||||
0xe8, XX4,
|
||||
0x83, 0xf8,
|
||||
0xff,0x75,0xdc
|
||||
};
|
||||
0xff, 0x75, 0xdc};
|
||||
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
addr += sizeof(bytes);
|
||||
ConsoleOutput("%p %p %p", addr, processStartAddress, processStopAddress);
|
||||
HookParam hp;
|
||||
@ -650,7 +689,8 @@ f: 6a 01 push 0x1
|
||||
ConsoleOutput("INSERT WillPlus6");
|
||||
return NewHook(hp, "WillPlus6");
|
||||
}
|
||||
bool willX(){
|
||||
bool willX()
|
||||
{
|
||||
// 世界でいちばんNGな恋
|
||||
// .text:0040EAE9 81 FE 94 81 00 00 cmp esi, 8194h
|
||||
// .text:0040EAEF 74 2C jz short loc_40EB1D
|
||||
@ -680,11 +720,11 @@ bool willX(){
|
||||
0x74, XX,
|
||||
0x81, 0xFE, 0x59, 0x81, 0x00, 0x00,
|
||||
0x74, XX,
|
||||
0x81,0xFE,0x96,0x81,0x00,0x00
|
||||
};
|
||||
0x81, 0xFE, 0x96, 0x81, 0x00, 0x00};
|
||||
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
auto succ = false;
|
||||
{
|
||||
HookParam hp;
|
||||
@ -707,12 +747,8 @@ bool willX(){
|
||||
return succ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace { // unnamed
|
||||
namespace
|
||||
{ // unnamed
|
||||
|
||||
// Sample prefix: %LF
|
||||
// Sample suffix: %L%P%W
|
||||
@ -720,21 +756,25 @@ template <typename strT>
|
||||
strT trim(strT text, int *size)
|
||||
{
|
||||
int length = *size;
|
||||
if (text[0] == '%') { // handle prefix
|
||||
if (text[0] == '%')
|
||||
{ // handle prefix
|
||||
int pos = 0;
|
||||
while (pos < length - 1 && text[pos] == '%' && ::isupper(text[pos+1])) {
|
||||
while (pos < length - 1 && text[pos] == '%' && ::isupper(text[pos + 1]))
|
||||
{
|
||||
pos += 2;
|
||||
while (::isupper(text[pos]))
|
||||
pos++;
|
||||
}
|
||||
if (pos) {
|
||||
if (pos)
|
||||
{
|
||||
length -= pos;
|
||||
text += pos;
|
||||
}
|
||||
}
|
||||
{ // handle suffix
|
||||
int pos = length;
|
||||
for (int i = length - 1; i >= 0; i--) {
|
||||
for (int i = length - 1; i >= 0; i--)
|
||||
{
|
||||
if (::isupper(text[i]))
|
||||
;
|
||||
else if (text[i] == '%' && ::isupper(text[i + 1]))
|
||||
@ -747,7 +787,8 @@ strT trim(strT text, int *size)
|
||||
*size = length;
|
||||
return text;
|
||||
}
|
||||
struct textinfo{
|
||||
struct textinfo
|
||||
{
|
||||
std::wstring text_;
|
||||
int stackIndex_;
|
||||
int role_;
|
||||
@ -762,7 +803,10 @@ namespace TextHookW
|
||||
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
||||
{
|
||||
auto info = savetyperef.at(idx);
|
||||
enum { sig = 0 };
|
||||
enum
|
||||
{
|
||||
sig = 0
|
||||
};
|
||||
auto text = (LPCWSTR)s->stack[info->stackIndex_];
|
||||
if (!text || !*text)
|
||||
return false;
|
||||
@ -776,10 +820,14 @@ namespace TextHookW
|
||||
return true;
|
||||
}
|
||||
template <int idx>
|
||||
void hookafter(hook_stack*s,void* data, size_t len){
|
||||
void hookafter(hook_stack *s, void *data, size_t len)
|
||||
{
|
||||
auto newText = std::wstring((LPWSTR)data, len / 2);
|
||||
auto info = savetyperef.at(idx);
|
||||
enum { sig = 0 };
|
||||
enum
|
||||
{
|
||||
sig = 0
|
||||
};
|
||||
auto text = (LPCWSTR)s->stack[info->stackIndex_];
|
||||
if (!text || !*text)
|
||||
return;
|
||||
@ -805,7 +853,8 @@ namespace TextHookW
|
||||
bool attach(const uint8_t *pattern, size_t patternSize, ULONG startAddress, ULONG stopAddress, int hookStackIndex, int role = Engine::UnknownRole)
|
||||
{
|
||||
ULONG addr = MemDbg::findBytes(pattern, patternSize, startAddress, stopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
auto _tinfo = new textinfo{};
|
||||
@ -958,7 +1007,6 @@ bool attachScenarioHookW2(ULONG startAddress, ULONG stopAddress)
|
||||
};
|
||||
int edi = get_reg(regs::edi) / 4;
|
||||
return TextHookW::attach<2>(bytes, sizeof(bytes), startAddress, stopAddress, edi, Engine::ScenarioRole);
|
||||
|
||||
}
|
||||
/**
|
||||
* Sample game: なついろレシピ
|
||||
@ -1028,7 +1076,6 @@ bool attachNameHookW(ULONG startAddress, ULONG stopAddress)
|
||||
|
||||
int ecx = get_reg(regs::ecx) / 4;
|
||||
return TextHookW::attach<3>(bytes, sizeof(bytes), startAddress, stopAddress, ecx, Engine::NameRole);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1096,12 +1143,13 @@ bool attachOtherHookW(ULONG startAddress, ULONG stopAddress)
|
||||
|
||||
int edx = get_reg(regs::edx) / 4;
|
||||
return TextHookW::attach<4>(bytes, sizeof(bytes), startAddress, stopAddress, edx, Engine::OtherRole);
|
||||
|
||||
}
|
||||
|
||||
namespace PatchA {
|
||||
namespace PatchA
|
||||
{
|
||||
|
||||
namespace Private {
|
||||
namespace Private
|
||||
{
|
||||
// The second argument is always 0 and not used
|
||||
bool isLeadByteChar(int ch, int)
|
||||
{
|
||||
@ -1181,7 +1229,8 @@ bool csmemcpy(void *dst, const void *src, size_t size)
|
||||
ulong replace_near_call(ulong addr, ulong val)
|
||||
{
|
||||
DWORD ret;
|
||||
switch (::disasm((LPCVOID)addr)) {
|
||||
switch (::disasm((LPCVOID)addr))
|
||||
{
|
||||
case 5: // near call / short jmp: relative address
|
||||
ret = *(DWORD *)(addr + 1) + (addr + 5);
|
||||
val -= addr + 5;
|
||||
@ -1195,7 +1244,8 @@ ulong replace_near_call(ulong addr, ulong val)
|
||||
*(DWORD *)(data + 1) = val - (addr + 5);
|
||||
return csmemcpy((LPVOID)addr, data, sizeof(data)) ? ret : 0;
|
||||
}
|
||||
default: return 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
@ -1205,7 +1255,10 @@ ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
0xff, 0x75, 0x08, // 00487fe1 ff75 08 push dword ptr ss:[ebp+0x8]
|
||||
0xe8, 0xaa, 0xff, 0xff, 0xff // 00487fe4 e8 aaffffff call .00487f93 ; jichi: called here
|
||||
};
|
||||
enum { addr_offset = 5 };
|
||||
enum
|
||||
{
|
||||
addr_offset = 5
|
||||
};
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||
|
||||
return addr; //&& replace_near_call(addr + addr_offset, (ULONG)Private::isLeadByteChar);
|
||||
@ -1213,9 +1266,11 @@ ULONG patchEncoding(ULONG startAddress, ULONG stopAddress)
|
||||
|
||||
} // namespace PatchA
|
||||
|
||||
namespace ScenarioHookA {
|
||||
namespace ScenarioHookA
|
||||
{
|
||||
|
||||
namespace Private {
|
||||
namespace Private
|
||||
{
|
||||
/*
|
||||
void dispatch(LPSTR text, int role)
|
||||
{
|
||||
@ -1244,7 +1299,10 @@ namespace Private {
|
||||
// dispatch(text - 1024, Engine::NameRole);
|
||||
// dispatch(text, Engine::ScenarioRole);
|
||||
|
||||
enum { sig = 0 };
|
||||
enum
|
||||
{
|
||||
sig = 0
|
||||
};
|
||||
if (!Engine::isAddressWritable(text) || !*text) // isAddressWritable is not needed for correct games
|
||||
return false;
|
||||
int size = ::strlen(text),
|
||||
@ -1263,7 +1321,8 @@ namespace Private {
|
||||
::strcpy(text, newData.c_str());
|
||||
return true;*/
|
||||
}
|
||||
void hookafter(hook_stack*s,void* data, size_t len){
|
||||
void hookafter(hook_stack *s, void *data, size_t len)
|
||||
{
|
||||
|
||||
auto newData = std::string((char *)data, len);
|
||||
auto text = (LPSTR)s->eax;
|
||||
@ -1510,7 +1569,8 @@ bool attach(ULONG startAddress, ULONG stopAddress)
|
||||
0x81, 0xec, 0x14, 0x08, 0x00, 0x00 // 0042B5E0 81EC 14080000 SUB ESP,0x814 ; jichi: text in eax, name in eax - 1024, able to copy
|
||||
};
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
|
||||
@ -1521,12 +1581,13 @@ bool attach(ULONG startAddress, ULONG stopAddress)
|
||||
hp.hook_font = F_GetGlyphOutlineA | F_TextOutA;
|
||||
static ULONG paddr = (PatchA::patchEncoding(startAddress, stopAddress));
|
||||
ConsoleOutput("%p", paddr);
|
||||
if(paddr){
|
||||
if (paddr)
|
||||
{
|
||||
hp.type |= EMBED_DYNA_SJIS;
|
||||
hp.hook_font = F_GetGlyphOutlineA | F_TextOutA;
|
||||
patch_fun=[](){
|
||||
patch_fun = []()
|
||||
{
|
||||
PatchA::replace_near_call(paddr + 5, (ULONG)PatchA::Private::isLeadByteChar);
|
||||
|
||||
};
|
||||
}
|
||||
return NewHook(hp, "EmbedWillplusA");
|
||||
@ -1534,9 +1595,11 @@ bool attach(ULONG startAddress, ULONG stopAddress)
|
||||
|
||||
} // namespace ScenarioHookA
|
||||
|
||||
namespace OtherHookA {
|
||||
namespace OtherHookA
|
||||
{
|
||||
|
||||
namespace Private {
|
||||
namespace Private
|
||||
{
|
||||
|
||||
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
||||
{
|
||||
@ -1563,7 +1626,8 @@ namespace Private {
|
||||
bool attach(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
ULONG addr = MemDbg::findCallerAddressAfterInt3((ULONG)::GetGlyphOutlineA, startAddress, stopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.hook_before = Private::hookBefore;
|
||||
@ -1577,21 +1641,23 @@ bool attach(ULONG startAddress, ULONG stopAddress)
|
||||
} // unnamed namespace
|
||||
|
||||
/** Public class */
|
||||
namespace WillPlusEngine{
|
||||
namespace WillPlusEngine
|
||||
{
|
||||
bool attach()
|
||||
{
|
||||
ULONG startAddress = processStartAddress, stopAddress = processStopAddress;
|
||||
|
||||
|
||||
if (::attachScenarioHookW1(startAddress, stopAddress) || ::attachScenarioHookW2(startAddress, stopAddress)) {
|
||||
if (::attachScenarioHookW1(startAddress, stopAddress) || ::attachScenarioHookW2(startAddress, stopAddress))
|
||||
{
|
||||
|
||||
(::attachNameHookW(startAddress, stopAddress));
|
||||
|
||||
(::attachOtherHookW(startAddress, stopAddress));
|
||||
|
||||
return true;
|
||||
|
||||
} else if (ScenarioHookA::attach(startAddress, stopAddress)) { // try widechar pattern first, which is more unique
|
||||
}
|
||||
else if (ScenarioHookA::attach(startAddress, stopAddress))
|
||||
{ // try widechar pattern first, which is more unique
|
||||
|
||||
(OtherHookA::attach(startAddress, stopAddress));
|
||||
// HijackManager::instance()->attachFunction((ULONG)::GetGlyphOutlineA);
|
||||
@ -1603,7 +1669,8 @@ bool attach()
|
||||
}
|
||||
}
|
||||
|
||||
namespace{
|
||||
namespace
|
||||
{
|
||||
|
||||
static bool InsertWillPlus4()
|
||||
{
|
||||
@ -1620,7 +1687,8 @@ static bool InsertWillPlus4()
|
||||
};
|
||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||||
if (!addr) {
|
||||
if (!addr)
|
||||
{
|
||||
ConsoleOutput("WillPlus4: pattern not found");
|
||||
return false;
|
||||
}
|
||||
@ -1651,7 +1719,8 @@ static bool InsertWillPlus5()
|
||||
};
|
||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||||
if (!addr) {
|
||||
if (!addr)
|
||||
{
|
||||
ConsoleOutput("WillPlus5: pattern not found");
|
||||
return false;
|
||||
}
|
||||
@ -1669,7 +1738,8 @@ static bool InsertWillPlus5()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _xxx(){
|
||||
bool _xxx()
|
||||
{
|
||||
bool ok = false;
|
||||
ok = InsertWillPlus4() || ok;
|
||||
ok = InsertWillPlus5() || ok;
|
||||
@ -1677,7 +1747,8 @@ bool ok=false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WillPlus::attach_function() {
|
||||
bool WillPlus::attach_function()
|
||||
{
|
||||
bool succ = WillPlusEngine::attach();
|
||||
succ |= InsertWillPlusHook();
|
||||
succ |= InsertWillPlus4Hook();
|
||||
@ -1689,17 +1760,19 @@ bool WillPlus::attach_function() {
|
||||
return succ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool Willold::attach_function() {
|
||||
bool Willold::attach_function()
|
||||
{
|
||||
// https://vndb.org/v17755
|
||||
// 凌辱鬼
|
||||
auto addr = MemDbg::findLongJumpAddress((ULONG)TextOutA, processStartAddress, processStopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
addr = MemDbg::findNearCallAddress(addr, processStartAddress, processStopAddress);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
addr = findfuncstart(addr, 0x200);
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.type = USING_CHAR | CODEC_ANSI_BE;
|
||||
|
Loading…
Reference in New Issue
Block a user