This commit is contained in:
BugisoftRSG 2023-08-09 12:43:03 +02:00
commit 466edec3a3
No known key found for this signature in database
GPG Key ID: 709B5D5A25866561
89 changed files with 3601 additions and 0 deletions

63
.gitattributes vendored Normal file
View File

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

26
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: Build Test
on:
push:
branches:
- master
jobs:
build:
name: Build on Windows and Linux
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest]
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Configure and Build
run: |
mkdir build
cd build
cmake ..
cmake --build .

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
# IDE
.vs/
.vscode/*
!.vscode/launch.json
.cache/
# output directory
build/
out/
__pycache__/
# precompiled headers
*.ipch
*.gch
*.pch

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

48
CMakeLists.txt Normal file
View File

@ -0,0 +1,48 @@
cmake_minimum_required(VERSION 3.20)
project(SCAPI CXX ASM_MASM)
set(SRC_DIR "${PROJECT_SOURCE_DIR}/src")
# Fetch modules
message("\nFetching modules")
include(scripts/pugixml.cmake)
include(scripts/cpr.cmake)
include(scripts/json.cmake)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/scripts)
find_package(botan 2.19.3 REQUIRED)
botan_generate(botan sha1 hmac rc4 rng base64 mac stream hash auto_rng win32_stats)
# SCAPI
message(STATUS "SCAPI")
file(GLOB_RECURSE SRC_MAIN
"${SRC_DIR}/**.hpp"
"${SRC_DIR}/**.h"
"${SRC_DIR}/**.cpp"
"${SRC_DIR}/**.cc"
"${SRC_DIR}/**.cxx"
"${SRC_DIR}/**.asm"
)
add_executable(SCAPI "${SRC_MAIN}")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(TARGET SCAPI PROPERTY CXX_STANDARD 23) # 23 Because std::format is not avalible in std:c++20 for some reason. Maybe it's because i use v142 toolset.
source_group(TREE ${SRC_DIR} PREFIX "src" FILES ${SRC_MAIN} )
target_include_directories(SCAPI PRIVATE
"${SRC_DIR}"
"${json_SOURCE_DIR}/single_include"
)
target_link_libraries(SCAPI PRIVATE botan pugixml cpr json)
# Warnings as errors
set_property(TARGET SCAPI PROPERTY COMPILE_WARNING_AS_ERROR ON)
add_compile_definitions(SCAPI
"_CRT_SECURE_NO_WARNINGS"
"NOMINMAX"
"WIN32_LEAN_AND_MEAN"
)

15
CMakeSettings.json Normal file
View File

@ -0,0 +1,15 @@
{
"configurations": [
{
"name": "x64-Release",
"generator": "Ninja",
"configurationType": "RelWithDebInfo",
"inheritEnvironments": [ "msvc_x64_x64" ],
"buildRoot": "${projectDir}\\out\\build\\${name}",
"installRoot": "${projectDir}\\out\\install\\${name}",
"cmakeCommandArgs": "",
"buildCommandArgs": "",
"ctestCommandArgs": ""
}
]
}

53
README.md Normal file
View File

@ -0,0 +1,53 @@
# SCAPI
This project is designed to better understand the API's from Rockstar Games used in Grand Theft Auto V.
## Features
### UGC
- Copy Job (From other/same platforms to PC, but not vice versa)
- Copy Local Job (Copy your own jobs)
- Delete Content (Can delete any job you created)
- Query Content (Get the job meta info of a job)
- Check Text (Checks if a given text is a profanity)
- Query Content Creators (Actual usage unknown)
### Auth
- Create Ticket
### Geo Location
- Get Location Info from IP (Looks like its Max Mind DB)
### Matchmaking
- Get Matchmaking (Lists all Sessions available to join)
### Inbox
- Send Email (May also corrupt the target's inbox if base64'd gamer handle is wrong)
- Send Bounty completed Message
### Presence
- Send Invite (IIRC only works on friends since the ballstortue incursion)
### Misc
- Decrypt (Allows you to decrypt an http request/response and get the raw xml)
### Libraries
This project was builded on Microsoft Visual Studio Community 2022 (64bit)
Dependencies:
- [Botan](https://github.com/randombit/botan)
- [cpr](https://github.com/libcpr/cpr)
- [pugixml](https://github.com/libcpr/cpr)
- Python for Botan
Build Instructions (Win64)
```bash
git clone https://github.com/BugisoftRSG/SCAPI.git
cd SCAPI
mkdir build && cd build
cmake ..
```
## Known Issues
- GetTopRatedContent returns SqlException

BIN
bfg-1.14.0.jar Normal file

Binary file not shown.

140
scripts/FindBotan.cmake Normal file
View File

@ -0,0 +1,140 @@
## This module will automagically download the tarball of the specified Botan version and invoke the configure.py
## python script to generate the amalgamation files (botan_all.cpp and botan_all.h).
##
## Usage:
## find_package(
## botan 2.18.2
## COMPONENTS
## system_rng
## argon2
## sha3
## REQUIRED
## )
##
## target_link_libraries(
## MyTarget
## PRIVATE
## botan
## )
##
cmake_minimum_required(VERSION 3.19)
include(FetchContent)
# Find python
find_package(
Python
COMPONENTS
Interpreter
REQUIRED
)
# Assemble version string
set(Botan_VERSION_STRING "Botan-2.19.3")
# Assemble download URL
set(DOWNLOAD_URL https://botan.randombit.net/releases/${Botan_VERSION_STRING}.tar.xz)
# Just do a dummy download to see whether we can download the tarball
file(
DOWNLOAD
${DOWNLOAD_URL}
STATUS download_status
)
if (NOT download_status EQUAL 0)
message(FATAL_ERROR "Could not download Botan tarball (status = ${download_status}): ${DOWNLOAD_URL}")
endif()
# Download the tarball
FetchContent_Declare(
botan_upstream
URL ${DOWNLOAD_URL}
)
FetchContent_MakeAvailable(botan_upstream)
# Heavy lifting by cmake
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Botan DEFAULT_MSG Botan_VERSION_STRING)
## Function to generate a target named 'TARGET_NAME' with specific Botan modules enabled.
function(botan_generate TARGET_NAME MODULES)
# The last N arguments are considered to be the modules list.
# Here, we collect those in a list and join them with a comma separator ready to be passed to the configure.py script.
foreach(module_index RANGE 1 ${ARGC}-2)
list(APPEND modules_list ${ARGV${module_index}})
# Check if PKCS11 module is enabled
# Note: This is for a workaround, see further below for more details.
if (ARGV${module_index} STREQUAL "pkcs11")
set(PKCS11_ENABLED ON)
endif()
endforeach()
list(JOIN modules_list "," ENABLE_MODULES_LIST)
# Determine botan compiler ID (--cc parameter of configure.py)
set(BOTAN_COMPILER_ID ${CMAKE_CXX_COMPILER_ID})
string(TOLOWER ${BOTAN_COMPILER_ID} BOTAN_COMPILER_ID)
if (BOTAN_COMPILER_ID STREQUAL "gnu")
set(BOTAN_COMPILER_ID "gcc")
endif()
# Run the configure.py script
add_custom_command(
OUTPUT botan_all.cpp botan_all.h
COMMENT "Generating Botan amalgamation files botan_all.cpp and botan_all.h"
COMMAND ${Python_EXECUTABLE}
${botan_upstream_SOURCE_DIR}/configure.py
--quiet
--cc-bin=${CMAKE_CXX_COMPILER}
--cc=${BOTAN_COMPILER_ID}
$<$<BOOL:${MINGW}>:--os=mingw>
--disable-shared
--amalgamation
--minimized-build
--enable-modules=${ENABLE_MODULES_LIST}
)
# Create target
set(TARGET ${TARGET_NAME})
add_library(${TARGET} STATIC)
target_sources(
${TARGET}
PUBLIC
${CMAKE_CURRENT_BINARY_DIR}/botan_all.h
PRIVATE
${CMAKE_CURRENT_BINARY_DIR}/botan_all.cpp
)
target_include_directories(
${TARGET}
INTERFACE
${CMAKE_CURRENT_BINARY_DIR}
)
set_target_properties(
${TARGET}
PROPERTIES
POSITION_INDEPENDENT_CODE ON
)
#
# PKCS11 Workaround
#
# This section is a workaround to handle a "bug" in upstream Botan.
# Basically, the amalgamation build of Botan does not include the necessary PKCS11 headers when the PKCS11 module
# is enabled.
#
# See:
# - https://github.com/randombit/botan/issues/1447
# - https://github.com/randombit/botan/issues/976
#
if (PKCS11_ENABLED)
file(COPY ${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11/pkcs11.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
file(COPY ${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11/pkcs11f.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
file(COPY ${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11/pkcs11t.h DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(
${TARGET}
PRIVATE
${botan_upstream_SOURCE_DIR}/src/lib/prov/pkcs11
)
endif()
endfunction()

14
scripts/cpr.cmake Normal file
View File

@ -0,0 +1,14 @@
include(FetchContent)
set(BUILD_TESTING_BEFORE ${BUILD_TESTING})
set(CURL_DISABLE_TESTS OFF)
FetchContent_Declare(
cpr
GIT_REPOSITORY https://github.com/libcpr/cpr.git
GIT_TAG 1986262ba4e0cb052161e9e7919aef5ef08217f0
GIT_PROGRESS TRUE
)
message("cpr")
FetchContent_MakeAvailable(cpr)
set(BUILD_TESTING ${BUILD_TESTING_BEFORE} CACHE INTERNAL "" FORCE)

12
scripts/json.cmake Normal file
View File

@ -0,0 +1,12 @@
include(FetchContent)
set(JSON_MultipleHeaders OFF)
FetchContent_Declare(
json
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git
GIT_TAG 67e6070f9d9a44b4dec79ebe6b591f39d2285593
GIT_PROGRESS TRUE
)
message("json")
FetchContent_MakeAvailable(json)

11
scripts/pugixml.cmake Normal file
View File

@ -0,0 +1,11 @@
include(FetchContent)
FetchContent_Declare(
pugixml
GIT_REPOSITORY https://github.com/zeux/pugixml.git
GIT_TAG a0e064336317c9347a91224112af9933598714e9
GIT_PROGRESS TRUE
)
message("pugixml")
FetchContent_MakeAvailable(pugixml)
set_property(TARGET pugixml PROPERTY CXX_STANDARD 23)

17
src/AccountInfo.hpp Normal file
View File

@ -0,0 +1,17 @@
#pragma once
#include <cstdint>
class AccountInfo
{
public:
uint64_t m_rockstar_id;
int m_age;
string m_avatar_url;
string m_country_code;
string m_date_of_birth;
string m_email;
bool m_is_approx_dob;
string m_language_code;
string m_nickname;
string m_last_portal_login_date;
};

118
src/command.cpp Normal file
View File

@ -0,0 +1,118 @@
#include "command.hpp"
#include "ros_crypt.hpp"
#include <cpr/cpr.h>
ROSCrypt* command::m_launcher_ros = nullptr;
ROSCrypt* command::m_ros = nullptr;
command::command(const string& name) : m_name(name)
{
m_launcher_ros = new ROSCrypt(true);
m_ros = new ROSCrypt(false);
g_commands[hash<string>()(name)] = this;
}
command* command::get(int command)
{
return g_commands[command];
}
string command::run_raw(const string url, const string queryString, bool launcher)
{
auto api = launcher ? m_launcher_ros : m_ros;
string absolutePath = url.substr(url.find('/', url.find("://") + 3));
Botan::AutoSeeded_RNG rng;
auto challenge = rng.random_vec(8);
cpr::Response response = cpr::Post(
cpr::Url{ url },
cpr::Header
{
{"ros-SecurityFlags", "239" },
{"ros-SessionTicket", SESSION_TICKET},
{"ros-Challenge", Botan::base64_encode(challenge)},
{"ros-HeadersHmac", Botan::base64_encode(api->HeadersHmac(challenge, "POST", absolutePath, SESSION_KEY, SESSION_TICKET)) },
{"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"},
{"User-Agent", api->GetROSVersionString()},
},
cpr::Body{ queryString });
return response.text;
}
string command::run(const string url, map<string, string> map)
{
auto service_type = this->get_service_type();
if (service_type == PROD_ROS || service_type == PROD_ROS_LAUNCHER)
{
auto api = service_type == SERVICE_TYPE::PROD_ROS_LAUNCHER ? m_launcher_ros : m_ros;
auto params = api->BuildPostString(map);
string queryString = api->EncryptROSData(params, SESSION_KEY);
string response = run_raw(url, queryString, service_type == SERVICE_TYPE::PROD_ROS_LAUNCHER);
if (!response.contains("Internal server error"))
return api->DecryptROSData(response.c_str(), response.size(), SESSION_KEY);
else {
return response;
}
}
else if (service_type == PROD_SCAPI_AMC)
{
cpr::Parameters params;
for (const auto& entry : map) {
params.Add(cpr::Parameter(entry.first, entry.second));
}
cpr::Response response = cpr::Get(
cpr::Url{ url },
cpr::Header
{
{"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"},
{"X-AMC", "true"},
{"X-Requested-With", "XMLHttpRequest"}
},
cpr::Parameters{ params });
cout << response.status_code << endl;
return response.text;
}
return "";
}
string command::run(const string url, string params)
{
string queryString = m_ros->EncryptROSData(params, SESSION_KEY);
string response = run_raw(url, queryString);
if (!response.contains("Internal server error"))
return m_ros->DecryptROSData(response.c_str(), response.size(), SESSION_KEY);
else {
return response;
}
}
string command::run_anonymous(const string& url, map<string, string> map)
{
string queryString = m_ros->EncryptROSData(m_ros->BuildPostString(map));
cpr::Response response = cpr::Post(
cpr::Url{ url },
cpr::Header
{
{"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"},
{"User-Agent", m_ros->GetROSVersionString()}
},
cpr::Body{ queryString });
return m_ros->DecryptROSData(response.text.c_str(), response.text.size(), "");
}

45
src/command.hpp Normal file
View File

@ -0,0 +1,45 @@
#pragma once
#include <string>
#include <unordered_map>
#include <map>
#include <iostream>
#include <pugixml.hpp>
#include "ros_crypt.hpp"
using namespace std;
inline string TICKET;
inline string SESSION_TICKET;
inline string SESSION_KEY;
enum SERVICE_TYPE
{
UNKNOWN,
PROD_ROS,
PROD_ROS_LAUNCHER,
PROD_SCAPI_AMC,
PROD_CLOUD
};
class command
{
protected:
string m_name;
string run_raw(const string url, const string queryString, bool launcher = false);
string run(const string url, map<string, string> map);
string run(const string url, string params);
string run_anonymous(const string& url, map<string, string> map);
public:
command(const string& name);
inline const string& get_name() { return m_name; }
static command* get(int command);
virtual string execute(const vector<string>& args) = 0;
virtual SERVICE_TYPE get_service_type() = 0;
static ROSCrypt* m_launcher_ros;
static ROSCrypt* m_ros;
};
inline unordered_map<int, command*> g_commands;

View File

@ -0,0 +1,25 @@
#include "../../../command.hpp"
#include <iostream>
class AwardAchievement : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the achievementId:" << endl;
string achievementId;
cin >> achievementId;
map<string, string> map;
map["ticket"] = TICKET;
map["achievementId"] = achievementId;
map["achievedOffline"] = "False";
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/AwardAchievement", map);
}
};
AwardAchievement g_award_achievement("awardachievement");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class AwardAchievementProgress : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the achievementId:" << endl;
string achievementId;
cin >> achievementId;
cout << "Specify the achievementProgress:" << endl;
string achievementProgress;
cin >> achievementProgress;
map<string, string> map;
map["ticket"] = TICKET;
map["achievementId"] = achievementId;
map["achievedOffline"] = "False";
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/AwardAchievementProgress", map);
}
};
AwardAchievementProgress g_award_achievement_progress("awardachievementprogress");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <iostream>
class GetAchievementDefinitions : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string firstAchievementId;
cin >> firstAchievementId;
cout << "Specify the maxDefinitions:" << endl;
string maxDefinitions;
cin >> maxDefinitions;
cout << "Specify the locale (ex. en-US):" << endl;
string locale;
cin >> locale;
map<string, string> map;
map["ticket"] = TICKET;
map["firstAchievementId"] = firstAchievementId;
map["maxDefinitions"] = maxDefinitions;
map["locale"] = locale;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/GetAchievementDefinitions", map);
}
};
GetAchievementDefinitions g_get_achievement_definitions("getachievementdefinitions");

View File

@ -0,0 +1,27 @@
#include "../../../command.hpp"
#include <iostream>
class GetPlayerAchievements : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstarId:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["playerRockstarId"] = rockstarId;
map["crossTitleId"] = "11";
map["crossTitleName"] = "gta5";
map["crossTitlePlatformName"] = "pcros";
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/achievements.asmx/GetPlayerAchievements", map);
}
};
GetPlayerAchievements g_get_player_achievements("getplayerachievements");

View File

@ -0,0 +1,30 @@
#include "../../../command.hpp"
class CreateP2PCertificate : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pubKey" << endl;
string pubKey;
cin >> pubKey;
cout << "Specify the sig" << endl;
string sig;
cin >> sig;
map<string, string> map;
map["ticket"] = TICKET;
map["pubKeyCurve"] = "nistP256";
map["pubKey"] = pubKey;
map["hashAlg"] = "SHA256";
map["sig"] = sig;
return run("https://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/auth.asmx/CreateP2PCertificate", map);
}
};
CreateP2PCertificate g_create_p2p_certificate("createp2pcertificate");

View File

@ -0,0 +1,20 @@
#include "../../../command.hpp"
#include <iostream>
class CreateScAuthToken : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/auth.asmx/CreateTicketScAuthToken2", map);
}
};
CreateScAuthToken g_create_sc_auth_token("createscauthtoken");

View File

@ -0,0 +1,195 @@
#include "../../../command.hpp"
#include "pugixml.hpp"
#include <iostream>
#include <filesystem>
#include <fstream>
class CreateTicket : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
inline void request_socialclub_data(unordered_map<string, string>& env_vars)
{
cout << "Specify your SocialClub Email" << endl;
string email;
cin >> email;
cout << "Specify your SocialClub Profile Name" << endl;
string nickname;
cin >> nickname;
cout << "Specify your SocialClub Password" << endl;
string password;
cin >> password;
env_vars["EMAIL"] = email;
env_vars["NICKNAME"] = nickname;
env_vars["PASSWORD"] = password;
env_vars["PLATFORM"] = "pcros";
ofstream outFile(".env");
for (const auto& pair : env_vars) {
outFile << pair.first << "=" << pair.second << "\n";
}
}
inline bool request_ticket(string email, string nickname, string password, string platform, string& _response)
{
map<string, string> map;
map["ticket"] = "";
map["email"] = email;
map["nickname"] = nickname;
map["password"] = password;
map["platformName"] = platform;
string response = run_anonymous("https://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/auth.asmx/CreateTicketSc3", map);
pugi::xml_document doc;
if (!doc.load_string(response.c_str())) return false;
bool successfully = false;
ofstream outFile("data.bin");
pugi::xml_node xml_response = doc.child("Response");
for (pugi::xml_node panel = xml_response.first_child(); panel; panel = panel.next_sibling())
{
if (strcmp(panel.name(), "Ticket") == 0)
{
TICKET = panel.text().get();
cout << "Ticket: " << TICKET << endl;
outFile << "TICKET" << "=" << TICKET << "\n";
successfully = true;
}
else if (strcmp(panel.name(), "SessionKey") == 0)
{
SESSION_KEY = panel.text().get();
cout << "Session Key: " << SESSION_KEY << endl;
outFile << "SESSION_KEY" << "=" << SESSION_KEY << "\n";
}
else if (strcmp(panel.name(), "SessionTicket") == 0)
{
SESSION_TICKET = panel.text().get();
cout << "Session Ticket: " << SESSION_TICKET << endl;
outFile << "SESSION_TICKET" << "=" << SESSION_TICKET << "\n";
}
}
_response = response;
return successfully;
}
virtual string execute(const vector<string>& args)
{
unordered_map<string, string> env_vars;
ifstream infile("data.bin");
bool skip;
if (filesystem::exists("data.bin"))
{
string line;
while (getline(infile, line)) {
size_t equal_pos = line.find('=');
if (equal_pos != string::npos) {
string key = line.substr(0, equal_pos);
string value = line.substr(equal_pos + 1);
if (key == "TICKET")
TICKET = value;
else if (key == "SESSION_KEY")
SESSION_KEY = value;
else if (key == "SESSION_TICKET")
SESSION_TICKET = value;
}
}
string data = command::get(hash<string>()("getaccountinfo"))->execute({});
if (data.empty() || data.contains("Internal Server Error") || data.contains("AuthenticationFailed"))
{
cout << "Auth -> Cached session is no longer valid... recreating now." << endl;
if (filesystem::exists("data.bin"))
{
cout << ".env found at " << filesystem::absolute(".env") << endl;
ifstream infile(".env");
string line;
while (getline(infile, line)) {
size_t equal_pos = line.find('=');
if (equal_pos != string::npos) {
string key = line.substr(0, equal_pos);
string value = line.substr(equal_pos + 1);
env_vars[key] = value;
}
}
infile.close();
bool success;
string response;
do {
success = request_ticket(env_vars.at("EMAIL"), env_vars.at("NICKNAME"), env_vars.at("PASSWORD"), env_vars.at("PLATFORM"), response);
if (!success)
{
cout << "Auth -> Invalid credentials or rate limited" << endl;
request_socialclub_data(env_vars);
}
} while (!success);
return response;
}
}
else if (data.contains("Error Code"))
{
cout << "Auth -> Received Error: " << data << endl;
bool success;
string response;
do {
request_socialclub_data(env_vars);
success = request_ticket(env_vars.at("EMAIL"), env_vars.at("NICKNAME"), env_vars.at("PASSWORD"), env_vars.at("PLATFORM"), response);
if (!success)
{
cout << "Auth -> Invalid credentials or rate limited" << endl;
}
} while (!success);
return response;
}
else
{
return "Auth -> Using cached session";
}
}
else if (!filesystem::exists(".env") || !filesystem::exists("data.bin"))
{
request_socialclub_data(env_vars);
bool success;
string response;
do {
success = request_ticket(env_vars.at("EMAIL"), env_vars.at("NICKNAME"), env_vars.at("PASSWORD"), env_vars.at("PLATFORM"), response);
if (!success)
{
cout << "Auth -> Invalid credentials or rate limited" << endl;
request_socialclub_data(env_vars);
}
} while (!success);
return response;
}
return "error";
}
};
CreateTicket g_create_ticket("createticket");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class Disband : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Disband", map);
}
};
Disband g_disband("disbandcrew");

View File

@ -0,0 +1,49 @@
#include "../../../command.hpp"
#include <iostream>
class GetAll : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
cout << "Specify if isSystemClan (0 = no/1 = yes, -1 = any):" << endl;
string isSystemClan;
cin >> isSystemClan;
cout << "Specify if isOpenClan (0 = no/1 = yes, -1 = any):" << endl;
string isOpenClan;
cin >> isOpenClan;
cout << "Specify the search (Can be 0):" << endl;
string search;
cin >> search;
cout << "Specify the sortMode (Can be 0, other values unknown yet):" << endl;
string sortMode;
cin >> sortMode;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
map["isSystemClan"] = isSystemClan;
map["isOpenClan"] = isOpenClan;
map["search"] = search;
map["sortMode"] = sortMode;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetAll", map);
}
};
GetAll g_get_all("getallcrews");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class GetDesc : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetDesc", map);
}
};
GetDesc g_get_desc("getcrewdesc");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class GetDescs : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanIdsCsv (ex.: 12345,56789):" << endl;
string clanIdsCsv;
cin >> clanIdsCsv;
map<string, string> map;
map["ticket"] = TICKET;
map["clanIdsCsv"] = clanIdsCsv;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetDescs", map);
}
};
GetDescs g_get_descs("getcrewdescs");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetFeudStats : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the since ((lastday, lastweek, last2weeks, lastmonth, last3months, last6months, alltime) / 0):" << endl;
string since;
cin >> since;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["since"] = since;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetFeudStats", map); // TODO Internal Server Error (no longer in use?)
}
};
GetFeudStats g_get_feud_stats("getfeudstats");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetInvites : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetInvites", map);
}
};
GetInvites g_get_invites("getcrewinvites");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class GetLeadersForClans : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanIdsCsv (ex.: 123456,789801):" << endl;
string clanIdsCsv;
cin >> clanIdsCsv;
map<string, string> map;
map["ticket"] = TICKET;
map["clanIdsCsv"] = clanIdsCsv;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetLeadersForClans", map);
}
};
GetLeadersForClans g_get_leaders_for_clans("getleadersforclans");

View File

@ -0,0 +1,39 @@
#include "../../../command.hpp"
#include <iostream>
class GetCrewMembers : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the clanName:" << endl;
string clanName;
cin >> clanName;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
map["clanId"] = clanId;
map["clanName"] = clanName;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMembers", map);
}
};
GetCrewMembers g_get_crew_members("getcrewmembers");

View File

@ -0,0 +1,39 @@
#include "../../../command.hpp"
#include <iostream>
class GetCrewMembersTitleOnly : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the clanName:" << endl;
string clanName;
cin >> clanName;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
map["clanId"] = clanId;
map["clanName"] = clanName;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMembersTitleOnly", map);
}
};
GetCrewMembersTitleOnly g_get_crew_members_title_only("getcrewmemberstitleonly");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <iostream>
class GetMetadataForClan : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMetadataForClan", map);
}
};
GetMetadataForClan g_get_metadata_for_clan("getcrewmetadata");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetMine : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetMine", map);
}
};
GetMine g_get_mine("getmycrew");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class GetPrimaryClans : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the gamerHandlesCsv (ex.: 123456,789900):" << endl;
string gamerHandlesCsv;
cin >> gamerHandlesCsv;
map<string, string> map;
map["ticket"] = TICKET;
map["gamerHandlesCsv"] = gamerHandlesCsv;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetPrimaryClans", map); // Exception, no further info
}
};
GetPrimaryClans g_get_primary_clans("getprimaryclans");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <iostream>
class GetRanks : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetRanks", map);
}
};
GetRanks g_get_ranks("getcrewranks");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetSentInvites : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetSentInvites", map);
}
};
GetSentInvites g_get_sent_invites("getsentcrewinvites");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetTopRivals : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the since ((lastday, lastweek, last2weeks, lastmonth, last3months, last6months, alltime) / 0):" << endl;
string since;
cin >> since;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["since"] = since;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetTopRivals1", map); // Internal Error, no longer used?
}
};
GetTopRivals g_get_top_rivals("gettoprivals");

View File

@ -0,0 +1,35 @@
#include "../../../command.hpp"
#include <iostream>
class GetWallMessages : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the pageIndex:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the pageSize:" << endl;
string pageSize;
cin >> pageSize;
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/GetWallMessages", map); // Internal Server Error, great
}
};
GetWallMessages g_get_wall_messages("getwallmessages");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class JoinCrew : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Join", map);
}
};
JoinCrew g_join_crew("joincrew");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class Kick : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the targetGamerHandle:" << endl;
string targetGamerHandle;
cin >> targetGamerHandle;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["targetGamerHandle"] = targetGamerHandle;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Kick", map);
}
};
Kick g_kick("kickfromcrew");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class Leave : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/Leave", map);
}
};
Leave g_leave("leavecrew");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <iostream>
class MemberSetRankByRankOrder : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the targetGamerHandle:" << endl;
string targetGamerHandle;
cin >> targetGamerHandle;
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the rankOrder:" << endl;
string rankOrder;
cin >> rankOrder;
map<string, string> map;
map["ticket"] = TICKET;
map["targetGamerHandle"] = targetGamerHandle;
map["clanId"] = clanId;
map["rankOrder"] = rankOrder;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/MemberSetRankByRankOrder", map); // Title or Environment not supported
}
};
MemberSetRankByRankOrder g_member_set_rank_by_rank_order("membersetrankbyrankorder");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <iostream>
class MemberUpdateRankId : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the targetGamerHandle:" << endl;
string targetGamerHandle;
cin >> targetGamerHandle;
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify if promote (true/false):" << endl;
string promote;
cin >> promote;
map<string, string> map;
map["ticket"] = TICKET;
map["targetGamerHandle"] = targetGamerHandle;
map["clanId"] = clanId;
map["promote"] = promote;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/MemberUpdateRankId", map); // Invalid Argument for some reason
}
};
MemberUpdateRankId g_member_update_rank_id("memberupdaterankid");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <iostream>
class RankCreate : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the rankName (0-4):" << endl; //?
string rankName;
cin >> rankName;
cout << "Specify the initialSystemFlags:" << endl;
string initialSystemFlags;
cin >> initialSystemFlags;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["rankName"] = rankName;
map["initialSystemFlags"] = initialSystemFlags;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/RankCreate", map); // Error: OutOfRange -> ClanRankLength
}
};
RankCreate g_rank_create("createcrewrank");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class RankDelete : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the rankId:" << endl;
string rankId;
cin >> rankId;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["rankId"] = rankId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/RankDelete", map);
}
};
RankDelete g_rank_delete("deletecrewrank");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class SetPrimaryClan : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/SetPrimaryClan", map);
}
};
SetPrimaryClan g_set_primary_clan("setprimaryclan");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class WriteWallMessage : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the clanId:" << endl;
string clanId;
cin >> clanId;
cout << "Specify the message:" << endl;
string message;
cin >> message;
map<string, string> map;
map["ticket"] = TICKET;
map["clanId"] = clanId;
map["message"] = message;
return run("http://crews-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Clans.asmx/WriteWallMessage", map); // Internal Server Error, no longer in use?
}
};
WriteWallMessage write_wall_message("writecrewwallmessage");

View File

@ -0,0 +1,23 @@
#include "../../command.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
#include "../../ros_crypt.hpp"
class Decrypt : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
ifstream infile(R"(C:\Users\Bugisoft\Downloads\GTA_Reverse\request_content.txt)", ios_base::binary);
vector<char> bytes((istreambuf_iterator<char>(infile)), (istreambuf_iterator<char>()));
return m_ros->DecryptROSData(&bytes[0], bytes.size(), SESSION_KEY);
}
};
Decrypt g_decrypt("decrypt");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class AcceptFriendRequest : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstarId:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/AcceptInvite", map); // Missleading name, friend request not session invite
}
};
AcceptFriendRequest g_accept_friend_request("acceptfriendrequest");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class InviteByNickname : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the nickname:" << endl;
string nickname;
cin >> nickname;
map<string, string> map;
map["ticket"] = TICKET;
map["nickName"] = nickname;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/InviteByNickname", map); // This name is missleading since you doesnt actually "invite" a friend instead send a friend request
}
};
InviteByNickname g_invite_by_nickname("addfriendbyname");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class InviteByRockstarId : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstar id:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/InviteByRockstarId", map); // This name is missleading since you doesnt actually "invite" a friend instead send a friend request
}
};
InviteByRockstarId g_invite_by_rockstarid("addfriendbyrid");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class BlockCommunications : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstarId:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/Block", map); // Missleading name, dont have to be a friend
}
};
BlockCommunications g_block_communications("blockcoms");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class CancelFriendRequest : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstar id:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/CancelInvite", map);
}
};
CancelFriendRequest g_cancel_invite("cancelfriendrequest");

View File

@ -0,0 +1,27 @@
#include "../../../command.hpp"
#include <iostream>
class CountAll : command
{
using command::command;
/*
* Response:
* b -> ?
* f -> Friend Count
* ir -> Friend Requests Received (See: getfriendrequestssent)
* is -> Friend Requests Sent (See:
*/
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/CountAll", map);
}
};
CountAll g_count_all_friends("countallfriends");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class DeclineFriendRequest : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstarId:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/DeclineInvite", map); // Missleading name, friend request not session invite
}
};
DeclineFriendRequest g_decline_friend_request("declinefriendrequest");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetBlocked : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the page index:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the page size:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetBlocked", map); // Missleading name, not blocked friends just overall blocked players
}
};
GetBlocked g_get_blocked("getblocked");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetFriendRequestsReceived : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the page index:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the page size:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetInvitesReceived", map); // Again missleading name
}
};
GetFriendRequestsReceived g_get_friend_requests_received("getfriendrequestsreceived");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetFriendRequestsSent : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the page index:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the page size:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetInvitesSent", map); // Again missleading name
}
};
GetFriendRequestsSent g_get_friend_requests("getfriendrequestssent");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class GetFriends : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the page index:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the page size:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetFriends", map);
}
};
GetFriends g_get_friends("getfriends");

View File

@ -0,0 +1,31 @@
#include "../../../command.hpp"
#include <iostream>
// Basically this just also includes the crew name and id
class GetFriendsAndRequestsSent : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the page index:" << endl;
string pageIndex;
cin >> pageIndex;
cout << "Specify the page size:" << endl;
string pageSize;
cin >> pageSize;
map<string, string> map;
map["ticket"] = TICKET;
map["pageIndex"] = pageIndex;
map["pageSize"] = pageSize;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/GetFriendsAndInvitesSent", map); // missleading name
}
};
GetFriendsAndRequestsSent g_get_friends_and_requests_sent("getfriendsandrequestssent");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class RemoveFriend : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstar id:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/RemoveFriend", map);
}
};
RemoveFriend g_remove_friend("removefriend");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <iostream>
class UnblockCommunications : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the rockstarId:" << endl;
string rockstarId;
cin >> rockstarId;
map<string, string> map;
map["ticket"] = TICKET;
map["rockstarId"] = rockstarId;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Friends.asmx/Unblock", map); // Missleading name, dont have to be a friend
}
};
UnblockCommunications g_unblock_communications("unblockcoms");

View File

@ -0,0 +1,23 @@
#include "../../../command.hpp"
class GetLocationInfoFromIP : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the ip:" << endl;
string target_rid;
cin >> target_rid;
map<string, string> map;
map["ticket"] = TICKET;
map["ipAddrStr"] = target_rid;
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/GeoLocation.asmx/GetLocationInfoFromIP", map);
}
};
GetLocationInfoFromIP g_get_location_info_from_ip("getlocationinfofromip");

