mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-30 17:15:38 +08:00
250 lines
11 KiB
C++
250 lines
11 KiB
C++
|
#include"Artemis.h"
|
|||
|
|
|||
|
/**
|
|||
|
* 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[] = {
|
|||
|
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
|
|||
|
};
|
|||
|
//enum { addr_offset = 0 };
|
|||
|
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|||
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|||
|
//GROWL_DWORD3(reladdr, processStartAddress, range);
|
|||
|
if (!addr) {
|
|||
|
ConsoleOutput("Artemis1: pattern not exist");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
HookParam hp;
|
|||
|
hp.address = addr;
|
|||
|
hp.offset=get_reg(regs::ecx);
|
|||
|
hp.split = get_stack(5);
|
|||
|
hp.type = NO_CONTEXT|DATA_INDIRECT|USING_SPLIT; // 0x418
|
|||
|
|
|||
|
//hp.address = 0x650a2f;
|
|||
|
//GROWL_DWORD(hp.address);
|
|||
|
|
|||
|
ConsoleOutput("INSERT Artemis1");
|
|||
|
|
|||
|
//ConsoleOutput("Artemis1");
|
|||
|
return NewHook(hp, "Artemis1");
|
|||
|
}
|
|||
|
|
|||
|
bool InsertArtemis2Hook()
|
|||
|
{
|
|||
|
const BYTE bytes[] = {
|
|||
|
// 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
|
|||
|
};
|
|||
|
enum { addr_offset = 0 }; // distance to the beginning of the function, which is 0x55 (push ebp)
|
|||
|
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|||
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|||
|
if (!addr) {
|
|||
|
ConsoleOutput("Artemis2: pattern not found");
|
|||
|
return false;
|
|||
|
}
|
|||
|
addr += addr_offset;
|
|||
|
enum { push_ebp = 0x55 }; // beginning of the function
|
|||
|
if (*(BYTE *)addr != push_ebp) {
|
|||
|
ConsoleOutput("Artemis2: beginning of the function not found");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
HookParam hp;
|
|||
|
hp.address = addr;
|
|||
|
hp.offset=get_stack(1);
|
|||
|
hp.type = USING_STRING|NO_CONTEXT;
|
|||
|
|
|||
|
ConsoleOutput("INSERT Artemis2");
|
|||
|
bool succ=NewHook(hp, "Artemis2");
|
|||
|
|
|||
|
// 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;
|
|||
|
hp.offset=get_reg(regs::ebp);
|
|||
|
hp.index = 8; // ebp was also pushed
|
|||
|
hp.type = CODEC_UTF8 | USING_STRING | DATA_INDIRECT ;
|
|||
|
succ|=NewHook(hp, "Artemis2");
|
|||
|
//ConsoleOutput("Artemis2");
|
|||
|
return succ;
|
|||
|
}
|
|||
|
|
|||
|
bool InsertArtemis3Hook()
|
|||
|
{
|
|||
|
const BYTE bytes[] = {
|
|||
|
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 |
|
|||
|
};
|
|||
|
|
|||
|
enum { addr_offset = 0 }; // distance to the beginning of the function, which is 0x55 (push ebp)
|
|||
|
ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR);
|
|||
|
ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range);
|
|||
|
if (!addr) {
|
|||
|
ConsoleOutput("Artemis3: pattern not found");
|
|||
|
return false;
|
|||
|
}
|
|||
|
addr += addr_offset;
|
|||
|
enum { push_ebp = 0x55 }; // beginning of the function
|
|||
|
if (*(BYTE *)addr != push_ebp) {
|
|||
|
ConsoleOutput("Artemis3: beginning of the function not found");
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
HookParam hp;
|
|||
|
hp.address = addr;
|
|||
|
hp.offset=get_stack(1);
|
|||
|
hp.type = USING_STRING| EMBED_ABLE|CODEC_UTF8|EMBED_BEFORE_SIMPLE|EMBED_AFTER_NEW;
|
|||
|
|
|||
|
|
|||
|
return NewHook(hp, "EmbedArtemis");
|
|||
|
}
|
|||
|
|
|||
|
namespace{
|
|||
|
bool a4(){
|
|||
|
//高慢な奥さんは好きですか?~傲慢人妻教師の堕とし方~
|
|||
|
auto entryA=Util::FindImportEntry(processStartAddress,(DWORD)GetGlyphOutlineA);
|
|||
|
auto entryW=Util::FindImportEntry(processStartAddress,(DWORD)GetGlyphOutlineW);
|
|||
|
std::vector<uint64_t> addrs;
|
|||
|
BYTE bytes[]={0xFF,0x15,XX4};
|
|||
|
for(DWORD entry:{entryA,entryW})
|
|||
|
if(entry) {
|
|||
|
memcpy(bytes+2,&entry,4);
|
|||
|
auto addrs_ = Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE, processStartAddress, processStopAddress);
|
|||
|
addrs.insert(addrs.end(), addrs_.begin(), addrs_.end());
|
|||
|
}
|
|||
|
bool ok=false;
|
|||
|
for (auto addr : addrs) {
|
|||
|
auto funcaddr = MemDbg::findEnclosingAlignedFunction(addr);
|
|||
|
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;
|
|||
|
}
|
|||
|
if(found==4){
|
|||
|
{
|
|||
|
HookParam hp;
|
|||
|
hp.address = funcaddr;
|
|||
|
hp.type = CODEC_ANSI_BE;
|
|||
|
hp.offset=get_stack(2);
|
|||
|
ok|=NewHook(hp, "Artemis4A");
|
|||
|
}
|
|||
|
{
|
|||
|
HookParam hp;
|
|||
|
hp.address = funcaddr+5;
|
|||
|
hp.type = CODEC_UTF16;
|
|||
|
hp.offset=get_stack(2);
|
|||
|
ok|=NewHook(hp, "Artemis4W");
|
|||
|
}
|
|||
|
return ok;
|
|||
|
}
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
bool Artemis::attach_function() {
|
|||
|
|
|||
|
return InsertArtemis1Hook() || InsertArtemis2Hook() || InsertArtemis3Hook()||a4();
|
|||
|
}
|