From c21942ee3b700c7f0a270e7b5037593a23d4a864 Mon Sep 17 00:00:00 2001 From: ps1337 Date: Sun, 16 Jun 2019 22:57:18 +0200 Subject: [PATCH] refactor --- .gitignore | 2 + CMakeLists.txt | 12 +++ globalsettings.h | 8 ++ main.cpp | 269 +++++++++++++++++++++++++++++++++++++++++++++++ mem.cpp | 67 ++++++++++++ mem.h | 20 ++++ util.cpp | 31 ++++++ util.h | 14 +++ 8 files changed, 423 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 globalsettings.h create mode 100644 main.cpp create mode 100644 mem.cpp create mode 100644 mem.h create mode 100644 util.cpp create mode 100644 util.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a3e4c39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/* +test/* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..6dab5e2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.0.0) +project(bananabot VERSION 0.1.0) + +include(CTest) +enable_testing() + +include_directories(${PROJECT_SOURCE_DIR}) +add_executable(bananabot main.cpp globalsettings.h mem.cpp util.cpp) + +set(CPACK_PROJECT_NAME ${PROJECT_NAME}) +set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) +include(CPack) diff --git a/globalsettings.h b/globalsettings.h new file mode 100644 index 0000000..5033564 --- /dev/null +++ b/globalsettings.h @@ -0,0 +1,8 @@ +#ifndef GLOBALSETTINGS_H +#define GLOBALSETTINGS_H + +#include + +extern pid_t PID; + +#endif \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..5d20e28 --- /dev/null +++ b/main.cpp @@ -0,0 +1,269 @@ +#include "util.h" +#include "mem.h" +#include "globalsettings.h" +#include +#include +#include +#include +#include +#include + +// Settings +unsigned int player_base_so_offset = 0x214AEF0; +unsigned int player_base_ptr_offset = 0xC; +std::vector player_base_offsets = {player_base_so_offset, player_base_ptr_offset}; +uint64_t player_base_addr = -1; + +unsigned int force_jump_so_offset = 0x029F3C18; +unsigned int force_jump_ptr_offset = 0x110; +std::vector force_jump_offsets = {force_jump_so_offset, force_jump_ptr_offset}; +uint64_t force_jump_addr = -1; + +unsigned int client_state_so_offset = 0x00E20D08; +unsigned int client_state_ptr_offset = 0x08; +std::vector client_state_offsets = {client_state_so_offset, client_state_ptr_offset}; +uint64_t client_state_addr = -1; +unsigned int client_state_view_angle_x_offset = 0x8E98; +unsigned int client_state_view_angle_y_offset = client_state_view_angle_x_offset + 0x04; +uint64_t client_state_view_angle_x_addr = -1; +uint64_t client_state_view_angle_y_addr = -1; + +unsigned int glow_manager_so_offset = 0x29e8980; +uint64_t glow_manager_ptr_addr = -1; +uint64_t glow_manager_addr = 0; +unsigned int glow_object_offset = 0x40; +unsigned int glow_object_count_addr_offset = 0x10; +unsigned int glow_object_count = -1; + +// members of player_base +unsigned int player_base_health_offset = 0x12c; +uint64_t player_health_addr = -1; +unsigned int player_base_team_offset = 0x124; +uint64_t player_team_addr = -1; +unsigned int player_base_is_on_floor_offset = 0x130; +uint64_t player_is_on_floor_addr = -1; +unsigned int player_base_flash_time_offset = 0xACF8; +uint64_t player_flash_time_addr = -1; + +unsigned int player_base_location_x_offset = 0xCC; +unsigned int player_base_location_z_offset = 0xD0; +unsigned int player_base_location_y_offset = 0xD4; +uint64_t player_base_location_x_addr = -1; +uint64_t player_base_location_y_addr = -1; +uint64_t player_base_location_z_addr = -1; + +unsigned int entity_team_offset = 0x130; +unsigned int entity_health_offset = 0x138; +unsigned int entity_m_vec_origin_start = 0xE0; +unsigned int entity_m_vec_origin_z_offset = entity_m_vec_origin_start + 0x08; +unsigned int entity_m_vec_origin_y_offset = entity_m_vec_origin_start; +unsigned int entity_m_vec_origin_x_offset = entity_m_vec_origin_start + 0x04; + +pid_t PID; + +uint64_t addr_from_ptr(uint64_t ptr) +{ + unsigned char buffer[8]; + if (!Mem::readmem((void *)ptr, buffer, sizeof(buffer))) + { + std::cerr << "Couldn't read from " << std::hex << ptr << std::endl; + exit(1); + } + ptr = *(uint64_t *)(&buffer); + return ptr; +} + +uint64_t addr_from_multilvl_ptr(uint64_t ptr, std::vector offsets) +{ + unsigned char buffer[8]; + for (int i = 0; i < offsets.size(); i++) + { + ptr += offsets[i]; + if (!Mem::readmem((void *)ptr, buffer, sizeof(buffer))) + { + std::cerr << "Couldn't read from " << std::hex << ptr << std::endl; + exit(1); + } + // don't dereference in last round + if (i == offsets.size() - 1) + { + return ptr; + } + // dereference where buffer points to + ptr = *(uint64_t *)(&buffer); + } + return ptr; +} + +std::vector readFromAddr(void *address, size_t size) +{ + unsigned char buffer[size] = {0}; + if (!Mem::readmem(address, buffer, size)) + { + std::cerr << "Couldn't read from " << std::hex << address << std::endl; + exit(1); + } + std::vector res(buffer, buffer + size); + return res; +} + +bool writeToAddr(void *address, std::vector buffer) +{ + return Mem::writemem(address, reinterpret_cast(buffer.data()), buffer.size()); +} + +bool getAddrs() +{ + if (PID <= 0) + { + return false; + } + uint64_t client_panorama_client_base = Mem::getModuleStart("client_panorama_client.so"); + std::cout << "client_panorama_client.so is @ " << std::hex << client_panorama_client_base << std::endl; + + uint64_t engine_client_base = Mem::getModuleStart("engine_client.so"); + std::cout << "engine_client.so is @ " << std::hex << engine_client_base << std::endl; + + player_base_addr = addr_from_multilvl_ptr(client_panorama_client_base, player_base_offsets); + + std::cout << "player_base is @ " << std::hex << player_base_addr << std::endl; + player_health_addr = player_base_addr + player_base_health_offset; + player_team_addr = player_base_addr + player_base_team_offset; + + player_is_on_floor_addr = player_base_addr + player_base_is_on_floor_offset; + player_flash_time_addr = player_base_addr + player_base_flash_time_offset; + + player_base_location_x_addr = player_base_addr + player_base_location_x_offset; + player_base_location_y_addr = player_base_addr + player_base_location_y_offset; + player_base_location_z_addr = player_base_addr + player_base_location_z_offset; + + force_jump_addr = addr_from_multilvl_ptr(client_panorama_client_base, force_jump_offsets); + std::cout << "force_jump is @ " << std::hex << force_jump_addr << std::endl; + + client_state_addr = addr_from_multilvl_ptr(engine_client_base, client_state_offsets); + std::cout << "client_state is @ " << std::hex << client_state_addr << std::endl; + client_state_view_angle_x_addr = client_state_addr + client_state_view_angle_x_offset; + std::cout << "view_angle_x is @ " << std::hex << client_state_view_angle_x_addr << std::endl; + client_state_view_angle_y_addr = client_state_addr + client_state_view_angle_y_offset; + std::cout << "view_angle_y is @ " << std::hex << client_state_view_angle_y_addr << std::endl; + + glow_manager_ptr_addr = client_panorama_client_base + glow_manager_so_offset; + std::cout << "glow_manager_ptr is @ " << std::hex << glow_manager_ptr_addr << std::endl; + glow_manager_addr = addr_from_multilvl_ptr(glow_manager_ptr_addr, {0, 0}); + std::cout << "glow_manager is @ " << std::hex << glow_manager_addr << std::endl; + + auto tmp = readFromAddr((void *)(glow_manager_ptr_addr + glow_object_count_addr_offset), sizeof(int)); + + return true; +} + +std::vector getPlayerLocation() +{ + auto x = readFromAddr((void *)(player_base_location_x_addr), sizeof(float)); + auto y = readFromAddr((void *)(player_base_location_y_addr), sizeof(float)); + auto z = readFromAddr((void *)(player_base_location_z_addr), sizeof(float)); + + float result_x = 0; + float result_y = 0; + float result_z = 0; + + std::copy(reinterpret_cast(&x[0]), + reinterpret_cast(&x[4]), + reinterpret_cast(&result_x)); + + std::copy(reinterpret_cast(&y[0]), + reinterpret_cast(&y[4]), + reinterpret_cast(&result_y)); + + std::copy(reinterpret_cast(&z[0]), + reinterpret_cast(&z[4]), + reinterpret_cast(&result_z)); + + return {result_x, result_y, result_z}; +} + +std::vector getEntityLocation(void *entity_base_addr) +{ + auto x = readFromAddr((void *)(entity_base_addr + entity_m_vec_origin_x_offset), sizeof(float)); + auto y = readFromAddr((void *)(entity_base_addr + entity_m_vec_origin_y_offset), sizeof(float)); + auto z = readFromAddr((void *)(entity_base_addr + entity_m_vec_origin_z_offset), sizeof(float)); + + float result_x = 0; + float result_y = 0; + float result_z = 0; + + std::copy(reinterpret_cast(&x[0]), + reinterpret_cast(&x[4]), + reinterpret_cast(&result_x)); + + std::copy(reinterpret_cast(&y[0]), + reinterpret_cast(&y[4]), + reinterpret_cast(&result_y)); + + std::copy(reinterpret_cast(&z[0]), + reinterpret_cast(&z[4]), + reinterpret_cast(&result_z)); + + return {result_x, result_y, result_z}; +} + +void getPlayerAddrs() +{ + auto vec = readFromAddr((void *)(glow_manager_ptr_addr + glow_object_count_addr_offset), sizeof(int)); + // TODO value is cut + int count = vec[0]; + + auto x = getPlayerLocation(); + std::cout << "P: " << x[0] << " " << x[1] << " " << x[2] << std::endl; + + for (int i = 0; i < count; i++) + { + uint64_t ptr = glow_manager_addr + (glow_object_offset * i); + uint64_t addr = addr_from_ptr(ptr); + // empty entity slot + if (addr == 0) + { + continue; + } + + int entity_team = readFromAddr((void *)(addr + entity_team_offset), sizeof(int))[0]; + int entity_health = readFromAddr((void *)(addr + entity_health_offset), sizeof(int))[0]; + + int own_team = readFromAddr((void *)(player_team_addr), sizeof(int))[0]; + + if (entity_team != own_team && entity_health > 0) + { + auto f = getEntityLocation((void *)addr); + std::cout << "* " << addr << " " << entity_team << " " << entity_health << " " << f[0] << ":" << f[1] << ":" << f[2] << std::endl; + } + } +} + +int main() +{ + std::cout << "CSO:GO 1337 BANANABOT STARTING" << std::endl; + + PID = Util::getPID(); + std::cout << "CSGO Process PID: " << PID << std::endl; + + getAddrs(); + getPlayerAddrs(); + + bool bunnyhop = false; + bool noflash = false; + + while (true) + { + if (bunnyhop && readFromAddr((void *)player_is_on_floor_addr, 1)[0] == 1) + { + writeToAddr((void *)force_jump_addr, {0x06}); + } + + if (noflash) + writeToAddr((void *)player_flash_time_addr, {0, 0, 0, 0, 0, 0, 0, 0}); + + usleep(200); + } + + return 0; +} diff --git a/mem.cpp b/mem.cpp new file mode 100644 index 0000000..c25e7a3 --- /dev/null +++ b/mem.cpp @@ -0,0 +1,67 @@ +#include "mem.h" +#include "util.h" +#include + +uint64_t Mem::getModuleStart(std::string module) +{ + uint64_t moduleStart = -1; + std::string cmd = "cat /proc/" + std::to_string(Util::getPID()) + "/maps | grep " + module + " | head -n1 | cut -d '-' -f1"; + std::string output = Util::exec(cmd.c_str()); + if (output.length() == 0) + { + std::cerr << "Error getting CSGO memory map" << std::endl; + exit(1); + } + std::stringstream ss; + ss << std::hex << output.c_str(); + ss >> moduleStart; + return moduleStart; +} + +bool Mem::readmem(void *address, void *buf, size_t size) +{ + if (PID == 0 || size == 0) + return false; + + iovec iovLocalAddressSpace; + iovec iovRemoteAddressSpace; + + iovLocalAddressSpace.iov_base = buf; + iovLocalAddressSpace.iov_len = size; + + iovRemoteAddressSpace.iov_base = address; + iovRemoteAddressSpace.iov_len = size; + + ssize_t bytes_count_read = process_vm_readv(PID, + &iovLocalAddressSpace, + 1, //Size of the local iovec array + &iovRemoteAddressSpace, //Remote iovec array + 1, //Size of the remote iovec array + 0); //Flags, unused + + return (bytes_count_read == (ssize_t)size); +} + +bool Mem::writemem(void *address, void *buf, size_t size) +{ + if (PID == 0 || size == 0) + return false; + + iovec iovLocalAddressSpace; + iovec iovRemoteAddressSpace; + + iovLocalAddressSpace.iov_base = buf; + iovLocalAddressSpace.iov_len = size; + + iovRemoteAddressSpace.iov_base = address; + iovRemoteAddressSpace.iov_len = size; + + ssize_t bytes_count_write = process_vm_writev(PID, + &iovLocalAddressSpace, //Local iovec array + 1, //Size of the local iovec array + &iovRemoteAddressSpace, //Remote iovec array + 1, //Size of the remote iovec array + 0); //Flags, unused + + return (bytes_count_write == (ssize_t)size); +} \ No newline at end of file diff --git a/mem.h b/mem.h new file mode 100644 index 0000000..90b3f59 --- /dev/null +++ b/mem.h @@ -0,0 +1,20 @@ +#ifndef MEM_H +#define MEM_H + +#include "globalsettings.h" +#include +#include +#include +#include +#include +#include // iovec + +class Mem +{ +public: + static uint64_t getModuleStart(std::string module); + static bool readmem(void *address, void *buf, size_t size); + static bool writemem(void *address, void *buf, size_t size); +}; + +#endif \ No newline at end of file diff --git a/util.cpp b/util.cpp new file mode 100644 index 0000000..39465b6 --- /dev/null +++ b/util.cpp @@ -0,0 +1,31 @@ +#include "util.h" +#include +#include + +std::string Util::exec(const char *cmd) +{ + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) + { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) + { + result += buffer.data(); + } + return result; +} + +pid_t Util::getPID() +{ + std::string output = Util::exec("ps aux | grep steam | grep csgo | grep -v grep | awk '{print $2}'"); + if (output.length() == 0) + { + std::cerr << "Error getting CSGO PID" << std::endl; + exit(1); + } + pid_t PID = (pid_t)atoi(output.c_str()); + return PID; +} \ No newline at end of file diff --git a/util.h b/util.h new file mode 100644 index 0000000..2784c58 --- /dev/null +++ b/util.h @@ -0,0 +1,14 @@ +#ifndef UTIL_H +#define UTIL_H + +#include +#include + +class Util +{ +public: + static std::string exec(const char *cmd); + static pid_t getPID(); +}; + +#endif \ No newline at end of file