View File

@ -0,0 +1,25 @@
#include "../../../command.hpp"
#include <iostream>
class GetRelayServers : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the ipAddrStr:" << endl;
string ipAddrStr;
cin >> ipAddrStr;
map<string, string> map;
map["ticket"] = TICKET;
map["ipAddrStr"] = ipAddrStr;
map["secure"] = "false";
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/GeoLocation.asmx/GetRelayServers", map);
}
};
GetRelayServers g_get_relay_servers("getrelayservers");

View File

@ -0,0 +1,31 @@
#include "../../../command.hpp"
#include <format>
#include <iostream>
class SendAwardMsg : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the target rid:" << endl;
string target_rid;
cin >> target_rid;
cout << "Specify the sender name:" << endl;
string senderGamerTag;
cin >> senderGamerTag;
map<string, string> map;
map["ticket"] = TICKET;
map["recipientsCsv"] = target_rid;
map["message"] = format(R"("ros.publish":{{"channel":"friends","msg":{{"gm.evt":{{"e":"StatUpdate","d":{{"stat":1488317176,"from":"{}","ival":100}}}}}}}})", senderGamerTag);
map["ttlSeconds"] = "0";
return run("http://prs-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Presence.asmx/MultiPostMessage", map);
}
};
SendAwardMsg g_send_award_msg("sendawardmessage");

