mirror of
https://github.com/Simplxss/SignerServer.git
synced 2024-11-21 00:37:53 +08:00
try to fix 9912
This commit is contained in:
parent
0328134d86
commit
2778c168c7
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@ -1,6 +1,6 @@
|
||||
# https://docs.github.com/en/actions/learn-github-actions/contexts
|
||||
|
||||
name: SignerServer
|
||||
name: build
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
@ -7,8 +7,6 @@ project(SignerServer)
|
||||
if("${CMAKE_SYSTEM_NAME}" STREQUAL "Windows")
|
||||
add_definitions(-D _WIN_PLATFORM_)
|
||||
|
||||
enable_language(ASM_MASM)
|
||||
|
||||
link_libraries(ws2_32)
|
||||
elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
|
||||
add_definitions(-D _MAC_PLATFORM_)
|
||||
@ -24,12 +22,6 @@ elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
|
||||
add_definitions(-D _ARM64_ARCH_)
|
||||
endif()
|
||||
|
||||
file(GLOB SOURCE_FILES "./src/*.cpp" "./src/*.asm")
|
||||
file(GLOB SOURCE_FILES "./src/*.cpp")
|
||||
|
||||
add_library(SignerServer SHARED ${SOURCE_FILES})
|
||||
|
||||
if(MSVC)
|
||||
target_link_options(SignerServer PRIVATE
|
||||
/DEF:${CMAKE_CURRENT_SOURCE_DIR}/version.def
|
||||
)
|
||||
endif()
|
@ -8,7 +8,7 @@
|
||||
#ifndef CPPHTTPLIB_HTTPLIB_H
|
||||
#define CPPHTTPLIB_HTTPLIB_H
|
||||
|
||||
#define CPPHTTPLIB_VERSION "0.15.3"
|
||||
#define CPPHTTPLIB_VERSION "0.16.0"
|
||||
|
||||
/*
|
||||
* Configuration
|
||||
@ -726,6 +726,10 @@ private:
|
||||
assert(true == static_cast<bool>(fn));
|
||||
fn();
|
||||
}
|
||||
|
||||
#ifdef CPPHTTPLIB_OPENSSL_SUPPORT
|
||||
OPENSSL_thread_stop ();
|
||||
#endif
|
||||
}
|
||||
|
||||
ThreadPool &pool_;
|
||||
@ -1820,6 +1824,9 @@ public:
|
||||
|
||||
SSL_CTX *ssl_context() const;
|
||||
|
||||
void update_certs (X509 *cert, EVP_PKEY *private_key,
|
||||
X509_STORE *client_ca_cert_store = nullptr);
|
||||
|
||||
private:
|
||||
bool process_and_close_socket(socket_t sock) override;
|
||||
|
||||
@ -2825,15 +2832,25 @@ inline bool mmap::open(const char *path) {
|
||||
if (!::GetFileSizeEx(hFile_, &size)) { return false; }
|
||||
size_ = static_cast<size_t>(size.QuadPart);
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
hMapping_ =
|
||||
::CreateFileMappingFromApp(hFile_, NULL, PAGE_READONLY, size_, NULL);
|
||||
#else
|
||||
hMapping_ =
|
||||
::CreateFileMappingW(hFile_, NULL, PAGE_READONLY, size.HighPart,
|
||||
size.LowPart, NULL);
|
||||
#endif
|
||||
|
||||
if (hMapping_ == NULL) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
addr_ = ::MapViewOfFileFromApp(hMapping_, FILE_MAP_READ, 0, 0);
|
||||
#else
|
||||
addr_ = ::MapViewOfFile(hMapping_, FILE_MAP_READ, 0, 0, 0);
|
||||
#endif
|
||||
#else
|
||||
fd_ = ::open(path, O_RDONLY);
|
||||
if (fd_ == -1) { return false; }
|
||||
@ -7268,7 +7285,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) {
|
||||
if (location.empty()) { return false; }
|
||||
|
||||
const static std::regex re(
|
||||
R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)");
|
||||
R"((?:(https?):)?(?://(?:\[([a-fA-F\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)");
|
||||
|
||||
std::smatch m;
|
||||
if (!std::regex_match(location, m, re)) { return false; }
|
||||
@ -8753,6 +8770,19 @@ inline bool SSLServer::is_valid() const { return ctx_; }
|
||||
|
||||
inline SSL_CTX *SSLServer::ssl_context() const { return ctx_; }
|
||||
|
||||
inline void SSLServer::update_certs (X509 *cert, EVP_PKEY *private_key,
|
||||
X509_STORE *client_ca_cert_store) {
|
||||
|
||||
std::lock_guard<std::mutex> guard(ctx_mutex_);
|
||||
|
||||
SSL_CTX_use_certificate (ctx_, cert);
|
||||
SSL_CTX_use_PrivateKey (ctx_, private_key);
|
||||
|
||||
if (client_ca_cert_store != nullptr) {
|
||||
SSL_CTX_set_cert_store (ctx_, client_ca_cert_store);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool SSLServer::process_and_close_socket(socket_t sock) {
|
||||
auto ssl = detail::ssl_new(
|
||||
sock, ctx_, ctx_mutex_,
|
||||
@ -9213,7 +9243,7 @@ inline Client::Client(const std::string &scheme_host_port,
|
||||
const std::string &client_cert_path,
|
||||
const std::string &client_key_path) {
|
||||
const static std::regex re(
|
||||
R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
|
||||
R"((?:([a-z]+):\/\/)?(?:\[([a-fA-F\d:]+)\]|([^:/?#]+))(?::(\d+))?)");
|
||||
|
||||
std::smatch m;
|
||||
if (std::regex_match(scheme_host_port, m, re)) {
|
||||
@ -9250,6 +9280,8 @@ inline Client::Client(const std::string &scheme_host_port,
|
||||
client_key_path);
|
||||
}
|
||||
} else {
|
||||
// NOTE: Update TEST(UniversalClientImplTest, Ipv6LiteralAddress)
|
||||
// if port param below changes.
|
||||
cli_ = detail::make_unique<ClientImpl>(scheme_host_port, 80,
|
||||
client_cert_path, client_key_path);
|
||||
}
|
||||
|
201
include/moehoo/hook.h
Normal file
201
include/moehoo/hook.h
Normal file
@ -0,0 +1,201 @@
|
||||
#ifndef _HOOK_H_
|
||||
#define _HOOK_H_
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
#include <Windows.h>
|
||||
#elif defined(_LINUX_PLATFORM_)
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
namespace moehoo
|
||||
{
|
||||
void *get_call_address(uint8_t *ptr);
|
||||
void *search_and_fill_jump(uint64_t baseAddress, void *targetAddress);
|
||||
bool hook(uint8_t *callAddr, void *lpFunction);
|
||||
} // namespace moehoo
|
||||
|
||||
inline void *moehoo::get_call_address(uint8_t *ptr)
|
||||
{
|
||||
// 读取操作码
|
||||
if (ptr[0] != 0xE8)
|
||||
{
|
||||
printf("Not a call instruction!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 读取相对偏移量
|
||||
int32_t relativeOffset = *reinterpret_cast<int32_t *>(ptr + 1);
|
||||
|
||||
// 计算函数地址
|
||||
uint8_t *callAddress = ptr + 5; // call 指令占 5 个字节
|
||||
void *functionAddress = callAddress + relativeOffset;
|
||||
|
||||
return reinterpret_cast<void *>(functionAddress);
|
||||
}
|
||||
|
||||
inline void *moehoo::search_and_fill_jump(uint64_t baseAddress, void *targetAddress)
|
||||
{
|
||||
uint8_t jumpInstruction[] = {
|
||||
0x49, 0xBB,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x41, 0xFF, 0xE3};
|
||||
|
||||
memcpy(jumpInstruction + 2, &targetAddress, 8);
|
||||
|
||||
// Iterate through memory regions
|
||||
uint64_t searchStart = baseAddress - 0x7fffffff;
|
||||
uint64_t searchEnd = baseAddress + 0x7fffffff;
|
||||
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
while (searchStart < searchEnd - sizeof(jumpInstruction))
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
if (VirtualQuery(reinterpret_cast<void *>(searchStart), &mbi, sizeof(mbi)) == 0)
|
||||
break;
|
||||
if (mbi.State == MEM_COMMIT)
|
||||
{
|
||||
for (char *addr = static_cast<char *>(mbi.BaseAddress); addr < static_cast<char *>(mbi.BaseAddress) + mbi.RegionSize - 1024 * 5; ++addr)
|
||||
{
|
||||
|
||||
bool isFree = true;
|
||||
for (int i = 0; i < 1024 * 5; ++i)
|
||||
{
|
||||
if (addr[i] != 0)
|
||||
{
|
||||
isFree = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isFree)
|
||||
{
|
||||
DWORD oldProtect;
|
||||
addr += 0x200;
|
||||
// printf("addr: %p\n", addr);
|
||||
|
||||
if (!VirtualProtect(addr, sizeof(jumpInstruction), PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
break;
|
||||
memcpy(addr, jumpInstruction, sizeof(jumpInstruction));
|
||||
if (!VirtualProtect(addr, sizeof(jumpInstruction), PAGE_EXECUTE_READ, &oldProtect))
|
||||
break;
|
||||
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
searchStart += mbi.RegionSize;
|
||||
}
|
||||
#elif defined(_LINUX_PLATFORM_)
|
||||
// 保证地址对齐
|
||||
searchStart &= 0xfffffffffffff000;
|
||||
searchStart += 0x1000;
|
||||
searchEnd &= 0xfffffffffffff000;
|
||||
|
||||
auto pmap = hak::get_maps();
|
||||
do
|
||||
{
|
||||
auto fpmap = pmap;
|
||||
pmap = fpmap->next();
|
||||
if (std::min(pmap->start(), searchEnd) - std::max(fpmap->end(), searchStart) > 0x2000) // 搜索一片 0x2000 大小的空区域
|
||||
{
|
||||
void *addr = mmap(reinterpret_cast<void *>(std::max(fpmap->end(), searchStart)), 0x2000, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
// printf("addr: %p\n", addr);
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
printf("mmap failed\n");
|
||||
continue;
|
||||
}
|
||||
if (reinterpret_cast<uint64_t>(addr) > searchEnd - sizeof(jumpInstruction))
|
||||
{
|
||||
munmap(addr, 0x2000);
|
||||
printf("addr > searchEnd\n");
|
||||
continue;
|
||||
}
|
||||
memcpy(addr, jumpInstruction, sizeof(jumpInstruction));
|
||||
if (mprotect(addr, 0x2000, PROT_READ | PROT_EXEC) == -1) // 设置内存 r-w
|
||||
{
|
||||
munmap(addr, 0x2000);
|
||||
printf("mprotect failed\n");
|
||||
continue;
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
} while (pmap->next() != nullptr);
|
||||
|
||||
#endif
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline bool moehoo::hook(uint8_t *callAddr, void *lpFunction)
|
||||
{
|
||||
uint64_t startAddr = reinterpret_cast<uint64_t>(callAddr) + 5;
|
||||
int64_t distance = reinterpret_cast<uint64_t>(lpFunction) - startAddr;
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
// printf("Hooking %p to %p, distance: %lld\n", callAddr, lpFunction, distance);
|
||||
|
||||
DWORD oldProtect;
|
||||
DWORD reProtect;
|
||||
if (!VirtualProtect(callAddr, 10, PAGE_EXECUTE_READWRITE, &oldProtect))
|
||||
{
|
||||
printf("VirtualProtect failed\n");
|
||||
return false;
|
||||
}
|
||||
if (distance < INT32_MIN || distance > INT32_MAX)
|
||||
{
|
||||
void *new_ret = search_and_fill_jump(startAddr, lpFunction);
|
||||
if (new_ret == nullptr)
|
||||
{
|
||||
printf("Can't find a place to jump\n");
|
||||
return false;
|
||||
}
|
||||
distance = reinterpret_cast<uint64_t>(new_ret) - startAddr;
|
||||
// printf("new_ret: %p, new_distance: %lld\n", new_ret, distance);
|
||||
}
|
||||
// 直接进行小跳转
|
||||
memcpy(callAddr + 1, reinterpret_cast<int32_t *>(&distance), 4); // 修改 call 地址
|
||||
if (!VirtualProtect(callAddr, 10, oldProtect, &reProtect)) // 恢复原来的内存保护属性
|
||||
{
|
||||
std::cout << GetLastError() << "/" << callAddr << "/" << oldProtect << "/" << reProtect;
|
||||
printf("VirtualProtect failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#elif defined(_LINUX_PLATFORM_)
|
||||
// printf("Hooking %p to %p, distance: %ld\n", callAddr, lpFunction, distance);
|
||||
|
||||
auto get_page_addr = [](void *addr) -> void *
|
||||
{
|
||||
return (void *)((uintptr_t)addr & ~(getpagesize() - 1));
|
||||
};
|
||||
|
||||
if (mprotect(get_page_addr(callAddr), 2 * getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC) == -1) // 设置内存可写 两倍 pagesize 防止处于页边界
|
||||
{
|
||||
printf("mprotect failed\n");
|
||||
return false;
|
||||
}
|
||||
if (distance < INT32_MIN || distance > INT32_MAX)
|
||||
{
|
||||
void *new_ret = search_and_fill_jump(startAddr, lpFunction);
|
||||
if (new_ret == nullptr)
|
||||
{
|
||||
printf("Can't find a place to jump\n");
|
||||
return false;
|
||||
}
|
||||
distance = reinterpret_cast<uint64_t>(new_ret) - startAddr;
|
||||
// printf("new_ret: %p, new_distance: %ld\n", new_ret, distance);
|
||||
}
|
||||
|
||||
memcpy(callAddr + 1, reinterpret_cast<int32_t *>(&distance), 4); // 修改 call 地址
|
||||
if (mprotect(get_page_addr(callAddr), 2 * getpagesize(), PROT_READ | PROT_EXEC) == -1) // 还原内存保护属性
|
||||
{
|
||||
printf("mprotect failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // _HOOK_H_
|
@ -1,49 +0,0 @@
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
|
||||
#include "exports.h"
|
||||
#include <filesystem>
|
||||
|
||||
FARPROC OriginalFuncs_version[17];
|
||||
|
||||
void Exports::Load() {
|
||||
char szSystemDirectory[MAX_PATH]{};
|
||||
GetSystemDirectoryA(szSystemDirectory, MAX_PATH);
|
||||
|
||||
std::string OriginalPath = szSystemDirectory;
|
||||
OriginalPath += "\\version.dll";
|
||||
|
||||
HMODULE version = LoadLibraryA(OriginalPath.c_str());
|
||||
// load version.dll from system32
|
||||
if (!version) {
|
||||
throw std::runtime_error("Failed to load version.dll from system32\n");
|
||||
}
|
||||
|
||||
std::vector<std::string> ExportNames_version = {
|
||||
"GetFileVersionInfoA",
|
||||
"GetFileVersionInfoByHandle",
|
||||
"GetFileVersionInfoExA",
|
||||
"GetFileVersionInfoExW",
|
||||
"GetFileVersionInfoSizeA",
|
||||
"GetFileVersionInfoSizeExA",
|
||||
"GetFileVersionInfoSizeExW",
|
||||
"GetFileVersionInfoSizeW",
|
||||
"GetFileVersionInfoW",
|
||||
"VerFindFileA",
|
||||
"VerFindFileW",
|
||||
"VerInstallFileA",
|
||||
"VerInstallFileW",
|
||||
"VerLanguageNameA",
|
||||
"VerLanguageNameW",
|
||||
"VerQueryValueA",
|
||||
"VerQueryValueW"
|
||||
};
|
||||
|
||||
// get addresses of original functions
|
||||
for (int i = 0; i < 17; i++) {
|
||||
OriginalFuncs_version[i] = GetProcAddress(version, ExportNames_version[i].c_str());
|
||||
if (!OriginalFuncs_version[i]) {
|
||||
throw std::runtime_error("Failed to get address of " + ExportNames_version[i] + "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,10 +0,0 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
extern "C" FARPROC OriginalFuncs_version[17];
|
||||
|
||||
namespace Exports {
|
||||
void Load();
|
||||
}
|
@ -1,17 +1,19 @@
|
||||
#include "run_as_node.h"
|
||||
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
|
||||
#include "exports.h"
|
||||
|
||||
bool TlsOnce = false;
|
||||
// this runs way before dllmain
|
||||
void __stdcall TlsCallback(PVOID hModule, DWORD fdwReason, PVOID pContext) {
|
||||
if (!TlsOnce) {
|
||||
// for version.dll proxy
|
||||
// load exports as early as possible
|
||||
try {
|
||||
Exports::Load();
|
||||
} catch (std::exception &e) {
|
||||
printf("Failed to load exports: %s\n", e.what());
|
||||
void __stdcall TlsCallback(PVOID hModule, DWORD fdwReason, PVOID pContext)
|
||||
{
|
||||
if (!TlsOnce)
|
||||
{
|
||||
try
|
||||
{
|
||||
RunAsNode::Init();
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
printf("Failed to Init RunAsNode: %s\n", e.what());
|
||||
}
|
||||
TlsOnce = true;
|
||||
}
|
||||
@ -22,4 +24,39 @@ void __stdcall TlsCallback(PVOID hModule, DWORD fdwReason, PVOID pContext) {
|
||||
#pragma const_seg(".CRT$XLF")
|
||||
EXTERN_C const PIMAGE_TLS_CALLBACK tls_callback_func = TlsCallback;
|
||||
|
||||
// // version.dll DLLHijack
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoA() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoByHandle() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoExA() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoExW() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoSizeA() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoSizeExA() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoSizeExW() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoSizeW() {}
|
||||
// extern "C" __declspec(dllexport) void GetFileVersionInfoW() {}
|
||||
// extern "C" __declspec(dllexport) void VerFindFileA() {}
|
||||
// extern "C" __declspec(dllexport) void VerFindFileW() {}
|
||||
// extern "C" __declspec(dllexport) void VerInstallFileA() {}
|
||||
// extern "C" __declspec(dllexport) void VerInstallFileW() {}
|
||||
// extern "C" __declspec(dllexport) void VerLanguageNameA() {}
|
||||
// extern "C" __declspec(dllexport) void VerLanguageNameW() {}
|
||||
// extern "C" __declspec(dllexport) void VerQueryValueA() {}
|
||||
// extern "C" __declspec(dllexport) void VerQueryValueW() {}
|
||||
|
||||
// dbghelp.dll DLLHijack
|
||||
extern "C" __declspec(dllexport) void StackWalk64() {}
|
||||
extern "C" __declspec(dllexport) void SymCleanup() {}
|
||||
extern "C" __declspec(dllexport) void SymFromAddr() {}
|
||||
extern "C" __declspec(dllexport) void SymFunctionTableAccess64() {}
|
||||
extern "C" __declspec(dllexport) void SymGetLineFromAddr64() {}
|
||||
extern "C" __declspec(dllexport) void SymGetModuleBase64() {}
|
||||
extern "C" __declspec(dllexport) void SymGetModuleInfo64() {}
|
||||
extern "C" __declspec(dllexport) void SymGetSymFromAddr64() {}
|
||||
extern "C" __declspec(dllexport) void SymGetSearchPathW() {}
|
||||
extern "C" __declspec(dllexport) void SymInitialize() {}
|
||||
extern "C" __declspec(dllexport) void SymSetOptions() {}
|
||||
extern "C" __declspec(dllexport) void SymGetOptions() {}
|
||||
extern "C" __declspec(dllexport) void SymSetSearchPathW() {}
|
||||
extern "C" __declspec(dllexport) void UnDecorateSymbolName() {}
|
||||
extern "C" __declspec(dllexport) void MiniDumpWriteDump() {}
|
||||
#endif
|
59
src/main.cpp
59
src/main.cpp
@ -1,3 +1,60 @@
|
||||
#include "server.h"
|
||||
|
||||
Server server(1145);
|
||||
Server *server = nullptr;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
|
||||
{
|
||||
switch (fdwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string ip = "0.0.0.0";
|
||||
int port = 8080;
|
||||
printf("Start Init server\n");
|
||||
server = new Server();
|
||||
server->Init();
|
||||
|
||||
printf("Start Init sign\n");
|
||||
std::thread([=] { // Cannot use & capture!!!!! will cause crash
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Sign::Init())
|
||||
{
|
||||
if (!server->Run(ip, port))
|
||||
printf("Server run failed\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
printf("Init failed: %s\n", e.what());
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
printf("Init failed: %s\n", e.what());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DLL_THREAD_ATTACH:
|
||||
break;
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
if (server != nullptr)
|
||||
{
|
||||
delete server;
|
||||
server = nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
64
src/run_as_node.cpp
Normal file
64
src/run_as_node.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
#include "run_as_node.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
#define CURRENT_VERSION "9.9.12-25234"
|
||||
#if defined(_X64_ARCH_) // {call winmain, check run as node function}
|
||||
std::map<std::string, std::pair<uint64_t, uint64_t>> mainAddrMap = {
|
||||
{"9.9.12-25234", {0x457A76D, 0x3A5D70}}};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int(__stdcall *oriWinMain)(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
|
||||
|
||||
void(__fastcall *checkRunAsNode)(void *a1);
|
||||
|
||||
int __stdcall fakeWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
|
||||
{
|
||||
checkRunAsNode(nullptr);
|
||||
return oriWinMain(hInstance, hPrevInstance, lpCmdLine, nShowCmd);
|
||||
}
|
||||
|
||||
bool RunAsNode::Init()
|
||||
{
|
||||
uint64_t baseAddr = 0;
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
HMODULE wrapperModule = GetModuleHandleW(NULL);
|
||||
if (wrapperModule == NULL)
|
||||
throw std::runtime_error("Can't GetModuleHandle");
|
||||
baseAddr = reinterpret_cast<uint64_t>(wrapperModule);
|
||||
printf("baseAddr: %llx\n", baseAddr);
|
||||
#elif defined(_MAC_PLATFORM_)
|
||||
auto pmap = hak::get_maps();
|
||||
do
|
||||
{
|
||||
if (pmap->module_name.find("QQ") != std::string::npos && pmap->offset == 0)
|
||||
{
|
||||
baseAddr = pmap->start();
|
||||
printf("baseAddr: %llx\n", baseAddr);
|
||||
break;
|
||||
}
|
||||
} while ((pmap = pmap->next()) != nullptr);
|
||||
#elif defined(_LINUX_PLATFORM_)
|
||||
auto pmap = hak::get_maps();
|
||||
do
|
||||
{
|
||||
if (pmap->module_name.find("QQ") != std::string::npos && pmap->offset == 0)
|
||||
{
|
||||
baseAddr = pmap->start();
|
||||
printf("baseAddr: %lx\n", baseAddr);
|
||||
break;
|
||||
}
|
||||
} while ((pmap = pmap->next()) != nullptr);
|
||||
#endif
|
||||
if (baseAddr == 0)
|
||||
throw std::runtime_error("Can't find hook address");
|
||||
|
||||
auto [callptr, funcptr] = mainAddrMap[CURRENT_VERSION];
|
||||
|
||||
uint8_t *abscallptr = reinterpret_cast<uint8_t *>(baseAddr + callptr);
|
||||
oriWinMain = reinterpret_cast<int(__stdcall *)(HINSTANCE, HINSTANCE, LPSTR, int)>(moehoo::get_call_address(abscallptr));
|
||||
checkRunAsNode = reinterpret_cast<void(__fastcall *)(void *)>(baseAddr + funcptr);
|
||||
return moehoo::hook(abscallptr, &fakeWinMain);
|
||||
}
|
8
src/run_as_node.h
Normal file
8
src/run_as_node.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "../include/moehoo/hook.h"
|
||||
|
||||
namespace RunAsNode
|
||||
{
|
||||
bool Init();
|
||||
}
|
@ -4,7 +4,11 @@
|
||||
|
||||
#include <thread>
|
||||
|
||||
std::string ConstructResponse(const std::string &sign, const std::string &extra, const std::string &token) {
|
||||
std::string Server::GetSign(const std::string_view &cmd, const std::string_view &src, const int seq)
|
||||
{
|
||||
auto [signDataHex, extraDataHex, tokenDataHex] = Sign::Call(cmd, src, seq);
|
||||
counter++;
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
@ -12,26 +16,21 @@ std::string ConstructResponse(const std::string &sign, const std::string &extra,
|
||||
writer.Key("value");
|
||||
writer.StartObject();
|
||||
writer.Key("sign");
|
||||
writer.String(sign.c_str());
|
||||
writer.String(signDataHex.c_str());
|
||||
writer.Key("extra");
|
||||
writer.String(extra.c_str());
|
||||
writer.String(extraDataHex.c_str());
|
||||
writer.Key("token");
|
||||
writer.String(token.c_str());
|
||||
writer.String(tokenDataHex.c_str());
|
||||
writer.EndObject();
|
||||
writer.EndObject();
|
||||
|
||||
return buffer.GetString();
|
||||
}
|
||||
|
||||
Server::Server(int port) {
|
||||
printf("Start server on port: %d\n", port);
|
||||
std::thread(&Server::Init, this, port)
|
||||
.detach();
|
||||
}
|
||||
|
||||
void Server::Init(int port) {
|
||||
try {
|
||||
svr.Post("/sign", [this](const httplib::Request &req, httplib::Response &res) {
|
||||
void Server::Init()
|
||||
{
|
||||
svr.Post("/sign", [this](const httplib::Request &req, httplib::Response &res)
|
||||
{
|
||||
try {
|
||||
rapidjson::Document doc;
|
||||
doc.Parse(req.body.c_str(), req.body.size());
|
||||
@ -40,37 +39,31 @@ void Server::Init(int port) {
|
||||
std::string_view src = doc["src"].GetString();
|
||||
int seq = doc["seq"].GetInt();
|
||||
|
||||
auto [signDataHex, extraDataHex, tokenDataHex] = sign.Call(cmd, src, seq);
|
||||
std::string buffer = ConstructResponse(signDataHex, extraDataHex, tokenDataHex);
|
||||
counter++;
|
||||
std::string buffer = GetSign(cmd, src, seq);
|
||||
|
||||
res.set_content(buffer, "application/json");
|
||||
}
|
||||
catch (...) {
|
||||
res.set_content("Bad Request", "text/plain");
|
||||
res.status = httplib::StatusCode::BadRequest_400;
|
||||
}
|
||||
});
|
||||
|
||||
svr.Get("/sign", [this](const httplib::Request &req, httplib::Response &res) {
|
||||
} })
|
||||
.Get("/sign", [this](const httplib::Request &req, httplib::Response &res)
|
||||
{
|
||||
try {
|
||||
std::string cmd = req.get_param_value("cmd");
|
||||
std::string src = req.get_param_value("src");
|
||||
std::string_view cmd = req.get_param_value("cmd");
|
||||
std::string_view src = req.get_param_value("src");
|
||||
int seq = std::stoi(req.get_param_value("seq"));
|
||||
|
||||
auto [signDataHex, extraDataHex, tokenDataHex] = sign.Call(cmd, src, seq);
|
||||
std::string buffer = ConstructResponse(signDataHex, extraDataHex, tokenDataHex);
|
||||
counter++;
|
||||
std::string buffer = GetSign(cmd, src, seq);
|
||||
|
||||
res.set_content(buffer, "application/json");
|
||||
}
|
||||
catch (...) {
|
||||
res.set_content("Bad Request", "text/plain");
|
||||
res.status = httplib::StatusCode::BadRequest_400;
|
||||
}
|
||||
});
|
||||
|
||||
svr.Get("/ping", [](const httplib::Request &req, httplib::Response &res) {
|
||||
} })
|
||||
.Get("/ping", [](const httplib::Request &req, httplib::Response &res)
|
||||
{
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
@ -79,10 +72,9 @@ void Server::Init(int port) {
|
||||
writer.Int(0);
|
||||
writer.EndObject();
|
||||
|
||||
res.set_content(buffer.GetString(), "application/json");
|
||||
});
|
||||
|
||||
svr.Get("/count", [this](const httplib::Request &req, httplib::Response &res) {
|
||||
res.set_content(buffer.GetString(), "application/json"); })
|
||||
.Get("/count", [this](const httplib::Request &req, httplib::Response &res)
|
||||
{
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
|
||||
@ -91,12 +83,10 @@ void Server::Init(int port) {
|
||||
writer.String(std::to_string(counter.load()).c_str());
|
||||
writer.EndObject();
|
||||
|
||||
res.set_content(buffer.GetString(), "application/json");
|
||||
});
|
||||
res.set_content(buffer.GetString(), "application/json"); });
|
||||
}
|
||||
|
||||
bool ret = svr.listen("0.0.0.0", port);
|
||||
}
|
||||
catch(std::exception &e) {
|
||||
printf("Server init failed: %s\n", e.what());
|
||||
}
|
||||
bool Server::Run(const std::string &ip, int port)
|
||||
{
|
||||
return svr.listen(ip.c_str(), port);
|
||||
}
|
||||
|
12
src/server.h
12
src/server.h
@ -1,16 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "sign.h"
|
||||
#include "../include/cpp-httplib/httplib.h"
|
||||
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
Server(int port);
|
||||
|
||||
private:
|
||||
Sign sign;
|
||||
httplib::Server svr;
|
||||
std::atomic<uint64_t> counter = 0;
|
||||
|
||||
private:
|
||||
void Init(int port);
|
||||
std::string Server::GetSign(const std::string_view &cmd, const std::string_view &src, const int seq);
|
||||
|
||||
public:
|
||||
void Init();
|
||||
bool Server::Run(const std::string &ip, int port);
|
||||
};
|
85
src/sign.cpp
85
src/sign.cpp
@ -19,9 +19,12 @@
|
||||
#include <cstring>
|
||||
#endif
|
||||
|
||||
typedef int (*SignFunctionType)(const char *cmd, const unsigned char *src, size_t src_len, int seq, unsigned char *result);
|
||||
SignFunctionType SignFunction = nullptr;
|
||||
|
||||
// 签名函数定义
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
#define CURRENT_VERSION "9.9.10-24108"
|
||||
#define CURRENT_VERSION "9.9.12-25234"
|
||||
#if defined(_X64_ARCH_)
|
||||
std::map<std::string, uint64_t> addrMap = {
|
||||
{"9.9.2-16183", 0x2E0D0},
|
||||
@ -29,24 +32,22 @@ std::map<std::string, uint64_t> addrMap = {
|
||||
{"9.9.9-23424", 0x2EB50},
|
||||
{"9.9.9-23424", 0x2EB50},
|
||||
{"9.9.10-24108", 0x2EB50},
|
||||
{"9.9.11-24568", 0xAA1A20}
|
||||
};
|
||||
{"9.9.11-24568", 0xAA1A20},
|
||||
{"9.9.11-24815", 0xAB5510},
|
||||
{"9.9.12-25234", 0xA84980}};
|
||||
#elif defined(_X86_ARCH_)
|
||||
std::map<std::string, uint64_t> addrMap = {
|
||||
{"9.9.2-15962", 0x2BD70},
|
||||
{"9.9.2-16183", 0x2BD70}
|
||||
};
|
||||
{"9.9.2-16183", 0x2BD70}};
|
||||
#endif
|
||||
#elif defined(_MAC_PLATFORM_)
|
||||
#define CURRENT_VERSION "6.9.20-17153"
|
||||
#if defined(_X64_ARCH_)
|
||||
std::map<std::string, uint64_t> addrMap = {
|
||||
{"6.9.19-16183", 0x1B29469}
|
||||
};
|
||||
{"6.9.19-16183", 0x1B29469}};
|
||||
#elif defined(_ARM64_ARCH_)
|
||||
std::map<std::string, uint64_t> addrMap = {
|
||||
{"6.9.20-17153", 0x1c73dd0}
|
||||
};
|
||||
{"6.9.20-17153", 0x1c73dd0}};
|
||||
#endif
|
||||
#elif defined(_LINUX_PLATFORM_)
|
||||
#define CURRENT_VERSION "3.2.7-23361"
|
||||
@ -54,12 +55,10 @@ std::map<std::string, uint64_t> addrMap = {
|
||||
std::map<std::string, uint64_t> addrMap = {
|
||||
{"3.1.2-12912", 0x33C38E0},
|
||||
{"3.1.2-13107", 0x33C3920},
|
||||
{"3.2.7-23361", 0x4C93C57}
|
||||
};
|
||||
{"3.2.7-23361", 0x4C93C57}};
|
||||
#elif defined(_ARM64_ARCH_)
|
||||
std::map<std::string, uint64_t> addrMap = {
|
||||
{"3.2.7-23361", 0x351EC98}
|
||||
};
|
||||
{"3.2.7-23361", 0x351EC98}};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -67,13 +66,16 @@ int SignOffsets = 767; // 562 before 3.1.2-13107, 767 in others
|
||||
int ExtraOffsets = 511;
|
||||
int TokenOffsets = 255;
|
||||
|
||||
std::vector<uint8_t> Hex2Bin(std::string_view str) {
|
||||
if (str.length() % 2 != 0) {
|
||||
std::vector<uint8_t> Hex2Bin(std::string_view str)
|
||||
{
|
||||
if (str.length() % 2 != 0)
|
||||
{
|
||||
throw std::invalid_argument("Hex string length must be even");
|
||||
}
|
||||
std::vector<uint8_t> bin(str.size() / 2);
|
||||
std::string extract("00");
|
||||
for (size_t i = 0; i < str.size() / 2; i++) {
|
||||
for (size_t i = 0; i < str.size() / 2; i++)
|
||||
{
|
||||
extract[0] = str[2 * i];
|
||||
extract[1] = str[2 * i + 1];
|
||||
bin[i] = std::stoi(extract, nullptr, 16);
|
||||
@ -81,45 +83,36 @@ std::vector<uint8_t> Hex2Bin(std::string_view str) {
|
||||
return bin;
|
||||
}
|
||||
|
||||
std::string Bin2Hex(const uint8_t *ptr, size_t length) {
|
||||
std::string Bin2Hex(const uint8_t *ptr, size_t length)
|
||||
{
|
||||
const char table[] = "0123456789ABCDEF";
|
||||
std::string str;
|
||||
str.resize(length * 2);
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
str[2 * i] = table[ptr[i] / 16];
|
||||
str[2 * i + 1] = table[ptr[i] % 16];
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
Sign::Sign() {
|
||||
printf("Start init sign\n");
|
||||
std::thread([this]{
|
||||
while (true) {
|
||||
try {
|
||||
Init();
|
||||
break;
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
printf("Init sign failed: %s\n", e.what());
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
} }).detach();
|
||||
}
|
||||
|
||||
void Sign::Init() {
|
||||
bool Sign::Init()
|
||||
{
|
||||
uint64_t HookAddress = 0;
|
||||
#if defined(_WIN_PLATFORM_)
|
||||
HMODULE wrapperModule = GetModuleHandleW(L"wrapper.node");
|
||||
if (wrapperModule == NULL) {
|
||||
if (wrapperModule == NULL)
|
||||
{
|
||||
throw std::runtime_error("Can't find wrapper.node module");
|
||||
}
|
||||
HookAddress = reinterpret_cast<uint64_t>(wrapperModule) + addrMap[CURRENT_VERSION];
|
||||
printf("HookAddress: %llx\n", HookAddress);
|
||||
#elif defined(_MAC_PLATFORM_)
|
||||
auto pmap = hak::get_maps();
|
||||
do {
|
||||
if (pmap->module_name.find("wrapper.node") != std::string::npos && pmap->offset == 0) {
|
||||
do
|
||||
{
|
||||
if (pmap->module_name.find("wrapper.node") != std::string::npos && pmap->offset == 0)
|
||||
{
|
||||
HookAddress = pmap->start() + addrMap[CURRENT_VERSION];
|
||||
printf("HookAddress: %llx\n", HookAddress);
|
||||
break;
|
||||
@ -127,29 +120,35 @@ void Sign::Init() {
|
||||
} while ((pmap = pmap->next()) != nullptr);
|
||||
#elif defined(_LINUX_PLATFORM_)
|
||||
auto pmap = hak::get_maps();
|
||||
do {
|
||||
if (pmap->module_name.find("wrapper.node") != std::string::npos && pmap->offset == 0) {
|
||||
do
|
||||
{
|
||||
if (pmap->module_name.find("wrapper.node") != std::string::npos && pmap->offset == 0)
|
||||
{
|
||||
HookAddress = pmap->start() + addrMap[CURRENT_VERSION];
|
||||
printf("HookAddress: %lx\n", HookAddress);
|
||||
break;
|
||||
}
|
||||
} while ((pmap = pmap->next()) != nullptr);
|
||||
#endif
|
||||
if (HookAddress == 0) {
|
||||
if (HookAddress == 0)
|
||||
{
|
||||
throw std::runtime_error("Can't find hook address");
|
||||
}
|
||||
SignFunction = reinterpret_cast<SignFunctionType>(HookAddress);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::tuple<std::string, std::string, std::string> Sign::Call(const std::string_view cmd, const std::string_view src, int seq) {
|
||||
if (SignFunction == nullptr) {
|
||||
std::tuple<std::string, std::string, std::string> Sign::Call(const std::string_view cmd, const std::string_view src, int seq)
|
||||
{
|
||||
if (SignFunction == nullptr)
|
||||
{
|
||||
throw std::runtime_error("Sign function not initialized");
|
||||
}
|
||||
|
||||
const std::vector<uint8_t> signArgSrc = Hex2Bin(src);
|
||||
|
||||
size_t resultSize = 1024;
|
||||
auto *signResult = new uint8_t[resultSize];
|
||||
uint8_t *signResult = new uint8_t[resultSize];
|
||||
|
||||
SignFunction(cmd.data(), signArgSrc.data(), signArgSrc.size(), seq, signResult);
|
||||
|
||||
|
18
src/sign.h
18
src/sign.h
@ -1,18 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
|
||||
class Sign
|
||||
namespace Sign
|
||||
{
|
||||
public:
|
||||
Sign();
|
||||
|
||||
private:
|
||||
typedef int (*SignFunctionType)(const char *cmd, const unsigned char *src, size_t src_len, int seq, unsigned char *result);
|
||||
SignFunctionType SignFunction = nullptr;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
public:
|
||||
bool Init();
|
||||
std::tuple<std::string, std::string, std::string> Call(const std::string_view cmd, const std::string_view src, int seq);
|
||||
};
|
||||
}
|
114
src/version.asm
114
src/version.asm
@ -1,114 +0,0 @@
|
||||
ifdef _WIN_PLATFORM_
|
||||
ifdef RAX
|
||||
.code
|
||||
extern OriginalFuncs_version:QWORD
|
||||
GetFileVersionInfoA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[0 * 8]
|
||||
GetFileVersionInfoA endp
|
||||
GetFileVersionInfoByHandle proc
|
||||
jmp QWORD ptr OriginalFuncs_version[1 * 8]
|
||||
GetFileVersionInfoByHandle endp
|
||||
GetFileVersionInfoExA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[2 * 8]
|
||||
GetFileVersionInfoExA endp
|
||||
GetFileVersionInfoExW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[3 * 8]
|
||||
GetFileVersionInfoExW endp
|
||||
GetFileVersionInfoSizeA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[4 * 8]
|
||||
GetFileVersionInfoSizeA endp
|
||||
GetFileVersionInfoSizeExA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[5 * 8]
|
||||
GetFileVersionInfoSizeExA endp
|
||||
GetFileVersionInfoSizeExW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[6 * 8]
|
||||
GetFileVersionInfoSizeExW endp
|
||||
GetFileVersionInfoSizeW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[7 * 8]
|
||||
GetFileVersionInfoSizeW endp
|
||||
GetFileVersionInfoW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[8 * 8]
|
||||
GetFileVersionInfoW endp
|
||||
VerFindFileA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[9 * 8]
|
||||
VerFindFileA endp
|
||||
VerFindFileW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[10 * 8]
|
||||
VerFindFileW endp
|
||||
VerInstallFileA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[11 * 8]
|
||||
VerInstallFileA endp
|
||||
VerInstallFileW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[12 * 8]
|
||||
VerInstallFileW endp
|
||||
VerLanguageNameA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[13 * 8]
|
||||
VerLanguageNameA endp
|
||||
VerLanguageNameW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[14 * 8]
|
||||
VerLanguageNameW endp
|
||||
VerQueryValueA proc
|
||||
jmp QWORD ptr OriginalFuncs_version[15 * 8]
|
||||
VerQueryValueA endp
|
||||
VerQueryValueW proc
|
||||
jmp QWORD ptr OriginalFuncs_version[16 * 8]
|
||||
VerQueryValueW endp
|
||||
else
|
||||
.model flat, C
|
||||
.stack 4096
|
||||
.code
|
||||
extern OriginalFuncs_version:DWORD
|
||||
GetFileVersionInfoA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[0 * 4]
|
||||
GetFileVersionInfoA endp
|
||||
GetFileVersionInfoByHandle proc
|
||||
jmp DWORD ptr OriginalFuncs_version[1 * 4]
|
||||
GetFileVersionInfoByHandle endp
|
||||
GetFileVersionInfoExA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[2 * 4]
|
||||
GetFileVersionInfoExA endp
|
||||
GetFileVersionInfoExW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[3 * 4]
|
||||
GetFileVersionInfoExW endp
|
||||
GetFileVersionInfoSizeA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[4 * 4]
|
||||
GetFileVersionInfoSizeA endp
|
||||
GetFileVersionInfoSizeExA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[5 * 4]
|
||||
GetFileVersionInfoSizeExA endp
|
||||
GetFileVersionInfoSizeExW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[6 * 4]
|
||||
GetFileVersionInfoSizeExW endp
|
||||
GetFileVersionInfoSizeW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[7 * 4]
|
||||
GetFileVersionInfoSizeW endp
|
||||
GetFileVersionInfoW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[8 * 4]
|
||||
GetFileVersionInfoW endp
|
||||
VerFindFileA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[9 * 4]
|
||||
VerFindFileA endp
|
||||
VerFindFileW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[10 * 4]
|
||||
VerFindFileW endp
|
||||
VerInstallFileA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[11 * 4]
|
||||
VerInstallFileA endp
|
||||
VerInstallFileW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[12 * 4]
|
||||
VerInstallFileW endp
|
||||
VerLanguageNameA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[13 * 4]
|
||||
VerLanguageNameA endp
|
||||
VerLanguageNameW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[14 * 4]
|
||||
VerLanguageNameW endp
|
||||
VerQueryValueA proc
|
||||
jmp DWORD ptr OriginalFuncs_version[15 * 4]
|
||||
VerQueryValueA endp
|
||||
VerQueryValueW proc
|
||||
jmp DWORD ptr OriginalFuncs_version[16 * 4]
|
||||
VerQueryValueW endp
|
||||
endif
|
||||
endif
|
||||
end
|
15
start.bat
15
start.bat
@ -22,15 +22,9 @@ if not exist "%pathWithoutUninstall%version.dll" (
|
||||
set /p Choice="version.dll already exists, do you want to replace it?(Y/N):"
|
||||
if /i "!Choice!"=="Y" goto copydll
|
||||
if /i "!Choice!"=="y" goto copydll
|
||||
goto launch
|
||||
)
|
||||
|
||||
:launch
|
||||
set "QQPath=!pathWithoutUninstall!QQ.exe"
|
||||
set ELECTRON_RUN_AS_NODE=1
|
||||
|
||||
echo Launching QQ
|
||||
"!QQPath!" "%~dp0load.js" %*
|
||||
|
||||
:copydll
|
||||
copy /y "%~dp0SignerServer.dll" "%pathWithoutUninstall%version.dll"
|
||||
if errorlevel 1 (
|
||||
@ -43,3 +37,10 @@ goto launch
|
||||
|
||||
:restart
|
||||
powershell Start-Process -FilePath cmd.exe -ArgumentList """/c pushd %~dp0 && %~s0 %*""" -Verb RunAs
|
||||
|
||||
:launch
|
||||
set "QQPath=!pathWithoutUninstall!QQ.exe"
|
||||
set ELECTRON_RUN_AS_NODE=1
|
||||
|
||||
echo Launching QQ
|
||||
"!QQPath!" "%~dp0load.js" %*
|
18
version.def
18
version.def
@ -1,18 +0,0 @@
|
||||
EXPORTS
|
||||
GetFileVersionInfoA
|
||||
GetFileVersionInfoByHandle
|
||||
GetFileVersionInfoExA
|
||||
GetFileVersionInfoExW
|
||||
GetFileVersionInfoSizeA
|
||||
GetFileVersionInfoSizeExA
|
||||
GetFileVersionInfoSizeExW
|
||||
GetFileVersionInfoSizeW
|
||||
GetFileVersionInfoW
|
||||
VerFindFileA
|
||||
VerFindFileW
|
||||
VerInstallFileA
|
||||
VerInstallFileW
|
||||
VerLanguageNameA
|
||||
VerLanguageNameW
|
||||
VerQueryValueA
|
||||
VerQueryValueW
|
Loading…
x
Reference in New Issue
Block a user