mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-27 07:44:02 +08:00
v8
This commit is contained in:
parent
ae81a3ee11
commit
9cbc2e0260
@ -1,17 +1,24 @@
|
||||
#include "v8.h"
|
||||
namespace{
|
||||
namespace
|
||||
{
|
||||
constexpr auto magicsend = L"\x01LUNAFROMJS\x01";
|
||||
constexpr auto magicrecv = L"\x01LUNAFROMHOST\x01";
|
||||
bool hookClipboard(){
|
||||
bool hookClipboard()
|
||||
{
|
||||
HookParam hp;
|
||||
hp.address = (uintptr_t)SetClipboardData;
|
||||
hp.type = USING_STRING | NO_CONTEXT | CODEC_UTF16 | EMBED_ABLE | EMBED_BEFORE_SIMPLE;
|
||||
hp.text_fun=[](hook_stack* stack, HookParam *hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
hp.text_fun = [](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
HGLOBAL hClipboardData = (HGLOBAL)stack->ARG2;
|
||||
auto text = (wchar_t *)GlobalLock(hClipboardData);
|
||||
if(startWith(text,magicsend)){
|
||||
if (startWith(text, magicsend))
|
||||
{
|
||||
text += wcslen(magicsend);
|
||||
auto spl=wcschr(text,L'\x02');
|
||||
auto spl = wcschr(text, L'\x03');
|
||||
strcpy(hp->name, wcasta(std::wstring(text, spl - text)).c_str());
|
||||
text = spl + 1;
|
||||
spl = wcschr(text, L'\x02');
|
||||
*split = std::stoi(std::wstring(text, spl - text));
|
||||
text = spl + 1;
|
||||
*data = (uintptr_t)text;
|
||||
@ -20,7 +27,8 @@ namespace{
|
||||
|
||||
GlobalUnlock(hClipboardData);
|
||||
};
|
||||
hp.hook_after=[](hook_stack*s,void* data, size_t len){
|
||||
hp.hook_after = [](hook_stack *s, void *data, size_t len)
|
||||
{
|
||||
std::wstring transwithfont = magicrecv;
|
||||
transwithfont += embedsharedmem->fontFamily;
|
||||
transwithfont += L'\x02';
|
||||
@ -31,10 +39,11 @@ namespace{
|
||||
GlobalUnlock(hClipboardData);
|
||||
s->ARG2 = (uintptr_t)hClipboardData;
|
||||
};
|
||||
return NewHook(hp,"nwjs/electron");
|
||||
return NewHook(hp, "nwjs/electron rpgmakermv/tyranoscript");
|
||||
}
|
||||
}
|
||||
namespace v8script{
|
||||
namespace v8script
|
||||
{
|
||||
HMODULE hmodule;
|
||||
|
||||
typedef void (*RequestInterrupt_callback)(void *, void *);
|
||||
@ -74,9 +83,63 @@ NewFromUtf8t NewFromUtf8=0,NewFromUtf8v2,NewFromUtf8v1;
|
||||
GetCurrentContextt GetCurrentContext;
|
||||
Compilet Compile;
|
||||
void *Run;
|
||||
bool v8runscript_isolate(void* isolate){
|
||||
void _interrupt_function(void *isolate, void *)
|
||||
{
|
||||
void *context;
|
||||
void *v8string;
|
||||
void *script;
|
||||
void *useless;
|
||||
ConsoleOutput("isolate %p", isolate);
|
||||
GetCurrentContext(isolate, &context);
|
||||
ConsoleOutput("context %p", context);
|
||||
if (context == 0)
|
||||
return;
|
||||
int is_packed = 0;
|
||||
if (auto moduleFileName = getModuleFilename())
|
||||
{
|
||||
|
||||
if(isolate==0)return false;
|
||||
AutoHandle hFile = CreateFile(moduleFileName.value().c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile)
|
||||
{
|
||||
LARGE_INTEGER fileSize;
|
||||
if (GetFileSizeEx(hFile, &fileSize))
|
||||
{
|
||||
if (fileSize.QuadPart > 1024 * 1024 * 200)
|
||||
{
|
||||
// 200mb
|
||||
is_packed = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NewFromUtf8(&v8string, isolate, FormatString(LoadResData(L"lunajspatch", L"JSSOURCE").c_str(), is_packed).c_str(), 1, -1);
|
||||
ConsoleOutput("v8string %p", v8string);
|
||||
if (v8string == 0)
|
||||
return;
|
||||
if (NewFromUtf8v1)
|
||||
{
|
||||
Compile(&script, v8string, 0, 0);
|
||||
ConsoleOutput("script %p", script);
|
||||
if (script == 0)
|
||||
return;
|
||||
((Runt1)Run)(script, &useless);
|
||||
ConsoleOutput("useless %p", useless);
|
||||
}
|
||||
else if (NewFromUtf8v2)
|
||||
{
|
||||
Compile(&script, context, v8string, 0);
|
||||
ConsoleOutput("script %p", script);
|
||||
if (script == 0)
|
||||
return;
|
||||
((Runt2)Run)(script, &useless, context);
|
||||
ConsoleOutput("useless %p", useless);
|
||||
}
|
||||
}
|
||||
bool v8runscript_isolate(void *isolate)
|
||||
{
|
||||
|
||||
if (isolate == 0)
|
||||
return false;
|
||||
RequestInterrupt = (decltype(RequestInterrupt))GetProcAddress(hmodule, fnRequestInterrupt);
|
||||
|
||||
NewFromUtf8v2 = (decltype(NewFromUtf8))GetProcAddress(hmodule, fnNewFromUtf8v2);
|
||||
@ -88,7 +151,8 @@ bool v8runscript_isolate(void* isolate){
|
||||
{
|
||||
NewFromUtf8 = NewFromUtf8v1;
|
||||
Compile = (decltype(Compile))GetProcAddress(hmodule, fnCompilev1);
|
||||
if(!Compile) Compile=(decltype(Compile))GetProcAddress(hmodule, fnCompilev12);
|
||||
if (!Compile)
|
||||
Compile = (decltype(Compile))GetProcAddress(hmodule, fnCompilev12);
|
||||
Run = (decltype(Run))GetProcAddress(hmodule, fnRunv1);
|
||||
}
|
||||
else if (NewFromUtf8v2)
|
||||
@ -99,65 +163,27 @@ bool v8runscript_isolate(void* isolate){
|
||||
}
|
||||
ConsoleOutput("%p %p", NewFromUtf8v1, NewFromUtf8v2);
|
||||
ConsoleOutput("%p %p %p %p", GetCurrentContext, NewFromUtf8, Compile, Run);
|
||||
if(!(GetCurrentContext && NewFromUtf8 && Compile && Run && RequestInterrupt))return false;
|
||||
if (!(GetCurrentContext && NewFromUtf8 && Compile && Run && RequestInterrupt))
|
||||
return false;
|
||||
|
||||
if(RequestInterrupt==0)return false;
|
||||
RequestInterrupt(isolate,+[](void*isolate,void*){
|
||||
void* context;
|
||||
void* v8string;
|
||||
void* script;
|
||||
void* useless;
|
||||
ConsoleOutput("isolate %p",isolate);
|
||||
GetCurrentContext(isolate,&context);
|
||||
ConsoleOutput("context %p",context);
|
||||
if(context==0)return;
|
||||
int is_packed=0;
|
||||
if(auto moduleFileName=getModuleFilename()){
|
||||
|
||||
AutoHandle hFile = CreateFile(moduleFileName.value().c_str(), FILE_READ_ATTRIBUTES , FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(hFile){
|
||||
LARGE_INTEGER fileSize;
|
||||
if (GetFileSizeEx(hFile, &fileSize)) {
|
||||
if(fileSize.QuadPart>1024*1024*200){
|
||||
//200mb
|
||||
is_packed=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NewFromUtf8(&v8string,isolate,FormatString(LoadResData(L"lunajspatch",L"JSSOURCE").c_str(),is_packed).c_str(),1,-1);
|
||||
ConsoleOutput("v8string %p",v8string);
|
||||
if(v8string==0)return;
|
||||
if(NewFromUtf8v1)
|
||||
{
|
||||
Compile(&script,v8string,0,0);
|
||||
ConsoleOutput("script %p",script);
|
||||
if(script==0)return;
|
||||
((Runt1)Run)(script,&useless);
|
||||
ConsoleOutput("useless %p",useless);
|
||||
}
|
||||
else if(NewFromUtf8v2)
|
||||
{
|
||||
Compile(&script,context,v8string,0);
|
||||
ConsoleOutput("script %p",script);
|
||||
if(script==0)return ;
|
||||
((Runt2)Run)(script,&useless,context);
|
||||
ConsoleOutput("useless %p",useless);
|
||||
}
|
||||
|
||||
},0);
|
||||
if (RequestInterrupt == 0)
|
||||
return false;
|
||||
RequestInterrupt(isolate, _interrupt_function, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void v8runscript_isolate_bypass(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
void v8runscript_isolate_bypass(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
|
||||
hp->type=HOOK_EMPTY;hp->text_fun=nullptr;
|
||||
hp->type = HOOK_EMPTY;
|
||||
hp->text_fun = nullptr;
|
||||
|
||||
auto isolate = (void *)stack->ARG2; // 测试正确,且和v8::Isolate::GetCurrent结果相同
|
||||
v8runscript_isolate(isolate);
|
||||
}
|
||||
void* v8getcurrisolate(HMODULE hmod){
|
||||
void *v8getcurrisolate(HMODULE hmod)
|
||||
{
|
||||
#ifndef _WIN64
|
||||
#define fnGetCurrent "?GetCurrent@Isolate@v8@@SAPAV12@XZ"
|
||||
#define fnTryGetCurrent "?TryGetCurrent@Isolate@v8@@SAPAV12@XZ"
|
||||
@ -169,11 +195,13 @@ void* v8getcurrisolate(HMODULE hmod){
|
||||
GetCurrent = GetProcAddress(hmod, fnGetCurrent);
|
||||
if (!GetCurrent)
|
||||
GetCurrent = GetProcAddress(hmod, fnTryGetCurrent);
|
||||
if(!GetCurrent)return 0;
|
||||
if (!GetCurrent)
|
||||
return 0;
|
||||
auto isolate = ((void *(*)())GetCurrent)();
|
||||
return isolate;
|
||||
}
|
||||
bool v8runscript(HMODULE _hmodule){
|
||||
bool v8runscript(HMODULE _hmodule)
|
||||
{
|
||||
auto isolate = v8getcurrisolate(_hmodule);
|
||||
if (isolate)
|
||||
return v8runscript_isolate(isolate);
|
||||
@ -183,9 +211,11 @@ bool v8runscript(HMODULE _hmodule){
|
||||
#define fnisolategetters {"?New@Integer@v8@@SA?AV?$Local@VInteger@v8@@@2@PEAVIsolate@2@H@Z", "?New@Number@v8@@SA?AV?$Local@VNumber@v8@@@2@PEAVIsolate@2@N@Z", "?New@Number@v8@@SA?AV?$Local@VNumber@v8@@@2@PAVIsolate@2@N@Z", "?NewFromUtf8@String@v8@@SA?AV?$Local@VString@v8@@@2@PEAVIsolate@2@PEBDW4NewStringType@12@H@Z", "?Utf8Length@String@v8@@QEBAHPEAVIsolate@2@@Z"}
|
||||
#endif
|
||||
bool succ = false;
|
||||
for(auto fnisolategetter:fnisolategetters){
|
||||
for (auto fnisolategetter : fnisolategetters)
|
||||
{
|
||||
auto isolategetter = GetProcAddress(_hmodule, fnisolategetter);
|
||||
if(!isolategetter)continue;
|
||||
if (!isolategetter)
|
||||
continue;
|
||||
hmodule = _hmodule;
|
||||
HookParam hp;
|
||||
hp.address = (uintptr_t)isolategetter;
|
||||
@ -195,7 +225,8 @@ bool v8runscript(HMODULE _hmodule){
|
||||
return succ;
|
||||
}
|
||||
}
|
||||
namespace{
|
||||
namespace
|
||||
{
|
||||
#ifndef _WIN64
|
||||
#define v8StringLength "?Length@String@v8@@QBEHXZ"
|
||||
#define v8StringWriteUtf8 "?WriteUtf8@String@v8@@QBEHPADHPAHH@Z"
|
||||
@ -211,66 +242,76 @@ namespace{
|
||||
#endif
|
||||
uintptr_t WriteUtf8;
|
||||
uintptr_t Utf8Length;
|
||||
bool hookstring(HMODULE hm){
|
||||
bool hookstring(HMODULE hm)
|
||||
{
|
||||
WriteUtf8 = (uintptr_t)GetProcAddress(hm, v8StringWriteUtf8);
|
||||
Utf8Length = (uintptr_t)GetProcAddress(hm, v8StringUtf8Length);
|
||||
if(WriteUtf8==0||Utf8Length==0)return false;
|
||||
|
||||
if (WriteUtf8 == 0 || Utf8Length == 0)
|
||||
return false;
|
||||
|
||||
HookParam hp;
|
||||
hp.type = USING_STRING | CODEC_UTF8;
|
||||
hp.text_fun =
|
||||
[](hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||
{
|
||||
|
||||
auto length = ((size_t(THISCALL *)(void *))Utf8Length)((void *)stack->THISCALLTHIS);
|
||||
if(!length)return;
|
||||
if (!length)
|
||||
return;
|
||||
auto u8str = new char[length + 1];
|
||||
int writen;
|
||||
((size_t(THISCALL *)(void *, char *, int, int *, int))WriteUtf8)((void *)stack->THISCALLTHIS, u8str, length, &writen, 0);
|
||||
*data = (uintptr_t)u8str;
|
||||
*len = length;
|
||||
|
||||
};
|
||||
hp.filter_fun=[](void* data, size_t* len, HookParam* hp){
|
||||
if(strstr((char*)data,R"(\\?\)")!=0)return false;//过滤路径
|
||||
hp.filter_fun = [](void *data, size_t *len, HookParam *hp)
|
||||
{
|
||||
if (strstr((char *)data, R"(\\?\)") != 0)
|
||||
return false; // 过滤路径
|
||||
return true;
|
||||
};
|
||||
bool succ = false;
|
||||
|
||||
auto pv8StringLength = GetProcAddress(hm, v8StringLength);
|
||||
if(pv8StringLength){
|
||||
if (pv8StringLength)
|
||||
{
|
||||
|
||||
hp.address = (uintptr_t)pv8StringLength;
|
||||
succ |= NewHook(hp, "v8::String::Length");
|
||||
}
|
||||
auto pv8StringWrite = GetProcAddress(hm, v8StringWrite);
|
||||
if(pv8StringWrite){
|
||||
if (pv8StringWrite)
|
||||
{
|
||||
|
||||
hp.address = (uintptr_t)pv8StringWrite;
|
||||
succ |= NewHook(hp, "v8::String::Write");
|
||||
}
|
||||
auto pv8StringWriteIsolate = GetProcAddress(hm, v8StringWriteIsolate);
|
||||
if(pv8StringWriteIsolate){
|
||||
if (pv8StringWriteIsolate)
|
||||
{
|
||||
hp.address = (uintptr_t)pv8StringWriteIsolate;
|
||||
succ |= NewHook(hp, "v8::String::Write::isolate");
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
}
|
||||
bool tryhookv8_internal(HMODULE hm){
|
||||
bool tryhookv8_internal(HMODULE hm)
|
||||
{
|
||||
auto succ = hookstring(hm);
|
||||
if (!std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.clipboard")))
|
||||
if (v8script::v8runscript(hm))
|
||||
succ |= hookClipboard();
|
||||
return succ;
|
||||
}
|
||||
bool tryhookv8() {
|
||||
for (const wchar_t* moduleName : { (const wchar_t*)NULL, L"node.dll", L"nw.dll" }) {
|
||||
bool tryhookv8()
|
||||
{
|
||||
for (const wchar_t *moduleName : {(const wchar_t *)NULL, L"node.dll", L"nw.dll"})
|
||||
{
|
||||
auto hm = GetModuleHandleW(moduleName);
|
||||
if(hm==0)continue;
|
||||
if (hm == 0)
|
||||
continue;
|
||||
bool ok = tryhookv8_internal(hm);
|
||||
if(ok) return true;
|
||||
if (ok)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ function splitfonttext(transwithfont) {
|
||||
return transwithfont;
|
||||
}
|
||||
}
|
||||
function clipboardsender(s, lpsplit) {
|
||||
function clipboardsender(name, s, lpsplit) {
|
||||
//magic split \x02 text
|
||||
s = magicsend + lpsplit.toString() + '\x02' + s;
|
||||
s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s;
|
||||
try {
|
||||
const _clipboard = require('nw.gui').Clipboard.get();
|
||||
_clipboard.set(s, 'text');
|
||||
@ -42,9 +42,9 @@ function clipboardsender(s, lpsplit) {
|
||||
return splitfonttext(transwithfont)
|
||||
}
|
||||
|
||||
function clipboardsender_only_send(s, lpsplit) {
|
||||
function clipboardsender_only_send(name, s, lpsplit) {
|
||||
//magic split \x02 text
|
||||
s = magicsend + lpsplit.toString() + '\x02' + s;
|
||||
s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s;
|
||||
try {
|
||||
const _clipboard = require('nw.gui').Clipboard.get();
|
||||
_clipboard.set(s, 'text');
|
||||
@ -82,24 +82,24 @@ function rpgmakerhook() {
|
||||
if (text && (y < 100)) {
|
||||
extra = 5 + ((text.length == 1) ? 0 : 1);
|
||||
if (y != Bitmap.prototype.last_y)
|
||||
clipboardsender_only_send('\n', extra)
|
||||
clipboardsender_only_send(text, extra)
|
||||
clipboardsender_only_send('rpgmakermv', '\n', extra)
|
||||
clipboardsender_only_send('rpgmakermv', text, extra)
|
||||
Bitmap.prototype.last_y = y;
|
||||
}
|
||||
return this.drawText_ori(text, x, y, maxWidth, lineHeight, align);
|
||||
}
|
||||
Window_Message.prototype.startMessage = function () {
|
||||
gametext = $gameMessage.allText();
|
||||
resp = clipboardsender(gametext, 0);
|
||||
resp = clipboardsender('rpgmakermv', gametext, 0);
|
||||
$gameMessage._texts = [resp]
|
||||
this.originstartMessage();
|
||||
};
|
||||
Window_Base.prototype.drawText = function (text, x, y, maxWidth, align) {
|
||||
text = clipboardsender(text, 1)
|
||||
text = clipboardsender('rpgmakermv', text, 1)
|
||||
return this.drawText_origin(text, x, y, maxWidth, align)
|
||||
}
|
||||
Window_Base.prototype.drawTextEx = function (text, x, y) {
|
||||
text = clipboardsender(text, 2)
|
||||
text = clipboardsender('rpgmakermv', text, 2)
|
||||
return this.drawTextEx_origin(text, x, y)
|
||||
}
|
||||
}
|
||||
@ -111,7 +111,7 @@ function tyranohook() {
|
||||
tyrano.plugin.kag.tag.chara_ptext.startorigin = tyrano.plugin.kag.tag.chara_ptext.start;
|
||||
tyrano.plugin.kag.tag.text.start = function (pm) {
|
||||
if (1 != this.kag.stat.is_script && 1 != this.kag.stat.is_html) {
|
||||
pm.val = clipboardsender(pm.val, 0);
|
||||
pm.val = clipboardsender('tyranoscript', pm.val, 0);
|
||||
if (fontface != '') {
|
||||
this.kag.stat.font.face = fontface
|
||||
}
|
||||
@ -119,7 +119,7 @@ function tyranohook() {
|
||||
return this.originstart(pm)
|
||||
}
|
||||
tyrano.plugin.kag.tag.chara_ptext.start = function (pm) {
|
||||
pm.name = clipboardsender(pm.name, 1)
|
||||
pm.name = clipboardsender('tyranoscript', pm.name, 1)
|
||||
return this.startorigin(pm)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user