Skip to content

Instantly share code, notes, and snippets.

@xorz57
Last active March 2, 2025 17:29
Show Gist options
  • Save xorz57/d3a876a63ab5224747e522d749cfdd6d to your computer and use it in GitHub Desktop.
Save xorz57/d3a876a63ab5224747e522d749cfdd6d to your computer and use it in GitHub Desktop.
#include <cstring>
#include <cstdint>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <sys/types.h>
#include <unistd.h>
template <typename T>
bool read(pid_t pid, uintptr_t address, T &old_value)
{
const std::string filename = "/proc/" + std::to_string(pid) + "/mem";
std::ifstream mem(filename, std::ios::in | std::ios::binary);
if (!mem.is_open())
{
std::cerr << "Error: Failed to open memory file for process " << pid << " at " << filename << std::endl;
return false;
}
mem.seekg(address);
if (!mem)
{
std::cerr << "Error: Failed to seek to address " << std::hex << address << std::dec << " in process " << pid << std::endl;
return false;
}
mem.read(reinterpret_cast<char *>(&old_value), sizeof(old_value));
if (!mem)
{
std::cerr << "Error: Failed to read from address " << std::hex << address << std::dec << " in process " << pid << std::endl;
return false;
}
return true;
}
template <typename T>
bool modify(pid_t pid, uintptr_t address, const T &new_value)
{
const std::string filename = "/proc/" + std::to_string(pid) + "/mem";
std::ofstream mem(filename, std::ios::in | std::ios::out | std::ios::binary);
if (!mem.is_open())
{
std::cerr << "Error: Failed to open memory file for process " << pid << " at " << filename << std::endl;
return false;
}
mem.seekp(address);
if (!mem)
{
std::cerr << "Error: Failed to seek to address " << std::hex << address << std::dec << " in process " << pid << std::endl;
return false;
}
mem.write(reinterpret_cast<const char *>(&new_value), sizeof(new_value));
if (!mem)
{
std::cerr << "Error: Failed to write to address " << std::hex << address << std::dec << " in process " << pid << std::endl;
return false;
}
return true;
}
template <typename T>
bool display_and_modify(pid_t pid, uintptr_t address, const T &new_value)
{
T old_value;
if (!read<T>(pid, address, old_value))
{
std::cerr << "Error: Failed to read value at address " << std::hex << address << std::dec << " in process " << pid << std::endl;
return false;
}
std::cout << "Current value at address " << std::hex << address << ": " << std::dec << old_value << std::endl;
if (!modify<T>(pid, address, new_value))
{
std::cerr << "Error: Failed to modify value at address " << std::hex << address << std::dec << " in process " << pid << std::endl;
return false;
}
std::cout << "Successfully modified value at address " << std::hex << address << " to " << std::dec << new_value << std::endl;
return true;
}
bool is_valid_pid(pid_t pid)
{
std::ifstream proc_file("/proc/" + std::to_string(pid));
return proc_file.is_open();
}
bool is_valid_address(uintptr_t address)
{
return address > 0;
}
template <typename T>
bool parse_value(const std::string &str, T &value)
{
std::istringstream ss(str);
ss >> value;
return !ss.fail();
}
int main(int argc, char *argv[])
{
if (argc != 5)
{
std::cerr << "Usage: " << argv[0] << " <pid> <address> <type> <value>" << std::endl;
std::cerr << "Supported types: int, float, double, char, long, short, etc." << std::endl;
return 1;
}
pid_t pid = std::stoi(argv[1]);
uintptr_t address = std::stoull(argv[2], nullptr, 16);
std::string type = argv[3];
std::string new_value_str = argv[4];
if (!is_valid_pid(pid))
{
std::cerr << "Error: Invalid process ID " << pid << std::endl;
return 1;
}
if (!is_valid_address(address))
{
std::cerr << "Error: Invalid memory address " << std::hex << address << std::dec << std::endl;
return 1;
}
bool success = false;
if (type == "int")
{
int value;
if (parse_value(new_value_str, value))
{
success = display_and_modify<int>(pid, address, value);
}
else
{
std::cerr << "Error: Invalid value for type int" << std::endl;
}
}
else if (type == "float")
{
float value;
if (parse_value(new_value_str, value))
{
success = display_and_modify<float>(pid, address, value);
}
else
{
std::cerr << "Error: Invalid value for type float" << std::endl;
}
}
else if (type == "double")
{
double value;
if (parse_value(new_value_str, value))
{
success = display_and_modify<double>(pid, address, value);
}
else
{
std::cerr << "Error: Invalid value for type double" << std::endl;
}
}
else if (type == "char")
{
char value = new_value_str[0];
success = display_and_modify<char>(pid, address, value);
}
else
{
std::cerr << "Error: Unsupported type '" << type << "'" << std::endl;
return 1;
}
if (!success)
{
std::cerr << "Operation failed!" << std::endl;
return 1;
}
return 0;
}
#include <chrono>
#include <iomanip>
#include <iostream>
#include <thread>
// int main() {
// int x = 42;
// while (true) {
// using namespace std::chrono_literals;
// std::cout << "x @ " << std::hex << &x << " = " << std::dec << x << std::endl;
// std::this_thread::sleep_for(1s);
// }
// return 0;
// }
int main() {
float x = 4.2f;
while (true) {
using namespace std::chrono_literals;
std::cout << "x @ " << std::hex << &x << " = " << std::dec << x << std::endl;
std::this_thread::sleep_for(1s);
}
return 0;
}
@xorz57
Copy link
Author

xorz57 commented Mar 2, 2025

Terminal 1

  1. Run ./target.
  2. Get the address of x.

Terminal 2

  1. Run ps -aux | grep ./target.
  2. Get the pid of ./target.
  3. Run sudo ./attacker <pid_here> <address_of_x_here> float 1.618.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment