mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 22:05:36 +08:00
3730 lines
178 KiB
C++
3730 lines
178 KiB
C++
|
||
#include"PPSSPP.h"
|
||
|
||
#include"ppsspp/psputils.hpp"
|
||
#include "ppsspp/funcinfo.h"
|
||
namespace { // unnamed
|
||
|
||
inline bool _bandaigarbage_ch(char c)
|
||
{
|
||
return c == ' ' || c == '/' || c == '#' || c == '.' || c == ':'
|
||
|| c >= '0' && c <= '9'
|
||
|| c >= 'A' && c <= 'z'; // also ignore ASCII 91-96: [ \ ] ^ _ `
|
||
}
|
||
|
||
// Remove trailing /L/P or #n garbage
|
||
size_t _bandaistrlen(LPCSTR text)
|
||
{
|
||
size_t len = ::strlen(text);
|
||
size_t ret = len;
|
||
while (len && _bandaigarbage_ch(text[len - 1])) {
|
||
len--;
|
||
if (text[len] == '/' || text[len] == '#') // in case trim UTF-8 trailing bytes
|
||
ret = len;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
// Trim leading garbage
|
||
LPCSTR _bandailtrim(LPCSTR p)
|
||
{
|
||
enum { MAX_LENGTH = VNR_TEXT_CAPACITY };
|
||
if (p)
|
||
for (int count = 0; *p && count < MAX_LENGTH; count++, p++)
|
||
if (!_bandaigarbage_ch(*p))
|
||
return p;
|
||
return nullptr;
|
||
}
|
||
} // unnamed namespae
|
||
|
||
|
||
|
||
static void SpecialPSPHookBandai(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
|
||
if (*text) {
|
||
//lasttext = text;
|
||
text = _bandailtrim(text);
|
||
*data = (DWORD)text;
|
||
*len = _bandaistrlen(text);
|
||
|
||
// Issue: The split value will create lots of threads for Shining Hearts
|
||
//*split = regof(ecx, esp_base); // works for Shool Rumble, but mix character name for Shining Hearts
|
||
*split = stack->edi; // works for Shining Hearts to split character name
|
||
}
|
||
}
|
||
|
||
// 7/22/2014 jichi: This engine works for multiple game?
|
||
// It is also observed in Broccoli game ぁ<>の<EFBFBD>リンスさまっ.
|
||
bool InsertBandaiPSPHook()
|
||
{
|
||
ConsoleOutput("BANDAI PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 13400560 77 0f ja short 13400571
|
||
0xc7,0x05, XX8, // 13400562 c705 a8aa1001 cc>mov dword ptr ds:[0x110aaa8],0x883decc
|
||
0xe9, XX4, // 1340056c -e9 93fa54f0 jmp 03950004
|
||
0x8b,0x35, XX4, // 13400571 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
0x81,0xc6, 0x01,0x00,0x00,0x00, // 13400577 81c6 01000000 add esi,0x1
|
||
0x8b,0x05, XX4, // 1340057d 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13400583 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb8, XX4, // 13400589 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x8b,0x2d, XX4, // 13400590 8b2d 78a71001 mov ebp,dword ptr ds:[0x110a778]
|
||
0x8d,0x6d, 0x01, // 13400596 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
0x81,0xff, 0x00,0x00,0x00,0x00 // 13400599 81ff 00000000 cmp edi,0x0
|
||
};
|
||
enum { memory_offset = 3 }; // 13400589 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = 0x13400589 - 0x13400560 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("BANDAI PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
//hp.offset=get_reg(regs::eax);
|
||
hp.text_fun = SpecialPSPHookBandai;
|
||
ConsoleOutput("BANDAI PSP: INSERT");
|
||
succ|=NewHook(hp, "BANDAI PSP");
|
||
}
|
||
|
||
ConsoleOutput("BANDAI PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
|
||
/** 7/29/2014 jichi Otomate PPSSPP 0.9.9
|
||
* Sample game: Amnesia Crowd
|
||
* Sample game: Amnesia Later
|
||
*
|
||
* 006db4af cc int3
|
||
* 006db4b0 8b15 b8ebaf00 mov edx,dword ptr ds:[0xafebb8] ; ppssppwi.01134988
|
||
* 006db4b6 56 push esi
|
||
* 006db4b7 8b42 10 mov eax,dword ptr ds:[edx+0x10]
|
||
* 006db4ba 25 ffffff3f and eax,0x3fffffff
|
||
* 006db4bf 0305 94411301 add eax,dword ptr ds:[0x1134194]
|
||
* 006db4c5 8d70 01 lea esi,dword ptr ds:[eax+0x1]
|
||
* 006db4c8 8a08 mov cl,byte ptr ds:[eax] ; jichi: hook here, get text in [eax]
|
||
* 006db4ca 40 inc eax
|
||
* 006db4cb 84c9 test cl,cl
|
||
* 006db4cd ^75 f9 jnz short ppssppwi.006db4c8
|
||
* 006db4cf 2bc6 sub eax,esi
|
||
* 006db4d1 8942 08 mov dword ptr ds:[edx+0x8],eax
|
||
* 006db4d4 5e pop esi
|
||
* 006db4d5 8d0485 07000000 lea eax,dword ptr ds:[eax*4+0x7]
|
||
* 006db4dc c3 retn
|
||
* 006db4dd cc int3
|
||
*/
|
||
static void SpecialPPSSPPHookOtomate(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
// 006db4b7 8b42 10 mov eax,dword ptr ds:[edx+0x10] ; jichi: hook here
|
||
// 006db4ba 25 ffffff3f and eax,0x3fffffff
|
||
// 006db4bf 0305 94411301 add eax,dword ptr ds:[0x1134194]; jichi: ds offset
|
||
// 006db4c5 8d70 01 lea esi,dword ptr ds:[eax+0x1]
|
||
DWORD edx = stack->edx;
|
||
DWORD eax = *(DWORD *)(edx + 0x10);
|
||
eax &= 0x3fffffff;
|
||
eax += *(DWORD *)hp->user_value;
|
||
|
||
//DWORD eax = regof(eax, esp_base);
|
||
LPCSTR text = LPCSTR(eax);
|
||
if (*text) {
|
||
text = _bandailtrim(text); // the same as bandai PSP
|
||
*data = (DWORD)text;
|
||
*len = _bandaistrlen(text);
|
||
|
||
*split = stack->ecx; // the same as Otomate PSP hook
|
||
//DWORD ecx = regof(ecx, esp_base); // the same as Otomate PSP hook
|
||
//*split = ecx ? ecx : (FIXED_SPLIT_VALUE << 2);
|
||
//*split = ecx & 0xffffff00; // skip cl which is used
|
||
}
|
||
}
|
||
bool InsertOtomatePPSSPPHook()
|
||
{
|
||
ConsoleOutput("Otomate PPSSPP: enter");
|
||
const BYTE bytes[] = {
|
||
0x8b,0x15, XX4, // 006db4b0 8b15 b8ebaf00 mov edx,dword ptr ds:[0xafebb8] ; ppssppwi.01134988
|
||
0x56, // 006db4b6 56 push esi
|
||
0x8b,0x42, 0x10, // 006db4b7 8b42 10 mov eax,dword ptr ds:[edx+0x10] ; jichi: hook here
|
||
0x25, 0xff,0xff,0xff,0x3f, // 006db4ba 25 ffffff3f and eax,0x3fffffff
|
||
0x03,0x05, XX4, // 006db4bf 0305 94411301 add eax,dword ptr ds:[0x1134194]; jichi: ds offset
|
||
0x8d,0x70, 0x01, // 006db4c5 8d70 01 lea esi,dword ptr ds:[eax+0x1]
|
||
0x8a,0x08, // 006db4c8 8a08 mov cl,byte ptr ds:[eax] ; jichi: hook here
|
||
0x40, // 006db4ca 40 inc eax
|
||
0x84,0xc9, // 006db4cb 84c9 test cl,cl
|
||
0x75, 0xf9, // 006db4cd ^75 f9 jnz short ppssppwi.006db4c8
|
||
0x2b,0xc6, // 006db4cf 2bc6 sub eax,esi
|
||
0x89,0x42, 0x08, // 006db4d1 8942 08 mov dword ptr ds:[edx+0x8],eax
|
||
0x5e, // 006db4d4 5e pop esi
|
||
0x8d,0x04,0x85, 0x07,0x00,0x00,0x00 // 006db4d5 8d0485 07000000 lea eax,dword ptr ds:[eax*4+0x7]
|
||
};
|
||
//enum { addr_offset = 0x006db4c8 - 0x006db4b0 };
|
||
enum { addr_offset = 0x006db4b7 - 0x006db4b0 };
|
||
enum { ds_offset = 0x006db4bf - 0x006db4b0 + 2 };
|
||
auto succ=false;
|
||
DWORD addr = SafeFindBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress);
|
||
//GROWL_DWORD(addr);
|
||
if (!addr)
|
||
ConsoleOutput("Otomate PPSSPP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(addr + ds_offset); // this is the address after ds:[]
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPPSSPPHookOtomate;
|
||
ConsoleOutput("Otomate PPSSPP: INSERT");
|
||
succ|=NewHook(hp, "Otomate PPSSPP");
|
||
}
|
||
|
||
ConsoleOutput("Otomate PPSSPP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** jichi 7/12/2014 PPSSPP
|
||
* Tested with PPSSPP 0.9.8.
|
||
*/
|
||
void SpecialPSPHook(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD offset = *(DWORD *)(stack->base + hp->offset);
|
||
LPCSTR text = LPCSTR(offset + hp->user_value);
|
||
static LPCSTR lasttext;
|
||
if (*text) {
|
||
*data = (DWORD)text;
|
||
// I only considered SHIFT-JIS/UTF-8 case
|
||
if (hp->length_offset == 1)
|
||
*len = 1; // only read 1 byte
|
||
else if (hp->length_offset)
|
||
*len = *(DWORD *)(stack->base + hp->length_offset);
|
||
else
|
||
*len = ::strlen(text); // should only be applied to hp->type|USING_STRING
|
||
if (hp->type & USING_SPLIT) {
|
||
if (hp->type & FIXING_SPLIT)
|
||
*split = FIXED_SPLIT_VALUE;
|
||
else
|
||
*split = *(DWORD *)(stack->base + hp->split);
|
||
}
|
||
}
|
||
}
|
||
|
||
bool InsertPPSSPPHLEHooks()
|
||
{
|
||
ConsoleOutput("PPSSPP HLE: enter");
|
||
|
||
// 0x400000 - 0x139f000
|
||
//GROWL_DWORD2(processStartAddress, processStopAddress);
|
||
|
||
HookParam hp;
|
||
hp.length_offset = 1; // determine string length at runtime
|
||
auto succ=false;
|
||
const PPSSPPFunction funcs[] = { PPSSPP_FUNCTIONS_INITIALIZER };
|
||
enum { FunctionCount = sizeof(funcs) / sizeof(*funcs) };
|
||
for (size_t i = 0; i < FunctionCount; i++) {
|
||
const auto &it = funcs[i];
|
||
ULONG addr = MemDbg::findBytes(it.pattern, ::strlen(it.pattern), processStartAddress, processStopAddress);
|
||
if (addr
|
||
&& (addr = MemDbg::findPushAddress(addr, processStartAddress, processStopAddress))
|
||
&& (addr = SafeFindEnclosingAlignedFunction(addr, 0x200)) // range = 0x200, use the safe version or it might raise
|
||
) {
|
||
hp.address = addr;
|
||
hp.type = USING_STRING|it.hookType;
|
||
hp.offset=get_stack(it.argIndex);
|
||
hp.split = it.hookSplit;
|
||
if (hp.split)
|
||
hp.type |= USING_SPLIT;
|
||
succ|=NewHook(hp, it.hookName);
|
||
}
|
||
if (addr)
|
||
ConsoleOutput("PPSSPP HLE: found pattern");
|
||
else
|
||
ConsoleOutput("PPSSPP HLE: not found pattern");
|
||
//ConsoleOutput(it.hookName); // wchar_t not supported
|
||
ConsoleOutput(it.pattern);
|
||
}
|
||
ConsoleOutput("PPSSPP HLE: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 8/9/2014 jichi imageepoch.co.jp PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: Sol Trigger (0.9.8, 0.9.9)
|
||
*
|
||
* Though Imageepoch1 also exists, it cannot find scenario text.
|
||
*
|
||
* FIXED memory addresses (different from Imageepoch1): two matches, UTF-8
|
||
*
|
||
* Debug method: find current text and add breakpoint.
|
||
*
|
||
* There a couple of good functions. The first one is used.
|
||
* There is only one text threads. But it cannot extract character names.
|
||
*
|
||
* 135fd497 cc int3
|
||
* 135fd498 77 0f ja short 135fd4a9
|
||
* 135fd49a c705 a8aa1001 20>mov dword ptr ds:[0x110aaa8],0x8952d20
|
||
* 135fd4a4 -e9 5b2b2ef0 jmp 038e0004
|
||
* 135fd4a9 8b35 dca71001 mov esi,dword ptr ds:[0x110a7dc]
|
||
* 135fd4af 81c6 04000000 add esi,0x4
|
||
* 135fd4b5 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
* 135fd4bb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 135fd4c1 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 135fd4c8 813d 68a71001 00>cmp dword ptr ds:[0x110a768],0x0
|
||
* 135fd4d2 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
* 135fd4d8 c705 aca71001 23>mov dword ptr ds:[0x110a7ac],0x23434623
|
||
* 135fd4e2 c705 b0a71001 30>mov dword ptr ds:[0x110a7b0],0x30303030
|
||
* 135fd4ec 8935 b4a71001 mov dword ptr ds:[0x110a7b4],esi
|
||
* 135fd4f2 c705 b8a71001 00>mov dword ptr ds:[0x110a7b8],0x0
|
||
* 135fd4fc 0f85 16000000 jnz 135fd518
|
||
* 135fd502 832d c4aa1001 08 sub dword ptr ds:[0x110aac4],0x8
|
||
* 135fd509 e9 22000000 jmp 135fd530
|
||
* 135fd50e 01642d 95 add dword ptr ss:[ebp+ebp-0x6b],esp
|
||
* 135fd512 08e9 or cl,ch
|
||
* 135fd514 0b2b or ebp,dword ptr ds:[ebx]
|
||
* 135fd516 2e:f0:832d c4aa1>lock sub dword ptr cs:[0x110aac4],0x8 ; lock prefix
|
||
* 135fd51f c705 a8aa1001 40>mov dword ptr ds:[0x110aaa8],0x8952d40
|
||
* 135fd529 -e9 f52a2ef0 jmp 038e0023
|
||
* 135fd52e 90 nop
|
||
* 135fd52f cc int3
|
||
*/
|
||
bool InsertImageepoch2PSPHook()
|
||
{
|
||
ConsoleOutput("Imageepoch2 PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
// 135fd497 cc int3
|
||
0x77, 0x0f, // 135fd498 77 0f ja short 135fd4a9
|
||
0xc7,0x05, XX8, // 135fd49a c705 a8aa1001 20>mov dword ptr ds:[0x110aaa8],0x8952d20
|
||
0xe9, XX4, // 135fd4a4 -e9 5b2b2ef0 jmp 038e0004
|
||
0x8b,0x35, XX4, // 135fd4a9 8b35 dca71001 mov esi,dword ptr ds:[0x110a7dc]
|
||
0x81,0xc6, 0x04,0x00,0x00,0x00, // 135fd4af 81c6 04000000 add esi,0x4
|
||
0x8b,0x05, XX4, // 135fd4b5 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 135fd4bb 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb8, XX4, // 135fd4c1 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x81,0x3d, XX4, 0x00,0x00,0x00,0x00, // 135fd4c8 813d 68a71001 00>cmp dword ptr ds:[0x110a768],0x0
|
||
0x89,0x3d, XX4, // 135fd4d2 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
0xc7,0x05, XX8, // 135fd4d8 c705 aca71001 23>mov dword ptr ds:[0x110a7ac],0x23434623
|
||
0xc7,0x05, XX8, // 135fd4e2 c705 b0a71001 30>mov dword ptr ds:[0x110a7b0],0x30303030
|
||
0x89,0x35, XX4, // 135fd4ec 8935 b4a71001 mov dword ptr ds:[0x110a7b4],esi
|
||
0xc7,0x05, XX4, 0x00,0x00,0x00,0x00, // 135fd4f2 c705 b8a71001 00>mov dword ptr ds:[0x110a7b8],0x0
|
||
0x0f,0x85 //, XX4, // 135fd4fc 0f85 16000000 jnz 135fd518
|
||
};
|
||
enum { memory_offset = 3 }; // 1346d381 0fb6a8 00004007 movzx ebp,byte ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = 0x135fd4c1 - 0x135fd498 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Imageepoch2 PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT; // UTF-8, though
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.split = get_reg(regs::ecx);
|
||
hp.text_fun = SpecialPSPHook;
|
||
ConsoleOutput("Imageepoch2 PSP: INSERT");
|
||
succ|=NewHook(hp, "Imageepoch2 PSP");
|
||
}
|
||
|
||
ConsoleOutput("Imageepoch2 PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/22/2014 jichi BANDAI PSP engine, 0.9.8 only
|
||
* Replaced by Otomate PPSSPP on 0.9.9.
|
||
* Sample game: School Rumble PSP 姉さん事件で<E4BBB6>(SHIFT-JIS)
|
||
* See: http://sakuradite.com/topic/333
|
||
*
|
||
* Sample game: 寮<>のサクリファイス work on 0.9.8, not 0.9.9
|
||
*
|
||
*
|
||
* Sample game: Shining Hearts (UTF-8)
|
||
* See: http://sakuradite.com/topic/346
|
||
*
|
||
* The encoding could be either UTF-8 or SHIFT-JIS
|
||
*
|
||
* Debug method: breakpoint the memory address
|
||
* There are two matched memory address to the current text
|
||
*
|
||
* Only one function is accessing the text address.
|
||
*
|
||
* Character name:
|
||
*
|
||
* 1346c122 cc int3
|
||
* 1346c123 cc int3
|
||
* 1346c124 77 0f ja short 1346c135
|
||
* 1346c126 c705 a8aa1001 a4>mov dword ptr ds:[0x110aaa8],0x882f2a4
|
||
* 1346c130 -e9 cf3e2cf0 jmp 03730004
|
||
* 1346c135 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
* 1346c13b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1346c141 8bb0 14004007 mov esi,dword ptr ds:[eax+0x7400014]
|
||
* 1346c147 8b3d 70a71001 mov edi,dword ptr ds:[0x110a770]
|
||
* 1346c14d c1e7 02 shl edi,0x2
|
||
* 1346c150 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
* 1346c156 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1346c15c 8ba8 18004007 mov ebp,dword ptr ds:[eax+0x7400018]
|
||
* 1346c162 03fe add edi,esi
|
||
* 1346c164 8bc7 mov eax,edi
|
||
* 1346c166 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1346c16c 0fb790 02004007 movzx edx,word ptr ds:[eax+0x7400002]
|
||
* 1346c173 8bc2 mov eax,edx
|
||
* 1346c175 8bd5 mov edx,ebp
|
||
* 1346c177 03d0 add edx,eax
|
||
* 1346c179 8bc2 mov eax,edx
|
||
* 1346c17b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1346c181 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 1346c188 8bcf mov ecx,edi
|
||
* 1346c18a 81e7 ff000000 and edi,0xff
|
||
* 1346c190 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 1346c196 8b35 b8a71001 mov esi,dword ptr ds:[0x110a7b8]
|
||
* 1346c19c 81c6 bc82ffff add esi,0xffff82bc
|
||
* 1346c1a2 81ff 00000000 cmp edi,0x0
|
||
* 1346c1a8 893d 70a71001 mov dword ptr ds:[0x110a770],edi
|
||
* 1346c1ae 8915 78a71001 mov dword ptr ds:[0x110a778],edx
|
||
* 1346c1b4 892d 7ca71001 mov dword ptr ds:[0x110a77c],ebp
|
||
* 1346c1ba 890d 80a71001 mov dword ptr ds:[0x110a780],ecx
|
||
* 1346c1c0 8935 84a71001 mov dword ptr ds:[0x110a784],esi
|
||
* 1346c1c6 0f85 16000000 jnz 1346c1e2
|
||
* 1346c1cc 832d c4aa1001 0b sub dword ptr ds:[0x110aac4],0xb
|
||
* 1346c1d3 e9 3c050000 jmp 1346c714
|
||
* 1346c1d8 014cf3 82 add dword ptr ds:[ebx+esi*8-0x7e],ecx
|
||
* 1346c1dc 08e9 or cl,ch
|
||
* 1346c1de 41 inc ecx
|
||
* 1346c1df 3e:2c f0 sub al,0xf0 ; superfluous prefix
|
||
* 1346c1e2 832d c4aa1001 0b sub dword ptr ds:[0x110aac4],0xb
|
||
* 1346c1e9 e9 0e000000 jmp 1346c1fc
|
||
* 1346c1ee 01d0 add eax,edx
|
||
* 1346c1f0 f2: prefix repne: ; superfluous prefix
|
||
* 1346c1f1 8208 e9 or byte ptr ds:[eax],0xffffffe9
|
||
* 1346c1f4 2b3e sub edi,dword ptr ds:[esi]
|
||
* 1346c1f6 2c f0 sub al,0xf0
|
||
* 1346c1f8 90 nop
|
||
* 1346c1f9 cc int3
|
||
* 1346c1fa cc int3
|
||
* 1346c1fb cc int3
|
||
*
|
||
* Scenario:
|
||
*
|
||
* 1340055d cc int3
|
||
* 1340055e cc int3
|
||
* 1340055f cc int3
|
||
* 13400560 77 0f ja short 13400571
|
||
* 13400562 c705 a8aa1001 cc>mov dword ptr ds:[0x110aaa8],0x883decc
|
||
* 1340056c -e9 93fa54f0 jmp 03950004
|
||
* 13400571 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
* 13400577 81c6 01000000 add esi,0x1
|
||
* 1340057d 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 13400583 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13400589 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 13400590 8b2d 78a71001 mov ebp,dword ptr ds:[0x110a778]
|
||
* 13400596 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 13400599 81ff 00000000 cmp edi,0x0
|
||
* 1340059f 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 134005a5 893d 74a71001 mov dword ptr ds:[0x110a774],edi
|
||
* 134005ab 892d 78a71001 mov dword ptr ds:[0x110a778],ebp
|
||
* 134005b1 0f84 16000000 je 134005cd
|
||
* 134005b7 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 134005be e9 21000000 jmp 134005e4
|
||
* 134005c3 01d0 add eax,edx
|
||
* 134005c5 de83 08e956fa fiadd word ptr ds:[ebx+0xfa56e908]
|
||
* 134005cb 54 push esp
|
||
* 134005cc f0:832d c4aa1001>lock sub dword ptr ds:[0x110aac4],0x4 ; lock prefix
|
||
* 134005d4 e9 7f000000 jmp 13400658
|
||
* 134005d9 01dc add esp,ebx
|
||
* 134005db de83 08e940fa fiadd word ptr ds:[ebx+0xfa40e908]
|
||
* 134005e1 54 push esp
|
||
* 134005e2 f0:90 lock nop ; lock prefix is not allowed
|
||
* 134005e4 77 0f ja short 134005f5
|
||
* 134005e6 c705 a8aa1001 d0>mov dword ptr ds:[0x110aaa8],0x883ded0
|
||
* 134005f0 -e9 0ffa54f0 jmp 03950004
|
||
* 134005f5 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 134005fb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13400601 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000]
|
||
* 13400608 8b3d 78a71001 mov edi,dword ptr ds:[0x110a778]
|
||
* 1340060e 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 13400611 81fe 00000000 cmp esi,0x0
|
||
* 13400617 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 1340061d 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
* 13400623 0f84 16000000 je 1340063f
|
||
* 13400629 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 13400630 ^e9 afffffff jmp 134005e4
|
||
* 13400635 01d0 add eax,edx
|
||
* 13400637 de83 08e9e4f9 fiadd word ptr ds:[ebx+0xf9e4e908]
|
||
* 1340063d 54 push esp
|
||
* 1340063e f0:832d c4aa1001>lock sub dword ptr ds:[0x110aac4],0x3 ; lock prefix
|
||
* 13400646 e9 0d000000 jmp 13400658
|
||
* 1340064b 01dc add esp,ebx
|
||
* 1340064d de83 08e9cef9 fiadd word ptr ds:[ebx+0xf9cee908]
|
||
* 13400653 54 push esp
|
||
* 13400654 f0:90 lock nop ; lock prefix is not allowed
|
||
* 13400656 cc int3
|
||
* 13400657 cc int3
|
||
*/
|
||
bool InsertBandaiNamePSPHook()
|
||
{
|
||
ConsoleOutput("BANDAI Name PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
//0xcc, // 1346c122 cc int3
|
||
//0xcc, // 1346c123 cc int3
|
||
0x77, 0x0f, // 1346c124 77 0f ja short 1346c135
|
||
0xc7,0x05, XX8, // 1346c126 c705 a8aa1001 a4>mov dword ptr ds:[0x110aaa8],0x882f2a4
|
||
0xe9, XX4, // 1346c130 -e9 cf3e2cf0 jmp 03730004
|
||
0x8b,0x05, XX4, // 1346c135 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1346c13b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb0, XX4, // 1346c141 8bb0 14004007 mov esi,dword ptr ds:[eax+0x7400014]
|
||
0x8b,0x3d, XX4, // 1346c147 8b3d 70a71001 mov edi,dword ptr ds:[0x110a770]
|
||
0xc1,0xe7, 0x02, // 1346c14d c1e7 02 shl edi,0x2
|
||
0x8b,0x05, XX4, // 1346c150 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1346c156 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xa8, XX4, // 1346c15c 8ba8 18004007 mov ebp,dword ptr ds:[eax+0x7400018]
|
||
0x03,0xfe, // 1346c162 03fe add edi,esi
|
||
0x8b,0xc7, // 1346c164 8bc7 mov eax,edi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1346c166 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb7,0x90, XX4, // 1346c16c 0fb790 02004007 movzx edx,word ptr ds:[eax+0x7400002]
|
||
0x8b,0xc2, // 1346c173 8bc2 mov eax,edx
|
||
0x8b,0xd5, // 1346c175 8bd5 mov edx,ebp
|
||
0x03,0xd0, // 1346c177 03d0 add edx,eax
|
||
0x8b,0xc2, // 1346c179 8bc2 mov eax,edx
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1346c17b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb8 //, XX4 // 1346c181 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
};
|
||
enum { memory_offset = 3 }; // 1346c181 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = sizeof(bytes) - memory_offset };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("BANDAI Name PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.split = get_reg(regs::ebx);
|
||
hp.text_fun = SpecialPSPHook;
|
||
ConsoleOutput("BANDAI Name PSP: INSERT");
|
||
succ|=NewHook(hp, "BANDAI Name PSP");
|
||
}
|
||
|
||
ConsoleOutput("BANDAI Name PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/26/2014 jichi Otomate PSP engine, 0.9.8 only, 0.9.9 not work
|
||
* Replaced by Otomate PPSSPP on 0.9.9.
|
||
*
|
||
* Sample game: クロノスタシア
|
||
* Sample game: フォトカ<E38388>(repetition)
|
||
*
|
||
* Not work on 0.9.9: Amnesia Crowd
|
||
*
|
||
* The instruction pattern also exist in 0.9.9. But the function is not called.
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: breakpoint the memory address
|
||
*
|
||
* The memory access of the function below is weird that the accessed value is 2 bytes after the real text.
|
||
*
|
||
* PPSSPP 0.9.8, クロノスタシア
|
||
* 13c00fe1 cc int3
|
||
* 13c00fe2 cc int3
|
||
* 13c00fe3 cc int3
|
||
* 13c00fe4 77 0f ja short 13c00ff5
|
||
* 13c00fe6 c705 a8aa1001 30>mov dword ptr ds:[0x110aaa8],0x884b330
|
||
* 13c00ff0 -e9 0ff0edf2 jmp 06ae0004
|
||
* 13c00ff5 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 13c00ffb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13c01001 0fbeb0 0000c007 movsx esi,byte ptr ds:[eax+0x7c00000] ; jichi: hook here
|
||
* 13c01008 81fe 00000000 cmp esi,0x0 ; jichi: hook here, get the esi value
|
||
* 13c0100e 8935 80a71001 mov dword ptr ds:[0x110a780],esi
|
||
* 13c01014 0f84 25000000 je 13c0103f
|
||
* 13c0101a 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
* 13c01020 8d76 01 lea esi,dword ptr ds:[esi+0x1]
|
||
* 13c01023 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 13c01029 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 13c01030 ^e9 afffffff jmp 13c00fe4
|
||
* 13c01035 0130 add dword ptr ds:[eax],esi
|
||
* 13c01037 b3 84 mov bl,0x84
|
||
* 13c01039 08e9 or cl,ch
|
||
* 13c0103b e4 ef in al,0xef ; i/o command
|
||
* 13c0103d ed in eax,dx ; i/o command
|
||
* 13c0103e f2: prefix repne: ; superfluous prefix
|
||
* 13c0103f 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 13c01046 e9 0d000000 jmp 13c01058
|
||
* 13c0104b 013cb3 add dword ptr ds:[ebx+esi*4],edi
|
||
* 13c0104e 8408 test byte ptr ds:[eax],cl
|
||
* 13c01050 -e9 ceefedf2 jmp 06ae0023
|
||
* 13c01055 90 nop
|
||
* 13c01056 cc int3
|
||
* 13c01057 cc int3
|
||
*/
|
||
// TODO: is reverse_strlen a better choice?
|
||
// Read text from esi
|
||
static void SpecialPSPHookOtomate(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
//static uniquemap uniq;
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value - 2); // -2 to read 1 word more from previous location
|
||
if (*text) {
|
||
*split = stack->ecx; // this would cause lots of texts, but it works for all games
|
||
//*split = regof(ecx, esp_base) & 0xff00; // only use higher bits
|
||
*data = (DWORD)text;
|
||
size_t sz = ::strlen(text);
|
||
*len = sz == 3 ? 3 : 1; // handling the last two bytes
|
||
}
|
||
}
|
||
|
||
bool InsertOtomatePSPHook()
|
||
{
|
||
ConsoleOutput("Otomate PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 13c00fe4 77 0f ja short 13c00ff5
|
||
0xc7,0x05, XX8, // 13c00fe6 c705 a8aa1001 30>mov dword ptr ds:[0x110aaa8],0x884b330
|
||
0xe9, XX4, // 13c00ff0 -e9 0ff0edf2 jmp 06ae0004
|
||
0x8b,0x05, XX4, // 13c00ff5 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13c00ffb 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 13c01001 0fbeb0 0000c007 movsx esi,byte ptr ds:[eax+0x7c00000] ; jichi: hook here
|
||
0x81,0xfe, 0x00,0x00,0x00,0x00, // 13c01008 81fe 00000000 cmp esi,0x0
|
||
0x89,0x35, XX4, // 13c0100e 8935 80a71001 mov dword ptr ds:[0x110a780],esi
|
||
0x0f,0x84, 0x25,0x00,0x00,0x00, // 13c01014 0f84 25000000 je 13c0103f
|
||
0x8b,0x35, XX4, // 13c0101a 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
0x8d,0x76, 0x01, // 13c01020 8d76 01 lea esi,dword ptr ds:[esi+0x1]
|
||
0x89,0x35, XX4, // 13c01023 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
0x83,0x2d, XX4, 0x03 // 13c01029 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
};
|
||
enum { memory_offset = 3 };
|
||
//enum { addr_offset = 0x13c01008 - 0x13c00fe4 };
|
||
enum { addr_offset = 0x13c01001- 0x13c00fe4 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
//GROWL_DWORD(addr);
|
||
if (!addr)
|
||
ConsoleOutput("Otomate PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookOtomate;
|
||
ConsoleOutput("Otomate PSP: INSERT");
|
||
succ|=NewHook(hp, "Otomate PSP");
|
||
}
|
||
|
||
ConsoleOutput("Otomate PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/27/2014 jichi Intense.jp PSP engine, 0.9.8, 0.9.9,
|
||
* Though Otomate can work, it cannot work line by line.
|
||
*
|
||
* Sample game: 寮<>のサクリファイス work on 0.9.8 & 0.9.9
|
||
* This hook is only for intro graphic painting
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: predict and breakpoint the memory address
|
||
*
|
||
* There are two matches in the memory, and only one function accessing them.
|
||
* The memory is accessed by words.
|
||
*
|
||
* The memory and hooked function is as follows.
|
||
*
|
||
* 09dfee77 88 c3 82 a2 95 a3 82 cc 89 9c 92 ea 82 c5 81 41 暗い淵の奥底で<E5BA95> * 09dfee87 92 e1 82 ad 81 41 8f ac 82 b3 82 ad 81 41 8b bf 低く、小さく〟<E3818F>
|
||
* 09dfee97 82 ad 81 42 2a 70 0a 82 b1 82 ea 82 cd 81 41 8c く<>p.これは、<E381AF>
|
||
* 09dfeea7 db 93 ae 81 63 81 48 2a 70 0a 82 c6 82 e0 82 b7 <20>動…p.ともす
|
||
* 09dfeeb7 82 ea 82 ce 95 b7 82 ab 93 a6 82 b5 82 c4 82 b5 れ<>聞き送<E3818D>て<EFBFBD> * 09dfeec7 82 dc 82 a2 82 bb 82 a4 82 c8 81 41 2a 70 0a 8f まぁ<E381BE>ぁ<EFBFBD><E38181>p.・
|
||
* 09dfeed7 ac 82 b3 82 ad 81 41 8e e3 81 58 82 b5 82 ad 81 <20>さく、弱、<E5BCB1>く<EFBFBD>
|
||
* 09dfeee7 41 95 73 8a 6d 82 a9 82 c8 89 b9 81 42 00 00 00 a不確かな音<E381AA>..
|
||
* 09dfeef7 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||
* 09dfee07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
|
||
*
|
||
* 13472227 90 nop
|
||
* 13472228 77 0f ja short 13472239
|
||
* 1347222a c705 a8aa1001 20>mov dword ptr ds:[0x110aaa8],0x884ce20
|
||
* 13472234 -e9 cbdd16f0 jmp 035e0004
|
||
* 13472239 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
* 1347223f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13472245 8bb0 30004007 mov esi,dword ptr ds:[eax+0x7400030]
|
||
* 1347224b 8b3d 84a71001 mov edi,dword ptr ds:[0x110a784]
|
||
* 13472251 81c7 01000000 add edi,0x1
|
||
* 13472257 8bee mov ebp,esi
|
||
* 13472259 032d 84a71001 add ebp,dword ptr ds:[0x110a784]
|
||
* 1347225f 8bc5 mov eax,ebp
|
||
* 13472261 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13472267 0fbe90 00004007 movsx edx,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 1347226e 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
* 13472274 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1347227a 89b8 38004007 mov dword ptr ds:[eax+0x7400038],edi
|
||
* 13472280 8bea mov ebp,edx
|
||
* 13472282 81e5 ff000000 and ebp,0xff
|
||
* 13472288 81fa 0a000000 cmp edx,0xa
|
||
* 1347228e c705 70a71001 0a>mov dword ptr ds:[0x110a770],0xa
|
||
* 13472298 8915 74a71001 mov dword ptr ds:[0x110a774],edx
|
||
* 1347229e 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
* 134722a4 892d 7ca71001 mov dword ptr ds:[0x110a77c],ebp
|
||
* 134722aa 8935 80a71001 mov dword ptr ds:[0x110a780],esi
|
||
* 134722b0 0f85 16000000 jnz 134722cc
|
||
* 134722b6 832d c4aa1001 08 sub dword ptr ds:[0x110aac4],0x8
|
||
* 134722bd e9 02680000 jmp 13478ac4
|
||
* 134722c2 01ec add esp,ebp
|
||
* 134722c4 ce into
|
||
* 134722c5 8408 test byte ptr ds:[eax],cl
|
||
* 134722c7 -e9 57dd16f0 jmp 035e0023
|
||
* 134722cc 832d c4aa1001 08 sub dword ptr ds:[0x110aac4],0x8
|
||
* 134722d3 e9 0c000000 jmp 134722e4
|
||
* 134722d8 0140 ce add dword ptr ds:[eax-0x32],eax
|
||
* 134722db 8408 test byte ptr ds:[eax],cl
|
||
* 134722dd -e9 41dd16f0 jmp 035e0023
|
||
* 134722e2 90 nop
|
||
* 134722e3 cc int3
|
||
*/
|
||
// Read text from esi
|
||
static void SpecialPSPHookIntense(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
DWORD text = eax + hp->user_value;
|
||
if (BYTE c = *(BYTE *)text) { // unsigned char
|
||
*data = text;
|
||
*len = ::LeadByteTable[c]; // 1 or 2
|
||
//*split = regof(ecx, esp_base); // cause scenario text to split
|
||
//*split = regof(edx, esp_base); // cause scenario text to split
|
||
|
||
//*split = regof(ebx, esp_base); // works, but floating value
|
||
*split = FIXED_SPLIT_VALUE * 3;
|
||
}
|
||
}
|
||
bool InsertIntensePSPHook()
|
||
{
|
||
ConsoleOutput("Intense PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 13472228 77 0f ja short 13472239
|
||
0xc7,0x05, XX8, // 1347222a c705 a8aa1001 20>mov dword ptr ds:[0x110aaa8],0x884ce20
|
||
0xe9, XX4, // 13472234 -e9 cbdd16f0 jmp 035e0004
|
||
0x8b,0x05, XX4, // 13472239 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1347223f 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb0, XX4, // 13472245 8bb0 30004007 mov esi,dword ptr ds:[eax+0x7400030]
|
||
0x8b,0x3d, XX4, // 1347224b 8b3d 84a71001 mov edi,dword ptr ds:[0x110a784]
|
||
0x81,0xc7, 0x01,0x00,0x00,0x00, // 13472251 81c7 01000000 add edi,0x1
|
||
0x8b,0xee, // 13472257 8bee mov ebp,esi
|
||
0x03,0x2d, XX4, // 13472259 032d 84a71001 add ebp,dword ptr ds:[0x110a784]
|
||
0x8b,0xc5, // 1347225f 8bc5 mov eax,ebp
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13472261 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0x90, XX4, // 13472267 0fbe90 00004007 movsx edx,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x8b,0x05, XX4, // 1347226e 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f // 13472274 81e0 ffffff3f and eax,0x3fffffff
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x13472267 - 0x13472228 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Intense PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookIntense;
|
||
ConsoleOutput("Intense PSP: INSERT");
|
||
succ|=NewHook(hp, "Intense PSP");
|
||
}
|
||
|
||
ConsoleOutput("Intense PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/26/2014 jichi Broccoli PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: 明治東亰恋伽 (works on both 0.9.8, 0.9.9)
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: breakpoint the memory address
|
||
*
|
||
* The data is in (WORD)dl in bytes.
|
||
*
|
||
* There are two text threads.
|
||
* Only one is correct.
|
||
*
|
||
* 13d26cab cc int3
|
||
* 13d26cac 77 0f ja short 13d26cbd
|
||
* 13d26cae c705 a8aa1001 24>mov dword ptr ds:[0x110aaa8],0x886a724
|
||
* 13d26cb8 -e9 4793ccef jmp 039f0004
|
||
* 13d26cbd 8b35 dca71001 mov esi,dword ptr ds:[0x110a7dc]
|
||
* 13d26cc3 8db6 60feffff lea esi,dword ptr ds:[esi-0x1a0]
|
||
* 13d26cc9 8b3d e4a71001 mov edi,dword ptr ds:[0x110a7e4]
|
||
* 13d26ccf 8bc6 mov eax,esi
|
||
* 13d26cd1 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13d26cd7 89b8 9001c007 mov dword ptr ds:[eax+0x7c00190],edi
|
||
* 13d26cdd 8b2d 80a71001 mov ebp,dword ptr ds:[0x110a780]
|
||
* 13d26ce3 0fbfed movsx ebp,bp
|
||
* 13d26ce6 8bd6 mov edx,esi
|
||
* 13d26ce8 8bce mov ecx,esi
|
||
* 13d26cea 03cd add ecx,ebp
|
||
* 13d26cec 8935 dca71001 mov dword ptr ds:[0x110a7dc],esi
|
||
* 13d26cf2 33c0 xor eax,eax
|
||
* 13d26cf4 3bd1 cmp edx,ecx
|
||
* 13d26cf6 0f92c0 setb al
|
||
* 13d26cf9 8bf0 mov esi,eax
|
||
* 13d26cfb 81fe 00000000 cmp esi,0x0
|
||
* 13d26d01 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 13d26d07 890d 74a71001 mov dword ptr ds:[0x110a774],ecx
|
||
* 13d26d0d 892d 80a71001 mov dword ptr ds:[0x110a780],ebp
|
||
* 13d26d13 8915 8ca71001 mov dword ptr ds:[0x110a78c],edx
|
||
* 13d26d19 0f85 16000000 jnz 13d26d35
|
||
* 13d26d1f 832d c4aa1001 08 sub dword ptr ds:[0x110aac4],0x8
|
||
* 13d26d26 e9 b9000000 jmp 13d26de4
|
||
* 13d26d2b 0158 a7 add dword ptr ds:[eax-0x59],ebx
|
||
* 13d26d2e 8608 xchg byte ptr ds:[eax],cl
|
||
* 13d26d30 -e9 ee92ccef jmp 039f0023
|
||
* 13d26d35 832d c4aa1001 08 sub dword ptr ds:[0x110aac4],0x8
|
||
* 13d26d3c e9 0b000000 jmp 13d26d4c
|
||
* 13d26d41 0144a7 86 add dword ptr ds:[edi-0x7a],eax
|
||
* 13d26d45 08e9 or cl,ch
|
||
* 13d26d47 d892 ccef9077 fcom dword ptr ds:[edx+0x7790efcc]
|
||
* 13d26d4d 0fc7 ??? ; unknown command
|
||
* 13d26d4f 05 a8aa1001 add eax,0x110aaa8
|
||
* 13d26d54 44 inc esp
|
||
* 13d26d55 a7 cmps dword ptr ds:[esi],dword ptr es:[ed>
|
||
* 13d26d56 8608 xchg byte ptr ds:[eax],cl
|
||
* 13d26d58 -e9 a792ccef jmp 039f0004
|
||
* 13d26d5d 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 13d26d63 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13d26d69 0fb6b0 0000c007 movzx esi,byte ptr ds:[eax+0x7c00000]
|
||
* 13d26d70 8b3d 7ca71001 mov edi,dword ptr ds:[0x110a77c]
|
||
* 13d26d76 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 13d26d79 8b05 8ca71001 mov eax,dword ptr ds:[0x110a78c]
|
||
* 13d26d7f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13d26d85 8bd6 mov edx,esi
|
||
* 13d26d87 8890 0000c007 mov byte ptr ds:[eax+0x7c00000],dl ; jichi: hook here, get byte from dl
|
||
* 13d26d8d 8b2d 8ca71001 mov ebp,dword ptr ds:[0x110a78c]
|
||
* 13d26d93 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 13d26d96 81fe 00000000 cmp esi,0x0
|
||
* 13d26d9c 893d 7ca71001 mov dword ptr ds:[0x110a77c],edi
|
||
* 13d26da2 8935 88a71001 mov dword ptr ds:[0x110a788],esi
|
||
* 13d26da8 892d 8ca71001 mov dword ptr ds:[0x110a78c],ebp
|
||
* 13d26dae 0f84 16000000 je 13d26dca
|
||
* 13d26db4 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 13d26dbb e9 f48b0100 jmp 13d3f9b4
|
||
* 13d26dc0 0138 add dword ptr ds:[eax],edi
|
||
* 13d26dc2 a7 cmps dword ptr ds:[esi],dword ptr es:[ed>
|
||
* 13d26dc3 8608 xchg byte ptr ds:[eax],cl
|
||
* 13d26dc5 -e9 5992ccef jmp 039f0023
|
||
* 13d26dca 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 13d26dd1 e9 0e000000 jmp 13d26de4
|
||
* 13d26dd6 0158 a7 add dword ptr ds:[eax-0x59],ebx
|
||
* 13d26dd9 8608 xchg byte ptr ds:[eax],cl
|
||
* 13d26ddb -e9 4392ccef jmp 039f0023
|
||
* 13d26de0 90 nop
|
||
* 13d26de1 cc int3
|
||
*/
|
||
|
||
// New line character for Broccoli games is '^'
|
||
static inline bool _broccoligarbage_ch(char c) { return c == '^'; }
|
||
|
||
// Read text from dl
|
||
static void SpecialPSPHookBroccoli(hook_stack* stack, HookParam *, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD text = stack->edx; // edx address
|
||
char c = *(LPCSTR)text;
|
||
if (c && !_broccoligarbage_ch(c)) {
|
||
*data = text;
|
||
*len = 1;
|
||
*split = stack->ecx;
|
||
}
|
||
}
|
||
|
||
bool InsertBroccoliPSPHook()
|
||
{
|
||
ConsoleOutput("Broccoli PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
0x0f,0xc7, // 13d26d4d 0fc7 ??? ; unknown command
|
||
0x05, XX4, // 13d26d4f 05 a8aa1001 add eax,0x110aaa8
|
||
0x44, // 13d26d54 44 inc esp
|
||
0xa7, // 13d26d55 a7 cmps dword ptr ds:[esi],dword ptr es:[ed>
|
||
0x86,0x08, // 13d26d56 8608 xchg byte ptr ds:[eax],cl
|
||
0xe9, XX4, // 13d26d58 -e9 a792ccef jmp 039f0004
|
||
0x8b,0x05, XX4, // 13d26d5d 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
// Following pattern is not sufficient
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13d26d63 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb0, XX4, // 13d26d69 0fb6b0 0000c007 movzx esi,byte ptr ds:[eax+0x7c00000]
|
||
0x8b,0x3d, XX4, // 13d26d70 8b3d 7ca71001 mov edi,dword ptr ds:[0x110a77c]
|
||
0x8d,0x7f, 0x01, // 13d26d76 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
0x8b,0x05, XX4, // 13d26d79 8b05 8ca71001 mov eax,dword ptr ds:[0x110a78c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13d26d7f 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xd6, // 13d26d85 8bd6 mov edx,esi
|
||
0x88,0x90, XX4, // 13d26d87 8890 0000c007 mov byte ptr ds:[eax+0x7c00000],dl ; jichi: hook here, get byte from dl
|
||
0x8b,0x2d, XX4, // 13d26d8d 8b2d 8ca71001 mov ebp,dword ptr ds:[0x110a78c]
|
||
0x8d,0x6d, 0x01, // 13d26d93 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
0x81,0xfe, 0x00,0x00,0x00,0x00 // 13d26d96 81fe 00000000 cmp esi,0x0
|
||
};
|
||
enum { addr_offset = 0x13d26d87 - 0x13d26d4d };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Broccoli PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookBroccoli;
|
||
//GROWL_DWORD(hp.address);
|
||
ConsoleOutput("Broccoli PSP: INSERT");
|
||
succ|=NewHook(hp, "Broccoli PSP");
|
||
}
|
||
|
||
ConsoleOutput("Broccoli PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 9/5/2014 jichi felistella.co.jp PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: Summon Night 5 0.9.8/0.9.9
|
||
*
|
||
* Encoding: utf8
|
||
* Fixed memory addresses: two matches
|
||
*
|
||
* Debug method: predict the text and add break-points.
|
||
*
|
||
* There are two good functions
|
||
* The second is used as it contains fewer garbage
|
||
*
|
||
* // Not used
|
||
* 14081173 cc int3
|
||
* 14081174 77 0f ja short 14081185
|
||
* 14081176 c705 c84c1301 40>mov dword ptr ds:[0x1134cc8],0x8989540
|
||
* 14081180 -e9 7feef5f3 jmp 07fe0004
|
||
* 14081185 8b35 9c491301 mov esi,dword ptr ds:[0x113499c]
|
||
* 1408118b 8bc6 mov eax,esi
|
||
* 1408118d 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14081193 0fb6b8 00000008 movzx edi,byte ptr ds:[eax+0x8000000] ; jichi: hook here
|
||
* 1408119a 8bef mov ebp,edi
|
||
* 1408119c 81e5 80000000 and ebp,0x80
|
||
* 140811a2 8d76 01 lea esi,dword ptr ds:[esi+0x1]
|
||
* 140811a5 81fd 00000000 cmp ebp,0x0
|
||
* 140811ab c705 90491301 00>mov dword ptr ds:[0x1134990],0x0
|
||
* 140811b5 893d 9c491301 mov dword ptr ds:[0x113499c],edi
|
||
* 140811bb 8935 a0491301 mov dword ptr ds:[0x11349a0],esi
|
||
* 140811c1 892d a4491301 mov dword ptr ds:[0x11349a4],ebp
|
||
* 140811c7 0f85 16000000 jnz 140811e3
|
||
* 140811cd 832d e44c1301 06 sub dword ptr ds:[0x1134ce4],0x6
|
||
* 140811d4 e9 fbf71200 jmp 141b09d4
|
||
* 140811d9 01dc add esp,ebx
|
||
* 140811db 95 xchg eax,ebp
|
||
* 140811dc 98 cwde
|
||
* 140811dd 08e9 or cl,ch
|
||
* 140811df 40 inc eax
|
||
*
|
||
* // Used
|
||
* 141be92f cc int3
|
||
* 141be930 77 0f ja short 141be941
|
||
* 141be932 c705 c84c1301 0c>mov dword ptr ds:[0x1134cc8],0x8988f0c
|
||
* 141be93c -e9 c316e2f3 jmp 07fe0004
|
||
* 141be941 8b35 98491301 mov esi,dword ptr ds:[0x1134998]
|
||
* 141be947 8bc6 mov eax,esi
|
||
* 141be949 81e0 ffffff3f and eax,0x3fffffff
|
||
* 141be94f 0fb6b8 00000008 movzx edi,byte ptr ds:[eax+0x8000000] ; jichi: hook here
|
||
* 141be956 81ff 00000000 cmp edi,0x0
|
||
* 141be95c c705 90491301 00>mov dword ptr ds:[0x1134990],0x0
|
||
* 141be966 893d 98491301 mov dword ptr ds:[0x1134998],edi
|
||
* 141be96c 8935 9c491301 mov dword ptr ds:[0x113499c],esi
|
||
* 141be972 0f85 16000000 jnz 141be98e
|
||
* 141be978 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
* 141be97f e9 e4020000 jmp 141bec68
|
||
* 141be984 01748f 98 add dword ptr ds:[edi+ecx*4-0x68],esi
|
||
* 141be988 08e9 or cl,ch
|
||
* 141be98a 95 xchg eax,ebp
|
||
* 141be98b 16 push ss
|
||
* 141be98c ^e2 f3 loopd short 141be981
|
||
* 141be98e 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
* 141be995 e9 0e000000 jmp 141be9a8
|
||
* 141be99a 011c8f add dword ptr ds:[edi+ecx*4],ebx
|
||
* 141be99d 98 cwde
|
||
* 141be99e 08e9 or cl,ch
|
||
* 141be9a0 7f 16 jg short 141be9b8
|
||
* 141be9a2 ^e2 f3 loopd short 141be997
|
||
* 141be9a4 90 nop
|
||
* 141be9a5 cc int3
|
||
*/
|
||
// Only split text when edi is eax
|
||
// The value of edi is either eax or 0
|
||
static void SpecialPSPHookFelistella(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
if (text) {
|
||
*len = ::strlen(text); // utf8
|
||
*data = (DWORD)text;
|
||
|
||
DWORD edi = stack->edi;
|
||
*split = FIXED_SPLIT_VALUE * (edi == eax ? 4 : 5);
|
||
}
|
||
}
|
||
bool InsertFelistellaPSPHook()
|
||
{
|
||
ConsoleOutput("FELISTELLA PSP: enter");
|
||
const BYTE bytes[] = {
|
||
//0xcc, // 141be92f cc int3
|
||
0x77, 0x0f, // 141be930 77 0f ja short 141be941
|
||
0xc7,0x05, XX8, // 141be932 c705 c84c1301 0c>mov dword ptr ds:[0x1134cc8],0x8988f0c
|
||
0xe9, XX4, // 141be93c -e9 c316e2f3 jmp 07fe0004
|
||
0x8b,0x35, XX4, // 141be941 8b35 98491301 mov esi,dword ptr ds:[0x1134998]
|
||
0x8b,0xc6, // 141be947 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 141be949 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb8, XX4, // 141be94f 0fb6b8 00000008 movzx edi,byte ptr ds:[eax+0x8000000] ; jichi: hook here
|
||
0x81,0xff, 0x00,0x00,0x00,0x00, // 141be956 81ff 00000000 cmp edi,0x0
|
||
0xc7,0x05, XX4, 0x00,0x00,0x00,0x00, // 141be95c c705 90491301 00>mov dword ptr ds:[0x1134990],0x0
|
||
0x89,0x3d, XX4, // 141be966 893d 98491301 mov dword ptr ds:[0x1134998],edi
|
||
0x89,0x35, XX4, // 141be96c 8935 9c491301 mov dword ptr ds:[0x113499c],esi
|
||
0x0f,0x85, XX4, // 141be972 0f85 16000000 jnz 141be98e
|
||
0x83,0x2d, XX4, 0x04, // 141be978 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
// Above is not sufficient
|
||
0xe9, XX4, // 141be97f e9 e4020000 jmp 141bec68
|
||
0x01,0x74,0x8f, 0x98 // 141be984 01748f 98 add dword ptr ds:[edi+ecx*4-0x68],esi
|
||
//0x08,0xe9, // 141be988 08e9 or cl,ch
|
||
// Below could be changed for different run
|
||
//0x95, // 141be98a 95 xchg eax,ebp
|
||
//0x16 // 141be98b 16 push ss
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x141be94f - 0x141be930 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
//GROWL_DWORD(addr);
|
||
if (!addr)
|
||
ConsoleOutput("FELISTELLA PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|CODEC_UTF8|USING_SPLIT|NO_CONTEXT; // Fix the split value to merge all threads
|
||
//hp.text_fun = SpecialPSPHook;
|
||
hp.text_fun = SpecialPSPHookFelistella;
|
||
hp.offset=get_reg(regs::eax);
|
||
ConsoleOutput("FELISTELLA PSP: INSERT");
|
||
succ|=NewHook(hp, "FELISTELLA PSP");
|
||
}
|
||
|
||
ConsoleOutput("FELISTELLA PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/13/2014 jichi alchemist-net.co.jp PSP engine, 0.9.8 only, not work on 0.9.9
|
||
* Sample game: your diary+ (moe-ydp.iso)
|
||
* The memory address is fixed.
|
||
* Note: This pattern seems to be common that not only exists in Alchemist games.
|
||
*
|
||
* Not work on 0.9.9: Amnesia Crowd
|
||
*
|
||
* Debug method: simply add hardware break points to the matched memory
|
||
*
|
||
* PPSSPP 0.9.8, your diary+
|
||
* 134076f2 cc int3
|
||
* 134076f3 cc int3
|
||
* 134076f4 77 0f ja short 13407705
|
||
* 134076f6 c705 a8aa1001 40>mov dword ptr ds:[0x110aaa8],0x8931040
|
||
* 13407700 -e9 ff88f2f3 jmp 07330004
|
||
* 13407705 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 1340770b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13407711 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000] // jichi: hook here
|
||
* 13407718 8b3d 78a71001 mov edi,dword ptr ds:[0x110a778]
|
||
* 1340771e 8b2d 7ca71001 mov ebp,dword ptr ds:[0x110a77c]
|
||
* 13407724 81c5 01000000 add ebp,0x1
|
||
* 1340772a 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 13407730 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13407736 8bd6 mov edx,esi
|
||
* 13407738 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl // jichi: alternatively hook here
|
||
* 1340773e 8b15 78a71001 mov edx,dword ptr ds:[0x110a778]
|
||
* 13407744 81c2 01000000 add edx,0x1
|
||
* 1340774a 8bcd mov ecx,ebp
|
||
* 1340774c 8935 88a71001 mov dword ptr ds:[0x110a788],esi
|
||
* 13407752 8bf2 mov esi,edx
|
||
* 13407754 813d 88a71001 00>cmp dword ptr ds:[0x110a788],0x0
|
||
* 1340775e 893d 70a71001 mov dword ptr ds:[0x110a770],edi
|
||
* 13407764 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 1340776a 890d 7ca71001 mov dword ptr ds:[0x110a77c],ecx
|
||
* 13407770 8915 80a71001 mov dword ptr ds:[0x110a780],edx
|
||
* 13407776 892d 84a71001 mov dword ptr ds:[0x110a784],ebp
|
||
* 1340777c 0f85 16000000 jnz 13407798
|
||
* 13407782 832d c4aa1001 08 sub dword ptr ds:[0x110aac4],0x8
|
||
* 13407789 e9 ce000000 jmp 1340785c
|
||
* 1340778e 017c10 93 add dword ptr ds:[eax+edx-0x6d],edi
|
||
* 13407792 08e9 or cl,ch
|
||
* 13407794 8b88 f2f3832d mov ecx,dword ptr ds:[eax+0x2d83f3f2]
|
||
* 1340779a c4aa 100108e9 les ebp,fword ptr ds:[edx+0xe9080110] ; modification of segment register
|
||
* 134077a0 0c 00 or al,0x0
|
||
* 134077a2 0000 add byte ptr ds:[eax],al
|
||
* 134077a4 0160 10 add dword ptr ds:[eax+0x10],esp
|
||
* 134077a7 93 xchg eax,ebx
|
||
* 134077a8 08e9 or cl,ch
|
||
* 134077aa ^75 88 jnz short 13407734
|
||
* 134077ac f2: prefix repne: ; superfluous prefix
|
||
* 134077ad f3: prefix rep: ; superfluous prefix
|
||
* 134077ae 90 nop
|
||
* 134077af cc int3
|
||
*/
|
||
|
||
namespace { // unnamed
|
||
|
||
// Return true if the text is a garbage character
|
||
inline bool _alchemistgarbage_ch(char c)
|
||
{
|
||
return c == '.' || c == '/'
|
||
|| c == '#' || c == ':' // garbage in alchemist2 hook
|
||
|| c >= '0' && c <= '9'
|
||
|| c >= 'A' && c <= 'z' // also ignore ASCII 91-96: [ \ ] ^ _ `
|
||
;
|
||
}
|
||
|
||
// Return true if the text is full of garbage characters
|
||
bool _alchemistgarbage(LPCSTR p)
|
||
{
|
||
enum { MAX_LENGTH = VNR_TEXT_CAPACITY };
|
||
for (int count = 0; *p && count < MAX_LENGTH; count++, p++)
|
||
if (!_alchemistgarbage_ch(*p))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
// 7/20/2014 jichi: Trim Rejet garbage. Sample game: 月華繚乱ROMANCE
|
||
// Such as: #Pos[1,2]
|
||
inline bool _rejetgarbage_ch(char c)
|
||
{
|
||
return c == '#' || c == ' ' || c == '[' || c == ']' || c == ','
|
||
|| c >= 'A' && c <= 'z' // also ignore ASCII 91-96: [ \ ] ^ _ `
|
||
|| c >= '0' && c <= '9';
|
||
}
|
||
|
||
bool _rejetgarbage(LPCSTR p)
|
||
{
|
||
enum { MAX_LENGTH = VNR_TEXT_CAPACITY };
|
||
for (int count = 0; *p && count < MAX_LENGTH; count++, p++)
|
||
if (!_rejetgarbage_ch(*p))
|
||
return false;
|
||
return true;
|
||
}
|
||
|
||
// Trim leading garbage
|
||
LPCSTR _rejetltrim(LPCSTR p)
|
||
{
|
||
enum { MAX_LENGTH = VNR_TEXT_CAPACITY };
|
||
if (p)
|
||
for (int count = 0; *p && count < MAX_LENGTH; count++, p++)
|
||
if (!_rejetgarbage_ch(*p))
|
||
return p;
|
||
return nullptr;
|
||
}
|
||
|
||
// Trim trailing garbage
|
||
size_t _rejetstrlen(LPCSTR text)
|
||
{
|
||
if (!text)
|
||
return 0;
|
||
size_t len = ::strlen(text),
|
||
ret = len;
|
||
while (len && _rejetgarbage_ch(text[len - 1])) {
|
||
len--;
|
||
if (text[len] == '#') // in case trim UTF-8 trailing bytes
|
||
ret = len;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
} // unnamed namespace
|
||
|
||
static void SpecialPSPHookAlchemist(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
if (*text && !_alchemistgarbage(text)) {
|
||
text = _rejetltrim(text);
|
||
*data = (DWORD)text;
|
||
*len = _rejetstrlen(text);
|
||
*split = stack->ecx;
|
||
}
|
||
}
|
||
|
||
bool InsertAlchemistPSPHook()
|
||
{
|
||
ConsoleOutput("Alchemist PSP: enter");
|
||
const BYTE bytes[] = {
|
||
//0xcc, // 134076f2 cc int3
|
||
//0xcc, // 134076f3 cc int3
|
||
0x77, 0x0f, // 134076f4 77 0f ja short 13407705
|
||
0xc7,0x05, XX8, // 134076f6 c705 a8aa1001 40>mov dword ptr ds:[0x110aaa8],0x8931040
|
||
0xe9, XX4, // 13407700 -e9 ff88f2f3 jmp 07330004
|
||
0x8b,0x05, XX4, // 13407705 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1340770b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 13407711 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000] // jichi: hook here
|
||
0x8b,0x3d, XX4, // 13407718 8b3d 78a71001 mov edi,dword ptr ds:[0x110a778]
|
||
0x8b,0x2d, XX4, // 1340771e 8b2d 7ca71001 mov ebp,dword ptr ds:[0x110a77c]
|
||
0x81,0xc5, 0x01,0x00,0x00,0x00, // 13407724 81c5 01000000 add ebp,0x1
|
||
0x8b,0x05, XX4, // 1340772a 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13407730 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xd6, // 13407736 8bd6 mov edx,esi
|
||
0x88,0x90 //, XX4 // 13407738 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl // jichi: alternatively hook here
|
||
};
|
||
enum { memory_offset = 3 }; // 13407711 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = 0x13407711 - 0x134076f4 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
//GROWL_DWORD(addr);
|
||
if (!addr)
|
||
ConsoleOutput("Alchemist PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.text_fun = SpecialPSPHookAlchemist;
|
||
hp.type = USING_STRING|NO_CONTEXT; // no context is needed to get rid of variant retaddr
|
||
ConsoleOutput("Alchemist PSP: INSERT");
|
||
succ|=NewHook(hp, "Alchemist PSP");
|
||
}
|
||
|
||
ConsoleOutput("Alchemist PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 8/12/2014 jichi Konami.jp PSP engine, 0.9.8, 0.9.9,
|
||
* Though Alchemist/Otomate can work, it has bad split that creates too many threads.
|
||
*
|
||
* Sample game: 幻想水滸<E6B0B4>紡がれし百年の<E5B9B4>on 0.9.8, 0.9.9
|
||
*
|
||
* Memory address is FIXED.
|
||
* But hardware accesses are looped.
|
||
* Debug method: predict and breakpoint the memory address
|
||
*
|
||
* There are two matches in the memory.
|
||
* Three looped functions are as follows.
|
||
* I randomply picked the first one.
|
||
*
|
||
* It cannot extract character names.
|
||
*
|
||
* 14178f73 cc int3
|
||
* 14178f74 77 0f ja short 14178f85
|
||
* 14178f76 c705 c84c1301 a4>mov dword ptr ds:[0x1134cc8],0x88129a4
|
||
* 14178f80 -e9 7f7071ef jmp 03890004
|
||
* 14178f85 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
* 14178f8b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14178f91 0fbeb0 00000008 movsx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here, loop
|
||
* 14178f98 81fe 40000000 cmp esi,0x40
|
||
* 14178f9e 8935 98491301 mov dword ptr ds:[0x1134998],esi
|
||
* 14178fa4 c705 9c491301 40>mov dword ptr ds:[0x113499c],0x40
|
||
* 14178fae 0f85 2f000000 jnz 14178fe3
|
||
* 14178fb4 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
* 14178fba 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14178fc0 0fbeb0 01000008 movsx esi,byte ptr ds:[eax+0x8000001]
|
||
* 14178fc7 8935 98491301 mov dword ptr ds:[0x1134998],esi
|
||
* 14178fcd 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
* 14178fd4 c705 c84c1301 d0>mov dword ptr ds:[0x1134cc8],0x88129d0
|
||
* 14178fde -e9 407071ef jmp 03890023
|
||
* 14178fe3 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
* 14178fea e9 0d000000 jmp 14178ffc
|
||
* 14178fef 01b429 8108e92a add dword ptr ds:[ecx+ebp+0x2ae90881],es>
|
||
* 14178ff6 70 71 jo short 14179069
|
||
* 14178ff8 ef out dx,eax ; i/o command
|
||
* 14178ff9 90 nop
|
||
* 14178ffa cc int3
|
||
*
|
||
* 1417a18c 77 0f ja short 1417a19d
|
||
* 1417a18e c705 c84c1301 78>mov dword ptr ds:[0x1134cc8],0x8818378
|
||
* 1417a198 -e9 675e71ef jmp 03890004
|
||
* 1417a19d 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
* 1417a1a3 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1417a1a9 0fbeb0 00000008 movsx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here, loop
|
||
* 1417a1b0 81fe 0a000000 cmp esi,0xa
|
||
* 1417a1b6 8935 98491301 mov dword ptr ds:[0x1134998],esi
|
||
* 1417a1bc c705 9c491301 0a>mov dword ptr ds:[0x113499c],0xa
|
||
* 1417a1c6 0f84 2e000000 je 1417a1fa
|
||
* 1417a1cc 8b05 fc491301 mov eax,dword ptr ds:[0x11349fc]
|
||
* 1417a1d2 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1417a1d8 8bb0 18000008 mov esi,dword ptr ds:[eax+0x8000018]
|
||
* 1417a1de 8935 98491301 mov dword ptr ds:[0x1134998],esi
|
||
* 1417a1e4 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
* 1417a1eb e9 24000000 jmp 1417a214
|
||
* 1417a1f0 01b0 838108e9 add dword ptr ds:[eax+0xe9088183],esi
|
||
* 1417a1f6 295e 71 sub dword ptr ds:[esi+0x71],ebx
|
||
* 1417a1f9 ef out dx,eax ; i/o command
|
||
* 1417a1fa 832d e44c1301 04 sub dword ptr ds:[0x1134ce4],0x4
|
||
* 1417a201 e9 1e660000 jmp 14180824
|
||
* 1417a206 0188 838108e9 add dword ptr ds:[eax+0xe9088183],ecx
|
||
* 1417a20c 135e 71 adc ebx,dword ptr ds:[esi+0x71]
|
||
* 1417a20f ef out dx,eax ; i/o command
|
||
* 1417a210 90 nop
|
||
* 1417a211 cc int3
|
||
* 1417a212 cc int3
|
||
*
|
||
* 1417a303 90 nop
|
||
* 1417a304 77 0f ja short 1417a315
|
||
* 1417a306 c705 c84c1301 48>mov dword ptr ds:[0x1134cc8],0x8818448
|
||
* 1417a310 -e9 ef5c71ef jmp 03890004
|
||
* 1417a315 8b35 dc491301 mov esi,dword ptr ds:[0x11349dc]
|
||
* 1417a31b 8b3d 98491301 mov edi,dword ptr ds:[0x1134998]
|
||
* 1417a321 33c0 xor eax,eax
|
||
* 1417a323 3bf7 cmp esi,edi
|
||
* 1417a325 0f9cc0 setl al
|
||
* 1417a328 8bf8 mov edi,eax
|
||
* 1417a32a 81ff 00000000 cmp edi,0x0
|
||
* 1417a330 893d 98491301 mov dword ptr ds:[0x1134998],edi
|
||
* 1417a336 0f84 2f000000 je 1417a36b
|
||
* 1417a33c 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
* 1417a342 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1417a348 0fbeb0 00000008 movsx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here, loop
|
||
* 1417a34f 8935 98491301 mov dword ptr ds:[0x1134998],esi
|
||
* 1417a355 832d e44c1301 03 sub dword ptr ds:[0x1134ce4],0x3
|
||
* 1417a35c e9 23000000 jmp 1417a384
|
||
* 1417a361 018484 8108e9b8 add dword ptr ss:[esp+eax*4+0xb8e90881],>
|
||
* 1417a368 5c pop esp
|
||
* 1417a369 ^71 ef jno short 1417a35a
|
||
* 1417a36b 832d e44c1301 03 sub dword ptr ds:[0x1134ce4],0x3
|
||
* 1417a372 c705 c84c1301 54>mov dword ptr ds:[0x1134cc8],0x8818454
|
||
* 1417a37c -e9 a25c71ef jmp 03890023
|
||
* 1417a381 90 nop
|
||
* 1417a382 cc int3
|
||
*/
|
||
// Read text from looped address word by word
|
||
// Use reverse search to avoid looping issue assume the text is at fixed address.
|
||
static void SpecialPSPHookKonami(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
//static LPCSTR lasttext; // this value should be the same for the same game
|
||
static size_t lastsize;
|
||
|
||
DWORD eax = stack->eax;
|
||
LPCSTR cur = LPCSTR(eax + hp->user_value);
|
||
if (!*cur)
|
||
return;
|
||
|
||
LPCSTR text = reverse_search_begin(cur);
|
||
if (!text)
|
||
return;
|
||
//if (lasttext != text) {
|
||
// lasttext = text;
|
||
// lastsize = 0; // reset last size
|
||
//}
|
||
|
||
size_t size = ::strlen(text);
|
||
if (size == lastsize)
|
||
return;
|
||
|
||
*len = lastsize = size;
|
||
*data = (DWORD)text;
|
||
|
||
*split = stack->ebx; // ecx changes for each character, ebx is an address, edx is stable, but very large
|
||
}
|
||
bool InsertKonamiPSPHook()
|
||
{
|
||
ConsoleOutput("KONAMI PSP: enter");
|
||
const BYTE bytes[] = {
|
||
// 14178f73 cc int3
|
||
0x77, 0x0f, // 14178f74 77 0f ja short 14178f85
|
||
0xc7,0x05, XX8, // 14178f76 c705 c84c1301 a4>mov dword ptr ds:[0x1134cc8],0x88129a4
|
||
0xe9, XX4, // 14178f80 -e9 7f7071ef jmp 03890004
|
||
0x8b,0x05, XX4, // 14178f85 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14178f8b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 14178f91 0fbeb0 00000008 movsx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here, loop
|
||
0x81,0xfe, 0x40,0x00,0x00,0x00, // 14178f98 81fe 40000000 cmp esi,0x40
|
||
0x89,0x35 //, XX4, // 14178f9e 8935 98491301 mov dword ptr ds:[0x1134998],esi
|
||
//0xc7,0x05, XX4, 0x40,0x00,0x00,0x00, // 14178fa4 c705 9c491301 40>mov dword ptr ds:[0x113499c],0x40
|
||
//0x0f,0x85, 0x2f,0x00,0x00,0x00,0x00, // 14178fae 0f85 2f000000 jnz 14178fe3
|
||
//0x8b,0x05, XX4 // 14178fb4 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x14178f91 - 0x14178f74 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("KONAMI PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookKonami;
|
||
ConsoleOutput("KONAMI PSP: INSERT");
|
||
succ|=NewHook(hp, "KONAMI PSP");
|
||
}
|
||
|
||
ConsoleOutput("KONAMI PSP: leave");
|
||
return succ;
|
||
}
|
||
/** 7/13/2014 jichi 5pb.jp PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: STEINS;GATE
|
||
*
|
||
* FIXME: The current pattern could crash VNR
|
||
*
|
||
* Note: searching after 0x15000000 would found a wrong address on 0.9.9.
|
||
* Hooking to it would crash PPSSPP.
|
||
*
|
||
* Float memory addresses: two matches
|
||
*
|
||
* Debug method: precompute memory address and set break points, then navigate to that scene
|
||
*
|
||
* Attach to this function for wrong game might cause BEX (buffer overflow) exception.
|
||
*
|
||
* 135752c7 90 nop
|
||
* 135752c8 77 0f ja short 135752d9
|
||
* 135752ca c705 a8aa1001 d4>mov dword ptr ds:[0x110aaa8],0x8888ed4
|
||
* 135752d4 -e9 2badf3ef jmp 034b0004
|
||
* 135752d9 8b35 dca71001 mov esi,dword ptr ds:[0x110a7dc]
|
||
* 135752df 8d76 a0 lea esi,dword ptr ds:[esi-0x60]
|
||
* 135752e2 8b3d e4a71001 mov edi,dword ptr ds:[0x110a7e4]
|
||
* 135752e8 8bc6 mov eax,esi
|
||
* 135752ea 81e0 ffffff3f and eax,0x3fffffff
|
||
* 135752f0 89b8 1c004007 mov dword ptr ds:[eax+0x740001c],edi
|
||
* 135752f6 8b2d bca71001 mov ebp,dword ptr ds:[0x110a7bc]
|
||
* 135752fc 8bc6 mov eax,esi
|
||
* 135752fe 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575304 89a8 18004007 mov dword ptr ds:[eax+0x7400018],ebp
|
||
* 1357530a 8b15 b8a71001 mov edx,dword ptr ds:[0x110a7b8]
|
||
* 13575310 8bc6 mov eax,esi
|
||
* 13575312 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575318 8990 14004007 mov dword ptr ds:[eax+0x7400014],edx
|
||
* 1357531e 8b0d b4a71001 mov ecx,dword ptr ds:[0x110a7b4]
|
||
* 13575324 8bc6 mov eax,esi
|
||
* 13575326 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1357532c 8988 10004007 mov dword ptr ds:[eax+0x7400010],ecx
|
||
* 13575332 8b3d b0a71001 mov edi,dword ptr ds:[0x110a7b0]
|
||
* 13575338 8bc6 mov eax,esi
|
||
* 1357533a 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575340 89b8 0c004007 mov dword ptr ds:[eax+0x740000c],edi
|
||
* 13575346 8b3d aca71001 mov edi,dword ptr ds:[0x110a7ac]
|
||
* 1357534c 8bc6 mov eax,esi
|
||
* 1357534e 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575354 89b8 08004007 mov dword ptr ds:[eax+0x7400008],edi
|
||
* 1357535a 8b3d a8a71001 mov edi,dword ptr ds:[0x110a7a8]
|
||
* 13575360 8bc6 mov eax,esi
|
||
* 13575362 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575368 89b8 04004007 mov dword ptr ds:[eax+0x7400004],edi
|
||
* 1357536e 8b15 78a71001 mov edx,dword ptr ds:[0x110a778]
|
||
* 13575374 8935 dca71001 mov dword ptr ds:[0x110a7dc],esi
|
||
* 1357537a 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 13575380 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575386 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 1357538d 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 13575393 8b35 80a71001 mov esi,dword ptr ds:[0x110a780]
|
||
* 13575399 8935 b0a71001 mov dword ptr ds:[0x110a7b0],esi
|
||
* 1357539f 8b35 84a71001 mov esi,dword ptr ds:[0x110a784]
|
||
* 135753a5 8b0d 7ca71001 mov ecx,dword ptr ds:[0x110a77c]
|
||
* 135753ab 813d 78a71001 00>cmp dword ptr ds:[0x110a778],0x0
|
||
* 135753b5 c705 a8a71001 00>mov dword ptr ds:[0x110a7a8],0x0
|
||
* 135753bf 8935 aca71001 mov dword ptr ds:[0x110a7ac],esi
|
||
* 135753c5 890d b4a71001 mov dword ptr ds:[0x110a7b4],ecx
|
||
* 135753cb 8915 b8a71001 mov dword ptr ds:[0x110a7b8],edx
|
||
* 135753d1 0f85 16000000 jnz 135753ed
|
||
* 135753d7 832d c4aa1001 0f sub dword ptr ds:[0x110aac4],0xf
|
||
* 135753de e9 e5010000 jmp 135755c8
|
||
* 135753e3 01f0 add eax,esi
|
||
* 135753e5 90 nop
|
||
* 135753e6 8808 mov byte ptr ds:[eax],cl
|
||
* 135753e8 -e9 36acf3ef jmp 034b0023
|
||
* 135753ed 832d c4aa1001 0f sub dword ptr ds:[0x110aac4],0xf
|
||
* 135753f4 e9 0b000000 jmp 13575404
|
||
* 135753f9 0110 add dword ptr ds:[eax],edx
|
||
* 135753fb 8f ??? ; unknown command
|
||
* 135753fc 8808 mov byte ptr ds:[eax],cl
|
||
* 135753fe -e9 20acf3ef jmp 034b0023
|
||
* 13575403 90 nop
|
||
* 13575404 77 0f ja short 13575415
|
||
* 13575406 c705 a8aa1001 10>mov dword ptr ds:[0x110aaa8],0x8888f10
|
||
* 13575410 -e9 efabf3ef jmp 034b0004
|
||
* 13575415 8b35 a8a71001 mov esi,dword ptr ds:[0x110a7a8]
|
||
* 1357541b 33c0 xor eax,eax
|
||
* 1357541d 3b35 b0a71001 cmp esi,dword ptr ds:[0x110a7b0]
|
||
* 13575423 0f9cc0 setl al
|
||
* 13575426 8bf8 mov edi,eax
|
||
* 13575428 81ff 00000000 cmp edi,0x0
|
||
* 1357542e 893d 74a71001 mov dword ptr ds:[0x110a774],edi
|
||
* 13575434 0f84 22000000 je 1357545c
|
||
* 1357543a 8b35 b4a71001 mov esi,dword ptr ds:[0x110a7b4]
|
||
* 13575440 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 13575446 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 1357544d c705 a8aa1001 2c>mov dword ptr ds:[0x110aaa8],0x8888f2c
|
||
* 13575457 -e9 c7abf3ef jmp 034b0023
|
||
* 1357545c 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 13575463 e9 0c000000 jmp 13575474
|
||
* 13575468 011c8f add dword ptr ds:[edi+ecx*4],ebx
|
||
* 1357546b 8808 mov byte ptr ds:[eax],cl
|
||
* 1357546d -e9 b1abf3ef jmp 034b0023
|
||
* 13575472 90 nop
|
||
* 13575473 cc int3
|
||
* 13575474 77 0f ja short 13575485
|
||
* 13575476 c705 a8aa1001 1c>mov dword ptr ds:[0x110aaa8],0x8888f1c
|
||
* 13575480 -e9 7fabf3ef jmp 034b0004
|
||
* 13575485 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
* 1357548b 8b05 b8a71001 mov eax,dword ptr ds:[0x110a7b8]
|
||
* 13575491 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13575497 8bd6 mov edx,esi
|
||
* 13575499 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl
|
||
* 1357549f 8b3d b4a71001 mov edi,dword ptr ds:[0x110a7b4]
|
||
* 135754a5 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 135754a8 8b2d b8a71001 mov ebp,dword ptr ds:[0x110a7b8]
|
||
* 135754ae 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 135754b1 813d 68a71001 00>cmp dword ptr ds:[0x110a768],0x0
|
||
* 135754bb 893d b4a71001 mov dword ptr ds:[0x110a7b4],edi
|
||
* 135754c1 892d b8a71001 mov dword ptr ds:[0x110a7b8],ebp
|
||
* 135754c7 0f85 16000000 jnz 135754e3
|
||
* 135754cd 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 135754d4 e9 23000000 jmp 135754fc
|
||
* 135754d9 01e4 add esp,esp
|
||
* 135754db 90 nop
|
||
* 135754dc 8808 mov byte ptr ds:[eax],cl
|
||
* 135754de -e9 40abf3ef jmp 034b0023
|
||
* 135754e3 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 135754ea c705 a8aa1001 2c>mov dword ptr ds:[0x110aaa8],0x8888f2c
|
||
* 135754f4 -e9 2aabf3ef jmp 034b0023
|
||
* 135754f9 90 nop
|
||
* 135754fa cc int3
|
||
* 135754fb cc int3
|
||
*/
|
||
namespace { // unnamed
|
||
|
||
// Characters to ignore: [%0-9A-Z]
|
||
inline bool _5pbgarbage_ch(char c)
|
||
{ return c == '%' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9'; }
|
||
|
||
// Trim leading garbage
|
||
LPCSTR _5pbltrim(LPCSTR p)
|
||
{
|
||
enum { MAX_LENGTH = VNR_TEXT_CAPACITY };
|
||
if (p)
|
||
for (int count = 0; *p && count < MAX_LENGTH; count++, p++)
|
||
if (!_5pbgarbage_ch(*p))
|
||
return p;
|
||
return nullptr;
|
||
}
|
||
|
||
// Trim trailing garbage
|
||
size_t _5pbstrlen(LPCSTR text)
|
||
{
|
||
if (!text)
|
||
return 0;
|
||
size_t len = ::strlen(text),
|
||
ret = len;
|
||
while (len && _5pbgarbage_ch(text[len - 1])) {
|
||
len--;
|
||
if (text[len] == '%') // in case trim UTF-8 trailing bytes
|
||
ret = len;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
} // unnamed namespace
|
||
|
||
static void SpecialPSPHook5pb(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
if (*text) {
|
||
text = _5pbltrim(text);
|
||
*data = (DWORD)text;
|
||
*len = _5pbstrlen(text);
|
||
*split = stack->ecx;
|
||
//*split = FIXED_SPLIT_VALUE; // there is only one thread, no split used
|
||
}
|
||
}
|
||
|
||
bool Insert5pbPSPHook()
|
||
{
|
||
ConsoleOutput("5pb PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
//0x90, // 135752c7 90 nop
|
||
0x77, 0x0f, // 135752c8 77 0f ja short 135752d9
|
||
0xc7,0x05, XX8, // 135752ca c705 a8aa1001 d4>mov dword ptr ds:[0x110aaa8],0x8888ed4
|
||
0xe9, XX4, // 135752d4 -e9 2badf3ef jmp 034b0004
|
||
0x8b,0x35, XX4, // 135752d9 8b35 dca71001 mov esi,dword ptr ds:[0x110a7dc]
|
||
0x8d,0x76, 0xa0, // 135752df 8d76 a0 lea esi,dword ptr ds:[esi-0x60]
|
||
0x8b,0x3d, XX4, // 135752e2 8b3d e4a71001 mov edi,dword ptr ds:[0x110a7e4]
|
||
0x8b,0xc6, // 135752e8 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 135752ea 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb8, XX4, // 135752f0 89b8 1c004007 mov dword ptr ds:[eax+0x740001c],edi
|
||
0x8b,0x2d, XX4, // 135752f6 8b2d bca71001 mov ebp,dword ptr ds:[0x110a7bc]
|
||
0x8b,0xc6, // 135752fc 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 135752fe 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xa8, XX4, // 13575304 89a8 18004007 mov dword ptr ds:[eax+0x7400018],ebp
|
||
0x8b,0x15, XX4, // 1357530a 8b15 b8a71001 mov edx,dword ptr ds:[0x110a7b8]
|
||
0x8b,0xc6, // 13575310 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13575312 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0x90, XX4, // 13575318 8990 14004007 mov dword ptr ds:[eax+0x7400014],edx
|
||
0x8b,0x0d, XX4, // 1357531e 8b0d b4a71001 mov ecx,dword ptr ds:[0x110a7b4]
|
||
0x8b,0xc6, // 13575324 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13575326 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0x88, XX4, // 1357532c 8988 10004007 mov dword ptr ds:[eax+0x7400010],ecx
|
||
0x8b,0x3d, XX4, // 13575332 8b3d b0a71001 mov edi,dword ptr ds:[0x110a7b0]
|
||
0x8b,0xc6, // 13575338 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1357533a 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb8, XX4, // 13575340 89b8 0c004007 mov dword ptr ds:[eax+0x740000c],edi
|
||
0x8b,0x3d, XX4, // 13575346 8b3d aca71001 mov edi,dword ptr ds:[0x110a7ac]
|
||
0x8b,0xc6, // 1357534c 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1357534e 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb8, XX4, // 13575354 89b8 08004007 mov dword ptr ds:[eax+0x7400008],edi
|
||
0x8b,0x3d, XX4, // 1357535a 8b3d a8a71001 mov edi,dword ptr ds:[0x110a7a8]
|
||
0x8b,0xc6, // 13575360 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13575362 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb8, XX4, // 13575368 89b8 04004007 mov dword ptr ds:[eax+0x7400004],edi
|
||
0x8b,0x15, XX4, // 1357536e 8b15 78a71001 mov edx,dword ptr ds:[0x110a778]
|
||
0x89,0x35, XX4, // 13575374 8935 dca71001 mov dword ptr ds:[0x110a7dc],esi
|
||
0x8b,0x05, XX4, // 1357537a 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13575380 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0 //, XX4 // 13575386 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
};
|
||
enum { memory_offset = 3 }; // 13575386 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = sizeof(bytes) - memory_offset };
|
||
|
||
enum : DWORD { start = MemDbg::MappedMemoryStartAddress };
|
||
DWORD stop = PPSSPP_VERSION[1] == 9 && PPSSPP_VERSION[2] == 8 ? MemDbg::MemoryStopAddress : 0x15000000;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes), start, stop);
|
||
//GROWL_DWORD(addr);
|
||
auto succ=false;
|
||
if (!addr)
|
||
ConsoleOutput("5pb PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.text_fun = SpecialPSPHook5pb;
|
||
hp.type = USING_STRING|NO_CONTEXT; // no context is needed to get rid of variant retaddr
|
||
ConsoleOutput("5pb PSP: INSERT");
|
||
succ|=NewHook(hp, "5pb PSP");
|
||
}
|
||
|
||
ConsoleOutput("5pb PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/19/2014 jichi kid-game.co.jp PSP engine, 0,9.8, 0.9.9
|
||
* Sample game: Monochrome
|
||
*
|
||
* Note: sceFontGetCharInfo, sceFontGetCharGlyphImage_Clip also works
|
||
*
|
||
* Debug method: breakpoint the memory address
|
||
* There are two matched memory address to the current text
|
||
*
|
||
* == Second run ==
|
||
* 13973a7b 90 nop
|
||
* 13973a7c 77 0f ja short 13973a8d
|
||
* 13973a7e c705 a8aa1001 90>mov dword ptr ds:[0x110aaa8],0x885c290
|
||
* 13973a88 -e9 77c5ecef jmp 03840004
|
||
* 13973a8d 8b05 90a71001 mov eax,dword ptr ds:[0x110a790]
|
||
* 13973a93 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13973a99 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000]
|
||
* 13973aa0 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 13973aa6 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13973aac 0fb6b8 00008007 movzx edi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 13973ab3 81fe 00000000 cmp esi,0x0
|
||
* 13973ab9 c705 8ca71001 00>mov dword ptr ds:[0x110a78c],0x0
|
||
* 13973ac3 893d 9ca71001 mov dword ptr ds:[0x110a79c],edi
|
||
* 13973ac9 8935 a0a71001 mov dword ptr ds:[0x110a7a0],esi
|
||
* 13973acf 0f85 16000000 jnz 13973aeb
|
||
* 13973ad5 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 13973adc c705 a8aa1001 d0>mov dword ptr ds:[0x110aaa8],0x885c2d0
|
||
* 13973ae6 -e9 38c5ecef jmp 03840023
|
||
* 13973aeb 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 13973af2 e9 0d000000 jmp 13973b04
|
||
* 13973af7 01a0 c28508e9 add dword ptr ds:[eax+0xe90885c2],esp
|
||
* 13973afd 22c5 and al,ch
|
||
* 13973aff ec in al,dx ; i/o command
|
||
* 13973b00 ef out dx,eax ; i/o command
|
||
* 13973b01 90 nop
|
||
* 13973b02 cc int3
|
||
* 13973b03 cc int3
|
||
*
|
||
* == First run ==
|
||
* 1087394a cc int3
|
||
* 1087394b cc int3
|
||
* 1087394c 77 0f ja short 1087395d
|
||
* 1087394e c705 a8aa1001 78>mov dword ptr ds:[0x110aaa8],0x885c278
|
||
* 10873958 -e9 a7c6bff2 jmp 03470004
|
||
* 1087395d 8b35 80d0da12 mov esi,dword ptr ds:[0x12dad080]
|
||
* 10873963 8bc6 mov eax,esi
|
||
* 10873965 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1087396b 8bb8 0000000a mov edi,dword ptr ds:[eax+0xa000000]
|
||
* 10873971 81ff 00000000 cmp edi,0x0
|
||
* 10873977 c705 70a71001 00>mov dword ptr ds:[0x110a770],0x8db0000
|
||
* 10873981 c705 74a71001 00>mov dword ptr ds:[0x110a774],0x0
|
||
* 1087398b 893d 90a71001 mov dword ptr ds:[0x110a790],edi
|
||
* 10873991 8935 94a71001 mov dword ptr ds:[0x110a794],esi
|
||
* 10873997 c705 98a71001 00>mov dword ptr ds:[0x110a798],0x0
|
||
* 108739a1 0f85 16000000 jnz 108739bd
|
||
* 108739a7 832d c4aa1001 06 sub dword ptr ds:[0x110aac4],0x6
|
||
* 108739ae e9 75c20100 jmp 1088fc28
|
||
* 108739b3 0148 c3 add dword ptr ds:[eax-0x3d],ecx
|
||
* 108739b6 8508 test dword ptr ds:[eax],ecx
|
||
* 108739b8 -e9 66c6bff2 jmp 03470023
|
||
* 108739bd 832d c4aa1001 06 sub dword ptr ds:[0x110aac4],0x6
|
||
* 108739c4 e9 0b000000 jmp 108739d4
|
||
* 108739c9 0190 c28508e9 add dword ptr ds:[eax+0xe90885c2],edx
|
||
* 108739cf 50 push eax
|
||
* 108739d0 c6 ??? ; unknown command
|
||
* 108739d1 bf f290770f mov edi,0xf7790f2
|
||
* 108739d6 c705 a8aa1001 90>mov dword ptr ds:[0x110aaa8],0x885c290
|
||
* 108739e0 -e9 1fc6bff2 jmp 03470004
|
||
* 108739e5 8b05 90a71001 mov eax,dword ptr ds:[0x110a790]
|
||
* 108739eb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 108739f1 0fb6b0 0000000a movzx esi,byte ptr ds:[eax+0xa000000] ; jichi: hook here
|
||
* 108739f8 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 108739fe 81e0 ffffff3f and eax,0x3fffffff
|
||
* 10873a04 0fb6b8 0000000a movzx edi,byte ptr ds:[eax+0xa000000] ; jichi: hook here
|
||
* 10873a0b 81fe 00000000 cmp esi,0x0
|
||
* 10873a11 c705 8ca71001 00>mov dword ptr ds:[0x110a78c],0x0
|
||
* 10873a1b 893d 9ca71001 mov dword ptr ds:[0x110a79c],edi
|
||
* 10873a21 8935 a0a71001 mov dword ptr ds:[0x110a7a0],esi
|
||
* 10873a27 0f85 16000000 jnz 10873a43
|
||
* 10873a2d 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 10873a34 c705 a8aa1001 d0>mov dword ptr ds:[0x110aaa8],0x885c2d0
|
||
* 10873a3e -e9 e0c5bff2 jmp 03470023
|
||
* 10873a43 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 10873a4a e9 0d000000 jmp 10873a5c
|
||
* 10873a4f 01a0 c28508e9 add dword ptr ds:[eax+0xe90885c2],esp
|
||
* 10873a55 ca c5bf retf 0xbfc5 ; far return
|
||
* 10873a58 f2: prefix repne: ; superfluous prefix
|
||
* 10873a59 90 nop
|
||
* 10873a5a cc int3
|
||
* 10873a5b cc int3
|
||
*/
|
||
static void SpecialPSPHookKid(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
static LPCSTR lasttext; // Prevent reading the same address multiple times
|
||
if (text != lasttext && *text) {
|
||
lasttext = text;
|
||
text = _5pbltrim(text);
|
||
*data = (DWORD)text;
|
||
*len = _5pbstrlen(text);
|
||
*split = stack->ecx;
|
||
}
|
||
}
|
||
|
||
bool InsertKidPSPHook()
|
||
{
|
||
ConsoleOutput("KID PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
//0x90, // 13973a7b 90 nop
|
||
0x77, 0x0f, // 13973a7c 77 0f ja short 13973a8d
|
||
0xc7,0x05, XX8, // 13973a7e c705 a8aa1001 90>mov dword ptr ds:[0x110aaa8],0x885c290
|
||
0xe9, XX4, // 13973a88 -e9 77c5ecef jmp 03840004
|
||
0x8b,0x05, XX4, // 13973a8d 8b05 90a71001 mov eax,dword ptr ds:[0x110a790]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13973a93 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb0, XX4, // 13973a99 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000]
|
||
0x8b,0x05, XX4, // 13973aa0 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13973aa6 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb8, XX4, // 13973aac 0fb6b8 00008007 movzx edi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
0x81,0xfe, 0x00,0x00,0x00,0x00 // 13973ab3 81fe 00000000 cmp esi,0x0
|
||
};
|
||
enum { memory_offset = 3 }; // 13973aac 0fb6b8 00008007 movzx edi,byte ptr ds:[eax+0x7800000]
|
||
enum { addr_offset = 0x13973aac - 0x13973a7c };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("KID PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.text_fun = SpecialPSPHookKid;
|
||
hp.type = USING_STRING|NO_CONTEXT; // no context is needed to get rid of variant retaddr
|
||
|
||
//HookParam hp;
|
||
//hp.address = addr + addr_offset;
|
||
//hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
//hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT; // Fix the split value to merge all threads
|
||
//hp.offset=get_reg(regs::eax);
|
||
//hp.split = get_reg(regs::ecx);
|
||
//hp.text_fun = SpecialPSPHook;
|
||
|
||
ConsoleOutput("KID PSP: INSERT");
|
||
succ|=NewHook(hp, "KID PSP");
|
||
}
|
||
|
||
ConsoleOutput("KID PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/13/2014 jichi imageepoch.co.jp PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: BLACK<43>OCK SHOOTER
|
||
*
|
||
* Float memory addresses: two matches, UTF-8
|
||
*
|
||
* 7/29/2014: seems to work on 0.9.9
|
||
*
|
||
* Debug method: find current sentence, then find next sentence in the memory
|
||
* and add break-points
|
||
*
|
||
* 1346d34b f0:90 lock nop ; lock prefix is not allowed
|
||
* 1346d34d cc int3
|
||
* 1346d34e cc int3
|
||
* 1346d34f cc int3
|
||
* 1346d350 77 0f ja short 1346d361
|
||
* 1346d352 c705 a8aa1001 e4>mov dword ptr ds:[0x110aaa8],0x89609e4
|
||
* 1346d35c -e9 a32c27f0 jmp 036e0004
|
||
* 1346d361 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 1346d367 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1346d36d 8bb0 00004007 mov esi,dword ptr ds:[eax+0x7400000] ; jichi: or hook here
|
||
* 1346d373 8b3d 78a71001 mov edi,dword ptr ds:[0x110a778]
|
||
* 1346d379 8bc6 mov eax,esi
|
||
* 1346d37b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1346d381 0fb6a8 00004007 movzx ebp,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 1346d388 8d56 01 lea edx,dword ptr ds:[esi+0x1]
|
||
* 1346d38b 8bc5 mov eax,ebp
|
||
* 1346d38d 0fbec8 movsx ecx,al
|
||
* 1346d390 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 1346d396 8bf5 mov esi,ebp
|
||
* 1346d398 81f9 00000000 cmp ecx,0x0
|
||
* 1346d39e 892d 74a71001 mov dword ptr ds:[0x110a774],ebp
|
||
* 1346d3a4 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 1346d3aa 8915 7ca71001 mov dword ptr ds:[0x110a77c],edx
|
||
* 1346d3b0 890d 80a71001 mov dword ptr ds:[0x110a780],ecx
|
||
* 1346d3b6 893d 84a71001 mov dword ptr ds:[0x110a784],edi
|
||
* 1346d3bc 0f8d 16000000 jge 1346d3d8
|
||
* 1346d3c2 832d c4aa1001 07 sub dword ptr ds:[0x110aac4],0x7
|
||
* 1346d3c9 e9 22000000 jmp 1346d3f0
|
||
* 1346d3ce 010c0a add dword ptr ds:[edx+ecx],ecx
|
||
* 1346d3d1 96 xchg eax,esi
|
||
* 1346d3d2 08e9 or cl,ch
|
||
* 1346d3d4 4b dec ebx
|
||
* 1346d3d5 2c 27 sub al,0x27
|
||
* 1346d3d7 f0:832d c4aa1001>lock sub dword ptr ds:[0x110aac4],0x7 ; lock prefix
|
||
* 1346d3df e9 bc380000 jmp 13470ca0
|
||
* 1346d3e4 0100 add dword ptr ds:[eax],eax
|
||
* 1346d3e6 0a96 08e9352c or dl,byte ptr ds:[esi+0x2c35e908]
|
||
* 1346d3ec 27 daa
|
||
* 1346d3ed f0:90 lock nop ; lock prefix is not allowed
|
||
* 1346d3ef cc int3
|
||
*/
|
||
static void SpecialPSPHookImageepoch(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
// 7/25/2014: I tried using uniquemap to eliminate duplication, which does not work
|
||
DWORD eax = stack->eax;
|
||
DWORD text = eax + hp->user_value;
|
||
static DWORD lasttext; // Prevent reading the same address multiple times
|
||
if (text != lasttext && *(LPCSTR)text) {
|
||
*data = lasttext = text;
|
||
*len = ::strlen((LPCSTR)text); // UTF-8 is null-terminated
|
||
*split = stack->ecx; // use ecx = "this" to split?
|
||
}
|
||
}
|
||
|
||
bool InsertImageepochPSPHook()
|
||
{
|
||
ConsoleOutput("Imageepoch PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
//0xcc, // 1346d34f cc int3
|
||
0x77, 0x0f, // 1346d350 77 0f ja short 1346d361
|
||
0xc7,0x05, XX8, // 1346d352 c705 a8aa1001 e4>mov dword ptr ds:[0x110aaa8],0x89609e4
|
||
0xe9, XX4, // 1346d35c -e9 a32c27f0 jmp 036e0004
|
||
0x8b,0x05, XX4, // 1346d361 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1346d367 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb0, XX4, // 1346d36d 8bb0 00004007 mov esi,dword ptr ds:[eax+0x7400000] ; jichi: or hook here
|
||
0x8b,0x3d, XX4, // 1346d373 8b3d 78a71001 mov edi,dword ptr ds:[0x110a778]
|
||
0x8b,0xc6, // 1346d379 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1346d37b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xa8, XX4, // 1346d381 0fb6a8 00004007 movzx ebp,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x8d,0x56, 0x01, // 1346d388 8d56 01 lea edx,dword ptr ds:[esi+0x1]
|
||
0x8b,0xc5, // 1346d38b 8bc5 mov eax,ebp
|
||
0x0f,0xbe,0xc8 // 1346d38d 0fbec8 movsx ecx,al
|
||
};
|
||
enum { memory_offset = 3 }; // 1346d381 0fb6a8 00004007 movzx ebp,byte ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = 0x1346d381 - 0x1346d350 };
|
||
//enum { addr_offset = sizeof(bytes) - memory_offset };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Imageepoch PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT; // UTF-8, though
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.split = get_reg(regs::ecx);
|
||
//hp.text_fun = SpecialPSPHook;
|
||
hp.text_fun = SpecialPSPHookImageepoch; // since this function is common, use its own static lasttext for HPF_IgnoreSameAddress
|
||
ConsoleOutput("Imageepoch PSP: INSERT");
|
||
succ|=NewHook(hp, "Imageepoch PSP");
|
||
}
|
||
|
||
ConsoleOutput("Imageepoch PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/20/2014 jichi alchemist-net.co.jp PSP engine, 0.9.8, 0.9.9
|
||
* An alternative alchemist hook for old alchemist games.
|
||
* Sample game: のーふぁ<E381B5>と (No Fate)
|
||
* The memory address is fixed.
|
||
*
|
||
* Also work on 0.9.9 Otoboku PSP
|
||
*
|
||
* Debug method: simply add hardware break points to the matched memory
|
||
*
|
||
* Two candidate functions are seems OK.
|
||
*
|
||
* Instruction pattern: 81e580808080 // and ebp,0x80808080
|
||
*
|
||
* 0.9.8 のーふぁ<E381B5>と
|
||
* 13400ef3 90 nop
|
||
* 13400ef4 77 0f ja short 13400f05
|
||
* 13400ef6 c705 a8aa1001 d0>mov dword ptr ds:[0x110aaa8],0x889aad0
|
||
* 13400f00 -e9 fff050f0 jmp 03910004
|
||
* 13400f05 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
* 13400f0b 8bc6 mov eax,esi
|
||
* 13400f0d 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13400f13 8bb8 00004007 mov edi,dword ptr ds:[eax+0x7400000] ; jichi
|
||
* 13400f19 8bef mov ebp,edi
|
||
* 13400f1b 81ed 01010101 sub ebp,0x1010101
|
||
* 13400f21 f7d7 not edi
|
||
* 13400f23 23ef and ebp,edi
|
||
* 13400f25 81e5 80808080 and ebp,0x80808080
|
||
* 13400f2b 81fd 00000000 cmp ebp,0x0
|
||
* 13400f31 c705 78a71001 80>mov dword ptr ds:[0x110a778],0x80808080
|
||
* 13400f3b c705 7ca71001 01>mov dword ptr ds:[0x110a77c],0x1010101
|
||
* 13400f45 8935 80a71001 mov dword ptr ds:[0x110a780],esi
|
||
* 13400f4b 892d 88a71001 mov dword ptr ds:[0x110a788],ebp
|
||
* 13400f51 0f84 22000000 je 13400f79
|
||
* 13400f57 8b35 80a71001 mov esi,dword ptr ds:[0x110a780]
|
||
* 13400f5d 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 13400f63 832d c4aa1001 0c sub dword ptr ds:[0x110aac4],0xc
|
||
* 13400f6a e9 35ba0000 jmp 1340c9a4
|
||
* 13400f6f 0124ab add dword ptr ds:[ebx+ebp*4],esp
|
||
* 13400f72 8908 mov dword ptr ds:[eax],ecx
|
||
* 13400f74 -e9 aaf050f0 jmp 03910023
|
||
* 13400f79 832d c4aa1001 0c sub dword ptr ds:[0x110aac4],0xc
|
||
* 13400f80 e9 0b000000 jmp 13400f90
|
||
* 13400f85 0100 add dword ptr ds:[eax],eax
|
||
* 13400f87 ab stos dword ptr es:[edi]
|
||
* 13400f88 8908 mov dword ptr ds:[eax],ecx
|
||
* 13400f8a -e9 94f050f0 jmp 03910023
|
||
* 13400f8f 90 nop
|
||
*/
|
||
|
||
static void SpecialPSPHookAlchemist2(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
if (*text && !_alchemistgarbage(text)) {
|
||
*data = (DWORD)text;
|
||
*len = ::strlen(text);
|
||
*split = stack->ecx;
|
||
}
|
||
}
|
||
|
||
bool InsertAlchemist2PSPHook()
|
||
{
|
||
ConsoleOutput("Alchemist2 PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 13400ef4 77 0f ja short 13400f05
|
||
0xc7,0x05, XX8, // 13400ef6 c705 a8aa1001 d0>mov dword ptr ds:[0x110aaa8],0x889aad0
|
||
0xe9, XX4, // 13400f00 -e9 fff050f0 jmp 03910004
|
||
0x8b,0x35, XX4, // 13400f05 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
0x8b,0xc6, // 13400f0b 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13400f0d 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb8, XX4, // 13400f13 8bb8 00004007 mov edi,dword ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x8b,0xef, // 13400f19 8bef mov ebp,edi
|
||
0x81,0xed, 0x01,0x01,0x01,0x01, // 13400f1b 81ed 01010101 sub ebp,0x1010101
|
||
0xf7,0xd7, // 13400f21 f7d7 not edi
|
||
0x23,0xef, // 13400f23 23ef and ebp,edi
|
||
0x81,0xe5, 0x80,0x80,0x80,0x80, // 13400f25 81e5 80808080 and ebp,0x80808080
|
||
0x81,0xfd, 0x00,0x00,0x00,0x00 // 13400f2b 81fd 00000000 cmp ebp,0x0
|
||
};
|
||
enum { memory_offset = 2 }; // 13400f13 8bb8 00004007 mov edi,dword ptr ds:[eax+0x7400000]
|
||
enum { addr_offset = 0x13400f13 - 0x13400ef4 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
//GROWL_DWORD(addr);
|
||
if (!addr)
|
||
ConsoleOutput("Alchemist2 PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.text_fun = SpecialPSPHookAlchemist2;
|
||
hp.type = USING_STRING|NO_CONTEXT; // no context is needed to get rid of variant retaddr
|
||
ConsoleOutput("Alchemist2 PSP: INSERT");
|
||
succ|=NewHook(hp, "Alchemist2 PSP");
|
||
}
|
||
|
||
ConsoleOutput("Alchemist2 PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/19/2014 jichi CYBERFRONT PSP engine, 0,9.8, 0.9.9
|
||
* Sample game: 想<>かけ<E3818B>クローストゥ (0.9.9)
|
||
*
|
||
* Debug method: breakpoint the memory address
|
||
* There are two matched memory address to the current text
|
||
*
|
||
* The second is used.
|
||
* The #1 is missing text.
|
||
*
|
||
* #1 The text is written word by word
|
||
*
|
||
* 0ed8be86 90 nop
|
||
* 0ed8be87 cc int3
|
||
* 0ed8be88 77 0f ja short 0ed8be99
|
||
* 0ed8be8a c705 c84c1301 dc>mov dword ptr ds:[0x1134cc8],0x88151dc
|
||
* 0ed8be94 -e9 6b41b4f4 jmp 038d0004
|
||
* 0ed8be99 8b35 cc491301 mov esi,dword ptr ds:[0x11349cc]
|
||
* 0ed8be9f 8d76 02 lea esi,dword ptr ds:[esi+0x2]
|
||
* 0ed8bea2 8b3d 94491301 mov edi,dword ptr ds:[0x1134994]
|
||
* 0ed8bea8 8b05 d0491301 mov eax,dword ptr ds:[0x11349d0]
|
||
* 0ed8beae 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8beb4 8bd7 mov edx,edi
|
||
* 0ed8beb6 8890 00008009 mov byte ptr ds:[eax+0x9800000],dl ; jichi: hook here, write text here
|
||
* 0ed8bebc 8b05 c8491301 mov eax,dword ptr ds:[0x11349c8]
|
||
* 0ed8bec2 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8bec8 0fb6a8 00008009 movzx ebp,byte ptr ds:[eax+0x9800000]
|
||
* 0ed8becf 8b05 d0491301 mov eax,dword ptr ds:[0x11349d0]
|
||
* 0ed8bed5 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8bedb 8bd5 mov edx,ebp
|
||
* 0ed8bedd 8890 01008009 mov byte ptr ds:[eax+0x9800001],dl
|
||
* 0ed8bee3 8b15 d0491301 mov edx,dword ptr ds:[0x11349d0]
|
||
* 0ed8bee9 8d52 02 lea edx,dword ptr ds:[edx+0x2]
|
||
* 0ed8beec 892d 90491301 mov dword ptr ds:[0x1134990],ebp
|
||
* 0ed8bef2 8935 cc491301 mov dword ptr ds:[0x11349cc],esi
|
||
* 0ed8bef8 8915 d0491301 mov dword ptr ds:[0x11349d0],edx
|
||
* 0ed8befe 832d e44c1301 06 sub dword ptr ds:[0x1134ce4],0x6
|
||
* 0ed8bf05 e9 0e000000 jmp 0ed8bf18
|
||
* 0ed8bf0a 013451 add dword ptr ds:[ecx+edx*2],esi
|
||
* 0ed8bf0d 8108 e90f41b4 or dword ptr ds:[eax],0xb4410fe9
|
||
* 0ed8bf13 f4 hlt ; privileged command
|
||
* 0ed8bf14 90 nop
|
||
* 0ed8bf15 cc int3
|
||
*
|
||
* #2 The text is read
|
||
*
|
||
* Issue: the text is read multiple times.
|
||
* Only esp > 0xfff is kept.
|
||
*
|
||
* 0ed8cf13 90 nop
|
||
* 0ed8cf14 77 0f ja short 0ed8cf25
|
||
* 0ed8cf16 c705 c84c1301 b8>mov dword ptr ds:[0x1134cc8],0x888d1b8
|
||
* 0ed8cf20 -e9 df30b4f4 jmp 038d0004
|
||
* 0ed8cf25 8b05 98491301 mov eax,dword ptr ds:[0x1134998]
|
||
* 0ed8cf2b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8cf31 0fb6b0 00008009 movzx esi,byte ptr ds:[eax+0x9800000] ; jichi: hook here
|
||
* 0ed8cf38 81fe 00000000 cmp esi,0x0
|
||
* 0ed8cf3e 8935 90491301 mov dword ptr ds:[0x1134990],esi
|
||
* 0ed8cf44 0f85 2f000000 jnz 0ed8cf79
|
||
* 0ed8cf4a 8b05 9c491301 mov eax,dword ptr ds:[0x113499c]
|
||
* 0ed8cf50 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8cf56 0fbeb0 00008009 movsx esi,byte ptr ds:[eax+0x9800000]
|
||
* 0ed8cf5d 8935 90491301 mov dword ptr ds:[0x1134990],esi
|
||
* 0ed8cf63 832d e44c1301 03 sub dword ptr ds:[0x1134ce4],0x3
|
||
* 0ed8cf6a c705 c84c1301 18>mov dword ptr ds:[0x1134cc8],0x888d218
|
||
* 0ed8cf74 -e9 aa30b4f4 jmp 038d0023
|
||
* 0ed8cf79 832d e44c1301 03 sub dword ptr ds:[0x1134ce4],0x3
|
||
* 0ed8cf80 e9 0b000000 jmp 0ed8cf90
|
||
* 0ed8cf85 01c4 add esp,eax
|
||
* 0ed8cf87 d188 08e99430 ror dword ptr ds:[eax+0x3094e908],1
|
||
* 0ed8cf8d b4 f4 mov ah,0xf4
|
||
* 0ed8cf8f 90 nop
|
||
*/
|
||
|
||
static void SpecialPSPHookCyberfront(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD splitvalue = stack->edi;
|
||
if (splitvalue < 0x0fff)
|
||
return;
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
if (*text) {
|
||
*data = (DWORD)text;
|
||
*len = ::strlen(text);
|
||
*split = splitvalue;
|
||
}
|
||
}
|
||
bool InsertCyberfrontPSPHook()
|
||
{
|
||
ConsoleOutput("CYBERFRONT PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
// 0ed8cf13 90 nop
|
||
0x77, 0x0f, // 0ed8cf14 77 0f ja short 0ed8cf25
|
||
0xc7,0x05, XX8, // 0ed8cf16 c705 c84c1301 b8>mov dword ptr ds:[0x1134cc8],0x888d1b8
|
||
0xe9, XX4, // 0ed8cf20 -e9 df30b4f4 jmp 038d0004
|
||
0x8b,0x05, XX4, // 0ed8cf25 8b05 98491301 mov eax,dword ptr ds:[0x1134998]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 0ed8cf2b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb0, XX4, // 0ed8cf31 0fb6b0 00008009 movzx esi,byte ptr ds:[eax+0x9800000] ; jichi: hook here
|
||
0x81,0xfe, 0x00,0x00,0x00,0x00, // 0ed8cf38 81fe 00000000 cmp esi,0x0
|
||
0x89,0x35, XX4, // 0ed8cf3e 8935 90491301 mov dword ptr ds:[0x1134990],esi
|
||
0x0f,0x85, 0x2f,0x00,0x00,0x00, // 0ed8cf44 0f85 2f000000 jnz 0ed8cf79
|
||
0x8b,0x05, XX4, // 0ed8cf4a 8b05 9c491301 mov eax,dword ptr ds:[0x113499c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 0ed8cf50 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 0ed8cf56 0fbeb0 00008009 movsx esi,byte ptr ds:[eax+0x9800000]
|
||
0x89,0x35, XX4, // 0ed8cf5d 8935 90491301 mov dword ptr ds:[0x1134990],esi
|
||
0x83,0x2d, XX4, 0x03, // 0ed8cf63 832d e44c1301 03 sub dword ptr ds:[0x1134ce4],0x3
|
||
0xc7,0x05 //, XX8 // 0ed8cf6a c705 c84c1301 18>mov dword ptr ds:[0x1134cc8],0x888d218
|
||
};
|
||
enum { memory_offset = 3 }; // 13909a51 8890 00008007 mov byte ptr ds:[eax+0x7800000],dl
|
||
enum { addr_offset = 0x0ed8cf31 - 0x0ed8cf14 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
//GROWL_DWORD(addr);
|
||
if (!addr)
|
||
ConsoleOutput("CYBERFRONT PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
//hp.offset=get_reg(regs::eax);
|
||
hp.text_fun = SpecialPSPHookCyberfront;
|
||
ConsoleOutput("CYBERFRONT PSP: INSERT");
|
||
succ|=NewHook(hp, "CYBERFRONT PSP");
|
||
}
|
||
|
||
ConsoleOutput("CYBERFRONT PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
|
||
/** 7/19/2014 jichi yetigame.jp PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: Secret Game Portable 0.9.8/0.9.9
|
||
*
|
||
* Float memory addresses: two matches
|
||
*
|
||
* Debug method: find current sentence, then find next sentence in the memory
|
||
* and add break-points. Need to patch 1 leading \u3000 space.
|
||
*
|
||
* It seems that each time I ran the game, the instruction pattern would change?!
|
||
* == The second time I ran the game ==
|
||
*
|
||
* 14e49ed9 90 nop
|
||
* 14e49eda cc int3
|
||
* 14e49edb cc int3
|
||
* 14e49edc 77 0f ja short 14e49eed
|
||
* 14e49ede c705 a8aa1001 98>mov dword ptr ds:[0x110aaa8],0x885ff98
|
||
* 14e49ee8 -e9 17619eee jmp 03830004
|
||
* 14e49eed 8b35 70a71001 mov esi,dword ptr ds:[0x110a770]
|
||
* 14e49ef3 c1ee 1f shr esi,0x1f
|
||
* 14e49ef6 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 14e49efc 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14e49f02 8bb8 14deff07 mov edi,dword ptr ds:[eax+0x7ffde14]
|
||
* 14e49f08 0335 70a71001 add esi,dword ptr ds:[0x110a770]
|
||
* 14e49f0e d1fe sar esi,1
|
||
* 14e49f10 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
* 14e49f16 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14e49f1c 89b8 00000008 mov dword ptr ds:[eax+0x8000000],edi
|
||
* 14e49f22 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 14e49f28 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14e49f2e 89b0 30000008 mov dword ptr ds:[eax+0x8000030],esi
|
||
* 14e49f34 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 14e49f3a 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14e49f40 8ba8 14deff07 mov ebp,dword ptr ds:[eax+0x7ffde14]
|
||
* 14e49f46 8bc5 mov eax,ebp
|
||
* 14e49f48 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14e49f4e 0fb6b0 00000008 movzx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here
|
||
* 14e49f55 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 14e49f58 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
*
|
||
* == The first time I ran the game ==
|
||
* There are a couple of good break-points, as follows.
|
||
* Only the second function is hooked.
|
||
*
|
||
* 138cf7a2 cc int3
|
||
* 138cf7a3 cc int3
|
||
* 138cf7a4 77 0f ja short 138cf7b5
|
||
* 138cf7a6 c705 a8aa1001 90>mov dword ptr ds:[0x110aaa8],0x885ff90
|
||
* 138cf7b0 -e9 4f08a9f3 jmp 07360004
|
||
* 138cf7b5 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 138cf7bb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cf7c1 8bb0 14de7f07 mov esi,dword ptr ds:[eax+0x77fde14]
|
||
* 138cf7c7 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 138cf7cd c705 e4a71001 98>mov dword ptr ds:[0x110a7e4],0x885ff98
|
||
* 138cf7d7 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 138cf7de e9 0d000000 jmp 138cf7f0
|
||
* 138cf7e3 015c48 85 add dword ptr ds:[eax+ecx*2-0x7b],ebx
|
||
* 138cf7e7 08e9 or cl,ch
|
||
* 138cf7e9 36:08a9 f390cccc or byte ptr ss:[ecx+0xcccc90f3],ch
|
||
* 138cf7f0 77 0f ja short 138cf801
|
||
* 138cf7f2 c705 a8aa1001 5c>mov dword ptr ds:[0x110aaa8],0x885485c
|
||
* 138cf7fc -e9 0308a9f3 jmp 07360004
|
||
* 138cf801 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 138cf807 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cf80d 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 138cf814 81fe 00000000 cmp esi,0x0
|
||
* 138cf81a 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 138cf820 c705 80a71001 00>mov dword ptr ds:[0x110a780],0x0
|
||
* 138cf82a c705 84a71001 25>mov dword ptr ds:[0x110a784],0x25
|
||
* 138cf834 c705 88a71001 4e>mov dword ptr ds:[0x110a788],0x4e
|
||
* 138cf83e c705 8ca71001 6e>mov dword ptr ds:[0x110a78c],0x6e
|
||
* 138cf848 0f85 16000000 jnz 138cf864
|
||
* 138cf84e 832d c4aa1001 06 sub dword ptr ds:[0x110aac4],0x6
|
||
* 138cf855 e9 b6010000 jmp 138cfa10
|
||
* 138cf85a 01bc48 8508e9bf add dword ptr ds:[eax+ecx*2+0xbfe90885],>
|
||
* 138cf861 07 pop es ; modification of segment register
|
||
* 138cf862 a9 f3832dc4 test eax,0xc42d83f3
|
||
* 138cf867 aa stos byte ptr es:[edi]
|
||
* 138cf868 1001 adc byte ptr ds:[ecx],al
|
||
* 138cf86a 06 push es
|
||
* 138cf86b e9 0c000000 jmp 138cf87c
|
||
* 138cf870 017448 85 add dword ptr ds:[eax+ecx*2-0x7b],esi
|
||
* 138cf874 08e9 or cl,ch
|
||
* 138cf876 a9 07a9f390 test eax,0x90f3a907
|
||
* 138cf87b cc int3
|
||
*
|
||
* This function is used.
|
||
* 138cfa46 cc int3
|
||
* 138cfa47 cc int3
|
||
* 138cfa48 77 0f ja short 138cfa59
|
||
* 138cfa4a c705 a8aa1001 98>mov dword ptr ds:[0x110aaa8],0x885ff98
|
||
* 138cfa54 -e9 ab05a9f3 jmp 07360004
|
||
* 138cfa59 8b35 70a71001 mov esi,dword ptr ds:[0x110a770]
|
||
* 138cfa5f c1ee 1f shr esi,0x1f
|
||
* 138cfa62 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 138cfa68 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfa6e 8bb8 14de7f07 mov edi,dword ptr ds:[eax+0x77fde14]
|
||
* 138cfa74 0335 70a71001 add esi,dword ptr ds:[0x110a770]
|
||
* 138cfa7a d1fe sar esi,1
|
||
* 138cfa7c 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
* 138cfa82 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfa88 89b8 00008007 mov dword ptr ds:[eax+0x7800000],edi
|
||
* 138cfa8e 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 138cfa94 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfa9a 89b0 30008007 mov dword ptr ds:[eax+0x7800030],esi
|
||
* 138cfaa0 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 138cfaa6 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfaac 8ba8 14de7f07 mov ebp,dword ptr ds:[eax+0x77fde14]
|
||
* 138cfab2 8bc5 mov eax,ebp
|
||
* 138cfab4 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfaba 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 138cfac1 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 138cfac4 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 138cfaca 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfad0 89a8 14de7f07 mov dword ptr ds:[eax+0x77fde14],ebp
|
||
* 138cfad6 81fe 00000000 cmp esi,0x0
|
||
* 138cfadc 892d 70a71001 mov dword ptr ds:[0x110a770],ebp
|
||
* 138cfae2 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 138cfae8 893d aca71001 mov dword ptr ds:[0x110a7ac],edi
|
||
* 138cfaee 0f84 16000000 je 138cfb0a
|
||
* 138cfaf4 832d c4aa1001 0b sub dword ptr ds:[0x110aac4],0xb
|
||
* 138cfafb e9 24000000 jmp 138cfb24
|
||
* 138cfb00 01b0 ff8508e9 add dword ptr ds:[eax+0xe90885ff],esi
|
||
* 138cfb06 1905 a9f3832d sbb dword ptr ds:[0x2d83f3a9],eax
|
||
* 138cfb0c c4aa 10010be9 les ebp,fword ptr ds:[edx+0xe90b0110] ; modification of segment register
|
||
* 138cfb12 9a 00000001 c4ff call far ffc4:01000000 ; far call
|
||
* 138cfb19 8508 test dword ptr ds:[eax],ecx
|
||
* 138cfb1b -e9 0305a9f3 jmp 07360023
|
||
* 138cfb20 90 nop
|
||
* 138cfb21 cc int3
|
||
* 138cfb22 cc int3
|
||
*
|
||
* 138cfb22 cc int3
|
||
* 138cfb23 cc int3
|
||
* 138cfb24 77 0f ja short 138cfb35
|
||
* 138cfb26 c705 a8aa1001 b0>mov dword ptr ds:[0x110aaa8],0x885ffb0
|
||
* 138cfb30 -e9 cf04a9f3 jmp 07360004
|
||
* 138cfb35 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 138cfb3b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfb41 8bb0 14de7f07 mov esi,dword ptr ds:[eax+0x77fde14]
|
||
* 138cfb47 8bc6 mov eax,esi
|
||
* 138cfb49 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfb4f 0fb6b8 00008007 movzx edi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 138cfb56 8d76 01 lea esi,dword ptr ds:[esi+0x1]
|
||
* 138cfb59 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
* 138cfb5f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfb65 89b0 14de7f07 mov dword ptr ds:[eax+0x77fde14],esi
|
||
* 138cfb6b 81ff 00000000 cmp edi,0x0
|
||
* 138cfb71 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 138cfb77 893d 74a71001 mov dword ptr ds:[0x110a774],edi
|
||
* 138cfb7d 0f84 16000000 je 138cfb99
|
||
* 138cfb83 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 138cfb8a ^e9 95ffffff jmp 138cfb24
|
||
* 138cfb8f 01b0 ff8508e9 add dword ptr ds:[eax+0xe90885ff],esi
|
||
* 138cfb95 8a04a9 mov al,byte ptr ds:[ecx+ebp*4]
|
||
* 138cfb98 f3: prefix rep: ; superfluous prefix
|
||
* 138cfb99 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 138cfba0 e9 0b000000 jmp 138cfbb0
|
||
* 138cfba5 01c4 add esp,eax
|
||
* 138cfba7 ff85 08e97404 inc dword ptr ss:[ebp+0x474e908]
|
||
* 138cfbad a9 f390770f test eax,0xf7790f3
|
||
* 138cfbb2 c705 a8aa1001 c4>mov dword ptr ds:[0x110aaa8],0x885ffc4
|
||
* 138cfbbc -e9 4304a9f3 jmp 07360004
|
||
* 138cfbc1 f3:0f1015 6c1609>movss xmm2,dword ptr ds:[0x1009166c]
|
||
* 138cfbc9 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
* 138cfbcf 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfbd5 8bb0 00008007 mov esi,dword ptr ds:[eax+0x7800000]
|
||
* 138cfbdb f3:0f101d 641609>movss xmm3,dword ptr ds:[0x10091664]
|
||
* 138cfbe3 c7c7 00000000 mov edi,0x0
|
||
* 138cfbe9 893d f4b12b11 mov dword ptr ds:[0x112bb1f4],edi
|
||
* 138cfbef 8bc6 mov eax,esi
|
||
* 138cfbf1 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138cfbf7 0fb6a8 00008007 movzx ebp,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 138cfbfe 81fd 00000000 cmp ebp,0x0
|
||
* 138cfc04 c705 70a71001 00>mov dword ptr ds:[0x110a770],0x9ac0000
|
||
* 138cfc0e c705 74a71001 00>mov dword ptr ds:[0x110a774],0x8890000
|
||
* 138cfc18 892d a8a71001 mov dword ptr ds:[0x110a7a8],ebp
|
||
* 138cfc1e 8935 aca71001 mov dword ptr ds:[0x110a7ac],esi
|
||
* 138cfc24 c705 b4a71001 00>mov dword ptr ds:[0x110a7b4],0x8890000
|
||
* 138cfc2e c705 b8a71001 80>mov dword ptr ds:[0x110a7b8],0x80
|
||
* 138cfc38 c705 bca71001 00>mov dword ptr ds:[0x110a7bc],0x0
|
||
* 138cfc42 c705 e0a71001 00>mov dword ptr ds:[0x110a7e0],0x0
|
||
* 138cfc4c f3:0f111d 3ca810>movss dword ptr ds:[0x110a83c],xmm3
|
||
* 138cfc54 f3:0f1115 40a810>movss dword ptr ds:[0x110a840],xmm2
|
||
* 138cfc5c 0f85 16000000 jnz 138cfc78
|
||
* 138cfc62 832d c4aa1001 0d sub dword ptr ds:[0x110aac4],0xd
|
||
* 138cfc69 e9 32270000 jmp 138d23a0
|
||
* 138cfc6e 0158 00 add dword ptr ds:[eax],ebx
|
||
* 138cfc71 8608 xchg byte ptr ds:[eax],cl
|
||
* 138cfc73 -e9 ab03a9f3 jmp 07360023
|
||
* 138cfc78 832d c4aa1001 0d sub dword ptr ds:[0x110aac4],0xd
|
||
* 138cfc7f e9 0c000000 jmp 138cfc90
|
||
* 138cfc84 01f8 add eax,edi
|
||
* 138cfc86 ff85 08e99503 inc dword ptr ss:[ebp+0x395e908]
|
||
* 138cfc8c a9 f390cc77 test eax,0x77cc90f3
|
||
* 138cfc91 0fc7 ??? ; unknown command
|
||
* 138cfc93 05 a8aa1001 add eax,0x110aaa8
|
||
* 138cfc98 f8 clc
|
||
* 138cfc99 ff85 08e96303 inc dword ptr ss:[ebp+0x363e908]
|
||
* 138cfc9f a9 f38b35ac test eax,0xac358bf3
|
||
* 138cfca4 a7 cmps dword ptr ds:[esi],dword ptr es:[ed>
|
||
* 138cfca5 1001 adc byte ptr ds:[ecx],al
|
||
* 138cfca7 8b3d b4a71001 mov edi,dword ptr ds:[0x110a7b4]
|
||
* 138cfcad 81c7 48d6ffff add edi,-0x29b8
|
||
* 138cfcb3 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 138cfcb9 893d 7ca71001 mov dword ptr ds:[0x110a77c],edi
|
||
* 138cfcbf c705 80a71001 02>mov dword ptr ds:[0x110a780],0x2
|
||
* 138cfcc9 c705 e4a71001 08>mov dword ptr ds:[0x110a7e4],0x8860008
|
||
* 138cfcd3 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 138cfcda ^e9 4914f4ff jmp 13811128
|
||
* 138cfcdf 90 nop
|
||
* 138cfce0 77 0f ja short 138cfcf1
|
||
* 138cfce2 c705 a8aa1001 74>mov dword ptr ds:[0x110aaa8],0x8844574
|
||
* 138cfcec -e9 1303a9f3 jmp 07360004
|
||
* 138cfcf1 8b35 84a71001 mov esi,dword ptr ds:[0x110a784]
|
||
* 138cfcf7 81c6 ffffffff add esi,-0x1
|
||
* 138cfcfd 813d 84a71001 00>cmp dword ptr ds:[0x110a784],0x0
|
||
* 138cfd07 8935 8ca71001 mov dword ptr ds:[0x110a78c],esi
|
||
* 138cfd0d 0f85 16000000 jnz 138cfd29
|
||
* 138cfd13 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 138cfd1a c705 a8aa1001 e0>mov dword ptr ds:[0x110aaa8],0x88445e0
|
||
* 138cfd24 -e9 fa02a9f3 jmp 07360023
|
||
* 138cfd29 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 138cfd30 ^e9 ab15f4ff jmp 138112e0
|
||
* 138cfd35 90 nop
|
||
* 138cfd36 cc int3
|
||
* 138cfd37 cc int3
|
||
*
|
||
* 13811266 cc int3
|
||
* 13811267 cc int3
|
||
* 13811268 77 0f ja short 13811279
|
||
* 1381126a c705 a8aa1001 b0>mov dword ptr ds:[0x110aaa8],0x88445b0
|
||
* 13811274 -e9 8bedb4f3 jmp 07360004
|
||
* 13811279 8b35 8ca71001 mov esi,dword ptr ds:[0x110a78c]
|
||
* 1381127f 8b3d 88a71001 mov edi,dword ptr ds:[0x110a788]
|
||
* 13811285 8b2d 84a71001 mov ebp,dword ptr ds:[0x110a784]
|
||
* 1381128b 81c5 ffffffff add ebp,-0x1
|
||
* 13811291 813d 84a71001 00>cmp dword ptr ds:[0x110a784],0x0
|
||
* 1381129b 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 138112a1 893d 7ca71001 mov dword ptr ds:[0x110a77c],edi
|
||
* 138112a7 892d 8ca71001 mov dword ptr ds:[0x110a78c],ebp
|
||
* 138112ad 0f84 16000000 je 138112c9
|
||
* 138112b3 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 138112ba e9 21000000 jmp 138112e0
|
||
* 138112bf 017c45 84 add dword ptr ss:[ebp+eax*2-0x7c],edi
|
||
* 138112c3 08e9 or cl,ch
|
||
* 138112c5 5a pop edx
|
||
* 138112c6 ed in eax,dx ; i/o command
|
||
* 138112c7 b4 f3 mov ah,0xf3
|
||
* 138112c9 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 138112d0 c705 a8aa1001 c0>mov dword ptr ds:[0x110aaa8],0x88445c0
|
||
* 138112da -e9 44edb4f3 jmp 07360023
|
||
* 138112df 90 nop
|
||
* 138112e0 77 0f ja short 138112f1
|
||
* 138112e2 c705 a8aa1001 7c>mov dword ptr ds:[0x110aaa8],0x884457c
|
||
* 138112ec -e9 13edb4f3 jmp 07360004
|
||
* 138112f1 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 138112f7 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138112fd 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 13811304 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 1381130a 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13811310 0fbeb8 00008007 movsx edi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 13811317 8bc6 mov eax,esi
|
||
* 13811319 0fbee8 movsx ebp,al
|
||
* 1381131c 3bef cmp ebp,edi
|
||
* 1381131e 893d 70a71001 mov dword ptr ds:[0x110a770],edi
|
||
* 13811324 892d 74a71001 mov dword ptr ds:[0x110a774],ebp
|
||
* 1381132a 8935 80a71001 mov dword ptr ds:[0x110a780],esi
|
||
* 13811330 0f85 16000000 jnz 1381134c
|
||
* 13811336 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 1381133d e9 56110000 jmp 13812498
|
||
* 13811342 01c8 add eax,ecx
|
||
* 13811344 45 inc ebp
|
||
* 13811345 8408 test byte ptr ds:[eax],cl
|
||
* 13811347 -e9 d7ecb4f3 jmp 07360023
|
||
* 1381134c 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 13811353 e9 0c000000 jmp 13811364
|
||
* 13811358 0190 458408e9 add dword ptr ds:[eax+0xe9088445],edx
|
||
* 1381135e c1ec b4 shr esp,0xb4 ; shift constant out of range 1..31
|
||
* 13811361 f3: prefix rep: ; superfluous prefix
|
||
* 13811362 90 nop
|
||
* 13811363 cc int3
|
||
*
|
||
* 13811362 90 nop
|
||
* 13811363 cc int3
|
||
* 13811364 77 0f ja short 13811375
|
||
* 13811366 c705 a8aa1001 90>mov dword ptr ds:[0x110aaa8],0x8844590
|
||
* 13811370 -e9 8fecb4f3 jmp 07360004
|
||
* 13811375 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 1381137b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13811381 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 13811388 81e6 ff000000 and esi,0xff
|
||
* 1381138e 8b3d 80a71001 mov edi,dword ptr ds:[0x110a780]
|
||
* 13811394 81e7 ff000000 and edi,0xff
|
||
* 1381139a 8bc7 mov eax,edi
|
||
* 1381139c 8bfe mov edi,esi
|
||
* 1381139e 2bf8 sub edi,eax
|
||
* 138113a0 8b05 e4a71001 mov eax,dword ptr ds:[0x110a7e4]
|
||
* 138113a6 893d 70a71001 mov dword ptr ds:[0x110a770],edi
|
||
* 138113ac 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 138113b2 8905 a8aa1001 mov dword ptr ds:[0x110aaa8],eax
|
||
* 138113b8 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 138113bf -e9 5fecb4f3 jmp 07360023
|
||
* 138113c4 90 nop
|
||
* 138113c5 cc int3
|
||
* 138113c6 cc int3
|
||
* 138113c7 cc int3
|
||
*
|
||
* 138124f2 cc int3
|
||
* 138124f3 cc int3
|
||
* 138124f4 77 0f ja short 13812505
|
||
* 138124f6 c705 a8aa1001 d0>mov dword ptr ds:[0x110aaa8],0x88445d0
|
||
* 13812500 -e9 ffdab4f3 jmp 07360004
|
||
* 13812505 813d 74a71001 00>cmp dword ptr ds:[0x110a774],0x0
|
||
* 1381250f c705 90a71001 00>mov dword ptr ds:[0x110a790],0x0
|
||
* 13812519 0f84 16000000 je 13812535
|
||
* 1381251f 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 13812526 e9 21000000 jmp 1381254c
|
||
* 1381252b 018446 8408e9ee add dword ptr ds:[esi+eax*2+0xeee90884],>
|
||
* 13812532 dab4f3 832dc4aa fidiv dword ptr ds:[ebx+esi*8+0xaac42d83>
|
||
* 13812539 1001 adc byte ptr ds:[ecx],al
|
||
* 1381253b 02e9 add ch,cl
|
||
* 1381253d 3302 xor eax,dword ptr ds:[edx]
|
||
* 1381253f 0000 add byte ptr ds:[eax],al
|
||
* 13812541 01d8 add eax,ebx
|
||
* 13812543 45 inc ebp
|
||
* 13812544 8408 test byte ptr ds:[eax],cl
|
||
* 13812546 -e9 d8dab4f3 jmp 07360023
|
||
* 1381254b 90 nop
|
||
* 1381254c 77 0f ja short 1381255d
|
||
* 1381254e c705 a8aa1001 84>mov dword ptr ds:[0x110aaa8],0x8844684
|
||
* 13812558 -e9 a7dab4f3 jmp 07360004
|
||
* 1381255d 8b35 78a71001 mov esi,dword ptr ds:[0x110a778]
|
||
* 13812563 0335 8ca71001 add esi,dword ptr ds:[0x110a78c]
|
||
* 13812569 8b3d 88a71001 mov edi,dword ptr ds:[0x110a788]
|
||
* 1381256f 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 13812572 8b2d 7ca71001 mov ebp,dword ptr ds:[0x110a77c]
|
||
* 13812578 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 1381257b 8b15 90a71001 mov edx,dword ptr ds:[0x110a790]
|
||
* 13812581 3b15 8ca71001 cmp edx,dword ptr ds:[0x110a78c]
|
||
* 13812587 892d 7ca71001 mov dword ptr ds:[0x110a77c],ebp
|
||
* 1381258d 893d 88a71001 mov dword ptr ds:[0x110a788],edi
|
||
* 13812593 8935 94a71001 mov dword ptr ds:[0x110a794],esi
|
||
* 13812599 0f85 16000000 jnz 138125b5
|
||
* 1381259f 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 138125a6 c705 a8aa1001 c4>mov dword ptr ds:[0x110aaa8],0x88446c4
|
||
* 138125b0 -e9 6edab4f3 jmp 07360023
|
||
* 138125b5 832d c4aa1001 04 sub dword ptr ds:[0x110aac4],0x4
|
||
* 138125bc e9 0b000000 jmp 138125cc
|
||
* 138125c1 019446 8408e958 add dword ptr ds:[esi+eax*2+0x58e90884],>
|
||
* 138125c8 dab4f3 90770fc7 fidiv dword ptr ds:[ebx+esi*8+0xc70f7790>
|
||
* 138125cf 05 a8aa1001 add eax,0x110aaa8
|
||
* 138125d4 94 xchg eax,esp
|
||
* 138125d5 46 inc esi
|
||
* 138125d6 8408 test byte ptr ds:[eax],cl
|
||
* 138125d8 -e9 27dab4f3 jmp 07360004
|
||
* 138125dd 8b05 88a71001 mov eax,dword ptr ds:[0x110a788]
|
||
* 138125e3 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138125e9 0fb6b0 00008007 movzx esi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 138125f0 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 138125f6 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138125fc 0fb6b8 00008007 movzx edi,byte ptr ds:[eax+0x7800000]
|
||
* 13812603 8bc6 mov eax,esi
|
||
* 13812605 0fbee8 movsx ebp,al
|
||
* 13812608 8bc7 mov eax,edi
|
||
* 1381260a 0fbed0 movsx edx,al
|
||
* 1381260d 8b0d 90a71001 mov ecx,dword ptr ds:[0x110a790]
|
||
* 13812613 8d49 01 lea ecx,dword ptr ds:[ecx+0x1]
|
||
* 13812616 3bd5 cmp edx,ebp
|
||
* 13812618 892d 70a71001 mov dword ptr ds:[0x110a770],ebp
|
||
* 1381261e 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 13812624 893d 80a71001 mov dword ptr ds:[0x110a780],edi
|
||
* 1381262a 8915 84a71001 mov dword ptr ds:[0x110a784],edx
|
||
* 13812630 890d 90a71001 mov dword ptr ds:[0x110a790],ecx
|
||
* 13812636 0f84 16000000 je 13812652
|
||
* 1381263c 832d c4aa1001 06 sub dword ptr ds:[0x110aac4],0x6
|
||
* 13812643 e9 98d70b00 jmp 138cfde0
|
||
* 13812648 019445 8408e9d1 add dword ptr ss:[ebp+eax*2+0xd1e90884],>
|
||
* 1381264f d9b4f3 832dc4aa fstenv (28-byte) ptr ds:[ebx+esi*8+0xaac>
|
||
* 13812656 1001 adc byte ptr ds:[ecx],al
|
||
* 13812658 06 push es
|
||
* 13812659 e9 0e000000 jmp 1381266c
|
||
* 1381265e 01ac46 8408e9bb add dword ptr ds:[esi+eax*2+0xbbe90884],>
|
||
* 13812665 d9b4f3 90cccccc fstenv (28-byte) ptr ds:[ebx+esi*8+0xccc>
|
||
* 1381266c 77 0f ja short 1381267d
|
||
* 1381266e c705 a8aa1001 ac>mov dword ptr ds:[0x110aaa8],0x88446ac
|
||
* 13812678 -e9 87d9b4f3 jmp 07360004
|
||
* 1381267d 8b35 88a71001 mov esi,dword ptr ds:[0x110a788]
|
||
* 13812683 3b35 94a71001 cmp esi,dword ptr ds:[0x110a794]
|
||
* 13812689 0f85 16000000 jnz 138126a5
|
||
* 1381268f 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 13812696 e9 d9000000 jmp 13812774
|
||
* 1381269b 01d8 add eax,ebx
|
||
* 1381269d 45 inc ebp
|
||
* 1381269e 8408 test byte ptr ds:[eax],cl
|
||
* 138126a0 -e9 7ed9b4f3 jmp 07360023
|
||
* 138126a5 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 138126ac e9 0b000000 jmp 138126bc
|
||
* 138126b1 01b446 8408e968 add dword ptr ds:[esi+eax*2+0x68e90884],>
|
||
* 138126b8 d9b4f3 90770fc7 fstenv (28-byte) ptr ds:[ebx+esi*8+0xc70>
|
||
* 138126bf 05 a8aa1001 add eax,0x110aaa8
|
||
* 138126c4 b4 46 mov ah,0x46
|
||
* 138126c6 8408 test byte ptr ds:[eax],cl
|
||
* 138126c8 -e9 37d9b4f3 jmp 07360004
|
||
* 138126cd 8b35 88a71001 mov esi,dword ptr ds:[0x110a788]
|
||
* 138126d3 8d76 01 lea esi,dword ptr ds:[esi+0x1]
|
||
* 138126d6 813d 84a71001 00>cmp dword ptr ds:[0x110a784],0x0
|
||
* 138126e0 8935 88a71001 mov dword ptr ds:[0x110a788],esi
|
||
* 138126e6 0f84 16000000 je 13812702
|
||
* 138126ec 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 138126f3 e9 24000000 jmp 1381271c
|
||
* 138126f8 018c46 8408e921 add dword ptr ds:[esi+eax*2+0x21e90884],>
|
||
* 138126ff d9b4f3 832dc4aa fstenv (28-byte) ptr ds:[ebx+esi*8+0xaac>
|
||
* 13812706 1001 adc byte ptr ds:[ecx],al
|
||
* 13812708 02c7 add al,bh
|
||
* 1381270a 05 a8aa1001 add eax,0x110aaa8
|
||
* 1381270f bc 468408e9 mov esp,0xe9088446
|
||
* 13812714 0bd9 or ebx,ecx
|
||
* 13812716 b4 f3 mov ah,0xf3
|
||
* 13812718 90 nop
|
||
* 13812719 cc int3
|
||
* 1381271a cc int3
|
||
* 1381271b cc int3
|
||
*
|
||
* This function is very similar to Imageepoch, and can have duplicate text
|
||
* 138d1486 cc int3
|
||
* 138d1487 cc int3
|
||
* 138d1488 77 0f ja short 138d1499
|
||
* 138d148a c705 a8aa1001 2c>mov dword ptr ds:[0x110aaa8],0x884452c
|
||
* 138d1494 -e9 6beba8f3 jmp 07360004
|
||
* 138d1499 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 138d149f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138d14a5 0fbeb0 00008007 movsx esi,byte ptr ds:[eax+0x7800000] ; jichi: hook here
|
||
* 138d14ac 8b3d 7ca71001 mov edi,dword ptr ds:[0x110a77c]
|
||
* 138d14b2 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 138d14b5 8b05 74a71001 mov eax,dword ptr ds:[0x110a774]
|
||
* 138d14bb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 138d14c1 8bd6 mov edx,esi
|
||
* 138d14c3 8890 00008007 mov byte ptr ds:[eax+0x7800000],dl
|
||
* 138d14c9 8b2d 74a71001 mov ebp,dword ptr ds:[0x110a774]
|
||
* 138d14cf 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 138d14d2 81fe 00000000 cmp esi,0x0
|
||
* 138d14d8 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 138d14de 892d 74a71001 mov dword ptr ds:[0x110a774],ebp
|
||
* 138d14e4 893d 7ca71001 mov dword ptr ds:[0x110a77c],edi
|
||
* 138d14ea 0f85 16000000 jnz 138d1506
|
||
* 138d14f0 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 138d14f7 e9 e8000000 jmp 138d15e4
|
||
* 138d14fc 015445 84 add dword ptr ss:[ebp+eax*2-0x7c],edx
|
||
* 138d1500 08e9 or cl,ch
|
||
* 138d1502 1d eba8f383 sbb eax,0x83f3a8eb
|
||
* 138d1507 2d c4aa1001 sub eax,0x110aac4
|
||
* 138d150c 05 e90e0000 add eax,0xee9
|
||
* 138d1511 0001 add byte ptr ds:[ecx],al
|
||
* 138d1513 40 inc eax
|
||
* 138d1514 45 inc ebp
|
||
* 138d1515 8408 test byte ptr ds:[eax],cl
|
||
* 138d1517 -e9 07eba8f3 jmp 07360023
|
||
* 138d151c 90 nop
|
||
* 138d151d cc int3
|
||
* 138d151e cc int3
|
||
* 138d151f cc int3
|
||
*/
|
||
//static void SpecialPSPHookYeti(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
//{
|
||
// //enum { base = 0x7400000 };
|
||
// DWORD eax = regof(eax, esp_base);
|
||
// LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
// if (*text) {
|
||
// *data = (DWORD)text;
|
||
// *len = ::strlen(text); // SHIFT-JIS
|
||
// //*split = regof(ecx, esp_base); // ecx is bad that will split text threads
|
||
// //*split = FIXED_SPLIT_VALUE; // Similar to 5pb, it only has one thread?
|
||
// //*split = regof(ebx, esp_base); // value of ebx is splitting
|
||
// *split = FIXED_SPLIT_VALUE << 1; // * 2 to make it unique
|
||
// }
|
||
//}
|
||
|
||
bool InsertYetiPSPHook()
|
||
{
|
||
ConsoleOutput("Yeti PSP: enter");
|
||
const BYTE bytes[] = {
|
||
//0xcc, // 14e49edb cc int3
|
||
0x77, 0x0f, // 14e49edc 77 0f ja short 14e49eed
|
||
0xc7,0x05, XX8, // 14e49ede c705 a8aa1001 98>mov dword ptr ds:[0x110aaa8],0x885ff98
|
||
0xe9, XX4, // 14e49ee8 -e9 17619eee jmp 03830004
|
||
0x8b,0x35, XX4, // 14e49eed 8b35 70a71001 mov esi,dword ptr ds:[0x110a770]
|
||
0xc1,0xee, 0x1f, // 14e49ef3 c1ee 1f shr esi,0x1f
|
||
0x8b,0x05, XX4, // 14e49ef6 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14e49efc 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb8, XX4, // 14e49f02 8bb8 14deff07 mov edi,dword ptr ds:[eax+0x7ffde14]
|
||
0x03,0x35, XX4, // 14e49f08 0335 70a71001 add esi,dword ptr ds:[0x110a770]
|
||
0xd1,0xfe, // 14e49f0e d1fe sar esi,1
|
||
0x8b,0x05, XX4, // 14e49f10 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14e49f16 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb8, XX4, // 14e49f1c 89b8 00000008 mov dword ptr ds:[eax+0x8000000],edi
|
||
0x8b,0x05, XX4, // 14e49f22 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14e49f28 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb0, XX4, // 14e49f2e 89b0 30000008 mov dword ptr ds:[eax+0x8000030],esi
|
||
0x8b,0x05, XX4, // 14e49f34 8b05 b4a71001 mov eax,dword ptr ds:[0x110a7b4]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14e49f3a 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xa8, XX4, // 14e49f40 8ba8 14deff07 mov ebp,dword ptr ds:[eax+0x7ffde14]
|
||
0x8b,0xc5, // 14e49f46 8bc5 mov eax,ebp
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14e49f48 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb0 //, XX4, // 14e49f4e 0fb6b0 00000008 movzx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here
|
||
};
|
||
enum { memory_offset = 3 }; // 14e49f4e 0fb6b0 00000008 movzx esi,byte ptr ds:[eax+0x8000000]
|
||
enum { addr_offset = sizeof(bytes) - memory_offset };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Yeti PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|FIXING_SPLIT|NO_CONTEXT; // Fix the split value to merge all threads
|
||
hp.text_fun = SpecialPSPHook;
|
||
hp.offset=get_reg(regs::eax);
|
||
ConsoleOutput("Yeti PSP: INSERT");
|
||
succ|=NewHook(hp, "Yeti PSP");
|
||
}
|
||
|
||
ConsoleOutput("Yeti PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/19/2014 jichi Alternative Yeti PSP engine, 0.9.8, 0.9.9
|
||
* Sample game: Never 7, 0.9.8 & 0.9.9
|
||
* Sample game: ひまわり
|
||
*
|
||
* Do not work on 0.9.9 Ever17 (7/27/2014)
|
||
*
|
||
*
|
||
* This hook does not work for 12River.
|
||
* However, sceFont functions work.
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: breakpoint the memory address
|
||
* There are two matched memory address to the current text
|
||
*
|
||
* There are several functions. The first one is used.
|
||
*
|
||
* The text also has 5pb-like garbage, but it is difficult to trim.
|
||
*
|
||
* PPSSPP 0.9.8:
|
||
*
|
||
* 14289802 cc int3
|
||
* 14289803 cc int3
|
||
* 14289804 77 0f ja short 14289815
|
||
* 14289806 c705 a8aa1001 58>mov dword ptr ds:[0x110aaa8],0x881ab58
|
||
* 14289810 -e9 ef6767ef jmp 03900004
|
||
* 14289815 8b35 74a71001 mov esi,dword ptr ds:[0x110a774]
|
||
* 1428981b 0335 78a71001 add esi,dword ptr ds:[0x110a778]
|
||
* 14289821 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 14289827 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1428982d 8bb8 28004007 mov edi,dword ptr ds:[eax+0x7400028]
|
||
* 14289833 8bc6 mov eax,esi
|
||
* 14289835 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1428983b 8bd7 mov edx,edi
|
||
* 1428983d 8890 10044007 mov byte ptr ds:[eax+0x7400410],dl
|
||
* 14289843 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
* 14289849 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1428984f 8bb8 84004007 mov edi,dword ptr ds:[eax+0x7400084]
|
||
* 14289855 8b05 aca71001 mov eax,dword ptr ds:[0x110a7ac]
|
||
* 1428985b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289861 0fb6a8 00004007 movzx ebp,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 14289868 81ff 00000000 cmp edi,0x0
|
||
* 1428986e 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 14289874 893d 74a71001 mov dword ptr ds:[0x110a774],edi
|
||
* 1428987a 892d 78a71001 mov dword ptr ds:[0x110a778],ebp
|
||
* 14289880 0f85 16000000 jnz 1428989c
|
||
* 14289886 832d c4aa1001 06 sub dword ptr ds:[0x110aac4],0x6
|
||
* 1428988d c705 a8aa1001 ac>mov dword ptr ds:[0x110aaa8],0x881aeac
|
||
* 14289897 -e9 876767ef jmp 03900023
|
||
* 1428989c 832d c4aa1001 06 sub dword ptr ds:[0x110aac4],0x6
|
||
* 142898a3 e9 0c000000 jmp 142898b4
|
||
* 142898a8 0170 ab add dword ptr ds:[eax-0x55],esi
|
||
* 142898ab 8108 e9716767 or dword ptr ds:[eax],0x676771e9
|
||
* 142898b1 ef out dx,eax ; i/o command
|
||
* 142898b2 90 nop
|
||
*
|
||
* 142878ed cc int3
|
||
* 142878ee cc int3
|
||
* 142878ef cc int3
|
||
* 142878f0 77 0f ja short 14287901
|
||
* 142878f2 c705 a8aa1001 44>mov dword ptr ds:[0x110aaa8],0x8811e44
|
||
* 142878fc -e9 038767ef jmp 03900004
|
||
* 14287901 8b35 70a71001 mov esi,dword ptr ds:[0x110a770]
|
||
* 14287907 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
* 1428790d 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14287913 8bd6 mov edx,esi
|
||
* 14287915 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl ; jichi: hook here
|
||
* 1428791b 8b05 a8a71001 mov eax,dword ptr ds:[0x110a7a8]
|
||
* 14287921 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14287927 0fb6b8 00004007 movzx edi,byte ptr ds:[eax+0x7400000]
|
||
* 1428792e 8b2d aca71001 mov ebp,dword ptr ds:[0x110a7ac]
|
||
* 14287934 81c5 02000000 add ebp,0x2
|
||
* 1428793a 8bd5 mov edx,ebp
|
||
* 1428793c 8915 aca71001 mov dword ptr ds:[0x110a7ac],edx
|
||
* 14287942 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
* 14287948 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1428794e 8bd7 mov edx,edi
|
||
* 14287950 8890 01004007 mov byte ptr ds:[eax+0x7400001],dl
|
||
* 14287956 8b15 b0a71001 mov edx,dword ptr ds:[0x110a7b0]
|
||
* 1428795c 8d52 02 lea edx,dword ptr ds:[edx+0x2]
|
||
* 1428795f 893d 74a71001 mov dword ptr ds:[0x110a774],edi
|
||
* 14287965 892d a8a71001 mov dword ptr ds:[0x110a7a8],ebp
|
||
* 1428796b 8915 b0a71001 mov dword ptr ds:[0x110a7b0],edx
|
||
* 14287971 832d c4aa1001 07 sub dword ptr ds:[0x110aac4],0x7
|
||
* 14287978 e9 0b000000 jmp 14287988
|
||
* 1428797d 01a8 1d8108e9 add dword ptr ds:[eax+0xe908811d],ebp
|
||
* 14287983 9c pushfd
|
||
* 14287984 8667 ef xchg byte ptr ds:[edi-0x11],ah
|
||
* 14287987 90 nop
|
||
*
|
||
* 14289a2a 90 nop
|
||
* 14289a2b cc int3
|
||
* 14289a2c 77 0f ja short 14289a3d
|
||
* 14289a2e c705 a8aa1001 b4>mov dword ptr ds:[0x110aaa8],0x881abb4
|
||
* 14289a38 -e9 c76567ef jmp 03900004
|
||
* 14289a3d 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 14289a43 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289a49 8bb0 18004007 mov esi,dword ptr ds:[eax+0x7400018]
|
||
* 14289a4f 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 14289a55 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289a5b 8bb8 24004007 mov edi,dword ptr ds:[eax+0x7400024]
|
||
* 14289a61 8b2d 70a71001 mov ebp,dword ptr ds:[0x110a770]
|
||
* 14289a67 03ee add ebp,esi
|
||
* 14289a69 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 14289a6f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289a75 8bb0 20004007 mov esi,dword ptr ds:[eax+0x7400020]
|
||
* 14289a7b 8bc5 mov eax,ebp
|
||
* 14289a7d 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289a83 66:89b8 c2034007 mov word ptr ds:[eax+0x74003c2],di
|
||
* 14289a8a 8bc5 mov eax,ebp
|
||
* 14289a8c 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289a92 66:89b0 c0034007 mov word ptr ds:[eax+0x74003c0],si
|
||
* 14289a99 8b05 aca71001 mov eax,dword ptr ds:[0x110a7ac]
|
||
* 14289a9f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289aa5 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 14289aac 81e6 ff000000 and esi,0xff
|
||
* 14289ab2 892d 70a71001 mov dword ptr ds:[0x110a770],ebp
|
||
* 14289ab8 893d 74a71001 mov dword ptr ds:[0x110a774],edi
|
||
* 14289abe 8935 78a71001 mov dword ptr ds:[0x110a778],esi
|
||
* 14289ac4 c705 e4a71001 d8>mov dword ptr ds:[0x110a7e4],0x881abd8
|
||
* 14289ace 832d c4aa1001 09 sub dword ptr ds:[0x110aac4],0x9
|
||
* 14289ad5 ^e9 d6c6f8ff jmp 142161b0
|
||
* 14289ada 90 nop
|
||
*
|
||
* 14289adb cc int3
|
||
* 14289adc 77 0f ja short 14289aed
|
||
* 14289ade c705 a8aa1001 d8>mov dword ptr ds:[0x110aaa8],0x881abd8
|
||
* 14289ae8 -e9 176567ef jmp 03900004
|
||
* 14289aed 813d 70a71001 00>cmp dword ptr ds:[0x110a770],0x0
|
||
* 14289af7 0f85 2f000000 jnz 14289b2c
|
||
* 14289afd 8b05 aca71001 mov eax,dword ptr ds:[0x110a7ac]
|
||
* 14289b03 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14289b09 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 14289b10 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 14289b16 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 14289b1d e9 22000000 jmp 14289b44
|
||
* 14289b22 0110 add dword ptr ds:[eax],edx
|
||
* 14289b24 af scas dword ptr es:[edi]
|
||
* 14289b25 8108 e9f76467 or dword ptr ds:[eax],0x6764f7e9
|
||
* 14289b2b ef out dx,eax ; i/o command
|
||
* 14289b2c 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 14289b33 c705 a8aa1001 e0>mov dword ptr ds:[0x110aaa8],0x881abe0
|
||
* 14289b3d -e9 e16467ef jmp 03900023
|
||
*
|
||
* PPSSPP 0.9.9 (7/27/2014)
|
||
*
|
||
* 0ed85942 cc int3
|
||
* 0ed85943 cc int3
|
||
* 0ed85944 77 0f ja short 0ed85955
|
||
* 0ed85946 c705 c84c1301 58>mov dword ptr ds:[0x1134cc8],0x881ab58
|
||
* 0ed85950 -e9 afa6aef4 jmp 03870004
|
||
* 0ed85955 8b35 94491301 mov esi,dword ptr ds:[0x1134994]
|
||
* 0ed8595b 0335 98491301 add esi,dword ptr ds:[0x1134998]
|
||
* 0ed85961 8b05 fc491301 mov eax,dword ptr ds:[0x11349fc]
|
||
* 0ed85967 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8596d 8bb8 28008009 mov edi,dword ptr ds:[eax+0x9800028]
|
||
* 0ed85973 8bc6 mov eax,esi
|
||
* 0ed85975 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8597b 8bd7 mov edx,edi
|
||
* 0ed8597d 8890 10048009 mov byte ptr ds:[eax+0x9800410],dl
|
||
* 0ed85983 8b05 d0491301 mov eax,dword ptr ds:[0x11349d0]
|
||
* 0ed85989 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed8598f 8bb8 84008009 mov edi,dword ptr ds:[eax+0x9800084]
|
||
* 0ed85995 8b05 cc491301 mov eax,dword ptr ds:[0x11349cc]
|
||
* 0ed8599b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 0ed859a1 0fb6a8 00008009 movzx ebp,byte ptr ds:[eax+0x9800000] ; jichi: hook here
|
||
* 0ed859a8 81ff 00000000 cmp edi,0x0
|
||
* 0ed859ae 8935 90491301 mov dword ptr ds:[0x1134990],esi
|
||
* 0ed859b4 893d 94491301 mov dword ptr ds:[0x1134994],edi
|
||
* 0ed859ba 892d 98491301 mov dword ptr ds:[0x1134998],ebp
|
||
* 0ed859c0 0f85 16000000 jnz 0ed859dc
|
||
* 0ed859c6 832d e44c1301 06 sub dword ptr ds:[0x1134ce4],0x6
|
||
* 0ed859cd c705 c84c1301 ac>mov dword ptr ds:[0x1134cc8],0x881aeac
|
||
* 0ed859d7 -e9 47a6aef4 jmp 03870023
|
||
* 0ed859dc 832d e44c1301 06 sub dword ptr ds:[0x1134ce4],0x6
|
||
* 0ed859e3 e9 0c000000 jmp 0ed859f4
|
||
* 0ed859e8 0170 ab add dword ptr ds:[eax-0x55],esi
|
||
* 0ed859eb 8108 e931a6ae or dword ptr ds:[eax],0xaea631e9
|
||
* 0ed859f1 f4 hlt ; privileged command
|
||
* 0ed859f2 90 nop
|
||
*/
|
||
// TODO: Is reverse_strlen a better choice?
|
||
static void SpecialPSPHookYeti2(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = stack->eax;
|
||
LPCSTR text = LPCSTR(eax + hp->user_value);
|
||
if (BYTE c = *(BYTE *)text) {
|
||
*data = (DWORD)text;
|
||
//*len = text[1] ? 2 : 1;
|
||
*len = ::LeadByteTable[c];
|
||
|
||
*split = stack->edx;
|
||
//DWORD ecx = regof(ecx, esp_base);
|
||
//*split = ecx ? (FIXED_SPLIT_VALUE << 1) : 0; // << 1 to be unique, non-zero ecx is what I want
|
||
}
|
||
}
|
||
|
||
bool InsertYeti2PSPHook()
|
||
{
|
||
ConsoleOutput("Yeti2 PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14289827 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb8, XX4, // 1428982d 8bb8 28004007 mov edi,dword ptr ds:[eax+0x7400028]
|
||
0x8b,0xc6, // 14289833 8bc6 mov eax,esi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14289835 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xd7, // 1428983b 8bd7 mov edx,edi
|
||
0x88,0x90, XX4, // 1428983d 8890 10044007 mov byte ptr ds:[eax+0x7400410],dl
|
||
0x8b,0x05, XX4, // 14289843 8b05 b0a71001 mov eax,dword ptr ds:[0x110a7b0]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14289849 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb8, XX4, // 1428984f 8bb8 84004007 mov edi,dword ptr ds:[eax+0x7400084]
|
||
0x8b,0x05, XX4, // 14289855 8b05 aca71001 mov eax,dword ptr ds:[0x110a7ac]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1428985b 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xa8 //, XX4 // 14289861 0fb6a8 00004007 movzx ebp,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
// 14289b10 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
// 14289b16 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = sizeof(bytes) - memory_offset };
|
||
//enum { addr_offset = sizeof(bytes) + 4 }; // point to next statement after ebp is assigned
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Yeti2 PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookYeti2;
|
||
ConsoleOutput("Yeti2 PSP: INSERT");
|
||
succ|=NewHook(hp, "Yeti2 PSP");
|
||
}
|
||
|
||
ConsoleOutput("Yeti2 PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/22/2014 jichi: Nippon1 PSP engine, 0.9.8 only
|
||
* Sample game: ぁ<>の<EFBFBD>リンスさまっ♪ (0.9.8 only)
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: breakpoint the precomputed address
|
||
*
|
||
* The data is in (WORD)bp instead of eax.
|
||
* bp contains SHIFT-JIS CODEC_ANSI_BE data.
|
||
*
|
||
* There is only one text thread.
|
||
*
|
||
* 134e0553 cc int3
|
||
* 134e0554 77 0f ja short 134e0565
|
||
* 134e0556 c705 a8aa1001 34>mov dword ptr ds:[0x110aaa8],0x8853a34
|
||
* 134e0560 -e9 9ffa03f0 jmp 03520004
|
||
* 134e0565 8b35 74a71001 mov esi,dword ptr ds:[0x110a774]
|
||
* 134e056b d1e6 shl esi,1
|
||
* 134e056d c7c7 987db708 mov edi,0x8b77d98
|
||
* 134e0573 03fe add edi,esi
|
||
* 134e0575 8b2d 78a71001 mov ebp,dword ptr ds:[0x110a778]
|
||
* 134e057b 8bc7 mov eax,edi
|
||
* 134e057d 81e0 ffffff3f and eax,0x3fffffff
|
||
* 134e0583 66:89a8 00004007 mov word ptr ds:[eax+0x7400000],bp ; jichi: hook here
|
||
* 134e058a 8b2d 8c7df70f mov ebp,dword ptr ds:[0xff77d8c]
|
||
* 134e0590 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 134e0593 892d 8c7df70f mov dword ptr ds:[0xff77d8c],ebp
|
||
* 134e0599 8b05 e4a71001 mov eax,dword ptr ds:[0x110a7e4]
|
||
* 134e059f c705 74a71001 00>mov dword ptr ds:[0x110a774],0x8b70000
|
||
* 134e05a9 892d 78a71001 mov dword ptr ds:[0x110a778],ebp
|
||
* 134e05af 8935 7ca71001 mov dword ptr ds:[0x110a77c],esi
|
||
* 134e05b5 8905 a8aa1001 mov dword ptr ds:[0x110aaa8],eax
|
||
* 134e05bb 832d c4aa1001 0c sub dword ptr ds:[0x110aac4],0xc
|
||
* 134e05c2 -e9 5cfa03f0 jmp 03520023
|
||
*/
|
||
// Read text from bp
|
||
// TODO: This should be expressed as general hook without extern fun
|
||
static void SpecialPSPHookNippon1(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
LPCSTR text = LPCSTR(stack->base + hp->offset); // dynamic offset, ebp or esi
|
||
if (*text) {
|
||
*data = (DWORD)text;
|
||
*len = !text[0] ? 0 : !text[1] ? 1 : 2; // bp or si has at most two bytes
|
||
//*len = ::LeadByteTable[*(BYTE *)text] // TODO: Test leadbytetable
|
||
*split = stack->ecx;
|
||
}
|
||
}
|
||
|
||
bool InsertNippon1PSPHook()
|
||
{
|
||
ConsoleOutput("Nippon1 PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
//0xcc, // 134e0553 cc int3
|
||
0x77, 0x0f, // 134e0554 77 0f ja short 134e0565
|
||
0xc7,0x05, XX8, // 134e0556 c705 a8aa1001 34>mov dword ptr ds:[0x110aaa8],0x8853a34
|
||
0xe9, XX4, // 134e0560 -e9 9ffa03f0 jmp 03520004
|
||
0x8b,0x35, XX4, // 134e0565 8b35 74a71001 mov esi,dword ptr ds:[0x110a774]
|
||
0xd1,0xe6, // 134e056b d1e6 shl esi,1
|
||
0xc7,0xc7, XX4, // 134e056d c7c7 987db708 mov edi,0x8b77d98
|
||
0x03,0xfe, // 134e0573 03fe add edi,esi
|
||
0x8b,0x2d, XX4, // 134e0575 8b2d 78a71001 mov ebp,dword ptr ds:[0x110a778]
|
||
0x8b,0xc7, // 134e057b 8bc7 mov eax,edi
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 134e057d 81e0 ffffff3f and eax,0x3fffffff
|
||
0x66,0x89,0xa8, XX4, // 134e0583 66:89a8 00004007 mov word ptr ds:[eax+0x7400000],bp ; jichi: hook here
|
||
0x8b,0x2d, XX4, // 134e058a 8b2d 8c7df70f mov ebp,dword ptr ds:[0xff77d8c]
|
||
0x8d,0x6d, 0x01 // 134e0590 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x134e0583 - 0x134e0554 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Nippon1 PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.offset=get_reg(regs::ebp);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookNippon1;
|
||
ConsoleOutput("Nippon1 PSP: INSERT");
|
||
succ|=NewHook(hp, "Nippon1 PSP");
|
||
}
|
||
|
||
ConsoleOutput("Nippon1 PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
/** 7/26/2014 jichi: Alternative Nippon1 PSP engine, 0.9.8 only
|
||
* Sample game: 神<>悪戯 (0.9.8 only)
|
||
* Issue: character name cannot be extracted
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: breakpoint the precomputed address
|
||
*
|
||
* This function is the one that write the text into the memory.
|
||
*
|
||
* 13d13e8b 0f92c0 setb al
|
||
* 13d13e8e 8bf8 mov edi,eax
|
||
* 13d13e90 81ff 00000000 cmp edi,0x0
|
||
* 13d13e96 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
* 13d13e9c 8935 dca71001 mov dword ptr ds:[0x110a7dc],esi
|
||
* 13d13ea2 0f85 16000000 jnz 13d13ebe
|
||
* 13d13ea8 832d c4aa1001 0a sub dword ptr ds:[0x110aac4],0xa
|
||
* 13d13eaf c705 a8aa1001 cc>mov dword ptr ds:[0x110aaa8],0x887c2cc
|
||
* 13d13eb9 -e9 65c1a3ef jmp 03750023
|
||
* 13d13ebe 832d c4aa1001 0a sub dword ptr ds:[0x110aac4],0xa
|
||
* 13d13ec5 e9 0e000000 jmp 13d13ed8
|
||
* 13d13eca 01a8 c28708e9 add dword ptr ds:[eax+0xe90887c2],ebp
|
||
* 13d13ed0 4f dec edi
|
||
* 13d13ed1 c1a3 ef90cccc cc shl dword ptr ds:[ebx+0xcccc90ef],0xcc ; shift constant out of range 1..31
|
||
* 13d13ed8 77 0f ja short 13d13ee9
|
||
* 13d13eda c705 a8aa1001 a8>mov dword ptr ds:[0x110aaa8],0x887c2a8
|
||
* 13d13ee4 -e9 1bc1a3ef jmp 03750004
|
||
* 13d13ee9 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 13d13eef 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13d13ef5 0fb7b0 0000c007 movzx esi,word ptr ds:[eax+0x7c00000]
|
||
* 13d13efc 8b3d fccd5a10 mov edi,dword ptr ds:[0x105acdfc]
|
||
* 13d13f02 8bef mov ebp,edi
|
||
* 13d13f04 d1e5 shl ebp,1
|
||
* 13d13f06 81c5 e8cd9a08 add ebp,0x89acde8
|
||
* 13d13f0c 8bc5 mov eax,ebp
|
||
* 13d13f0e 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13d13f14 66:89b0 2000c007 mov word ptr ds:[eax+0x7c00020],si ; jichi: hook here
|
||
* 13d13f1b 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 13d13f1e 893d fccd5a10 mov dword ptr ds:[0x105acdfc],edi
|
||
* 13d13f24 8b15 dca71001 mov edx,dword ptr ds:[0x110a7dc]
|
||
* 13d13f2a 8d52 10 lea edx,dword ptr ds:[edx+0x10]
|
||
* 13d13f2d 8b05 e4a71001 mov eax,dword ptr ds:[0x110a7e4]
|
||
* 13d13f33 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
* 13d13f39 c705 7ca71001 e8>mov dword ptr ds:[0x110a77c],0x89acde8
|
||
* 13d13f43 8935 80a71001 mov dword ptr ds:[0x110a780],esi
|
||
* 13d13f49 892d 84a71001 mov dword ptr ds:[0x110a784],ebp
|
||
* 13d13f4f 8915 dca71001 mov dword ptr ds:[0x110a7dc],edx
|
||
* 13d13f55 8905 a8aa1001 mov dword ptr ds:[0x110aaa8],eax
|
||
* 13d13f5b 832d c4aa1001 0b sub dword ptr ds:[0x110aac4],0xb
|
||
* 13d13f62 -e9 bcc0a3ef jmp 03750023
|
||
* 13d13f67 90 nop
|
||
*/
|
||
|
||
// 8/13/2014: 5pb might crash on 0.9.9.
|
||
bool InsertNippon2PSPHook()
|
||
{
|
||
ConsoleOutput("Nippon2 PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
0xe9, XX4, // 13d13ee4 -e9 1bc1a3ef jmp 03750004
|
||
0x8b,0x05, XX4, // 13d13ee9 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13d13eef 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb7,0xb0, XX4, // 13d13ef5 0fb7b0 0000c007 movzx esi,word ptr ds:[eax+0x7c00000]
|
||
0x8b,0x3d, XX4, // 13d13efc 8b3d fccd5a10 mov edi,dword ptr ds:[0x105acdfc]
|
||
0x8b,0xef, // 13d13f02 8bef mov ebp,edi
|
||
0xd1,0xe5, // 13d13f04 d1e5 shl ebp,1
|
||
0x81,0xc5, XX4, // 13d13f06 81c5 e8cd9a08 add ebp,0x89acde8
|
||
0x8b,0xc5, // 13d13f0c 8bc5 mov eax,ebp
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13d13f0e 81e0 ffffff3f and eax,0x3fffffff
|
||
0x66,0x89,0xb0 //, XX4 // 13d13f14 66:89b0 2000c007 mov word ptr ds:[eax+0x7c00020],si ; jichi: hook here
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = sizeof(bytes) - memory_offset };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Nippon2 PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.offset=get_reg(regs::esi);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookNippon1;
|
||
ConsoleOutput("Nippon2 PSP: INSERT");
|
||
succ|=NewHook(hp, "Nippon2 PSP");
|
||
}
|
||
|
||
ConsoleOutput("Nippon2 PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
#if 0 // 8/9/2014 jichi: cannot find a good function
|
||
|
||
/** 8/9/2014 jichi Typemoon.com PSP engine, 0.9.8, 0.9.9,
|
||
*
|
||
* Sample game: Fate CCC
|
||
* This game is made by both TYPE-MOON and Imageepoch
|
||
* But the encoding is SHIFT-JIS than UTF-8 like other Imageepoch games.
|
||
* Otomate hook will produce significant amount of garbage.
|
||
*
|
||
* Memory address is FIXED.
|
||
* There are two matches in the memory.
|
||
*
|
||
* Debug method: breakpoint the memory address
|
||
* The hooked functions were looping which made it difficult to debug.
|
||
*
|
||
* Two looped functions are as follows. The first one is used
|
||
* The second function is tested as bad.
|
||
*
|
||
* Registers: (all of them are fixed except eax)
|
||
* EAX 08C91373
|
||
* ECX 00000016
|
||
* EDX 00000012
|
||
* EBX 0027A580
|
||
* ESP 0353E6D0
|
||
* EBP 0000000B
|
||
* ESI 0000001E
|
||
* EDI 00000001
|
||
* EIP 1351E14D
|
||
*
|
||
* 1351e12d f0:90 lock nop ; lock prefix is not allowed
|
||
* 1351e12f cc int3
|
||
* 1351e130 77 0f ja short 1351e141
|
||
* 1351e132 c705 a8aa1001 b8>mov dword ptr ds:[0x110aaa8],0x88ed7b8
|
||
* 1351e13c -e9 c31e27f0 jmp 03790004
|
||
* 1351e141 8b05 aca71001 mov eax,dword ptr ds:[0x110a7ac]
|
||
* 1351e147 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1351e14d 0fbeb0 01004007 movsx esi,byte ptr ds:[eax+0x7400001] ; or jichi: hook here
|
||
* 1351e154 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
* 1351e15a 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1351e160 8bb8 50004007 mov edi,dword ptr ds:[eax+0x7400050]
|
||
* 1351e166 81e6 ff000000 and esi,0xff
|
||
* 1351e16c 8bc6 mov eax,esi
|
||
* 1351e16e 8b35 a8a71001 mov esi,dword ptr ds:[0x110a7a8]
|
||
* 1351e174 0bf0 or esi,eax
|
||
* 1351e176 c1e6 10 shl esi,0x10
|
||
* 1351e179 c1fe 10 sar esi,0x10
|
||
* 1351e17c 893d 78a71001 mov dword ptr ds:[0x110a778],edi
|
||
* 1351e182 8935 7ca71001 mov dword ptr ds:[0x110a77c],esi
|
||
* 1351e188 c705 e4a71001 d4>mov dword ptr ds:[0x110a7e4],0x88ed7d4
|
||
* 1351e192 832d c4aa1001 07 sub dword ptr ds:[0x110aac4],0x7
|
||
* 1351e199 e9 0e000000 jmp 1351e1ac
|
||
* 1351e19e 01ac3e 8e08e97b add dword ptr ds:[esi+edi+0x7be9088e],eb>
|
||
* 1351e1a5 1e push ds
|
||
* 1351e1a6 27 daa
|
||
* 1351e1a7 f0:90 lock nop ; lock prefix is not allowed
|
||
* 1351e1a9 cc int3
|
||
*
|
||
* 13513f23 cc int3
|
||
* 13513f24 77 0f ja short 13513f35
|
||
* 13513f26 c705 a8aa1001 d4>mov dword ptr ds:[0x110aaa8],0x88e7bd4
|
||
* 13513f30 -e9 cfc027f0 jmp 03790004
|
||
* 13513f35 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 13513f3b 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13513f41 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000]
|
||
* 13513f48 8b3d 84a71001 mov edi,dword ptr ds:[0x110a784]
|
||
* 13513f4e 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 13513f51 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 13513f57 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13513f5d 8bd6 mov edx,esi
|
||
* 13513f5f 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl ; jichi: bad hook
|
||
* 13513f65 8b2d 78a71001 mov ebp,dword ptr ds:[0x110a778]
|
||
* 13513f6b 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 13513f6e 33c0 xor eax,eax
|
||
* 13513f70 3b3d 80a71001 cmp edi,dword ptr ds:[0x110a780]
|
||
* 13513f76 0f9cc0 setl al
|
||
* 13513f79 8bf0 mov esi,eax
|
||
* 13513f7b 8b15 7ca71001 mov edx,dword ptr ds:[0x110a77c]
|
||
* 13513f81 8d52 01 lea edx,dword ptr ds:[edx+0x1]
|
||
* 13513f84 81fe 00000000 cmp esi,0x0
|
||
* 13513f8a 892d 78a71001 mov dword ptr ds:[0x110a778],ebp
|
||
* 13513f90 8915 7ca71001 mov dword ptr ds:[0x110a77c],edx
|
||
* 13513f96 893d 84a71001 mov dword ptr ds:[0x110a784],edi
|
||
* 13513f9c 8935 88a71001 mov dword ptr ds:[0x110a788],esi
|
||
* 13513fa2 0f84 16000000 je 13513fbe
|
||
* 13513fa8 832d c4aa1001 07 sub dword ptr ds:[0x110aac4],0x7
|
||
* 13513faf ^e9 70ffffff jmp 13513f24
|
||
* 13513fb4 01d4 add esp,edx
|
||
* 13513fb6 7b 8e jpo short 13513f46
|
||
* 13513fb8 08e9 or cl,ch
|
||
* 13513fba 65:c027 f0 shl byte ptr gs:[edi],0xf0 ; shift constant out of range 1..31
|
||
* 13513fbe 832d c4aa1001 07 sub dword ptr ds:[0x110aac4],0x7
|
||
* 13513fc5 e9 0e000000 jmp 13513fd8
|
||
* 13513fca 01f0 add eax,esi
|
||
* 13513fcc 7b 8e jpo short 13513f5c
|
||
* 13513fce 08e9 or cl,ch
|
||
* 13513fd0 4f dec edi
|
||
* 13513fd1 c027 f0 shl byte ptr ds:[edi],0xf0 ; shift constant out of range 1..31
|
||
* 13513fd4 90 nop
|
||
* 13513fd5 cc int3
|
||
* 13513fd6 cc int3
|
||
*/
|
||
// Read text from dl
|
||
static void SpecialPSPHookTypeMoon(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
DWORD eax = regof(eax, esp_base);
|
||
DWORD text = eax + hp->user_value - 1; // the text is in the previous byte
|
||
if (BYTE c = *(BYTE *)text) { // unsigned char
|
||
*data = text;
|
||
*len = ::LeadByteTable[c]; // 1 or 2
|
||
//*split = regof(ecx, esp_base);
|
||
//*split = regof(edx, esp_base);
|
||
*split = regof(ebx, esp_base);
|
||
}
|
||
}
|
||
bool InsertTypeMoonPSPHook()
|
||
{
|
||
ConsoleOutput("TypeMoon PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 1351e130 77 0f ja short 1351e141
|
||
0xc7,0x05, XX8, // 1351e132 c705 a8aa1001 b8>mov dword ptr ds:[0x110aaa8],0x88ed7b8
|
||
0xe9, XX4, // 1351e13c -e9 c31e27f0 jmp 03790004
|
||
0x8b,0x05, XX4, // 1351e141 8b05 aca71001 mov eax,dword ptr ds:[0x110a7ac]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1351e147 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 1351e14d 0fbeb0 01004007 movsx esi,byte ptr ds:[eax+0x7400001] ; jichi: hook here
|
||
0x8b,0x05, XX4, // 1351e154 8b05 dca71001 mov eax,dword ptr ds:[0x110a7dc]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1351e15a 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb8, XX4, // 1351e160 8bb8 50004007 mov edi,dword ptr ds:[eax+0x7400050]
|
||
0x81,0xe6, 0xff,0x00,0x00,0x00, // 1351e166 81e6 ff000000 and esi,0xff
|
||
0x8b,0xc6, // 1351e16c 8bc6 mov eax,esi
|
||
0x8b,0x35, XX4, // 1351e16e 8b35 a8a71001 mov esi,dword ptr ds:[0x110a7a8]
|
||
0x0b,0xf0, // 1351e174 0bf0 or esi,eax
|
||
0xc1,0xe6, 0x10, // 1351e176 c1e6 10 shl esi,0x10
|
||
0xc1,0xfe, 0x10 // 1351e179 c1fe 10 sar esi,0x10
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x1351e14d - 0x1351e130 };
|
||
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("TypeMoon PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookTypeMoon;
|
||
ConsoleOutput("TypeMoon PSP: INSERT");
|
||
NewHook(hp, "TypeMoon PSP");
|
||
}
|
||
|
||
ConsoleOutput("TypeMoon PSP: leave");
|
||
return addr;
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
#if 0 // 7/25/2014: This function is not invoked? Why?
|
||
/** 7/22/2014 jichi: KOEI TECMO PSP, 0.9.8
|
||
* Sample game: 金色のコルダ3
|
||
*
|
||
* 134598e2 cc int3
|
||
* 134598e3 cc int3
|
||
* 134598e4 77 0f ja short 134598f5
|
||
* 134598e6 c705 a8aa1001 8c>mov dword ptr ds:[0x110aaa8],0x880f08c
|
||
* 134598f0 -e9 0f67fbef jmp 03410004
|
||
* 134598f5 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 134598fb 81e0 ffffff3f and eax,0x3fffffff
|
||
* 13459901 8bb0 00004007 mov esi,dword ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 13459907 8b3d 7ca71001 mov edi,dword ptr ds:[0x110a77c]
|
||
* 1345990d 8d7f 04 lea edi,dword ptr ds:[edi+0x4]
|
||
* 13459910 8b05 84a71001 mov eax,dword ptr ds:[0x110a784]
|
||
* 13459916 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1345991c 89b0 00004007 mov dword ptr ds:[eax+0x7400000],esi
|
||
* 13459922 8b2d 84a71001 mov ebp,dword ptr ds:[0x110a784]
|
||
* 13459928 8d6d 04 lea ebp,dword ptr ss:[ebp+0x4]
|
||
* 1345992b 8b15 78a71001 mov edx,dword ptr ds:[0x110a778]
|
||
* 13459931 81fa 01000000 cmp edx,0x1
|
||
* 13459937 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 1345993d 893d 7ca71001 mov dword ptr ds:[0x110a77c],edi
|
||
* 13459943 892d 84a71001 mov dword ptr ds:[0x110a784],ebp
|
||
* 13459949 c705 88a71001 01>mov dword ptr ds:[0x110a788],0x1
|
||
* 13459953 0f84 16000000 je 1345996f
|
||
* 13459959 832d c4aa1001 09 sub dword ptr ds:[0x110aac4],0x9
|
||
* 13459960 e9 17000000 jmp 1345997c
|
||
* 13459965 0190 f08008e9 add dword ptr ds:[eax+0xe90880f0],edx
|
||
* 1345996b b4 66 mov ah,0x66
|
||
* 1345996d fb sti
|
||
* 1345996e ef out dx,eax ; i/o command
|
||
* 1345996f 832d c4aa1001 09 sub dword ptr ds:[0x110aac4],0x9
|
||
* 13459976 ^e9 ddc1ffff jmp 13455b58
|
||
* 1345997b 90 nop
|
||
*/
|
||
bool InsertTecmoPSPHook()
|
||
{
|
||
ConsoleOutput("Tecmo PSP: enter");
|
||
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 134598e4 77 0f ja short 134598f5
|
||
0xc7,0x05, XX8, // 134598e6 c705 a8aa1001 8c>mov dword ptr ds:[0x110aaa8],0x880f08c
|
||
0xe9, XX4, // 134598f0 -e9 0f67fbef jmp 03410004
|
||
0x8b,0x05, XX4, // 134598f5 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 134598fb 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xb0, XX4, // 13459901 8bb0 00004007 mov esi,dword ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x8b,0x3d, XX4, // 13459907 8b3d 7ca71001 mov edi,dword ptr ds:[0x110a77c]
|
||
0x8d,0x7f, 0x04, // 1345990d 8d7f 04 lea edi,dword ptr ds:[edi+0x4]
|
||
0x8b,0x05, XX4, // 13459910 8b05 84a71001 mov eax,dword ptr ds:[0x110a784]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13459916 81e0 ffffff3f and eax,0x3fffffff
|
||
0x89,0xb0 //, XX4, // 1345991c 89b0 00004007 mov dword ptr ds:[eax+0x7400000],esi
|
||
//0x8b,0x2d, XX4, // 13459922 8b2d 84a71001 mov ebp,dword ptr ds:[0x110a784]
|
||
//0x8d,0x6d, 0x04, // 13459928 8d6d 04 lea ebp,dword ptr ss:[ebp+0x4]
|
||
//0x8b,0x15, XX4, // 1345992b 8b15 78a71001 mov edx,dword ptr ds:[0x110a778]
|
||
//0x81,0xfa, 0x01,0x00,0x00,0x00 // 13459931 81fa 01000000 cmp edx,0x1
|
||
};
|
||
enum { memory_offset = 2 };
|
||
enum { addr_offset = 0x13459901 - 0x134598e4 };
|
||
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Tecmo PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.split = get_reg(regs::ecx);
|
||
hp.text_fun = SpecialPSPHook;
|
||
ConsoleOutput("Tecmo PSP: INSERT");
|
||
NewHook(hp, "Tecmo PSP");
|
||
}
|
||
|
||
ConsoleOutput("Tecmo PSP: leave");
|
||
return addr;
|
||
}
|
||
#endif // 0
|
||
|
||
#if 0 // 8/9/2014 jichi: does not work
|
||
|
||
bool InsertKadokawaPSPHook()
|
||
{
|
||
ConsoleOutput("Kadokawa PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 134844f3 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb0, XX4, // 134844f9 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here, byte by byte
|
||
0x8b,0x05, XX4, // 13484500 8b05 84a71001 mov eax,dword ptr ds:[0x110a784]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 13484506 81e0 ffffff3f and eax,0x3fffffff
|
||
0x8b,0xd6, // 1348450c 8bd6 mov edx,esi
|
||
0x88,0x90, XX4, // 1348450e 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl
|
||
0x8b,0x3d, XX4, // 13484514 8b3d 84a71001 mov edi,dword ptr ds:[0x110a784]
|
||
0x8d,0x7f, 0x01, // 1348451a 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
0x8b,0x2d, XX4, // 1348451d 8b2d 7ca71001 mov ebp,dword ptr ds:[0x110a77c]
|
||
0x8d,0x6d, 0x01, // 13484523 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
0x3b,0x3d, XX4, // 13484526 3b3d 74a71001 cmp edi,dword ptr ds:[0x110a774]
|
||
0x89,0x35, XX4, // 1348452c 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
0x89,0x2d, XX4, // 13484532 892d 7ca71001 mov dword ptr ds:[0x110a77c],ebp
|
||
0x89,0x3d, XX4, // 13484538 893d 84a71001 mov dword ptr ds:[0x110a784],edi
|
||
// Above is not sufficient
|
||
//0x0f,0x84, XX4, // 1348453e 0f84 16000000 je 1348455a
|
||
//0x83,0x2d, XX4, 0x05, // 13484544 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
//0xe9, XX4, // 1348454b ^e9 8cffffff jmp 134844dc
|
||
//0x01,0x38, // 13484550 0138 add dword ptr ds:[eax],edi
|
||
//0xb0, 0x84, // 13484552 b0 84 mov al,0x84
|
||
//0x08,0xe9 // 13484554 08e9 or cl,ch
|
||
// Below will change at runtime
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x134844f9 - 0x134844f3 };
|
||
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr) {
|
||
ConsoleOutput("Kadokawa PSP: pattern not found");
|
||
return false;
|
||
}
|
||
addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes), addr);
|
||
addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes), addr);
|
||
|
||
if (!addr)
|
||
ConsoleOutput("Kadokawa PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.split = get_reg(regs::ecx);
|
||
hp.length_offset = 1; // byte by byte
|
||
hp.text_fun = SpecialPSPHook;
|
||
|
||
//GROWL_DWORD2(hp.address, hp.user_value);
|
||
ConsoleOutput("Kadokawa PSP: INSERT");
|
||
NewHook(hp, "Kadokawa PSP");
|
||
}
|
||
|
||
ConsoleOutput("Kadokawa PSP: leave");
|
||
return addr;
|
||
}
|
||
#endif // 0
|
||
|
||
#if 0 // FIXME: I am not able to find stable pattern in PSP 0.9.9.1
|
||
|
||
/** 9/21/2014 jichi Otomate PPSSPP 0.9.9.1
|
||
* Sample game: Amnesia Later
|
||
*
|
||
* There are four fixed memory addresses.
|
||
* The two out of four can be used.
|
||
* (The other twos have loops or cannot be debugged).
|
||
*
|
||
* This function is the same as PPSSPP 0.9.9.1 (?).
|
||
*
|
||
* 14039126 cc int3
|
||
* 14039127 cc int3
|
||
* 14039128 77 0f ja short 14039139
|
||
* 1403912a c705 988e1301 3c>mov dword ptr ds:[0x1138e98],0x8922c3c
|
||
* 14039134 -e9 cb6e83ef jmp 03870004
|
||
* 14039139 8b05 688b1301 mov eax,dword ptr ds:[0x1138b68]
|
||
* 1403913f 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14039145 0fbeb0 00000008 movsx esi,byte ptr ds:[eax+0x8000000] ; jichi: text accessed, but looped
|
||
* 1403914c 8b05 6c8b1301 mov eax,dword ptr ds:[0x1138b6c]
|
||
* 14039152 81e0 ffffff3f and eax,0x3fffffff
|
||
* 14039158 0fbeb8 00000008 movsx edi,byte ptr ds:[eax+0x8000000]
|
||
* 1403915f 3bf7 cmp esi,edi
|
||
* 14039161 8935 748b1301 mov dword ptr ds:[0x1138b74],esi
|
||
* 14039167 893d 7c8b1301 mov dword ptr ds:[0x1138b7c],edi
|
||
* 1403916d 0f84 2f000000 je 140391a2
|
||
* 14039173 8b05 688b1301 mov eax,dword ptr ds:[0x1138b68]
|
||
* 14039179 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1403917f 0fb6b0 00000008 movzx esi,byte ptr ds:[eax+0x8000000] ; jichi: hook here
|
||
* 14039186 8935 608b1301 mov dword ptr ds:[0x1138b60],esi
|
||
* 1403918c 832d b48e1301 04 sub dword ptr ds:[0x1138eb4],0x4
|
||
* 14039193 e9 24000000 jmp 140391bc
|
||
* 14039198 0170 2c add dword ptr ds:[eax+0x2c],esi
|
||
* 1403919b 92 xchg eax,edx
|
||
* 1403919c 08e9 or cl,ch
|
||
* 1403919e 816e 83 ef832db4 sub dword ptr ds:[esi-0x7d],0xb42d83ef
|
||
* 140391a5 8e13 mov ss,word ptr ds:[ebx] ; modification of segment register
|
||
* 140391a7 0104e9 add dword ptr ds:[ecx+ebp*8],eax
|
||
* 140391aa b2 59 mov dl,0x59
|
||
* 140391ac 0000 add byte ptr ds:[eax],al
|
||
* 140391ae 014c2c 92 add dword ptr ss:[esp+ebp-0x6e],ecx
|
||
* 140391b2 08e9 or cl,ch
|
||
* 140391b4 6b6e 83 ef imul ebp,dword ptr ds:[esi-0x7d],-0x11
|
||
* 140391b8 90 nop
|
||
* 140391b9 cc int3
|
||
* 140391ba cc int3
|
||
*/
|
||
// Get bytes in esi
|
||
static void SpecialPSPHookOtomate2(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
||
{
|
||
//static uniquemap uniq;
|
||
DWORD text = esp_base + get_reg(regs::esi);
|
||
if (*(LPCSTR *)text) {
|
||
*split = regof(ecx, esp_base); // this would cause lots of texts, but it works for all games
|
||
*data = text;
|
||
*len = 1;
|
||
}
|
||
}
|
||
|
||
bool InsertOtomate2PSPHook()
|
||
{
|
||
ConsoleOutput("Otomate2 PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 14039128 77 0f ja short 14039139
|
||
0xc7,0x05, XX8, // 1403912a c705 988e1301 3c>mov dword ptr ds:[0x1138e98],0x8922c3c
|
||
0xe9, XX4, // 14039134 -e9 cb6e83ef jmp 03870004
|
||
0x8b,0x05, XX4, // 14039139 8b05 688b1301 mov eax,dword ptr ds:[0x1138b68]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1403913f 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 14039145 0fbeb0 00000008 movsx esi,byte ptr ds:[eax+0x8000000] ; jichi: text accessed, but looped
|
||
0x8b,0x05, XX4, // 1403914c 8b05 6c8b1301 mov eax,dword ptr ds:[0x1138b6c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14039152 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb8, XX4, // 14039158 0fbeb8 00000008 movsx edi,byte ptr ds:[eax+0x8000000]
|
||
0x3b,0xf7, // 1403915f 3bf7 cmp esi,edi
|
||
0x89,0x35, XX4, // 14039161 8935 748b1301 mov dword ptr ds:[0x1138b74],esi
|
||
0x89,0x3d, XX4, // 14039167 893d 7c8b1301 mov dword ptr ds:[0x1138b7c],edi
|
||
0x0f,0x84, 0x2f,0x00,0x00,0x00, // 1403916d 0f84 2f000000 je 140391a2
|
||
|
||
//0x8b,0x05, XX4, // 14039173 8b05 688b1301 mov eax,dword ptr ds:[0x1138b68]
|
||
//0x81,0xe0, 0xff,0xff,0xff,0x3f, // 14039179 81e0 ffffff3f and eax,0x3fffffff
|
||
//0x0f,0xb6,0xb0, XX4, // 1403917f 0fb6b0 00000008 movzx esi,byte ptr ds:[eax+0x8000000] ; jichi: text accessed
|
||
//0x89,0x35, XX4, // 14039186 8935 608b1301 mov dword ptr ds:[0x1138b60],esi ; jichi: hook here, get lower bytes in esi
|
||
//0x83,0x2d, XX4, 0x04 // 1403918c 832d b48e1301 04 sub dword ptr ds:[0x1138eb4],0x4
|
||
};
|
||
enum { addr_offset = 0x14039186 - 0x14039128 };
|
||
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr) {
|
||
ConsoleOutput("Otomate2 PSP: leave: first pattern not found");
|
||
return false;
|
||
}
|
||
addr += addr_offset;
|
||
|
||
//0x89,0x35, XX4, // 14039186 8935 608b1301 mov dword ptr ds:[0x1138b60],esi ; jichi: hook here, get lower bytes in esi
|
||
enum : WORD { mov_esi = 0x3589 };
|
||
if (*(WORD *)addr != mov_esi) {
|
||
ConsoleOutput("Otomate2 PSP: leave: second pattern not found");
|
||
return false;
|
||
}
|
||
|
||
HookParam hp;
|
||
hp.address = addr;
|
||
hp.type = USING_STRING|NO_CONTEXT;
|
||
hp.text_fun = SpecialPSPHookOtomate2;
|
||
ConsoleOutput("Otomate2 PSP: INSERT");
|
||
NewHook(hp, "Otomate PSP");
|
||
|
||
ConsoleOutput("Otomate2 PSP: leave");
|
||
return addr;
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
/** 8/9/2014 jichi Kadokawa.co.jp PSP engine, 0.9.8, ?,
|
||
*
|
||
* Sample game: 未来日<E69DA5>work on 0.9.8, not tested on 0.9.9
|
||
*
|
||
* FIXME: Currently, only the character name works
|
||
*
|
||
* Memory address is FIXED.
|
||
* Debug method: predict and breakpoint the memory address
|
||
*
|
||
* There are two matches in the memory, and only one function accessing them.
|
||
*
|
||
* Character name function is as follows.
|
||
* The scenario is the text after the name.
|
||
*
|
||
* 1348d79f cc int3
|
||
* 1348d7a0 77 0f ja short 1348d7b1
|
||
* 1348d7a2 c705 a8aa1001 fc>mov dword ptr ds:[0x110aaa8],0x884c6fc
|
||
* 1348d7ac -e9 532844f0 jmp 038d0004
|
||
* 1348d7b1 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
* 1348d7b7 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1348d7bd 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
* 1348d7c4 81fe 00000000 cmp esi,0x0
|
||
* 1348d7ca 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 1348d7d0 0f85 2f000000 jnz 1348d805
|
||
* 1348d7d6 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 1348d7dc 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1348d7e2 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000]
|
||
* 1348d7e9 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 1348d7ef 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 1348d7f6 c705 a8aa1001 5c>mov dword ptr ds:[0x110aaa8],0x884c75c
|
||
* 1348d800 -e9 1e2844f0 jmp 038d0023
|
||
* 1348d805 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 1348d80c e9 0b000000 jmp 1348d81c
|
||
* 1348d811 0108 add dword ptr ds:[eax],ecx
|
||
* 1348d813 c78408 e9082844 >mov dword ptr ds:[eax+ecx+0x442808e9],0x>
|
||
* 1348d81e c705 a8aa1001 08>mov dword ptr ds:[0x110aaa8],0x884c708
|
||
* 1348d828 -e9 d72744f0 jmp 038d0004
|
||
* 1348d82d 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
* 1348d833 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1348d839 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000]
|
||
* 1348d840 81fe 00000000 cmp esi,0x0
|
||
* 1348d846 8935 88a71001 mov dword ptr ds:[0x110a788],esi
|
||
* 1348d84c 0f85 16000000 jnz 1348d868
|
||
* 1348d852 832d c4aa1001 03 sub dword ptr ds:[0x110aac4],0x3
|
||
* 1348d859 e9 aa030000 jmp 1348dc08
|
||
* 1348d85e 0154c7 84 add dword ptr ds:[edi+eax*8-0x7c],edx
|
||
* 1348d862 08e9 or cl,ch
|
||
* 1348d864 bb 2744f083 mov ebx,0x83f04427
|
||
* 1348d869 2d c4aa1001 sub eax,0x110aac4
|
||
* 1348d86e 03e9 add ebp,ecx
|
||
* 1348d870 0c 00 or al,0x0
|
||
* 1348d872 0000 add byte ptr ds:[eax],al
|
||
* 1348d874 0114c7 add dword ptr ds:[edi+eax*8],edx
|
||
* 1348d877 8408 test byte ptr ds:[eax],cl
|
||
* 1348d879 -e9 a52744f0 jmp 038d0023
|
||
* 1348d87e 90 nop
|
||
* 1348d87f cc int3
|
||
*
|
||
* Scenario function is as follows.
|
||
* But I am not able to find it at runtime.
|
||
*
|
||
* 13484483 90 nop
|
||
* 13484484 77 0f ja short 13484495
|
||
* 13484486 c705 a8aa1001 30>mov dword ptr ds:[0x110aaa8],0x884b030
|
||
* 13484490 -e9 6fbb59f3 jmp 06a20004
|
||
* 13484495 8b35 74a71001 mov esi,dword ptr ds:[0x110a774]
|
||
* 1348449b 81fe 00000000 cmp esi,0x0
|
||
* 134844a1 9c pushfd
|
||
* 134844a2 8bc6 mov eax,esi
|
||
* 134844a4 8b35 84a71001 mov esi,dword ptr ds:[0x110a784]
|
||
* 134844aa 03f0 add esi,eax
|
||
* 134844ac 8935 74a71001 mov dword ptr ds:[0x110a774],esi
|
||
* 134844b2 9d popfd
|
||
* 134844b3 0f8f 0c000000 jg 134844c5
|
||
* 134844b9 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 134844c0 ^e9 23b0f9ff jmp 1341f4e8
|
||
* 134844c5 832d c4aa1001 02 sub dword ptr ds:[0x110aac4],0x2
|
||
* 134844cc e9 0b000000 jmp 134844dc
|
||
* 134844d1 0138 add dword ptr ds:[eax],edi
|
||
* 134844d3 b0 84 mov al,0x84
|
||
* 134844d5 08e9 or cl,ch
|
||
* 134844d7 48 dec eax
|
||
* 134844d8 bb 59f39077 mov ebx,0x7790f359
|
||
* 134844dd 0fc7 ??? ; unknown command
|
||
* 134844df 05 a8aa1001 add eax,0x110aaa8
|
||
* 134844e4 38b0 8408e917 cmp byte ptr ds:[eax+0x17e90884],dh
|
||
* 134844ea bb 59f38b05 mov ebx,0x58bf359
|
||
* 134844ef ^7c a7 jl short 13484498
|
||
* 134844f1 1001 adc byte ptr ds:[ecx],al
|
||
* 134844f3 81e0 ffffff3f and eax,0x3fffffff
|
||
* 134844f9 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here, byte by byte
|
||
* 13484500 8b05 84a71001 mov eax,dword ptr ds:[0x110a784]
|
||
* 13484506 81e0 ffffff3f and eax,0x3fffffff
|
||
* 1348450c 8bd6 mov edx,esi
|
||
* 1348450e 8890 00004007 mov byte ptr ds:[eax+0x7400000],dl
|
||
* 13484514 8b3d 84a71001 mov edi,dword ptr ds:[0x110a784]
|
||
* 1348451a 8d7f 01 lea edi,dword ptr ds:[edi+0x1]
|
||
* 1348451d 8b2d 7ca71001 mov ebp,dword ptr ds:[0x110a77c]
|
||
* 13484523 8d6d 01 lea ebp,dword ptr ss:[ebp+0x1]
|
||
* 13484526 3b3d 74a71001 cmp edi,dword ptr ds:[0x110a774]
|
||
* 1348452c 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
* 13484532 892d 7ca71001 mov dword ptr ds:[0x110a77c],ebp
|
||
* 13484538 893d 84a71001 mov dword ptr ds:[0x110a784],edi
|
||
* 1348453e 0f84 16000000 je 1348455a
|
||
* 13484544 832d c4aa1001 05 sub dword ptr ds:[0x110aac4],0x5
|
||
* 1348454b ^e9 8cffffff jmp 134844dc
|
||
* 13484550 0138 add dword ptr ds:[eax],edi
|
||
* 13484552 b0 84 mov al,0x84
|
||
* 13484554 08e9 or cl,ch
|
||
* 13484556 c9 leave
|
||
* 13484557 ba 59f3832d mov edx,0x2d83f359
|
||
* 1348455c c4aa 100105e9 les ebp,fword ptr ds:[edx+0xe9050110] ; modification of segment register
|
||
* 13484562 0e push cs
|
||
* 13484563 0000 add byte ptr ds:[eax],al
|
||
* 13484565 0001 add byte ptr ds:[ecx],al
|
||
* 13484567 4c dec esp
|
||
* 13484568 b0 84 mov al,0x84
|
||
* 1348456a 08e9 or cl,ch
|
||
* 1348456c b3 ba mov bl,0xba
|
||
* 1348456e 59 pop ecx
|
||
* 1348456f f3: prefix rep: ; superfluous prefix
|
||
* 13484570 90 nop
|
||
* 13484571 cc int3
|
||
* 13484572 cc int3
|
||
* 13484573 cc int3
|
||
*/
|
||
bool InsertKadokawaNamePSPHook()
|
||
{
|
||
ConsoleOutput("Kadokawa Name PSP: enter");
|
||
const BYTE bytes[] = {
|
||
0x77, 0x0f, // 1348d7a0 77 0f ja short 1348d7b1
|
||
0xc7,0x05, XX8, // 1348d7a2 c705 a8aa1001 fc>mov dword ptr ds:[0x110aaa8],0x884c6fc
|
||
0xe9, XX4, // 1348d7ac -e9 532844f0 jmp 038d0004
|
||
0x8b,0x05, XX4, // 1348d7b1 8b05 78a71001 mov eax,dword ptr ds:[0x110a778]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1348d7b7 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xb6,0xb0, XX4, // 1348d7bd 0fb6b0 00004007 movzx esi,byte ptr ds:[eax+0x7400000] ; jichi: hook here
|
||
0x81,0xfe, 0x00,0x00,0x00,0x00, // 1348d7c4 81fe 00000000 cmp esi,0x0
|
||
0x89,0x35, XX4, // 1348d7ca 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
0x0f,0x85, 0x2f,0x00,0x00,0x00, // 1348d7d0 0f85 2f000000 jnz 1348d805
|
||
0x8b,0x05, XX4, // 1348d7d6 8b05 7ca71001 mov eax,dword ptr ds:[0x110a77c]
|
||
0x81,0xe0, 0xff,0xff,0xff,0x3f, // 1348d7dc 81e0 ffffff3f and eax,0x3fffffff
|
||
0x0f,0xbe,0xb0, XX4, // 1348d7e2 0fbeb0 00004007 movsx esi,byte ptr ds:[eax+0x7400000]
|
||
0x89,0x35 //, XX4, // 1348d7e9 8935 70a71001 mov dword ptr ds:[0x110a770],esi
|
||
};
|
||
enum { memory_offset = 3 };
|
||
enum { addr_offset = 0x1348d7bd - 0x1348d7a0 };
|
||
auto succ=false;
|
||
DWORD addr = SafeMatchBytesInPSPMemory(bytes, sizeof(bytes));
|
||
if (!addr)
|
||
ConsoleOutput("Kadokawa Name PSP: pattern not found");
|
||
else {
|
||
HookParam hp;
|
||
hp.address = addr + addr_offset;
|
||
hp.user_value = *(DWORD *)(hp.address + memory_offset);
|
||
hp.type = USING_STRING|USING_SPLIT|NO_CONTEXT;
|
||
hp.offset=get_reg(regs::eax);
|
||
hp.split = get_reg(regs::edx);
|
||
hp.text_fun = SpecialPSPHook;
|
||
|
||
//GROWL_DWORD2(hp.address, hp.user_value);
|
||
ConsoleOutput("Kadokawa Name PSP: INSERT");
|
||
succ|=NewHook(hp, "Kadokawa Name PSP");
|
||
}
|
||
|
||
ConsoleOutput("Kadokawa Name PSP: leave");
|
||
return succ;
|
||
}
|
||
|
||
bool InsertPPSSPPHooks()
|
||
{
|
||
//if (PPSSPP_VERSION[1] == 9 && (PPSSPP_VERSION[2] > 9 || PPSSPP_VERSION[2] == 9 && PPSSPP_VERSION[3] >= 1)) // >= 0.9.9.1
|
||
|
||
ConsoleOutput("PPSSPP: enter");
|
||
|
||
// http://stackoverflow.com/questions/940707/how-do-i-programatically-get-the-version-of-a-dll-or-exe-file
|
||
// get the version info for the file requested
|
||
// if (DWORD dwSize = ::GetFileVersionInfoSizeW(processPath, nullptr)) {
|
||
// UINT len = 0;
|
||
// BYTE * buf = new BYTE[dwSize];
|
||
// VS_FIXEDFILEINFO * info = nullptr;
|
||
// if (::GetFileVersionInfoW(processPath, 0, dwSize, buf)
|
||
// && ::VerQueryValueW(buf, L"\\", (LPVOID*)&info, &len)
|
||
// && info)
|
||
// {
|
||
// PPSSPP_VERSION[0] = HIWORD(info->dwFileVersionMS),
|
||
// PPSSPP_VERSION[1] = LOWORD(info->dwFileVersionMS),
|
||
// PPSSPP_VERSION[2] = HIWORD(info->dwFileVersionLS),
|
||
// PPSSPP_VERSION[3] = LOWORD(info->dwFileVersionLS);
|
||
//
|
||
// }
|
||
// else
|
||
// ConsoleOutput("failed to get PPSSPP version");
|
||
// delete[] buf;
|
||
//
|
||
//}
|
||
|
||
InsertPPSSPPHLEHooks();
|
||
|
||
if (PPSSPP_VERSION[1] == 9 && PPSSPP_VERSION[2] == 9 && PPSSPP_VERSION[3] == 0) // 0.9.9.0
|
||
InsertOtomatePPSSPPHook();
|
||
|
||
//bool engineFound = false;
|
||
Insert5pbPSPHook();
|
||
InsertCyberfrontPSPHook();
|
||
InsertImageepoch2PSPHook();
|
||
InsertFelistellaPSPHook();
|
||
|
||
InsertBroccoliPSPHook();
|
||
InsertIntensePSPHook();
|
||
//InsertKadokawaNamePSPHook(); // disabled
|
||
InsertKonamiPSPHook();
|
||
|
||
if (PPSSPP_VERSION[1] == 9 && PPSSPP_VERSION[2] == 8) { // only works for 0.9.8 anyway
|
||
InsertNippon1PSPHook();
|
||
InsertNippon2PSPHook(); // This could crash PPSSPP 099 just like 5pb
|
||
}
|
||
|
||
//InsertTecmoPSPHook();
|
||
|
||
// Generic hooks
|
||
|
||
bool bandaiFound = InsertBandaiPSPHook();
|
||
InsertBandaiNamePSPHook();
|
||
|
||
// Hooks whose pattern is not generic enouph
|
||
|
||
InsertYetiPSPHook();
|
||
InsertYeti2PSPHook();
|
||
|
||
InsertAlchemistPSPHook();
|
||
InsertAlchemist2PSPHook();
|
||
|
||
//InsertTypeMoonPSPHook() // otomate is creating too many garbage
|
||
//|| InsertOtomatePSPHook();
|
||
InsertOtomatePSPHook();
|
||
|
||
if (!bandaiFound) {
|
||
// KID pattern is a subset of BANDAI, and hence MUST NOT be together with BANDAI
|
||
// Sample BANDAI game that could be broken by KID: 寮<>のサクリファイス
|
||
InsertKidPSPHook(); // KID could lose text, could exist in multiple game
|
||
|
||
InsertImageepochPSPHook(); // Imageepoch could crash vnrcli for School Rumble PSP
|
||
}
|
||
|
||
ConsoleOutput("PPSSPP: leave");
|
||
return true;
|
||
}
|
||
|
||
/** Artikash 6/7/2019
|
||
* PPSSPP JIT code has pointers, but they are all added to an offset before being used.
|
||
Find that offset so that hook searching works properly.
|
||
To find the offset, find a page of mapped memory with size 0x1f00000, read and write permissions, take its address and subtract 0x8000000.
|
||
The above is useful for emulating PSP hardware, so unlikely to change between versions.
|
||
*/
|
||
bool FindPPSSPP()
|
||
{
|
||
bool found = false;
|
||
SYSTEM_INFO systemInfo;
|
||
GetNativeSystemInfo(&systemInfo);
|
||
for (BYTE* probe = NULL; probe < systemInfo.lpMaximumApplicationAddress;)
|
||
{
|
||
MEMORY_BASIC_INFORMATION info;
|
||
if (!VirtualQuery(probe, &info, sizeof(info)))
|
||
{
|
||
probe += systemInfo.dwPageSize;
|
||
}
|
||
else
|
||
{
|
||
if (info.RegionSize == 0x1f00000 && info.Protect == PAGE_READWRITE && info.Type == MEM_MAPPED)
|
||
{
|
||
found = true;
|
||
ConsoleOutput("PPSSPP memory found: searching for hooks should yield working hook codes");
|
||
// PPSSPP 1.8.0 compiles jal to sub dword ptr [ebp+0x360],??
|
||
memcpy(spDefault.pattern, Array<BYTE>{ 0x83, 0xAD, 0x60, 0x03, 0x00, 0x00 }, spDefault.length = 6);
|
||
spDefault.offset = 0;
|
||
spDefault.minAddress = 0;
|
||
spDefault.maxAddress = -1ULL;
|
||
spDefault.padding = (uintptr_t)probe - 0x8000000;
|
||
spDefault.hookPostProcessor = [](HookParam& hp)
|
||
{
|
||
hp.type |= NO_CONTEXT | USING_SPLIT | SPLIT_INDIRECT;
|
||
hp.split = get_reg(regs::ebp);
|
||
hp.split_index =get_reg(regs::eax); // this is where PPSSPP 1.8.0 stores its return address stack
|
||
};
|
||
}
|
||
probe += info.RegionSize;
|
||
}
|
||
}
|
||
return found;
|
||
}
|
||
|
||
bool PPSSPP::attach_function() {
|
||
bool _b1=InsertPPSSPPHooks(); // Artikash 8/4/2018: removed for now as doesn't work for non ancient ppsspp versions
|
||
bool _b2=FindPPSSPP();
|
||
if(_b1||_b2)
|
||
return true;
|
||
return false;
|
||
}
|
||
|