View File

@ -0,0 +1,47 @@
#include "../../../command.hpp"
#include <format>
class BountyCompletedMsg : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the target rid:" << endl;
string target_rid;
cin >> target_rid;
cout << "Specify the tl31FromGamerTag:" << endl;
string tl31FromGamerTag;
cin >> tl31FromGamerTag;
cout << "Specify the tl31TargetGamerTag:" << endl;
string tl31TargetGamerTag;
cin >> tl31TargetGamerTag;
cout << "Specify the iOutcome:" << endl;
string iOutcome;
cin >> iOutcome;
cout << "Specify the iCash:" << endl;
string iCash;
cin >> iCash;
cout << "Specify the iRank:" << endl;
string iRank;
cin >> iRank;
map<string, string> map;
map["ticket"] = TICKET;
map["userIds"] = target_rid;
map["message"] = format(R"({{"gm.evt":{{"e":"bounty","d":{{"Ft":"{}","Tt":"{}","o":{},"c":{},"r":{},"t":1690670145566}}}}}})", tl31FromGamerTag, tl31TargetGamerTag, iOutcome, iCash, iRank);
map["tagsCsv"] = "gta5";
map["ttlSeconds"] = "1800";
return run("http://inbox-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Inbox.asmx/PostMessageToRecipients", map);
}
};
BountyCompletedMsg g_send_bounty_completed_msg("sendbountycompletedmsg");

