mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-10-22 23:18:16 +08:00
Update BGI.cpp
This commit is contained in:
parent
7b61703dcb
commit
ed299f7b20
@ -1,4 +1,4 @@
|
||||
#include"BGI.h"
|
||||
#include "BGI.h"
|
||||
/********************************************************************************************
|
||||
BGI hook:
|
||||
Usually game folder contains BGI.*. After first run BGI.gdb appears.
|
||||
@ -9,7 +9,8 @@ BGI hook:
|
||||
After 2 tries we will get to the right place. Use ESP value to split text since
|
||||
it's likely to be different for different calls.
|
||||
********************************************************************************************/
|
||||
namespace { // unnamed
|
||||
namespace
|
||||
{ // unnamed
|
||||
#if 0 // jichi 12/28/2013: dynamic BGI is not used
|
||||
static bool FindBGIHook(DWORD fun, DWORD size, DWORD pt, WORD sig)
|
||||
{
|
||||
@ -63,7 +64,7 @@ bool InsertBGIDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
||||
}
|
||||
#endif // 0
|
||||
|
||||
/** jichi 5/12/2014
|
||||
/** jichi 5/12/2014
|
||||
* Sample game: FORTUNE ARTERIAL, case 2 at 0x41ebd0
|
||||
*
|
||||
* sub_41EBD0 proc near, seems to take 5 parameters
|
||||
@ -125,56 +126,64 @@ bool InsertBGIDynamicHook(LPVOID addr, DWORD frame, DWORD stack)
|
||||
* 0041ec7b |. 56 push esi
|
||||
* 0041ec7c |. e8 1fa0feff call bgi.00408ca0
|
||||
*/
|
||||
bool InsertBGI1Hook()
|
||||
{
|
||||
union {
|
||||
bool InsertBGI1Hook()
|
||||
{
|
||||
union
|
||||
{
|
||||
DWORD i;
|
||||
DWORD *id;
|
||||
BYTE *ib;
|
||||
};
|
||||
HookParam hp;
|
||||
for (i = processStartAddress + 0x1000; i < processStopAddress; i++) {
|
||||
if (ib[0] == 0x3d) {
|
||||
for (i = processStartAddress + 0x1000; i < processStopAddress; i++)
|
||||
{
|
||||
if (ib[0] == 0x3d)
|
||||
{
|
||||
i++;
|
||||
if (id[0] == 0xffff) { //cmp eax,0xffff
|
||||
if (id[0] == 0xffff)
|
||||
{ // cmp eax,0xffff
|
||||
hp.address = SafeFindEnclosingAlignedFunction(i, 0x40);
|
||||
if (hp.address) {
|
||||
hp.offset=get_stack(3);
|
||||
if (hp.address)
|
||||
{
|
||||
hp.offset = get_stack(3);
|
||||
hp.split = get_reg(regs::esp);
|
||||
hp.type = CODEC_ANSI_BE|USING_SPLIT;
|
||||
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
||||
ConsoleOutput("INSERT BGI#1");
|
||||
|
||||
//RegisterEngineType(ENGINE_BGI);
|
||||
// RegisterEngineType(ENGINE_BGI);
|
||||
return NewHook(hp, "BGI");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ib[0] == 0x81 && ((ib[1] & 0xf8) == 0xf8)) {
|
||||
if (ib[0] == 0x81 && ((ib[1] & 0xf8) == 0xf8))
|
||||
{
|
||||
i += 2;
|
||||
if (id[0] == 0xffff) { //cmp reg,0xffff
|
||||
if (id[0] == 0xffff)
|
||||
{ // cmp reg,0xffff
|
||||
hp.address = SafeFindEnclosingAlignedFunction(i, 0x40);
|
||||
if (hp.address) {
|
||||
hp.offset=get_stack(3);
|
||||
if (hp.address)
|
||||
{
|
||||
hp.offset = get_stack(3);
|
||||
hp.split = get_reg(regs::esp);
|
||||
hp.type = CODEC_ANSI_BE|USING_SPLIT;
|
||||
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
||||
ConsoleOutput("INSERT BGI#2");
|
||||
|
||||
//RegisterEngineType(ENGINE_BGI);
|
||||
// RegisterEngineType(ENGINE_BGI);
|
||||
return NewHook(hp, "BGI");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//ConsoleOutput("Unknown BGI engine.");
|
||||
// ConsoleOutput("Unknown BGI engine.");
|
||||
|
||||
//ConsoleOutput("Probably BGI. Wait for text.");
|
||||
//SwitchTrigger(true);
|
||||
//trigger_fun=InsertBGIDynamicHook;
|
||||
// ConsoleOutput("Probably BGI. Wait for text.");
|
||||
// SwitchTrigger(true);
|
||||
// trigger_fun=InsertBGIDynamicHook;
|
||||
ConsoleOutput("BGI: failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* jichi 2/5/2014: Add an alternative BGI hook
|
||||
*
|
||||
* Issue: This hook cannot extract character name for コトバの消えた日
|
||||
@ -511,32 +520,40 @@ bool InsertBGI1Hook()
|
||||
* 00A643D0 B9 01000000 MOV ECX,0x1
|
||||
* ...
|
||||
*/
|
||||
//static inline size_t _bgistrlen(LPCSTR text)
|
||||
//{
|
||||
// size_t r = ::strlen(text);
|
||||
// if (r >=2 && *(WORD *)(text + r - 2) == 0xa581) // remove trailing ▼ = \x81\xa5
|
||||
// r -= 2;
|
||||
// return r;
|
||||
//}
|
||||
//
|
||||
//static void SpecialHookBGI2(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||||
//{
|
||||
// LPCSTR text = (LPCSTR)*(DWORD *)(esp_base + hp->offset);
|
||||
// if (text) {
|
||||
// *data = (DWORD)text;
|
||||
// *len = _bgistrlen(text);
|
||||
// }
|
||||
//}
|
||||
namespace Private {
|
||||
enum { Type1 = 1, Type2, Type3,Type_BGI3 } type_;
|
||||
int textIndex_; // the i-th of argument on the stack holding the text
|
||||
bool hookBefore(hook_stack*s,void* data, size_t* len,uintptr_t*role)
|
||||
// static inline size_t _bgistrlen(LPCSTR text)
|
||||
//{
|
||||
// size_t r = ::strlen(text);
|
||||
// if (r >=2 && *(WORD *)(text + r - 2) == 0xa581) // remove trailing ▼ = \x81\xa5
|
||||
// r -= 2;
|
||||
// return r;
|
||||
// }
|
||||
//
|
||||
// static void SpecialHookBGI2(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||||
//{
|
||||
// LPCSTR text = (LPCSTR)*(DWORD *)(esp_base + hp->offset);
|
||||
// if (text) {
|
||||
// *data = (DWORD)text;
|
||||
// *len = _bgistrlen(text);
|
||||
// }
|
||||
// }
|
||||
namespace Private
|
||||
{
|
||||
enum
|
||||
{
|
||||
Type1 = 1,
|
||||
Type2,
|
||||
Type3,
|
||||
Type_BGI3
|
||||
} type_;
|
||||
int textIndex_; // the i-th of argument on the stack holding the text
|
||||
bool hookBefore(hook_stack *s, void *data, size_t *len, uintptr_t *role)
|
||||
{
|
||||
if (type_ == Type_BGI3)
|
||||
{
|
||||
if (type_ == Type_BGI3) {
|
||||
|
||||
DWORD retaddr = s->stack[0]; // retaddr
|
||||
* role = Engine::ScenarioRole;
|
||||
return write_string_overwrite(data,len,(LPCSTR)s->stack[textIndex_]);
|
||||
*role = Engine::ScenarioRole;
|
||||
return write_string_overwrite(data, len, (LPCSTR)s->stack[textIndex_]);
|
||||
}
|
||||
|
||||
static std::string data_; // persistent storage, which makes this function not thread-safe
|
||||
@ -546,18 +563,20 @@ namespace Private {
|
||||
return false;
|
||||
// In Type 1, split = arg8
|
||||
// In Type 2, there is no arg8. However, arg8 seems to be a good split that can differenciate choice and character name
|
||||
//DWORD split = stack->args[3]; // arg4
|
||||
//DWORD split = s->stack[8]; // arg8
|
||||
//auto sig = Engine::hashThreadSignature(s->stack[0], split);
|
||||
//enum { role = Engine::UnknownRole };
|
||||
// DWORD split = stack->args[3]; // arg4
|
||||
// DWORD split = s->stack[8]; // arg8
|
||||
// auto sig = Engine::hashThreadSignature(s->stack[0], split);
|
||||
// enum { role = Engine::UnknownRole };
|
||||
|
||||
//DWORD split = s->stack[8]; // this is a good split, but usually game-specific
|
||||
// DWORD split = s->stack[8]; // this is a good split, but usually game-specific
|
||||
DWORD retaddr = s->stack[0]; // retaddr
|
||||
//* role = Engine::OtherRole;
|
||||
switch (type_) {
|
||||
switch (type_)
|
||||
{
|
||||
|
||||
case Type3:
|
||||
switch (s->stack[textIndex_+1]) {
|
||||
switch (s->stack[textIndex_ + 1])
|
||||
{
|
||||
case 1:
|
||||
if (*(WORD *)(retaddr + 8) == 0xcccc) // two int3
|
||||
*role = Engine::ScenarioRole;
|
||||
@ -567,9 +586,11 @@ namespace Private {
|
||||
s->stack[10] == 0 && s->stack[10 - 1] == 0 && s->stack[10 - 2] == 0) // for new BGI2 games
|
||||
*role = Engine::NameRole;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case Type2:
|
||||
switch (s->stack[textIndex_+1]) {
|
||||
switch (s->stack[textIndex_ + 1])
|
||||
{
|
||||
case 1:
|
||||
// Return address for history text
|
||||
// 012B37BA 83C4 34 ADD ESP,0x34
|
||||
@ -581,20 +602,25 @@ namespace Private {
|
||||
if (s->stack[12] == 0x00ffffff && s->stack[12 - 3] == 2)
|
||||
*role = Engine::NameRole;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
break;
|
||||
case Type1:
|
||||
switch (s->stack[textIndex_+1]) {
|
||||
case 1: *role = Engine::ScenarioRole; break;
|
||||
switch (s->stack[textIndex_ + 1])
|
||||
{
|
||||
case 1:
|
||||
*role = Engine::ScenarioRole;
|
||||
break;
|
||||
case 0:
|
||||
if (s->stack[12] == 0x00ffffff && s->stack[12 - 3] == 1)
|
||||
*role = Engine::NameRole;
|
||||
break;
|
||||
} break;
|
||||
}
|
||||
return write_string_overwrite(data,len,(LPCSTR)s->stack[textIndex_]);
|
||||
break;
|
||||
}
|
||||
return write_string_overwrite(data, len, (LPCSTR)s->stack[textIndex_]);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 5/12/2014
|
||||
@ -705,8 +731,8 @@ namespace Private {
|
||||
*/
|
||||
ULONG search1(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
//return 0x4207e0; // FORTUNE ARTERIAL
|
||||
//const BYTE bytes[] = {
|
||||
// return 0x4207e0; // FORTUNE ARTERIAL
|
||||
// const BYTE bytes[] = {
|
||||
// 0x8a,0x45, 0x00, // 00420822 |. 8a45 00 mov al,byte ptr ss:[ebp]
|
||||
// 0x3c, 0x20, // 00420825 |. 3c 20 cmp al,0x20
|
||||
// 0x7d, 0x69, // 00420827 |. 7d 69 jge short bgi.00420892
|
||||
@ -714,31 +740,35 @@ namespace Private {
|
||||
// 0x83,0xc0, 0xfe, // 0042082c |. 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
// 0x83,0xf8, 0x06, // 0042082f |. 83f8 06 cmp eax,0x6
|
||||
// 0x77, 0x5e // 00420832 |. 77 5e ja short bgi.00420892
|
||||
//};
|
||||
//enum { hook_offset = 0x4207e0 - 0x420822 }; // distance to the beginning of the function
|
||||
// };
|
||||
// enum { hook_offset = 0x4207e0 - 0x420822 }; // distance to the beginning of the function
|
||||
|
||||
const uint8_t bytes[] = { // 0fafcbf7e9c1fa058bc2c1e81f03d08bfa85ff
|
||||
0x0f,0xaf,0xcb, // 004208de |. 0fafcb imul ecx,ebx
|
||||
0xf7,0xe9, // 004208e1 |. f7e9 imul ecx
|
||||
0xc1,0xfa, 0x05, // 004208e3 |. c1fa 05 sar edx,0x5
|
||||
0x8b,0xc2, // 004208e6 |. 8bc2 mov eax,edx
|
||||
0xc1,0xe8, 0x1f, // 004208e8 |. c1e8 1f shr eax,0x1f
|
||||
0x03,0xd0, // 004208eb |. 03d0 add edx,eax
|
||||
0x8b,0xfa, // 004208ed |. 8bfa mov edi,edx
|
||||
0x85,0xff, // 004208ef |. 85ff test edi,edi
|
||||
const uint8_t bytes[] = {
|
||||
// 0fafcbf7e9c1fa058bc2c1e81f03d08bfa85ff
|
||||
0x0f, 0xaf, 0xcb, // 004208de |. 0fafcb imul ecx,ebx
|
||||
0xf7, 0xe9, // 004208e1 |. f7e9 imul ecx
|
||||
0xc1, 0xfa, 0x05, // 004208e3 |. c1fa 05 sar edx,0x5
|
||||
0x8b, 0xc2, // 004208e6 |. 8bc2 mov eax,edx
|
||||
0xc1, 0xe8, 0x1f, // 004208e8 |. c1e8 1f shr eax,0x1f
|
||||
0x03, 0xd0, // 004208eb |. 03d0 add edx,eax
|
||||
0x8b, 0xfa, // 004208ed |. 8bfa mov edi,edx
|
||||
0x85, 0xff, // 004208ef |. 85ff test edi,edi
|
||||
};
|
||||
//enum { hook_offset = 0x4207e0 - 0x4208de }; // distance to the beginning of the function
|
||||
//ULONG range = qMin(stopAddress - startAddress, Engine::MaximumMemoryRange);
|
||||
// enum { hook_offset = 0x4207e0 - 0x4208de }; // distance to the beginning of the function
|
||||
// ULONG range = qMin(stopAddress - startAddress, Engine::MaximumMemoryRange);
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||
if (!addr)
|
||||
//ConsoleOutput("BGI2: pattern not found");
|
||||
// ConsoleOutput("BGI2: pattern not found");
|
||||
return 0;
|
||||
enum : WORD {
|
||||
enum : WORD
|
||||
{
|
||||
sub_esp = 0xec81 // 004207e0 /$ 81ec 30090000
|
||||
, push_ff = 0xff6a // 00427450 /$ 6a ff push -0x1, seh handler
|
||||
,
|
||||
push_ff = 0xff6a // 00427450 /$ 6a ff push -0x1, seh handler
|
||||
};
|
||||
for (int i = 0; i < 300; i++, addr--)
|
||||
if (*(WORD *)addr == sub_esp) { // beginning of the function without seh
|
||||
if (*(WORD *)addr == sub_esp)
|
||||
{ // beginning of the function without seh
|
||||
|
||||
// Sample game: 世界征服彼女 with SEH
|
||||
// 00427450 /$ 6a ff push -0x1
|
||||
@ -838,26 +868,33 @@ namespace Private {
|
||||
*/
|
||||
ULONG search2(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
//return startAddress + 0x31850; // 世界と世界の真ん中 体験版
|
||||
const uint8_t bytes[] = { // 3c207d750fbec083c0fe83f806776a
|
||||
// return startAddress + 0x31850; // 世界と世界の真ん中 体験版
|
||||
const uint8_t bytes[] = {
|
||||
// 3c207d750fbec083c0fe83f806776a
|
||||
0x3c, 0x20, // 011d4d31 |. 3c 20 cmp al,0x20
|
||||
0x7d, 0x75, // 011d4d33 |. 7d 75 jge short sekachu.011d4daa
|
||||
0x0f,0xbe,0xc0, // 011d4d35 |. 0fbec0 movsx eax,al
|
||||
0x83,0xc0, 0xfe, // 011d4d38 |. 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
0x83,0xf8, 0x06, // 011d4d3b |. 83f8 06 cmp eax,0x6
|
||||
0x0f, 0xbe, 0xc0, // 011d4d35 |. 0fbec0 movsx eax,al
|
||||
0x83, 0xc0, 0xfe, // 011d4d38 |. 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
0x83, 0xf8, 0x06, // 011d4d3b |. 83f8 06 cmp eax,0x6
|
||||
0x77, 0x6a // 011d4d3e |. 77 6a ja short sekachu.011d4daa
|
||||
};
|
||||
enum { hook_offset = 0x34c80 - 0x34d31 }; // distance to the beginning of the function
|
||||
//ULONG range = qMin(stopAddress - startAddress, Engine::MaximumMemoryRange);
|
||||
enum
|
||||
{
|
||||
hook_offset = 0x34c80 - 0x34d31
|
||||
}; // distance to the beginning of the function
|
||||
// ULONG range = qMin(stopAddress - startAddress, Engine::MaximumMemoryRange);
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||
if (!addr)
|
||||
//ConsoleOutput("BGI2: pattern not found");
|
||||
// ConsoleOutput("BGI2: pattern not found");
|
||||
return 0;
|
||||
|
||||
addr += hook_offset;
|
||||
enum : uint8_t { push_ebp = 0x55 }; // 011d4c80 /$ 55 push ebp
|
||||
enum : uint8_t
|
||||
{
|
||||
push_ebp = 0x55
|
||||
}; // 011d4c80 /$ 55 push ebp
|
||||
if (*(uint8_t *)addr != push_ebp)
|
||||
//ConsoleOutput("BGI2: pattern found but the function offset is invalid");
|
||||
// ConsoleOutput("BGI2: pattern found but the function offset is invalid");
|
||||
return 0;
|
||||
|
||||
return addr;
|
||||
@ -1016,15 +1053,16 @@ namespace Private {
|
||||
* 01312ed8 . 33f6 xor esi,esi
|
||||
* 01312eda . 83c4 04 add esp,0x4
|
||||
*/
|
||||
ULONG search3(ULONG startAddress, ULONG stopAddress)
|
||||
ULONG search3(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
//return startAddress + 0x31850; // 世界と世界の真ん中 体験版
|
||||
const uint8_t bytes[] = { // 3c207d580fbec083c0fe83f806774d
|
||||
// return startAddress + 0x31850; // 世界と世界の真ん中 体験版
|
||||
const uint8_t bytes[] = {
|
||||
// 3c207d580fbec083c0fe83f806774d
|
||||
0x3c, 0x20, // 01312d8e 3c 20 cmp al,0x20 ; jichi: pattern starts
|
||||
0x7d, 0x58, // 01312d90 7d 58 jge short 蒼の彼方.01312dea
|
||||
0x0f,0xbe,0xc0, // 01312d92 0fbec0 movsx eax,al
|
||||
0x83,0xc0, 0xfe, // 01312d95 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
0x83,0xf8, 0x06, // 01312d98 83f8 06 cmp eax,0x6
|
||||
0x0f, 0xbe, 0xc0, // 01312d92 0fbec0 movsx eax,al
|
||||
0x83, 0xc0, 0xfe, // 01312d95 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
0x83, 0xf8, 0x06, // 01312d98 83f8 06 cmp eax,0x6
|
||||
0x77, 0x4d // 01312d9b 77 4d ja short 蒼の彼方.01312dea
|
||||
};
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, stopAddress);
|
||||
@ -1034,22 +1072,30 @@ ULONG search3(ULONG startAddress, ULONG stopAddress)
|
||||
// distance to the beginning of the function
|
||||
static const int hook_offsets[] = {
|
||||
0x01312cd0 - 0x01312d8e // for new BGI2 game since 蒼の彼方 (2014/08), text is in arg2
|
||||
, 0x00a64260 - 0x00a64318 // For newer BGI2 game since コドモノアソビ (2015/11)
|
||||
,
|
||||
0x00a64260 - 0x00a64318 // For newer BGI2 game since コドモノアソビ (2015/11)
|
||||
};
|
||||
enum
|
||||
{
|
||||
hook_offset_count = sizeof(hook_offsets) / sizeof(*hook_offsets)
|
||||
};
|
||||
enum { hook_offset_count = sizeof(hook_offsets) / sizeof(*hook_offsets) };
|
||||
|
||||
for (size_t i = 0; i < hook_offset_count; i++) {
|
||||
for (size_t i = 0; i < hook_offset_count; i++)
|
||||
{
|
||||
int hook_offset = hook_offsets[i];
|
||||
|
||||
enum : uint8_t { push_ebp = 0x55 }; // 011d4c80 /$ 55 push ebp
|
||||
enum : uint8_t
|
||||
{
|
||||
push_ebp = 0x55
|
||||
}; // 011d4c80 /$ 55 push ebp
|
||||
if (*(uint8_t *)(addr + hook_offset) == push_ebp)
|
||||
return addr + hook_offset;
|
||||
}
|
||||
return 0; // failed
|
||||
}
|
||||
ULONG search_bgi3(ULONG startAddress, ULONG stopAddress )
|
||||
ULONG search_bgi3(ULONG startAddress, ULONG stopAddress)
|
||||
{
|
||||
//黄昏のフォルクローレ
|
||||
// 黄昏のフォルクローレ
|
||||
/* .text:00C3A700 push ebp
|
||||
.text : 00C3A701 mov ebp, esp
|
||||
.text : 00C3A703 push[ebp + arg_30]
|
||||
@ -1084,47 +1130,53 @@ ULONG search_bgi3(ULONG startAddress, ULONG stopAddress )
|
||||
*/
|
||||
const uint8_t bytes[] = {
|
||||
0x55,
|
||||
0x8b,0xec,
|
||||
0xff,0x75,0x38,
|
||||
0x8b,0x55,0x0c,
|
||||
0xff,0x75,0x34,
|
||||
0x8b,0x4d,0x08,
|
||||
0xff,0x75,0x30
|
||||
};
|
||||
0x8b, 0xec,
|
||||
0xff, 0x75, 0x38,
|
||||
0x8b, 0x55, 0x0c,
|
||||
0xff, 0x75, 0x34,
|
||||
0x8b, 0x4d, 0x08,
|
||||
0xff, 0x75, 0x30};
|
||||
ULONG range = min(ULONG(stopAddress - startAddress), ULONG(0x00300000));
|
||||
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), startAddress, startAddress + range);
|
||||
if (addr == 0)return 0;
|
||||
if (addr == 0)
|
||||
return 0;
|
||||
return addr;
|
||||
}
|
||||
bool search_tayutama(DWORD *funaddr,DWORD *addr){
|
||||
bool search_tayutama(DWORD *funaddr, DWORD *addr)
|
||||
{
|
||||
const BYTE bytes[] = {
|
||||
// The following code does not exist in newer BGI games after BGI 1.633.0.0 (tayutama2_trial_EX)
|
||||
//0x3c, 0x20, // 011d4d31 |. 3c 20 cmp al,0x20
|
||||
//0x7d, XX, // 011d4d33 |. 7d 75 jge short sekachu.011d4daa ; jichi: 0x75 or 0x58
|
||||
0x0f,0xbe,0xc0, // 011d4d35 |. 0fbec0 movsx eax,al
|
||||
0x83,0xc0, 0xfe, // 011d4d38 |. 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
0x83,0xf8//, 0x06 // 011d4d3b |. 83f8 06 cmp eax,0x6
|
||||
// 0x3c, 0x20, // 011d4d31 |. 3c 20 cmp al,0x20
|
||||
// 0x7d, XX, // 011d4d33 |. 7d 75 jge short sekachu.011d4daa ; jichi: 0x75 or 0x58
|
||||
0x0f, 0xbe, 0xc0, // 011d4d35 |. 0fbec0 movsx eax,al
|
||||
0x83, 0xc0, 0xfe, // 011d4d38 |. 83c0 fe add eax,-0x2 ; switch (cases 2..8)
|
||||
0x83, 0xf8 //, 0x06 // 011d4d3b |. 83f8 06 cmp eax,0x6
|
||||
// The following code does not exist in newer BGI games after 蒼の彼方
|
||||
//0x77, 0x6a // 011d4d3e |. 77 6a ja short sekachu.011d4daa
|
||||
// 0x77, 0x6a // 011d4d3e |. 77 6a ja short sekachu.011d4daa
|
||||
};
|
||||
|
||||
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
||||
* addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||||
//GROWL_DWORD(reladdr);
|
||||
if (!*addr) {
|
||||
*addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
||||
// GROWL_DWORD(reladdr);
|
||||
if (!*addr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
* funaddr = MemDbg::findEnclosingAlignedFunction(*addr, 0x300); // range is around 177 ~ 190
|
||||
*funaddr = MemDbg::findEnclosingAlignedFunction(*addr, 0x300); // range is around 177 ~ 190
|
||||
|
||||
enum : BYTE { push_ebp = 0x55 }; // 011d4c80 /$ 55 push ebp
|
||||
if (!*funaddr || *(BYTE *)*funaddr != push_ebp) {
|
||||
enum : BYTE
|
||||
{
|
||||
push_ebp = 0x55
|
||||
}; // 011d4c80 /$ 55 push ebp
|
||||
if (!*funaddr || *(BYTE *)*funaddr != push_ebp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool InsertBGI2Hook()
|
||||
{
|
||||
}
|
||||
bool InsertBGI2Hook()
|
||||
{
|
||||
|
||||
/* Artikash 6/14/2019: Ugh, what a mess I've dug up...
|
||||
At some point the beginning four bytes to search for were removed, but the difference below were not corrected? Or maybe they were?
|
||||
@ -1134,20 +1186,24 @@ bool InsertBGI2Hook()
|
||||
I think the safest option is to just add the new? difference as a case that detects offset=arg3 since either way one case will detect offset=arg3 correctly.
|
||||
And all the other cases fall through to offset=arg2.
|
||||
*/
|
||||
ULONG addr , funaddr;HookParam hp;
|
||||
hp.hook_font=F_TextOutA|F_TextOutW;
|
||||
if (addr=search_bgi3(processStartAddress, processStopAddress)){
|
||||
//有乱码,无法处理。
|
||||
ULONG addr, funaddr;
|
||||
HookParam hp;
|
||||
hp.hook_font = F_TextOutA | F_TextOutW;
|
||||
if (addr = search_bgi3(processStartAddress, processStopAddress))
|
||||
{
|
||||
// 有乱码,无法处理。
|
||||
Private::textIndex_ = 3;
|
||||
hp.offset=get_stack(Private::textIndex_);
|
||||
hp.offset = get_stack(Private::textIndex_);
|
||||
Private::type_ = Private::Type_BGI3;
|
||||
hp.hook_font|=F_GetTextExtentPoint32W;
|
||||
if(addr-processStartAddress==0x3B860)//[220729][1171051][きゃべつそふと] ジュエリー・ハーツ・アカデミア -We will wing wonder world-,无法处理的乱码,不知道怎么回事。
|
||||
addr=0;
|
||||
hp.hook_font |= F_GetTextExtentPoint32W;
|
||||
if (addr - processStartAddress == 0x3B860) //[220729][1171051][きゃべつそふと] ジュエリー・ハーツ・アカデミア -We will wing wonder world-,无法处理的乱码,不知道怎么回事。
|
||||
addr = 0;
|
||||
}
|
||||
else if ( search_tayutama(&funaddr,&addr)) {
|
||||
else if (search_tayutama(&funaddr, &addr))
|
||||
{
|
||||
|
||||
switch (funaddr - addr) {
|
||||
switch (funaddr - addr)
|
||||
{
|
||||
// for old BGI2 game, text is arg3
|
||||
case 0x34c80 - 0x34d31: // old offset
|
||||
case 0x34c50 - 0x34d05: // correction as mentioned above
|
||||
@ -1174,44 +1230,48 @@ bool InsertBGI2Hook()
|
||||
Private::type_ = Private::Type3;
|
||||
addr = funaddr;
|
||||
}
|
||||
else if (addr =search3(processStartAddress, processStopAddress)) {
|
||||
else if (addr = search3(processStartAddress, processStopAddress))
|
||||
{
|
||||
Private::type_ = Private::Type3;
|
||||
Private::textIndex_ = 2; // use arg2, name = "BGI2";
|
||||
}else if (addr = search2(processStartAddress, processStopAddress)) {
|
||||
}
|
||||
else if (addr = search2(processStartAddress, processStopAddress))
|
||||
{
|
||||
Private::type_ = Private::Type2;
|
||||
Private::textIndex_ = 3; // use arg3, name = "BGI2";
|
||||
} else if (addr =search1(processStartAddress, processStopAddress)) {
|
||||
}
|
||||
else if (addr = search1(processStartAddress, processStopAddress))
|
||||
{
|
||||
Private::type_ = Private::Type1;
|
||||
Private::textIndex_ = 3; // use arg3, name = "BGI";
|
||||
}
|
||||
if(addr==0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
hp.address = addr;
|
||||
hp.offset=get_stack(Private::textIndex_);
|
||||
hp.offset = get_stack(Private::textIndex_);
|
||||
// jichi 5/12/2014: Using split could distinguish name and choices. But the signature might become unstable
|
||||
hp.type = USING_STRING|USING_SPLIT|EMBED_ABLE|EMBED_DYNA_SJIS|EMBED_AFTER_NEW;
|
||||
hp.type = USING_STRING | USING_SPLIT | EMBED_ABLE | EMBED_DYNA_SJIS | EMBED_AFTER_NEW;
|
||||
|
||||
hp.hook_before=Private::hookBefore;
|
||||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||||
hp.hook_before = Private::hookBefore;
|
||||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
// It could be either <R..> or <r..>
|
||||
static const std::regex rx("<r.+?>(.+?)</r>", std::regex_constants::icase);
|
||||
std::string result = std::string((char*)data,*len);
|
||||
std::string result = std::string((char *)data, *len);
|
||||
result = std::regex_replace(result, rx, "$1");
|
||||
|
||||
return write_string_overwrite(data,len,result);
|
||||
} ;
|
||||
return write_string_overwrite(data, len, result);
|
||||
};
|
||||
|
||||
hp.split = get_stack(8); // pseudo arg8
|
||||
|
||||
//GROWL_DWORD2(hp.address, processStartAddress);
|
||||
|
||||
|
||||
|
||||
// GROWL_DWORD2(hp.address, processStartAddress);
|
||||
|
||||
return NewHook(hp, "EmbedBGI");
|
||||
}
|
||||
}
|
||||
|
||||
bool InsertBGI3Hook()
|
||||
{
|
||||
bool InsertBGI3Hook()
|
||||
{
|
||||
/*
|
||||
* Sample games:
|
||||
* https://vndb.org/v28283
|
||||
@ -1223,24 +1283,25 @@ bool InsertBGI3Hook()
|
||||
bool found = false;
|
||||
const BYTE pattern[] = {
|
||||
0x55, // 55 push ebp
|
||||
0x8b,0xec, // 8BEC mov ebp,esp
|
||||
0x83,0xe4, 0xf8, // 83E4 F8 and esp,FFFFFFF8
|
||||
0x81,0xec, 0x84,0x00,0x00,0x00 // 81EC 84000000 sub esp,0x84
|
||||
0x8b, 0xec, // 8BEC mov ebp,esp
|
||||
0x83, 0xe4, 0xf8, // 83E4 F8 and esp,FFFFFFF8
|
||||
0x81, 0xec, 0x84, 0x00, 0x00, 0x00 // 81EC 84000000 sub esp,0x84
|
||||
};
|
||||
|
||||
for (auto addr : Util::SearchMemory(pattern, sizeof(pattern), PAGE_EXECUTE, processStartAddress, processStopAddress))
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.offset=get_stack(2);
|
||||
hp.split =get_stack(1);
|
||||
hp.offset = get_stack(2);
|
||||
hp.split = get_stack(1);
|
||||
hp.type = CODEC_UTF16 | USING_SPLIT;
|
||||
ConsoleOutput("INSERT BGI3");
|
||||
found|=NewHook(hp, "BGI3");
|
||||
found |= NewHook(hp, "BGI3");
|
||||
}
|
||||
if (!found) ConsoleOutput("BGI3: pattern not found");
|
||||
if (!found)
|
||||
ConsoleOutput("BGI3: pattern not found");
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
@ -1338,20 +1399,32 @@ bool BGI7Filter(LPVOID data, size_t *size, HookParam *)
|
||||
{
|
||||
auto text = reinterpret_cast<LPWSTR>(data);
|
||||
auto len = reinterpret_cast<size_t *>(size);
|
||||
|
||||
// BGI4 split不管用,所以只好手动过滤掉了
|
||||
auto ws = std::wstring(text, *len / 2);
|
||||
if (endWith(ws, L".bs5"))
|
||||
return false;
|
||||
if (endWith(ws, L".arc"))
|
||||
return false;
|
||||
if (all_ascii(ws.c_str()) && (ws.find(L"-") != ws.npos) && (ws.find(L"_") != ws.npos))
|
||||
return false;
|
||||
if (ws.find(L"[ 0 ]") != ws.npos)
|
||||
return false; // 個別アニメーション [ 0 ] の透明度
|
||||
//
|
||||
CharFilter(text, len, L'\x0001');
|
||||
CharFilter(text, len, L'\x0002');
|
||||
CharFilter(text, len, L'\x0003');
|
||||
CharFilter(text, len, L'\x0004');
|
||||
CharFilter(text, len, L'\x0005');
|
||||
CharFilter(text, len, L'\x000A');
|
||||
if (text[0] == L'\x3000') {
|
||||
if (text[0] == L'\x3000')
|
||||
{
|
||||
*len -= 2;
|
||||
::memmove(text, text+1, *len);
|
||||
::memmove(text, text + 1, *len);
|
||||
}
|
||||
CharReplacer(text, len, L'\x3000', L' '); //IDSP
|
||||
CharReplacer(text, len, L'\x3000', L' '); // IDSP
|
||||
|
||||
if (cpp_wcsnstr(text, L"<", *len/sizeof(wchar_t))) {
|
||||
if (cpp_wcsnstr(text, L"<", *len / sizeof(wchar_t)))
|
||||
{
|
||||
StringFilterBetween(text, len, L"<", 1, L">", 1);
|
||||
}
|
||||
|
||||
@ -1369,7 +1442,7 @@ bool InsertBGI7Hook()
|
||||
bool found = false;
|
||||
const BYTE pattern[] = {
|
||||
0x55, // 55 push ebp << hook here
|
||||
0x8b,0xec, // 8BEC mov ebp,esp
|
||||
0x8b, 0xec, // 8BEC mov ebp,esp
|
||||
0x53, // 53 push ebx
|
||||
0x56, // 56 push esi
|
||||
0x57, // 57 push edi
|
||||
@ -1382,14 +1455,15 @@ bool InsertBGI7Hook()
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
hp.offset=get_reg(regs::eax);
|
||||
hp.split =get_reg(regs::esp);
|
||||
hp.offset = get_reg(regs::eax);
|
||||
hp.split = get_reg(regs::esp);
|
||||
hp.type = CODEC_UTF16 | USING_STRING | USING_SPLIT | KNOWN_UNSTABLE;
|
||||
hp.filter_fun = BGI7Filter;
|
||||
ConsoleOutput("INSERT BGI4");
|
||||
found|=NewHook(hp, "BGI4");
|
||||
found |= NewHook(hp, "BGI4");
|
||||
}
|
||||
if (!found) ConsoleOutput("BGI4: pattern not found");
|
||||
if (!found)
|
||||
ConsoleOutput("BGI4: pattern not found");
|
||||
return found;
|
||||
}
|
||||
|
||||
@ -1398,7 +1472,8 @@ bool BGI56Filter(LPVOID data, size_t *size, HookParam *)
|
||||
auto text = reinterpret_cast<LPSTR>(data);
|
||||
auto len = reinterpret_cast<size_t *>(size);
|
||||
|
||||
if (text[0] == '@') {
|
||||
if (text[0] == '@')
|
||||
{
|
||||
*len -= 1;
|
||||
::memmove(text, text + 1, *len);
|
||||
}
|
||||
@ -1428,7 +1503,7 @@ bool InsertBGI5Hook()
|
||||
|
||||
HookParam hp;
|
||||
hp.address = addr + 1;
|
||||
hp.offset=get_reg(regs::ecx);
|
||||
hp.offset = get_reg(regs::ecx);
|
||||
hp.padding = 1;
|
||||
hp.type = USING_STRING;
|
||||
hp.filter_fun = BGI56Filter;
|
||||
@ -1462,7 +1537,7 @@ bool InsertBGI6Hook()
|
||||
|
||||
HookParam hp;
|
||||
hp.address = addr + 1;
|
||||
hp.offset=get_reg(regs::ecx);
|
||||
hp.offset = get_reg(regs::ecx);
|
||||
hp.padding = 1;
|
||||
hp.type = USING_STRING;
|
||||
hp.filter_fun = BGI56Filter;
|
||||
@ -1471,8 +1546,9 @@ bool InsertBGI6Hook()
|
||||
return NewHook(hp, "BGI6");
|
||||
}
|
||||
bool InsertBGIHook()
|
||||
{ return InsertBGI2Hook() || InsertBGI3Hook() || (PcHooks::hookOtherPcFunctions(), InsertBGI1Hook()); }
|
||||
|
||||
{
|
||||
return InsertBGI2Hook() || InsertBGI3Hook() || (PcHooks::hookOtherPcFunctions(), InsertBGI1Hook());
|
||||
}
|
||||
|
||||
bool InsertBGI4Hook()
|
||||
{
|
||||
@ -1509,119 +1585,135 @@ bool InsertBGI4Hook()
|
||||
return v3;
|
||||
}*/
|
||||
const BYTE bytes[] = {
|
||||
0xBE,0xE9,0xFD,0x00,0x00, //cp=65001
|
||||
0xBE, 0xE9, 0xFD, 0x00, 0x00, // cp=65001
|
||||
XX2,
|
||||
0xBE,0xA4,0x03,0x00,0x00 //cp=932
|
||||
0xBE, 0xA4, 0x03, 0x00, 0x00 // cp=932
|
||||
};
|
||||
auto addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||||
if (addr == 0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||||
if (addr == 0)return false;
|
||||
if (addr == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = addr;
|
||||
// hp.offset=get_reg(regs::eax);
|
||||
// hp.split = get_reg(regs::esp);
|
||||
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
*data=stack->stack[2];
|
||||
*split=stack->stack[6];//不一定对
|
||||
switch(*split){
|
||||
case 0://name
|
||||
case 1:
|
||||
*len=2*wcslen((wchar_t*)*data);
|
||||
break;
|
||||
}
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
*data = stack->stack[2];
|
||||
*split = stack->stack[6]; // 不一定对
|
||||
*len = 2 * wcslen((wchar_t *)*data);
|
||||
// switch(*split){
|
||||
// case 0://name
|
||||
// case 1:
|
||||
// *len=2*wcslen((wchar_t*)*data);
|
||||
// break;
|
||||
// }
|
||||
};
|
||||
hp.type = CODEC_UTF16 | USING_STRING|NO_CONTEXT |EMBED_ABLE|EMBED_BEFORE_SIMPLE|EMBED_AFTER_OVERWRITE;
|
||||
hp.hook_font=F_TextOutW|F_GetTextExtentPoint32W;
|
||||
hp.type = CODEC_UTF16 | USING_STRING | NO_CONTEXT | EMBED_ABLE | EMBED_BEFORE_SIMPLE | EMBED_AFTER_OVERWRITE;
|
||||
hp.hook_font = F_TextOutW | F_GetTextExtentPoint32W;
|
||||
hp.filter_fun = BGI7Filter;
|
||||
ConsoleOutput("BGI4");
|
||||
|
||||
return NewHook(hp, "BGI4");
|
||||
}
|
||||
namespace{
|
||||
bool veryold(){
|
||||
//紅月-くれないつき-
|
||||
//あの街の恋の詩
|
||||
auto addr = findiatcallormov((DWORD)GetGlyphOutlineA,processStartAddress,processStartAddress,processStopAddress);
|
||||
if (addr == 0)//銀行淫~堕ちゆく女達~ //mov ebp, ds:GetGlyphOutlineA
|
||||
addr = findiatcallormov((DWORD)GetGlyphOutlineA,processStartAddress,processStartAddress,processStopAddress,false,XX);
|
||||
if (addr == 0)return false;
|
||||
namespace
|
||||
{
|
||||
bool veryold()
|
||||
{
|
||||
// 紅月-くれないつき-
|
||||
// あの街の恋の詩
|
||||
auto addr = findiatcallormov((DWORD)GetGlyphOutlineA, processStartAddress, processStartAddress, processStopAddress);
|
||||
if (addr == 0) // 銀行淫~堕ちゆく女達~ //mov ebp, ds:GetGlyphOutlineA
|
||||
addr = findiatcallormov((DWORD)GetGlyphOutlineA, processStartAddress, processStartAddress, processStopAddress, false, XX);
|
||||
if (addr == 0)
|
||||
return false;
|
||||
addr = MemDbg::findEnclosingAlignedFunction(addr);
|
||||
if (addr == 0)return false;
|
||||
auto xrefs=findxref_reverse_checkcallop(addr,addr-0x1000,addr+0x1000,0xe8);
|
||||
if(xrefs.size()!=1)return false;
|
||||
auto xrefaddr=xrefs[0];
|
||||
if (addr == 0)
|
||||
return false;
|
||||
auto xrefs = findxref_reverse_checkcallop(addr, addr - 0x1000, addr + 0x1000, 0xe8);
|
||||
if (xrefs.size() != 1)
|
||||
return false;
|
||||
auto xrefaddr = xrefs[0];
|
||||
auto funcstart = MemDbg::findEnclosingAlignedFunction(xrefaddr);
|
||||
if (funcstart == 0)return false;
|
||||
BYTE sig[]={0x81,XX,0x00,0x01,0x00,0x00};//cmp ebx, 100h
|
||||
if(MemDbg::findBytes(sig, sizeof(sig), xrefaddr-0x40, xrefaddr)==0)return false;
|
||||
if (funcstart == 0)
|
||||
return false;
|
||||
BYTE sig[] = {0x81, XX, 0x00, 0x01, 0x00, 0x00}; // cmp ebx, 100h
|
||||
if (MemDbg::findBytes(sig, sizeof(sig), xrefaddr - 0x40, xrefaddr) == 0)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address = funcstart;
|
||||
hp.offset=get_stack(2);
|
||||
hp.split =get_stack(1);
|
||||
hp.type = CODEC_ANSI_BE |USING_SPLIT;
|
||||
hp.offset = get_stack(2);
|
||||
hp.split = get_stack(1);
|
||||
hp.type = CODEC_ANSI_BE | USING_SPLIT;
|
||||
|
||||
return NewHook(hp, "BGI5");
|
||||
|
||||
}
|
||||
}
|
||||
namespace{
|
||||
namespace
|
||||
{
|
||||
//[220729][1171051][きゃべつそふと] ジュエリー・ハーツ・アカデミア -We will wing wonder world-
|
||||
//int __fastcall sub_438E90(int a1, int *a2, int a3, _DWORD *a4, int a5)
|
||||
bool hook7(){
|
||||
BYTE sig[]={
|
||||
0x55,0x8b,0xec,
|
||||
0x83,0xe4,0xf0,
|
||||
0x83,0xec,XX,
|
||||
// int __fastcall sub_438E90(int a1, int *a2, int a3, _DWORD *a4, int a5)
|
||||
bool hook7()
|
||||
{
|
||||
BYTE sig[] = {
|
||||
0x55, 0x8b, 0xec,
|
||||
0x83, 0xe4, 0xf0,
|
||||
0x83, 0xec, XX,
|
||||
0x56,
|
||||
0x57,
|
||||
0x8b,XX,0x08,
|
||||
0x8b,0xf2,
|
||||
0x8b,0xd1,
|
||||
0x81,0xcf,0x00,0x00,0x00,0x80,
|
||||
0x8b,0xcf,
|
||||
0x89,0x54,0x24,0x0c,
|
||||
0xe8,XX4,
|
||||
0x85,0xc0,
|
||||
0x0f,0x84,XX4,
|
||||
0x8b,0x45,0x08
|
||||
0x8b, XX, 0x08,
|
||||
0x8b, 0xf2,
|
||||
0x8b, 0xd1,
|
||||
0x81, 0xcf, 0x00, 0x00, 0x00, 0x80,
|
||||
0x8b, 0xcf,
|
||||
0x89, 0x54, 0x24, 0x0c,
|
||||
0xe8, XX4,
|
||||
0x85, 0xc0,
|
||||
0x0f, 0x84, XX4,
|
||||
0x8b, 0x45, 0x08
|
||||
|
||||
};
|
||||
auto addr=MemDbg::findBytes(sig,sizeof(sig),processStartAddress,processStopAddress);
|
||||
if(!addr)return false;
|
||||
auto addr = MemDbg::findBytes(sig, sizeof(sig), processStartAddress, processStopAddress);
|
||||
if (!addr)
|
||||
return false;
|
||||
HookParam hp;
|
||||
hp.address=addr;
|
||||
//hp.offset=get_stack(1);
|
||||
//hp.split=get_stack(3);
|
||||
hp.type=USING_CHAR|CODEC_UTF16|NO_CONTEXT;//|USING_SPLIT;
|
||||
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
*data=(wchar_t)stack->stack[1];
|
||||
switch(stack->stack[3]){
|
||||
hp.address = addr;
|
||||
// hp.offset=get_stack(1);
|
||||
// hp.split=get_stack(3);
|
||||
hp.type = USING_CHAR | CODEC_UTF16 | NO_CONTEXT; //|USING_SPLIT;
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
*data = (wchar_t)stack->stack[1];
|
||||
switch (stack->stack[3])
|
||||
{
|
||||
case 0xfefefe:
|
||||
hp->user_value=stack->retaddr;
|
||||
*len=2;
|
||||
*split=1;
|
||||
hp->user_value = stack->retaddr;
|
||||
*len = 2;
|
||||
*split = 1;
|
||||
break;
|
||||
case 0xffffff://名字&历史+零散的文字,由于no_context他们被合并,但是和名字和文本是同一个调用地址
|
||||
case 0xffffff: // 名字&历史+零散的文字,由于no_context他们被合并,但是和名字和文本是同一个调用地址
|
||||
|
||||
if(hp->user_value==stack->retaddr){
|
||||
*len=2;
|
||||
*split=2;
|
||||
if (hp->user_value == stack->retaddr)
|
||||
{
|
||||
*len = 2;
|
||||
*split = 2;
|
||||
}
|
||||
break;
|
||||
case 0xfcfcc0://历史
|
||||
default:
|
||||
;
|
||||
case 0xfcfcc0: // 历史
|
||||
default:;
|
||||
}
|
||||
};
|
||||
return NewHook(hp,"bgi7");
|
||||
return NewHook(hp, "bgi7");
|
||||
}
|
||||
}
|
||||
bool BGI::attach_function() {
|
||||
bool b1= InsertBGIHook();
|
||||
bool b2=InsertBGI4Hook();
|
||||
bool ok= b1||b2||veryold();
|
||||
ok|=hook7();
|
||||
ok=InsertBGI7Hook()|| InsertBGI5Hook() || InsertBGI6Hook()||ok;
|
||||
bool BGI::attach_function()
|
||||
{
|
||||
bool b1 = InsertBGIHook();
|
||||
bool b2 = InsertBGI4Hook();
|
||||
bool ok = b1 || b2 || veryold();
|
||||
ok |= hook7();
|
||||
ok = InsertBGI7Hook() || InsertBGI5Hook() || InsertBGI6Hook() || ok;
|
||||
return ok;
|
||||
}
|
Loading…
Reference in New Issue
Block a user