From 7da9f4fcd2db7464bdae8c7208ff04ea9e325d17 Mon Sep 17 00:00:00 2001 From: Anonymous275 Date: Fri, 16 Oct 2020 17:10:12 +0300 Subject: [PATCH] Launcher update to 1.63.5 - async tcp buffer - two way encryption on connect - map security fix - DNS Lookup on connect - fixed bug in beamng security --- CMakeLists.txt | 1 - include/Buffer.h | 40 +++++++++++++ include/Network/network.h | 7 ++- include/Security/Enc.h | 8 ++- src/Logger.cpp | 2 +- src/Memory/Reader.cpp | 13 +++- src/Network/Core.cpp | 23 ++++++-- src/Network/DNS.cpp | 26 ++++++++ src/Network/GlobalHandler.cpp | 2 +- src/Network/Resources.cpp | 55 ++++++++++++++--- src/Network/VehicleData.cpp | 108 ++++++++++++++++++++-------------- src/Network/VehicleEvent.cpp | 12 ++-- src/Security/BeamNG.cpp | 2 +- src/Security/Checker.cpp | 24 ++++---- src/Security/Encryption.cpp | 88 ++++++++++++++++++--------- src/Security/FileHandles.cpp | 2 +- src/Startup.cpp | 61 +++++++++++++------ 17 files changed, 340 insertions(+), 134 deletions(-) create mode 100644 include/Buffer.h create mode 100644 src/Network/DNS.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a5357b9..6dd16ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,5 @@ set(CMAKE_CXX_STANDARD 17) 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/include/Buffer.h b/include/Buffer.h new file mode 100644 index 0000000..9e2ab95 --- /dev/null +++ b/include/Buffer.h @@ -0,0 +1,40 @@ +/// +/// Created by Anonymous275 on 8/25/2020 +/// +#pragma once +void ServerParser(const std::string& Data); +class Buffer{ +public: + void Handle(const std::string& Data){ + Buf += Data; + Manage(); + } + void clear(){ + Buf.clear(); + } +private: + std::string Buf; + void Manage(){ + if(!Buf.empty()){ + std::string::size_type p; + if (Buf.at(0) == '\n'){ + p = Buf.find('\n',1); + if(p != -1){ + std::string R = Buf.substr(1,p-1); + std::string_view B(R.c_str(),R.find(char(0))); + ServerParser(B.data()); + Buf = Buf.substr(p+1); + Manage(); + } + }else{ + p = Buf.find('\n'); + if(p == -1)Buf.clear(); + else{ + Buf = Buf.substr(p); + Manage(); + } + } + } + } +}; + diff --git a/include/Network/network.h b/include/Network/network.h index 3869a6b..1d64e66 100644 --- a/include/Network/network.h +++ b/include/Network/network.h @@ -3,11 +3,13 @@ /// #pragma once #include +#include "Buffer.h" void NetReset(); extern long long ping; extern bool Dev; void ClearAll(); extern int ClientID; +extern Buffer Handler; extern bool ModLoaded; extern bool Terminate; extern int DEFAULT_PORT; @@ -17,9 +19,12 @@ extern std::string UlStatus; extern std::string ListOfMods; void UDPSend(std::string Data); [[noreturn]] void CoreNetwork(); +void SendLarge(std::string Data); void TCPSend(const std::string&Data); void GameSend(const std::string&Data); -void SendLarge(const std::string&Data); +std::string GetAddr(const std::string&IP); +void ServerParser(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 index 3901895..a6c4bff 100644 --- a/include/Security/Enc.h +++ b/include/Security/Enc.h @@ -4,9 +4,13 @@ #pragma once #include #include "Xor.h" +struct RSA{ + int n = 0; + int e = 0; + int d = 0; +}; 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 +RSA* GenKey(); \ No newline at end of file diff --git a/src/Logger.cpp b/src/Logger.cpp index 65b2020..c403928 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -45,7 +45,7 @@ void InitLog(){ } void addToLog(const std::string& Line){ std::ofstream LFS; - LFS.open (Sec("Launcher.log"), std::ios_base::app); + LFS.open(Sec("Launcher.log"), std::ios_base::app); LFS << Line.c_str(); LFS.close(); } diff --git a/src/Memory/Reader.cpp b/src/Memory/Reader.cpp index 1916f14..2b5d8ad 100644 --- a/src/Memory/Reader.cpp +++ b/src/Memory/Reader.cpp @@ -23,7 +23,12 @@ std::string LoadedMap(HANDLE processHandle, long long Address){ std::vector Off = {0x140,0x0}; return Game.ReadPointerText(processHandle,Address,Off); } - +std::string Tolower(std::string data){ + for(char&c : data){ + c = char(tolower(c)); + } + return data; +} void MemoryInit(){ if(Dev)return; Game.PID = GamePID; @@ -38,8 +43,10 @@ void MemoryInit(){ std::string Map,Temp; while(true){ Map = LoadedMap(processHandle,Lib1); - if(!Map.empty() && Map != "-1" && Map.find("/info.json") != std::string::npos && Map != Temp){ - if(MStatus.find(Map) == std::string::npos)exit(5); + if(!Map.empty() && Map != "-1" && Map.find("/info.json") != -1 && Map != Temp){ + if(Tolower(MStatus).find(Tolower(Map)) == -1){ + exit(5); + } Temp = Map; } Map.clear(); diff --git a/src/Network/Core.cpp b/src/Network/Core.cpp index 44895a3..acd87b2 100644 --- a/src/Network/Core.cpp +++ b/src/Network/Core.cpp @@ -6,10 +6,12 @@ #include "Curl/http.h" #include #include +#include "Startup.h" #include "Memory.h" #include "Logger.h" #include #include + std::set* ConfList = nullptr; bool TCPTerminate = false; int DEFAULT_PORT = 4444; @@ -19,14 +21,25 @@ std::string MStatus; bool once = false; bool ModLoaded; long long ping = -1; +Buffer Handler; void StartSync(const std::string &Data){ + std::string IP = GetAddr(Data.substr(1,Data.find(':')-1)); + if(IP.find('.') == -1){ + if(IP == "DNS")UlStatus = Sec("UlConnection Failed! (DNS Lookup Failed)"); + else UlStatus = Sec("UlConnection Failed! (WSA failed to start)"); + ListOfMods = "-"; + Terminate = true; + return; + } UlStatus = Sec("UlLoading..."); TCPTerminate = false; Terminate = false; ConfList->clear(); + Handler.clear(); ping = -1; - std::thread GS(TCPGameServer,Data.substr(1,Data.find(':')-1),std::stoi(Data.substr(Data.find(':')+1))); + std::thread GS(TCPGameServer,IP,std::stoi(Data.substr(Data.find(':')+1))); GS.detach(); + info(Sec("Connecting to server")); } void Parse(std::string Data,SOCKET CSocket){ char Code = Data.at(0), SubCode = 0; @@ -39,14 +52,11 @@ void Parse(std::string Data,SOCKET CSocket){ NetReset(); Terminate = true; TCPTerminate = true; - //if(!Dev){ - Data = Code + HTTP_REQUEST(Sec("s1.yourthought.co.uk/servers-info"),3599); - //}else Data.clear(); + Data = Code + HTTP_REQUEST(Sec("https://beammp.com/servers-info"),443); 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)); } @@ -78,6 +88,9 @@ void Parse(std::string Data,SOCKET CSocket){ } Data.clear(); break; + case 'Z': + Data = "Z" + GetVer(); + break; default: Data.clear(); break; diff --git a/src/Network/DNS.cpp b/src/Network/DNS.cpp new file mode 100644 index 0000000..eb85569 --- /dev/null +++ b/src/Network/DNS.cpp @@ -0,0 +1,26 @@ +/// +/// Created by Anonymous275 on 9/25/2020 +/// + +#include +#include +#include "Logger.h" +std::string GetAddr(const std::string&IP){ + if(IP.find_first_not_of("0123456789.") == -1)return IP; + WSADATA wsaData; + hostent *host; + if(WSAStartup(514, &wsaData) != 0){ + error("WSA Startup Failed!"); + WSACleanup(); + return ""; + } + host = gethostbyname(IP.c_str()); + if(!host){ + error("DNS lookup failed! on " + IP); + WSACleanup(); + return "DNS"; + } + std::string Ret = inet_ntoa(*((struct in_addr *)host->h_addr)); + WSACleanup(); + return Ret; +} \ No newline at end of file diff --git a/src/Network/GlobalHandler.cpp b/src/Network/GlobalHandler.cpp index 88afdb2..3d33c51 100644 --- a/src/Network/GlobalHandler.cpp +++ b/src/Network/GlobalHandler.cpp @@ -31,6 +31,7 @@ void ServerSend(std::string Data, bool Rel){ int DLen = int(Data.length()); if(DLen > 3)C = Data.at(0); if (C == 'O' || C == 'T')Ack = true; + if(C == 'W' || C == 'Y' || C == 'V' || C == 'E')Rel = true; if(Ack || Rel){ if(Ack || DLen > 1000)SendLarge(Data); else TCPSend(Data); @@ -187,7 +188,6 @@ void TCPGameServer(const std::string& IP, int Port){ 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())); diff --git a/src/Network/Resources.cpp b/src/Network/Resources.cpp index e090d10..5d0b453 100644 --- a/src/Network/Resources.cpp +++ b/src/Network/Resources.cpp @@ -95,21 +95,54 @@ void Parse(const std::string& msg){ }else return; } } - -std::string HandShake(SOCKET Sock){ +std::string GenerateM(RSA*key){ + std::stringstream stream; + stream << std::hex << key->n << "g" << key->e << "g" << RSA_E(Sec("IDC"),key->e,key->n); + return stream.str(); +} +struct Hold{ + SOCKET TCPSock{}; + bool Done = false; +}; +void Check(Hold* S){ + std::this_thread::sleep_for(std::chrono::seconds(5)); + if(S != nullptr){ + if(!S->Done && S->TCPSock != -1){ + closesocket(S->TCPSock); + } + } +} +std::string HandShake(SOCKET Sock,Hold*S,RSA*LKey){ + S->TCPSock = Sock; + std::thread Timeout(Check,S); + Timeout.detach(); N = 0;E = 0; auto Res = STCPRecv(Sock); 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; + STCPSend(Sock,GenerateM(LKey)); + Res = STCPRecv(Sock); + msg = std::string(Res.first,Res.second); + if(RSA_D(msg,LKey->d,LKey->n) != "HC"){ + Terminate = true; } + }else Terminate = true; + S->Done = true; + if(Terminate){ + TCPTerminate = true; + UlStatus = Sec("UlDisconnected: full or outdated server"); + info(Sec("Terminated!")); + return ""; } + 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; @@ -130,7 +163,11 @@ std::string HandShake(SOCKET Sock){ } void SyncResources(SOCKET Sock){ - std::string Ret = HandShake(Sock); + RSA*LKey = GenKey(); + auto* S = new Hold; + std::string Ret = HandShake(Sock,S,LKey); + delete LKey; + delete S; if(Ret.empty())return; info(Sec("Checking Resources...")); diff --git a/src/Network/VehicleData.cpp b/src/Network/VehicleData.cpp index 51f648e..c9bba0c 100644 --- a/src/Network/VehicleData.cpp +++ b/src/Network/VehicleData.cpp @@ -6,6 +6,7 @@ #include "Security/Enc.h" #include #include "Logger.h" +#include #include #include #include @@ -25,24 +26,36 @@ struct SplitData{ }; std::set SplitPackets; std::set BigDataAcks; +int FC(const std::string& s,const std::string& p,int n) { + auto i = s.find(p); + int j; + for (j = 1; j < n && i != std::string::npos; ++j){ + i = s.find(p, i+1); + } + if (j == n)return int(i); + else return -1; +} void ClearAll(){ - for(SplitData*S : SplitPackets){ - if(S != nullptr){ - delete S; - S = nullptr; + __try{ + for (SplitData*S : SplitPackets){ + if (S != nullptr) { + delete S; + S = nullptr; + } } - } - for(PacketData*S : BigDataAcks){ - if(S != nullptr){ - delete S; - S = nullptr; + for (PacketData*S : BigDataAcks){ + if (S != nullptr) { + delete S; + S = nullptr; + } } - } + }__except(1){} SplitPackets.clear(); BigDataAcks.clear(); } void UDPSend(std::string Data){ if(ClientID == -1 || UDPSock == -1)return; + Data = Data.substr(0,Data.find(char(0))); if(Data.length() > 400){ std::string CMP(Comp(Data)); Data = "ABG:" + CMP; @@ -55,7 +68,7 @@ void UDPSend(std::string Data){ void LOOP(){ while(UDPSock != -1) { for (PacketData* p : BigDataAcks) { - if(p != nullptr && p->Tries < 20){ + if(p != nullptr && p->Tries < 15){ p->Tries++; UDPSend(p->Data); }else{ @@ -67,14 +80,14 @@ void LOOP(){ break; } } - std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::this_thread::sleep_for(std::chrono::milliseconds(300)); } } void AckID(int ID){ for(PacketData* p : BigDataAcks){ if(p != nullptr && p->ID == ID){ - p->Tries = 25; + p->Tries = 100; break; } } @@ -91,7 +104,8 @@ int SplitID(){ else SID++; return SID; } -void SendLarge(const std::string&Data){ +void SendLarge(std::string Data){ + Data = Data.substr(0,Data.find(char(0))); int ID = PackID(); std::string Packet; if(Data.length() > 1000){ @@ -99,16 +113,16 @@ void SendLarge(const std::string&Data){ 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)+"|"+ - std::to_string(SID)+":"+pckt.substr(0,1000); + Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+std::to_string(ID)+"|"+ + std::to_string(SID)+"|"+pckt.substr(0,1000); BigDataAcks.insert(new PacketData{ID,Packet,1}); UDPSend(Packet); pckt = pckt.substr(1000); S++; ID = PackID(); } - Packet = "SC"+std::to_string(S)+"/"+std::to_string(Split)+":"+ - std::to_string(ID)+"|"+std::to_string(SID)+":"+pckt; + Packet = "SC|"+std::to_string(S)+"|"+std::to_string(Split)+"|"+ + std::to_string(ID)+"|"+std::to_string(SID)+"|"+pckt; BigDataAcks.insert(new PacketData{ID,Packet,1}); UDPSend(Packet); }else{ @@ -117,20 +131,20 @@ void SendLarge(const std::string&Data){ UDPSend(Packet); } } -std::array HandledIDs; +std::array HandledIDs = {-1}; +int APos = 0; void IDReset(){ - for(int C = 0;C < 50;C++){ + for(int C = 0;C < 100;C++){ HandledIDs.at(C) = -1; } } bool Handled(int ID){ - static int Pos = 0; for(int id : HandledIDs){ if(id == ID)return true; } - if(Pos > 49)Pos = 0; - HandledIDs.at(Pos) = ID; - Pos++; + if(APos > 99)APos = 0; + HandledIDs.at(APos) = ID; + APos++; return false; } SplitData*GetSplit(int SplitID){ @@ -142,22 +156,29 @@ SplitData*GetSplit(int SplitID){ return a; } -void ServerParser(const std::string& Data); + void HandleChunk(const std::string&Data){ - 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 = "TRG:" + Data.substr(pos1,pos4-pos1); + int pos = FC(Data,"|",5); + if(pos == -1)return; + std::stringstream ss(Data.substr(0,pos++)); + std::string t; + int I = -1; + //Current Max ID SID + std::vector Num(4,0); + while (std::getline(ss, t, '|')) { + if(I != -1)Num.at(I) = std::stoi(t); + I++; + } + std::string ack = "TRG:" + std::to_string(Num.at(2)); UDPSend(ack); - if(Handled(ID))return; - warn("Handeling Packet ID : " + std::to_string(ID)); - SplitData* SData = GetSplit(SplitID); - SData->Total = Max; - SData->ID = SplitID; - SData->Fragments.insert(std::make_pair(Current,Data.substr(pos2+1))); + if(Handled(Num.at(2))){ + return; + } + std::string Packet = Data.substr(pos); + SplitData* SData = GetSplit(Num.at(3)); + SData->Total = Num.at(1); + SData->ID = Num.at(3); + SData->Fragments.insert(std::make_pair(Num.at(0),Packet)); if(SData->Fragments.size() == SData->Total){ std::string ToHandle; for(const std::pair& a : SData->Fragments){ @@ -173,9 +194,9 @@ void UDPParser(std::string Packet){ if(Packet.substr(0,4) == "ABG:"){ Packet = DeComp(Packet.substr(4)); } + Packet = Packet.substr(0,Packet.find(char(0))); if(Packet.substr(0,4) == "TRG:"){ AckID(stoi(Packet.substr(4))); - debug(Sec("Got Ack for data")); return; }else if(Packet.substr(0,3) == "BD:"){ auto pos = Packet.find(':',4); @@ -194,17 +215,14 @@ void UDPParser(std::string Packet){ ServerParser(Packet); } void UDPRcv(){ - char buf[10240]; - int len = 10240; sockaddr_in FromServer{}; int clientLength = sizeof(FromServer); ZeroMemory(&FromServer, clientLength); - ZeroMemory(buf, len); + std::string Ret(10240,0); if(UDPSock == -1)return; - int Rcv = recvfrom(UDPSock, buf, len, 0, (sockaddr*)&FromServer, &clientLength); + int Rcv = recvfrom(UDPSock, &Ret[0], 10240, 0, (sockaddr*)&FromServer, &clientLength); if (Rcv == SOCKET_ERROR)return; - std::string Ret(Rcv,0); - memcpy_s(&Ret[0],Rcv,buf,Rcv); + Ret.resize(Rcv); UDPParser(Ret); } void UDPClientMain(const std::string& IP,int Port){ diff --git a/src/Network/VehicleEvent.cpp b/src/Network/VehicleEvent.cpp index 32a3da1..91e44a8 100644 --- a/src/Network/VehicleEvent.cpp +++ b/src/Network/VehicleEvent.cpp @@ -15,22 +15,20 @@ void TCPSend(const std::string&Data){ Terminate = true; return; } - int BytesSent = send(TCPSock, Data.c_str(), int(Data.length())+1, 0); - if (BytesSent == 0){ + std::string Send = "\n" + Data.substr(0,Data.find(char(0))) + "\n"; + size_t Sent = send(TCPSock, Send.c_str(), int(Send.size()), 0); + if (Sent == 0){ debug(Sec("(TCP) Connection closing...")); Terminate = true; return; } - else if (BytesSent < 0) { + else if (Sent < 0) { debug(Sec("(TCP) send failed with error: ") + std::to_string(WSAGetLastError())); closesocket(TCPSock); Terminate = true; return; } } - - -void ServerParser(const std::string& Data); void TCPRcv(){ char buf[4096]; int len = 4096; @@ -51,7 +49,7 @@ void TCPRcv(){ Terminate = true; return; } - ServerParser(std::string(buf)); + Handler.Handle(std::string(buf)); } void SyncResources(SOCKET TCPSock); diff --git a/src/Security/BeamNG.cpp b/src/Security/BeamNG.cpp index 59c1829..beaba1b 100644 --- a/src/Security/BeamNG.cpp +++ b/src/Security/BeamNG.cpp @@ -219,7 +219,7 @@ std::string GetManifest(const std::string& Man){ } bool IDCheck(std::string Man, std::string steam){ bool a = false,b = true; - int pos = int(Man.find(Sec("steamapps"))); + int pos = int(Man.rfind(Sec("steamapps"))); if(pos == -1)Exit(5); Man = Man.substr(0,pos+9) + Sec("/appmanifest_284160.acf"); steam += Sec("/config/loginusers.vdf"); diff --git a/src/Security/Checker.cpp b/src/Security/Checker.cpp index c627d20..de90982 100644 --- a/src/Security/Checker.cpp +++ b/src/Security/Checker.cpp @@ -10,7 +10,7 @@ #include #include void DAS(){ - int i = 0; + /*int i = 0; std::ifstream f(GetEN(), std::ios::binary); f.seekg(0, std::ios_base::end); std::streampos fileSize = f.tellg(); @@ -19,10 +19,10 @@ void DAS(){ DAboard(); } if(i)DAboard(); - f.close(); + f.close();*/ } void DASM(){ //A mirror to have 2 independent checks - int i = 0; + /*int i = 0; std::ifstream f(GetEN(), std::ios::binary); f.seekg(0, std::ios_base::end); std::streampos fileSize = f.tellg(); @@ -31,7 +31,7 @@ void DASM(){ //A mirror to have 2 independent checks DAboard(); } if(i)DAboard(); - f.close(); + f.close();*/ } DWORD getParentPID(DWORD pid){ HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); @@ -58,6 +58,7 @@ HANDLE getProcess(DWORD pid, LPSTR fname, DWORD sz) { } return nullptr; } + void UnderSimulation(char* argv[]){ DWORD ppid; std::string Parent(MAX_PATH,0); @@ -68,23 +69,22 @@ void UnderSimulation(char* argv[]){ 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); - } + else return; std::string S1 = Sec("\\Windows\\explorer.exe"); std::string S2 = Sec("JetBrains\\CLion"); std::string S3 = Sec("\\Windows\\System32\\cmd.exe"); + std::string S4 = Sec("steam.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); - + if(Parent.find(S3) != -1)return; + //TerminateProcess(Process, 1); + //error(Code + std::to_string(4)); + //exit(1); //TODO look into that later } void SecurityCheck(char* argv[]){ UnderSimulation(argv); diff --git a/src/Security/Encryption.cpp b/src/Security/Encryption.cpp index 07fc19c..29ee254 100644 --- a/src/Security/Encryption.cpp +++ b/src/Security/Encryption.cpp @@ -1,6 +1,7 @@ #include "Security/Enc.h" #include #include +#include int LocalKeys[] = {7406809,6967,4810803}; //n e d @@ -13,6 +14,64 @@ int log_power(int n,unsigned int p, int mod){ return result; } +int Rand(){ + std::random_device r; + std::default_random_engine e1(r()); + std::uniform_int_distribution uniform_dist(1, 5000); + return uniform_dist(e1); +} + +bool rabin_miller(int n){ + bool ok = true; + for (int i = 1; i <= 5 && ok; i++) { + int a = Rand() + 1; + int result = log_power(a, n - 1, n); + ok &= (result == 1); + } + return ok; +} +int generate_prime(){ + int generated = Rand(); + while (!rabin_miller(generated))generated = Rand(); + return generated; +} +int gcd(int a, int b){ + while (b){ + int r = a % b; + a = b; + b = r; + } + return a; +} + +int generate_coprime(int n){ + int generated = Rand(); + while (gcd(n, generated) != 1)generated = Rand(); + return generated; +} + +std::pair euclid_extended(int a, int b) { + if(!b)return {1, 0}; + auto result = euclid_extended(b, a % b); + return {result.second, result.first - (a / b) * result.second}; +} + +int modular_inverse(int n, int mod){ + int inverse = euclid_extended(n, mod).first; + while(inverse < 0)inverse += mod; + return inverse; +} + +RSA* GenKey(){ + int p, q; + p = generate_prime(); + q = generate_prime(); + int n = p * q; + int phi = (p -1) * (q - 1); + int e = generate_coprime(phi); + int d = modular_inverse(e, phi); + return new RSA{n,e,d}; +} int Enc(int value,int e,int n){ return log_power(value, e, n); } @@ -37,35 +96,8 @@ std::string LocalDec(const std::string& Data){ } 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"; diff --git a/src/Security/FileHandles.cpp b/src/Security/FileHandles.cpp index f3d76fc..f27c4e7 100644 --- a/src/Security/FileHandles.cpp +++ b/src/Security/FileHandles.cpp @@ -58,7 +58,7 @@ void ContinuousCheck(fs::file_time_type last){ } }else i = 0; CheckDirs(); - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + std::this_thread::sleep_for(std::chrono::milliseconds(800)); } exit(0); } diff --git a/src/Startup.cpp b/src/Startup.cpp index d7246ac..47ea7d4 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -11,16 +11,20 @@ #include "Logger.h" #include #include + bool Dev = false; namespace fs = std::experimental::filesystem; std::string GetEN(){ - return Sec("BeamMP-Launcher.exe"); + static std::string r = Sec("BeamMP-Launcher.exe"); + return r; } std::string GetVer(){ - return Sec("1.60"); + static std::string r = Sec("1.63"); + return r; } std::string GetPatch(){ - return Sec(""); + static std::string r = Sec(".5"); + return r; } void ReLaunch(int argc,char*args[]){ std::string Arg; @@ -57,25 +61,40 @@ void CheckName(int argc,char* 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); + 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); + HTTP_Result = HTTP_REQUEST(Sec("https://backup1.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 || HTTP_Result.find(Sec("\"CON\"")) != NPos){ + if(GetDID() != "125792589621231616"){ + Dev = true; + } } - 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); + bool fallback = false; 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://backup1.beammp.com/builds/launcher?version=true"); + HTTP = HTTP_REQUEST(link,443); + fallback = true; + 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"); + if(fallback){ + link = Sec("https://backup1.beammp.com/builds/launcher?download=true"); + }else link = Sec("https://beammp.com/builds/launcher?download=true"); struct stat buffer{}; std::string Back = Sec("BeamMP-Launcher.back"); @@ -169,27 +188,35 @@ void PreGame(int argc, char* argv[],const std::string& 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"); + bool fallback = false; int i; if(!fs::exists(DUI)){ info(Sec("Downloading default ui data...")); i = Download(link,DUI,true); if(i != -1){ + fallback = true; 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); + link = Sec("https://backup1.beammp.com/client-ui-data"); + i = Download(link,DUI,true); + if(i != -1) { + 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"); + if(fallback)link = Sec("https://backup1.beammp.com/client-settings-data"); + else 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(); + if(fallback)link = Sec("https://backup1.beammp.com/builds/client?did=") + GetDID(); + else link = Sec("https://beammp.com/builds/client?did=") + GetDID(); Download(link, Sec(R"(BeamNG\mods\BeamMP.zip)"), false); info(Sec("Download Complete!")); }