mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-10-22 23:18:16 +08:00
v8
This commit is contained in:
parent
14d846f71e
commit
a3922d7ffb
@ -51,4 +51,4 @@ target_precompile_headers(LunaHook REUSE_FROM pchhook)
|
|||||||
|
|
||||||
set_target_properties(LunaHook PROPERTIES OUTPUT_NAME "LunaHook${bitappendix}")
|
set_target_properties(LunaHook PROPERTIES OUTPUT_NAME "LunaHook${bitappendix}")
|
||||||
|
|
||||||
target_link_libraries(LunaHook Version Shlwapi pch minhook commonengine utils ${YY_Thunks_for_WinXP} ${Detours})
|
target_link_libraries(LunaHook Version httpapi Shlwapi pch minhook commonengine utils ${YY_Thunks_for_WinXP} ${Detours})
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
add_library(commonengine mono/impl_mono.cpp mono/monoil2cpp.cpp mono/impl_il2cpp.cpp ppsspp/ppsspp.cpp mages/mages.cpp v8/v8.cpp python/python2.cpp python/python3.cpp python/python.cpp pchooks/pchooks.cpp lua/lua51.cpp)
|
add_library(commonengine mono/impl_mono.cpp mono/monoil2cpp.cpp mono/impl_il2cpp.cpp ppsspp/ppsspp.cpp mages/mages.cpp v8/v8.cpp v8/httpserver.cpp python/python2.cpp python/python3.cpp python/python.cpp pchooks/pchooks.cpp lua/lua51.cpp)
|
||||||
target_precompile_headers(commonengine REUSE_FROM pchhook)
|
target_precompile_headers(commonengine REUSE_FROM pchhook)
|
||||||
|
|
||||||
|
561
LunaHook/engines/v8/httpserver.cpp
Normal file
561
LunaHook/engines/v8/httpserver.cpp
Normal file
@ -0,0 +1,561 @@
|
|||||||
|
// https://github.com/microsoft/Windows-classic-samples/blob/main/Samples/Win7Samples/netds/http/HttpV2Server/main.c
|
||||||
|
/*++
|
||||||
|
Copyright (c) 2002 - 2002 Microsoft Corporation. All Rights Reserved.
|
||||||
|
|
||||||
|
THIS CODE AND INFORMATION IS PROVIDED "AS-IS" WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE.
|
||||||
|
|
||||||
|
THIS CODE IS NOT SUPPORTED BY MICROSOFT.
|
||||||
|
|
||||||
|
--*/
|
||||||
|
|
||||||
|
#define SECURITY_WIN32
|
||||||
|
#include <http.h>
|
||||||
|
#include <sspi.h>
|
||||||
|
#include <strsafe.h>
|
||||||
|
#define NUM_SCHEMES 2
|
||||||
|
#define MAX_USERNAME_LENGTH 100
|
||||||
|
#pragma warning(disable : 4127) // condition expression is constant
|
||||||
|
|
||||||
|
//
|
||||||
|
// Macros.
|
||||||
|
//
|
||||||
|
#define INITIALIZE_HTTP_RESPONSE(resp, status, reason) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
RtlZeroMemory((resp), sizeof(*(resp))); \
|
||||||
|
(resp)->StatusCode = (status); \
|
||||||
|
(resp)->pReason = (reason); \
|
||||||
|
(resp)->ReasonLength = (USHORT)strlen(reason); \
|
||||||
|
} while (FALSE)
|
||||||
|
|
||||||
|
#define ADD_KNOWN_HEADER(Response, HeaderId, RawValue) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
(Response).Headers.KnownHeaders[(HeaderId)].pRawValue = (RawValue); \
|
||||||
|
(Response).Headers.KnownHeaders[(HeaderId)].RawValueLength = \
|
||||||
|
(USHORT)strlen(RawValue); \
|
||||||
|
} while (FALSE)
|
||||||
|
|
||||||
|
#define ALLOC_MEM(cb) HeapAlloc(GetProcessHeap(), 0, (cb))
|
||||||
|
#define FREE_MEM(ptr) HeapFree(GetProcessHeap(), 0, (ptr))
|
||||||
|
|
||||||
|
//
|
||||||
|
// Prototypes.
|
||||||
|
//
|
||||||
|
DWORD
|
||||||
|
DoReceiveRequests(
|
||||||
|
HANDLE hReqQueue);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
SendHttpResponse(
|
||||||
|
IN HANDLE hReqQueue,
|
||||||
|
IN PHTTP_REQUEST pRequest);
|
||||||
|
|
||||||
|
/***************************************************************************++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
main routine.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
argc - # of command line arguments.
|
||||||
|
argv - Arguments.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
Success/Failure.
|
||||||
|
|
||||||
|
--***************************************************************************/
|
||||||
|
|
||||||
|
int cleanuphttp(HANDLE hReqQueue, HTTP_SERVER_SESSION_ID ssID, HTTP_URL_GROUP_ID urlGroupId)
|
||||||
|
{
|
||||||
|
ULONG retCode;
|
||||||
|
//
|
||||||
|
// Call HttpRemoveUrl for all the URLs that we added.
|
||||||
|
// HTTP_URL_FLAG_REMOVE_ALL flag allows us to remove
|
||||||
|
// all the URLs registered on URL Group at once
|
||||||
|
//
|
||||||
|
if (!HTTP_IS_NULL_ID(&urlGroupId))
|
||||||
|
{
|
||||||
|
|
||||||
|
retCode = HttpRemoveUrlFromUrlGroup(urlGroupId,
|
||||||
|
NULL,
|
||||||
|
HTTP_URL_FLAG_REMOVE_ALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Close the Url Group
|
||||||
|
//
|
||||||
|
|
||||||
|
if (!HTTP_IS_NULL_ID(&urlGroupId))
|
||||||
|
{
|
||||||
|
retCode = HttpCloseUrlGroup(urlGroupId);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Close the serversession
|
||||||
|
//
|
||||||
|
|
||||||
|
if (!HTTP_IS_NULL_ID(&urlGroupId))
|
||||||
|
{
|
||||||
|
retCode = HttpCloseServerSession(ssID);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Close the Request Queue handle.
|
||||||
|
//
|
||||||
|
|
||||||
|
if (hReqQueue)
|
||||||
|
{
|
||||||
|
retCode = HttpCloseRequestQueue(hReqQueue);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Call HttpTerminate.
|
||||||
|
//
|
||||||
|
HttpTerminate(HTTP_INITIALIZE_SERVER, NULL);
|
||||||
|
return retCode;
|
||||||
|
}
|
||||||
|
auto makeserveronce(int port)
|
||||||
|
{
|
||||||
|
ULONG retCode;
|
||||||
|
|
||||||
|
HANDLE hReqQueue = NULL;
|
||||||
|
HTTP_SERVER_SESSION_ID ssID = HTTP_NULL_ID;
|
||||||
|
HTTP_URL_GROUP_ID urlGroupId = HTTP_NULL_ID;
|
||||||
|
HTTPAPI_VERSION HttpApiVersion = HTTPAPI_VERSION_2;
|
||||||
|
HTTP_BINDING_INFO BindingProperty;
|
||||||
|
HTTP_TIMEOUT_LIMIT_INFO CGTimeout;
|
||||||
|
|
||||||
|
auto url = std::wstring(L"http://127.0.0.1:") + std::to_wstring(port) + L"/fuck";
|
||||||
|
//
|
||||||
|
// Initialize HTTP APIs.
|
||||||
|
//
|
||||||
|
|
||||||
|
retCode = HttpInitialize(
|
||||||
|
HttpApiVersion,
|
||||||
|
HTTP_INITIALIZE_SERVER, // Flags
|
||||||
|
NULL // Reserved
|
||||||
|
);
|
||||||
|
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a server session handle
|
||||||
|
//
|
||||||
|
|
||||||
|
retCode = HttpCreateServerSession(HttpApiVersion,
|
||||||
|
&ssID,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create UrlGroup handle
|
||||||
|
//
|
||||||
|
|
||||||
|
retCode = HttpCreateUrlGroup(ssID,
|
||||||
|
&urlGroupId,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Create a request queue handle
|
||||||
|
//
|
||||||
|
|
||||||
|
retCode = HttpCreateRequestQueue(HttpApiVersion,
|
||||||
|
(std::wstring(L"LUNA_INTERNAL_HTTP_QUEUE") + std::to_wstring(GetCurrentProcessId()) + L"_" + std::to_wstring(rand())).c_str(),
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
&hReqQueue);
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
BindingProperty.Flags.Present = 1; // Specifies that the property is present on UrlGroup
|
||||||
|
BindingProperty.RequestQueueHandle = hReqQueue;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Bind the request queue to UrlGroup
|
||||||
|
//
|
||||||
|
|
||||||
|
retCode = HttpSetUrlGroupProperty(urlGroupId,
|
||||||
|
HttpServerBindingProperty,
|
||||||
|
&BindingProperty,
|
||||||
|
sizeof(BindingProperty));
|
||||||
|
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Set EntityBody Timeout property on UrlGroup
|
||||||
|
//
|
||||||
|
|
||||||
|
ZeroMemory(&CGTimeout, sizeof(HTTP_TIMEOUT_LIMIT_INFO));
|
||||||
|
|
||||||
|
CGTimeout.Flags.Present = 1; // Specifies that the property is present on UrlGroup
|
||||||
|
CGTimeout.EntityBody = 50; // The timeout is in secs
|
||||||
|
|
||||||
|
retCode = HttpSetUrlGroupProperty(urlGroupId,
|
||||||
|
HttpServerTimeoutsProperty,
|
||||||
|
&CGTimeout,
|
||||||
|
sizeof(HTTP_TIMEOUT_LIMIT_INFO));
|
||||||
|
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add the URLs on URL Group
|
||||||
|
// The command line arguments represent URIs that we want to listen on.
|
||||||
|
// We will call HttpAddUrlToUrlGroup for each of these URIs.
|
||||||
|
//
|
||||||
|
// The URI is a fully qualified URI and MUST include the terminating '/'
|
||||||
|
//
|
||||||
|
|
||||||
|
retCode = HttpAddUrlToUrlGroup(urlGroupId,
|
||||||
|
url.c_str(),
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
if (retCode != NO_ERROR)
|
||||||
|
{
|
||||||
|
return std::tuple{false, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
return std::tuple{true, hReqQueue, ssID, urlGroupId};
|
||||||
|
}
|
||||||
|
int GetRandomAvailablePort()
|
||||||
|
{
|
||||||
|
static int xx = 9000 + GetCurrentProcessId() % 20000;
|
||||||
|
return xx++;
|
||||||
|
|
||||||
|
// WSADATA wsaData;
|
||||||
|
// int result = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||||
|
// if (result != 0)
|
||||||
|
// {
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 创建一个 TCP 套接字
|
||||||
|
// SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
// if (sock == INVALID_SOCKET)
|
||||||
|
// {
|
||||||
|
// WSACleanup();
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 绑定到随机端口
|
||||||
|
// sockaddr_in addr;
|
||||||
|
// addr.sin_family = AF_INET;
|
||||||
|
// addr.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
// addr.sin_port = 0; // 0 表示让系统自动选择一个可用端口
|
||||||
|
|
||||||
|
// result = bind(sock, (SOCKADDR *)&addr, sizeof(addr));
|
||||||
|
// if (result == SOCKET_ERROR)
|
||||||
|
// {
|
||||||
|
// closesocket(sock);
|
||||||
|
// WSACleanup();
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 获取实际绑定的端口号
|
||||||
|
// int addrLen = sizeof(addr);
|
||||||
|
// result = getsockname(sock, (SOCKADDR *)&addr, &addrLen);
|
||||||
|
// if (result == SOCKET_ERROR)
|
||||||
|
// {
|
||||||
|
// closesocket(sock);
|
||||||
|
// WSACleanup();
|
||||||
|
// return 0;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // 关闭套接字
|
||||||
|
// closesocket(sock);
|
||||||
|
// WSACleanup();
|
||||||
|
|
||||||
|
// // 返回实际绑定的端口号
|
||||||
|
// return ntohs(addr.sin_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
int makehttpgetserverinternal()
|
||||||
|
{
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
auto port = GetRandomAvailablePort();
|
||||||
|
auto [succ, hReqQueue, ssID, urlGroupId] = makeserveronce(port);
|
||||||
|
if (!succ)
|
||||||
|
{
|
||||||
|
cleanuphttp(hReqQueue, ssID, urlGroupId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::thread([=]()
|
||||||
|
{
|
||||||
|
// Loop while receiving requests
|
||||||
|
DoReceiveRequests(hReqQueue);
|
||||||
|
cleanuphttp(hReqQueue, ssID, urlGroupId); })
|
||||||
|
.detach();
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// int main()
|
||||||
|
// {
|
||||||
|
// wprintf(L"%d", makehttpgetserverinternal());
|
||||||
|
// Sleep(999999);
|
||||||
|
// }
|
||||||
|
/***************************************************************************++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
The routine to receive a request. This routine calls the corresponding
|
||||||
|
routine to deal with the response.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
hReqQueue - Handle to the request queue.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
Success/Failure.
|
||||||
|
|
||||||
|
--***************************************************************************/
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
DoReceiveRequests(
|
||||||
|
IN HANDLE hReqQueue)
|
||||||
|
{
|
||||||
|
ULONG result;
|
||||||
|
HTTP_REQUEST_ID requestId;
|
||||||
|
DWORD bytesRead;
|
||||||
|
PHTTP_REQUEST pRequest;
|
||||||
|
PCHAR pRequestBuffer;
|
||||||
|
ULONG RequestBufferLength;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Allocate a 2K buffer. Should be good for most requests, we'll grow
|
||||||
|
// this if required. We also need space for a HTTP_REQUEST structure.
|
||||||
|
//
|
||||||
|
RequestBufferLength = sizeof(HTTP_REQUEST) + 2048;
|
||||||
|
pRequestBuffer = (PCHAR)ALLOC_MEM(RequestBufferLength);
|
||||||
|
|
||||||
|
if (pRequestBuffer == NULL)
|
||||||
|
{
|
||||||
|
return ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pRequest = (PHTTP_REQUEST)pRequestBuffer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Wait for a new request -- This is indicated by a NULL request ID.
|
||||||
|
//
|
||||||
|
|
||||||
|
HTTP_SET_NULL_ID(&requestId);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
RtlZeroMemory(pRequest, RequestBufferLength);
|
||||||
|
|
||||||
|
result = HttpReceiveHttpRequest(
|
||||||
|
hReqQueue, // Req Queue
|
||||||
|
requestId, // Req ID
|
||||||
|
0, // Flags
|
||||||
|
pRequest, // HTTP request buffer
|
||||||
|
RequestBufferLength, // req buffer length
|
||||||
|
&bytesRead, // bytes received
|
||||||
|
NULL // LPOVERLAPPED
|
||||||
|
);
|
||||||
|
|
||||||
|
if (NO_ERROR == result)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Worked!
|
||||||
|
//
|
||||||
|
// switch (pRequest->Verb)
|
||||||
|
// {
|
||||||
|
// case HttpVerbGET:
|
||||||
|
result = SendHttpResponse(
|
||||||
|
hReqQueue,
|
||||||
|
pRequest);
|
||||||
|
|
||||||
|
// case HttpVerbPOST:
|
||||||
|
// default:
|
||||||
|
|
||||||
|
// if (result != NO_ERROR)
|
||||||
|
// {
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
|
||||||
|
//
|
||||||
|
// Reset the Request ID so that we pick up the next request.
|
||||||
|
//
|
||||||
|
HTTP_SET_NULL_ID(&requestId);
|
||||||
|
}
|
||||||
|
else if (result == ERROR_MORE_DATA)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// The input buffer was too small to hold the request headers
|
||||||
|
// We have to allocate more buffer & call the API again.
|
||||||
|
//
|
||||||
|
// When we call the API again, we want to pick up the request
|
||||||
|
// that just failed. This is done by passing a RequestID.
|
||||||
|
//
|
||||||
|
// This RequestID is picked from the old buffer.
|
||||||
|
//
|
||||||
|
requestId = pRequest->RequestId;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Free the old buffer and allocate a new one.
|
||||||
|
//
|
||||||
|
RequestBufferLength = bytesRead;
|
||||||
|
FREE_MEM(pRequestBuffer);
|
||||||
|
pRequestBuffer = (PCHAR)ALLOC_MEM(RequestBufferLength);
|
||||||
|
|
||||||
|
if (pRequestBuffer == NULL)
|
||||||
|
{
|
||||||
|
result = ERROR_NOT_ENOUGH_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pRequest = (PHTTP_REQUEST)pRequestBuffer;
|
||||||
|
}
|
||||||
|
else if (ERROR_CONNECTION_INVALID == result &&
|
||||||
|
!HTTP_IS_NULL_ID(&requestId))
|
||||||
|
{
|
||||||
|
// The TCP connection got torn down by the peer when we were
|
||||||
|
// trying to pick up a request with more buffer. We'll just move
|
||||||
|
// onto the next request.
|
||||||
|
|
||||||
|
HTTP_SET_NULL_ID(&requestId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // for(;;)
|
||||||
|
|
||||||
|
if (pRequestBuffer)
|
||||||
|
{
|
||||||
|
FREE_MEM(pRequestBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************************************************************++
|
||||||
|
|
||||||
|
Routine Description:
|
||||||
|
The routine sends a HTTP response.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
hReqQueue - Handle to the request queue.
|
||||||
|
pRequest - The parsed HTTP request.
|
||||||
|
StatusCode - Response Status Code.
|
||||||
|
pReason - Response reason phrase.
|
||||||
|
pEntityString - Response entity body.
|
||||||
|
|
||||||
|
Return Value:
|
||||||
|
Success/Failure.
|
||||||
|
|
||||||
|
--***************************************************************************/
|
||||||
|
|
||||||
|
std::string urlDecode(const std::string &encoded)
|
||||||
|
{
|
||||||
|
std::string decoded;
|
||||||
|
for (size_t i = 0; i < encoded.size(); i++)
|
||||||
|
{
|
||||||
|
if (encoded[i] == '%')
|
||||||
|
{
|
||||||
|
char ch = std::stoi(encoded.substr(i + 1, 2), 0, 16);
|
||||||
|
decoded += ch;
|
||||||
|
i = i + 2;
|
||||||
|
}
|
||||||
|
else if (encoded[i] == '+')
|
||||||
|
{
|
||||||
|
decoded += ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
decoded += encoded[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma optimize("", off)
|
||||||
|
const wchar_t *LUNA_CONTENTBYPASS(const wchar_t *_)
|
||||||
|
{
|
||||||
|
return _;
|
||||||
|
}
|
||||||
|
#pragma optimize("", on)
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
SendHttpResponse(
|
||||||
|
IN HANDLE hReqQueue,
|
||||||
|
IN PHTTP_REQUEST pRequest)
|
||||||
|
{
|
||||||
|
HTTP_RESPONSE response;
|
||||||
|
HTTP_DATA_CHUNK dataChunk;
|
||||||
|
DWORD result;
|
||||||
|
DWORD bytesSent;
|
||||||
|
USHORT StatusCode = 200;
|
||||||
|
PSTR pReason = "OK";
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the HTTP response structure.
|
||||||
|
//
|
||||||
|
INITIALIZE_HTTP_RESPONSE(&response, StatusCode, pReason);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add a known header.
|
||||||
|
//
|
||||||
|
ADD_KNOWN_HEADER(response, HttpHeaderContentType, "text/html");
|
||||||
|
std::string url(pRequest->pRawUrl, pRequest->RawUrlLength);
|
||||||
|
auto fnd = url.find('?');
|
||||||
|
|
||||||
|
if (fnd != url.npos)
|
||||||
|
{
|
||||||
|
url = url.substr(fnd + 1);
|
||||||
|
url = urlDecode(url);
|
||||||
|
url = WideStringToString(LUNA_CONTENTBYPASS(StringToWideString(url).c_str()));
|
||||||
|
//
|
||||||
|
// Add an entity chunk
|
||||||
|
//
|
||||||
|
dataChunk.DataChunkType = HttpDataChunkFromMemory;
|
||||||
|
dataChunk.FromMemory.pBuffer = (PVOID)url.c_str();
|
||||||
|
dataChunk.FromMemory.BufferLength = (ULONG)url.size();
|
||||||
|
|
||||||
|
response.EntityChunkCount = 1;
|
||||||
|
response.pEntityChunks = &dataChunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Since we are sending all the entity body in one call, we don't have
|
||||||
|
// to specify the Content-Length.
|
||||||
|
//
|
||||||
|
|
||||||
|
result = HttpSendHttpResponse(
|
||||||
|
hReqQueue, // ReqQueueHandle
|
||||||
|
pRequest->RequestId, // Request ID
|
||||||
|
0, // Flags
|
||||||
|
&response, // HTTP response
|
||||||
|
NULL, // pReserved1
|
||||||
|
&bytesSent, // bytes sent (OPTIONAL)
|
||||||
|
NULL, // pReserved2 (must be NULL)
|
||||||
|
0, // Reserved3 (must be 0)
|
||||||
|
NULL, // LPOVERLAPPED (OPTIONAL)
|
||||||
|
NULL // pReserved4 (must be NULL)
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
@ -1,8 +1,41 @@
|
|||||||
#include "v8.h"
|
#include "v8.h"
|
||||||
|
|
||||||
|
int makehttpgetserverinternal();
|
||||||
|
const wchar_t *LUNA_CONTENTBYPASS(const wchar_t *_);
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
constexpr auto magicsend = L"\x01LUNAFROMJS\x01";
|
constexpr auto magicsend = L"\x01LUNAFROMJS\x01";
|
||||||
constexpr auto magicrecv = L"\x01LUNAFROMHOST\x01";
|
constexpr auto magicrecv = L"\x01LUNAFROMHOST\x01";
|
||||||
|
}
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
void parsebefore(wchar_t *text, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len)
|
||||||
|
{
|
||||||
|
if (startWith(text, magicsend))
|
||||||
|
{
|
||||||
|
text += wcslen(magicsend);
|
||||||
|
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;
|
||||||
|
*len = wcslen(text) * 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::wstring parseafter(void *data, size_t len)
|
||||||
|
{
|
||||||
|
std::wstring transwithfont = magicrecv;
|
||||||
|
transwithfont += embedsharedmem->fontFamily;
|
||||||
|
transwithfont += L'\x02';
|
||||||
|
transwithfont += std::wstring((wchar_t *)data, len / 2);
|
||||||
|
return transwithfont;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
namespace
|
||||||
|
{
|
||||||
bool hookClipboard()
|
bool hookClipboard()
|
||||||
{
|
{
|
||||||
HookParam hp;
|
HookParam hp;
|
||||||
@ -11,28 +44,12 @@ namespace
|
|||||||
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;
|
HGLOBAL hClipboardData = (HGLOBAL)stack->ARG2;
|
||||||
auto text = (wchar_t *)GlobalLock(hClipboardData);
|
parsebefore((wchar_t *)GlobalLock(hClipboardData), hp, data, split, len);
|
||||||
if (startWith(text, magicsend))
|
|
||||||
{
|
|
||||||
text += wcslen(magicsend);
|
|
||||||
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;
|
|
||||||
*len = wcslen(text) * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalUnlock(hClipboardData);
|
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;
|
std::wstring transwithfont = parseafter(data, len);
|
||||||
transwithfont += embedsharedmem->fontFamily;
|
|
||||||
transwithfont += L'\x02';
|
|
||||||
transwithfont += std::wstring((wchar_t *)data, len / 2);
|
|
||||||
HGLOBAL hClipboardData = GlobalAlloc(GMEM_MOVEABLE, transwithfont.size() * 2 + 2);
|
HGLOBAL hClipboardData = GlobalAlloc(GMEM_MOVEABLE, transwithfont.size() * 2 + 2);
|
||||||
auto pchData = (wchar_t *)GlobalLock(hClipboardData);
|
auto pchData = (wchar_t *)GlobalLock(hClipboardData);
|
||||||
wcscpy(pchData, (wchar_t *)transwithfont.c_str());
|
wcscpy(pchData, (wchar_t *)transwithfont.c_str());
|
||||||
@ -42,6 +59,27 @@ namespace
|
|||||||
return NewHook(hp, "nwjs/electron rpgmakermv/tyranoscript");
|
return NewHook(hp, "nwjs/electron rpgmakermv/tyranoscript");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool hook_LUNA_CONTENTBYPASS()
|
||||||
|
{
|
||||||
|
HookParam hp;
|
||||||
|
hp.address = (uintptr_t)LUNA_CONTENTBYPASS;
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
parsebefore((wchar_t *)stack->ARG1, hp, data, split, len);
|
||||||
|
};
|
||||||
|
hp.hook_after = [](hook_stack *s, void *data, size_t len)
|
||||||
|
{
|
||||||
|
std::wstring transwithfont = parseafter(data, len);
|
||||||
|
auto news = new wchar_t[transwithfont.size() + 1];
|
||||||
|
wcscpy(news, transwithfont.c_str());
|
||||||
|
s->ARG1 = (uintptr_t)news;
|
||||||
|
};
|
||||||
|
return NewHook(hp, "nwjs/electron rpgmakermv/tyranoscript");
|
||||||
|
}
|
||||||
|
}
|
||||||
namespace v8script
|
namespace v8script
|
||||||
{
|
{
|
||||||
HMODULE hmodule;
|
HMODULE hmodule;
|
||||||
@ -112,7 +150,26 @@ namespace v8script
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NewFromUtf8(&v8string, isolate, FormatString(LoadResData(L"lunajspatch", L"JSSOURCE").c_str(), is_packed).c_str(), 1, -1);
|
auto port = 0;
|
||||||
|
|
||||||
|
auto useclipboard = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.clipboard"));
|
||||||
|
auto usehttp = !std::filesystem::exists(std::filesystem::path(getModuleFilename().value()).replace_filename("disable.http"));
|
||||||
|
if (usehttp)
|
||||||
|
{
|
||||||
|
port = makehttpgetserverinternal();
|
||||||
|
ConsoleOutput("%d %d", GetCurrentProcessId(), port);
|
||||||
|
hook_LUNA_CONTENTBYPASS();
|
||||||
|
dont_detach = true;
|
||||||
|
}
|
||||||
|
if (useclipboard)
|
||||||
|
{
|
||||||
|
hookClipboard();
|
||||||
|
}
|
||||||
|
auto lunajspatch = LoadResData(L"lunajspatch", L"JSSOURCE");
|
||||||
|
strReplace(lunajspatch, "IS_PACKED", std::to_string(is_packed));
|
||||||
|
strReplace(lunajspatch, "IS_USECLIPBOARD", std::to_string(useclipboard));
|
||||||
|
strReplace(lunajspatch, "INTERNAL_HTTP_PORT", std::to_string(port));
|
||||||
|
NewFromUtf8(&v8string, isolate, lunajspatch.c_str(), 1, -1);
|
||||||
ConsoleOutput("v8string %p", v8string);
|
ConsoleOutput("v8string %p", v8string);
|
||||||
if (v8string == 0)
|
if (v8string == 0)
|
||||||
return;
|
return;
|
||||||
@ -168,7 +225,8 @@ namespace v8script
|
|||||||
|
|
||||||
if (RequestInterrupt == 0)
|
if (RequestInterrupt == 0)
|
||||||
return false;
|
return false;
|
||||||
RequestInterrupt(isolate, _interrupt_function, 0);
|
|
||||||
|
RequestInterrupt(isolate, _interrupt_function, nullptr);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -294,14 +352,6 @@ namespace
|
|||||||
return succ;
|
return succ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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()
|
bool tryhookv8()
|
||||||
{
|
{
|
||||||
for (const wchar_t *moduleName : {(const wchar_t *)NULL, L"node.dll", L"nw.dll"})
|
for (const wchar_t *moduleName : {(const wchar_t *)NULL, L"node.dll", L"nw.dll"})
|
||||||
@ -309,7 +359,8 @@ bool tryhookv8()
|
|||||||
auto hm = GetModuleHandleW(moduleName);
|
auto hm = GetModuleHandleW(moduleName);
|
||||||
if (hm == 0)
|
if (hm == 0)
|
||||||
continue;
|
continue;
|
||||||
bool ok = tryhookv8_internal(hm);
|
auto ok = hookstring(hm);
|
||||||
|
ok |= v8script::v8runscript(hm);
|
||||||
if (ok)
|
if (ok)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
var fontface = '';
|
var fontface = '';
|
||||||
var magicsend = '\x01LUNAFROMJS\x01'
|
var magicsend = '\x01LUNAFROMJS\x01'
|
||||||
var magicrecv = '\x01LUNAFROMHOST\x01'
|
var magicrecv = '\x01LUNAFROMHOST\x01'
|
||||||
var is_packed = %d
|
var is_packed = IS_PACKED
|
||||||
|
var is_useclipboard = IS_USECLIPBOARD
|
||||||
|
var internal_http_port = INTERNAL_HTTP_PORT
|
||||||
function splitfonttext(transwithfont) {
|
function splitfonttext(transwithfont) {
|
||||||
if (transwithfont.substr(0, magicsend.length) == magicsend) //not trans
|
if (transwithfont.substr(0, magicsend.length) == magicsend) //not trans
|
||||||
{
|
{
|
||||||
@ -20,41 +22,77 @@ function splitfonttext(transwithfont) {
|
|||||||
return transwithfont;
|
return transwithfont;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function syncquery(s) {
|
||||||
|
if (internal_http_port == 0) { throw new Error('') }
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', 'http://127.0.0.1:' + internal_http_port + '/fuck?' + s, false);
|
||||||
|
xhr.send();
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
return xhr.responseText;
|
||||||
|
} else {
|
||||||
|
throw new Error('')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
function isEmptyString(str) {
|
||||||
|
return str === null || str === undefined || str.length == 0;
|
||||||
|
}
|
||||||
function clipboardsender(name, s_raw, lpsplit) {
|
function clipboardsender(name, s_raw, lpsplit) {
|
||||||
//magic split \x02 text
|
//magic split \x02 text
|
||||||
|
if (isEmptyString(s_raw))
|
||||||
|
return s_raw
|
||||||
s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s_raw;
|
s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s_raw;
|
||||||
try {
|
try {
|
||||||
|
if (!is_useclipboard) { throw new Error('') }
|
||||||
const _clipboard = require('nw.gui').Clipboard.get();
|
const _clipboard = require('nw.gui').Clipboard.get();
|
||||||
_clipboard.set(s, 'text');
|
_clipboard.set(s, 'text');
|
||||||
transwithfont = _clipboard.get('text');
|
transwithfont = _clipboard.get('text');
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
try {
|
try {
|
||||||
|
if (!is_useclipboard) { throw new Error('') }
|
||||||
const clipboard = require('electron').clipboard;
|
const clipboard = require('electron').clipboard;
|
||||||
clipboard.writeText(s);
|
clipboard.writeText(s);
|
||||||
transwithfont = clipboard.readText();
|
transwithfont = clipboard.readText();
|
||||||
}
|
}
|
||||||
catch (err2) {
|
catch (err2) {
|
||||||
return s_raw;
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
transwithfont = syncquery(s)
|
||||||
|
}
|
||||||
|
catch (err3) {
|
||||||
|
return s_raw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (transwithfont.length == 0) return s_raw;
|
if (transwithfont.length == 0) return s_raw;
|
||||||
return splitfonttext(transwithfont)
|
return splitfonttext(transwithfont)
|
||||||
}
|
}
|
||||||
|
|
||||||
function clipboardsender_only_send(name, s, lpsplit) {
|
function clipboardsender_only_send(name, s_raw, lpsplit) {
|
||||||
//magic split \x02 text
|
//magic split \x02 text
|
||||||
s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s;
|
if (isEmptyString(s_raw))
|
||||||
|
return s_raw
|
||||||
|
s = magicsend + name + '\x03' + lpsplit.toString() + '\x02' + s_raw;
|
||||||
try {
|
try {
|
||||||
|
if (!is_useclipboard) { throw new Error('') }
|
||||||
const _clipboard = require('nw.gui').Clipboard.get();
|
const _clipboard = require('nw.gui').Clipboard.get();
|
||||||
_clipboard.set(s, 'text');
|
_clipboard.set(s, 'text');
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
try {
|
try {
|
||||||
|
if (!is_useclipboard) { throw new Error('') }
|
||||||
const clipboard = require('electron').clipboard;
|
const clipboard = require('electron').clipboard;
|
||||||
clipboard.writeText(s);
|
clipboard.writeText(s);
|
||||||
}
|
}
|
||||||
catch (err2) {
|
catch (err2) {
|
||||||
|
try {
|
||||||
|
syncquery(s)
|
||||||
|
}
|
||||||
|
catch (err3) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user