mirror of
https://github.com/diamante0018/MW3ServerFreezer.git
synced 2025-10-27 06:36:55 +00:00
use protocol buffers to do something cool
This commit is contained in:
62
src/client/component/crypto_key.cpp
Normal file
62
src/client/component/crypto_key.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
#include <std_include.hpp>
|
||||
|
||||
#include "crypto_key.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include <utils/io.hpp>
|
||||
|
||||
namespace crypto_key {
|
||||
namespace {
|
||||
bool load_key(utils::cryptography::ecc::key& key) {
|
||||
std::string data{};
|
||||
if (!utils::io::read_file("./private.key", &data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
key.deserialize(data);
|
||||
if (!key.is_valid()) {
|
||||
console::info("Loaded key is invalid!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
utils::cryptography::ecc::key generate_key() {
|
||||
auto key = utils::cryptography::ecc::generate_key(512);
|
||||
if (!key.is_valid()) {
|
||||
throw std::runtime_error("Failed to generate server key!");
|
||||
}
|
||||
|
||||
if (!utils::io::write_file("./private.key", key.serialize())) {
|
||||
throw std::runtime_error("Failed to write server key!");
|
||||
}
|
||||
|
||||
console::info("Generated cryptographic key: {}", key.get_hash());
|
||||
return key;
|
||||
}
|
||||
|
||||
utils::cryptography::ecc::key load_or_generate_key() {
|
||||
utils::cryptography::ecc::key key{};
|
||||
if (load_key(key)) {
|
||||
console::info("Loaded cryptographic key: {}", key.get_hash());
|
||||
return key;
|
||||
}
|
||||
|
||||
return generate_key();
|
||||
}
|
||||
|
||||
utils::cryptography::ecc::key get_key_internal() {
|
||||
auto key = load_or_generate_key();
|
||||
if (!utils::io::write_file("./public.key", key.get_public_key())) {
|
||||
console::info("Failed to write public key!");
|
||||
}
|
||||
return key;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
const utils::cryptography::ecc::key& get() {
|
||||
static auto key = get_key_internal();
|
||||
return key;
|
||||
}
|
||||
} // namespace crypto_key
|
||||
7
src/client/component/crypto_key.hpp
Normal file
7
src/client/component/crypto_key.hpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/cryptography.hpp"
|
||||
|
||||
namespace crypto_key {
|
||||
const utils::cryptography::ecc::key& get();
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace network {
|
||||
using callback =
|
||||
std::function<void(const game::netadr_s&, const std::string_view&)>;
|
||||
|
||||
void on_packet(const std::string& command, const callback& callback);
|
||||
} // namespace network
|
||||
@@ -1,15 +1,17 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../loader/component_loader.hpp"
|
||||
#include "../../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
#include "../console.hpp"
|
||||
|
||||
#include "network.hpp"
|
||||
|
||||
namespace network {
|
||||
namespace {
|
||||
std::unordered_map<std::string, network::callback>& get_callbacks() {
|
||||
static std::unordered_map<std::string, network::callback> network_callbacks{};
|
||||
std::unordered_map<std::string, callback>& get_callbacks() {
|
||||
static std::unordered_map<std::string, callback> network_callbacks{};
|
||||
return network_callbacks;
|
||||
}
|
||||
|
||||
@@ -32,7 +34,6 @@ bool handle_command(game::netadr_s* address, const char* command,
|
||||
handler->second(*address, data);
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
int packet_interception_handler(game::netadr_s* from, const char* command,
|
||||
game::msg_t* message) {
|
||||
@@ -42,12 +43,61 @@ int packet_interception_handler(game::netadr_s* from, const char* command,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void send(const game::netadr_s& address, const std::string& command,
|
||||
const std::string& data, const char separator) {
|
||||
std::string packet = "\xFF\xFF\xFF\xFF";
|
||||
packet.append(command);
|
||||
packet.push_back(separator);
|
||||
packet.append(data);
|
||||
|
||||
send_data(address, packet);
|
||||
}
|
||||
|
||||
void send_data(const game::netadr_s& address, const std::string& data) {
|
||||
auto size = static_cast<int>(data.size());
|
||||
|
||||
if (address.type == game::NA_LOOPBACK) {
|
||||
// TODO: Fix this for loopback
|
||||
if (size > 1280) {
|
||||
console::info("Packet was too long. Truncated!\n");
|
||||
size = 1280;
|
||||
}
|
||||
|
||||
game::NET_SendLoopPacket(game::NS_CLIENT1, size, data.data(), address);
|
||||
} else {
|
||||
game::Sys_SendPacket(size, data.data(), address);
|
||||
}
|
||||
}
|
||||
|
||||
void on_packet(const std::string& command, const callback& callback) {
|
||||
get_callbacks()[utils::string::to_lower(command)] = callback;
|
||||
}
|
||||
|
||||
class component final : public component_interface {
|
||||
const char* net_adr_to_string(const game::netadr_s& a) {
|
||||
if (a.type == game::netadrtype_t::NA_LOOPBACK) {
|
||||
return "loopback";
|
||||
}
|
||||
|
||||
if (a.type == game::netadrtype_t::NA_BOT) {
|
||||
return "bot";
|
||||
}
|
||||
|
||||
if (a.type == game::netadrtype_t::NA_IP ||
|
||||
a.type == game::netadrtype_t::NA_BROADCAST) {
|
||||
if (a.port) {
|
||||
return utils::string::va("%u.%u.%u.%u:%u", a.ip[0], a.ip[1], a.ip[2],
|
||||
a.ip[3], htons(a.port));
|
||||
}
|
||||
|
||||
return utils::string::va("%u.%u.%u.%u", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
|
||||
}
|
||||
|
||||
return "bad";
|
||||
}
|
||||
|
||||
class network final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
add_network_commands();
|
||||
@@ -67,4 +117,4 @@ private:
|
||||
};
|
||||
} // namespace network
|
||||
|
||||
REGISTER_COMPONENT(network::component)
|
||||
REGISTER_COMPONENT(network::network)
|
||||
13
src/client/component/network/network.hpp
Normal file
13
src/client/component/network/network.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace network {
|
||||
void send(const game::netadr_s& address, const std::string& command,
|
||||
const std::string& data = {}, char separator = ' ');
|
||||
void send_data(const game::netadr_s& address, const std::string& data);
|
||||
|
||||
using callback =
|
||||
std::function<void(const game::netadr_s&, const std::string_view&)>;
|
||||
void on_packet(const std::string& command, const callback& callback);
|
||||
|
||||
const char* net_adr_to_string(const game::netadr_s& a);
|
||||
} // namespace network
|
||||
54
src/client/component/rcon.cpp
Normal file
54
src/client/component/rcon.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include <std_include.hpp>
|
||||
#include "../loader/component_loader.hpp"
|
||||
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
#include "network/network.hpp"
|
||||
|
||||
#include "crypto_key.hpp"
|
||||
#include "key_catcher.hpp"
|
||||
|
||||
#include <proto/rcon.pb.h>
|
||||
|
||||
namespace rcon {
|
||||
namespace {
|
||||
utils::cryptography::ecc::key key;
|
||||
std::string commands;
|
||||
} // namespace
|
||||
|
||||
class component final : public component_interface {
|
||||
public:
|
||||
void post_unpack() override {
|
||||
key = crypto_key::get();
|
||||
add_key_hooks();
|
||||
add_commands();
|
||||
}
|
||||
|
||||
private:
|
||||
static void add_key_hooks() {
|
||||
// Why commands don't work? I don't know!
|
||||
key_catcher::on_key_press(
|
||||
"7", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
||||
commands = "quit";
|
||||
network::send(game::localClientConnection->serverAddress,
|
||||
"rcon_request");
|
||||
});
|
||||
}
|
||||
|
||||
static void add_commands() {
|
||||
network::on_packet("rcon_authorization", [](const game::netadr_s& adr,
|
||||
const std::string_view& data) {
|
||||
const auto signed_msg =
|
||||
utils::cryptography::ecc::sign_message(key, std::string(data));
|
||||
|
||||
proto::rcon::command info;
|
||||
info.set_commands(commands);
|
||||
info.set_signature(signed_msg);
|
||||
|
||||
network::send(adr, "rcon_execute", info.SerializeAsString());
|
||||
});
|
||||
}
|
||||
};
|
||||
} // namespace rcon
|
||||
|
||||
REGISTER_COMPONENT(rcon::component)
|
||||
@@ -69,7 +69,7 @@ struct netadr_s {
|
||||
unsigned int addrHandleIndex;
|
||||
};
|
||||
|
||||
static_assert(sizeof(netadr_s) == 24);
|
||||
static_assert(sizeof(netadr_s) == 0x18);
|
||||
|
||||
typedef enum {
|
||||
ERR_FATAL = 0x0,
|
||||
|
||||
@@ -54,7 +54,9 @@ WEAK symbol<bool(netsrc_t, netadr_s dest, unsigned char* data, int size)>
|
||||
WEAK symbol<void(netadr_s*, sockaddr*)> NetadrToSockadr{0x48B460};
|
||||
WEAK symbol<int(const char* serverName, netadr_s serverRemote)> NET_StringToAdr{
|
||||
0x4E09A0};
|
||||
WEAK symbol<SOCKET> query_socket{0x5A861EC};
|
||||
WEAK symbol<bool(int length, const void* voiddata, netadr_s to)> Sys_SendPacket{0x5145C0};
|
||||
WEAK symbol<void(netsrc_t sock, int length, const void* data, netadr_s to)> NET_SendLoopPacket{0x4B9DF0};
|
||||
|
||||
WEAK symbol<void()> Com_Quit_f{0x556060};
|
||||
|
||||
WEAK symbol<void(const msg_t*, unsigned char*, int)> MSG_Init{0x40E030};
|
||||
@@ -74,11 +76,6 @@ WEAK symbol<int(unsigned __int64, const void*, unsigned int)>
|
||||
WEAK symbol<XAssetHeader(int type, const char* name, int allowCreateDefault)>
|
||||
DB_FindXAssetHeader{0x4B25C0};
|
||||
|
||||
WEAK symbol<void(const char* text, int maxChars, Font_s* font, float x, float y,
|
||||
float xScale, float yScale, float rotation, const float* color,
|
||||
int style)>
|
||||
R_AddCmdDrawText{0x42C970};
|
||||
|
||||
// Variables
|
||||
WEAK symbol<CmdArgs> cmd_args{0x1C96850};
|
||||
WEAK symbol<PlayerKeyState> playerKeys{0xB3A38C};
|
||||
|
||||
8
src/client/proto/rcon.proto
Normal file
8
src/client/proto/rcon.proto
Normal file
@@ -0,0 +1,8 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package proto.rcon;
|
||||
|
||||
message command {
|
||||
bytes commands = 1;
|
||||
bytes signature = 2;
|
||||
}
|
||||
@@ -1 +1,11 @@
|
||||
#include "std_include.hpp"
|
||||
|
||||
extern "C" {
|
||||
int s_read_arc4random(void*, std::size_t) { return -1; }
|
||||
|
||||
int s_read_getrandom(void*, std::size_t) { return -1; }
|
||||
|
||||
int s_read_urandom(void*, std::size_t) { return -1; }
|
||||
|
||||
int s_read_ltm_rng(void*, std::size_t) { return -1; }
|
||||
}
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <WinSock2.h>
|
||||
#include <Windows.h>
|
||||
#include <WinSock2.h>
|
||||
#include <WS2tcpip.h>
|
||||
|
||||
#include <corecrt_io.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
@@ -15,10 +17,12 @@
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <source_location>
|
||||
#include <queue>
|
||||
|
||||
#pragma comment(lib, "ntdll.lib")
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user