mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-12-26 21:24:12 +08:00
204 lines
5.9 KiB
C++
204 lines
5.9 KiB
C++
|
#include"godot.h"
|
|||
|
|
|||
|
bool queryversion(WORD *_1, WORD *_2, WORD *_3, WORD *_4)
|
|||
|
{
|
|||
|
wchar_t fileName[MAX_PATH];
|
|||
|
GetModuleFileNameW(NULL, fileName, MAX_PATH);
|
|||
|
DWORD dwHandle;
|
|||
|
DWORD dwSize = GetFileVersionInfoSizeW(fileName, &dwHandle);
|
|||
|
if (dwSize == 0)
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
std::vector<char> versionInfoBuffer(dwSize);
|
|||
|
if (!GetFileVersionInfoW(fileName, dwHandle, dwSize, versionInfoBuffer.data()))
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
VS_FIXEDFILEINFO *pFileInfo;
|
|||
|
UINT fileInfoSize;
|
|||
|
if (!VerQueryValueW(versionInfoBuffer.data(), L"\\", reinterpret_cast<LPVOID *>(&pFileInfo), &fileInfoSize))
|
|||
|
{
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
DWORD ms = pFileInfo->dwFileVersionMS;
|
|||
|
DWORD ls = pFileInfo->dwFileVersionLS;
|
|||
|
|
|||
|
WORD majorVersion = HIWORD(ms);
|
|||
|
WORD minorVersion = LOWORD(ms);
|
|||
|
WORD buildNumber = HIWORD(ls);
|
|||
|
WORD revisionNumber = LOWORD(ls);
|
|||
|
*_1 = majorVersion;
|
|||
|
*_2 = minorVersion;
|
|||
|
*_3 = buildNumber;
|
|||
|
*_4 = revisionNumber;
|
|||
|
return true;
|
|||
|
}
|
|||
|
namespace{
|
|||
|
bool godot35(){
|
|||
|
//https://store.steampowered.com/app/1713610/__Purrgatory/
|
|||
|
//喵的炼狱 / Purrgatory
|
|||
|
/*
|
|||
|
int __userpurge sub_C49270@<eax>(
|
|||
|
int a1@<ecx>,
|
|||
|
int a2,
|
|||
|
int a3,
|
|||
|
float *a4,
|
|||
|
int *a5,
|
|||
|
int a6,
|
|||
|
int a7,
|
|||
|
int a8,
|
|||
|
int *a9,
|
|||
|
float *a10,
|
|||
|
float *a11,
|
|||
|
char a12,
|
|||
|
float *a13,
|
|||
|
int *a14,
|
|||
|
int *a15,
|
|||
|
int *a16,
|
|||
|
_BYTE *a17,
|
|||
|
int a18)
|
|||
|
*/
|
|||
|
/*
|
|||
|
特征
|
|||
|
v90 = *v81;
|
|||
|
if ( (unsigned __int16)(v90 - 11784) > 0x71F7u
|
|||
|
&& (unsigned __int16)(v90 + 21504) > 0x2BFFu
|
|||
|
&& (unsigned __int16)(v90 + 1792) > 0x1FFu
|
|||
|
&& (unsigned __int16)(v90 + 464) > 0x1Fu
|
|||
|
&& (unsigned __int16)(v90 + 155) > 0x77u )
|
|||
|
|
|||
|
|
|||
|
*/
|
|||
|
/*
|
|||
|
const CharType current = c[end];
|
|||
|
const bool separatable = (current >= 0x2E08 && current <= 0x9FFF) || // CJK scripts and symbols.
|
|||
|
(current >= 0xAC00 && current <= 0xD7FF) || // Hangul Syllables and Hangul Jamo Extended-B.
|
|||
|
(current >= 0xF900 && current <= 0xFAFF) || // CJK Compatibility Ideographs.
|
|||
|
(current >= 0xFE30 && current <= 0xFE4F) || // CJK Compatibility Forms.
|
|||
|
(current >= 0xFF65 && current <= 0xFF9F) || // Halfwidth forms of katakana
|
|||
|
(current >= 0xFFA0 && current <= 0xFFDC) || // Halfwidth forms of compatibility jamo characters for Hangul
|
|||
|
(current >= 0x20000 && current <= 0x2FA1F) || // CJK Unified Ideographs Extension B ~ F and CJK Compatibility Ideographs Supplement.
|
|||
|
(current >= 0x30000 && current <= 0x3134F); // CJK Unified Ideographs Extension G.
|
|||
|
*/
|
|||
|
/*
|
|||
|
这个函数是scene/gui/rich_text_label.cpp
|
|||
|
int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &y, int p_width, int p_line, ProcessMode p_mode, const Ref<Font> &p_base_font, const Color &p_base_color, const Color &p_font_color_shadow, bool p_shadow_as_outline, const Point2 &shadow_ofs, const Point2i &p_click_pos, Item **r_click_item, int *r_click_char, bool *r_outside, int p_char_count)
|
|||
|
*/
|
|||
|
BYTE sig[]={
|
|||
|
/*
|
|||
|
.text:017FA34C movzx eax, word ptr [esi]
|
|||
|
.text:017FA34F lea edx, [eax-2E08h]
|
|||
|
.text:017FA355 cmp dx, 71F7h
|
|||
|
.text:017FA35A lea edx, [eax+5400h]
|
|||
|
.text:017FA360 setbe cl
|
|||
|
.text:017FA363 cmp dx, 2BFFh
|
|||
|
.text:017FA368 setbe dl
|
|||
|
.text:017FA36B or dl, cl
|
|||
|
.text:017FA36D jz loc_17FA230
|
|||
|
*/
|
|||
|
0x0f,0xb7,0x06,
|
|||
|
0x8D,0x90,0xF8,0xD1,0xFF,0xFF,
|
|||
|
0x66,0x81,0xFA,0xF7,0x71,
|
|||
|
0x8D,0x90,0x00,0x54,0x00,0x00,
|
|||
|
0x0F,0x96,0xC1,
|
|||
|
0x66,0x81,0xFA,0xFF,0x2B,
|
|||
|
0x0F,0x96,0xc2,0x08,0xca,
|
|||
|
0x0f,0x84,
|
|||
|
};
|
|||
|
auto addr=MemDbg::findBytes(sig,sizeof(sig),processStartAddress,processStopAddress);
|
|||
|
if(!addr)return false;
|
|||
|
BYTE sig2[]={
|
|||
|
// shl esi, 6
|
|||
|
0xC1,0xE6,0x06
|
|||
|
};
|
|||
|
addr=reverseFindBytes(sig2,sizeof(sig2),addr-0x1800,addr);
|
|||
|
if(!addr)return false;
|
|||
|
BYTE sig3[]={0x01,0xF0};//add eax, esi
|
|||
|
addr=MemDbg::findBytes(sig3,sizeof(sig3),addr,addr+0x40);
|
|||
|
|
|||
|
if(!addr)return false;
|
|||
|
|
|||
|
HookParam hp;
|
|||
|
hp.address = addr+sizeof(sig3);
|
|||
|
|
|||
|
hp.type = USING_STRING|CODEC_UTF16;
|
|||
|
hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
|||
|
/*
|
|||
|
Line &l = p_frame->lines.write[p_line];
|
|||
|
Item *it = l.from;
|
|||
|
*/
|
|||
|
/*
|
|||
|
while (it) {
|
|||
|
switch (it->type) {
|
|||
|
case ITEM_ALIGN: {
|
|||
|
ItemAlign *align_it = static_cast<ItemAlign *>(it);
|
|||
|
|
|||
|
align = align_it->align;
|
|||
|
|
|||
|
} break;
|
|||
|
case ITEM_INDENT: {
|
|||
|
if (it != l.from) {
|
|||
|
ItemIndent *indent_it = static_cast<ItemIndent *>(it);
|
|||
|
|
|||
|
float indent = indent_it->level * tab_size * cfont->get_char_size(' ').width;
|
|||
|
margin += indent;
|
|||
|
begin += indent;
|
|||
|
wofs += indent;
|
|||
|
}
|
|||
|
|
|||
|
} break;
|
|||
|
case ITEM_TEXT: {
|
|||
|
ItemText *text = static_cast<ItemText *>(it);
|
|||
|
|
|||
|
Ref<Font> font = _find_font(it);
|
|||
|
if (font.is_null()) {
|
|||
|
font = p_base_font;
|
|||
|
}
|
|||
|
|
|||
|
const CharType *c = text->text.c_str();
|
|||
|
const CharType *cf = c;
|
|||
|
*/
|
|||
|
/*
|
|||
|
struct ItemText : public Item {
|
|||
|
String text;
|
|||
|
ItemText() { type = ITEM_TEXT; }
|
|||
|
};
|
|||
|
*/
|
|||
|
/*
|
|||
|
const CharType *String::c_str() const {
|
|||
|
static const CharType zero = 0;
|
|||
|
|
|||
|
return size() ? &operator[](0) : &zero;
|
|||
|
}
|
|||
|
*/
|
|||
|
|
|||
|
|
|||
|
//Line &l = p_frame->lines.write[p_line];
|
|||
|
//Item *it = l.from;
|
|||
|
|
|||
|
//auto v471 = (int *)((a7 << 6) + *(DWORD *)(a3 + 40));
|
|||
|
|
|||
|
if(stack->retaddr!=1)return;//不懂为什么这个是1,按理说返回地址应该一样才对。不管了无所谓
|
|||
|
auto v471= (DWORD*)stack->eax;
|
|||
|
auto v481 = *v471;
|
|||
|
auto ptr=*(WCHAR**)(v481 + 28);
|
|||
|
*data=(DWORD)ptr;
|
|||
|
*len=wcslen((wchar_t*)ptr)*2;
|
|||
|
};
|
|||
|
|
|||
|
return NewHook(hp, "godot35");
|
|||
|
}
|
|||
|
}
|
|||
|
bool godot::attach_function() {
|
|||
|
WORD _1,_2,_3,_4;
|
|||
|
queryversion(&_1,&_2,&_3,&_4);
|
|||
|
ConsoleOutput("%d %d %d %d",_1,_2,_3,_4);
|
|||
|
if(_1==3&&_2==5){
|
|||
|
return godot35();
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|