From ccdbc51b30b25374577a28d391aa4b32c04306e3 Mon Sep 17 00:00:00 2001 From: Anonymous275 Date: Fri, 21 Aug 2020 20:57:41 +0300 Subject: [PATCH] V1.6 Rewrite --- CMakeLists.txt | 21 +- cmake-build-debug/zlibstatic.lib | Bin 181848 -> 284634 bytes cmake-build-release/zlibstatic.lib | Bin 181848 -> 181944 bytes {src/curl => include/Curl}/curl.h | 0 {src/curl => include/Curl}/curlbuild.h | 0 {src/curl => include/Curl}/curlrules.h | 0 {src/curl => include/Curl}/curlver.h | 0 {src/curl => include/Curl}/easy.h | 0 include/Curl/http.h | 6 + {src/curl => include/Curl}/mprintf.h | 0 {src/curl => include/Curl}/multi.h | 0 {src/curl => include/Curl}/stdcheaders.h | 0 {src/curl => include/Curl}/system.h | 0 {src/curl => include/Curl}/typecheck-gcc.h | 2 +- include/Discord/discord_info.h | 11 + .../Discord}/discord_register.h | 0 .../include => include/Discord}/discord_rpc.h | 2 +- include/Logger.h | 12 + include/Memory.h | 5 + include/Network/network.h | 25 ++ include/Security/Enc.h | 12 + include/Security/Game.h | 6 + include/Security/Init.h | 11 + include/Security/Xor.h | 130 ++++++++ include/Startup.h | 10 + include/Zlib/Compressor.h | 7 + {src/include => include/Zlib}/zconf.h | 9 + {src/include => include/Zlib}/zlib.h | 0 include/Zlib/zutil.h | 271 ++++++++++++++++ src/Compressor.cpp | 68 ++-- src/CoreNetwork.cpp | 196 ----------- src/Discord.cpp | 272 ++++++---------- src/GameStart.cpp | 85 +++-- src/Logger.cpp | 80 +++++ src/Memory/Memory.cpp | 8 +- src/Memory/Memory.hpp | 3 +- src/Memory/Reader.cpp | 22 +- src/Network 2.0/GlobalHandler.cpp | 249 -------------- src/Network/Core.cpp | 198 +++++++++++ src/Network/GlobalHandler.cpp | 202 ++++++++++++ src/{http.cpp => Network/Http.cpp} | 56 ++-- src/{ => Network}/Resources.cpp | 148 +++++---- src/{Network 2.0 => Network}/VehicleData.cpp | 111 ++++--- src/{Network 2.0 => Network}/VehicleEvent.cpp | 45 +-- src/Security.cpp | 307 ------------------ src/Security/BeamNG.cpp | 289 +++++++++++++++++ src/Security/Checker.cpp | 92 ++++++ src/Security/Encryption.cpp | 85 +++++ src/Security/FileHandles.cpp | 71 ++++ src/Startup.cpp | 199 ++++++++++++ src/UpdateCheck.cpp | 60 ---- src/VehicleNetwork.cpp | 164 ---------- src/main.cpp | 226 ++----------- 53 files changed, 2150 insertions(+), 1626 deletions(-) rename {src/curl => include/Curl}/curl.h (100%) rename {src/curl => include/Curl}/curlbuild.h (100%) rename {src/curl => include/Curl}/curlrules.h (100%) rename {src/curl => include/Curl}/curlver.h (100%) rename {src/curl => include/Curl}/easy.h (100%) create mode 100644 include/Curl/http.h rename {src/curl => include/Curl}/mprintf.h (100%) rename {src/curl => include/Curl}/multi.h (100%) rename {src/curl => include/Curl}/stdcheaders.h (100%) rename {src/curl => include/Curl}/system.h (100%) rename {src/curl => include/Curl}/typecheck-gcc.h (99%) create mode 100644 include/Discord/discord_info.h rename {src/include => include/Discord}/discord_register.h (100%) rename {src/include => include/Discord}/discord_rpc.h (99%) create mode 100644 include/Logger.h create mode 100644 include/Memory.h create mode 100644 include/Network/network.h create mode 100644 include/Security/Enc.h create mode 100644 include/Security/Game.h create mode 100644 include/Security/Init.h create mode 100644 include/Security/Xor.h create mode 100644 include/Startup.h create mode 100644 include/Zlib/Compressor.h rename {src/include => include/Zlib}/zconf.h (97%) rename {src/include => include/Zlib}/zlib.h (100%) create mode 100644 include/Zlib/zutil.h delete mode 100644 src/CoreNetwork.cpp create mode 100644 src/Logger.cpp delete mode 100644 src/Network 2.0/GlobalHandler.cpp create mode 100644 src/Network/Core.cpp create mode 100644 src/Network/GlobalHandler.cpp rename src/{http.cpp => Network/Http.cpp} (69%) rename src/{ => Network}/Resources.cpp (57%) rename src/{Network 2.0 => Network}/VehicleData.cpp (66%) rename src/{Network 2.0 => Network}/VehicleEvent.cpp (60%) delete mode 100644 src/Security.cpp create mode 100644 src/Security/BeamNG.cpp create mode 100644 src/Security/Checker.cpp create mode 100644 src/Security/Encryption.cpp create mode 100644 src/Security/FileHandles.cpp create mode 100644 src/Startup.cpp delete mode 100644 src/UpdateCheck.cpp delete mode 100644 src/VehicleNetwork.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a240a6b..a5357b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,9 @@ -cmake_minimum_required(VERSION 3.15) - -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /O2") -project(BeamMP-Launcher) +cmake_minimum_required(VERSION 3.10) +project(Launcher) set(CMAKE_CXX_STANDARD 17) - -file(GLOB source_files - "src/*.cpp" "src/include/*.h" - "src/include/*.hpp" "src/curl/*.h" - "src/Network 2.0/*.cpp" "src/Network 2.0/*.h" - "src/Memory/*.hpp" "src/Memory/*.cpp") - -add_executable(BeamMP-Launcher ${source_files}) -target_link_libraries(BeamMP-Launcher ws2_32 urlmon discord-rpc libcurl_a zlibstatic) \ No newline at end of file +file(GLOB source_files "src/*.cpp" "src/*/*.cpp" "src/*/*.hpp" "include/*.h" "include/*/*.h") +add_executable(${PROJECT_NAME} ${source_files}) +set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "BeamMP-Launcher") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") +target_link_libraries(${PROJECT_NAME} ws2_32 urlmon rstrtmgr discord-rpc zlibstatic libcurl_a) +target_include_directories(${PROJECT_NAME} PUBLIC $) \ No newline at end of file diff --git a/cmake-build-debug/zlibstatic.lib b/cmake-build-debug/zlibstatic.lib index 7f8f1cef98bb74197dd90b27c82e99efd89ac9e8..6f0648439cb6b31d3965fe3ae873dbbd77f13636 100644 GIT binary patch literal 284634 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
Had~i#m4Enr67xmK4)- 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 Xzqa^211uL(wYT3;XDy2Uk3V(dH>IU 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 J>OJim|2I}P02lxO diff --git a/src/curl/curl.h b/include/Curl/curl.h similarity index 100% rename from src/curl/curl.h rename to include/Curl/curl.h diff --git a/src/curl/curlbuild.h b/include/Curl/curlbuild.h similarity index 100% rename from src/curl/curlbuild.h rename to include/Curl/curlbuild.h diff --git a/src/curl/curlrules.h b/include/Curl/curlrules.h similarity index 100% rename from src/curl/curlrules.h rename to include/Curl/curlrules.h diff --git a/src/curl/curlver.h b/include/Curl/curlver.h similarity index 100% rename from src/curl/curlver.h rename to include/Curl/curlver.h diff --git a/src/curl/easy.h b/include/Curl/easy.h similarity index 100% rename from src/curl/easy.h rename to include/Curl/easy.h diff --git a/include/Curl/http.h b/include/Curl/http.h new file mode 100644 index 0000000..9a1438e --- /dev/null +++ b/include/Curl/http.h @@ -0,0 +1,6 @@ +/// +/// Created by Anonymous275 on 7/18/2020 +/// +#pragma once +int Download(const std::string& URL,const std::string& Path,bool close); +std::string HTTP_REQUEST(const std::string& IP,int port); \ No newline at end of file diff --git a/src/curl/mprintf.h b/include/Curl/mprintf.h similarity index 100% rename from src/curl/mprintf.h rename to include/Curl/mprintf.h diff --git a/src/curl/multi.h b/include/Curl/multi.h similarity index 100% rename from src/curl/multi.h rename to include/Curl/multi.h diff --git a/src/curl/stdcheaders.h b/include/Curl/stdcheaders.h similarity index 100% rename from src/curl/stdcheaders.h rename to include/Curl/stdcheaders.h diff --git a/src/curl/system.h b/include/Curl/system.h similarity index 100% rename from src/curl/system.h rename to include/Curl/system.h diff --git a/src/curl/typecheck-gcc.h b/include/Curl/typecheck-gcc.h similarity index 99% rename from src/curl/typecheck-gcc.h rename to include/Curl/typecheck-gcc.h index 6ec8bcf..315c264 100644 --- a/src/curl/typecheck-gcc.h +++ b/include/Curl/typecheck-gcc.h @@ -581,7 +581,7 @@ typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *); typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *); typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *); #ifdef HEADER_SSL_H -/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX +/* hTRG: if we included OpenSSL's ssl.h, we know about SSL_CTX * this will of course break if we're included before OpenSSL headers... */ typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *); diff --git a/include/Discord/discord_info.h b/include/Discord/discord_info.h new file mode 100644 index 0000000..a1a2b01 --- /dev/null +++ b/include/Discord/discord_info.h @@ -0,0 +1,11 @@ +/// +/// Created by Anonymous275 on 7/16/2020 +/// +#pragma once +#include +void Discord_Main(); +std::string GetDName(); +std::string GetDTag(); +std::string GetDID(); +void DAboard(); + diff --git a/src/include/discord_register.h b/include/Discord/discord_register.h similarity index 100% rename from src/include/discord_register.h rename to include/Discord/discord_register.h diff --git a/src/include/discord_rpc.h b/include/Discord/discord_rpc.h similarity index 99% rename from src/include/discord_rpc.h rename to include/Discord/discord_rpc.h index 3e1441e..8609bf7 100644 --- a/src/include/discord_rpc.h +++ b/include/Discord/discord_rpc.h @@ -1,5 +1,5 @@ #pragma once -#include +#include // clang-format off diff --git a/include/Logger.h b/include/Logger.h new file mode 100644 index 0000000..5c3a52f --- /dev/null +++ b/include/Logger.h @@ -0,0 +1,12 @@ +/// +/// Created by Anonymous275 on 4/2/2020. +/// +#pragma once +#include +#include +void InitLog(); +void except(const std::string& toPrint); +void debug(const std::string& toPrint); +void error(const std::string& toPrint); +void info(const std::string& toPrint); +void warn(const std::string& toPrint); diff --git a/include/Memory.h b/include/Memory.h new file mode 100644 index 0000000..e6e3d42 --- /dev/null +++ b/include/Memory.h @@ -0,0 +1,5 @@ +/// +/// Created by Anonymous275 on 7/20/2020 +/// +#pragma once +void MemoryInit(); diff --git a/include/Network/network.h b/include/Network/network.h new file mode 100644 index 0000000..3869a6b --- /dev/null +++ b/include/Network/network.h @@ -0,0 +1,25 @@ +/// +/// Created by Anonymous275 on 7/18/2020 +/// +#pragma once +#include +void NetReset(); +extern long long ping; +extern bool Dev; +void ClearAll(); +extern int ClientID; +extern bool ModLoaded; +extern bool Terminate; +extern int DEFAULT_PORT; +extern bool TCPTerminate; +extern std::string MStatus; +extern std::string UlStatus; +extern std::string ListOfMods; +void UDPSend(std::string Data); +[[noreturn]] void CoreNetwork(); +void TCPSend(const std::string&Data); +void GameSend(const std::string&Data); +void SendLarge(const std::string&Data); +void TCPClientMain(const std::string& IP,int Port); +void UDPClientMain(const std::string& IP,int Port); +void TCPGameServer(const std::string& IP, int Port); diff --git a/include/Security/Enc.h b/include/Security/Enc.h new file mode 100644 index 0000000..3901895 --- /dev/null +++ b/include/Security/Enc.h @@ -0,0 +1,12 @@ +/// +/// Created by Anonymous275 on 7/16/2020 +/// +#pragma once +#include +#include "Xor.h" +std::string RSA_D(const std::string& Data,int d, int n); +std::string RSA_E(const std::string& Data,int e, int n); +std::string LocalEnc(const std::string& Data); +std::string LocalDec(const std::string& Data); +std::string Encrypt(std::string msg); +std::string Decrypt(std::string msg); \ No newline at end of file diff --git a/include/Security/Game.h b/include/Security/Game.h new file mode 100644 index 0000000..7eaa2e3 --- /dev/null +++ b/include/Security/Game.h @@ -0,0 +1,6 @@ +/// +/// Created by Anonymous275 on 7/19/2020 +/// +#pragma once +extern unsigned long GamePID; +void SecureMods(); diff --git a/include/Security/Init.h b/include/Security/Init.h new file mode 100644 index 0000000..4fae3cd --- /dev/null +++ b/include/Security/Init.h @@ -0,0 +1,11 @@ +/// +/// Created by Anonymous275 on 7/18/2020 +/// +#pragma once +#include +void PreGame(int argc, char* argv[],const std::string& GamePath); +void InitGame(const std::string& Dir,const std::string&Current); +std::string CheckVer(const std::string &path); +void SecurityCheck(char* argv[]); +std::string GetGameDir(); +void LegitimacyCheck(); \ No newline at end of file diff --git a/include/Security/Xor.h b/include/Security/Xor.h new file mode 100644 index 0000000..a7b2874 --- /dev/null +++ b/include/Security/Xor.h @@ -0,0 +1,130 @@ +/// +/// Created by Anonymous275 on 8/11/2020 +/// +#pragma once +#include +#include +#include + +#define BEGIN_NAMESPACE(x) namespace x { +#define END_NAMESPACE } + +BEGIN_NAMESPACE(XorCompileTime) + + constexpr auto time = __TIME__; + constexpr auto seed = static_cast(time[7]) + static_cast(time[6]) * 10 + static_cast(time[4]) * 60 + static_cast(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000; + +// 1988, Stephen Park and Keith Miller +// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard" +// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation: +// with 32-bit math and without division + + template + struct RandomGenerator{ + private: + static constexpr unsigned a = 16807; // 7^5 + static constexpr unsigned m = 2147483647; // 2^31 - 1 + + static constexpr unsigned s = RandomGenerator< N - 1 >::value; + static constexpr unsigned lo = a * (s & 0xFFFFu); // Multiply lower 16 bits by 16807 + static constexpr unsigned hi = a * (s >> 16u); // Multiply higher 16 bits by 16807 + static constexpr unsigned lo2 = lo + ((hi & 0x7FFFu) << 16u); // Combine lower 15 bits of hi with lo's upper bits + static constexpr unsigned hi2 = hi >> 15u; // Discard lower 15 bits of hi + static constexpr unsigned lo3 = lo2 + hi; + + public: + static constexpr unsigned max = m; + static constexpr unsigned value = lo3 > m ? lo3 - m : lo3; + }; + + template <> + struct RandomGenerator< 0 >{ + static constexpr unsigned value = seed; + }; + + template + struct RandomInt{ + static constexpr auto value = RandomGenerator< N + 1 >::value % M; + }; + + template + struct RandomChar{ + static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value); + }; + + template + struct XorString{ + private: + const char _key; + std::array< Char, N + 1 > _encrypted; + + constexpr Char enc(Char c) const{ + return c ^ _key; + } + + Char dec(Char c) const{ + return c ^ _key; + } + + public: + template + constexpr __forceinline XorString(const Char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... } + {} + + __forceinline decltype(auto) decrypt(){ + for (size_t i = 0; i < N; ++i) { + _encrypted[i] = dec(_encrypted[i]); + } + _encrypted[N] = '\0'; + return _encrypted.data(); + } + }; + + static auto w_printf = [](const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vprintf_s(fmt, args); + va_end(args); + }; + + static auto w_printf_s = [](const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vprintf_s(fmt, args); + va_end(args); + }; + + /*static auto w_sprintf = [](char* buf, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + };*/ + + /*static auto w_sprintf_ret = [](char* buf, const char* fmt, ...) { + int ret; + va_list args; + va_start(args, fmt); + ret = vsprintf(buf, fmt, args); + va_end(args); + return ret; + };*/ + + static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vsprintf_s(buf, buf_size, fmt, args); + va_end(args); + }; + + static auto w_sprintf_s_ret = [](char* buf, size_t buf_size, const char* fmt, ...) { + int ret; + va_list args; + va_start(args, fmt); + ret = vsprintf_s(buf, buf_size, fmt, args); + va_end(args); + return ret; + }; +#define Sec( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(char) - 1, __COUNTER__, char > expr( s, std::make_index_sequence< sizeof(s)/sizeof(char) - 1>() ); return expr; }().decrypt() +#define SecW( s ) []{ constexpr XorCompileTime::XorString< sizeof(s)/sizeof(wchar_t) - 1, __COUNTER__, wchar_t > expr( s, std::make_index_sequence< sizeof(s)/sizeof(wchar_t) - 1>() ); return expr; }().decrypt() +END_NAMESPACE diff --git a/include/Startup.h b/include/Startup.h new file mode 100644 index 0000000..0d219ad --- /dev/null +++ b/include/Startup.h @@ -0,0 +1,10 @@ +/// +/// Created by Anonymous275 on 7/18/2020 +/// +#pragma once +#include +void InitLauncher(int argc, char* argv[]); +void CheckDir(int argc,char* args[]); +std::string GetVer(); +std::string GetEN(); +extern bool Dev; \ No newline at end of file diff --git a/include/Zlib/Compressor.h b/include/Zlib/Compressor.h new file mode 100644 index 0000000..1947ef5 --- /dev/null +++ b/include/Zlib/Compressor.h @@ -0,0 +1,7 @@ +/// +/// Created by Anonymous275 on 7/24/2020 +/// +#pragma once +#include +std::string Comp(std::string Data); +std::string DeComp(std::string Compressed); diff --git a/src/include/zconf.h b/include/Zlib/zconf.h similarity index 97% rename from src/include/zconf.h rename to include/Zlib/zconf.h index 733b5eb..352f552 100644 --- a/src/include/zconf.h +++ b/include/Zlib/zconf.h @@ -3,10 +3,19 @@ * For conditions of distribution and use, see copyright notice in zlib.h */ +/* @(#) $Id$ */ #ifndef ZCONF_H #define ZCONF_H +/* #undef Z_PREFIX */ +/* #undef Z_HAVE_UNISTD_H */ +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ # define Z_PREFIX_SET diff --git a/src/include/zlib.h b/include/Zlib/zlib.h similarity index 100% rename from src/include/zlib.h rename to include/Zlib/zlib.h diff --git a/include/Zlib/zutil.h b/include/Zlib/zutil.h new file mode 100644 index 0000000..b079ea6 --- /dev/null +++ b/include/Zlib/zutil.h @@ -0,0 +1,271 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/src/Compressor.cpp b/src/Compressor.cpp index 42b68ec..9733650 100644 --- a/src/Compressor.cpp +++ b/src/Compressor.cpp @@ -1,59 +1,49 @@ /// -/// Created by Anonymous275 on 4/23/2020 +/// Created by Anonymous275 on 7/15/2020 /// - -#include +#include "Zlib/zlib.h" #include -#include "include/zlib.h" - -void Print(const std::string&MSG){ - //std::cout << MSG << std::endl; -} - -std::string Compress(const std::string&Data){ - std::string b; - b.resize(Data.length()); +#define Biggest 30000 +std::string Comp(std::string Data){ + char*C = new char[Biggest]; + memset(C, 0, Biggest); z_stream defstream; defstream.zalloc = Z_NULL; defstream.zfree = Z_NULL; defstream.opaque = Z_NULL; - defstream.avail_in = (uInt)Data.length()+1; + defstream.avail_in = (uInt)Data.length(); defstream.next_in = (Bytef *)&Data[0]; - defstream.avail_out = (uInt)b.size(); - defstream.next_out = (Bytef *)&b[0]; + defstream.avail_out = Biggest; + defstream.next_out = reinterpret_cast(C); deflateInit(&defstream, Z_BEST_COMPRESSION); + deflate(&defstream, Z_SYNC_FLUSH); deflate(&defstream, Z_FINISH); deflateEnd(&defstream); - for(int i = int(b.length())-1;i >= 0;i--){ - if(b.at(i) != '\0'){ - b.resize(i); - break; - } - } - return b; + int TO = defstream.total_out; + std::string Ret(TO,0); + memcpy_s(&Ret[0],TO,C,TO); + delete [] C; + return Ret; } - -std::string Decompress(const std::string&Data) -{ - std::string c; - c.resize(Data.size()*5); +std::string DeComp(std::string Compressed){ + char*C = new char[Biggest]; + memset(C, 0, Biggest); z_stream infstream; infstream.zalloc = Z_NULL; infstream.zfree = Z_NULL; infstream.opaque = Z_NULL; - infstream.avail_in = (uInt)(Data.c_str()); - infstream.next_in = (Bytef *)&Data[0]; - infstream.avail_out = (uInt)c.size(); - infstream.next_out = (Bytef *)&c[0]; + infstream.avail_in = Biggest; + infstream.next_in = (Bytef *)(&Compressed[0]); + infstream.avail_out = Biggest; + infstream.next_out = (Bytef *)(C); inflateInit(&infstream); - inflate(&infstream, Z_NO_FLUSH); + inflate(&infstream, Z_SYNC_FLUSH); + inflate(&infstream, Z_FINISH); inflateEnd(&infstream); - for(int i = int(c.length())-1;i >= 0;i--){ - if(c.at(i) != '\0'){ - c.resize(i+1); - break; - } - } - return c; + int TO = infstream.total_out; + std::string Ret(TO,0); + memcpy_s(&Ret[0],TO,C,TO); + delete [] C; + return Ret; } \ No newline at end of file diff --git a/src/CoreNetwork.cpp b/src/CoreNetwork.cpp deleted file mode 100644 index e9c54b7..0000000 --- a/src/CoreNetwork.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/// -/// Created by Anonymous275 on 4/3/2020 -/// -#include -#include -#include -#include -#include -#include -#include -extern int DEFAULT_PORT; -std::string HTTP_REQUEST(const std::string&url,int port); -void ProxyThread(const std::string& IP, int port); -void Exit(const std::string& Msg); -extern std::string UlStatus; -extern std::string MStatus; -extern int ping; -extern bool Terminate; -extern bool TCPTerminate; -extern bool Dev; -extern std::string ListOfMods; -bool Confirm = false; -void Reset(); -std::set Conf; - -void StartSync(const std::string &Data){ - UlStatus = "UlLoading..."; - Terminate = false; - TCPTerminate = false; - Conf.clear(); - ping = -1; - std::thread t1(ProxyThread,Data.substr(1,Data.find(':')-1),std::stoi(Data.substr(Data.find(':')+1))); - //std::thread t1(ProxyThread,"127.0.0.1",30814); - t1.detach(); -} - -std::string Parse(const std::string& Data){ - char Code = Data.substr(0,1).at(0), SubCode = 0; - if(Data.length() > 1)SubCode = Data.substr(1,1).at(0); - switch (Code){ - case 'A': - return Data.substr(0,1); - case 'B': - Reset(); - Terminate = true; - TCPTerminate = true; - return Code + HTTP_REQUEST("s1.yourthought.co.uk/servers-info",3599); - case 'C': - ListOfMods.clear(); - StartSync(Data); - std::cout << "Connecting to server" << std::endl; - while(ListOfMods.empty() && !Terminate){ - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - if(ListOfMods == "-")return "L"; - else return "L"+ListOfMods; - case 'U': - if(SubCode == 'l')return UlStatus; - if(SubCode == 'p')return "Up" + std::to_string(ping); - if(!SubCode)return UlStatus+ "\n" + "Up" + std::to_string(ping); - case 'M': - return MStatus; - case 'Q': - if(SubCode == 'S'){ - Reset(); - Terminate = true; - TCPTerminate = true; - ping = -1; - } - if(SubCode == 'G')exit(2); - return ""; - case 'R': //will send mod name - if(Conf.find(Data) == Conf.end()){ - Conf.insert(Data); - Confirm = true; - } - return ""; - default: - return ""; - } -} -bool once = false; -[[noreturn]] void MemoryInit(); -[[noreturn]] void CoreNetworkThread(){ - try { - std::cout << "Ready!" << std::endl; - do { - if (Dev)std::cout << "Core Network on start!" << std::endl; - WSADATA wsaData; - int iResult; - SOCKET ListenSocket; - SOCKET ClientSocket; - - struct addrinfo *result = nullptr; - struct addrinfo hints{}; - - int iSendResult; - char recvbuf[64000]; - int recvbuflen = 64000; - - // Initialize Winsock - iResult = WSAStartup(514, &wsaData); //2.2 - if (iResult != 0) { - if (Dev)std::cout << "WSAStartup failed with error: " << iResult << std::endl; - } - - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_PASSIVE; - - // Resolve the server address and port - iResult = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT).c_str(), &hints, &result); - if (iResult != 0) { - if (Dev)std::cout << "(Core) getaddrinfo failed with error: " << iResult << std::endl; - WSACleanup(); - } - - // Create a socket for connecting to server - ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); - if (ListenSocket == -1) { - if (Dev)std::cout << "(Core) socket failed with error: " << WSAGetLastError() << std::endl; - freeaddrinfo(result); - WSACleanup(); - }else{ - iResult = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen); - if (iResult == SOCKET_ERROR) { - if (Dev)Exit("(Core) bind failed with error: " + std::to_string(WSAGetLastError())); - freeaddrinfo(result); - closesocket(ListenSocket); - WSACleanup(); - } - } - - - iResult = listen(ListenSocket, SOMAXCONN); - if (iResult == SOCKET_ERROR) { - if (Dev)std::cout << "(Core) listen failed with error: " << WSAGetLastError() << std::endl; - closesocket(ListenSocket); - WSACleanup(); - } - ClientSocket = accept(ListenSocket, nullptr, nullptr); - if (ClientSocket == -1) { - if (Dev)std::cout << "(Core) accept failed with error: " << WSAGetLastError() << std::endl; - closesocket(ListenSocket); - WSACleanup(); - } - closesocket(ListenSocket); - if (!once) { - std::thread Memory(MemoryInit); - Memory.detach(); - once = true; - } - do { - std::string Response; - iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); - if (iResult > 0) { - std::string data = recvbuf; - data.resize(iResult); - Response = Parse(data); - } else if (iResult == 0) { - if (Dev)std::cout << "(Core) Connection closing...\n"; - } else { - if (Dev)std::cout << "(Core) recv failed with error: " << WSAGetLastError() << std::endl; - closesocket(ClientSocket); - WSACleanup(); - } - if (!Response.empty()) { - iSendResult = send(ClientSocket, (Response+"\n").c_str(), int(Response.length())+1, 0); - if (iSendResult == SOCKET_ERROR) { - if (Dev)std::cout << "send failed with error: " << WSAGetLastError() << std::endl; - closesocket(ClientSocket); - WSACleanup(); - } else { - ///std::cout << "Bytes sent: " << iSendResult << std::endl; - } - } - } while (iResult > 0); - - iResult = shutdown(ClientSocket, SD_SEND); - if (iResult == SOCKET_ERROR) { - if (Dev)std::cout << "(Core) shutdown failed with error: " << WSAGetLastError() << std::endl; - closesocket(ClientSocket); - WSACleanup(); - Sleep(500); - } - closesocket(ClientSocket); - WSACleanup(); - } while (true); - } catch (std::exception&e) { - std::cout << "Exception! : " << e.what() << std::endl; - system("pause"); - exit(1); - } -} \ No newline at end of file diff --git a/src/Discord.cpp b/src/Discord.cpp index f88cfdf..7ca0205 100644 --- a/src/Discord.cpp +++ b/src/Discord.cpp @@ -1,206 +1,126 @@ /// -/// Created by Anonymous275 on 3/25/2020 +/// Created by Anonymous275 on 7/16/2020 /// - -#define _CRT_SECURE_NO_WARNINGS -#include -#include -#include -#include -#include "include/discord_rpc.h" -#include +#include "Discord/discord_rpc.h" +#include "Security/Enc.h" +#include "Logger.h" +#include #include -#include -#include -#include -extern bool Dev; -extern char*EName; -static const char* APPLICATION_ID = "629743237988352010"; -static int64_t StartTime; -static int SendPresence = 1; -std::vector GlobalInfo; -std::string hta(const std::string& hex); -void SystemExec(const std::string& cmd); -static void updateDiscordPresence() -{ - if (SendPresence) { - char buffer[256]; - DiscordRichPresence discordPresence; - memset(&discordPresence, 0, sizeof(discordPresence)); - discordPresence.state = "Playing with friends!"; - //sprintf(buffer, "Frustration level: %d", FrustrationLevel); - //discordPresence.details = buffer; - discordPresence.startTimestamp = StartTime; - //discordPresence.endTimestamp = time(0) + 5 * 60; - discordPresence.largeImageKey = "mainlogo"; - //discordPresence.smallImageKey = "logo"; - //discordPresence.partyId = "party1234"; - //discordPresence.partySize = 1; - //discordPresence.partyMax = 6; - //discordPresence.matchSecret = "xyzzy"; - //discordPresence.joinSecret = "join"; - //discordPresence.spectateSecret = "look"; - //discordPresence.instance = 0; - Discord_UpdatePresence(&discordPresence); - } - else { - Discord_ClearPresence(); - } +#include +struct DInfo{ + std::string Name; + std::string Tag; + std::string DID; +}; +DInfo* DiscordInfo = nullptr; +void DASM(); +int64_t StartTime; +void updateDiscordPresence(){ + //if (SendPresence) { + //char buffer[256]; + DiscordRichPresence discordPresence; + memset(&discordPresence, 0, sizeof(discordPresence)); + std::string P = Sec("Playing with friends!"); + discordPresence.state = P.c_str(); + //sprintf(buffer, "Frustration level: %d", FrustrationLevel); + //discordPresence.details = buffer; + discordPresence.startTimestamp = StartTime; + //discordPresence.endTimestamp = time(0) + 5 * 60; + std::string L = Sec("mainlogo"); + discordPresence.largeImageKey = L.c_str(); + //discordPresence.smallImageKey = "logo"; + //discordPresence.partyId = "party1234"; + //discordPresence.partySize = 1; + //discordPresence.partyMax = 6; + //discordPresence.matchSecret = "xyzzy"; + //discordPresence.joinSecret = "join"; + //discordPresence.spectateSecret = "look"; + //discordPresence.instance = 0; + Discord_UpdatePresence(&discordPresence); + //} + //else { + // Discord_ClearPresence(); + //} } - -std::string ATH(const std::string& text){ - std::string hex; - for (const char&c : text) { - int des = (int)c; - char*C = new char[5]{0}; - _itoa_s(des,C,5,16); - hex += C; - delete[] C; - } - return hex; +void handleDiscordReady(const DiscordUser* User){ + DiscordInfo = new DInfo{ + LocalEnc(User->username), + LocalEnc(User->discriminator), + LocalEnc(User->userId) + }; } - -static void handleDiscordReady(const DiscordUser* connectedUser) -{ - /*printf("\nDiscord: connected to user %s#%s - %s\n", - connectedUser->username, - connectedUser->discriminator, - connectedUser->userId);*/ - GlobalInfo.emplace_back(connectedUser->username); - GlobalInfo.emplace_back(ATH(connectedUser->discriminator)); - GlobalInfo.emplace_back(ATH(connectedUser->userId)); - GlobalInfo.emplace_back(connectedUser->userId); -} - -static void handleDiscordDisconnected(int errcode, const char* message) -{ - if(Dev)printf("\nDiscord: disconnected (%d: %s)\n", errcode, message); -} - -static void handleDiscordError(int errcode, const char* message) -{ - if(Dev)printf("\nDiscord: error (%d: %s)\n", errcode, message); -} - -static void handleDiscordJoin(const char* secret) -{ - if(Dev)printf("\nDiscord: join (%s)\n", secret); -} - -static void handleDiscordSpectate(const char* secret) -{ - if(Dev)printf("\nDiscord: spectate (%s)\n", secret); -} - -static void handleDiscordJoinRequest(const DiscordUser* request) -{ - /* int response = -1; - char yn[4]; - printf("\nDiscord: join request from %s#%s - %s\n", - request->username, - request->discriminator, - request->userId); - do { - printf("Accept? (y/n)"); - if (!prompt(yn, sizeof(yn))) { - break; - } - - if (!yn[0]) { - continue; - } - - if (yn[0] == 'y') { - response = DISCORD_REPLY_YES; - break; - } - - if (yn[0] == 'n') { - response = DISCORD_REPLY_NO; - break; - } - } while (1); - if (response != -1) { - Discord_Respond(request->userId, response); - }*/ -} - - -static void discordInit() -{ +void discordInit(){ DiscordEventHandlers handlers; memset(&handlers, 0, sizeof(handlers)); handlers.ready = handleDiscordReady; - handlers.disconnected = handleDiscordDisconnected; + /*handlers.disconnected = handleDiscordDisconnected; handlers.errored = handleDiscordError; handlers.joinGame = handleDiscordJoin; handlers.spectateGame = handleDiscordSpectate; - handlers.joinRequest = handleDiscordJoinRequest; - Discord_Initialize(APPLICATION_ID, &handlers, 1,nullptr); + handlers.joinRequest = handleDiscordJoinRequest;*/ + std::string a = Sec("629743237988352010"); + Discord_Initialize(a.c_str(), &handlers, 1,nullptr); } - -[[noreturn]] static void Loop() -{ - char line[512]; - char* space; - - StartTime = time(0); - +[[noreturn]] void Loop(){ + StartTime = time(nullptr); while (true) { updateDiscordPresence(); - -#ifdef DISCORD_DISABLE_IO_THREAD - Discord_UpdateConnection(); -#endif + #ifdef DISCORD_DISABLE_IO_THREAD + Discord_UpdateConnection(); + #endif Discord_RunCallbacks(); - if(GlobalInfo.empty()){ + if(DiscordInfo == nullptr){ std::this_thread::sleep_for(std::chrono::milliseconds(250)); - }else std::this_thread::sleep_for(std::chrono::milliseconds(2000)); + }else std::this_thread::sleep_for(std::chrono::seconds(2)); } } - -void SecurityCheck2(){ - int i = 0; - std::ifstream f(hta(EName), std::ios::binary); - f.seekg(0, std::ios_base::end); - std::streampos fileSize = f.tellg(); - if(IsDebuggerPresent() || fileSize > 0x60B5F){ - i++; - GlobalInfo.clear(); - } - if(i)GlobalInfo.clear(); - f.close(); -} - [[noreturn]] void SecurityLoop(){ - static std::string t; - static std::string t1; - static std::string t2; - t.clear(); - t1.clear(); - t2.clear(); + std::string t,t1,t2; while(true){ - if(!GlobalInfo.empty() && GlobalInfo.size() == 4){ + if(DiscordInfo != nullptr){ if(t.empty()){ - t = GlobalInfo.at(0); - t1 = GlobalInfo.at(1); - t2 = GlobalInfo.at(2); - }else if(t2 != ATH(GlobalInfo.at(3)) || t != GlobalInfo.at(0) || - t1 != GlobalInfo.at(1) || t2 != GlobalInfo.at(2))exit(0); - } - SecurityCheck2(); - if(IsDebuggerPresent())GlobalInfo.clear(); + t = LocalDec(DiscordInfo->Name); + t1 = LocalDec(DiscordInfo->Tag); + t2 = LocalDec(DiscordInfo->DID); + }else if(t2 != LocalDec(DiscordInfo->DID) || + t != LocalDec(DiscordInfo->Name) || t1 != LocalDec(DiscordInfo->Tag))DiscordInfo = nullptr; + }else if(!t.empty())DiscordInfo->DID.clear(); + DASM(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } - - -void Discord_Main(){ +void DMain(){ auto*S = new std::thread(SecurityLoop); S->detach(); delete S; discordInit(); Loop(); - Discord_Shutdown(); } - +std::string GetDName(){ + return LocalDec(DiscordInfo->Name); +} +std::string GetDTag(){ + return LocalDec(DiscordInfo->Tag); +} +std::string GetDID(){ + return LocalDec(DiscordInfo->DID); +} +void DAboard(){ + DiscordInfo = nullptr; +} +void ErrorAboard(){ + error(Sec("Discord timeout! please start the discord app and try again after 30 secs")); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(6); +} +void Discord_Main(){ + std::thread t1(DMain); + t1.detach(); + info(Sec("Connecting to discord client...")); + int C = 0; + while(DiscordInfo == nullptr && C < 80){ + std::this_thread::sleep_for(std::chrono::milliseconds(300)); + C++; + } + if(DiscordInfo == nullptr)ErrorAboard(); +} diff --git a/src/GameStart.cpp b/src/GameStart.cpp index b31b5fd..fdc1554 100644 --- a/src/GameStart.cpp +++ b/src/GameStart.cpp @@ -1,55 +1,78 @@ /// -/// Created by Anonymous275 on 5/2/2020 +/// Created by Anonymous275 on 7/19/2020 /// +#include "Security/Enc.h" #include +#include "Startup.h" +#include "Logger.h" #include #include - +unsigned long GamePID = 0; std::string QueryKey(HKEY hKey,int ID); -void SystemExec(const std::string&cmd); -void Exit(const std::string& Msg); - +void DeleteKey(){ + HKEY hKey; + LPCTSTR sk = Sec("Software\\BeamNG\\BeamNG.drive"); + RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); + RegDeleteValueA(hKey, Sec("userpath_override")); +} std::string Write(const std::string&Path){ HKEY hKey; - LPCTSTR sk = TEXT("Software\\BeamNG\\BeamNG.drive"); + LPCTSTR sk = Sec("Software\\BeamNG\\BeamNG.drive"); LONG openRes = RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); - if (openRes != ERROR_SUCCESS)Exit("Error! Please launch the game at least once"); + if (openRes != ERROR_SUCCESS){ + error(Sec("Please launch the game at least once")); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(5); + } std::string Query = QueryKey(hKey,4); - LONG setRes = RegSetValueEx(hKey, TEXT("userpath_override"), 0, REG_SZ, (LPBYTE)Path.c_str(), Path.size()); - if(setRes != ERROR_SUCCESS)Exit("Error! Failed to launch the game code 1"); + LONG setRes = RegSetValueEx(hKey, Sec("userpath_override"), 0, REG_SZ, (LPBYTE)Path.c_str(), DWORD(Path.size())); + if(setRes != ERROR_SUCCESS){ + error(Sec("Failed to launch the game")); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(5); + } RegCloseKey(hKey); return Query; } -void DeleteKey(){ - HKEY hKey; - LPCTSTR sk = TEXT("Software\\BeamNG\\BeamNG.drive"); - RegOpenKeyEx(HKEY_CURRENT_USER, sk, 0, KEY_ALL_ACCESS, &hKey); - RegDeleteValueA(hKey, TEXT("userpath_override")); -} void RollBack(const std::string&Val,int T){ std::this_thread::sleep_for(std::chrono::seconds(T)); - if(!Val.empty())Write(Val); - else DeleteKey(); + if(!Val.empty()){ + if(Write(Val) == Val)DeleteKey(); + }else DeleteKey(); } - -void SetPID(DWORD PID); -void StartGame(const std::string&ExeDir,const std::string&Current){ +std::string Restore; +void OnExit(){ + RollBack(Restore,0); +} +void StartGame(std::string Dir,std::string Current){ + Current = Current.substr(0,Current.find_last_of('\\')) + Sec("\\BeamNG\\"); BOOL bSuccess = FALSE; PROCESS_INFORMATION pi; STARTUPINFO si = {0}; si.cb = sizeof(si); - std::string BaseDir = ExeDir.substr(0,ExeDir.find_last_of('\\')); - bSuccess = CreateProcessA(ExeDir.c_str(), nullptr, nullptr, nullptr, TRUE, 0, nullptr, BaseDir.c_str(), &si, &pi); - if (bSuccess) - { - std::cout << "Game Launched!\n"; - SetPID(pi.dwProcessId); - std::thread RB(RollBack,Write(Current),7); + std::string BaseDir = Dir + Sec("\\Bin64"); + Dir += Sec(R"(\Bin64\BeamNG.drive.x64.exe)"); + bSuccess = CreateProcessA(Dir.c_str(), nullptr, nullptr, nullptr, TRUE, 0, nullptr, BaseDir.c_str(), &si, &pi); + if (bSuccess){ + info(Sec("Game Launched!")); + GamePID = pi.dwProcessId; + Restore = Write(Current); + atexit(OnExit); + std::thread RB(RollBack,Restore,7); RB.detach(); WaitForSingleObject(pi.hProcess, INFINITE); - std::cout << "\nGame Closed! launcher closing in 5 secs\n"; - }else std::cout << "\nFailed to Launch the game! launcher closing in 5 secs\n"; - RollBack(Write(Current),0); + error(Sec("Game Closed! launcher closing soon")); + RollBack(Restore,0); + }else{ + error(Sec("Failed to Launch the game! launcher closing soon")); + RollBack(Write(Current),0); + } std::this_thread::sleep_for(std::chrono::seconds(5)); exit(2); -} \ No newline at end of file +} +void InitGame(const std::string& Dir,const std::string&Current){ + if(!Dev){ + std::thread Game(StartGame, Dir, Current); + Game.detach(); + } +} diff --git a/src/Logger.cpp b/src/Logger.cpp new file mode 100644 index 0000000..65b2020 --- /dev/null +++ b/src/Logger.cpp @@ -0,0 +1,80 @@ +/// +/// Created by Anonymous275 on 7/17/2020 +/// +#include "Security/Enc.h" +#include "Startup.h" +#include "Logger.h" +#include +#include +#include +std::string getDate() { + typedef std::chrono::duration>::type> days; + std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); + std::chrono::system_clock::duration tp = now.time_since_epoch(); + days d = std::chrono::duration_cast(tp);tp -= d; + auto h = std::chrono::duration_cast(tp);tp -= h; + auto m = std::chrono::duration_cast(tp);tp -= m; + auto s = std::chrono::duration_cast(tp);tp -= s; + time_t tt = std::chrono::system_clock::to_time_t(now); + tm local_tm{}; + localtime_s(&local_tm,&tt); + std::stringstream date; + int S = local_tm.tm_sec; + int M = local_tm.tm_min; + int H = local_tm.tm_hour; + std::string Secs = (S > 9 ? std::to_string(S) : "0" + std::to_string(S)); + std::string Min = (M > 9 ? std::to_string(M) : "0" + std::to_string(M)); + std::string Hour = (H > 9 ? std::to_string(H) : "0" + std::to_string(H)); + date + << "[" + << local_tm.tm_mday << "/" + << local_tm.tm_mon + 1 << "/" + << local_tm.tm_year + 1900 << " " + << Hour << ":" + << Min << ":" + << Secs + << "] "; + return date.str(); +} +void InitLog(){ + std::ofstream LFS; + LFS.open (Sec("Launcher.log")); + if(!LFS.is_open()){ + error(Sec("logger file init failed!")); + }else LFS.close(); +} +void addToLog(const std::string& Line){ + std::ofstream LFS; + LFS.open (Sec("Launcher.log"), std::ios_base::app); + LFS << Line.c_str(); + LFS.close(); +} +void info(const std::string& toPrint) { + std::string Print = getDate() + Sec("[INFO] ") + toPrint + "\n"; + std::cout << Print; + addToLog(Print); +} +void debug(const std::string& toPrint) { + if(!Dev)return; + std::string Print = getDate() + Sec("[DEBUG] ") + toPrint + "\n"; + std::cout << Print; + addToLog(Print); +} +void warn(const std::string& toPrint){ + std::string Print = getDate() + Sec("[WARN] ") + toPrint + "\n"; + std::cout << Print; + addToLog(Print); +} +void error(const std::string& toPrint) { + static int ECounter = 0; + std::string Print = getDate() + Sec("[ERROR] ") + toPrint + "\n"; + std::cout << Print; + addToLog(Print); + if(ECounter > 10)exit(7); + ECounter++; +} +void except(const std::string& toPrint) { + std::string Print = getDate() + Sec("[EXCEP] ") + toPrint + "\n"; + std::cout << Print; + addToLog(Print); +} diff --git a/src/Memory/Memory.cpp b/src/Memory/Memory.cpp index 7194369..76c8b21 100644 --- a/src/Memory/Memory.cpp +++ b/src/Memory/Memory.cpp @@ -31,8 +31,7 @@ int Memory::GetProcessId(const std::string& processName) { return pe32.th32ProcessID; } -long long Memory::GetModuleBase(HANDLE processHandle, const std::string &sModuleName) -{ +long long Memory::GetModuleBase(HANDLE processHandle, const std::string &sModuleName){ HMODULE *hModules = nullptr; char szBuf[50]; DWORD cModules; @@ -74,8 +73,7 @@ void PrintAllBases(HANDLE processHandle){ delete[] hModules; } -BOOL Memory::SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) -{ +BOOL Memory::SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege){ TOKEN_PRIVILEGES tp; LUID luid; @@ -215,7 +213,7 @@ double Memory::ReadPointerDouble(HANDLE processHandle, long long startAddress, i std::string Memory::ReadText(HANDLE processHandle, long long address) { if (address == -1) return "-1"; - char buffer = !0; + char buffer = 1; char* stringToRead = new char[128]; SIZE_T NumberOfBytesToRead = sizeof(buffer); SIZE_T NumberOfBytesActuallyRead; diff --git a/src/Memory/Memory.hpp b/src/Memory/Memory.hpp index d942a4c..e6e648e 100644 --- a/src/Memory/Memory.hpp +++ b/src/Memory/Memory.hpp @@ -9,8 +9,7 @@ #include #include -class Memory -{ +class Memory{ public: DWORD PID = 0; int GetProcessId(const std::string& processName); diff --git a/src/Memory/Reader.cpp b/src/Memory/Reader.cpp index 6635478..1916f14 100644 --- a/src/Memory/Reader.cpp +++ b/src/Memory/Reader.cpp @@ -1,11 +1,14 @@ /// /// Created by Anonymous275 on 6/17/2020 /// +#include "Network/network.h" +#include "Security/Game.h" +#include "Security/Enc.h" #include "Memory.hpp" +#include "Startup.h" #include #include -extern std::string MStatus; -extern bool Dev; + Memory Game; std::string GameVer(HANDLE processHandle, long long Address){ //lib_Beam @@ -15,15 +18,16 @@ std::string GameVer(HANDLE processHandle, long long Address){ } std::string LoadedMap(HANDLE processHandle, long long Address){ //lib_Beam - Address += 0x1B0688; - std::vector Off = {0x2F8,0x0}; + //History : 0x1B0688 + Address += 0x1A1668; + std::vector Off = {0x140,0x0}; return Game.ReadPointerText(processHandle,Address,Off); } -void SetPID(DWORD PID){ - Game.PID = PID; -} -[[noreturn]] void MemoryInit(){ - if(Game.PID == 0 && !Dev)exit(4); + +void MemoryInit(){ + if(Dev)return; + Game.PID = GamePID; + if(Game.PID == 0)exit(4); HANDLE processHandle; long long ExeBase; //BeamNG.drive.x64.exe long long Lib1 = 0x180000000; //libbeamng.x64.dll Contains Vehicle Data diff --git a/src/Network 2.0/GlobalHandler.cpp b/src/Network 2.0/GlobalHandler.cpp deleted file mode 100644 index 6cfe5d2..0000000 --- a/src/Network 2.0/GlobalHandler.cpp +++ /dev/null @@ -1,249 +0,0 @@ -//// -//// Created by Anonymous275 on 3/3/2020. -//// -#include -#include -#include -#include -#include -#include - -int ClientID = -1; -extern int DEFAULT_PORT; -std::chrono::time_point PingStart,PingEnd; -bool TCPTerminate = false; -bool Terminate = false; -bool CServer = true; -bool gameConected = false; -SOCKET ClientSocket; -extern bool Dev; -int ping = -1; - -void GameSend(const std::string&Data){ - if(TCPTerminate || !gameConected || ClientSocket == -1)return; - int iSendResult = send(ClientSocket, (Data + "\n").c_str(), int(Data.length()) + 1, 0); - if (iSendResult == SOCKET_ERROR) { - if (Dev)std::cout << "(Proxy) send failed with error: " << WSAGetLastError() << std::endl; - } else { - if (Dev && Data.length() > 1000) { - std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << std::endl; - } - //std::cout << "(Launcher->Game) Bytes sent: " << iSendResult << " : " << Data << std::endl; - } -} -void SendLarge(const std::string&Data); -void TCPSend(const std::string&Data); -void UDPSend(const std::string&Data); -void ServerSend(const std::string&Data, bool Rel){ - if(Terminate || Data.empty())return; - char C = 0; - bool Ack = false; - if(Data.length() > 3)C = Data.at(0); - if (C == 'O' || C == 'T' || C == 'C')Ack = true; - if(Ack || Rel){ - if(Ack || Data.length() > 1000)SendLarge(Data); - else TCPSend(Data); - }else UDPSend(Data); - - if (Dev && Data.length() > 1000) { - std::cout << "(Launcher->Server) Bytes sent: " + std::to_string(Data.length()) + " : " - + Data.substr(0, 10) - + Data.substr(Data.length() - 10) + "\n"; - }else if(Dev && C == 'Z'){ - //std::cout << "(Game->Launcher) : " << Data << std::endl; - } -} - - -void AutoPing(){ - while(!Terminate){ - ServerSend("p",false); - PingStart = std::chrono::high_resolution_clock::now(); - std::this_thread::sleep_for(std::chrono::seconds (1)); - } -} - -std::string UlStatus = "Ulstart"; -std::string MStatus = " "; -void ServerParser(const std::string& Data){ - if(Data.empty())return; - char Code = Data.at(0),SubCode = 0; - if(Data.length() > 1)SubCode = Data.at(1); - switch (Code) { - case 'P': - ClientID = std::stoi(Data.substr(1)); - break; - case 'p': - PingEnd = std::chrono::high_resolution_clock::now(); - ping = std::chrono::duration_cast(PingEnd-PingStart).count(); - return; - case 'M': - MStatus = Data; - UlStatus = "Uldone"; - return; - } - GameSend(Data); -} - -void TCPClientMain(const std::string& IP,int Port); -void UDPClientMain(const std::string& IP,int Port); -void NetMain(const std::string& IP, int Port){ - std::thread Ping(AutoPing); - Ping.detach(); - UDPClientMain(IP,Port); - CServer = true; - Terminate = true; - std::cout << "Connection Terminated!" << std::endl; -} -extern SOCKET UDPSock; -extern SOCKET TCPSock; -void Reset(){ - TCPTerminate = false; - gameConected = false; - Terminate = false; - UlStatus = "Ulstart"; - MStatus = " "; - if(UDPSock != SOCKET_ERROR)closesocket(UDPSock); - UDPSock = -1; - if(TCPSock != SOCKET_ERROR)closesocket(TCPSock); - TCPSock = -1; -} -std::string Compress(const std::string&Data); -std::string Decompress(const std::string&Data); -void TCPGameServer(const std::string& IP, int Port){ - if(Dev)std::cout << "Game server Started! " << IP << ":" << Port << std::endl; - do { - Reset(); - if(CServer) { - std::thread Client(TCPClientMain, IP, Port); - Client.detach(); - } - if(Dev)std::cout << "Game server on Start" << std::endl; - WSADATA wsaData; - int iResult; - SOCKET ListenSocket = INVALID_SOCKET; - SOCKET Socket = INVALID_SOCKET; - - struct addrinfo *result = nullptr; - struct addrinfo hints{}; - char recvbuf[10000]; - int recvbuflen = 10000; - - // Initialize Winsock - iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) { - if(Dev)std::cout << "(Proxy) WSAStartup failed with error: " << iResult << std::endl; - exit(-1); - } - - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_PASSIVE; - // Resolve the server address and port - iResult = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT+1).c_str(), &hints, &result); - if (iResult != 0) { - if(Dev)std::cout << "(Proxy) getaddrinfo failed with error: " << iResult << std::endl; - WSACleanup(); - break; - } - - // Create a socket for connecting to server - ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); - if (ListenSocket == INVALID_SOCKET) { - if(Dev)std::cout << "(Proxy) socket failed with error: " << WSAGetLastError() << std::endl; - freeaddrinfo(result); - WSACleanup(); - break; - } - - // Setup the TCP listening socket - iResult = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen); - if (iResult == SOCKET_ERROR) { - if(Dev)std::cout << "(Proxy) bind failed with error: " << WSAGetLastError() << std::endl; - freeaddrinfo(result); - closesocket(ListenSocket); - WSACleanup(); - break; - } - - freeaddrinfo(result); - - iResult = listen(ListenSocket, SOMAXCONN); - if (iResult == SOCKET_ERROR) { - if(Dev)std::cout << "(Proxy) listen failed with error: " << WSAGetLastError() << std::endl; - closesocket(ListenSocket); - WSACleanup(); - continue; - } - Socket = accept(ListenSocket, nullptr, nullptr); - if (Socket == INVALID_SOCKET) { - if(Dev)std::cout << "(Proxy) accept failed with error: " << WSAGetLastError() << std::endl; - closesocket(ListenSocket); - WSACleanup(); - continue; - } - closesocket(ListenSocket); - if(Dev)std::cout << "(Proxy) Game Connected!" << std::endl; - gameConected = true; - if(CServer){ - std::thread t1(NetMain, IP, Port); - t1.detach(); - CServer = false; - } - - ClientSocket = Socket; - do { - //std::cout << "(Proxy) Waiting for Game Data..." << std::endl; - iResult = recv(Socket, recvbuf, recvbuflen, 0); - if (iResult > 0) { - std::string buff; - buff.resize(iResult*2); - memcpy(&buff[0],recvbuf,iResult); - buff.resize(iResult); - - ServerSend(buff,false); - - } else if (iResult == 0) { - if(Dev)std::cout << "(Proxy) Connection closing...\n"; - closesocket(Socket); - WSACleanup(); - Terminate = true; - continue; - } else { - if(Dev)std::cout << "(Proxy) recv failed with error: " << WSAGetLastError() << std::endl; - closesocket(Socket); - WSACleanup(); - continue; - } - } while (iResult > 0); - - iResult = shutdown(Socket, SD_SEND); - if (iResult == SOCKET_ERROR) { - if(Dev)std::cout << "(Proxy) shutdown failed with error: " << WSAGetLastError() << std::endl; - TCPTerminate = true; - Terminate = true; - closesocket(Socket); - WSACleanup(); - continue; - } - closesocket(Socket); - WSACleanup(); - }while (!TCPTerminate); -} - -void VehicleNetworkStart(); -void CoreNetworkThread(); -void ProxyStart(){ - std::thread t1(CoreNetworkThread); - if(Dev)std::cout << "Core Network Started!\n"; - t1.join(); -} - -void ProxyThread(const std::string& IP, int Port){ - std::thread GameThread(TCPGameServer,IP,Port); - GameThread.detach(); - /*std::thread t2(VehicleNetworkStart); - t2.detach();*/ -} \ No newline at end of file diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp new file mode 100644 index 0000000..44895a3 --- /dev/null +++ b/src/Network/Core.cpp @@ -0,0 +1,198 @@ +/// +/// Created by Anonymous275 on 7/20/2020 +/// +#include "Network/network.h" +#include "Security/Enc.h" +#include "Curl/http.h" +#include +#include +#include "Memory.h" +#include "Logger.h" +#include +#include +std::set* ConfList = nullptr; +bool TCPTerminate = false; +int DEFAULT_PORT = 4444; +bool Terminate = false; +std::string UlStatus; +std::string MStatus; +bool once = false; +bool ModLoaded; +long long ping = -1; +void StartSync(const std::string &Data){ + UlStatus = Sec("UlLoading..."); + TCPTerminate = false; + Terminate = false; + ConfList->clear(); + ping = -1; + std::thread GS(TCPGameServer,Data.substr(1,Data.find(':')-1),std::stoi(Data.substr(Data.find(':')+1))); + GS.detach(); +} +void Parse(std::string Data,SOCKET CSocket){ + char Code = Data.at(0), SubCode = 0; + if(Data.length() > 1)SubCode = Data.at(1); + switch (Code){ + case 'A': + Data = Data.substr(0,1); + break; + case 'B': + NetReset(); + Terminate = true; + TCPTerminate = true; + //if(!Dev){ + Data = Code + HTTP_REQUEST(Sec("s1.yourthought.co.uk/servers-info"),3599); + //}else Data.clear(); + break; + case 'C': + ListOfMods.clear(); + StartSync(Data); + info(Sec("Connecting to server")); + while(ListOfMods.empty() && !Terminate){ + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if(ListOfMods == "-")Data = "L"; + else Data = "L"+ListOfMods; + break; + case 'U': + if(SubCode == 'l')Data = UlStatus; + if(SubCode == 'p')Data = "Up" + std::to_string(ping); + if(!SubCode)Data = std::string(UlStatus) + "\n" + "Up" + std::to_string(ping); + break; + case 'M': + Data = MStatus; + break; + case 'Q': + if(SubCode == 'S'){ + NetReset(); + Terminate = true; + TCPTerminate = true; + ping = -1; + } + if(SubCode == 'G')exit(2); + Data.clear(); + break; + case 'R': //will send mod name + if(ConfList->find(Data) == ConfList->end()){ + ConfList->insert(Data); + ModLoaded = true; + } + Data.clear(); + break; + default: + Data.clear(); + break; + } + if(!Data.empty() && CSocket != -1){ + int res = send(CSocket, (Data+"\n").c_str(), int(Data.size())+1, 0); + if(res < 0){ + debug(Sec("(Core) send failed with error: ") + std::to_string(WSAGetLastError())); + } + } +} +void GameHandler(SOCKET Client){ + if (!once){ + std::thread Memory(MemoryInit); + Memory.detach(); + once = true; + } + char buf[64000]; + int res,len = 64000; + do{ + res = recv(Client, buf, len, 0); + if(res < 1)break; + std::string data(buf, res); + std::thread Respond(Parse, data, Client); + Respond.detach(); + }while(res > 0); + if (res == 0) { + debug(Sec("(Core) Connection closing")); + } else { + debug(Sec("(Core) recv failed with error: ") + std::to_string(WSAGetLastError())); + } + closesocket(Client); +} +void localRes(){ + MStatus = " "; + UlStatus = Sec("Ulstart"); + if(ConfList != nullptr){ + ConfList->clear(); + delete ConfList; + ConfList = nullptr; + } + ConfList = new std::set; +} +void CoreMain() { + debug(Sec("Core Network on start!")); + WSADATA wsaData; + SOCKET LSocket,CSocket; + struct addrinfo *res = nullptr; + struct addrinfo hints{}; + int iRes = WSAStartup(514, &wsaData); //2.2 + if (iRes)debug(Sec("WSAStartup failed with error: ") + std::to_string(iRes)); + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT).c_str(), &hints, &res); + if (iRes){ + debug(Sec("(Core) addr info failed with error: ") + std::to_string(iRes)); + WSACleanup(); + return; + } + LSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + if (LSocket == -1){ + debug(Sec("(Core) socket failed with error: ") + std::to_string(WSAGetLastError())); + freeaddrinfo(res); + WSACleanup(); + return; + } + iRes = bind(LSocket, res->ai_addr, int(res->ai_addrlen)); + if (iRes == SOCKET_ERROR) { + error(Sec("(Core) bind failed with error: ") + std::to_string(WSAGetLastError())); + freeaddrinfo(res); + closesocket(LSocket); + WSACleanup(); + return; + } + iRes = listen(LSocket, SOMAXCONN); + if (iRes == SOCKET_ERROR) { + debug(Sec("(Core) listen failed with error: ") + std::to_string(WSAGetLastError())); + freeaddrinfo(res); + closesocket(LSocket); + WSACleanup(); + return; + } + do{ + CSocket = accept(LSocket, nullptr, nullptr); + if (CSocket == -1) { + error(Sec("(Core) accept failed with error: ") + std::to_string(WSAGetLastError())); + continue; + } + localRes(); + info(Sec("Game Connected!")); + GameHandler(CSocket); + warn(Sec("Game Reconnecting...")); + }while(CSocket); + closesocket(LSocket); + WSACleanup(); +} +int Handle(EXCEPTION_POINTERS *ep){ + char* hex = new char[100]; + sprintf_s(hex,100, "%lX", ep->ExceptionRecord->ExceptionCode); + except(Sec("(Core) Code : ") + std::string(hex)); + delete [] hex; + return 1; +} +[[noreturn]] void CoreNetwork(){ + while(true){ + __try{ + CoreMain(); + }__except(Handle(GetExceptionInformation())){} + std::this_thread::sleep_for(std::chrono::seconds(1)); + } +} + + + + diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp new file mode 100644 index 0000000..88afdb2 --- /dev/null +++ b/src/Network/GlobalHandler.cpp @@ -0,0 +1,202 @@ +/// +/// Created by Anonymous275 on 7/25/2020 +/// +#include "Network/network.h" +#include "Security/Enc.h" +#include +#include +#include "Logger.h" +#include +#include +#include +std::chrono::time_point PingStart,PingEnd; +bool GConnected = false; +bool CServer = true; +extern SOCKET UDPSock; +extern SOCKET TCPSock; +SOCKET CSocket; +void GameSend(const std::string&Data){ + if(TCPTerminate || !GConnected || CSocket == -1)return; + int iSRes = send(CSocket, (Data + "\n").c_str(), int(Data.size()) + 1, 0); + if (iSRes == SOCKET_ERROR) { + debug(Sec("(Proxy) send failed with error: ") + std::to_string(WSAGetLastError())); + } else if (Data.length() > 1000){ + debug(Sec("(Launcher->Game) Bytes sent: ") + std::to_string(iSRes)); + } +} +void ServerSend(std::string Data, bool Rel){ + if(Terminate || Data.empty())return; + char C = 0; + bool Ack = false; + int DLen = int(Data.length()); + if(DLen > 3)C = Data.at(0); + if (C == 'O' || C == 'T')Ack = true; + if(Ack || Rel){ + if(Ack || DLen > 1000)SendLarge(Data); + else TCPSend(Data); + }else UDPSend(Data); + + if (DLen > 1000) { + debug(Sec("(Launcher->Server) Bytes sent: ") + std::to_string(Data.length()) + " : " + + Data.substr(0, 10) + + Data.substr(Data.length() - 10)); + }else if(C == 'Z'){ + //debug("(Game->Launcher) : " + Data); + } +} +void NetReset(){ + TCPTerminate = false; + GConnected = false; + Terminate = false; + UlStatus = Sec("Ulstart"); + MStatus = " "; + if(UDPSock != SOCKET_ERROR)closesocket(UDPSock); + UDPSock = -1; + if(TCPSock != SOCKET_ERROR)closesocket(TCPSock); + TCPSock = -1; + ClearAll(); +} + +SOCKET SetupListener(){ + static SOCKET LSocket = -1; + if(LSocket != -1)return LSocket; + struct addrinfo *result = nullptr; + struct addrinfo hints{}; + WSADATA wsaData; + int iRes = WSAStartup(514, &wsaData); //2.2 + if (iRes != 0) { + error(Sec("(Proxy) WSAStartup failed with error: ") + std::to_string(iRes)); + return -1; + } + ZeroMemory(&hints, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + hints.ai_flags = AI_PASSIVE; + iRes = getaddrinfo(nullptr, std::to_string(DEFAULT_PORT+1).c_str(), &hints, &result); + if (iRes != 0) { + error(Sec("(Proxy) info failed with error: ") + std::to_string(iRes)); + WSACleanup(); + } + LSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); + if (LSocket == -1) { + error(Sec("(Proxy) socket failed with error: ") + std::to_string(WSAGetLastError())); + freeaddrinfo(result); + WSACleanup(); + return -1; + } + iRes = bind(LSocket, result->ai_addr, (int) result->ai_addrlen); + if (iRes == SOCKET_ERROR) { + error(Sec("(Proxy) bind failed with error: ") + std::to_string(WSAGetLastError())); + freeaddrinfo(result); + closesocket(LSocket); + WSACleanup(); + return -1; + } + freeaddrinfo(result); + iRes = listen(LSocket, SOMAXCONN); + if (iRes == SOCKET_ERROR) { + error(Sec("(Proxy) listen failed with error: ") + std::to_string(WSAGetLastError())); + closesocket(LSocket); + WSACleanup(); + return -1; + } + return LSocket; +} +void AutoPing(){ + while(!Terminate){ + ServerSend(Sec("p"),false); + PingStart = std::chrono::high_resolution_clock::now(); + std::this_thread::sleep_for(std::chrono::seconds (1)); + } +} +int ClientID = -1; +void ParserAsync(const std::string& Data){ + if(Data.empty())return; + char Code = Data.at(0),SubCode = 0; + if(Data.length() > 1)SubCode = Data.at(1); + switch (Code) { + case 'P': + ClientID = std::stoi(Data.substr(1)); + break; + case 'p': + PingEnd = std::chrono::high_resolution_clock::now(); + if(PingStart > PingEnd)ping = 0; + else ping = std::chrono::duration_cast(PingEnd-PingStart).count(); + return; + case 'M': + MStatus = Data; + UlStatus = Sec("Uldone"); + return; + default: + break; + } + GameSend(Data); +} +void ServerParser(const std::string& Data){ + std::thread Async(ParserAsync,Data); + Async.detach(); +} +void NetMain(const std::string& IP, int Port){ + std::thread Ping(AutoPing); + Ping.detach(); + UDPClientMain(IP,Port); + CServer = true; + Terminate = true; + info(Sec("Connection Terminated!")); +} +void TCPGameServer(const std::string& IP, int Port){ + SOCKET LSocket = SetupListener(); + while (!TCPTerminate && LSocket != -1){ + GConnected = false; + if(!CServer){ + warn(Sec("Connection still alive terminating")); + NetReset(); + TCPTerminate = true; + Terminate = true; + break; + } + if(CServer) { + std::thread Client(TCPClientMain, IP, Port); + Client.detach(); + } + CSocket = accept(LSocket, nullptr, nullptr); + if (CSocket == -1) { + error(Sec("(Proxy) accept failed with error: ") + std::to_string(WSAGetLastError())); + break; + } + debug(Sec("(Proxy) Game Connected!")); + GConnected = true; + if(CServer){ + std::thread t1(NetMain, IP, Port); + t1.detach(); + CServer = false; + } + char buf[10000]; + int Res,len = 10000; + ZeroMemory(buf, len); + do{ + Res = recv(CSocket,buf,len,0); + if(Res < 1)break; + std::string t; + std::string buff(Res,0); + memcpy_s(&buff[0],Res,buf,Res); + std::stringstream ss(buff); + int S = 0; + while (std::getline(ss, t, '\n')) { + ServerSend(t,false); + S++; + } + if(S > 3)std::cout << S << std::endl; + }while(Res > 0); + if(Res == 0)debug(Sec("(Proxy) Connection closing")); + else debug(Sec("(Proxy) recv failed error : ") + std::to_string(WSAGetLastError())); + } + TCPTerminate = true; + GConnected = false; + Terminate = true; + if(LSocket == -1){ + UlStatus = Sec("Critical error! check the launcher logs"); + } + if(CSocket != SOCKET_ERROR)closesocket(CSocket); +} \ No newline at end of file diff --git a/src/http.cpp b/src/Network/Http.cpp similarity index 69% rename from src/http.cpp rename to src/Network/Http.cpp index 1002281..e77882a 100644 --- a/src/http.cpp +++ b/src/Network/Http.cpp @@ -1,29 +1,30 @@ /// -/// Created by Anonymous275 on 3/17/2020 +/// Created by Anonymous275 on 7/18/2020 /// - #define CURL_STATICLIB -#include "curl/curl.h" +#include "Security/Game.h" +#include "Security/Enc.h" +#include "Curl/curl.h" #include - -void Exit(const std::string& Msg); -static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) -{ +static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp){ ((std::string*)userp)->append((char*)contents, size * nmemb); return size * nmemb; } std::string HTTP_REQUEST(const std::string& IP,int port){ CURL *curl; - //CURLcode res; + CURLcode res; std::string readBuffer; curl = curl_easy_init(); if(curl) { curl_easy_setopt(curl, CURLOPT_URL, IP.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(curl, CURLOPT_PORT, port); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); - curl_easy_perform(curl); + res = curl_easy_perform(curl); curl_easy_cleanup(curl); + if(res != CURLE_OK)return "-1"; } curl_global_cleanup(); return readBuffer; @@ -31,14 +32,12 @@ std::string HTTP_REQUEST(const std::string& IP,int port){ int nb_bar; double last_progress, progress_bar_adv; -int progress_bar (void *bar, double t, double d) -{ - if(last_progress != round(d/t*100)) - { +int progress_bar (void *bar, double t, double d){ + if(last_progress != round(d/t*100)){ nb_bar = 25; progress_bar_adv = round(d/t*nb_bar); std::cout<<"\r"; - std::cout<<"Progress : [ "; + std::cout<stream) { - fopen_s(&out->stream,out->filename,"wb"); + fopen_s(&out->stream,out->filename,Sec("wb")); if(!out->stream)return -1; } return fwrite(buffer, size, nmemb, out->stream); } - -int Download(const std::string& URL,const std::string& Path) -{ +int Download(const std::string& URL,const std::string& Path,bool close){ CURL *curl; CURLcode res; - struct File file = { - Path.c_str(), - nullptr - }; - curl_global_init(CURL_GLOBAL_DEFAULT); + struct File file = {Path.c_str(),nullptr}; + //curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); - if(curl) { + if(curl){ curl_easy_setopt(curl, CURLOPT_URL,URL.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file); curl_easy_setopt(curl, CURLOPT_NOPROGRESS, FALSE); @@ -84,12 +77,11 @@ int Download(const std::string& URL,const std::string& Path) curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL); res = curl_easy_perform(curl); curl_easy_cleanup(curl); - if(CURLE_OK != res) { - return res; - } + if(res != CURLE_OK)return res; } if(file.stream)fclose(file.stream); + if(!close)SecureMods(); curl_global_cleanup(); std::cout << std::endl; return -1; -} \ No newline at end of file +} diff --git a/src/Resources.cpp b/src/Network/Resources.cpp similarity index 57% rename from src/Resources.cpp rename to src/Network/Resources.cpp index 89a9d42..e090d10 100644 --- a/src/Resources.cpp +++ b/src/Network/Resources.cpp @@ -1,26 +1,21 @@ /// /// Created by Anonymous275 on 4/11/2020 /// - +#include "Discord/discord_info.h" +#include "Network/network.h" +#include "Security/Enc.h" #include #include +#include "Startup.h" +#include "Logger.h" #include +#include #include #include #include #include -extern std::vector GlobalInfo; -void Exit(const std::string& Msg); namespace fs = std::experimental::filesystem; -std::string HTA(const std::string& hex); -std::string Encrypt(std::string msg); -std::string Decrypt(std::string msg); -extern std::string UlStatus; -extern bool TCPTerminate; -extern bool Terminate; -extern bool Confirm; -extern bool Dev; std::string ListOfMods; std::vector Split(const std::string& String,const std::string& delimiter){ std::vector Val; @@ -42,12 +37,12 @@ void STCPSend(SOCKET socket,const std::string&Data){ } int BytesSent = send(socket, Data.c_str(), int(Data.length())+1, 0); if (BytesSent == 0){ - if(Dev)std::cout << "(TCP) Connection closing..." << std::endl; + debug(Sec("(TCP) Connection closing...")); Terminate = true; return; } else if (BytesSent < 0) { - if(Dev)std::cout << "(TCP) send failed with error: " << WSAGetLastError() << std::endl; + debug(Sec("(TCP) send failed with error: ") + std::to_string(WSAGetLastError())); closesocket(socket); Terminate = true; return; @@ -60,12 +55,11 @@ std::pair STCPRecv(SOCKET socket){ ZeroMemory(buf, len); int BytesRcv = recv(socket, buf, len,0); if (BytesRcv == 0){ - std::cout << "(TCP) Connection closing..." << std::endl; + info(Sec("(TCP) Connection closing...")); Terminate = true; return std::make_pair((char*)"",0); - } - else if (BytesRcv < 0) { - std::cout << "(TCP) recv failed with error: " << WSAGetLastError() << std::endl; + }else if (BytesRcv < 0) { + info(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError())); closesocket(socket); Terminate = true; return std::make_pair((char*)"",0); @@ -77,75 +71,105 @@ std::pair STCPRecv(SOCKET socket){ } void CheckForDir(){ struct stat info{}; - if(stat( "Resources", &info) != 0){ - _wmkdir(L"Resources"); + if(stat( Sec("Resources"), &info) != 0){ + _wmkdir(SecW(L"Resources")); } } void WaitForConfirm(){ - while(!Terminate && !Confirm){ + while(!Terminate && !ModLoaded){ std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - Confirm = false; + ModLoaded = false; } -extern char* ver; -void SyncResources(SOCKET Sock){ - std::cout << "Checking Resources..." << std::endl; - CheckForDir(); - STCPSend(Sock,Encrypt(HTA("4e52") + GlobalInfo.at(0) + ":" + HTA(GlobalInfo.at(2)))); - STCPSend(Sock,Encrypt(HTA(std::string("5643")+ver))); +int N,E; +void Parse(const std::string& msg){ + std::stringstream ss(msg); + std::string t; + while (std::getline(ss, t, 'g')) { + if(t.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)return; + if(N == 0){ + N = std::stoi(t, nullptr, 16); + }else if(E == 0){ + E = std::stoi(t, nullptr, 16); + }else return; + } +} + +std::string HandShake(SOCKET Sock){ + N = 0;E = 0; auto Res = STCPRecv(Sock); - std::string msg = Res.first; - if(msg.size() < 2 || Decrypt(msg).substr(0,2) != "WS"){ + std::string msg(Res.first,Res.second); + Parse(msg); + if(N != 0 && E != 0) { + msg = RSA_E("NR" + GetDName() + ":" + GetDID(),E,N); + if(!msg.empty()) { + STCPSend(Sock,msg); + STCPSend(Sock, RSA_E("VC" + GetVer(),E,N)); + Res = STCPRecv(Sock); + msg = Res.first; + } + } + if(N == 0 || E == 0 || msg.size() < 2 || msg.substr(0,2) != "WS"){ Terminate = true; TCPTerminate = true; - UlStatus = "UlDisconnected: full or outdated server"; - std::cout << "Terminated!" << std::endl; - return; + UlStatus = Sec("UlDisconnected: full or outdated server"); + info(Sec("Terminated!")); + return ""; } - STCPSend(Sock,"SR"); + STCPSend(Sock,Sec("SR")); Res = STCPRecv(Sock); if(strlen(Res.first) == 0 || std::string(Res.first) == "-"){ - std::cout << "Didn't Receive any mods..." << std::endl; + info(Sec("Didn't Receive any mods...")); ListOfMods = "-"; - STCPSend(Sock,"Done"); - std::cout << "Done!" << std::endl; - return; + STCPSend(Sock,Sec("Done")); + info(Sec("Done!")); + return ""; } - std::vector list = Split(std::string(Res.first), ";"); + return Res.first; +} + +void SyncResources(SOCKET Sock){ + std::string Ret = HandShake(Sock); + if(Ret.empty())return; + + info(Sec("Checking Resources...")); + CheckForDir(); + + std::vector list = Split(Ret, ";"); std::vector FNames(list.begin(), list.begin() + (list.size() / 2)); std::vector FSizes(list.begin() + (list.size() / 2), list.end()); list.clear(); + Ret.clear(); int Amount = 0,Pos = 0; - struct stat info{}; std::string a,t; - for(const std::string&N : FNames){ - if(!N.empty()){ - t += N.substr(N.find_last_of('/')+1) + ";"; + for(const std::string&name : FNames){ + if(!name.empty()){ + t += name.substr(name.find_last_of('/') + 1) + ";"; } } if(t.empty())ListOfMods = "-"; else ListOfMods = t; t.clear(); for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) { - int pos = FN->find_last_of('/'); + auto pos = FN->find_last_of('/'); if (pos == std::string::npos)continue; Amount++; } - if(!FNames.empty())std::cout << "Syncing..." << std::endl; + if(!FNames.empty())info(Sec("Syncing...")); for(auto FN = FNames.begin(),FS = FSizes.begin(); FN != FNames.end() && !Terminate; ++FN,++FS) { - int pos = FN->find_last_of('/'); + auto pos = FN->find_last_of('/'); if (pos != std::string::npos) { - a = "Resources" + FN->substr(pos); + a = Sec("Resources") + FN->substr(pos); } else continue; Pos++; - if (stat(a.c_str(), &info) == 0) { + if (fs::exists(a)) { if (FS->find_first_not_of("0123456789") != std::string::npos)continue; if (fs::file_size(a) == std::stoi(*FS)){ - UlStatus = "UlLoading Resource: (" + std::to_string(Pos) + "/" + std::to_string(Amount) + + UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + "): " + a.substr(a.find_last_of('/')); std::this_thread::sleep_for(std::chrono::milliseconds(50)); - fs::copy_file(a, "BeamNG/mods"+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing); + fs::copy_file(a, Sec("BeamNG/mods")+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing); WaitForConfirm(); continue; }else remove(a.c_str()); @@ -160,42 +184,42 @@ void SyncResources(SOCKET Sock){ auto Pair = STCPRecv(Sock); char* Data = Pair.first; size_t BytesRcv = Pair.second; - if (strcmp(Data, "Cannot Open") == 0 || Terminate){ + if (strcmp(Data, Sec("Cannot Open")) == 0 || Terminate){ if(BytesRcv != 0)delete[] Data; break; } memcpy_s(File+Recv,BytesRcv,Data,BytesRcv); - Recv += BytesRcv; + Recv += int(BytesRcv); float per = float(Recv)/std::stof(*FS) * 100; std::string Percent = std::to_string(truncf(per * 10) / 10); - UlStatus = "UlDownloading Resource: (" + std::to_string(Pos) + "/" + std::to_string(Amount) + + UlStatus = Sec("UlDownloading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + "): " + a.substr(a.find_last_of('/')) + " (" + Percent.substr(0, Percent.find('.') + 2) + "%)"; delete[] Data; } while (Recv != Size && Recv < Size && !Terminate); if(Terminate)break; - UlStatus = "UlLoading Resource: (" + std::to_string(Pos) + "/" + std::to_string(Amount) + + UlStatus = Sec("UlLoading Resource: (") + std::to_string(Pos) + "/" + std::to_string(Amount) + "): " + a.substr(a.find_last_of('/')); std::ofstream LFS; - if (!LFS.is_open()) { - LFS.open(a.c_str(), std::ios_base::app | std::ios::binary); + LFS.open(a.c_str(), std::ios_base::app | std::ios::binary); + if (LFS.is_open()) { + LFS.write(File, Recv); + LFS.close(); } - LFS.write(File,Recv); - LFS.close(); ZeroMemory(File,Size); delete[] File; }while(fs::file_size(a) != std::stoi(*FS) && !Terminate); - if(!Terminate)fs::copy_file(a, "BeamNG/mods"+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing); + if(!Terminate)fs::copy_file(a,Sec("BeamNG/mods")+a.substr(a.find_last_of('/')), fs::copy_options::overwrite_existing); WaitForConfirm(); } FNames.clear(); FSizes.clear(); a.clear(); if(!Terminate){ - STCPSend(Sock,"Done"); - std::cout << "Done!" << std::endl; + STCPSend(Sock,Sec("Done")); + info(Sec("Done!")); }else{ - UlStatus = "Ulstart"; - std::cout << "Connection Terminated!" << std::endl; + UlStatus = Sec("Ulstart"); + info(Sec("Connection Terminated!")); } } \ No newline at end of file diff --git a/src/Network 2.0/VehicleData.cpp b/src/Network/VehicleData.cpp similarity index 66% rename from src/Network 2.0/VehicleData.cpp rename to src/Network/VehicleData.cpp index 3d51156..51f648e 100644 --- a/src/Network 2.0/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -1,18 +1,16 @@ /// /// Created by Anonymous275 on 5/8/2020 /// - - +#include "Zlib/Compressor.h" +#include "Network/network.h" +#include "Security/Enc.h" #include -#include +#include "Logger.h" #include #include #include #include -extern bool Terminate; -extern int ClientID; -extern bool Dev; SOCKET UDPSock; sockaddr_in ToServer{}; struct PacketData{ @@ -20,30 +18,52 @@ struct PacketData{ std::string Data; int Tries; }; - struct SplitData{ - int Total; - int ID; + int Total{}; + int ID{}; std::set> Fragments; }; - std::set SplitPackets; std::set BigDataAcks; -void UDPSend(const std::string&Data){ - if(ClientID == -1 || UDPSock == INVALID_SOCKET)return; +void ClearAll(){ + for(SplitData*S : SplitPackets){ + if(S != nullptr){ + delete S; + S = nullptr; + } + } + for(PacketData*S : BigDataAcks){ + if(S != nullptr){ + delete S; + S = nullptr; + } + } + SplitPackets.clear(); + BigDataAcks.clear(); +} +void UDPSend(std::string Data){ + if(ClientID == -1 || UDPSock == -1)return; + if(Data.length() > 400){ + std::string CMP(Comp(Data)); + Data = "ABG:" + CMP; + } std::string Packet = char(ClientID+1) + std::string(":") + Data; - int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.length()) + 1, 0, (sockaddr*)&ToServer, sizeof(ToServer)); - if (sendOk == SOCKET_ERROR)std::cout << "Error Code : " << WSAGetLastError() << std::endl; + int sendOk = sendto(UDPSock, Packet.c_str(), int(Packet.size()), 0, (sockaddr*)&ToServer, sizeof(ToServer)); + if (sendOk == SOCKET_ERROR)error(Sec("Error Code : ") + std::to_string(WSAGetLastError())); } void LOOP(){ while(UDPSock != -1) { for (PacketData* p : BigDataAcks) { - if(p->Tries < 20){ + if(p != nullptr && p->Tries < 20){ p->Tries++; UDPSend(p->Data); }else{ BigDataAcks.erase(p); + if(p != nullptr){ + delete p; + p = nullptr; + } break; } } @@ -53,13 +73,13 @@ void LOOP(){ void AckID(int ID){ for(PacketData* p : BigDataAcks){ - if(p->ID == ID){ + if(p != nullptr && p->ID == ID){ p->Tries = 25; break; } } } -int PacktID(){ +int PackID(){ static int ID = -1; if(ID > 999999)ID = 0; else ID++; @@ -72,11 +92,11 @@ int SplitID(){ return SID; } void SendLarge(const std::string&Data){ - int ID = PacktID(); + int ID = PackID(); std::string Packet; if(Data.length() > 1000){ std::string pckt = Data; - int S = 1,Split = ceil(float(pckt.length()) / 1000); + int S = 1,Split = int(ceil(float(pckt.length()) / 1000)); int SID = SplitID(); while(pckt.length() > 1000){ Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+std::to_string(ID)+"|"+ @@ -85,7 +105,7 @@ void SendLarge(const std::string&Data){ UDPSend(Packet); pckt = pckt.substr(1000); S++; - ID = PacktID(); + ID = PackID(); } Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+ std::to_string(ID)+"|"+std::to_string(SID)+":"+pckt; @@ -115,24 +135,25 @@ bool Handled(int ID){ } SplitData*GetSplit(int SplitID){ for(SplitData* a : SplitPackets){ - if(a->ID == SplitID)return a; + if(a != nullptr && a->ID == SplitID)return a; } - SplitData* a = new SplitData(); + auto* a = new SplitData(); SplitPackets.insert(a); return a; } void ServerParser(const std::string& Data); void HandleChunk(const std::string&Data){ - int pos1 = Data.find(':')+1,pos2 = Data.find(':',pos1),pos3 = Data.find('/'); - int pos4 = Data.find('|'); + int pos1 = int(Data.find(':'))+1,pos2 = int(Data.find(':',pos1)),pos3 = int(Data.find('/')); + int pos4 = int(Data.find('|')); int Max = stoi(Data.substr(pos3+1,pos1-pos3-2)); int Current = stoi(Data.substr(2,pos3-2)); int ID = stoi(Data.substr(pos1,pos4-pos1)); int SplitID = stoi(Data.substr(pos4+1,pos2-pos4-1)); - std::string ack = "ACK:" + Data.substr(pos1,pos4-pos1); + std::string ack = "TRG:" + Data.substr(pos1,pos4-pos1); UDPSend(ack); if(Handled(ID))return; + warn("Handeling Packet ID : " + std::to_string(ID)); SplitData* SData = GetSplit(SplitID); SData->Total = Max; SData->ID = SplitID; @@ -144,17 +165,22 @@ void HandleChunk(const std::string&Data){ } ServerParser(ToHandle); SplitPackets.erase(SData); + delete SData; + SData = nullptr; } } -void UDPParser(const std::string&Packet){ - if(Packet.substr(0,4) == "ACK:"){ +void UDPParser(std::string Packet){ + if(Packet.substr(0,4) == "ABG:"){ + Packet = DeComp(Packet.substr(4)); + } + if(Packet.substr(0,4) == "TRG:"){ AckID(stoi(Packet.substr(4))); - if(Dev)std::cout << "Got Ack for data" << std::endl; + debug(Sec("Got Ack for data")); return; }else if(Packet.substr(0,3) == "BD:"){ - int pos = Packet.find(':',4); + auto pos = Packet.find(':',4); int ID = stoi(Packet.substr(3,pos-3)); - std::string pckt = "ACK:" + std::to_string(ID); + std::string pckt = "TRG:" + std::to_string(ID); UDPSend(pckt); if(!Handled(ID)) { pckt = Packet.substr(pos + 1); @@ -174,33 +200,28 @@ void UDPRcv(){ int clientLength = sizeof(FromServer); ZeroMemory(&FromServer, clientLength); ZeroMemory(buf, len); - if(UDPSock == INVALID_SOCKET)return; - int bytesIn = recvfrom(UDPSock, buf, len, 0, (sockaddr*)&FromServer, &clientLength); - if (bytesIn == SOCKET_ERROR) - { - //std::cout << "Error receiving from Server " << WSAGetLastError() << std::endl; - return; - } - UDPParser(std::string(buf)); + if(UDPSock == -1)return; + int Rcv = recvfrom(UDPSock, buf, len, 0, (sockaddr*)&FromServer, &clientLength); + if (Rcv == SOCKET_ERROR)return; + std::string Ret(Rcv,0); + memcpy_s(&Ret[0],Rcv,buf,Rcv); + UDPParser(Ret); } -void TCPSend(const std::string&Data); void UDPClientMain(const std::string& IP,int Port){ WSADATA data; - if (WSAStartup(514, &data)) //2.2 - { - std::cout << "Can't start Winsock! " << std::endl; + if (WSAStartup(514, &data)){ + error(Sec("Can't start Winsock!")); return; } ToServer.sin_family = AF_INET; ToServer.sin_port = htons(Port); inet_pton(AF_INET, IP.c_str(), &ToServer.sin_addr); UDPSock = socket(AF_INET, SOCK_DGRAM, 0); - BigDataAcks.clear(); std::thread Ack(LOOP); Ack.detach(); IDReset(); - TCPSend("P"); - UDPSend("p"); + TCPSend(Sec("P")); + UDPSend(Sec("p")); while(!Terminate)UDPRcv(); closesocket(UDPSock); WSACleanup(); diff --git a/src/Network 2.0/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp similarity index 60% rename from src/Network 2.0/VehicleEvent.cpp rename to src/Network/VehicleEvent.cpp index 1d45e6c..32a3da1 100644 --- a/src/Network 2.0/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -3,15 +3,13 @@ /// #include +#include "Logger.h" #include #include +#include "Security/Enc.h" +#include "Network/network.h" -extern std::string UlStatus; -extern bool Terminate; -extern bool Dev; SOCKET TCPSock; - - void TCPSend(const std::string&Data){ if(TCPSock == -1){ Terminate = true; @@ -19,12 +17,12 @@ void TCPSend(const std::string&Data){ } int BytesSent = send(TCPSock, Data.c_str(), int(Data.length())+1, 0); if (BytesSent == 0){ - if(Dev)std::cout << "(TCP) Connection closing..." << std::endl; + debug(Sec("(TCP) Connection closing...")); Terminate = true; return; } else if (BytesSent < 0) { - if(Dev)std::cout << "(TCP) send failed with error: " << WSAGetLastError() << std::endl; + debug(Sec("(TCP) send failed with error: ") + std::to_string(WSAGetLastError())); closesocket(TCPSock); Terminate = true; return; @@ -43,12 +41,12 @@ void TCPRcv(){ } int BytesRcv = recv(TCPSock, buf, len,0); if (BytesRcv == 0){ - if(Dev)std::cout << "(TCP) Connection closing..." << std::endl; + debug(Sec("(TCP) Connection closing...")); Terminate = true; return; } else if (BytesRcv < 0) { - if(Dev)std::cout << "(TCP) recv failed with error: " << WSAGetLastError() << std::endl; + debug(Sec("(TCP) recv failed with error: ") + std::to_string(WSAGetLastError())); closesocket(TCPSock); Terminate = true; return; @@ -56,31 +54,25 @@ void TCPRcv(){ ServerParser(std::string(buf)); } -void GameSend(const std::string&Data); void SyncResources(SOCKET TCPSock); void TCPClientMain(const std::string& IP,int Port){ WSADATA wsaData; SOCKADDR_IN ServerAddr; int RetCode; - WSAStartup(514, &wsaData); //2.2 TCPSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if(TCPSock == -1) - { - printf("Client: socket failed! Error code: %d\n", WSAGetLastError()); + if(TCPSock == -1){ + printf(Sec("Client: socket failed! Error code: %d\n"), WSAGetLastError()); WSACleanup(); return; } - ServerAddr.sin_family = AF_INET; ServerAddr.sin_port = htons(Port); inet_pton(AF_INET, IP.c_str(), &ServerAddr.sin_addr); - RetCode = connect(TCPSock, (SOCKADDR *) &ServerAddr, sizeof(ServerAddr)); - if(RetCode != 0) - { - UlStatus = "UlConnection Failed!"; - std::cout << "Client: connect failed! Error code: " << WSAGetLastError() << std::endl; + if(RetCode != 0){ + UlStatus = Sec("UlConnection Failed!"); + std::cout << Sec("Client: connect failed! Error code: ") << WSAGetLastError() << std::endl; closesocket(TCPSock); WSACleanup(); Terminate = true; @@ -90,14 +82,11 @@ void TCPClientMain(const std::string& IP,int Port){ SyncResources(TCPSock); while(!Terminate)TCPRcv(); - GameSend("T"); + GameSend(Sec("T")); ////Game Send Terminate - if( shutdown(TCPSock, SD_SEND) != 0 && Dev) - std::cout << "(TCP) shutdown error code: " << WSAGetLastError() << std::endl; + if(closesocket(TCPSock) != 0) + debug(Sec("(TCP) Cannot close socket. Error code: ") + std::to_string(WSAGetLastError())); - if(closesocket(TCPSock) != 0 && Dev) - std::cout << "(TCP) Cannot close socket. Error code: " << WSAGetLastError() << std::endl; - - if(WSACleanup() != 0 && Dev) - std::cout << "(TCP) Client: WSACleanup() failed!..." << std::endl; + if(WSACleanup() != 0) + debug(Sec("(TCP) Client: WSACleanup() failed!...")); } diff --git a/src/Security.cpp b/src/Security.cpp deleted file mode 100644 index 52e264e..0000000 --- a/src/Security.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/// -/// Created by Anonymous275 on 3/16/2020 -/// -#include -#include -#include -#include -#include -#include -#include -#define MAX_KEY_LENGTH 255 -#define MAX_VALUE_NAME 16383 - -void Exit(const std::string& Msg); -int TraceBack = 0; - -std::vector SData; - -std::string HTA(const std::string& hex) -{ - std::string ascii; - for (size_t i = 0; i < hex.length(); i += 2) - { - std::string part = hex.substr(i, 2); - char ch = char(stoul(part, nullptr, 16)); - ascii += ch; - } - return ascii; -} -int Rand(){ - std::random_device r; - std::default_random_engine e1(r()); - std::uniform_int_distribution uniform_dist(1, 200); - return uniform_dist(e1); -} -std::string Encrypt(std::string msg){ - if(msg.size() < 2)return msg; - int R = (Rand()+Rand())/2,T = R; - for(char&c : msg){ - if(R > 30)c = char(int(c) + (R-=3)); - else c = char(int(c) - (R+=4)); - } - return char(T) + msg; -} -std::string Decrypt(std::string msg){ - int R = uint8_t(msg.at(0)); - if(msg.size() < 2 || R > 200 || R < 1)return ""; - msg = msg.substr(1); - for(char&c : msg){ - if(R > 30)c = char(int(c) - (R-=3)); - else c = char(int(c) + (R+=4)); - } - return msg; -} - - -LONG OpenKey(HKEY root,const char* path,PHKEY hKey){ - return RegOpenKeyEx(root, reinterpret_cast(path), 0, KEY_READ, hKey); -} - -std::string QueryKey(HKEY hKey,int ID) -{ - TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name - DWORD cbName; // size of name string - TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name - DWORD cchClassName = MAX_PATH; // size of class string - DWORD cSubKeys=0; // number of subkeys - DWORD cbMaxSubKey; // longest subkey size - DWORD cchMaxClass; // longest class string - DWORD cValues; // number of values for key - DWORD cchMaxValue; // longest value name - DWORD cbMaxValueData; // longest value data - DWORD cbSecurityDescriptor; // size of security descriptor - FILETIME ftLastWriteTime; // last write time - - DWORD i, retCode; - - TCHAR achValue[MAX_VALUE_NAME]; - DWORD cchValue = MAX_VALUE_NAME; - - retCode = RegQueryInfoKey( - hKey, // key handle - achClass, // buffer for class name - &cchClassName, // size of class string - nullptr, // reserved - &cSubKeys, // number of subkeys - &cbMaxSubKey, // longest subkey size - &cchMaxClass, // longest class string - &cValues, // number of values for this key - &cchMaxValue, // longest value name - &cbMaxValueData, // longest value data - &cbSecurityDescriptor, // security descriptor - &ftLastWriteTime); // last write time - - - - BYTE* buffer = new BYTE[cbMaxValueData]; - ZeroMemory(buffer, cbMaxValueData); - if (cSubKeys) - { - for (i=0; i(buffer); - std::string key = achValue; - switch (ID){ - case 1: if(key == HTA("537465616d50617468"))return data;break; - case 2: if(key == HTA("4e616d65") && data == HTA("4265616d4e472e6472697665"))return data;break; - case 3: return data.substr(0,data.length()-2); - case 4: if(key == HTA("75736572706174685f6f76657272696465"))return data; - default: break; - } - } - } - } - delete [] buffer; - return ""; -} -namespace fs = std::experimental::filesystem; -void FileList(std::vector&a,const std::string& Path){ - for (const auto &entry : fs::directory_iterator(Path)) { - int pos = entry.path().filename().string().find('.'); - if (pos != std::string::npos) { - a.emplace_back(entry.path().string()); - }else FileList(a,entry.path().string()); - } -} -bool Continue = false; -void Find(const std::string& FName,const std::string& Path){ - std::vector FS; - FileList(FS,Path); - for(const std::string&a : FS){ - if(a.find(FName)!=std::string::npos)Continue = true; - } - FS.clear(); -} -void ExitError(){ - std::string MSG2 = HTA("4572726f722120506c6561736520436f6e7461637420537570706f7274"); - Exit(MSG2 + " Code 2"); -} -void Check(){ - /*.HKEY_CURRENT_USER\Software\Valve\Steam - HKEY_CURRENT_USER\\Software\Valve\Steam\Apps\284160 - HKEY_CLASSES_ROOT\\beamng\\DefaultIcon */ - //Sandbox Scramble technique - std::string Result; - std::string K1 = HTA("536f6674776172655c56616c76655c537465616d"); - std::string K2 = HTA("536f6674776172655c56616c76655c537465616d5c417070735c323834313630"); - std::string K3 = HTA("6265616d6e675c44656661756c7449636f6e"); - std::string MSG1 = HTA("4572726f722120796f7520646f206e6f74206f776e204265616d4e4721"); //Error! you do not own BeamNG! - std::string MSG2 = HTA("4572726f722120506c6561736520436f6e7461637420537570706f7274"); //Error! Please Contact Support - std::string MSG3 = HTA("596f7520646f206e6f74206f776e207468652067616d65206f6e2074686973206d616368696e6521"); //You do not own the game on this machine! - //std::string MSG = HTA("5761726e696e672120796f75206f776e207468652067616d6520627574206120637261636b65642067616d652077617320666f756e64206f6e20796f7572206d616368696e6521"); - //not used : Warning! you own the game but a cracked game was found on your machine! - HKEY hKey; - LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey); - if(dwRegOPenKey == ERROR_SUCCESS) { - Result = QueryKey(hKey, 1); - if(Result.empty()){Exit(MSG1 + " Code 1");} - SData.push_back(Result); - Result += HTA("2f7573657264617461"); - struct stat buffer{}; - if(stat(Result.c_str(), &buffer) == 0){ - auto *F = new std::thread(Find,HTA("3238343136302e6a736f6e"),Result); - F->join(); - delete F; - if(!Continue)Exit(MSG2 + " Code 2"); - }else Exit(MSG2 + ". Code: 3"); - Result.clear(); - TraceBack++; - }else{Exit(MSG2 + ". Code: 4");} - K1.clear(); - RegCloseKey(hKey); - dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K2.c_str(), &hKey); - if(dwRegOPenKey == ERROR_SUCCESS) { - Result = QueryKey(hKey, 2); - if(Result.empty()){Exit(MSG1 + " Code 3");} - SData.push_back(Result); - TraceBack++; - }else{Exit(MSG3);} - K2.clear(); - RegCloseKey(hKey); - dwRegOPenKey = OpenKey(HKEY_CLASSES_ROOT, K3.c_str(), &hKey); - if(dwRegOPenKey == ERROR_SUCCESS) { - Result = QueryKey(hKey, 3); - if(Result.empty()){ - Exit(MSG2 + ". Code: 5"); - } - SData.push_back(Result); - TraceBack++; - }else{Exit(MSG2+ ". Code : 5");} - //Memory Cleaning - K3.clear(); - //MSG.clear(); - MSG1.clear(); - MSG2.clear(); - MSG3.clear(); - Result.clear(); - RegCloseKey(hKey); -} - -std::string HWID(){ - SYSTEM_INFO siSysInfo; - GetSystemInfo(&siSysInfo); - int I1 = siSysInfo.dwOemId; - int I2 = siSysInfo.dwNumberOfProcessors; - int I3 = siSysInfo.dwProcessorType; - int I4 = siSysInfo.dwActiveProcessorMask; - int I5 = siSysInfo.wProcessorLevel; - int I6 = siSysInfo.wProcessorRevision; - return std::to_string((I1*I2+I3)*(I4*I5+I6)); -} - -char* HashMD5(char* data, DWORD *result) -{ - DWORD dwStatus = 0; - DWORD cbHash = 16; - int i = 0; - HCRYPTPROV cryptProv; - HCRYPTHASH cryptHash; - BYTE hash[16]; - char hex[] = "0123456789abcdef"; - char *strHash; - strHash = (char*)malloc(500); - memset(strHash, '\0', 500); - if (!CryptAcquireContext(&cryptProv, nullptr, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - { - dwStatus = GetLastError(); - printf("CryptAcquireContext failed: %lu\n", dwStatus); - *result = dwStatus; - return nullptr; - } - if (!CryptCreateHash(cryptProv, CALG_MD5, 0, 0, &cryptHash)) - { - dwStatus = GetLastError(); - printf("CryptCreateHash failed: %lu\n", dwStatus); - CryptReleaseContext(cryptProv, 0); - *result = dwStatus; - return nullptr; - } - if (!CryptHashData(cryptHash, (BYTE*)data, strlen(data), 0)) - { - dwStatus = GetLastError(); - printf("CryptHashData failed: %lu\n", dwStatus); - CryptReleaseContext(cryptProv, 0); - CryptDestroyHash(cryptHash); - *result = dwStatus; - return nullptr; - } - if (!CryptGetHashParam(cryptHash, HP_HASHVAL, hash, &cbHash, 0)) - { - dwStatus = GetLastError(); - printf("CryptGetHashParam failed: %lu\n", dwStatus); - CryptReleaseContext(cryptProv, 0); - CryptDestroyHash(cryptHash); - *result = dwStatus; - return nullptr; - } - for (i = 0; i < cbHash; i++) - { - strHash[i * 2] = hex[hash[i] >> 4]; - strHash[(i * 2) + 1] = hex[hash[i] & 0xF]; - } - CryptReleaseContext(cryptProv, 0); - CryptDestroyHash(cryptHash); - return strHash; -} -std::string getHardwareID() -{ - DWORD err; - std::string hash = HashMD5((char*)HWID().c_str(), &err); - return hash; -} diff --git a/src/Security/BeamNG.cpp b/src/Security/BeamNG.cpp new file mode 100644 index 0000000..59c1829 --- /dev/null +++ b/src/Security/BeamNG.cpp @@ -0,0 +1,289 @@ +/// +/// Created by Anonymous275 on 7/18/2020 +/// +#include "Security/Enc.h" +#include +#include +#include "Logger.h" +#include +#include +#include +#include + +#define MAX_KEY_LENGTH 255 +#define MAX_VALUE_NAME 16383 + +int TraceBack = 0; +std::string GameDir; + +void lowExit(int code){ + TraceBack = 0; + std::string msg = + Sec("Failed to find the game please launch it. Report this if the issue persists code "); + error(msg+std::to_string(code)); + std::this_thread::sleep_for(std::chrono::seconds(10)); + exit(2); +} +void Exit(int code){ + TraceBack = 0; + std::string msg = + Sec("Sorry. We do not support cracked copies report this if you believe this is a mistake code "); + error(msg+std::to_string(code)); + std::this_thread::sleep_for(std::chrono::seconds(10)); + exit(3); +} +void SteamExit(int code){ + TraceBack = 0; + std::string msg = + Sec("Illegal steam modifications detected report this if you believe this is a mistake code "); + error(msg+std::to_string(code)); + std::this_thread::sleep_for(std::chrono::seconds(10)); + exit(4); +} +std::string GetGameDir(){ + if(TraceBack != 3)Exit(0); + return GameDir.substr(0,GameDir.find_last_of('\\')); +} +LONG OpenKey(HKEY root,const char* path,PHKEY hKey){ + return RegOpenKeyEx(root, reinterpret_cast(path), 0, KEY_READ, hKey); +} +std::string QueryKey(HKEY hKey,int ID){ + TCHAR achKey[MAX_KEY_LENGTH]; // buffer for subkey name + DWORD cbName; // size of name string + TCHAR achClass[MAX_PATH] = TEXT(""); // buffer for class name + DWORD cchClassName = MAX_PATH; // size of class string + DWORD cSubKeys=0; // number of subkeys + DWORD cbMaxSubKey; // longest subkey size + DWORD cchMaxClass; // longest class string + DWORD cValues; // number of values for key + DWORD cchMaxValue; // longest value name + DWORD cbMaxValueData; // longest value data + DWORD cbSecurityDescriptor; // size of security descriptor + FILETIME ftLastWriteTime; // last write time + + DWORD i, retCode; + + TCHAR achValue[MAX_VALUE_NAME]; + DWORD cchValue = MAX_VALUE_NAME; + + retCode = RegQueryInfoKey( + hKey, // key handle + achClass, // buffer for class name + &cchClassName, // size of class string + nullptr, // reserved + &cSubKeys, // number of subkeys + &cbMaxSubKey, // longest subkey size + &cchMaxClass, // longest class string + &cValues, // number of values for this key + &cchMaxValue, // longest value name + &cbMaxValueData, // longest value data + &cbSecurityDescriptor, // security descriptor + &ftLastWriteTime); // last write time + + BYTE* buffer = new BYTE[cbMaxValueData]; + ZeroMemory(buffer, cbMaxValueData); + if (cSubKeys){ + for (i=0; i(buffer); + std::string key = achValue; + switch (ID){ + case 1: if(key == Sec("SteamExe")){ + auto p = data.find_last_of('/'); + if(p != std::string::npos)return data.substr(0,p); + }break; + case 2: if(key == Sec("Name") && data == Sec("BeamNG.drive"))return data;break; + case 3: if(key == Sec("rootpath"))return data;break; + case 4: if(key == Sec("userpath_override"))return data; + default: break; + } + } + } + } + delete [] buffer; + return ""; +} +namespace fs = std::experimental::filesystem; +void FileList(std::vector&a,const std::string& Path){ + for (const auto &entry : fs::directory_iterator(Path)) { + auto pos = entry.path().filename().string().find('.'); + if (pos != std::string::npos) { + a.emplace_back(entry.path().string()); + }else FileList(a,entry.path().string()); + } +} +bool Find(const std::string& FName,const std::string& Path){ + std::vector FS; + FileList(FS,Path+Sec("/userdata")); + for(std::string&a : FS){ + if(a.find(FName) != std::string::npos){ + FS.clear(); + return true; + } + } + FS.clear(); + return false; +} +bool FindHack(const std::string& Path){ + bool s = true; + for (const auto &entry : fs::directory_iterator(Path)) { + std::string Name = entry.path().filename().string(); + for(char&c : Name)c = char(tolower(c)); + if(Name == Sec("steam.exe"))s = false; + if(Name.find(Sec("greenluma")) != -1)return true; + Name.clear(); + } + return s; +} +std::vector GetID(const std::string& log){ + std::string vec,t,r; + std::vector Ret; + std::ifstream f(log.c_str(), std::ios::binary); + f.seekg(0, std::ios_base::end); + std::streampos fileSize = f.tellg(); + vec.resize(size_t(fileSize) + 1); + f.seekg(0, std::ios_base::beg); + f.read(&vec[0], fileSize); + f.close(); + std::stringstream ss(vec); + bool S = false; + while (std::getline(ss, t, '{')) { + if(!S)S = true; + else{ + for(char& c : t){ + if(isdigit(c))r += c; + } + break; + } + } + Ret.emplace_back(r); + r.clear(); + S = false; + bool L = true; + while (std::getline(ss, t, '}')) { + if(L){ + L = false; + continue; + } + for(char& c : t){ + if(c == '"'){ + if(!S)S = true; + else{ + if(r.length() > 10) { + Ret.emplace_back(r); + } + r.clear(); + S = false; + continue; + } + } + if(isdigit(c))r += c; + } + } + vec.clear(); + return Ret; +} +std::string GetManifest(const std::string& Man){ + std::string vec; + std::ifstream f(Man.c_str(), std::ios::binary); + f.seekg(0, std::ios_base::end); + std::streampos fileSize = f.tellg(); + vec.resize(size_t(fileSize) + 1); + f.seekg(0, std::ios_base::beg); + f.read(&vec[0], fileSize); + f.close(); + std::string ToFind = Sec("\"LastOwner\"\t\t\""); + int pos = int(vec.find(ToFind)); + if(pos != -1){ + pos += int(ToFind.length()); + vec = vec.substr(pos); + return vec.substr(0,vec.find('\"')); + }else return ""; +} +bool IDCheck(std::string Man, std::string steam){ + bool a = false,b = true; + int pos = int(Man.find(Sec("steamapps"))); + if(pos == -1)Exit(5); + Man = Man.substr(0,pos+9) + Sec("/appmanifest_284160.acf"); + steam += Sec("/config/loginusers.vdf"); + if(fs::exists(Man) && fs::exists(steam)){ + for(const std::string&ID : GetID(steam)){ + if(ID == GetManifest(Man))b = false; + } + if(b)Exit(6); + }else a = true; + return a; +} +void LegitimacyCheck(){ + std::string Result,T; + std::string K1 = Sec("Software\\Valve\\Steam"); + std::string K2 = Sec("Software\\Valve\\Steam\\Apps\\284160"); + std::string K3 = Sec("Software\\BeamNG\\BeamNG.drive"); + HKEY hKey; + LONG dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K1.c_str(), &hKey); + if(dwRegOPenKey == ERROR_SUCCESS) { + Result = QueryKey(hKey, 1); + if(Result.empty())Exit(1); + if(fs::exists(Result)){ + if(!Find(Sec("284160.json"),Result))Exit(2); + if(FindHack(Result))SteamExit(1); + }else Exit(3); + T = Result; + Result.clear(); + TraceBack++; + }else Exit(4); + K1.clear(); + RegCloseKey(hKey); + dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K2.c_str(), &hKey); + if(dwRegOPenKey == ERROR_SUCCESS) { + Result = QueryKey(hKey, 2); + if(Result.empty())lowExit(1); + TraceBack++; + }else lowExit(2); + K2.clear(); + RegCloseKey(hKey); + dwRegOPenKey = OpenKey(HKEY_CURRENT_USER, K3.c_str(), &hKey); + if(dwRegOPenKey == ERROR_SUCCESS) { + Result = QueryKey(hKey, 3); + if(Result.empty())lowExit(3); + if(IDCheck(Result,T))lowExit(5); + GameDir = Result; + TraceBack++; + }else lowExit(4); + K3.clear(); + Result.clear(); + RegCloseKey(hKey); + if(TraceBack < 3)exit(-1); +} +std::string CheckVer(const std::string &dir){ + std::string vec,temp,Path = dir + Sec("\\integrity.json"); + std::ifstream f(Path.c_str(), std::ios::binary); + f.seekg(0, std::ios_base::end); + std::streampos fileSize = f.tellg(); + vec.resize(size_t(fileSize) + 1); + f.seekg(0, std::ios_base::beg); + f.read(&vec[0], fileSize); + f.close(); + vec = vec.substr(vec.find_last_of(Sec("version")),vec.find_last_of('"')); + for(const char &a : vec){ + if(isdigit(a) || a == '.')temp+=a; + } + return temp; +} diff --git a/src/Security/Checker.cpp b/src/Security/Checker.cpp new file mode 100644 index 0000000..c627d20 --- /dev/null +++ b/src/Security/Checker.cpp @@ -0,0 +1,92 @@ +/// +/// Created by Anonymous275 on 7/16/2020 +/// +#include "Discord/discord_info.h" +#include "Security/Enc.h" +#include +#include "Startup.h" +#include +#include "Logger.h" +#include +#include +void DAS(){ + int i = 0; + std::ifstream f(GetEN(), std::ios::binary); + f.seekg(0, std::ios_base::end); + std::streampos fileSize = f.tellg(); + if(IsDebuggerPresent() || fileSize > 0x3D0900){ + i++; + DAboard(); + } + if(i)DAboard(); + f.close(); +} +void DASM(){ //A mirror to have 2 independent checks + int i = 0; + std::ifstream f(GetEN(), std::ios::binary); + f.seekg(0, std::ios_base::end); + std::streampos fileSize = f.tellg(); + if(IsDebuggerPresent() || fileSize > 0x3D0900){ + i++; + DAboard(); + } + if(i)DAboard(); + f.close(); +} +DWORD getParentPID(DWORD pid){ + HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + PROCESSENTRY32 pe = {0}; + DWORD ppid = 0; + pe.dwSize = sizeof(PROCESSENTRY32); + if(Process32First(h, &pe)){ + do{ + if(pe.th32ProcessID == pid){ + ppid = pe.th32ParentProcessID; + break; + } + }while(Process32Next(h, &pe)); + } + CloseHandle(h); + return ppid; +} + +HANDLE getProcess(DWORD pid, LPSTR fname, DWORD sz) { + HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); + if (h) { + GetModuleFileNameEx(h, nullptr, fname, sz); + return h; + } + return nullptr; +} +void UnderSimulation(char* argv[]){ + DWORD ppid; + std::string Parent(MAX_PATH,0); + ppid = getParentPID(GetCurrentProcessId()); + HANDLE Process = getProcess(ppid, &Parent[0], MAX_PATH); + std::string Code = Sec("Code "); + if(Process == nullptr){ + error(Code+std::to_string(2)); + exit(1); + } + auto P = Parent.find(Sec(".exe")); + if(P != std::string::npos)Parent.resize(P + 4); + else{ + error(Code+std::to_string(3)); + exit(1); + } + std::string S1 = Sec("\\Windows\\explorer.exe"); + std::string S2 = Sec("JetBrains\\CLion"); + std::string S3 = Sec("\\Windows\\System32\\cmd.exe"); + if(Parent == std::string(argv[0]))return; + if(Parent.find(S1) == 2)return; + if(Parent.find(S2) != std::string::npos)return; + if(Parent.find(S3) == 2)return; + TerminateProcess(Process, 1); + error(Code + std::to_string(4)); + exit(1); + +} +void SecurityCheck(char* argv[]){ + UnderSimulation(argv); + DAS(); +} diff --git a/src/Security/Encryption.cpp b/src/Security/Encryption.cpp new file mode 100644 index 0000000..07fc19c --- /dev/null +++ b/src/Security/Encryption.cpp @@ -0,0 +1,85 @@ +#include "Security/Enc.h" +#include +#include + +int LocalKeys[] = {7406809,6967,4810803}; //n e d + +int log_power(int n,unsigned int p, int mod){ + int result = 1; + for (; p; p >>= 1u){ + if (p & 1u)result = int((1LL * result * n) % mod); + n = int((1LL * n * n) % mod); + } + return result; +} + +int Enc(int value,int e,int n){ + return log_power(value, e, n); +} + +int Dec(int value,int d,int n){ + return log_power(value, d, n); +} +std::string LocalEnc(const std::string& Data){ + std::stringstream stream; + for(const char&c : Data){ + stream << std::hex << Enc(uint8_t(c),LocalKeys[1],LocalKeys[0]) << "g"; + } + return stream.str(); +} +std::string LocalDec(const std::string& Data){ + std::stringstream ss(Data); + std::string token,ret; + while (std::getline(ss, token, 'g')) { + if(token.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)return ""; + int c = std::stoi(token, nullptr, 16); + ret += char(Dec(c,LocalKeys[2],LocalKeys[0])); + } + return ret; +} +#include +int Rand(){ + std::random_device r; + std::default_random_engine e1(r()); + std::uniform_int_distribution uniform_dist(1, 200); + return uniform_dist(e1); +} +std::string Encrypt(std::string msg){ + if(msg.size() < 2)return msg; + int R = (Rand()+Rand())/2,T = R; + for(char&c : msg){ + if(R > 30)c = char(int(c) + (R-=3)); + else c = char(int(c) - (R+=4)); + } + return char(T) + msg; +} +std::string Decrypt(std::string msg){ + if(msg.size() < 2)return ""; + int R = uint8_t(msg.at(0)); + if(R > 200 || R < 1)return ""; + msg = msg.substr(1); + for(char&c : msg){ + if(R > 30)c = char(int(c) - (R-=3)); + else c = char(int(c) + (R+=4)); + } + return msg; +} +std::string RSA_E(const std::string& Data,int e, int n){ + if(e < 10 || n < 10)return ""; + std::stringstream stream; + for(const char&c : Data){ + stream << std::hex << Enc(uint8_t(c),e,n) << "g"; + } + return stream.str(); +} + +std::string RSA_D(const std::string& Data, int d, int n){ + std::stringstream ss(Data); + std::string token,ret; + while (std::getline(ss, token, 'g')) { + if(token.find_first_not_of(Sec("0123456789abcdef")) != std::string::npos)return ""; + int c = std::stoi(token, nullptr, 16); + ret += char(Dec(c,d,n)); + } + return ret; +} \ No newline at end of file diff --git a/src/Security/FileHandles.cpp b/src/Security/FileHandles.cpp new file mode 100644 index 0000000..f3d76fc --- /dev/null +++ b/src/Security/FileHandles.cpp @@ -0,0 +1,71 @@ +/// +/// Created by Anonymous275 on 7/19/2020 +/// +#include "Security/Enc.h" +#include +#include "Security/Game.h" +#include +#include +#include "Logger.h" +#include + +namespace fs = std::experimental::filesystem; +void CheckDirs(){ + for (auto& p : fs::directory_iterator(Sec("BeamNG\\mods"))) { + if(fs::is_directory(p.path()))exit(0); + } +} + +bool BeamLoad(PCWSTR pszFile){ + bool Ret = false; + DWORD dwSession; + WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] = {0}; + DWORD dwError = RmStartSession(&dwSession, 0, szSessionKey); + if (dwError == ERROR_SUCCESS) { + dwError = RmRegisterResources(dwSession, 1, &pszFile, + 0, nullptr, 0, nullptr); + if (dwError == ERROR_SUCCESS) { + DWORD dwReason; + UINT nProcInfoNeeded; + UINT nProcInfo = 10; + RM_PROCESS_INFO rgpi[10]; + dwError = RmGetList(dwSession, &nProcInfoNeeded,&nProcInfo, rgpi, &dwReason); + if (dwError == ERROR_SUCCESS) { + if(nProcInfo == 1){ + std::string AppName(50,0); + size_t N; + wcstombs_s(&N,&AppName[0],50, rgpi[0].strAppName, 50); + if(!AppName.find(Sec("BeamNG.drive")) && GamePID == rgpi[0].Process.dwProcessId){ + Ret = true; + } + } + } + } + RmEndSession(dwSession); + } + return Ret; +} +void ContinuousCheck(fs::file_time_type last){ + std::string path = Sec(R"(BeamNG\mods\BeamMP.zip)"); + int i = 0; + while(fs::exists(path) && last == fs::last_write_time(path)){ + if(!BeamLoad(SecW(L"BeamNG\\mods\\BeamMP.zip"))) { + if (i < 60)i++; + else { + error(Sec("Mod did not load! launcher closing soon")); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(0); + } + }else i = 0; + CheckDirs(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } + exit(0); +} + +void SecureMods(){ + fs::file_time_type last = fs::last_write_time(Sec(R"(BeamNG\mods\BeamMP.zip)")); + auto* HandleCheck = new std::thread(ContinuousCheck,last); + HandleCheck->detach(); + delete HandleCheck; +} \ No newline at end of file diff --git a/src/Startup.cpp b/src/Startup.cpp new file mode 100644 index 0000000..d7246ac --- /dev/null +++ b/src/Startup.cpp @@ -0,0 +1,199 @@ +/// +/// Created by Anonymous275 on 7/16/2020 +/// +#include "Discord/discord_info.h" +#include "Network/network.h" +#include "Security/Init.h" +#include "Security/Enc.h" +#include "Curl/http.h" +#include +#include +#include "Logger.h" +#include +#include +bool Dev = false; +namespace fs = std::experimental::filesystem; +std::string GetEN(){ + return Sec("BeamMP-Launcher.exe"); +} +std::string GetVer(){ + return Sec("1.60"); +} +std::string GetPatch(){ + return Sec(""); +} +void ReLaunch(int argc,char*args[]){ + std::string Arg; + for(int c = 2; c <= argc; c++){ + Arg += " "; + Arg += args[c-1]; + } + system(Sec("cls")); + ShellExecute(nullptr,Sec("runas"),GetEN().c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); + ShowWindow(GetConsoleWindow(),0); + std::this_thread::sleep_for(std::chrono::seconds(1)); + exit(1); +} +void URelaunch(int argc,char* args[]){ + std::string Arg; + for(int c = 2; c <= argc; c++){ + Arg += " "; + Arg += args[c-1]; + } + ShellExecute(nullptr,Sec("open"),GetEN().c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); + ShowWindow(GetConsoleWindow(),0); + std::this_thread::sleep_for(std::chrono::seconds(1)); + exit(1); +} +void CheckName(int argc,char* args[]){ + struct stat info{}; + std::string DN = GetEN(),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1); + if(FN != DN){ + if(stat(DN.c_str(),&info)==0)remove(DN.c_str()); + if(stat(DN.c_str(),&info)==0)ReLaunch(argc,args); + std::rename(FN.c_str(), DN.c_str()); + URelaunch(argc,args); + } +} +void RequestRole(){ + auto NPos = std::string::npos; + std::string HTTP_Result=HTTP_REQUEST(Sec("https://beammp.com/entitlement?did=")+GetDID()+Sec("&t=l"),443); + if(HTTP_Result == "-1"){ + error(Sec("Sorry Backend System Outage! Don't worry it will back on soon!")); + std::this_thread::sleep_for(std::chrono::seconds(3)); + exit(-1); + } + if(HTTP_Result.find(Sec("\"MDEV\"")) != NPos)Dev = true; + info(Sec("Client Connected!")); +} + +void CheckForUpdates(int argc,char*args[],const std::string& CV){ + std::string link = Sec("https://beammp.com/builds/launcher?version=true"); + std::string HTTP = HTTP_REQUEST(link,443); + if(HTTP.find_first_of("0123456789") == std::string::npos){ + error(Sec("Primary Servers Offline! sorry for the inconvenience!")); + std::this_thread::sleep_for(std::chrono::seconds(4)); + exit(-1); + } + link = Sec("https://beammp.com/builds/launcher?download=true"); + + struct stat buffer{}; + std::string Back = Sec("BeamMP-Launcher.back"); + if(stat(Back.c_str(), &buffer) == 0)remove(Back.c_str()); + if(HTTP > CV){ + system(Sec("cls")); + info(Sec("Update found!")); + info(Sec("Updating...")); + if(std::rename(GetEN().c_str(), Back.c_str()))error(Sec("failed creating a backup!")); + int i = Download(link, GetEN(),true); + if(i != -1){ + error(Sec("Launcher Update failed! trying again... code : ") + std::to_string(i)); + std::this_thread::sleep_for(std::chrono::seconds(2)); + int i2 = Download(link, GetEN(),true); + if(i2 != -1){ + error(Sec("Launcher Update failed! code : ") + std::to_string(i2)); + std::this_thread::sleep_for(std::chrono::seconds(5)); + ReLaunch(argc,args); + } + } + URelaunch(argc,args); + }else{ + info(Sec("Version is up to date")); + } +} +void CheckDir(int argc,char*args[]){ + std::string CDir = args[0]; + std::string MDir = Sec("BeamNG\\mods"); + if(!fs::is_directory(Sec("BeamNG"))){ + if(!fs::create_directory(Sec("BeamNG"))){ + error(Sec("Cannot Create BeamNG Directory! Retrying...")); + std::this_thread::sleep_for(std::chrono::seconds(3)); + ReLaunch(argc,args); + } + } + if(fs::is_directory(MDir) && !Dev){ + int c = 0; + for (auto& p : fs::directory_iterator(MDir))c++; + if(c > 2) { + warn(std::to_string(c-1) + Sec(" local mods will be wiped! Close this window if you don't want that!")); + std::this_thread::sleep_for(std::chrono::seconds(15)); + } + try{ + fs::remove_all(MDir); + } catch (...) { + error(Sec("Please close the game and try again")); + std::this_thread::sleep_for(std::chrono::seconds(5)); + exit(1); + } + } + if(fs::is_directory(MDir) && !Dev)ReLaunch(argc,args); + if(!fs::create_directory(MDir) && !Dev){ + error(Sec("Cannot Create Mods Directory! Retrying...")); + std::this_thread::sleep_for(std::chrono::seconds(3)); + ReLaunch(argc,args); + } + if(!fs::is_directory(Sec("BeamNG\\settings"))){ + if(!fs::create_directory(Sec("BeamNG\\settings"))){ + error(Sec("Cannot Create Settings Directory! Retrying...")); + std::this_thread::sleep_for(std::chrono::seconds(3)); + ReLaunch(argc,args); + } + } +} +void CustomPort(int argc, char* argv[]){ + if(argc > 1){ + std::string Port = argv[1]; + if(Port.find_first_not_of("0123456789") == std::string::npos){ + if(std::stoi(Port) > 1000){ + DEFAULT_PORT = std::stoi(Port); + warn(Sec("Running on custom port : ") + std::to_string(DEFAULT_PORT)); + } + } + if(argc > 2)Dev = false; + } +} +void InitLauncher(int argc, char* argv[]) { + system(Sec("cls")); + SetConsoleTitleA((Sec("BeamMP Launcher v") + std::string(GetVer()) + GetPatch()).c_str()); + InitLog(); + CheckName(argc, argv); + SecurityCheck(argv); + Discord_Main(); + RequestRole(); + CustomPort(argc, argv); + CheckForUpdates(argc, argv, std::string(GetVer()) + GetPatch()); +} + +void PreGame(int argc, char* argv[],const std::string& GamePath){ + info(Sec("Game Version : ") + CheckVer(GamePath)); + std::string DUI = Sec(R"(BeamNG\settings\uiapps-layouts.json)"); + std::string GS = Sec(R"(BeamNG\settings\game-settings.ini)"); + std::string link = Sec("https://beammp.com/client-ui-data"); + int i; + if(!fs::exists(DUI)){ + info(Sec("Downloading default ui data...")); + i = Download(link,DUI,true); + if(i != -1){ + remove(DUI.c_str()); + error(Sec("Failed to download code : ") + std::to_string(i)); + std::this_thread::sleep_for(std::chrono::seconds(3)); + ReLaunch(argc,argv); + } + info(Sec("Download Complete!")); + } + if(!fs::exists(GS)) { + info(Sec("Downloading default game settings...")); + link = Sec("https://beammp.com/client-settings-data"); + Download(link, GS,true); + info(Sec("Download Complete!")); + } + if(!Dev) { + info(Sec("Downloading mod...")); + link = Sec("https://beammp.com/builds/client?did=") + GetDID(); + Download(link, Sec(R"(BeamNG\mods\BeamMP.zip)"), false); + info(Sec("Download Complete!")); + } + debug(Sec("Name : ") + GetDName()); + debug(Sec("Discriminator : ") + GetDTag()); + debug(Sec("Unique ID : ") + GetDID()); +} \ No newline at end of file diff --git a/src/UpdateCheck.cpp b/src/UpdateCheck.cpp deleted file mode 100644 index 7cbece4..0000000 --- a/src/UpdateCheck.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/// -/// Created by Anonymous275 on 3/29/2020 -/// - -#include -#include -#include - -int Download(const std::string& URL,const std::string& path); -std::string HTTP_REQUEST(const std::string&url,int port); -void SystemExec(const std::string& cmd); -void URelaunch(int argc,char* args[]); -void ReLaunch(int argc,char*args[]); -void Exit(const std::string& Msg); -extern char*EName; -std::string hta(const std::string& hex) -{ - std::string ascii; - for (size_t i = 0; i < hex.length(); i += 2) - { - std::string part = hex.substr(i, 2); - char ch = char(stoul(part, nullptr, 16)); - ascii += ch; - } - return ascii; -} - -void CheckForUpdates(int argc,char*args[],const std::string& CV){ - std::string link = hta("68747470733a2f2f6265616d6e672d6d702e636f6d2f6275696c64732f6c61756e636865723f76657273696f6e3d74727565"); - //https://beamng-mp.com/builds/launcher?version=true - std::string HTTP = HTTP_REQUEST(link,443); - if(HTTP.find_first_of("0123456789") == std::string::npos){ - Exit("Primary Servers Offline! sorry for the inconvenience!"); - } - link = hta("68747470733a2f2f6265616d6e672d6d702e636f6d2f6275696c64732f6c61756e636865723f646f776e6c6f61643d74727565"); - //https://beamng-mp.com/builds/launcher?download=true - - struct stat buffer{}; - std::string Back = hta("4265616d4d502d4c61756e636865722e6261636b"); - //BeamMP-Launcher.back - if(stat(Back.c_str(), &buffer) == 0)remove(Back.c_str()); - if(HTTP > CV){ - system("cls"); - std::cout << "Update found!" << std::endl; - std::cout << "Updating..." << std::endl; - SystemExec("rename "+hta(EName)+" "+Back+">nul"); - if(int i = Download(link, hta(EName)) != -1){ - std::cout << "Launcher Update failed! trying again... code : " << i << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(2)); - if(int i2 = Download(link, hta(EName)) != -1){ - std::cout << "Launcher Update failed! code : " << i2 << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(5)); - ReLaunch(argc,args); - } - } - URelaunch(argc,args); - }else{ - std::cout << "Version is up to date" << std::endl; - } -} \ No newline at end of file diff --git a/src/VehicleNetwork.cpp b/src/VehicleNetwork.cpp deleted file mode 100644 index 79de19c..0000000 --- a/src/VehicleNetwork.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/// -/// Created by Anonymous275 on 4/23/2020 -/// - -#include -#include -#include -#include -#include -#include - -extern bool TCPTerminate; -extern bool Dev; -void Print(const std::string&MSG); -std::queue VNTCPQueue; -//void RUDPSEND(const std::string&Data,bool Rel); -#define DEFAULT_PORT "4446" - -void Responder(const SOCKET *CS){ - SOCKET ClientSocket = *CS; - int iSendResult; - while(!TCPTerminate){ - while (!VNTCPQueue.empty()) { - VNTCPQueue.front() += "\n"; - iSendResult = send(ClientSocket, VNTCPQueue.front().c_str(), VNTCPQueue.front().length(), 0); - if (iSendResult == SOCKET_ERROR) { - if(Dev)std::cout << "(VN) send failed with error: " << WSAGetLastError() << std::endl; - break; - } else { - if(iSendResult > 1000){ - if(Dev){std::cout << "(Launcher->Game VN) Bytes sent: " << iSendResult << " : " << VNTCPQueue.front().substr(0, 10) - << VNTCPQueue.front().substr(VNTCPQueue.front().length()-10) << std::endl;} - } - VNTCPQueue.pop(); - } - } - std::this_thread::sleep_for(std::chrono::nanoseconds(1)); - } -} -std::string Compress(const std::string&Data); -std::string Decompress(const std::string&Data); -void VehicleNetworkStart(){ - do { - if(Dev)std::cout << "VN on Start" << std::endl; - WSADATA wsaData; - int iResult; - SOCKET ListenSocket = INVALID_SOCKET; - SOCKET ClientSocket = INVALID_SOCKET; - - struct addrinfo *result = nullptr; - struct addrinfo hints{}; - - int iSendResult; - char recvbuf[7507]; - int recvbuflen = 6507; - - // Initialize Winsock - iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); - if (iResult != 0) { - if(Dev)std::cout << "(VN) WSAStartup failed with error: " << iResult << std::endl; - std::cin.get(); - exit(-1); - } - - ZeroMemory(&hints, sizeof(hints)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; - hints.ai_flags = AI_PASSIVE; - - // Resolve the server address and port - iResult = getaddrinfo(nullptr, DEFAULT_PORT, &hints, &result); - if (iResult != 0) { - if(Dev)std::cout << "(VN) getaddrinfo failed with error: " << iResult << std::endl; - WSACleanup(); - break; - } - - // Create a socket for connecting to server - ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); - if (ListenSocket == INVALID_SOCKET) { - if(Dev)std::cout << "(VN) socket failed with error: " << WSAGetLastError() << std::endl; - freeaddrinfo(result); - WSACleanup(); - break; - } - - // Setup the TCP listening socket - iResult = bind(ListenSocket, result->ai_addr, (int) result->ai_addrlen); - if (iResult == SOCKET_ERROR) { - if(Dev)std::cout << "(VN) bind failed with error: " << WSAGetLastError() << std::endl; - freeaddrinfo(result); - closesocket(ListenSocket); - WSACleanup(); - break; - } - - freeaddrinfo(result); - - iResult = listen(ListenSocket, SOMAXCONN); - if (iResult == SOCKET_ERROR) { - if(Dev)std::cout << "(VN) listen failed with error: " << WSAGetLastError() << std::endl; - closesocket(ListenSocket); - WSACleanup(); - continue; - } - ClientSocket = accept(ListenSocket, NULL, NULL); - if (ClientSocket == INVALID_SOCKET) { - if(Dev)std::cout << "(VN) accept failed with error: " << WSAGetLastError() << std::endl; - closesocket(ListenSocket); - WSACleanup(); - continue; - } - closesocket(ListenSocket); - if(Dev)std::cout << "(VN) Game Connected!" << std::endl; - - std::thread TCPSend(Responder,&ClientSocket); - TCPSend.detach(); - do { - //std::cout << "(Proxy) Waiting for Game Data..." << std::endl; - iResult = recv(ClientSocket, recvbuf, recvbuflen, 0); - if (iResult > 0) { - std::string buff; - buff.resize(iResult*2); - memcpy(&buff[0],recvbuf,iResult); - buff.resize(iResult); - //Print(buff); - if(Dev) { - std::string cmp = Compress(buff), dcm = Decompress(cmp); - std::cout << "Compressed Size : " << cmp.length() << std::endl; - std::cout << "Decompressed Size : " << dcm.length() << std::endl; - if (cmp == dcm) { - std::cout << "Success!" << std::endl; - } else { - std::cout << "Fail!" << std::endl; - } - } - //RUDPSEND(buff,false); - //std::cout << "(Game->Launcher VN) Data : " << buff.length() << std::endl; - } else if (iResult == 0) { - if(Dev)std::cout << "(VN) Connection closing...\n"; - closesocket(ClientSocket); - WSACleanup(); - - continue; - } else { - if(Dev)std::cout << "(VN) recv failed with error: " << WSAGetLastError() << std::endl; - closesocket(ClientSocket); - WSACleanup(); - continue; - } - } while (iResult > 0); - - iResult = shutdown(ClientSocket, SD_SEND); - if (iResult == SOCKET_ERROR) { - if(Dev)std::cout << "(VN) shutdown failed with error: " << WSAGetLastError() << std::endl; - closesocket(ClientSocket); - WSACleanup(); - continue; - } - closesocket(ClientSocket); - WSACleanup(); - }while (!TCPTerminate); -} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7b836d4..9310f94 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,212 +1,26 @@ -//// -//// Created by Anonymous275 on 3/3/2020. -//// -#include -#include -#include -#include -#include -#include +/// +/// Created by Anonymous275 on 7/16/2020 +/// +#include "Network/network.h" +#include "Security/Init.h" +#include "Startup.h" #include -int Download(const std::string& URL,const std::string& OutFileName); -void StartGame(const std::string&ExeDir,const std::string&Current); -std::string HTTP_REQUEST(const std::string&url,int port); -void CheckForUpdates(int argc,char*args[],const std::string& CV); -char*EName = (char*)"4265616d4d502d4c61756e636865722e657865"; -extern std::vector GlobalInfo; -std::string HTA(const std::string& hex); -extern std::vector SData; -std::string getHardwareID(); -char* ver = (char*)"312e3530"; //1.50 -char* patchlevel = (char*)""; -int DEFAULT_PORT = 4444; -void Discord_Main(); -bool Dev = false; -void ProxyStart(); -void ExitError(); -void Check(); +#include -void SystemExec(const std::string& cmd){ - system(cmd.c_str()); -} - -void WinExec(const std::string& cmd){ - WinExec(cmd.c_str(), SW_HIDE); -} - -void Exit(const std::string& Msg){ - std::cout << Msg << std::endl; - std::cout << "Press Enter to continue..."; - std::cin.ignore(); - exit(-1); -} -void ReLaunch(int argc,char*args[]){ - std::string Arg; - for(int c = 2; c <= argc; c++){ - Arg += " "; - Arg += args[c-1]; - } - system("cls"); - ShellExecute(nullptr,"runas",HTA(EName).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); - exit(1); -} -std::string CheckDir(int argc,char*args[]){ - struct stat info{}; - std::string CDir = args[0]; - if(stat("BeamNG",&info)){ - SystemExec("mkdir BeamNG>nul"); - if(stat("BeamNG",&info))ReLaunch(argc,args); - } - if(!stat("BeamNG\\mods",&info))SystemExec("RD /S /Q BeamNG\\mods>nul"); - if(!stat("BeamNG\\mods",&info))ReLaunch(argc,args); - SystemExec("mkdir BeamNG\\mods>nul"); - if(stat("BeamNG\\settings",&info))SystemExec("mkdir BeamNG\\settings>nul"); - return CDir.substr(0,CDir.find_last_of('\\')) + "\\BeamNG"; -} - -std::string CheckVer(const std::string &path){ - std::string vec,temp,Path = path.substr(0,path.find_last_of('\\')) + "\\integrity.json"; - std::ifstream f(Path.c_str(), std::ios::binary); - f.seekg(0, std::ios_base::end); - std::streampos fileSize = f.tellg(); - vec.resize(size_t(fileSize) + 1); - f.seekg(0, std::ios_base::beg); - f.read(&vec[0], fileSize); - f.close(); - vec = vec.substr(vec.find_last_of("version"),vec.find_last_of('"')); - for(const char &a : vec){ - if(isdigit(a) || a == '.')temp+=a; - } - return temp; -} - -void URelaunch(int argc,char* args[]){ - std::string Arg; - for(int c = 2; c <= argc; c++){ - Arg += " "; - Arg += args[c-1]; - } - ShellExecute(nullptr,"open",HTA(EName).c_str(),Arg.c_str(),nullptr,SW_SHOWNORMAL); - exit(1); -} - -void CheckName(int argc,char* args[]){ - struct stat info{}; - std::string DN = HTA(EName),CDir = args[0],FN = CDir.substr(CDir.find_last_of('\\')+1); - if(FN != DN){ - if(stat(DN.c_str(),&info)==0)remove(DN.c_str()); - if(stat(DN.c_str(),&info)==0)ReLaunch(argc,args); - SystemExec("rename \""+ FN +"\" " + DN + ">nul"); - URelaunch(argc,args); +[[noreturn]] void aa(){ + while(true){ + std::cout.flush(); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } -void SecurityCheck(){ - int i = 0; - std::ifstream f(HTA(EName), std::ios::binary); - f.seekg(0, std::ios_base::end); - std::streampos fileSize = f.tellg(); - if(IsDebuggerPresent() || fileSize > 0x60B5F){ - i++; - GlobalInfo.clear(); - GlobalInfo.at(13); - } - if(i){ - GlobalInfo.clear(); - GlobalInfo.at(13); - } - f.close(); +int main(int argc, char* argv[]) { + std::thread gb(aa); + gb.detach(); + InitLauncher(argc,argv); + CheckDir(argc,argv); + LegitimacyCheck(); + PreGame(argc,argv,GetGameDir()); + InitGame(GetGameDir(),argv[0]); + CoreNetwork(); } -int main(int argc, char* argv[]){ - const unsigned long long NPos = std::string::npos; - struct stat info{}; - system("cls"); - SetConsoleTitleA(("BeamMP Launcher v" + HTA(ver) + patchlevel).c_str()); - CheckName(argc,argv); - SecurityCheck(); - std::string link, HTTP_Result; - std::thread t1(Discord_Main); - t1.detach(); - std::cout << "Connecting to discord client..." << std::endl; - while(GlobalInfo.empty())std::this_thread::sleep_for(std::chrono::milliseconds(300)); - std::cout << "Client Connected!" << std::endl; - //https://beamng-mp.com/entitlement?did=(ID)&t=l; - HTTP_Result = HTTP_REQUEST(HTA("68747470733a2f2f6265616d6e672d6d702e636f6d2f656e7469746c656d656e743f6469643d")+ - HTA(GlobalInfo.at(2) + "26743d6c"),443); - /*if (HTTP_Result.find("\"MOD\"") == NPos && HTTP_Result.find("\"EA\"") == NPos){ - if (HTTP_Result.find("\"SUPPORT\"") == NPos && HTTP_Result.find("\"YT\"") == NPos){ - exit(-1); - } - }*/ - - SecurityCheck(); - if(HTTP_Result.find('"') == NPos && HTTP_Result != "[]"){ - std::cout << HTA("596f7520617265206e6f7420696e20746865206f6666696369616c204265616d4d5020446973636f726420706c65617365206a6f696e20616e642074727920616761696e2068747470733a2f2f646973636f72642e67672f6265616d6d70") << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(3)); - exit(-1); - } - if(HTTP_Result.find(HTA("224d44455622")) != NPos)Dev = true; - std::string Path = CheckDir(argc,argv); - std::thread CFU(CheckForUpdates,argc,argv,HTA(ver)+patchlevel); - CFU.join(); - - if(argc > 1){ - std::string Port = argv[1]; - if(Port.find_first_not_of("0123456789") == NPos){ - if(std::stoi(Port) > 1000){ - DEFAULT_PORT = std::stoi(Port); - std::cout << "Running on custom port : " << DEFAULT_PORT << std::endl; - } - } - if(argc > 2)Dev = false; - } - - //Security - auto*Sec = new std::thread(Check); - Sec->join(); - delete Sec; - SecurityCheck(); - if(SData.size() != 3)ExitError(); - std::string GamePath = SData.at(2); - std::cout << "Game Version : " << CheckVer(GamePath) << std::endl; - std::string ExeDir = GamePath.substr(0,GamePath.find_last_of('\\')) + R"(\Bin64\BeamNG.drive.x64.exe)"; - std::string DUI = Path + R"(\settings\uiapps-layouts.json)"; - std::string GS = Path + R"(\settings\game-settings.ini)"; - if(stat(DUI.c_str(),&info)!=0 || stat(GS.c_str(),&info)!=0){ - link = "https://beamng-mp.com/client-ui-data"; - std::cout << "Downloading default config..." << std::endl; - if(int i = Download(link,DUI) != -1){ - remove(DUI.c_str()); - std::cout << "Error! Failed to download code : " << i << std::endl; - std::this_thread::sleep_for(std::chrono::seconds(3)); - ReLaunch(argc,argv); - } - link = "https://beamng-mp.com/client-settings-data"; - Download(link,GS); - std::cout << "Download Complete!" << std::endl; - } - DUI.clear(); - GS.clear(); - if(!Dev){ - std::cout << "Downloading mod..." << std::endl; - //https://beamng-mp.com/builds/client?did=(ID) - link = HTA("68747470733a2f2f6265616d6e672d6d702e636f6d2f6275696c64732f636c69656e743f6469643d") - +HTA(GlobalInfo.at(2)); - Download(link,Path + R"(\mods\BeamMP.zip)"); - std::cout << "Download Complete!" << std::endl; - link.clear(); - std::thread Game(StartGame,ExeDir,(Path + "\\")); - Game.detach(); - }else{ - SecurityCheck(); - std::cout << "Name : " << GlobalInfo.at(0) << std::endl; - std::cout << "Discriminator : " << HTA(GlobalInfo.at(1)) << std::endl; - std::cout << "Unique ID : " << HTA(GlobalInfo.at(2)) << std::endl; - //std::cout << "HWID : " << getHardwareID() << std::endl; - std::cout << "you have : " << HTTP_Result << std::endl; - } - - ProxyStart(); - Exit(""); - return 0; -} \ No newline at end of file