View File

@ -0,0 +1,76 @@
#include "../../../command.hpp"
#include <format>
class SendEmail : command
{
using command::command;
class rlGamerHandle
{
public:
uint64_t m_rockstar_id; //0x0000
uint8_t m_platform = 3; //0x0008
uint8_t unk_0009; //0x0009
}; //Size: 0x0010
static_assert(sizeof(rlGamerHandle) == 0x10);
string rlGamerHandleToBase64(const rlGamerHandle& handle)
{
const char* base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
vector<uint8_t> bytes(sizeof(rlGamerHandle));
memcpy(bytes.data(), &handle, sizeof(rlGamerHandle));
string result;
size_t paddingCount = (3 - bytes.size() % 3) % 3;
for (size_t i = 0; i < bytes.size(); i += 3)
{
uint32_t value = (bytes[i] << 16) | ((i + 1 < bytes.size() ? bytes[i + 1] : 0) << 8) | ((i + 2 < bytes.size() ? bytes[i + 2] : 0));
result += base64Chars[(value >> 18) & 0x3F];
result += base64Chars[(value >> 12) & 0x3F];
result += (i + 1 < bytes.size() || paddingCount < 2) ? base64Chars[(value >> 6) & 0x3F] : '=';
result += (i + 2 < bytes.size() || paddingCount < 1) ? base64Chars[value & 0x3F] : '=';
}
return result;
}
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the sender rid:" << endl;
string sender_rid;
cin >> sender_rid;
cout << "Specify the target rid:" << endl;
string target_rid;
cin >> target_rid;
cin.ignore(1000000, '\n');
cout << "Specify the subject:" << endl;
string subject;
getline(cin, subject);
cin.ignore(1000000, '\n');
cout << "Specify the content:" << endl;
string content;
getline(cin, content);
rlGamerHandle handle = rlGamerHandle(stoull(sender_rid));
map<string, string> map;
map["ticket"] = TICKET;
map["userIds"] = target_rid;
map["message"] = format(R"({{"email":{{"gh":"{}","sb":"{}","cn":"{}"}}}})", rlGamerHandleToBase64(handle), subject, content);
map["tagsCsv"] = "gta5email"; // gta5marketing
map["ttlSeconds"] = "2592000"; // 1800
return run("http://inbox-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Inbox.asmx/PostMessageToRecipients", map);
}
};
SendEmail g_send_email("sendemail");

View File

@ -0,0 +1,24 @@
#include "../../../command.hpp"
#include <format>
class Matchmaking : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
map["availableSlots"] = "1";
map["filterName"] = "Group";
// filterParamsJson={"GAME_MODE":0,"MMATTR_REGION":0}
map["filterParamsJson"] = R"({"GAME_MODE":0,"MMATTR_MM_GROUP_2":30,"MMATTR_REGION":3})";
map["maxResults"] = "999999";
return run("http://mm-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/matchmaking.asmx/Find", map);
}
};
Matchmaking g_matchmaking("matchmaking");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <format>
#include <iostream>
class QueryWithMaxRecordLength : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the target rid:" << endl;
string target_rid;
cin >> target_rid;
map<string, string> map;
map["ticket"] = TICKET;
map["queryName"] = "SessionByGamerHandle";
map["paramNameValueCsv"] = format(R"(@ghandle,"SC+{}")", target_rid);
map["offset"] = "0";
map["count"] = "20";
map["maxQueryBufferSize"] = "7680";
return run("http://prs-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Presence.asmx/QueryWithMaxRecordLength", map);
}
};
QueryWithMaxRecordLength query_with_max_record_length("querywithmaxrecordlength");

View File

@ -0,0 +1,35 @@
#include "../../../command.hpp"
#include <format>
class SendInvite : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the sender rid:" << endl;
string sender_rid;
cin >> sender_rid;
cout << "Specify the sender name:" << endl;
string sender_name;
cin >> sender_name;
cout << "Specify the target rid:" << endl;
string target_rid;
cin >> target_rid;
cout << "Specify the session info:" << endl;
string session_info;
cin >> session_info;
map<string, string> map;
map["ticket"] = TICKET;
map["recipientsCsv"] = "SC+" + target_rid;
map["message"] = format(R"("ros.mp.invite":{{"h":"SC+{}","n":"{}","s":"{}"}})", sender_rid, sender_name, session_info);
map["ttlSeconds"] = "0";
return run("http://prs-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/Presence.asmx/MultiPostMessage", map);
}
};
SendInvite g_send_invite("sendinvite");

View File

@ -0,0 +1,23 @@
#include "../../../command.hpp"
#include <iostream>
//#include <fstream>
class ReadGameConfig : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
//ofstream of("readgameconfig.txt");
//of << run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ProfileStatGroups.asmx/ReadGameConfig", map);
return run("http://gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ProfileStatGroups.asmx/ReadGameConfig", map); // Response text is too large for console
}
};
ReadGameConfig g_read_game_config("readgameconfig");

View File

@ -0,0 +1,19 @@
#include "../../../command.hpp"
#include <format>
class ReadAllStats : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
return run("https://ps-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/ReadAllStats", map); // loads infinite?
}
};
ReadAllStats g_read_all_stats("readallstats");

View File

@ -0,0 +1,55 @@
#include "../../../command.hpp"
#include <format>
class CreateAccountSc : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the country code" << endl;
string countryCode;
cin >> countryCode;
cout << "Specify the date of bearth (dd/mm/yyyy)" << endl;
string dob;
cin >> dob;
cout << "Specify the email" << endl;
string email;
cin >> email;
cout << "Specify the language code" << endl;
string languageCode;
cin >> languageCode;
cout << "Specify the nickname" << endl;
string nickname;
cin >> nickname;
cout << "Specify the password" << endl;
string password;
cin >> password;
map<string, string> map;
map["acceptNewsletter"] = "false";
map["avatarUrl"] = "https://prod-avatars.akamaized.net/stock-avatars/n/GTAO/CASINO_2.png";
map["countryCode"] = countryCode;
map["dob"] = dob;
map["email"] = email;
map["isApproxDob"] = "False";
map["languageCode"] = languageCode;
map["nickname"] = nickname;
map["password"] = password;
map["phone"] = "";
map["platform"] = "pcros";
map["zipCode"] = "1379800";
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/CreateAccountSc", map);
}
};
CreateAccountSc g_create_account_sc("createaccountsc");

View File

@ -0,0 +1,19 @@
#include "../../../command.hpp"
#include <format>
class GetAccountInfo : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/GetAccountInfo", map);
}
};
GetAccountInfo g_get_account_info("getaccountinfo");

View File

@ -0,0 +1,19 @@
#include "../../../command.hpp"
#include <format>
class GetScAuthToken : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/GetScAuthToken", map);
}
};
GetScAuthToken g_get_sc_auth_token("getscauthtoken");

View File

@ -0,0 +1,34 @@
#include "../../../command.hpp"
#include <format>
class LinkAccount2 : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the email:" << endl;
string email;
cin >> email;
cout << "Specify the nickname:" << endl;
string nickname;
cin >> nickname;
cout << "Specify the password:" << endl;
string password;
cin >> password;
map<string, string> map;
map["ticket"] = TICKET;
map["email"] = email;
map["nickname"] = nickname;
map["password"] = password;
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/LinkAccount2", map);
}
};
LinkAccount2 g_link_account_2("linkaccount2");

View File

@ -0,0 +1,62 @@
#include "../../../command.hpp"
#include <format>
#include "AccountInfo.hpp"
class UpdateAccount : command
{
using command::command;
inline AccountInfo GetAccountInfo()
{
string data = command::get(hash<string>()("getaccountinfo"))->execute({});
pugi::xml_document doc;
AccountInfo accountInfo{};
if (doc.load_string(data.c_str()))
{
auto path = doc.select_node("//Response/RockstarAccount");
auto node = path.node();
accountInfo.m_rockstar_id = node.child("RockstarId").text().as_uint();
accountInfo.m_age = node.child("Age").text().as_int();
accountInfo.m_avatar_url = node.child("AvatarUrl").text().as_string();
accountInfo.m_country_code = node.child("CountryCode").text().as_string();
accountInfo.m_date_of_birth = node.child("Dob").text().as_string();
accountInfo.m_email = node.child("Email").text().as_string();
accountInfo.m_is_approx_dob = node.child("IsApproxDob").text().as_bool(); // TODO
accountInfo.m_language_code = node.child("LanguageCode").text().as_string();
accountInfo.m_nickname = node.child("Nickname").text().as_string();
accountInfo.m_last_portal_login_date = node.child("LastPortalLoginDate").text().as_string();
}
return accountInfo;
}
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
AccountInfo accountInfo = GetAccountInfo();
cout << "Specify the email:" << endl;
string email;
cin >> email;
map<string, string> map;
map["ticket"] = TICKET;
map["avatarUrl"] = "null"; // if this invalid, it will be skipped, you can't just put a .jpg or .png there
map["countryCode"] = accountInfo.m_country_code;
map["dob"] = accountInfo.m_date_of_birth;
map["email"] = email;
map["isApproxDob"] = accountInfo.m_is_approx_dob ? "True" : "False";
map["languageCode"] = accountInfo.m_language_code;
map["nickname"] = accountInfo.m_nickname;
map["phone"] = "";
map["zipCode"] = "";
return run("http://prod.ros.rockstargames.com/gta5/11/gameservices/socialclub.asmx/UpdateAccount", map);
}
};
UpdateAccount g_update_account("updateaccount");

