270 lines
12 KiB
C++
Raw Normal View History

2024-11-02 15:49:09 +08:00
#include "Artemis.h"
2024-02-07 20:59:24 +08:00
/**
* jichi 10/1/2013: Artemis Engine
* See: http://www.ies-net.com/
* See (CaoNiMaGeBi): http://tieba.baidu.com/p/2625537737
* Pattern:
* 650a2f 83c4 0c add esp,0xc ; hook here
* 650a32 0fb6c0 movzx eax,al
* 650a35 85c0 test eax,eax
* 0fb6c0 75 0e jnz short tsugokaz.0065a47
*
* Wrong: 0x400000 + 0x7c574
*
* //Example: [130927]妹スパイラル /HBN-8*0:14@65589F
* Example: <EFBFBD><EFBFBD>Trial /HBN-8*0:14@650A2F
* Note: 0x650a2f > 40000(base) + 20000(limit)
* - addr: 0x650a2f
* - text_fun: 0x0
* - function: 0
* - hook_len: 0
* - ind: 0
* - length_offset: 1
* - module: 0
* - off: 4294967284 = 0xfffffff4 = -0xc
* - recover_len: 0
* - split: 20 = 0x14
* - split_ind: 0
* - type: 1048 = 0x418
*
* @CaoNiMaGeBi:
* RECENT GAMES:
* [130927] /HBN-8*0:14@65589F
* [130927]<EFBFBD>
* [131025]<EFBFBD><EFBFBD>/HBN-8*0:14@650A2F (for trial version)
* CLIENT ORGANIZAIONS:
* CROWD
* D:drive.
* Hands-Aid Corporation
* iMel株式会社
* SHANNON
* SkyFish
* SNACK-FACTORY
* team flap
* Zodiac
* <EFBFBD><EFBFBD> *
* <EFBFBD>
* <EFBFBD>
* <EFBFBD><EFBFBD>
*
*
* CUCURI
*
* <EFBFBD>
* <EFBFBD>
*
*
* <EFBFBD><EFBFBD> */
bool InsertArtemis1Hook()
{
const BYTE bytes[] = {
2024-11-02 15:49:09 +08:00
0x83, 0xc4, 0x0c, // add esp,0xc ; hook here
0x0f, 0xb6, 0xc0, // movzx eax,al
0x85, 0xc0, // test eax,eax
0x75, 0x0e // jnz XXOO ; it must be 0xe, or there will be duplication
2024-02-07 20:59:24 +08:00
};
2024-11-02 15:49:09 +08:00
// enum { addr_offset = 0 };
2024-02-07 20:59:24 +08:00
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
2024-11-02 15:49:09 +08:00
// GROWL_DWORD3(reladdr, processStartAddress, range);
if (!addr)
{
2024-02-07 20:59:24 +08:00
ConsoleOutput("Artemis1: pattern not exist");
return false;
}
HookParam hp;
hp.address = addr;
2024-11-02 15:49:09 +08:00
hp.offset = get_reg(regs::ecx);
2024-02-07 20:59:24 +08:00
hp.split = get_stack(5);
2024-11-02 15:49:09 +08:00
hp.type = NO_CONTEXT | DATA_INDIRECT | USING_SPLIT; // 0x418
2024-02-07 20:59:24 +08:00
2024-11-02 15:49:09 +08:00
// hp.address = 0x650a2f;
// GROWL_DWORD(hp.address);
2024-02-07 20:59:24 +08:00
ConsoleOutput("INSERT Artemis1");
2024-11-02 15:49:09 +08:00
// ConsoleOutput("Artemis1");
2024-02-07 20:59:24 +08:00
return NewHook(hp, "Artemis1");
}
bool InsertArtemis2Hook()
{
const BYTE bytes[] = {
2024-11-02 15:49:09 +08:00
// 0054461F | CC | int3 |
0x55, // 00544620 | 55 | push ebp |
0x8B, 0xEC, // 00544621 | 8B EC | mov ebp,esp |
0x83, 0xE4, 0xF8, // 00544623 | 83 E4 F8 | and esp,FFFFFFF8 |
0x6A, 0xFF, // 00544626 | 6A FF | push FFFFFFFF |
0x68, XX4, // 00544628 | 68 68 7C 6A 00 | push 空のつくりかた体験版_ver3.0.6A7C68 |
0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, // 0054462D | 64 A1 00 00 00 00 | mov eax,dword ptr fs:[0] |
0x50, // 00544633 | 50 | push eax |
0x83, 0xEC, XX, // 00544634 | 83 EC 28 | sub esp,28 |
0xA1, XX4, // 00544637 | A1 F0 57 81 00 | mov eax,dword ptr ds:[8157F0] |
0x33, 0xC4, // 0054463C | 33 C4 | xor eax,esp |
0x89, 0x44, 0x24, XX, // 0054463E | 89 44 24 20 | mov dword ptr ss:[esp+20],eax |
0x53, // 00544642 | 53 | push ebx |
0x56, // 00544643 | 56 | push esi |
0x57, // 00544644 | 57 | push edi |
0xA1, XX4, // 00544645 | A1 F0 57 81 00 | mov eax,dword ptr ds:[8157F0] |
0x33, 0xC4, // 0054464A | 33 C4 | xor eax,esp |
0x50, // 0054464C | 50 | push eax |
0x8D, 0x44, 0x24, XX, // 0054464D | 8D 44 24 38 | lea eax,dword ptr ss:[esp+38] | [esp+38]:BaseThreadInitThunk
0x64, 0xA3, 0x00, 0x00, 0x00, 0x00, // 00544651 | 64 A3 00 00 00 00 | mov dword ptr fs:[0],eax |
0x8B, 0xF1, // 00544657 | 8B F1 | mov esi,ecx |
0x8B, 0x5D, 0x08, // 00544659 | 8B 5D 08 | mov ebx,dword ptr ss:[ebp+8] |
0x8B, 0x4D, 0x0C // 0054465C | 8B 4D 0C | mov ecx,dword ptr ss:[ebp+C] | ecx:DbgUiRemoteBreakin, [ebp+C]:BaseThreadInitThunk
2024-02-07 20:59:24 +08:00
};
2024-11-02 15:49:09 +08:00
enum
{
addr_offset = 0
}; // distance to the beginning of the function, which is 0x55 (push ebp)
2024-02-07 20:59:24 +08:00
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
2024-11-02 15:49:09 +08:00
if (!addr)
{
2024-02-07 20:59:24 +08:00
ConsoleOutput("Artemis2: pattern not found");
return false;
}
addr += addr_offset;
2024-11-02 15:49:09 +08:00
enum
{
push_ebp = 0x55
}; // beginning of the function
if (*(BYTE *)addr != push_ebp)
{
2024-02-07 20:59:24 +08:00
ConsoleOutput("Artemis2: beginning of the function not found");
return false;
}
HookParam hp;
hp.address = addr;
2024-11-02 15:49:09 +08:00
hp.offset = get_stack(1);
hp.type = USING_STRING | NO_CONTEXT;
2024-02-07 20:59:24 +08:00
ConsoleOutput("INSERT Artemis2");
2024-11-02 15:49:09 +08:00
bool succ = NewHook(hp, "Artemis2");
2024-02-07 20:59:24 +08:00
// Artikash 1/1/2019: Recent games seem to use utf8 encoding instead, other than that the hook is identical.
// Not sure how to differentiate which games are sjis/utf8 so insert both
hp.address = addr + 6;
2024-11-02 15:49:09 +08:00
hp.offset = get_reg(regs::ebp);
2024-02-07 20:59:24 +08:00
hp.index = 8; // ebp was also pushed
2024-11-02 15:49:09 +08:00
hp.type = CODEC_UTF8 | USING_STRING | DATA_INDIRECT;
succ |= NewHook(hp, "Artemis2");
// ConsoleOutput("Artemis2");
2024-02-07 20:59:24 +08:00
return succ;
}
bool InsertArtemis3Hook()
{
const BYTE bytes[] = {
2024-11-02 15:49:09 +08:00
0x55, // 005FD780 | 55 | push ebp |
0x8B, 0xEC, // 005FD781 | 8BEC | mov ebp,esp |
0x83, 0xE4, 0xF8, // 005FD783 | 83E4 F8 | and esp,FFFFFFF8 |
0x83, 0xEC, 0x3C, // 005FD786 | 83EC 3C | sub esp,3C |
0xA1, XX4, // 005FD789 | A1 6C908600 | mov eax,dword ptr ds:[86906C] |
0x33, 0xC4, // 005FD78E | 33C4 | xor eax,esp |
0x89, 0x44, 0x24, 0x38, // 005FD790 | 894424 38 | mov dword ptr ss:[esp+38],eax |
0x53, // 005FD794 | 53 | push ebx |
0x56, // 005FD795 | 56 | push esi |
0x8B, 0xC1, // 005FD796 | 8BC1 | mov eax,ecx |
0xC7, 0x44, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00, // 005FD798 | C74424 14 00000000 | mov dword ptr ss:[esp+14],0 |
0x8B, 0x4D, 0x0C, // 005FD7A0 | 8B4D 0C | mov ecx,dword ptr ss:[ebp+C] |
0x33, 0xF6, // 005FD7A3 | 33F6 | xor esi,esi |
0x57, // 005FD7A5 | 57 | push edi |
0x8B, 0x7D, 0x08, // 005FD7A6 | 8B7D 08 | mov edi,dword ptr ss:[ebp+8] |
0x89, 0x44, 0x24, 0x14, // 005FD7A9 | 894424 14 | mov dword ptr ss:[esp+14],eax |
0x89, 0x4C, 0x24, 0x28, // 005FD7AD | 894C24 28 | mov dword ptr ss:[esp+28],ecx |
0x80, 0x3F, 0x00, // 005FD7B1 | 803F 00 | cmp byte ptr ds:[edi],0 |
0x0F, 0x84, XX4, // 005FD7B4 | 0F84 88040000 | je ヘンタイ・プリズンsplit 1.5FDC42 |
0x83, 0xB8, XX4, 0x00, // 005FD7BA | 83B8 74030000 00 | cmp dword ptr ds:[eax+374],0 |
0x8B, 0xDF, // 005FD7C1 | 8BDF | mov ebx,edi |
2024-02-07 20:59:24 +08:00
};
2024-11-02 15:49:09 +08:00
enum
{
addr_offset = 0
}; // distance to the beginning of the function, which is 0x55 (push ebp)
2024-02-07 20:59:24 +08:00
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
2024-11-02 15:49:09 +08:00
if (!addr)
{
2024-02-07 20:59:24 +08:00
ConsoleOutput("Artemis3: pattern not found");
return false;
}
addr += addr_offset;
2024-11-02 15:49:09 +08:00
enum
{
push_ebp = 0x55
}; // beginning of the function
if (*(BYTE *)addr != push_ebp)
{
2024-02-07 20:59:24 +08:00
ConsoleOutput("Artemis3: beginning of the function not found");
return false;
}
HookParam hp;
hp.address = addr;
2024-11-02 15:49:09 +08:00
hp.offset = get_stack(1);
hp.type = USING_STRING | EMBED_ABLE | CODEC_UTF8 | EMBED_BEFORE_SIMPLE | EMBED_AFTER_NEW;
2024-02-07 20:59:24 +08:00
2024-11-02 15:49:09 +08:00
return NewHook(hp, "EmbedArtemis");
2024-02-07 20:59:24 +08:00
}
2024-11-02 15:49:09 +08:00
namespace
{
bool a4()
{
// 高慢な奥さんは好きですか?~傲慢人妻教師の堕とし方~
2024-02-07 20:59:24 +08:00
std::vector<uint64_t> addrs;
2024-11-02 15:49:09 +08:00
for (DWORD func : {(DWORD)GetGlyphOutlineA, (DWORD)GetGlyphOutlineW})
2024-04-25 18:09:46 +08:00
{
2024-11-02 15:49:09 +08:00
auto addrs_ = findiatcallormov_all(func, processStartAddress, processStartAddress, processStopAddress, PAGE_EXECUTE);
2024-04-25 18:09:46 +08:00
addrs.insert(addrs.end(), addrs_.begin(), addrs_.end());
}
2024-11-02 15:49:09 +08:00
bool ok = false;
for (auto addr : addrs)
{
2024-02-07 20:59:24 +08:00
auto funcaddr = MemDbg::findEnclosingAlignedFunction(addr);
2024-11-02 15:49:09 +08:00
if (!funcaddr)
continue;
BYTE sig1[] = {0x81, XX, 0x00, 0x00, 0x10, 0x00};
BYTE sig2[] = {0x68, 0x00, 0x02, 0x00, 0x00, 0x68, 0x00, 0x02, 0x00, 0x00};
BYTE sig3[] = {XX, 0x80, 0x00, 0x00, 0x00, 0x0f, 0x95, 0xc1};
BYTE sig4[] = {0xC1, XX, 0x18};
int found = 0;
for (auto sigsz : std::vector<std::pair<BYTE *, int>>{{sig1, sizeof(sig1)}, {sig2, sizeof(sig2)}, {sig3, sizeof(sig3)}, {sig4, sizeof(sig4)}})
{
auto fd = MemDbg::findBytes(sigsz.first, sigsz.second, funcaddr, addr);
if (fd)
found += 1;
2024-02-07 20:59:24 +08:00
}
2024-11-02 15:49:09 +08:00
if (found == 4)
{
2024-02-07 20:59:24 +08:00
{
HookParam hp;
hp.address = funcaddr;
2024-11-02 15:49:09 +08:00
hp.type = CODEC_ANSI_BE;
hp.offset = get_stack(2);
ok |= NewHook(hp, "Artemis4A");
2024-02-07 20:59:24 +08:00
}
{
HookParam hp;
2024-11-02 15:49:09 +08:00
hp.address = funcaddr + 5;
2024-02-07 20:59:24 +08:00
hp.type = CODEC_UTF16;
2024-11-02 15:49:09 +08:00
hp.offset = get_stack(2);
ok |= NewHook(hp, "Artemis4W");
2024-02-07 20:59:24 +08:00
}
return ok;
}
}
return false;
}
}
2024-11-02 15:49:09 +08:00
bool Artemis::attach_function()
{
return InsertArtemis1Hook() || InsertArtemis2Hook() || InsertArtemis3Hook() || a4();
}