From 5ddb727d6d3b63eb01bc0bf7c3f8df323137fc03 Mon Sep 17 00:00:00 2001 From: rjindael Date: Wed, 26 Jul 2023 01:24:24 -0700 Subject: [PATCH] revamp all the code (not done yet!) --- .gitignore | 416 +---------------- CMakeLists.txt | 6 + Kiseki.Patcher.sln | 25 -- .../Configuration.hpp} | 111 +++-- .../{Include/Discord.h => Header/Discord.hpp} | 40 +- .../{Include/Helpers.h => Header/Helpers.hpp} | 50 +-- .../CRoblox.h => Header/Hooks/CRoblox.hpp} | 92 ++-- .../Context.h => Header/Hooks/Context.hpp} | 24 +- .../Hooks/Crypt.h => Header/Hooks/Crypt.hpp} | 38 +- .../Hooks/DataModel.hpp} | 38 +- .../Hooks/Http.h => Header/Hooks/Http.hpp} | 56 ++- .../Hooks/ServerReplicator.hpp} | 64 +-- .../Hooks/StandardOut.hpp} | 26 +- .../{Include/Patches.h => Header/Patcher.hpp} | 30 +- .../{Include/Server.h => Header/Server.hpp} | 82 ++-- Kiseki.Patcher/Include/framework.h | 5 - Kiseki.Patcher/Include/pch.h | 18 - Kiseki.Patcher/Include/resource.h | 14 - Kiseki.Patcher/Kiseki.Patcher.rc | 100 ----- Kiseki.Patcher/Kiseki.Patcher.vcxproj | 163 ------- Kiseki.Patcher/Kiseki.Patcher.vcxproj.filters | 113 ----- Kiseki.Patcher/Resource/Information.h | 12 + Kiseki.Patcher/Resource/Script.rc | 36 ++ Kiseki.Patcher/{ => Source}/Discord.cpp | 244 +++++----- Kiseki.Patcher/{ => Source}/Helpers.cpp | 420 +++++++++--------- Kiseki.Patcher/{ => Source}/Hooks/CRoblox.cpp | 296 ++++++------ Kiseki.Patcher/{ => Source}/Hooks/Context.cpp | 49 +- Kiseki.Patcher/{ => Source}/Hooks/Crypt.cpp | 259 ++++++----- .../{ => Source}/Hooks/DataModel.cpp | 42 +- Kiseki.Patcher/{ => Source}/Hooks/Http.cpp | 294 ++++++------ .../{ => Source}/Hooks/ServerReplicator.cpp | 66 ++- .../{ => Source}/Hooks/StandardOut.cpp | 46 +- .../{Patches.cpp => Source/Patcher.cpp} | 26 +- Kiseki.Patcher/{ => Source}/Server.cpp | 194 ++++---- .../{dllmain.cpp => Source/main.cpp} | 199 +++++---- Kiseki.Patcher/pch.cpp | 1 - README.md | 6 +- vcpkg.json | 3 +- 38 files changed, 1453 insertions(+), 2251 deletions(-) create mode 100644 CMakeLists.txt delete mode 100644 Kiseki.Patcher.sln rename Kiseki.Patcher/{Include/Configuration.h => Header/Configuration.hpp} (82%) rename Kiseki.Patcher/{Include/Discord.h => Header/Discord.hpp} (76%) rename Kiseki.Patcher/{Include/Helpers.h => Header/Helpers.hpp} (95%) rename Kiseki.Patcher/{Include/Hooks/CRoblox.h => Header/Hooks/CRoblox.hpp} (91%) rename Kiseki.Patcher/{Include/Hooks/Context.h => Header/Hooks/Context.hpp} (90%) rename Kiseki.Patcher/{Include/Hooks/Crypt.h => Header/Hooks/Crypt.hpp} (93%) rename Kiseki.Patcher/{Include/Hooks/DataModel.h => Header/Hooks/DataModel.hpp} (76%) rename Kiseki.Patcher/{Include/Hooks/Http.h => Header/Hooks/Http.hpp} (81%) rename Kiseki.Patcher/{Include/Hooks/ServerReplicator.h => Header/Hooks/ServerReplicator.hpp} (91%) rename Kiseki.Patcher/{Include/Hooks/StandardOut.h => Header/Hooks/StandardOut.hpp} (70%) rename Kiseki.Patcher/{Include/Patches.h => Header/Patcher.hpp} (63%) rename Kiseki.Patcher/{Include/Server.h => Header/Server.hpp} (84%) delete mode 100644 Kiseki.Patcher/Include/framework.h delete mode 100644 Kiseki.Patcher/Include/pch.h delete mode 100644 Kiseki.Patcher/Include/resource.h delete mode 100644 Kiseki.Patcher/Kiseki.Patcher.rc delete mode 100644 Kiseki.Patcher/Kiseki.Patcher.vcxproj delete mode 100644 Kiseki.Patcher/Kiseki.Patcher.vcxproj.filters create mode 100644 Kiseki.Patcher/Resource/Information.h create mode 100644 Kiseki.Patcher/Resource/Script.rc rename Kiseki.Patcher/{ => Source}/Discord.cpp (83%) rename Kiseki.Patcher/{ => Source}/Helpers.cpp (95%) rename Kiseki.Patcher/{ => Source}/Hooks/CRoblox.cpp (95%) rename Kiseki.Patcher/{ => Source}/Hooks/Context.cpp (88%) rename Kiseki.Patcher/{ => Source}/Hooks/Crypt.cpp (93%) rename Kiseki.Patcher/{ => Source}/Hooks/DataModel.cpp (82%) rename Kiseki.Patcher/{ => Source}/Hooks/Http.cpp (96%) rename Kiseki.Patcher/{ => Source}/Hooks/ServerReplicator.cpp (91%) rename Kiseki.Patcher/{ => Source}/Hooks/StandardOut.cpp (83%) rename Kiseki.Patcher/{Patches.cpp => Source/Patcher.cpp} (70%) rename Kiseki.Patcher/{ => Source}/Server.cpp (95%) rename Kiseki.Patcher/{dllmain.cpp => Source/main.cpp} (82%) delete mode 100644 Kiseki.Patcher/pch.cpp diff --git a/.gitignore b/.gitignore index 8dd4607..568ea10 100644 --- a/.gitignore +++ b/.gitignore @@ -1,398 +1,18 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. -## -## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore - -# User-specific files -*.rsuser -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Mono auto generated files -mono_crash.* - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -[Ww][Ii][Nn]32/ -[Aa][Rr][Mm]/ -[Aa][Rr][Mm]64/ -bld/ -[Bb]in/ -[Oo]bj/ -[Ll]og/ -[Ll]ogs/ - -# Visual Studio 2015/2017 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# Visual Studio 2017 auto generated files -Generated\ Files/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUnit -*.VisualState.xml -TestResult.xml -nunit-*.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# Benchmark Results -BenchmarkDotNet.Artifacts/ - -# .NET Core -project.lock.json -project.fragment.lock.json -artifacts/ - -# ASP.NET Scaffolding -ScaffoldingReadMe.txt - -# StyleCop -StyleCopReport.xml - -# Files built by Visual Studio -*_i.c -*_p.c -*_h.h -*.ilk -*.meta -*.obj -*.iobj -*.pch -*.pdb -*.ipdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*_wpftmp.csproj -*.log -*.tlog -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile -*.VC.db -*.VC.VC.opendb - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# Visual Studio Trace Files -*.e2e - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# AxoCover is a Code Coverage Tool -.axoCover/* -!.axoCover/settings.json - -# Coverlet is a free, cross platform Code Coverage Tool -coverage*.json -coverage*.xml -coverage*.info - -# Visual Studio code coverage results -*.coverage -*.coveragexml - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# Note: Comment the next line if you want to checkin your web deploy settings, -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# Microsoft Azure Web App publish settings. Comment the next line if you want to -# checkin your Azure Web App publish settings, but sensitive information contained -# in these scripts will be unencrypted -PublishScripts/ - -# NuGet Packages -*.nupkg -# NuGet Symbol Packages -*.snupkg -# The packages folder can be ignored because of Package Restore -**/[Pp]ackages/* -# except build/, which is used as an MSBuild target. -!**/[Pp]ackages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/[Pp]ackages/repositories.config -# NuGet v3's project.json files produces more ignorable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Windows Store app package directories and files -AppPackages/ -BundleArtifacts/ -Package.StoreAssociation.xml -_pkginfo.txt -*.appx -*.appxbundle -*.appxupload - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!?*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.jfm -*.pfx -*.publishsettings -orleans.codegen.cs - -# Including strong name files can present a security risk -# (https://github.com/github/gitignore/pull/2483#issue-259490424) -#*.snk - -# Since there are multiple workflows, uncomment next line to ignore bower_components -# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) -#bower_components/ - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm -ServiceFabricBackup/ -*.rptproj.bak - -# SQL Server files -*.mdf -*.ldf -*.ndf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings -*.rptproj.rsuser -*- [Bb]ackup.rdl -*- [Bb]ackup ([0-9]).rdl -*- [Bb]ackup ([0-9][0-9]).rdl - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat -node_modules/ - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) -*.vbw - -# Visual Studio 6 auto-generated project file (contains which files were open etc.) -*.vbp - -# Visual Studio 6 workspace and project file (working project files containing files to include in project) -*.dsw -*.dsp - -# Visual Studio 6 technical files -*.ncb -*.aps - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe -paket-files/ - -# FAKE - F# Make -.fake/ - -# CodeRush personal settings -.cr/personal - -# Python Tools for Visual Studio (PTVS) -__pycache__/ -*.pyc - -# Cake - Uncomment if you are using it -# tools/** -# !tools/packages.config - -# Tabs Studio -*.tss - -# Telerik's JustMock configuration file -*.jmconfig - -# BizTalk build output -*.btp.cs -*.btm.cs -*.odx.cs -*.xsd.cs - -# OpenCover UI analysis results -OpenCover/ - -# Azure Stream Analytics local run output -ASALocalRun/ - -# MSBuild Binary and Structured Log -*.binlog - -# NVidia Nsight GPU debugger configuration file -*.nvuser - -# MFractors (Xamarin productivity tool) working folder -.mfractor/ - -# Local History for Visual Studio -.localhistory/ - -# Visual Studio History (VSHistory) files -.vshistory/ - -# BeatPulse healthcheck temp database -healthchecksdb - -# Backup folder for Package Reference Convert tool in Visual Studio 2017 -MigrationBackup/ - -# Ionide (cross platform F# VS Code tools) working folder -.ionide/ - -# Fody - auto-generated XML schema -FodyWeavers.xsd - -# VS Code files for those working on multiple tools -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json -*.code-workspace - -# Local History for Visual Studio Code -.history/ - -# Windows Installer files from build outputs -*.cab -*.msi -*.msix -*.msm -*.msp - -# JetBrains Rider -*.sln.iml \ No newline at end of file +# GitHub official CMake gitignore template +# https://github.com/github/gitignore/blob/main/CMake.gitignore + +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +# Kiseki +build +.vscode \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..f04df9b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +cmake_minimum_required(VERSION 3.4) + +project(Kiseki.Patcher VERSION 1.0.0) + +option(COMPILE_PLAYER "Include player-specific code" OFF) +option(COMPILE_SERVER "Include server-specific code" OFF) \ No newline at end of file diff --git a/Kiseki.Patcher.sln b/Kiseki.Patcher.sln deleted file mode 100644 index d3d269c..0000000 --- a/Kiseki.Patcher.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Kiseki.Patcher", "Kiseki.Patcher\Kiseki.Patcher.vcxproj", "{9D232642-FB2F-43DC-B0AC-C56E3B691233}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|x86 = Debug|x86 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {9D232642-FB2F-43DC-B0AC-C56E3B691233}.Debug|x86.ActiveCfg = Debug|Win32 - {9D232642-FB2F-43DC-B0AC-C56E3B691233}.Debug|x86.Build.0 = Debug|Win32 - {9D232642-FB2F-43DC-B0AC-C56E3B691233}.Release|x86.ActiveCfg = Release|Win32 - {9D232642-FB2F-43DC-B0AC-C56E3B691233}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {01A4798F-B42A-4C9B-BFE7-A6D1BD35C7B3} - EndGlobalSection -EndGlobal diff --git a/Kiseki.Patcher/Include/Configuration.h b/Kiseki.Patcher/Header/Configuration.hpp similarity index 82% rename from Kiseki.Patcher/Include/Configuration.h rename to Kiseki.Patcher/Header/Configuration.hpp index b7b38e4..e943833 100644 --- a/Kiseki.Patcher/Include/Configuration.h +++ b/Kiseki.Patcher/Header/Configuration.hpp @@ -1,61 +1,50 @@ -#pragma once - -/* - * This is commented out since our CI defines this automatically. - * Uncomment this if you want to test locally, but please do not push with these uncommented! - */ - -// #define SERVER -// #define PLAYER - -#define BASE_URL "https://kiseki.lol" -#define DISCORD_APP_ID 0 - -#define ALLOWED_WILDCARD_DOMAINS "kiseki.lol", "rbxcdn.com", "roblox.com" -#define ALLOWED_DOMAINS -#define ALLOWED_SCHEMES "http", "https" -#define ALLOWED_EMBEDDED_SCHEMES "javascript", "jscript", "res" - -#ifdef _DEBUG -#define PUBLIC_KEY "" -#else -#define PUBLIC_KEY 0x00 -#endif - -// TODO: Verify this -#define CLASSPADDING_DATAMODEL__JOBID 739 - -#define ADDRESS_HTTP__HTTPGETPOSTWININET 0x0 -#define ADDRESS_HTTP__TRUSTCHECK 0x005B7050 -#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x00809EC0 -#define ADDRESS_CONTEXT__REQUIREPERMISSION 0x0 -#define ADDRESS_CONTEXT__ISINROLE 0x0 -#define ADDRESS_DATAMODEL__GETJOBID 0x005E70C0 -#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0 -#define ADDRESS_SERVERREPLICATOR__SENDTOP 0x00513E80 -#define ADDRESS_SERVERREPLICATOR__PROCESSTICKET 0x00514B60 -#define ADDRESS_SERVERREPLICATOR__PROCESSPACKET 0x00514B60 - -#define CLASSLOCATION_CROBLOXAPP 0x00CBA8A0 -#define CLASSLOCATION_CAPP 0x00406D80 - -#define CLASSPADDING_CROBLOXDOC__WORKSPACE 45 - -#define ADDRESS_CAPP__CREATEGAME 0x00406D80 -#define ADDRESS_CAPP__ROBLOXAUTHENTICATE 0x00409050 -#define ADDRESS_CROBLOXAPP__INITINSTANCE 0x004613C0 -#define ADDRESS_CROBLOXAPP__CREATEDOCUMENT 0x0045D030 -#define ADDRESS_CWORKSPACE__EXECURLSCRIPT 0x0049FC90 -#define ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM 0x0045EE50 -#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0081354A - -#ifndef _DEBUG -#define PADDING_STRUCT 1 -#else -#define PADDING_STRUCT 0 -#endif - -#define RBX__MESSAGE_INFO 0 -#define RBX__MESSAGE_OUTPUT 1 -#define RBX__MESSAGE_WARNING 2 -#define RBX__MESSAGE_ERROR 3 \ No newline at end of file +#pragma once + +#define ALLOWED_WILDCARD_DOMAINS "kiseki.lol", "rbxcdn.com", "roblox.com" +#define ALLOWED_DOMAINS +#define ALLOWED_SCHEMES "http", "https" +#define ALLOWED_EMBEDDED_SCHEMES "javascript", "jscript", "res" + +#ifdef _DEBUG +#define PUBLIC_KEY "" +#else +#define PUBLIC_KEY 0x00 +#endif + +#define RBX__MESSAGE_INFO 0 +#define RBX__MESSAGE_OUTPUT 1 +#define RBX__MESSAGE_WARNING 2 +#define RBX__MESSAGE_ERROR 3 + +// TODO: Verify this +#define CLASSPADDING_DATAMODEL__JOBID 739 + +#define ADDRESS_HTTP__HTTPGETPOSTWININET 0x0 +#define ADDRESS_HTTP__TRUSTCHECK 0x005B7050 +#define ADDRESS_CRYPT__VERIFYSIGNATUREBASE64 0x00809EC0 +#define ADDRESS_CONTEXT__REQUIREPERMISSION 0x0 +#define ADDRESS_CONTEXT__ISINROLE 0x0 +#define ADDRESS_DATAMODEL__GETJOBID 0x005E70C0 +#define ADDRESS_STANDARDOUT__PRINT 0x005B25E0 +#define ADDRESS_SERVERREPLICATOR__SENDTOP 0x00513E80 +#define ADDRESS_SERVERREPLICATOR__PROCESSTICKET 0x00514B60 +#define ADDRESS_SERVERREPLICATOR__PROCESSPACKET 0x00514B60 + +#define CLASSLOCATION_CROBLOXAPP 0x00CBA8A0 +#define CLASSLOCATION_CAPP 0x00406D80 + +#define CLASSPADDING_CROBLOXDOC__WORKSPACE 45 + +#define ADDRESS_CAPP__CREATEGAME 0x00406D80 +#define ADDRESS_CAPP__ROBLOXAUTHENTICATE 0x00409050 +#define ADDRESS_CROBLOXAPP__INITINSTANCE 0x004613C0 +#define ADDRESS_CROBLOXAPP__CREATEDOCUMENT 0x0045D030 +#define ADDRESS_CWORKSPACE__EXECURLSCRIPT 0x0049FC90 +#define ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM 0x0045EE50 +#define ADDRESS_CCOMMANDLINEINFO__PARSELAST 0x0081354A + +#ifdef _DEBUG +#define PADDING_STRUCT 0 +#else +#define PADDING_STRUCT 1 +#endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Discord.h b/Kiseki.Patcher/Header/Discord.hpp similarity index 76% rename from Kiseki.Patcher/Include/Discord.h rename to Kiseki.Patcher/Header/Discord.hpp index de9f6b6..ddb9435 100644 --- a/Kiseki.Patcher/Include/Discord.h +++ b/Kiseki.Patcher/Header/Discord.hpp @@ -1,20 +1,22 @@ -#pragma once - -#include -#include -#include - -#include "Configuration.h" -#include "Hooks/CRoblox.h" - -#ifdef PLAYER - -class Discord { -public: - static void Initialize(const std::string joinScriptUrl); - static void Cleanup(); -private: - static void Update(); -}; - +#ifdef PLAYER + +#pragma once + +#include +#include +#include + +#include "Configuration.hpp" + +#include "Hooks/CRoblox.hpp" + + +class Discord { +public: + static void Initialize(const std::string joinScriptUrl); + static void Cleanup(); +private: + static void Update(); +}; + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Helpers.h b/Kiseki.Patcher/Header/Helpers.hpp similarity index 95% rename from Kiseki.Patcher/Include/Helpers.h rename to Kiseki.Patcher/Header/Helpers.hpp index 85371cd..1b94d56 100644 --- a/Kiseki.Patcher/Include/Helpers.h +++ b/Kiseki.Patcher/Header/Helpers.hpp @@ -1,26 +1,26 @@ -#pragma once - -#include - -#include "Configuration.h" - -class Helpers -{ -public: - static const std::vector publicKey; - static const std::vector allowedWildcardDomains; - static const std::vector allowedDomains; - static const std::vector allowedSchemes; - static const std::vector allowedEmbeddedSchemes; - static bool isASCII(const std::string& s); - static std::string toLower(std::string s); - static std::vector base64Decode(const std::string_view data); - static std::map parseQueryString(const std::string query); - static std::string joinQueryString(const std::map query); - static std::string ws2s(const std::wstring widestring); - static size_t write(char* contents, size_t size, size_t memory, void* pointer); - static std::string getModulePath(); - static std::string getISOTimestamp(); - static std::pair> parseURL(const std::string url); - static std::pair httpGet(const std::string url); +#pragma once + +#include + +#include "Configuration.hpp" + +class Helpers +{ +public: + static const std::vector publicKey; + static const std::vector allowedWildcardDomains; + static const std::vector allowedDomains; + static const std::vector allowedSchemes; + static const std::vector allowedEmbeddedSchemes; + static bool isASCII(const std::string& s); + static std::string toLower(std::string s); + static std::vector base64Decode(const std::string_view data); + static std::map parseQueryString(const std::string query); + static std::string joinQueryString(const std::map query); + static std::string ws2s(const std::wstring widestring); + static size_t write(char* contents, size_t size, size_t memory, void* pointer); + static std::string getModulePath(); + static std::string getISOTimestamp(); + static std::pair> parseURL(const std::string url); + static std::pair httpGet(const std::string url); }; \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/CRoblox.h b/Kiseki.Patcher/Header/Hooks/CRoblox.hpp similarity index 91% rename from Kiseki.Patcher/Include/Hooks/CRoblox.h rename to Kiseki.Patcher/Header/Hooks/CRoblox.hpp index 6f2decc..763ade8 100644 --- a/Kiseki.Patcher/Include/Hooks/CRoblox.h +++ b/Kiseki.Patcher/Header/Hooks/CRoblox.hpp @@ -1,47 +1,47 @@ -#pragma once - -#include - -#include "Configuration.h" -#include "Helpers.h" -#include "Discord.h" - -class CWorkspace; - -const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspace, LPCWSTR, VARIANTARG, VARIANTARG, VARIANTARG, VARIANTARG, LPVOID))ADDRESS_CWORKSPACE__EXECURLSCRIPT; - -struct CRobloxDoc -{ - void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE]; - CWorkspace* workspace; -}; - -struct CApp; - -const auto CApp__RobloxAuthenticate = (void* (__thiscall*)(CApp * _this, LPVOID, LPCWSTR, LPCWSTR))ADDRESS_CAPP__ROBLOXAUTHENTICATE; - -struct CRobloxApp; - -const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp * _this))ADDRESS_CROBLOXAPP__CREATEDOCUMENT; - -struct CCommandLineInfo -{ - void* padding1[3]; - BOOL m_bRunAutomated; -}; - -class CRobloxCommandLineInfo : public CCommandLineInfo {}; - -const auto CCommandLineInfo__ParseLast = (void(__thiscall*)(CCommandLineInfo * _this, BOOL bLast))ADDRESS_CCOMMANDLINEINFO__PARSELAST; - -typedef BOOL(__thiscall* CRobloxApp__InitInstance_t)(CRobloxApp* _this); -typedef void(__thiscall* CRobloxCommandLineInfo__ParseParam_t)(CRobloxCommandLineInfo* _this, const char* pszParam, BOOL bFlag, BOOL bLast); - -BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this); -void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast); - -extern CRobloxApp__InitInstance_t CRobloxApp__InitInstance; -extern CRobloxCommandLineInfo__ParseParam_t CRobloxCommandLineInfo__ParseParam; - -extern std::wstring jobId; +#pragma once + +#include + +#include "Configuration.hpp" +#include "Helpers.hpp" +#include "Discord.hpp" + +class CWorkspace; + +const auto CWorkspace__ExecUrlScript = (HRESULT(__stdcall*)(CWorkspace * workspace, LPCWSTR, VARIANTARG, VARIANTARG, VARIANTARG, VARIANTARG, LPVOID))ADDRESS_CWORKSPACE__EXECURLSCRIPT; + +struct CRobloxDoc +{ + void* padding1[CLASSPADDING_CROBLOXDOC__WORKSPACE]; + CWorkspace* workspace; +}; + +struct CApp; + +const auto CApp__RobloxAuthenticate = (void* (__thiscall*)(CApp * _this, LPVOID, LPCWSTR, LPCWSTR))ADDRESS_CAPP__ROBLOXAUTHENTICATE; + +struct CRobloxApp; + +const auto CRobloxApp__CreateDocument = (CRobloxDoc * (__thiscall*)(CRobloxApp * _this))ADDRESS_CROBLOXAPP__CREATEDOCUMENT; + +struct CCommandLineInfo +{ + void* padding1[3]; + BOOL m_bRunAutomated; +}; + +class CRobloxCommandLineInfo : public CCommandLineInfo {}; + +const auto CCommandLineInfo__ParseLast = (void(__thiscall*)(CCommandLineInfo * _this, BOOL bLast))ADDRESS_CCOMMANDLINEINFO__PARSELAST; + +typedef BOOL(__thiscall* CRobloxApp__InitInstance_t)(CRobloxApp* _this); +typedef void(__thiscall* CRobloxCommandLineInfo__ParseParam_t)(CRobloxCommandLineInfo* _this, const char* pszParam, BOOL bFlag, BOOL bLast); + +BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this); +void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast); + +extern CRobloxApp__InitInstance_t CRobloxApp__InitInstance; +extern CRobloxCommandLineInfo__ParseParam_t CRobloxCommandLineInfo__ParseParam; + +extern std::wstring jobId; extern bool hasJobId; \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/Context.h b/Kiseki.Patcher/Header/Hooks/Context.hpp similarity index 90% rename from Kiseki.Patcher/Include/Hooks/Context.h rename to Kiseki.Patcher/Header/Hooks/Context.hpp index f17c04c..4a1ef5f 100644 --- a/Kiseki.Patcher/Include/Hooks/Context.h +++ b/Kiseki.Patcher/Header/Hooks/Context.hpp @@ -1,13 +1,13 @@ -#pragma once - -#include "Configuration.h" - -#ifdef _DEBUG - -const auto Context__isInRole = (bool(__cdecl*)(int identity, int permission))ADDRESS_CONTEXT__ISINROLE; - -typedef void (__thiscall* Context__requirePermission_t)(void* _this, int permission, const char* operation); -void __fastcall Context__requirePermission_hook(void* _this, void*, int permission, const char* operation); -extern Context__requirePermission_t Context__requirePermission; - +#ifdef _DEBUG + +#pragma once + +#include "Configuration.hpp" + +const auto Context__isInRole = (bool(__cdecl*)(int identity, int permission))ADDRESS_CONTEXT__ISINROLE; + +typedef void (__thiscall* Context__requirePermission_t)(void* _this, int permission, const char* operation); +void __fastcall Context__requirePermission_hook(void* _this, void*, int permission, const char* operation); +extern Context__requirePermission_t Context__requirePermission; + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/Crypt.h b/Kiseki.Patcher/Header/Hooks/Crypt.hpp similarity index 93% rename from Kiseki.Patcher/Include/Hooks/Crypt.h rename to Kiseki.Patcher/Header/Hooks/Crypt.hpp index 4218420..e1c718f 100644 --- a/Kiseki.Patcher/Include/Hooks/Crypt.h +++ b/Kiseki.Patcher/Header/Hooks/Crypt.hpp @@ -1,20 +1,20 @@ -#pragma once - -#include - -#include "Configuration.h" - -typedef void(__thiscall* Crypt__verifySignatureBase64_t)(HCRYPTPROV* _this, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15); -void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15); -extern Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64; - -class Crypt -{ - HCRYPTPROV context; - HCRYPTKEY key; - -public: - Crypt(); - ~Crypt(); - bool verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm); +#pragma once + +#include + +#include "Configuration.hpp" + +typedef void(__thiscall* Crypt__verifySignatureBase64_t)(HCRYPTPROV* _this, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15); +void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15); +extern Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64; + +class Crypt +{ + HCRYPTPROV context; + HCRYPTKEY key; + +public: + Crypt(); + ~Crypt(); + bool verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm); }; \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/DataModel.h b/Kiseki.Patcher/Header/Hooks/DataModel.hpp similarity index 76% rename from Kiseki.Patcher/Include/Hooks/DataModel.h rename to Kiseki.Patcher/Header/Hooks/DataModel.hpp index 27f068b..cd7b639 100644 --- a/Kiseki.Patcher/Include/Hooks/DataModel.h +++ b/Kiseki.Patcher/Header/Hooks/DataModel.hpp @@ -1,20 +1,20 @@ -#pragma once - -#include "Helpers.h" -#include "Configuration.h" - -#include "Hooks/CRoblox.h" - -#ifdef SERVER - -struct DataModel -{ - void* padding1[CLASSPADDING_DATAMODEL__JOBID]; - std::string jobId; -}; - -typedef INT(__thiscall* DataModel__getJobId_t)(DataModel* _this, int a2); -int __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2); -extern DataModel__getJobId_t DataModel__getJobId; - +#ifdef SERVER + +#pragma once + +#include "Hooks/CRoblox.hpp" + +#include "Configuration.hpp" +#include "Helpers.hpp" + +struct DataModel +{ + void* padding1[CLASSPADDING_DATAMODEL__JOBID]; + std::string jobId; +}; + +typedef INT(__thiscall* DataModel__getJobId_t)(DataModel* _this, int a2); +int __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2); +extern DataModel__getJobId_t DataModel__getJobId; + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/Http.h b/Kiseki.Patcher/Header/Hooks/Http.hpp similarity index 81% rename from Kiseki.Patcher/Include/Hooks/Http.h rename to Kiseki.Patcher/Header/Hooks/Http.hpp index 4774668..f9175f8 100644 --- a/Kiseki.Patcher/Include/Hooks/Http.h +++ b/Kiseki.Patcher/Header/Hooks/Http.hpp @@ -1,30 +1,28 @@ -#pragma once - -#include -#include - -#include "Configuration.h" -#include "Helpers.h" - -#ifdef SERVER -#include "Hooks/StandardOut.h" -#endif - -struct Http -{ -#if PADDING_STRUCT != 0 - void* padding1[1]; -#endif - std::string alternateUrl; - void* padding2[3 + PADDING_STRUCT]; - std::string url; -}; - -typedef void (__thiscall* Http__httpGetPostWinInet_t)(Http* _this, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6); -typedef bool(__thiscall* Http__trustCheck_t)(const char* url); - -void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6); -bool __fastcall Http__trustCheck_hook(const char* url); - -extern Http__httpGetPostWinInet_t Http__httpGetPostWinInet; +#include +#include + +#ifdef SERVER +#include "Hooks/StandardOut.hpp" +#endif + +#include "Configuration.hpp" +#include "Helpers.hpp" + +struct Http +{ +#if PADDING_STRUCT != 0 + void* padding1[1]; +#endif + std::string alternateUrl; + void* padding2[3 + PADDING_STRUCT]; + std::string url; +}; + +typedef void (__thiscall* Http__httpGetPostWinInet_t)(Http* _this, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6); +typedef bool(__thiscall* Http__trustCheck_t)(const char* url); + +void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6); +bool __fastcall Http__trustCheck_hook(const char* url); + +extern Http__httpGetPostWinInet_t Http__httpGetPostWinInet; extern Http__trustCheck_t Http__trustCheck; \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/ServerReplicator.h b/Kiseki.Patcher/Header/Hooks/ServerReplicator.hpp similarity index 91% rename from Kiseki.Patcher/Include/Hooks/ServerReplicator.h rename to Kiseki.Patcher/Header/Hooks/ServerReplicator.hpp index b289bb3..52df50b 100644 --- a/Kiseki.Patcher/Include/Hooks/ServerReplicator.h +++ b/Kiseki.Patcher/Header/Hooks/ServerReplicator.hpp @@ -1,33 +1,33 @@ -#pragma once - -#include "Configuration.h" - -#if defined(SERVER) - -struct Packet -{ - void* padding1[7]; - unsigned int length; - void* padding2[1]; - unsigned char* data; -}; - -struct RakPeerInterface {}; - -struct ServerReplicator -{ - void* padding1[1869]; // offset of 0 -> 7476 - bool padding2; // offset of 7476 -> 7477 - bool isAuthenticated; // offset of 7477 -> 7478 -}; - -typedef void(__thiscall* ServerReplicator__sendTop_t)(ServerReplicator* _this, RakPeerInterface* peer); -typedef void(__thiscall* ServerReplicator__processTicket_t)(ServerReplicator* _this, Packet* packet); - -void __fastcall ServerReplicator__sendTop_hook(ServerReplicator* _this, void*, RakPeerInterface* peer); -void __fastcall ServerReplicator__processTicket_hook(ServerReplicator* _this, void*, Packet* packet); - -extern ServerReplicator__sendTop_t ServerReplicator__sendTop; -extern ServerReplicator__processTicket_t ServerReplicator__processTicket; - +#ifdef SERVER + +#pragma once + +#include "Configuration.hpp" + +struct Packet +{ + void* padding1[7]; + unsigned int length; + void* padding2[1]; + unsigned char* data; +}; + +struct RakPeerInterface {}; + +struct ServerReplicator +{ + void* padding1[1869]; // offset of 0 -> 7476 + bool padding2; // offset of 7476 -> 7477 + bool isAuthenticated; // offset of 7477 -> 7478 +}; + +typedef void(__thiscall* ServerReplicator__sendTop_t)(ServerReplicator* _this, RakPeerInterface* peer); +typedef void(__thiscall* ServerReplicator__processTicket_t)(ServerReplicator* _this, Packet* packet); + +void __fastcall ServerReplicator__sendTop_hook(ServerReplicator* _this, void*, RakPeerInterface* peer); +void __fastcall ServerReplicator__processTicket_hook(ServerReplicator* _this, void*, Packet* packet); + +extern ServerReplicator__sendTop_t ServerReplicator__sendTop; +extern ServerReplicator__processTicket_t ServerReplicator__processTicket; + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Hooks/StandardOut.h b/Kiseki.Patcher/Header/Hooks/StandardOut.hpp similarity index 70% rename from Kiseki.Patcher/Include/Hooks/StandardOut.h rename to Kiseki.Patcher/Header/Hooks/StandardOut.hpp index 059131b..de9bf59 100644 --- a/Kiseki.Patcher/Include/Hooks/StandardOut.h +++ b/Kiseki.Patcher/Header/Hooks/StandardOut.hpp @@ -1,14 +1,14 @@ -#pragma once - -#include "Configuration.h" -#include "Patches.h" -#include "Helpers.h" -#include "Server.h" - -#ifdef SERVER - -typedef void(__thiscall* StandardOut__print_t)(int _this, int type, std::string* message); -void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message); -extern StandardOut__print_t StandardOut__print; - +#ifdef SERVER + +#pragma once + +#include "Configuration.hpp" +#include "Helpers.hpp" +#include "Patches.hpp" +#include "Server.hpp" + +typedef void(__thiscall* StandardOut__print_t)(int _this, int type, std::string* message); +void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message); +extern StandardOut__print_t StandardOut__print; + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Patches.h b/Kiseki.Patcher/Header/Patcher.hpp similarity index 63% rename from Kiseki.Patcher/Include/Patches.h rename to Kiseki.Patcher/Header/Patcher.hpp index de56a8f..95a3cd4 100644 --- a/Kiseki.Patcher/Include/Patches.h +++ b/Kiseki.Patcher/Header/Patcher.hpp @@ -1,16 +1,16 @@ -#pragma once - -#include - -namespace Patches -{ - typedef std::pair Patch; - - extern std::vector patchList; - - LONG Apply(); -} - -#define START_PATCH_LIST() std::vector Patches::patchList = { -#define ADD_PATCH(a, b) { (void**)&(a), (b) }, +#pragma once + +#include + +namespace Patcher +{ + typedef std::pair Patch; + + extern std::vector patchList; + + LONG Apply(); +} + +#define START_PATCH_LIST() std::vector Patcher::patchList = { +#define ADD_PATCH(a, b) { (void**)&(a), (b) }, #define END_PATCH_LIST() }; \ No newline at end of file diff --git a/Kiseki.Patcher/Include/Server.h b/Kiseki.Patcher/Header/Server.hpp similarity index 84% rename from Kiseki.Patcher/Include/Server.h rename to Kiseki.Patcher/Header/Server.hpp index 0511905..3ba2331 100644 --- a/Kiseki.Patcher/Include/Server.h +++ b/Kiseki.Patcher/Header/Server.hpp @@ -1,42 +1,42 @@ -#pragma once - -#include "Configuration.h" -#include "Helpers.h" - -#include "Hooks/StandardOut.h" - -#ifdef SERVER - -enum class RequestType { - POST, - GET -}; - -enum class LogSeverity { - Information = RBX__MESSAGE_INFO, - Output = RBX__MESSAGE_OUTPUT, - Warning = RBX__MESSAGE_WARNING, - Error = RBX__MESSAGE_ERROR -}; - -class Server { -public: - static HANDLE Handle; - - static void Initialize(const std::wstring jobId); - static void Cleanup(); - - struct Log - { - static void Http(const RequestType type, const std::string message); - static void Output(const LogSeverity severity, const std::string message); - }; -private: - static std::string HttpLogPath; - static std::string OutputLogPath; - - static std::ofstream HttpLog; - static std::ofstream OutputLog; -}; - +#ifdef SERVER + +#pragma once + +#include "Configuration.hpp" +#include "Helpers.hpp" + +#include "Hooks/StandardOut.hpp" + +enum class RequestType { + POST, + GET +}; + +enum class LogSeverity { + Information = RBX__MESSAGE_INFO, + Output = RBX__MESSAGE_OUTPUT, + Warning = RBX__MESSAGE_WARNING, + Error = RBX__MESSAGE_ERROR +}; + +class Server { +public: + static HANDLE Handle; + + static void Initialize(const std::wstring jobId); + static void Cleanup(); + + struct Log + { + static void Http(const RequestType type, const std::string message); + static void Output(const LogSeverity severity, const std::string message); + }; +private: + static std::string HttpLogPath; + static std::string OutputLogPath; + + static std::ofstream HttpLog; + static std::ofstream OutputLog; +}; + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Include/framework.h b/Kiseki.Patcher/Include/framework.h deleted file mode 100644 index a9744f8..0000000 --- a/Kiseki.Patcher/Include/framework.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers -// Windows Header Files -#include diff --git a/Kiseki.Patcher/Include/pch.h b/Kiseki.Patcher/Include/pch.h deleted file mode 100644 index bb4251d..0000000 --- a/Kiseki.Patcher/Include/pch.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fs = std::filesystem; \ No newline at end of file diff --git a/Kiseki.Patcher/Include/resource.h b/Kiseki.Patcher/Include/resource.h deleted file mode 100644 index aff5a6d..0000000 --- a/Kiseki.Patcher/Include/resource.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by PolygonDLL.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/Kiseki.Patcher/Kiseki.Patcher.rc b/Kiseki.Patcher/Kiseki.Patcher.rc deleted file mode 100644 index eb9b845..0000000 --- a/Kiseki.Patcher/Kiseki.Patcher.rc +++ /dev/null @@ -1,100 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "Include/resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "winres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (United States) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""winres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,0,0 - PRODUCTVERSION 1,0,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x40004L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "Kiseki" - VALUE "FileDescription", "Client Functionality Library" - VALUE "FileVersion", "1.0.0.0" - VALUE "InternalName", "Kiseki.Patcher.dll" - VALUE "LegalCopyright", "Copyright (C) Kiseki 2022-2023" - VALUE "OriginalFilename", "Kiseki.Patcher.dll" - VALUE "ProductName", "Client Functionality Library" - VALUE "ProductVersion", "1.0.0.0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (United States) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/Kiseki.Patcher/Kiseki.Patcher.vcxproj b/Kiseki.Patcher/Kiseki.Patcher.vcxproj deleted file mode 100644 index 23f571a..0000000 --- a/Kiseki.Patcher/Kiseki.Patcher.vcxproj +++ /dev/null @@ -1,163 +0,0 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - 16.0 - Win32Proj - {9d232642-fb2f-43dc-b0ac-c56e3b691233} - Kiseki.Patcher - 10.0 - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - true - true - $(SolutionDir)bin\$(Configuration)\ - obj\$(Configuration)\ - - - false - true - $(SolutionDir)bin\$(Configuration)\ - obj\$(Configuration)\ - - - true - - - $(SolutionDir)packages - x86-windows-static-md - - - $(SolutionDir)packages - x86-windows-static-md - - - - Level3 - true - WIN32;_DEBUG;KISEKIPATCHER_EXPORTS;_WINDOWS;_USRDLL;$(CIDefinitions);%(PreprocessorDefinitions) - true - Use - pch.h - $(ProjectDir)Include;%(AdditionalIncludeDirectories) - stdcpp17 - - - Windows - true - false - %(AdditionalLibraryDirectories) - detours.lib;crypt32.lib;libcurl-d.lib;WS2_32.lib;zlibd.lib;%(AdditionalDependencies) - - - LIBCMTD - $(OutDir)$(TargetName)$(TargetExt) - - - - - Level3 - - - false - true - WIN32;NDEBUG;KISEKIPATCHER_EXPORTS;_WINDOWS;_USRDLL;$(CIDefinitions);%(PreprocessorDefinitions) - true - Use - pch.h - $(ProjectDir)Include;%(AdditionalIncludeDirectories) - Disabled - false - stdcpp17 - - - Windows - true - true - true - false - %(AdditionalLibraryDirectories) - detours.lib;crypt32.lib;libcurl.lib;WS2_32.lib;zlib.lib;%(AdditionalDependencies) - - - LIBCMT - Default - $(OutDir)$(TargetName)$(TargetExt) - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Kiseki.Patcher/Kiseki.Patcher.vcxproj.filters b/Kiseki.Patcher/Kiseki.Patcher.vcxproj.filters deleted file mode 100644 index 7c8b41f..0000000 --- a/Kiseki.Patcher/Kiseki.Patcher.vcxproj.filters +++ /dev/null @@ -1,113 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} - rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms - - - {e1630ddd-f689-40cc-9f7b-506bcf8aca31} - - - {51130969-bcf1-4ae5-b838-7f4fb658856e} - - - - - Header Files - - - Header Files - - - Header Files - - - Header Files\Hooks - - - Header Files\Hooks - - - Header Files\Hooks - - - Header Files\Hooks - - - Header Files\Hooks - - - Header Files\Hooks - - - Header Files - - - Header Files - - - Header Files - - - Header Files\Hooks - - - Header Files - - - - - Source Files - - - Source Files - - - Source Files - - - Source Files - - - Source Files\Hooks - - - Source Files\Hooks - - - Source Files\Hooks - - - Source Files\Hooks - - - Source Files\Hooks - - - Source Files\Hooks - - - Source Files - - - Source Files - - - Source Files\Hooks - - - - - Resource Files - - - \ No newline at end of file diff --git a/Kiseki.Patcher/Resource/Information.h b/Kiseki.Patcher/Resource/Information.h new file mode 100644 index 0000000..48bf3fa --- /dev/null +++ b/Kiseki.Patcher/Resource/Information.h @@ -0,0 +1,12 @@ +#pragma once + +#define VERSION_MAJOR_MINOR_STR "1.0" +#define VERSION_MAJOR_MINOR_PATCH_STR "1.0.0" +#define VERSION_FULL_STR "1.0.0.0" +#define VERSION_RESOURCE 1, 0, 0, 0 +#define VERSION_RESOURCE_STR VERSION_FULL_STR "\0" + +#define APP_NAME "Kiseki.Patcher" +#define APP_DESCRIPTION "Client Functionality Library" +#define APP_ORGANIZATION "Kiseki" +#define APP_COPYRIGHT "Copyright (c) Kiseki 2023" \ No newline at end of file diff --git a/Kiseki.Patcher/Resource/Script.rc b/Kiseki.Patcher/Resource/Script.rc new file mode 100644 index 0000000..6790b81 --- /dev/null +++ b/Kiseki.Patcher/Resource/Script.rc @@ -0,0 +1,36 @@ +#include "Information.h" + +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_RESOURCE + PRODUCTVERSION VERSION_RESOURCE + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", APP_ORGANIZATION "\0" + VALUE "FileDescription", APP_DESCRIPTION "\0" + VALUE "FileVersion", VERSION_FULL_STR "\0" + VALUE "LegalCopyright", APP_COPYRIGHT "\0" + VALUE "ProductName", APP_NAME "\0" + VALUE "ProductVersion", VERSION_FULL_STR "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1200 + END +END \ No newline at end of file diff --git a/Kiseki.Patcher/Discord.cpp b/Kiseki.Patcher/Source/Discord.cpp similarity index 83% rename from Kiseki.Patcher/Discord.cpp rename to Kiseki.Patcher/Source/Discord.cpp index 0fe6f2f..df4ef3e 100644 --- a/Kiseki.Patcher/Discord.cpp +++ b/Kiseki.Patcher/Source/Discord.cpp @@ -1,124 +1,122 @@ -#include "pch.h" - -#include "Discord.h" - -#ifdef PLAYER - -bool isRunning = false; -std::string username; -int placeId; - -void Discord::Initialize(const std::string joinScriptUrl) -{ - std::pair> parsed = Helpers::parseURL(joinScriptUrl); - - if (!parsed.first) - { - return; - } - - if (parsed.second["query"].empty()) - { - return; - } - - std::map query = Helpers::parseQueryString(parsed.second["query"]); - - if (query.find("ticket") == query.end()) - { - return; - } - - if (query.find("discord") == query.end()) - { - return; - } - - if (query["ticket"].empty()) - { - return; - } - - if (query["discord"] == "0") - { - return; - } - - // Get the username and placeId - std::pair response = Helpers::httpGet(BASE_URL + std::string("/api/places/information?ticket=" + query["ticket"])); - if (!response.first) - { - return; - } - - rapidjson::Document document; - document.Parse(response.second.c_str()); - - if (document.HasParseError() || !document.HasMember("username") || !document.HasMember("placeId")) - { - return; - } - - username = document["username"].GetString(); - placeId = document["placeId"].GetInt(); - - Discord::Update(); - - // Run the updater - std::thread updater(Discord::Update); - updater.join(); -} - -void Discord::Update() -{ - isRunning = true; - - while (isRunning) - { - std::this_thread::sleep_for(std::chrono::milliseconds(60 * 1000)); - - std::string title = ""; - int size = 0; - int max = 0; - - // Get title, size, and max - std::pair response = Helpers::httpGet(BASE_URL + std::string("/api/places/information?id=" + placeId)); - if (!response.first) - { - return; - } - - rapidjson::Document document; - document.Parse(response.second.c_str()); - - if (document.HasParseError() || !document.HasMember("title") || !document.HasMember("size") || !document.HasMember("max")) - { - return; - } - - title = document["title"].GetString(); - size = document["size"].GetInt(); - max = document["max"].GetInt(); - - DiscordRichPresence presence; - memset(&presence, 0, sizeof(presence)); - - presence.largeImageText = username.c_str(); - presence.largeImageKey = "logo"; - presence.smallImageText = "2011"; - presence.smallImageKey = "2011"; - - presence.details = title.c_str(); - presence.state = "In a game"; - presence.partySize = size; - presence.partyMax = max; - } -} - -void Discord::Cleanup() -{ - isRunning = false; - Discord_Shutdown(); -} - +#ifdef PLAYER + +#include "Discord.hpp" + +bool isRunning = false; +std::string username; +int placeId; + +void Discord::Initialize(const std::string joinScriptUrl) +{ + std::pair> parsed = Helpers::parseURL(joinScriptUrl); + + if (!parsed.first) + { + return; + } + + if (parsed.second["query"].empty()) + { + return; + } + + std::map query = Helpers::parseQueryString(parsed.second["query"]); + + if (query.find("ticket") == query.end()) + { + return; + } + + if (query.find("discord") == query.end()) + { + return; + } + + if (query["ticket"].empty()) + { + return; + } + + if (query["discord"] == "0") + { + return; + } + + // Get the username and placeId + std::pair response = Helpers::httpGet(Helpers::getBaseUrl() + std::string("/api/places/information?ticket=" + query["ticket"])); + if (!response.first) + { + return; + } + + rapidjson::Document document; + document.Parse(response.second.c_str()); + + if (document.HasParseError() || !document.HasMember("username") || !document.HasMember("placeId")) + { + return; + } + + username = document["username"].GetString(); + placeId = document["placeId"].GetInt(); + + Discord::Update(); + + // Run the updater + std::thread updater(Discord::Update); + updater.join(); +} + +void Discord::Update() +{ + isRunning = true; + + while (isRunning) + { + std::this_thread::sleep_for(std::chrono::milliseconds(60 * 1000)); + + std::string title = ""; + int size = 0; + int max = 0; + + // Get title, size, and max + std::pair response = Helpers::httpGet(Helpers::getBaseUrl() + std::string("/api/places/information?id=" + placeId)); + if (!response.first) + { + return; + } + + rapidjson::Document document; + document.Parse(response.second.c_str()); + + if (document.HasParseError() || !document.HasMember("title") || !document.HasMember("size") || !document.HasMember("max")) + { + return; + } + + title = document["title"].GetString(); + size = document["size"].GetInt(); + max = document["max"].GetInt(); + + DiscordRichPresence presence; + memset(&presence, 0, sizeof(presence)); + + presence.largeImageText = username.c_str(); + presence.largeImageKey = "logo"; + presence.smallImageText = "2011"; + presence.smallImageKey = "2011"; + + presence.details = title.c_str(); + presence.state = "In a game"; + presence.partySize = size; + presence.partyMax = max; + } +} + +void Discord::Cleanup() +{ + isRunning = false; + Discord_Shutdown(); +} + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Helpers.cpp b/Kiseki.Patcher/Source/Helpers.cpp similarity index 95% rename from Kiseki.Patcher/Helpers.cpp rename to Kiseki.Patcher/Source/Helpers.cpp index b5474ac..e906eca 100644 --- a/Kiseki.Patcher/Helpers.cpp +++ b/Kiseki.Patcher/Source/Helpers.cpp @@ -1,211 +1,209 @@ -#include "pch.h" - -#include "Helpers.h" - -#ifdef _DEBUG -const std::vector Helpers::publicKey = Helpers::base64Decode(PUBLIC_KEY); -#else -const std::vector Helpers::publicKey { PUBLIC_KEY }; -#endif - -const std::vector Helpers::allowedWildcardDomains { ALLOWED_WILDCARD_DOMAINS }; -const std::vector Helpers::allowedDomains { ALLOWED_DOMAINS }; -const std::vector Helpers::allowedSchemes { ALLOWED_SCHEMES }; -const std::vector Helpers::allowedEmbeddedSchemes { ALLOWED_EMBEDDED_SCHEMES }; - -// https://stackoverflow.com/questions/48212992/how-to-find-out-if-there-is-any-non-ascii-character-in-a-string-with-a-file-path -bool Helpers::isASCII(const std::string& s) -{ - return !std::any_of(s.begin(), s.end(), [](char c) { - return static_cast(c) > 127; - }); -} - -// https://stackoverflow.com/questions/313970/how-to-convert-an-instance-of-stdstring-to-lower-case -std::string Helpers::toLower(std::string s) -{ - std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); }); - return s; -} - -// https://stackoverflow.com/a/44562527 -std::vector Helpers::base64Decode(const std::string_view data) -{ - // table from '+' to 'z' - const uint8_t lookup[] = { - 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, - 255, 0, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 - }; - - static_assert(sizeof(lookup) == 'z' - '+' + 1); - - std::vector out; - int val = 0, valb = -8; - for (uint8_t c : data) - { - if (c < '+' || c > 'z') - { - break; - } - - c -= '+'; - if (lookup[c] >= 64) - { - break; - } - - val = (val << 6) + lookup[c]; - valb += 6; - - if (valb >= 0) - { - out.push_back(char((val >> valb) & 0xFF)); - valb -= 8; - } - } - - return out; -} - -// https://stackoverflow.com/a/28269049 -std::map Helpers::parseQueryString(const std::string query) -{ - std::istringstream stream(query); - std::map parsed; - std::string pair, key, value; - - while (std::getline(stream, pair, '&')) // split each term - { - std::istringstream term(pair); - - if (std::getline(std::getline(term, key, '='), value)) - { - parsed[key] = value; - } - } - - return parsed; -} - -std::string Helpers::joinQueryString(const std::map query) -{ - std::stringstream stream; - stream << "?"; - - for (auto const& pair : query) - { - stream << pair.first << "=" << pair.second << "&"; - } - - std::string result = stream.str(); - result.pop_back(); // remove ending ampersand - - return result; -} - -// https://stackoverflow.com/a/12097772 -std::string Helpers::ws2s(const std::wstring widestring) -{ - std::string string; - std::transform(widestring.begin(), widestring.end(), std::back_inserter(string), [](wchar_t c) { - return (char)c; - }); - - return string; -} - -size_t Helpers::write(char* contents, size_t size, size_t memory, void* pointer) -{ - ((std::string*)pointer)->append((char*)contents, size * memory); - return size * memory; -} - -std::string Helpers::getModulePath() -{ - char buffer[MAX_PATH]; - GetModuleFileNameA(NULL, buffer, MAX_PATH); - - return std::string(buffer); -} - -std::string Helpers::getISOTimestamp() -{ - time_t now = time(0); - struct tm now_gmt {}; - - gmtime_s(&now_gmt, &now); - - char buffer[20]; - strftime(buffer, sizeof(buffer), "%FT%TZ", &now_gmt); - - return std::string(buffer); -} - -std::pair> Helpers::parseURL(const std::string url) -{ - CURLU* curl = curl_url(); - CURLUcode result = curl_url_set(curl, CURLUPART_URL, url.c_str(), 0); - - std::map map; - bool success = false; - - if (result == CURLE_OK) - { - success = true; - - char* path; - char* host; - char* query; - - curl_url_get(curl, CURLUPART_PATH, &path, 0); - curl_url_get(curl, CURLUPART_HOST, &host, 0); - curl_url_get(curl, CURLUPART_QUERY, &query, 0); - curl_url_cleanup(curl); - - map = { - { "path", std::string(path) }, - { "host", std::string(host) }, - { "query", std::string(query) } - }; - - curl_free(path); - curl_free(host); - curl_free(query); - } - - return std::make_pair(success, map); -} - -std::pair Helpers::httpGet(const std::string url) -{ - bool success = false; - std::string data; - - CURL* curl = curl_easy_init(); - CURLcode result; - long response = 0; - - if (!curl) - { - return std::make_pair(false, ""); - } - - curl_easy_setopt(curl, CURLOPT_URL, url); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); - - result = curl_easy_perform(curl); - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); - - curl_easy_cleanup(curl); - - if (result != CURLE_OK || response != 200) - { - return std::make_pair(false, ""); - } - - return std::make_pair(true, data); -} +#include "Helpers.hpp" + +#ifdef _DEBUG +const std::vector Helpers::publicKey = Helpers::base64Decode(PUBLIC_KEY); +#else +const std::vector Helpers::publicKey { PUBLIC_KEY }; +#endif + +const std::vector Helpers::allowedWildcardDomains { ALLOWED_WILDCARD_DOMAINS }; +const std::vector Helpers::allowedDomains { ALLOWED_DOMAINS }; +const std::vector Helpers::allowedSchemes { ALLOWED_SCHEMES }; +const std::vector Helpers::allowedEmbeddedSchemes { ALLOWED_EMBEDDED_SCHEMES }; + +// https://stackoverflow.com/questions/48212992/how-to-find-out-if-there-is-any-non-ascii-character-in-a-string-with-a-file-path +bool Helpers::isASCII(const std::string& s) +{ + return !std::any_of(s.begin(), s.end(), [](char c) { + return static_cast(c) > 127; + }); +} + +// https://stackoverflow.com/questions/313970/how-to-convert-an-instance-of-stdstring-to-lower-case +std::string Helpers::toLower(std::string s) +{ + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return std::tolower(c); }); + return s; +} + +// https://stackoverflow.com/a/44562527 +std::vector Helpers::base64Decode(const std::string_view data) +{ + // table from '+' to 'z' + const uint8_t lookup[] = { + 62, 255, 62, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, + 255, 0, 255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 255, 255, 255, 255, 63, 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 + }; + + static_assert(sizeof(lookup) == 'z' - '+' + 1); + + std::vector out; + int val = 0, valb = -8; + for (uint8_t c : data) + { + if (c < '+' || c > 'z') + { + break; + } + + c -= '+'; + if (lookup[c] >= 64) + { + break; + } + + val = (val << 6) + lookup[c]; + valb += 6; + + if (valb >= 0) + { + out.push_back(char((val >> valb) & 0xFF)); + valb -= 8; + } + } + + return out; +} + +// https://stackoverflow.com/a/28269049 +std::map Helpers::parseQueryString(const std::string query) +{ + std::istringstream stream(query); + std::map parsed; + std::string pair, key, value; + + while (std::getline(stream, pair, '&')) // split each term + { + std::istringstream term(pair); + + if (std::getline(std::getline(term, key, '='), value)) + { + parsed[key] = value; + } + } + + return parsed; +} + +std::string Helpers::joinQueryString(const std::map query) +{ + std::stringstream stream; + stream << "?"; + + for (auto const& pair : query) + { + stream << pair.first << "=" << pair.second << "&"; + } + + std::string result = stream.str(); + result.pop_back(); // remove ending ampersand + + return result; +} + +// https://stackoverflow.com/a/12097772 +std::string Helpers::ws2s(const std::wstring widestring) +{ + std::string string; + std::transform(widestring.begin(), widestring.end(), std::back_inserter(string), [](wchar_t c) { + return (char)c; + }); + + return string; +} + +size_t Helpers::write(char* contents, size_t size, size_t memory, void* pointer) +{ + ((std::string*)pointer)->append((char*)contents, size * memory); + return size * memory; +} + +std::string Helpers::getModulePath() +{ + char buffer[MAX_PATH]; + GetModuleFileNameA(NULL, buffer, MAX_PATH); + + return std::string(buffer); +} + +std::string Helpers::getISOTimestamp() +{ + time_t now = time(0); + struct tm now_gmt {}; + + gmtime_s(&now_gmt, &now); + + char buffer[20]; + strftime(buffer, sizeof(buffer), "%FT%TZ", &now_gmt); + + return std::string(buffer); +} + +std::pair> Helpers::parseURL(const std::string url) +{ + CURLU* curl = curl_url(); + CURLUcode result = curl_url_set(curl, CURLUPART_URL, url.c_str(), 0); + + std::map map; + bool success = false; + + if (result == CURLE_OK) + { + success = true; + + char* path; + char* host; + char* query; + + curl_url_get(curl, CURLUPART_PATH, &path, 0); + curl_url_get(curl, CURLUPART_HOST, &host, 0); + curl_url_get(curl, CURLUPART_QUERY, &query, 0); + curl_url_cleanup(curl); + + map = { + { "path", std::string(path) }, + { "host", std::string(host) }, + { "query", std::string(query) } + }; + + curl_free(path); + curl_free(host); + curl_free(query); + } + + return std::make_pair(success, map); +} + +std::pair Helpers::httpGet(const std::string url) +{ + bool success = false; + std::string data; + + CURL* curl = curl_easy_init(); + CURLcode result; + long response = 0; + + if (!curl) + { + return std::make_pair(false, ""); + } + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, Helpers::write); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data); + + result = curl_easy_perform(curl); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); + + curl_easy_cleanup(curl); + + if (result != CURLE_OK || response != 200) + { + return std::make_pair(false, ""); + } + + return std::make_pair(true, data); +} diff --git a/Kiseki.Patcher/Hooks/CRoblox.cpp b/Kiseki.Patcher/Source/Hooks/CRoblox.cpp similarity index 95% rename from Kiseki.Patcher/Hooks/CRoblox.cpp rename to Kiseki.Patcher/Source/Hooks/CRoblox.cpp index cf3e2c7..b612a62 100644 --- a/Kiseki.Patcher/Hooks/CRoblox.cpp +++ b/Kiseki.Patcher/Source/Hooks/CRoblox.cpp @@ -1,150 +1,148 @@ -#include "pch.h" - -#include "Hooks/CRoblox.h" - -#ifdef SERVER -#include "Server.h" -#endif - -bool hasAuthenticationUrl = false; -bool hasAuthenticationTicket = false; -bool hasJoinScriptUrl = false; -bool hasJobId = false; - -std::wstring authenticationUrl; -std::wstring authenticationTicket; -std::wstring joinScriptUrl; -std::wstring jobId; - -CRobloxApp__InitInstance_t CRobloxApp__InitInstance = (CRobloxApp__InitInstance_t)ADDRESS_CROBLOXAPP__INITINSTANCE; -CRobloxCommandLineInfo__ParseParam_t CRobloxCommandLineInfo__ParseParam = (CRobloxCommandLineInfo__ParseParam_t)ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM; - -BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this) -{ - if (!CRobloxApp__InitInstance(_this)) - { - return FALSE; - } - - CApp* app = reinterpret_cast(CLASSLOCATION_CAPP); - - if (hasAuthenticationUrl && hasAuthenticationTicket && !authenticationUrl.empty() && !authenticationTicket.empty()) - { - CApp__RobloxAuthenticate(app, nullptr, authenticationUrl.c_str(), authenticationTicket.c_str()); - } - - if (hasJoinScriptUrl && !joinScriptUrl.empty()) - { - try - { - CRobloxDoc* document = CRobloxApp__CreateDocument(_this); - CWorkspace__ExecUrlScript(document->workspace, joinScriptUrl.c_str(), VARIANT(), VARIANT(), VARIANT(), VARIANT(), nullptr); - } - catch (std::runtime_error) - { - return FALSE; - } - } - -#ifdef PLAYER - if (!hasAuthenticationUrl || !hasAuthenticationTicket || !hasJoinScriptUrl) - { - return FALSE; - } -#endif - -#ifdef SERVER - if (!hasAuthenticationUrl || !hasAuthenticationTicket || !hasJoinScriptUrl || !hasJobId) - { - ShellExecute(0, 0, L"https://kiseki.lol/games", 0, 0, SW_SHOW); - return FALSE; - } -#endif - - return TRUE; -} - -void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast) -{ - if (hasJoinScriptUrl && joinScriptUrl.empty()) - { - int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); - joinScriptUrl.resize(size); - MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &joinScriptUrl[0], size); - - _this->m_bRunAutomated = TRUE; - - CCommandLineInfo__ParseLast(_this, bLast); - -#ifdef PLAYER - Discord::Initialize(Helpers::ws2s(joinScriptUrl)); -#endif - } - - if (hasAuthenticationUrl && authenticationUrl.empty()) - { - int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); - authenticationUrl.resize(size); - MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &authenticationUrl[0], size); - - CCommandLineInfo__ParseLast(_this, bLast); - return; - } - - if (hasAuthenticationTicket && authenticationTicket.empty()) - { - int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); - authenticationTicket.resize(size); - MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &authenticationTicket[0], size); - - CCommandLineInfo__ParseLast(_this, bLast); - return; - } - -#ifdef SERVER - if (hasJobId && jobId.empty()) - { - int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); - jobId.resize(size); - MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &jobId[0], size); - - CCommandLineInfo__ParseLast(_this, bLast); - return; - } -#endif - - if (bFlag && _stricmp(pszParam, "a") == 0) - { - hasAuthenticationUrl = true; - CCommandLineInfo__ParseLast(_this, bLast); - return; - } - - if (bFlag && _stricmp(pszParam, "t") == 0) - { - hasAuthenticationTicket = true; - CCommandLineInfo__ParseLast(_this, bLast); - return; - } - - if (bFlag && _stricmp(pszParam, "j") == 0) - { - hasJoinScriptUrl = true; - CCommandLineInfo__ParseLast(_this, bLast); - return; - } - -#ifdef SERVER - if (bFlag && _stricmp(pszParam, "jobId") == 0) - { - hasJobId = true; - CCommandLineInfo__ParseLast(_this, bLast); - - Server::Initialize(jobId); - - return; - } -#endif - - CRobloxCommandLineInfo__ParseParam(_this, pszParam, bFlag, bLast); +#include "Hooks/CRoblox.hpp" + +#ifdef SERVER +#include "Server.h" +#endif + +bool hasAuthenticationUrl = false; +bool hasAuthenticationTicket = false; +bool hasJoinScriptUrl = false; +bool hasJobId = false; + +std::wstring authenticationUrl; +std::wstring authenticationTicket; +std::wstring joinScriptUrl; +std::wstring jobId; + +CRobloxApp__InitInstance_t CRobloxApp__InitInstance = (CRobloxApp__InitInstance_t)ADDRESS_CROBLOXAPP__INITINSTANCE; +CRobloxCommandLineInfo__ParseParam_t CRobloxCommandLineInfo__ParseParam = (CRobloxCommandLineInfo__ParseParam_t)ADDRESS_CROBLOXCOMMANDLINEINFO__PARSEPARAM; + +BOOL __fastcall CRobloxApp__InitInstance_hook(CRobloxApp* _this) +{ + if (!CRobloxApp__InitInstance(_this)) + { + return FALSE; + } + + CApp* app = reinterpret_cast(CLASSLOCATION_CAPP); + + if (hasAuthenticationUrl && hasAuthenticationTicket && !authenticationUrl.empty() && !authenticationTicket.empty()) + { + CApp__RobloxAuthenticate(app, nullptr, authenticationUrl.c_str(), authenticationTicket.c_str()); + } + + if (hasJoinScriptUrl && !joinScriptUrl.empty()) + { + try + { + CRobloxDoc* document = CRobloxApp__CreateDocument(_this); + CWorkspace__ExecUrlScript(document->workspace, joinScriptUrl.c_str(), VARIANT(), VARIANT(), VARIANT(), VARIANT(), nullptr); + } + catch (std::runtime_error) + { + return FALSE; + } + } + +#ifdef PLAYER + if (!hasAuthenticationUrl || !hasAuthenticationTicket || !hasJoinScriptUrl) + { + return FALSE; + } +#endif + +#ifdef SERVER + if (!hasAuthenticationUrl || !hasAuthenticationTicket || !hasJoinScriptUrl || !hasJobId) + { + ShellExecute(0, 0, L"https://kiseki.lol/games", 0, 0, SW_SHOW); + return FALSE; + } +#endif + + return TRUE; +} + +void __fastcall CRobloxCommandLineInfo__ParseParam_hook(CRobloxCommandLineInfo* _this, void*, const char* pszParam, BOOL bFlag, BOOL bLast) +{ + if (hasJoinScriptUrl && joinScriptUrl.empty()) + { + int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); + joinScriptUrl.resize(size); + MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &joinScriptUrl[0], size); + + _this->m_bRunAutomated = TRUE; + + CCommandLineInfo__ParseLast(_this, bLast); + +#ifdef PLAYER + Discord::Initialize(Helpers::ws2s(joinScriptUrl)); +#endif + } + + if (hasAuthenticationUrl && authenticationUrl.empty()) + { + int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); + authenticationUrl.resize(size); + MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &authenticationUrl[0], size); + + CCommandLineInfo__ParseLast(_this, bLast); + return; + } + + if (hasAuthenticationTicket && authenticationTicket.empty()) + { + int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); + authenticationTicket.resize(size); + MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &authenticationTicket[0], size); + + CCommandLineInfo__ParseLast(_this, bLast); + return; + } + +#ifdef SERVER + if (hasJobId && jobId.empty()) + { + int size = MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), nullptr, 0); + jobId.resize(size); + MultiByteToWideChar(CP_ACP, 0, pszParam, strlen(pszParam), &jobId[0], size); + + CCommandLineInfo__ParseLast(_this, bLast); + return; + } +#endif + + if (bFlag && _stricmp(pszParam, "a") == 0) + { + hasAuthenticationUrl = true; + CCommandLineInfo__ParseLast(_this, bLast); + return; + } + + if (bFlag && _stricmp(pszParam, "t") == 0) + { + hasAuthenticationTicket = true; + CCommandLineInfo__ParseLast(_this, bLast); + return; + } + + if (bFlag && _stricmp(pszParam, "j") == 0) + { + hasJoinScriptUrl = true; + CCommandLineInfo__ParseLast(_this, bLast); + return; + } + +#ifdef SERVER + if (bFlag && _stricmp(pszParam, "jobId") == 0) + { + hasJobId = true; + CCommandLineInfo__ParseLast(_this, bLast); + + Server::Initialize(jobId); + + return; + } +#endif + + CRobloxCommandLineInfo__ParseParam(_this, pszParam, bFlag, bLast); } \ No newline at end of file diff --git a/Kiseki.Patcher/Hooks/Context.cpp b/Kiseki.Patcher/Source/Hooks/Context.cpp similarity index 88% rename from Kiseki.Patcher/Hooks/Context.cpp rename to Kiseki.Patcher/Source/Hooks/Context.cpp index 3ccabc2..d1fc049 100644 --- a/Kiseki.Patcher/Hooks/Context.cpp +++ b/Kiseki.Patcher/Source/Hooks/Context.cpp @@ -1,27 +1,24 @@ -#include "pch.h" - -#include "Helpers.h" -#include "Hooks/Context.h" - -#ifdef _DEBUG - -Context__requirePermission_t Context__requirePermission = (Context__requirePermission_t)ADDRESS_CONTEXT__REQUIREPERMISSION; - -void __fastcall Context__requirePermission_hook(void* _this, void*, int permission, const char* operation) -{ - int identity = ((int*)_this)[0]; - - if (!Context__isInRole(identity, permission)) - { - if (operation != 0) - { - throw std::runtime_error("The current identity (" + std::to_string(identity) + ") cannot " + std::string(operation) + " (requires " + std::to_string(permission) + ")"); - } - else - { - throw std::runtime_error("The current identity (" + std::to_string(identity) + ") cannot perform the requested operation (requires " + std::to_string(permission) + ")"); - } - } -} - +#ifdef _DEBUG + +#include "Hooks/Context.hpp" + +Context__requirePermission_t Context__requirePermission = (Context__requirePermission_t)ADDRESS_CONTEXT__REQUIREPERMISSION; + +void __fastcall Context__requirePermission_hook(void* _this, void*, int permission, const char* operation) +{ + int identity = ((int*)_this)[0]; + + if (!Context__isInRole(identity, permission)) + { + if (operation != 0) + { + throw std::runtime_error("The current identity (" + std::to_string(identity) + ") cannot " + std::string(operation) + " (requires " + std::to_string(permission) + ")"); + } + else + { + throw std::runtime_error("The current identity (" + std::to_string(identity) + ") cannot perform the requested operation (requires " + std::to_string(permission) + ")"); + } + } +} + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Hooks/Crypt.cpp b/Kiseki.Patcher/Source/Hooks/Crypt.cpp similarity index 93% rename from Kiseki.Patcher/Hooks/Crypt.cpp rename to Kiseki.Patcher/Source/Hooks/Crypt.cpp index cd6a296..8ca82d6 100644 --- a/Kiseki.Patcher/Hooks/Crypt.cpp +++ b/Kiseki.Patcher/Source/Hooks/Crypt.cpp @@ -1,131 +1,130 @@ -#include "pch.h" - -#include "Patches.h" -#include "Helpers.h" -#include "Hooks/Crypt.h" - -Crypt::Crypt() -{ - if (!CryptAcquireContext(&context, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) - { - if (::GetLastError() == NTE_BAD_KEYSET) - { - if (!CryptAcquireContext(&context, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) - { - throw std::runtime_error("Error during CryptAcquireContext 2\n"); - } - } - else - { - throw std::runtime_error("Error during CryptAcquireContext\n"); - } - } - - try - { - BYTE* blob = new BYTE[Helpers::publicKey.size()]; - std::copy(Helpers::publicKey.begin(), Helpers::publicKey.end(), blob); - - if (!CryptImportKey(context, blob, Helpers::publicKey.size(), 0, 0, &key)) - { - throw std::runtime_error(""); - } - } - catch (...) - { -#ifdef _DEBUG - throw std::runtime_error("Failed to import public key"); -#else - throw std::runtime_error("Error during CryptImportKey"); -#endif - } -} - -Crypt::~Crypt() -{ - CryptDestroyKey(key); - CryptReleaseContext(context, 0); -} - -bool Crypt::verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm = CALG_SHA_256) -{ - // Check for a reasonable signature length before verifying - if (signatureBase64.length() > 4096) - { - return false; - } - - HCRYPTHASH hash; - - if (!CryptCreateHash(context, algorithm, NULL, 0, &hash)) - { - throw std::runtime_error(""); - } - - try - { - if (!CryptHashData(hash, (BYTE*)message.c_str(), message.size(), 0)) - { - return false; - } - - std::vector signature = Helpers::base64Decode(signatureBase64); - - /* - The native cryptography API uses little-endian byte order - while OpenSSL uses big-endian byte order. - - If you are verifying a signature generated by using a OpenSSL API - (or similar), you must swap the order of signature bytes before - calling the CryptVerifySignature function to verify the signature. - */ - - std::reverse(signature.begin(), signature.end()); - - BYTE* signatureData = new BYTE[signature.size()]; - std::copy(signature.begin(), signature.end(), signatureData); - - if (!CryptVerifySignature(hash, signatureData, signature.size(), key, NULL, 0)) - { - return false; - } - } - catch (...) - { - ::CryptDestroyHash(hash); - return false; - } - - ::CryptDestroyHash(hash); - - return true; -} - -Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64 = (Crypt__verifySignatureBase64_t)ADDRESS_CRYPT__VERIFYSIGNATUREBASE64; - -// Crypt::verifySignatureBase64(std::string message, std::string signatureBase64) -void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) -{ - // We have to reconstruct the parameters by hand since using the original function signature causes crashes - - std::string message; - std::string signatureBase64; - - // Get message - message = std::string(reinterpret_cast(pbData), dwDataLen); - - // Get signatureBase64 - int* v21 = (int*)a10; - if ((unsigned int)a15 < 0x10) - { - v21 = &a10; - } - - signatureBase64 = std::string(reinterpret_cast(v21), a14); - - // Verify signature - if (!Crypt().verifySignatureBase64(message, signatureBase64, CALG_SHA_256)) - { - throw std::runtime_error(""); - } +#include "Hooks/Crypt.hpp" + +#include "Helpers.hpp" +#include "Patches.hpp" + +Crypt::Crypt() +{ + if (!CryptAcquireContext(&context, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) + { + if (::GetLastError() == NTE_BAD_KEYSET) + { + if (!CryptAcquireContext(&context, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_NEWKEYSET)) + { + throw std::runtime_error("Error during CryptAcquireContext 2"); + } + } + else + { + throw std::runtime_error("Error during CryptAcquireContext"); + } + } + + try + { + BYTE* blob = new BYTE[Helpers::publicKey.size()]; + std::copy(Helpers::publicKey.begin(), Helpers::publicKey.end(), blob); + + if (!CryptImportKey(context, blob, Helpers::publicKey.size(), 0, 0, &key)) + { + throw std::runtime_error(""); + } + } + catch (...) + { +#ifdef _DEBUG + throw std::runtime_error("Failed to import public key"); +#else + throw std::runtime_error("Error during CryptImportKey"); +#endif + } +} + +Crypt::~Crypt() +{ + CryptDestroyKey(key); + CryptReleaseContext(context, 0); +} + +bool Crypt::verifySignatureBase64(std::string message, std::string signatureBase64, ALG_ID algorithm = CALG_SHA_256) +{ + // Check for a reasonable signature length before verifying + if (signatureBase64.length() > 4096) + { + return false; + } + + HCRYPTHASH hash; + + if (!CryptCreateHash(context, algorithm, NULL, 0, &hash)) + { + throw std::runtime_error(""); + } + + try + { + if (!CryptHashData(hash, (BYTE*)message.c_str(), message.size(), 0)) + { + return false; + } + + std::vector signature = Helpers::base64Decode(signatureBase64); + + /* + The native cryptography API uses little-endian byte order + while OpenSSL uses big-endian byte order. + + If you are verifying a signature generated by using a OpenSSL API + (or similar), you must swap the order of signature bytes before + calling the CryptVerifySignature function to verify the signature. + */ + + std::reverse(signature.begin(), signature.end()); + + BYTE* signatureData = new BYTE[signature.size()]; + std::copy(signature.begin(), signature.end(), signatureData); + + if (!CryptVerifySignature(hash, signatureData, signature.size(), key, NULL, 0)) + { + return false; + } + } + catch (...) + { + ::CryptDestroyHash(hash); + return false; + } + + ::CryptDestroyHash(hash); + + return true; +} + +Crypt__verifySignatureBase64_t Crypt__verifySignatureBase64 = (Crypt__verifySignatureBase64_t)ADDRESS_CRYPT__VERIFYSIGNATUREBASE64; + +// Crypt::verifySignatureBase64(std::string message, std::string signatureBase64) +void __fastcall Crypt__verifySignatureBase64_hook(HCRYPTPROV* _this, void*, int a2, BYTE* pbData, int a4, int a5, int a6, DWORD dwDataLen, int a8, int a9, int a10, int a11, int a12, int a13, int a14, int a15) +{ + // We have to reconstruct the parameters by hand since using the original function signature causes crashes + + std::string message; + std::string signatureBase64; + + // Get message + message = std::string(reinterpret_cast(pbData), dwDataLen); + + // Get signatureBase64 + int* v21 = (int*)a10; + if ((unsigned int)a15 < 0x10) + { + v21 = &a10; + } + + signatureBase64 = std::string(reinterpret_cast(v21), a14); + + // Verify signature + if (!Crypt().verifySignatureBase64(message, signatureBase64, CALG_SHA_256)) + { + throw std::runtime_error(""); + } } \ No newline at end of file diff --git a/Kiseki.Patcher/Hooks/DataModel.cpp b/Kiseki.Patcher/Source/Hooks/DataModel.cpp similarity index 82% rename from Kiseki.Patcher/Hooks/DataModel.cpp rename to Kiseki.Patcher/Source/Hooks/DataModel.cpp index ace36d5..3713cfb 100644 --- a/Kiseki.Patcher/Hooks/DataModel.cpp +++ b/Kiseki.Patcher/Source/Hooks/DataModel.cpp @@ -1,22 +1,20 @@ -#include "pch.h" - -#include "Hooks/DataModel.h" - -#ifdef SERVER - -bool setJobId = false; - -DataModel__getJobId_t DataModel__getJobId = (DataModel__getJobId_t)ADDRESS_DATAMODEL__GETJOBID; - -int __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2) -{ - if (!setJobId && hasJobId && !jobId.empty()) - { - _this->jobId = Helpers::ws2s(jobId); - setJobId = true; - } - - return DataModel__getJobId(_this, a2); -} - -#endif +#ifdef SERVER + +#include "Hooks/DataModel.hpp" + +bool setJobId = false; + +DataModel__getJobId_t DataModel__getJobId = (DataModel__getJobId_t)ADDRESS_DATAMODEL__GETJOBID; + +int __fastcall DataModel__getJobId_hook(DataModel* _this, void*, int a2) +{ + if (!setJobId && hasJobId && !jobId.empty()) + { + _this->jobId = Helpers::ws2s(jobId); + setJobId = true; + } + + return DataModel__getJobId(_this, a2); +} + +#endif \ No newline at end of file diff --git a/Kiseki.Patcher/Hooks/Http.cpp b/Kiseki.Patcher/Source/Hooks/Http.cpp similarity index 96% rename from Kiseki.Patcher/Hooks/Http.cpp rename to Kiseki.Patcher/Source/Hooks/Http.cpp index 657598b..51b77c8 100644 --- a/Kiseki.Patcher/Hooks/Http.cpp +++ b/Kiseki.Patcher/Source/Hooks/Http.cpp @@ -1,149 +1,147 @@ -#include "pch.h" - -#include "Hooks/Http.h" - -#define CHECK(condition, code) \ - if(!error) { \ - if ((condition)) { \ - error = code; \ - } \ - } - -Http__httpGetPostWinInet_t Http__httpGetPostWinInet = (Http__httpGetPostWinInet_t)ADDRESS_HTTP__HTTPGETPOSTWININET; -Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHECK; - -void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6) -{ - std::pair> parsed = Helpers::parseURL(_this->url); - Http _changed = *_this; - - if (parsed.first) - { - std::map url = parsed.second; - - if (!url["path"].empty() && !url["host"].empty() && !url["query"].empty()) - { - url["path"] = Helpers::toLower(url["path"]); - - if (url["host"] == "roblox.com" || url["host"] == "www.roblox.com") - { - if (url["path"] == "/asset" || url["path"] == "/asset/" || url["path"] == "/asset/default.ashx") - { - _changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + url["query"]; - _this = &_changed; - } - else if (url["path"] == "/thumbs/asset.ashx" || url["path"] == "/thumbs/avatar.ashx") - { - std::string api = "https://www.roblox.com/" + std::string(url["path"] == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix"; - - std::map source = Helpers::parseQueryString(url["query"]); - std::map fixed = { - { url["path"] == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" }, - { "thumbnailFormatId", "0" } - }; - - for (auto& pair : source) - { - fixed[Helpers::toLower(pair.first)] = pair.second; - } - - if (fixed.find("id") != fixed.end()) - { - auto handler = fixed.extract("id"); - handler.key() = url["path"] == "/thumbs/asset.ashx" ? "assetId" : "userId"; - - fixed.insert(std::move(handler)); - } - - api += Helpers::joinQueryString(fixed); - - // Get the API response - std::pair response = Helpers::httpGet(api); - if (!response.first) - { - throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0"); - } - - std::string data = response.second; - - rapidjson::Document document; - document.Parse(data.c_str()); - - int error = 0; - - CHECK(document.HasParseError(), 0x01); - CHECK(!document.HasMember("d"), 0x02); - CHECK(!document["d"].IsObject(), 0x03); - CHECK(!document["d"].HasMember("url"), 0x04); - CHECK(!document["d"]["url"].IsString(), 0x05); - - if (error != 0) - { - throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0" + std::to_string(error)); - } - - _changed.url = document["d"]["url"].GetString(); - _this = &_changed; - } - } - } - } - -#ifdef SERVER - if (Server::Handle) - { - Server::Log::Http((RequestType)isPost, _this->url); - } -#endif - - Http__httpGetPostWinInet(_this, isPost, a3, compressData, additionalHeaders, a6); -} - -bool __fastcall Http__trustCheck_hook(const char* url) -{ - if (strlen(url) == 7 && !Helpers::isASCII(url)) - { - url = ((char**)url)[0]; - } - - std::string _url = std::string(url); - - if (_url == "about:blank") - { - return true; - } - - for (std::string allowedEmbeddedScheme : Helpers::allowedEmbeddedSchemes) - { - if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0) - { - return true; - } - } - - std::pair> result = Helpers::parseURL(url); - if (!result.first) - { - return false; - } - - std::map parsed = result.second; - - if (!parsed["scheme"].empty() && !parsed["host"].empty()) - { - if (std::find(Helpers::allowedSchemes.begin(), Helpers::allowedSchemes.end(), std::string(parsed["scheme"])) != Helpers::allowedSchemes.end()) - { - for (std::string wildcard : Helpers::allowedWildcardDomains) - { - if (parsed["host"].size() >= wildcard.size() && 0 == wildcard.compare(parsed["host"].size() - wildcard.size(), wildcard.size(), wildcard)) - { - return true; - } - } - - return std::find(Helpers::allowedDomains.begin(), Helpers::allowedDomains.end(), parsed["host"]) != Helpers::allowedDomains.end(); - } - } - - return false; +#include "Hooks/Http.hpp" + +#define CHECK(condition, code) \ + if(!error) { \ + if ((condition)) { \ + error = code; \ + } \ + } + +Http__httpGetPostWinInet_t Http__httpGetPostWinInet = (Http__httpGetPostWinInet_t)ADDRESS_HTTP__HTTPGETPOSTWININET; +Http__trustCheck_t Http__trustCheck = (Http__trustCheck_t)ADDRESS_HTTP__TRUSTCHECK; + +void __fastcall Http__httpGetPostWinInet_hook(Http* _this, void*, bool isPost, int a3, bool compressData, LPCSTR additionalHeaders, int a6) +{ + std::pair> parsed = Helpers::parseURL(_this->url); + Http _changed = *_this; + + if (parsed.first) + { + std::map url = parsed.second; + + if (!url["path"].empty() && !url["host"].empty() && !url["query"].empty()) + { + url["path"] = Helpers::toLower(url["path"]); + + if (url["host"] == "roblox.com" || url["host"] == "www.roblox.com") + { + if (url["path"] == "/asset" || url["path"] == "/asset/" || url["path"] == "/asset/default.ashx") + { + _changed.url = "https://assetdelivery.roblox.com/v1/asset/?" + url["query"]; + _this = &_changed; + } + else if (url["path"] == "/thumbs/asset.ashx" || url["path"] == "/thumbs/avatar.ashx") + { + std::string api = "https://www.roblox.com/" + std::string(url["path"] == "/thumbs/asset.ashx" ? "asset" : "avatar") + "/request-thumbnail-fix"; + + std::map source = Helpers::parseQueryString(url["query"]); + std::map fixed = { + { url["path"] == "/thumbs/asset.ashx" ? "overrideModeration" : "dummy", "false" }, + { "thumbnailFormatId", "0" } + }; + + for (auto& pair : source) + { + fixed[Helpers::toLower(pair.first)] = pair.second; + } + + if (fixed.find("id") != fixed.end()) + { + auto handler = fixed.extract("id"); + handler.key() = url["path"] == "/thumbs/asset.ashx" ? "assetId" : "userId"; + + fixed.insert(std::move(handler)); + } + + api += Helpers::joinQueryString(fixed); + + // Get the API response + std::pair response = Helpers::httpGet(api); + if (!response.first) + { + throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0"); + } + + std::string data = response.second; + + rapidjson::Document document; + document.Parse(data.c_str()); + + int error = 0; + + CHECK(document.HasParseError(), 0x01); + CHECK(!document.HasMember("d"), 0x02); + CHECK(!document["d"].IsObject(), 0x03); + CHECK(!document["d"].HasMember("url"), 0x04); + CHECK(!document["d"]["url"].IsString(), 0x05); + + if (error != 0) + { + throw std::runtime_error("Unexpected error occurred when fetching Roblox API: 0x0" + std::to_string(error)); + } + + _changed.url = document["d"]["url"].GetString(); + _this = &_changed; + } + } + } + } + +#ifdef SERVER + if (Server::Handle) + { + Server::Log::Http((RequestType)isPost, _this->url); + } +#endif + + Http__httpGetPostWinInet(_this, isPost, a3, compressData, additionalHeaders, a6); +} + +bool __fastcall Http__trustCheck_hook(const char* url) +{ + if (strlen(url) == 7 && !Helpers::isASCII(url)) + { + url = ((char**)url)[0]; + } + + std::string _url = std::string(url); + + if (_url == "about:blank") + { + return true; + } + + for (std::string allowedEmbeddedScheme : Helpers::allowedEmbeddedSchemes) + { + if (_url.rfind(allowedEmbeddedScheme + ":", 0) == 0) + { + return true; + } + } + + std::pair> result = Helpers::parseURL(url); + if (!result.first) + { + return false; + } + + std::map parsed = result.second; + + if (!parsed["scheme"].empty() && !parsed["host"].empty()) + { + if (std::find(Helpers::allowedSchemes.begin(), Helpers::allowedSchemes.end(), std::string(parsed["scheme"])) != Helpers::allowedSchemes.end()) + { + for (std::string wildcard : Helpers::allowedWildcardDomains) + { + if (parsed["host"].size() >= wildcard.size() && 0 == wildcard.compare(parsed["host"].size() - wildcard.size(), wildcard.size(), wildcard)) + { + return true; + } + } + + return std::find(Helpers::allowedDomains.begin(), Helpers::allowedDomains.end(), parsed["host"]) != Helpers::allowedDomains.end(); + } + } + + return false; } \ No newline at end of file diff --git a/Kiseki.Patcher/Hooks/ServerReplicator.cpp b/Kiseki.Patcher/Source/Hooks/ServerReplicator.cpp similarity index 91% rename from Kiseki.Patcher/Hooks/ServerReplicator.cpp rename to Kiseki.Patcher/Source/Hooks/ServerReplicator.cpp index 213c0d0..ede9516 100644 --- a/Kiseki.Patcher/Hooks/ServerReplicator.cpp +++ b/Kiseki.Patcher/Source/Hooks/ServerReplicator.cpp @@ -1,35 +1,33 @@ -#include "pch.h" - -#include "Hooks/ServerReplicator.h" - -#ifdef SERVER - -static std::map rakPeers; - -ServerReplicator__sendTop_t ServerReplicator__sendTop = (ServerReplicator__sendTop_t)ADDRESS_SERVERREPLICATOR__SENDTOP; -ServerReplicator__processTicket_t ServerReplicator__processTicket = (ServerReplicator__processTicket_t)ADDRESS_SERVERREPLICATOR__PROCESSTICKET; - -void __fastcall ServerReplicator__sendTop_hook(ServerReplicator* _this, void*, RakPeerInterface* peer) -{ - if (_this->isAuthenticated) - { - ServerReplicator__sendTop(_this, peer); - } - else if (rakPeers.find(_this) == rakPeers.end()) - { - rakPeers.insert(std::pair(_this, peer)); - } -} - -void __fastcall ServerReplicator__processTicket_hook(ServerReplicator* _this, void*, Packet* packet) -{ - ServerReplicator__processTicket(_this, packet); - - auto pos = rakPeers.find(_this); - if (_this->isAuthenticated) - { - ServerReplicator__sendTop_hook(_this, nullptr, pos->second); - } -} - +#ifdef SERVER + +#include "Hooks/ServerReplicator.hpp" + +static std::map rakPeers; + +ServerReplicator__sendTop_t ServerReplicator__sendTop = (ServerReplicator__sendTop_t)ADDRESS_SERVERREPLICATOR__SENDTOP; +ServerReplicator__processTicket_t ServerReplicator__processTicket = (ServerReplicator__processTicket_t)ADDRESS_SERVERREPLICATOR__PROCESSTICKET; + +void __fastcall ServerReplicator__sendTop_hook(ServerReplicator* _this, void*, RakPeerInterface* peer) +{ + if (_this->isAuthenticated) + { + ServerReplicator__sendTop(_this, peer); + } + else if (rakPeers.find(_this) == rakPeers.end()) + { + rakPeers.insert(std::pair(_this, peer)); + } +} + +void __fastcall ServerReplicator__processTicket_hook(ServerReplicator* _this, void*, Packet* packet) +{ + ServerReplicator__processTicket(_this, packet); + + auto pos = rakPeers.find(_this); + if (_this->isAuthenticated) + { + ServerReplicator__sendTop_hook(_this, nullptr, pos->second); + } +} + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Hooks/StandardOut.cpp b/Kiseki.Patcher/Source/Hooks/StandardOut.cpp similarity index 83% rename from Kiseki.Patcher/Hooks/StandardOut.cpp rename to Kiseki.Patcher/Source/Hooks/StandardOut.cpp index a376c97..8b5b754 100644 --- a/Kiseki.Patcher/Hooks/StandardOut.cpp +++ b/Kiseki.Patcher/Source/Hooks/StandardOut.cpp @@ -1,26 +1,22 @@ -#include "pch.h" - -#include "Hooks/StandardOut.h" - -#ifdef SERVER - -StandardOut__print_t StandardOut__print = (StandardOut__print_t)ADDRESS_STANDARDOUT__PRINT; - -void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message) -{ - StandardOut__print(_this, type, message); - -#ifdef SERVER - if (Server::Handle) - { -#ifndef _DEBUG - // Message pointer is offset 4 bytes when the DLL is compiled as release - message = reinterpret_cast((int)message + 4); -#endif - - Server::Log::Output((LogSeverity)type, message->c_str()); - } -#endif -} - +#ifdef SERVER + +#include "Hooks/StandardOut.hpp" + +StandardOut__print_t StandardOut__print = (StandardOut__print_t)ADDRESS_STANDARDOUT__PRINT; + +void __fastcall StandardOut__print_hook(int _this, void*, int type, std::string* message) +{ + StandardOut__print(_this, type, message); + + if (Server::Handle) + { +#ifndef _DEBUG + // Message pointer is offset 4 bytes when the DLL is compiled as release + message = reinterpret_cast((int)message + 4); +#endif + + Server::Log::Output((LogSeverity)type, message->c_str()); + } +} + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/Patches.cpp b/Kiseki.Patcher/Source/Patcher.cpp similarity index 70% rename from Kiseki.Patcher/Patches.cpp rename to Kiseki.Patcher/Source/Patcher.cpp index e2d8a22..e0766f2 100644 --- a/Kiseki.Patcher/Patches.cpp +++ b/Kiseki.Patcher/Source/Patcher.cpp @@ -1,15 +1,13 @@ -#include "pch.h" - -#include "Patches.h" - -LONG Patches::Apply() -{ - DetourTransactionBegin(); - - for (Patch patch : patchList) - { - DetourAttach(&(PVOID&)*patch.first, patch.second); - } - - return DetourTransactionCommit(); +#include "Patcher.hpp" + +LONG Patcher::Apply() +{ + DetourTransactionBegin(); + + for (Patch patch : patchList) + { + DetourAttach(&(PVOID&)*patch.first, patch.second); + } + + return DetourTransactionCommit(); } \ No newline at end of file diff --git a/Kiseki.Patcher/Server.cpp b/Kiseki.Patcher/Source/Server.cpp similarity index 95% rename from Kiseki.Patcher/Server.cpp rename to Kiseki.Patcher/Source/Server.cpp index dc77cbd..32db2b7 100644 --- a/Kiseki.Patcher/Server.cpp +++ b/Kiseki.Patcher/Source/Server.cpp @@ -1,99 +1,97 @@ -#include "pch.h" - -#include "Server.h" - -#ifdef SERVER - -HANDLE Server::Handle; - -std::ofstream Server::OutputLog; -std::ofstream Server::HttpLog; - -std::string Server::OutputLogPath; -std::string Server::HttpLogPath; - -void Server::Initialize(const std::wstring jobId) -{ - std::string _jobId = Helpers::ws2s(jobId); - std::string signature = "Kiseki.Patcher v1.0.0"; - -#ifdef _DEBUG - signature += " (compiled as Debug)"; -#endif - - AllocConsole(); - freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); - Server::Handle = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - SetStdHandle(STD_OUTPUT_HANDLE, Server::Handle); - - printf((signature + "\n\n").c_str()); - - // Initialize file logging - fs::create_directory(fs::path(Helpers::getModulePath()).parent_path() / "logs"); - - OutputLogPath = (fs::path(Helpers::getModulePath()).parent_path() / "logs" / (_jobId + "-Output.log")).string(); - HttpLogPath = (fs::path(Helpers::getModulePath()).parent_path() / "logs" / (_jobId + "-Http.log")).string(); - - OutputLog.open(OutputLogPath, std::ios::out); - HttpLog.open(HttpLogPath, std::ios::out); - - OutputLog << signature << " - StandardOut" << std::endl << std::endl; - HttpLog << signature << " - Http" << std::endl << std::endl; - - OutputLog.close(); - HttpLog.close(); -} - -void Server::Log::Output(const LogSeverity severity, const std::string message) -{ - std::string type; - std::string time = Helpers::getISOTimestamp(); - - switch (severity) - { - case LogSeverity::Output: - SetConsoleTextAttribute(Server::Handle, FOREGROUND_BLUE | FOREGROUND_INTENSITY); - type = "out"; - break; - case LogSeverity::Information: - SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - type = "info"; - break; - case LogSeverity::Warning: - SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_GREEN); - type = "warn"; - break; - case LogSeverity::Error: - type = "err"; - SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_INTENSITY); - break; - } - - printf("%s\n", message.c_str()); - SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); - - OutputLog.open(OutputLogPath, std::ios::out); - OutputLog << "[" << time << "] [" << type << "] " << message << std::endl; - OutputLog.close(); -} - -void Server::Log::Http(const RequestType request, const std::string url) -{ - std::string type; - std::string time = Helpers::getISOTimestamp(); - - type = (request == RequestType::GET ? "GET" : "POST"); - - HttpLog.open(HttpLogPath, std::ios::out); - HttpLog << "[" << time << "] [" << type << "] " << "'" << url << "'" << std::endl; - HttpLog.close(); -} - -void Server::Cleanup() -{ - CloseHandle(Server::Handle); - OutputLog.close(); - HttpLog.close(); -} - +#ifdef SERVER + +#include "Server.hpp" + +HANDLE Server::Handle; + +std::ofstream Server::OutputLog; +std::ofstream Server::HttpLog; + +std::string Server::OutputLogPath; +std::string Server::HttpLogPath; + +void Server::Initialize(const std::wstring jobId) +{ + std::string _jobId = Helpers::ws2s(jobId); + std::string signature = "Kiseki.Patcher v1.0.0"; + +#ifdef _DEBUG + signature += " (compiled as Debug)"; +#endif + + AllocConsole(); + freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); + Server::Handle = CreateFileA("CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + SetStdHandle(STD_OUTPUT_HANDLE, Server::Handle); + + printf((signature + "\n\n").c_str()); + + // Initialize file logging + fs::create_directory(fs::path(Helpers::getModulePath()).parent_path() / "logs"); + + OutputLogPath = (fs::path(Helpers::getModulePath()).parent_path() / "logs" / (_jobId + "-Output.log")).string(); + HttpLogPath = (fs::path(Helpers::getModulePath()).parent_path() / "logs" / (_jobId + "-Http.log")).string(); + + OutputLog.open(OutputLogPath, std::ios::out); + HttpLog.open(HttpLogPath, std::ios::out); + + OutputLog << signature << " - StandardOut" << std::endl << std::endl; + HttpLog << signature << " - Http" << std::endl << std::endl; + + OutputLog.close(); + HttpLog.close(); +} + +void Server::Log::Output(const LogSeverity severity, const std::string message) +{ + std::string type; + std::string time = Helpers::getISOTimestamp(); + + switch (severity) + { + case LogSeverity::Output: + SetConsoleTextAttribute(Server::Handle, FOREGROUND_BLUE | FOREGROUND_INTENSITY); + type = "out"; + break; + case LogSeverity::Information: + SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + type = "info"; + break; + case LogSeverity::Warning: + SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_GREEN); + type = "warn"; + break; + case LogSeverity::Error: + type = "err"; + SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_INTENSITY); + break; + } + + printf("%s\n", message.c_str()); + SetConsoleTextAttribute(Server::Handle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + + OutputLog.open(OutputLogPath, std::ios::out); + OutputLog << "[" << time << "] [" << type << "] " << message << std::endl; + OutputLog.close(); +} + +void Server::Log::Http(const RequestType request, const std::string url) +{ + std::string type; + std::string time = Helpers::getISOTimestamp(); + + type = (request == RequestType::GET ? "GET" : "POST"); + + HttpLog.open(HttpLogPath, std::ios::out); + HttpLog << "[" << time << "] [" << type << "] " << "'" << url << "'" << std::endl; + HttpLog.close(); +} + +void Server::Cleanup() +{ + CloseHandle(Server::Handle); + OutputLog.close(); + HttpLog.close(); +} + #endif \ No newline at end of file diff --git a/Kiseki.Patcher/dllmain.cpp b/Kiseki.Patcher/Source/main.cpp similarity index 82% rename from Kiseki.Patcher/dllmain.cpp rename to Kiseki.Patcher/Source/main.cpp index 614777f..d3d25e6 100644 --- a/Kiseki.Patcher/dllmain.cpp +++ b/Kiseki.Patcher/Source/main.cpp @@ -1,101 +1,100 @@ -#include "pch.h" - -#include "Configuration.h" -#include "Patches.h" - -#ifndef SERVER -#include "Discord.h" -#endif - -#ifdef SERVER -#include "Server.h" -#endif - -#include "Hooks/Http.h" -#include "Hooks/Crypt.h" -#include "Hooks/CRoblox.h" - -#ifdef _DEBUG -#include "Hooks/Context.h" -#endif - -#ifdef SERVER -#include "Hooks/DataModel.h" -#include "Hooks/StandardOut.h" -#include "Hooks/ServerReplicator.h" -#endif - -START_PATCH_LIST() - -ADD_PATCH(Http__httpGetPostWinInet, Http__httpGetPostWinInet_hook) -ADD_PATCH(Http__trustCheck, Http__trustCheck_hook) - -ADD_PATCH(Crypt__verifySignatureBase64, Crypt__verifySignatureBase64_hook) - -ADD_PATCH(CRobloxApp__InitInstance, CRobloxApp__InitInstance_hook) -ADD_PATCH(CRobloxCommandLineInfo__ParseParam, CRobloxCommandLineInfo__ParseParam_hook) - -#ifdef _DEBUG -ADD_PATCH(Context__requirePermission, Context__requirePermission_hook) -#endif - -#ifdef SERVER -ADD_PATCH(DataModel__getJobId, DataModel__getJobId_hook) - -ADD_PATCH(StandardOut__print, StandardOut__print_hook) - -ADD_PATCH(ServerReplicator__sendTop, ServerReplicator__sendTop_hook) -ADD_PATCH(ServerReplicator__processTicket, ServerReplicator__processTicket_hook) -#endif - -END_PATCH_LIST() - -BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) -{ - if (ul_reason_for_call == DLL_PROCESS_ATTACH) - { - LONG patchesError = Patches::Apply(); - if (patchesError != NO_ERROR) - { -#ifdef _DEBUG - std::string message = "Patches::Apply returned " + std::to_string(patchesError); - MessageBoxA(nullptr, message.c_str(), nullptr, MB_ICONERROR); -#endif - - ExitProcess(EXIT_FAILURE); - } - - CURLcode curlError = curl_global_init(CURL_GLOBAL_DEFAULT); - if (curlError != CURLE_OK) - { -#ifdef _DEBUG - std::string message = "curl_global_init returned " + std::to_string(curlError); - MessageBoxA(nullptr, message.c_str(), nullptr, MB_ICONERROR); -#endif - - ExitProcess(EXIT_FAILURE); - } - } - - if (ul_reason_for_call == DLL_PROCESS_DETACH) - { - curl_global_cleanup(); - -#ifdef PLAYER - Discord::Cleanup(); -#endif - -#ifdef SERVER - if (Server::Handle) - { - Server::Cleanup(); - } -#endif - } - - return TRUE; -} - -#ifdef SERVER -void __declspec(dllexport) entrypoint() {} + +#include "Configuration.hpp" +#include "Patches.hpp" + +#ifdef PLAYER +#include "Discord.hpp" +#endif + +#ifdef SERVER +#include "Server.hpp" +#endif + +#include "Hooks/Http.hpp" +#include "Hooks/Crypt.hpp" +#include "Hooks/CRoblox.hpp" + +#ifdef _DEBUG +#include "Hooks/Context.hpp" +#endif + +#ifdef SERVER +#include "Hooks/DataModel.hpp" +#include "Hooks/StandardOut.hpp" +#include "Hooks/ServerReplicator.hpp" +#endif + +START_PATCH_LIST() + +ADD_PATCH(Http__httpGetPostWinInet, Http__httpGetPostWinInet_hook) +ADD_PATCH(Http__trustCheck, Http__trustCheck_hook) + +ADD_PATCH(Crypt__verifySignatureBase64, Crypt__verifySignatureBase64_hook) + +ADD_PATCH(CRobloxApp__InitInstance, CRobloxApp__InitInstance_hook) +ADD_PATCH(CRobloxCommandLineInfo__ParseParam, CRobloxCommandLineInfo__ParseParam_hook) + +#ifdef _DEBUG +ADD_PATCH(Context__requirePermission, Context__requirePermission_hook) +#endif + +#ifdef SERVER +ADD_PATCH(DataModel__getJobId, DataModel__getJobId_hook) + +ADD_PATCH(StandardOut__print, StandardOut__print_hook) + +ADD_PATCH(ServerReplicator__sendTop, ServerReplicator__sendTop_hook) +ADD_PATCH(ServerReplicator__processTicket, ServerReplicator__processTicket_hook) +#endif + +END_PATCH_LIST() + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) +{ + if (ul_reason_for_call == DLL_PROCESS_ATTACH) + { + LONG patchesError = Patches::Apply(); + if (patchesError != NO_ERROR) + { +#ifdef _DEBUG + std::string message = "Patches::Apply returned " + std::to_string(patchesError); + MessageBoxA(nullptr, message.c_str(), nullptr, MB_ICONERROR); +#endif + + ExitProcess(EXIT_FAILURE); + } + + CURLcode curlError = curl_global_init(CURL_GLOBAL_DEFAULT); + if (curlError != CURLE_OK) + { +#ifdef _DEBUG + std::string message = "curl_global_init returned " + std::to_string(curlError); + MessageBoxA(nullptr, message.c_str(), nullptr, MB_ICONERROR); +#endif + + ExitProcess(EXIT_FAILURE); + } + } + + if (ul_reason_for_call == DLL_PROCESS_DETACH) + { + curl_global_cleanup(); + +#ifdef PLAYER + Discord::Cleanup(); +#endif + +#ifdef SERVER + if (Server::Handle) + { + Server::Cleanup(); + } +#endif + } + + return TRUE; +} + +#ifdef SERVER +void __declspec(dllexport) entrypoint() {} #endif \ No newline at end of file diff --git a/Kiseki.Patcher/pch.cpp b/Kiseki.Patcher/pch.cpp deleted file mode 100644 index 1730571..0000000 --- a/Kiseki.Patcher/pch.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "pch.h" \ No newline at end of file diff --git a/README.md b/README.md index 3c27286..df94799 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Kiseki.Patcher -DLL used for extending client/server functionality +Fork of [@lrre-foss/lure](https://github.com/lrre-foss/lure) with Kiseki-specific additions # License -Copyright (c) Kiseki 2022-2023. All rights reserved. Not for public use. \ No newline at end of file +Copyright (c) Kiseki 2023. All rights reserved. Not for public use. + +This project is a fork of [@lrre-foss/lure](https://github.com/lrre-foss/lure), a project licensed under the [Apache License v2.0](https://www.apache.org/licenses/LICENSE-2.0.txt). \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index 339d7a0..fa5f666 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -6,6 +6,7 @@ "curl", "detours", "discord-rpc", - "rapidjson" + "rapidjson", + "pugixml" ] } \ No newline at end of file