View File

@ -0,0 +1,29 @@
#include "../../../command.hpp"
#include <iostream>
class CheckText : command
{
// Tested from UGC Creator -> Job Title
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the text to check:" << endl;
string text;
cin >> text;
map<string, string> map;
map["ticket"] = TICKET;
map["languageCode"] = ""; // Can be empty
map["contentName"] = ""; // Can be empty
map["description"] = text; // Text to check
map["tagCsv"] = ""; // Can be empty
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/CheckText", map);
}
};
CheckText g_check_text("checktext");

View File

@ -0,0 +1,189 @@
#include "../../../command.hpp"
#include <nlohmann/json.hpp>
#include "../../../ros_crypt.hpp"
#include <cpr/cpr.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iostream>
class CopyJob : command
{
using command::command;
inline bool GetJobDetails(string_view content_id, string& title, string& description, string& type, vector<string>& tags, string& image)
{
cpr::Response response = cpr::Get(
cpr::Url{ "https://scapi.rockstargames.com/ugc/mission/details" },
cpr::Header{ {"X-AMC", "true" }, { "X-Requested-With", "XMLHttpRequest"} },
cpr::Parameters{ {"title", "gtav"}, {"contentId", content_id.data()} });
nlohmann::json job_details = nlohmann::json::parse(string{ response.text });
if (job_details["content"].is_object())
{
nlohmann::json content = job_details["content"];
title = content["name"];
description = content["desc"];
type = content["type"];
tags = content["userTags"];
image = content["imgSrc"];
return true;
}
return false;
}
inline bool GetJobMetaData(string_view content_id, string& result)
{
string data = command::get(hash<string>()("querycontent"))->execute({ "GetLatestVersionByContentId", content_id.data() });
pugi::xml_document doc;
int f0 = 0, f1 = 0;
string lang;
if (doc.load_string(data.c_str()))
{
auto path = doc.select_node("//Response/Result/r/m");
auto node = path.node();
f1 = node.attribute("f1").as_int();
f0 = node.attribute("f0").as_int();
lang = node.attribute("l").as_string();
}
cpr::Response response = cpr::Get(cpr::Url{ format("https://prod.cloud.rockstargames.com/ugc/gta5mission/{}/{}_{}_{}.json", content_id, f1 < 0 ? 0 : f1, f0 < 0 ? 0 : f0, lang.empty() ? "en" : lang) });
result = response.text;
return response.status_code == 200;
}
vector<unsigned char> HexToBytes(const string& hex) {
vector<unsigned char> bytes;
for (unsigned int i = 0; i < hex.length(); i += 2) {
string byteString = hex.substr(i, 2);
unsigned char byte = (unsigned char)strtol(byteString.c_str(), NULL, 16);
bytes.push_back(byte);
}
return bytes;
}
vector<unsigned char> get_data_len(size_t data_len, bool image) // should be 107684
{
stringstream ss;
ss << hex << data_len;
string data_len_hex = ss.str();
if (data_len_hex.length() % 2 != 0) {
data_len_hex = "0" + data_len_hex;
}
vector<unsigned char> data_len_bytes = HexToBytes(data_len_hex); // should be \x01\xa4\xa4
switch (data_len_bytes.size()) {
case 1:
data_len_bytes.insert(data_len_bytes.begin(), 3, 0);
break;
case 2:
data_len_bytes.insert(data_len_bytes.begin(), 2, 0);
break;
case 3:
data_len_bytes.insert(data_len_bytes.begin(), 1, 0);
break;
default:
break;
}
data_len_bytes.insert(data_len_bytes.end(), 3, 0);
if (image)
data_len_bytes.push_back(2);
else
data_len_bytes.push_back(0);
return data_len_bytes;
}
string replaceAll(string const& original, string const& from, string const& to)
{
string results;
string::const_iterator end = original.end();
string::const_iterator current = original.begin();
string::const_iterator next = search(current, end, from.begin(), from.end());
while (next != end) {
results.append(current, next);
results.append(to);
current = next + from.size();
next = search(current, end, from.begin(), from.end());
}
results.append(current, next);
return results;
}
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the content id:" << endl;
string content_id;
cin >> content_id;
string title, description, type, image;
vector<string> tags;
string metadata;
if (GetJobDetails(content_id, title, description, type, tags, image))
{
if (!GetJobMetaData(content_id, metadata))
{
return "Couldn't download job metadata";
}
}
map<string, string> map;
ofstream of("2_0.jpg", ios::binary);
cpr::Response r = cpr::Download(of, cpr::Url{ image });
ifstream input("2_0.jpg", ios_base::binary);
vector<unsigned char> image_bytes((istreambuf_iterator<char>(input)), (istreambuf_iterator<char>()));
nlohmann::json meta_json = nlohmann::json::parse(metadata);
vector<unsigned char> data_len = get_data_len(meta_json.dump().size(), false);
vector<unsigned char> image_data_len = get_data_len(image_bytes.size(), true);
nlohmann::json datajson;
datajson["meta"] = meta_json["meta"];
datajson["mission"] = meta_json["mission"];
datajson["version"] = 2;
string temp = format("ticket={}&contentType=gta5mission&paramsJson=", m_ros->url_encode(TICKET));
temp += m_ros->ex_url_encode(format(R"({{"ContentName":"{}","DataJson":"{}","Description":"{}","Publish":true,"Language":"{}","TagCsv":"{}"}})", title, replaceAll(datajson.dump(), "\"", "\\\""), description, "en", ""));
temp += "&data=";
for (auto& i : data_len)
{
temp += i;
}
temp += meta_json.dump();
for (auto& i : image_data_len)
{
temp += i;
}
for (auto& i : image_bytes)
{
temp += i;
}
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/CreateContent", temp);
}
};
CopyJob g_copy_job("copyjob");

View File

@ -0,0 +1,21 @@
#include "../../../command.hpp"
#include <iostream>
class CopyLocalContent : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["ticket"] = TICKET;
map["contentType"] = "gta5mission";
map["contentId"] = "Qa2frulcv0u2eHmWg7KSHA"; // TODO
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/CopyContent", map);
}
};
CopyLocalContent g_copy_local_content("copylocalcontent");

View File

@ -0,0 +1,26 @@
#include "../../../command.hpp"
#include <iostream>
class DeleteContent : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the content id:" << endl;
string contentId;
cin >> contentId;
map<string, string> map;
map["ticket"] = TICKET;
map["contentType"] = "gta5mission";
map["contentId"] = contentId;
map["deleted"] = "true";
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/SetDeleted", map);
}
};
DeleteContent g_delete_content("deletecontent");

View File

@ -0,0 +1,110 @@
#include "../../../command.hpp"
#include <iostream>
class QueryContent : command
{
using command::command;
enum QueryType {
GetLatestVersionByContentId = 1,
GetMyBookmarkedContent,
GetMyContent,
GetRecentlyCreatedContent,
GetMyRecentlyPlayedContent,
GetFriendContent,
GetTopRatedContent
};
QueryType getQueryType(const vector<string>& args) {
if (args.empty()) {
cout << "Select one of the following query names:" << endl;
cout << "(1) GetLatestVersionByContentId" << endl;
cout << "(2) GetMyBookmarkedContent" << endl;
cout << "(3) GetMyContent" << endl;
cout << "(4) GetRecentlyCreatedContent" << endl;
cout << "(5) GetMyRecentlyPlayedContent" << endl;
cout << "(6) GetFriendContent" << endl;
cout << "(7) GetTopRatedContent" << endl;
int type;
cin >> type;
return static_cast<QueryType>(type);
}
else {
return static_cast<QueryType>(stoi(args[0]));
}
}
string getQueryName(QueryType type) {
switch (type) {
case GetLatestVersionByContentId:
return "GetLatestVersionByContentId";
case GetMyBookmarkedContent:
return "GetMyBookmarkedContent";
case GetMyContent:
return "GetMyContent";
case GetRecentlyCreatedContent:
return "GetRecentlyCreatedContent";
case GetMyRecentlyPlayedContent:
return "GetMyRecentlyPlayedContent";
case GetFriendContent:
return "GetFriendContent";
case GetTopRatedContent:
return "GetTopRatedContent";
}
return "";
}
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
string contentId;
string queryName;
string count;
map<string, string> params;
params["ticket"] = TICKET;
params["queryName"] = queryName;
QueryType queryType = getQueryType(args);
params["queryName"] = getQueryName(queryType);
if (!args.empty())
contentId = args[1];
else if (queryType == QueryType::GetLatestVersionByContentId)
{
cout << "Specify the contentId:" << endl;
cin >> contentId;
}
switch (queryType) {
case GetLatestVersionByContentId:
params["contentType"] = "gta5mission";
params["queryParams"] = "{contentids:[\"" + contentId + "\"], lang: ['en', 'fr', 'de', 'it', 'es', 'pt', 'pl', 'ru', 'es-mx'] }";
params["offset"] = "0";
params["count"] = "1";
break;
case GetMyBookmarkedContent:
case GetMyContent:
case GetRecentlyCreatedContent:
case GetMyRecentlyPlayedContent:
case GetFriendContent:
case GetTopRatedContent:
cout << "Specify the count:" << endl;
cin >> count;
params["contentType"] = "gta5mission";
params["queryParams"] = "{lang:['de','en','fr','it','es','pt','pl','ru','es-mx']}";
params["offset"] = "0";
params["count"] = count;
break;
}
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/QueryContent", params);
}
};
QueryContent g_query_content("querycontent");

View File

@ -0,0 +1,30 @@
#include "../../../command.hpp"
#include <iostream>
class QueryContentCreators : command
{
// No clue for what this is used and why but GetByUserId seems to be the only queryName
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the content creator RID:" << endl; // TODO support multiple
string contentCreators;
cin >> contentCreators;
map<string, string> map;
map["ticket"] = TICKET;
map["contentType"] = "gta5mission";
map["queryName"] = "GetByUserId";
map["queryParams"] = "{userids:[" + contentCreators + "]}"; // You can input here multiple seperated by a comma
map["offset"] = "0";
map["count"] = "10";
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/QueryContentCreators", map);
}
};
QueryContentCreators g_query_content_creators("querycontentcreators");

View File

@ -0,0 +1,30 @@
#include "../../../command.hpp"
#include <iostream>
class SetBookmarked : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_ROS; }
virtual string execute(const vector<string>& args)
{
cout << "Specify the content id:" << endl;
string contentId;
cin >> contentId;
cout << "Specify if it should be bookmarked (true/false):" << endl;
string bookmarked;
cin >> bookmarked;
map<string, string> map;
map["ticket"] = TICKET;
map["contentType"] = "gta5mission";
map["contentId"] = contentId;
map["bookmarked"] = bookmarked;
return run("http://ugc-gta5-prod.ros.rockstargames.com/gta5/11/gameservices/ugc.asmx/SetBookmarked", map);
}
};
SetBookmarked g_set_bookmarked("setbookmarked");

View File

@ -0,0 +1,21 @@
#include "../../../command.hpp"
#include <iostream>
class SearchMission : command
{
using command::command;
SERVICE_TYPE get_service_type() { return SERVICE_TYPE::PROD_SCAPI_AMC; }
virtual string execute(const vector<string>& args)
{
map<string, string> map;
map["title"] = "gtav";
map["platform"] = "pc";
map["includeCommentCount"] = "false";
return run("https://scapi.rockstargames.com/search/mission", map);
}
};
SearchMission g_search_mission("searchmission");

2
src/common.hpp Normal file
View File

@ -0,0 +1,2 @@
#pragma once
#include "command.hpp"

157
src/main.cpp Normal file
View File

@ -0,0 +1,157 @@
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <format>
#include "command.hpp"
#include <nlohmann/json.hpp>
#include "cpr/cpr.h"
#include <pugixml.hpp>
#include "AccountInfo.hpp"
#include <botan_all.h>
#ifdef _WIN32
#include <Windows.h>
#include <tlhelp32.h>
#endif
using namespace std;
#ifdef _WIN32
uintptr_t GetModuleBaseAddress(DWORD procId, const char* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry;
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!strcmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
#endif
AccountInfo GetAccountInfo()
{
string data = command::get(hash<string>()("getaccountinfo"))->execute({});
pugi::xml_document doc;
AccountInfo accountInfo{};
if (doc.load_string(data.c_str()))
{
auto path = doc.select_node("//Response/RockstarAccount");
auto node = path.node();
accountInfo.m_rockstar_id = node.child("RockstarId").text().as_uint();
accountInfo.m_age = node.child("Age").text().as_int();
accountInfo.m_avatar_url = node.child("AvatarUrl").text().as_string();
accountInfo.m_country_code = node.child("CountryCode").text().as_string();
accountInfo.m_date_of_birth = node.child("Dob").text().as_string();
accountInfo.m_email = node.child("Email").text().as_string();
accountInfo.m_is_approx_dob = node.child("IsApproxDob").text().as_bool(); // TODO
accountInfo.m_language_code = node.child("LanguageCode").text().as_string();
accountInfo.m_nickname = node.child("Nickname").text().as_string();
accountInfo.m_last_portal_login_date = node.child("LastPortalLoginDate").text().as_string();
}
return accountInfo;
}
/*
* <Services Count="12">
<S ep="/Accounts.svc/" h="accounts-prod.ros.rockstargames.com" />
<S ep="/Feed.asmx/" h="feed-gta5-prod.ros.rockstargames.com" />
<S ep="/Telemetry.asmx/SubmitCompressed" h="prod.telemetry.ros.rockstargames.com" />
<S ep="/Telemetry.asmx/SubmitRealTime" h="prod.telemetry.ros.rockstargames.com" />
<S ep="conductor" h="conductor-prod.ros.rockstargames.com" />
<S ep="/ProfileStats.asmx/" h="ps-gta5-prod.ros.rockstargames.com" />
<S ep="/matchmaking.asmx/" h="mm-gta5-prod.ros.rockstargames.com" />
<S ep="/ugc.asmx/" h="ugc-gta5-prod.ros.rockstargames.com" />
<S ep="/Presence.asmx/" h="prs-gta5-prod.ros.rockstargames.com" />
<S ep="/Inbox.asmx/" h="inbox-gta5-prod.ros.rockstargames.com" />
<S ep="/Clans.asmx/" h="crews-gta5-prod.ros.rockstargames.com" />
<S ep="/cloudservices/members//GTA5/saves/mpstats" h="cs-gta5-prod.ros.rockstargames.com" />
</Services>
*/
int main()
{
string endpoint;
#ifdef _WIN64
SetConsoleOutputCP(CP_UTF8);
HWND hwnd = FindWindowA(NULL, "Grand Theft Auto V");
if (hwnd)
{
DWORD pid;
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
uintptr_t base_address = GetModuleBaseAddress(pid, "GTA5.exe");
char ticket[208]{};
ReadProcessMemory(phandle, (void*)(base_address + 0x2E7B300), &ticket, 208, 0);
char session_ticket[88]{};
ReadProcessMemory(phandle, (void*)(base_address + 0x2E7B300 + 0x200), &session_ticket, 88, 0);
unsigned char session_key[16]{};
ReadProcessMemory(phandle, (void*)(base_address + 0x2E7B300 + 0x608), &session_key, 16, 0);
TICKET = ticket;
SESSION_TICKET = string(session_ticket, 88);
SESSION_KEY = Botan::base64_encode(reinterpret_cast<const Botan::byte*>(session_key), sizeof(session_key));
}
#endif
cout << "Help:" << endl;
for (auto& it : g_commands) {
cout << it.second->get_name() << endl;
}
if (!TICKET.empty())
{
cout << "Ticket " << TICKET << endl;
cout << "Session Ticket " << SESSION_TICKET << endl;
cout << "Session Key " << SESSION_KEY << endl;
cout << "Enter the endpoint:" << endl;
cin >> ws >> endpoint;
}
else
{
string response = command::get(hash<string>()("createticket"))->execute({});
if (TICKET.length() > 20)
{
cout << "Ticket " << TICKET << endl;
cout << "Session Ticket " << SESSION_TICKET << endl;
cout << "Session Key " << SESSION_KEY << endl;
}
}
while (true)
{
transform(endpoint.begin(), endpoint.end(), endpoint.begin(), ::tolower);
static command* command = command::get(hash<string>()(endpoint));
if (command) {
cout << command->execute({ }) << endl;
}
cout << "Enter the endpoint:" << endl;
cin >> ws >> endpoint;
command = command::get(hash<string>()(endpoint));
}
}

277
src/ros_crypt.cpp Normal file
View File

@ -0,0 +1,277 @@
#include "ros_crypt.hpp"
#include <sstream>
#include <iomanip>
#include <format>
#include <algorithm>
#include <iostream>
ROSCryptoState::ROSCryptoState(const string& platformKey)
{
Botan::secure_vector<uint8_t> platformStr = Botan::base64_decode(platformKey);
memcpy(m_rc4Key, &platformStr[1], sizeof(m_rc4Key));
memcpy(m_xorKey, &platformStr[33], sizeof(m_xorKey));
memcpy(m_hashKey, &platformStr[49], sizeof(m_hashKey));
m_rc4 = Botan::StreamCipher::create("RC4")->clone();
m_rc4->set_key(m_rc4Key, sizeof(m_rc4Key));
m_rc4->cipher1(m_xorKey, sizeof(m_xorKey));
m_rc4->set_key(m_rc4Key, sizeof(m_rc4Key));
m_rc4->cipher1(m_hashKey, sizeof(m_hashKey));
delete m_rc4;
}
ROSCryptoState::~ROSCryptoState()
{
delete m_rc4;
}
const uint8_t* ROSCryptoState::GetXorKey() const
{
return m_xorKey;
}
const uint8_t* ROSCryptoState::GetHashKey() const
{
return m_hashKey;
}
string ROSCrypt::DecryptROSData(const char* data, size_t size, const string& sessionKey)
{
auto cryptoState = m_cryptoState.get();
uint8_t rc4Key[16];
bool hasSecurity = (!sessionKey.empty());
uint8_t sessKey[16];
if (hasSecurity)
{
auto keyData = Botan::base64_decode(sessionKey.data());
memcpy(sessKey, keyData.data(), sizeof(sessKey));
}
for (int i = 0; i < sizeof(rc4Key); i++)
{
rc4Key[i] = data[i] ^ cryptoState->GetXorKey()[i];
if (hasSecurity)
{
rc4Key[i] ^= sessKey[i];
}
}
Botan::StreamCipher* rc4 = Botan::StreamCipher::create("RC4")->clone();
rc4->set_key(rc4Key, sizeof(rc4Key));
uint8_t blockSizeData[4];
uint8_t blockSizeDataLE[4];
rc4->cipher(reinterpret_cast<const uint8_t*>(&data[16]), blockSizeData, 4);
blockSizeDataLE[3] = blockSizeData[0];
blockSizeDataLE[2] = blockSizeData[1];
blockSizeDataLE[1] = blockSizeData[2];
blockSizeDataLE[0] = blockSizeData[3];
uint32_t blockSize = (*(uint32_t*)&blockSizeDataLE) + 20;
vector<uint8_t> blockData(blockSize);
stringstream result;
size_t start = 20;
while (start < size)
{
int end = min(size, start + blockSize);
end -= 20;
int thisLen = end - start;
if (thisLen < 0)
{
return string{data, size};
}
rc4->cipher(reinterpret_cast<const uint8_t*>(&data[start]), &blockData[0], thisLen);
result << string(reinterpret_cast<const char*>(&blockData[0]), thisLen);
start += blockSize;
}
delete rc4;
return result.str();
}
string ROSCrypt::EncryptROSData(const string& input, const string& sessionKey)
{
auto state = m_cryptoState.get();
stringstream output;
bool hasSecurity = (!sessionKey.empty());
uint8_t sessKey[16];
if (hasSecurity)
{
auto keyData = Botan::base64_decode(sessionKey);
memcpy(sessKey, keyData.data(), sizeof(sessKey));
}
uint8_t rc4Key[16];
Botan::AutoSeeded_RNG rng;
rng.randomize(rc4Key, sizeof(rc4Key));
for (int i = 0; i < sizeof(rc4Key); i++)
{
char thisChar = rc4Key[i] ^ state->GetXorKey()[i];
output << string(&thisChar, 1);
if (hasSecurity)
{
rc4Key[i] ^= sessKey[i];
}
}
Botan::StreamCipher* rc4 = Botan::StreamCipher::create("RC4")->clone();
rc4->set_key(rc4Key, sizeof(rc4Key));
vector<uint8_t> inData(input.size());
memcpy(&inData[0], input.c_str(), inData.size());
rc4->encipher(inData);
output << string(reinterpret_cast<const char*>(&inData[0]), inData.size());
string tempContent = output.str();
Botan::Buffered_Computation* sha1;
if (!hasSecurity)
{
sha1 = Botan::HashFunction::create("SHA1")->clone();
}
else
{
auto hmac = Botan::MessageAuthenticationCode::create("HMAC(SHA1)")->clone();
hmac->set_key(rc4Key, sizeof(rc4Key));
sha1 = hmac;
}
sha1->update(reinterpret_cast<const uint8_t*>(tempContent.c_str()), tempContent.size());
sha1->update(state->GetHashKey(), 16);
auto hashData = sha1->final();
delete rc4;
delete sha1;
return tempContent + string(reinterpret_cast<const char*>(&hashData[0]), hashData.size());
}
string ROSCrypt::url_encode(const string& value)
{
ostringstream escaped;
escaped.fill('0');
escaped << hex;
for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i)
{
string::value_type c = (*i);
if (((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '_' || c == '.' || c == '~') && c != '+')
{
escaped << c;
}
else if (c == ' ')
{
escaped << '+';
}
else
{
escaped << '%' << setw(2) << ((int)(uint8_t)c) << setw(0);
}
}
return string(escaped.str().c_str());
}
string ROSCrypt::ex_url_encode(const string& value)
{
ostringstream escaped;
escaped.fill('0');
escaped << hex;
for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i)
{
string::value_type c = (*i);
if (((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '_' || c == '.' || c == '~') || c == '+')
{
escaped << c;
}
else if (c == ' ')
{
escaped << '+';
}
else
{
escaped << uppercase << '%' << setw(2) << ((int)(uint8_t)c) << setw(0);
}
}
return string(escaped.str().c_str());
}
string ROSCrypt::BuildPostString(const map<string, string>& fields)
{
stringstream retval;
for (auto& field : fields)
{
retval << field.first << "=" << url_encode(field.second) << "&";
}
string str = string(retval.str().c_str());
return str.substr(0, str.length() - 1);
}
string ROSCrypt::GetROSVersionString()
{
string baseString;
if (m_launcher)
baseString = "e=1,t=launcher,p=pcros,v=11";
else
baseString = "e=1,t=gta5,p=pcros,v=11";
vector<uint8_t> xorBuffer(baseString.length() + 4);
if (m_launcher)
{
*(uint32_t*)&xorBuffer[0] = 0xC5C5C5C5;
for (int i = 4; i < xorBuffer.size(); i++)
{
xorBuffer[i] = baseString[i - 4] ^ 0xC5;
}
}
else
{
*(uint32_t*)&xorBuffer[0] = 0xCDCDCDCD;
for (int i = 4; i < xorBuffer.size(); i++)
{
xorBuffer[i] = baseString[i - 4] ^ 0xCD;
}
}
string base64str = Botan::base64_encode(reinterpret_cast<const Botan::byte*>(&xorBuffer[0]), xorBuffer.size());
return format("ros {}", base64str);
}

106
src/ros_crypt.hpp Normal file
View File

@ -0,0 +1,106 @@
#pragma once
#include <string>
#include <map>
#include <vector>
#include <memory>
#include <string>
#include <cstring>
#include "botan_all.h"
using namespace std;
class ROSCryptoState
{
private:
Botan::StreamCipher* m_rc4;
uint8_t m_rc4Key[32];
uint8_t m_xorKey[16];
uint8_t m_hashKey[16];
public:
ROSCryptoState(const string& platformKey);
~ROSCryptoState();
const uint8_t* GetXorKey() const;
const uint8_t* GetHashKey() const;
};
class ROSCrypt
{
public:
constexpr ROSCrypt(const bool launcher) : m_launcher(launcher)
{
constexpr const char* launcherPlatformKey = "C6fU6TQTPgUVmy3KIB5g8ElA7DrenVpGogSZjsh+lqJaQHqv4Azoctd/v4trfX6cBjbEitUKBG/hRINF4AhQqcg=";
constexpr const char* platformKey = "C4pWJwWIKGUxcHd69eGl2AOwH2zrmzZAoQeHfQFcMelybd32QFw9s10px6k0o75XZeB5YsI9Q9TdeuRgdbvKsxc=";
m_cryptoState = make_unique<ROSCryptoState>(launcher ? launcherPlatformKey : platformKey);
}
string EncryptROSData(const string& input, const string& sessionKey = "");
string DecryptROSData(const char* data, size_t size, const string& sessionKey);
string url_encode(const string& value);
string ex_url_encode(const string& value);
string BuildPostString(const map<string, string>& fields);
string GetROSVersionString();
template<typename TAlloc>
auto HeadersHmac(const vector<uint8_t, TAlloc>& challenge, const char* method, const string& path, const string& sessionKey, const string& sessionTicket);
private:
unique_ptr<ROSCryptoState> m_cryptoState;
bool m_launcher;
};
// TODO compiler error when in .cpp?
template<typename TAlloc>
inline auto ROSCrypt::HeadersHmac(const vector<uint8_t, TAlloc>& challenge, const char* method, const string& path, const string& sessionKey, const string& sessionTicket)
{
auto hmac = unique_ptr<Botan::MessageAuthenticationCode>(Botan::MessageAuthenticationCode::create("HMAC(SHA1)")->clone());
auto cryptoState = m_cryptoState.get();
// set the key
uint8_t hmacKey[16];
// xor the RC4 key with the platform key (and optionally the session key)
auto rc4Xor = Botan::base64_decode(sessionKey);
for (int i = 0; i < sizeof(hmacKey); i++)
{
hmacKey[i] = rc4Xor[i] ^ cryptoState->GetXorKey()[i];
}
hmac->set_key(hmacKey, sizeof(hmacKey));
// method
hmac->update(method);
hmac->update(0);
// path
hmac->update(path);
hmac->update(0);
// ros-SecurityFlags
hmac->update("239");
hmac->update(0);
// ros-SessionTicket
hmac->update(sessionTicket);
hmac->update(0);
// ros-Challenge
hmac->update(Botan::base64_encode(challenge));
hmac->update(0);
// platform hash key
hmac->update(cryptoState->GetHashKey(), 16);
// set the request header
auto hmacValue = hmac->final();
return hmacValue;
}