Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <windows.h>
- #include <iostream>
- #include <vector>
- #include <string>
- #include <sstream>
- #include <iomanip>
- #include <thread>
- #include <chrono>
- #include <unordered_map>
- // Define IOCTLs for driver communication
- #define IOCTL_READ_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define IOCTL_WRITE_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define IOCTL_GET_PROCESS_BASE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
- #define IOCTL_GET_MODULE_BASE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
- // Structure for memory operations
- typedef struct _MEMORY_STRUCT {
- ULONG64 Address; // Target memory address
- ULONG Size; // Size of data to read/write
- UCHAR* Buffer; // Buffer for data transfer
- ULONG ProcessId; // Process ID for operation
- } MEMORY_STRUCT, *PMEMORY_STRUCT;
- // Structure for module base address retrieval
- typedef struct _MODULE_STRUCT {
- ULONG ProcessId;
- WCHAR ModuleName[260];
- ULONG64 BaseAddress;
- } MODULE_STRUCT, *PMODULE_STRUCT;
- // Offset cache to store discovered offsets
- std::unordered_map<std::string, ULONG64> offsetCache;
- // Global variables
- HANDLE hDevice = INVALID_HANDLE_VALUE;
- ULONG targetProcessId = 0;
- ULONG64 processBaseAddress = 0;
- bool isRunning = true;
- // Function prototypes
- bool InitializeDriver();
- void CloseDriver();
- bool ReadMemory(ULONG64 address, void* buffer, SIZE_T size);
- bool WriteMemory(ULONG64 address, void* buffer, SIZE_T size);
- ULONG64 GetProcessBaseAddress(ULONG processId);
- ULONG64 GetModuleBaseAddress(ULONG processId, const wchar_t* moduleName);
- void MonitorValue(ULONG64 address, SIZE_T size, int interval);
- void DisplayMenu();
- void ProcessCommand(const std::string& command);
- std::vector<std::string> SplitString(const std::string& input, char delimiter);
- std::string ToLowerCase(const std::string& input);
- ULONG64 ParseHexAddress(const std::string& hexString);
- void PrintMemory(UCHAR* buffer, SIZE_T size, ULONG64 address);
- void ScanForValue(const std::string& valueType, const std::string& value);
- int main() {
- std::cout << "========================================\n";
- std::cout << "= Enhanced Memory Access Tool =\n";
- std::cout << "========================================\n\n";
- if (!InitializeDriver()) {
- std::cout << "Press any key to exit...\n";
- std::cin.get();
- return 1;
- }
- std::cout << "Driver initialized successfully!\n\n";
- std::string command;
- DisplayMenu();
- while (isRunning) {
- std::cout << "\n> ";
- std::getline(std::cin, command);
- ProcessCommand(command);
- }
- CloseDriver();
- return 0;
- }
- bool InitializeDriver() {
- hDevice = CreateFileW(L"\\\\.\\FortPenTest", GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
- if (hDevice == INVALID_HANDLE_VALUE) {
- std::cout << "Failed to open driver device: " << GetLastError() << std::endl;
- std::cout << "Make sure the driver is properly installed and running.\n";
- return false;
- }
- return true;
- }
- void CloseDriver() {
- if (hDevice != INVALID_HANDLE_VALUE) {
- CloseHandle(hDevice);
- hDevice = INVALID_HANDLE_VALUE;
- }
- }
- bool ReadMemory(ULONG64 address, void* buffer, SIZE_T size) {
- if (hDevice == INVALID_HANDLE_VALUE || targetProcessId == 0) {
- std::cout << "Driver not initialized or process not selected.\n";
- return false;
- }
- MEMORY_STRUCT mem = { address, static_cast<ULONG>(size), static_cast<UCHAR*>(buffer), targetProcessId };
- DWORD bytesReturned;
- if (!DeviceIoControl(hDevice, IOCTL_READ_MEMORY, &mem, sizeof(mem), &mem, sizeof(mem), &bytesReturned, nullptr)) {
- std::cout << "Memory read failed: " << GetLastError() << std::endl;
- return false;
- }
- return true;
- }
- bool WriteMemory(ULONG64 address, void* buffer, SIZE_T size) {
- if (hDevice == INVALID_HANDLE_VALUE || targetProcessId == 0) {
- std::cout << "Driver not initialized or process not selected.\n";
- return false;
- }
- MEMORY_STRUCT mem = { address, static_cast<ULONG>(size), static_cast<UCHAR*>(buffer), targetProcessId };
- DWORD bytesReturned;
- if (!DeviceIoControl(hDevice, IOCTL_WRITE_MEMORY, &mem, sizeof(mem), &mem, sizeof(mem), &bytesReturned, nullptr)) {
- std::cout << "Memory write failed: " << GetLastError() << std::endl;
- return false;
- }
- return true;
- }
- ULONG64 GetProcessBaseAddress(ULONG processId) {
- if (hDevice == INVALID_HANDLE_VALUE) {
- std::cout << "Driver not initialized.\n";
- return 0;
- }
- DWORD bytesReturned;
- ULONG64 baseAddress = 0;
- if (!DeviceIoControl(
- hDevice,
- IOCTL_GET_PROCESS_BASE,
- &processId,
- sizeof(processId),
- &baseAddress,
- sizeof(baseAddress),
- &bytesReturned,
- nullptr
- )) {
- std::cout << "Failed to get process base address: " << GetLastError() << std::endl;
- return 0;
- }
- return baseAddress;
- }
- ULONG64 GetModuleBaseAddress(ULONG processId, const wchar_t* moduleName) {
- if (hDevice == INVALID_HANDLE_VALUE) {
- std::cout << "Driver not initialized.\n";
- return 0;
- }
- MODULE_STRUCT moduleInfo = { 0 };
- moduleInfo.ProcessId = processId;
- wcscpy_s(moduleInfo.ModuleName, moduleName);
- DWORD bytesReturned;
- if (!DeviceIoControl(
- hDevice,
- IOCTL_GET_MODULE_BASE,
- &moduleInfo,
- sizeof(moduleInfo),
- &moduleInfo,
- sizeof(moduleInfo),
- &bytesReturned,
- nullptr
- )) {
- std::cout << "Failed to get module base address: " << GetLastError() << std::endl;
- return 0;
- }
- return moduleInfo.BaseAddress;
- }
- void MonitorValue(ULONG64 address, SIZE_T size, int interval) {
- std::cout << "Monitoring address 0x" << std::hex << address << " (Press Ctrl+C to stop)...\n";
- std::vector<UCHAR> buffer(size, 0);
- std::vector<UCHAR> prevBuffer(size, 0);
- bool firstRead = true;
- while (isRunning) {
- if (ReadMemory(address, buffer.data(), size)) {
- if (firstRead || memcmp(buffer.data(), prevBuffer.data(), size) != 0) {
- std::cout << "\r" << std::setw(20) << " " << "\r";
- std::cout << "0x" << std::hex << address << ": ";
- for (SIZE_T i = 0; i < size; i++) {
- std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(buffer[i]) << " ";
- }
- // Also show as decimal for small values
- if (size <= 8) {
- std::cout << "| ";
- if (size == 4) {
- DWORD value = *reinterpret_cast<DWORD*>(buffer.data());
- std::cout << std::dec << value;
- } else if (size == 8) {
- ULONG64 value = *reinterpret_cast<ULONG64*>(buffer.data());
- std::cout << std::dec << value;
- }
- }
- std::cout << std::endl;
- memcpy(prevBuffer.data(), buffer.data(), size);
- firstRead = false;
- }
- }
- std::this_thread::sleep_for(std::chrono::milliseconds(interval));
- }
- }
- void DisplayMenu() {
- std::cout << "Available commands:\n";
- std::cout << " help - Display this menu\n";
- std::cout << " process <pid> - Set target process ID\n";
- std::cout << " base - Get process base address\n";
- std::cout << " module <name> - Get module base address\n";
- std::cout << " read <addr> <size> - Read memory at address\n";
- std::cout << " write <addr> <data> - Write data to address (hex format)\n";
- std::cout << " monitor <addr> <size> [interval] - Monitor memory address\n";
- std::cout << " pattern <size> <pattern> - Create pattern for buffer overflow\n";
- std::cout << " scan <type> <value> - Scan for value in process memory\n";
- std::cout << " offset <name> <addr> - Save an offset with a name\n";
- std::cout << " offsets - List all saved offsets\n";
- std::cout << " calc <expression> - Calculate an expression with offsets\n";
- std::cout << " clear - Clear the screen\n";
- std::cout << " exit - Exit the program\n";
- }
- void ProcessCommand(const std::string& command) {
- std::vector<std::string> args = SplitString(command, ' ');
- if (args.empty()) {
- return;
- }
- std::string cmd = ToLowerCase(args[0]);
- if (cmd == "help") {
- DisplayMenu();
- }
- else if (cmd == "process" && args.size() > 1) {
- try {
- targetProcessId = std::stoul(args[1]);
- std::cout << "Set target process ID to: " << targetProcessId << std::endl;
- // Automatically get process base address
- processBaseAddress = GetProcessBaseAddress(targetProcessId);
- if (processBaseAddress) {
- std::cout << "Process base address: 0x" << std::hex << processBaseAddress << std::dec << std::endl;
- }
- }
- catch (const std::exception&) {
- std::cout << "Invalid process ID\n";
- }
- }
- else if (cmd == "base") {
- if (targetProcessId == 0) {
- std::cout << "Please select a process first\n";
- return;
- }
- processBaseAddress = GetProcessBaseAddress(targetProcessId);
- if (processBaseAddress) {
- std::cout << "Process base address: 0x" << std::hex << processBaseAddress << std::dec << std::endl;
- }
- }
- else if (cmd == "module" && args.size() > 1) {
- if (targetProcessId == 0) {
- std::cout << "Please select a process first\n";
- return;
- }
- std::wstring moduleName(args[1].begin(), args[1].end());
- ULONG64 moduleBase = GetModuleBaseAddress(targetProcessId, moduleName.c_str());
- if (moduleBase) {
- std::cout << "Module base address: 0x" << std::hex << moduleBase << std::dec << std::endl;
- // Save this in the offset cache as well
- offsetCache[args[1]] = moduleBase;
- }
- }
- else if (cmd == "read" && args.size() > 2) {
- try {
- ULONG64 address = ParseHexAddress(args[1]);
- SIZE_T size = std::stoul(args[2]);
- if (size > 1024) {
- std::cout << "Size too large. Maximum is 1024 bytes.\n";
- return;
- }
- std::vector<UCHAR> buffer(size, 0);
- if (ReadMemory(address, buffer.data(), size)) {
- PrintMemory(buffer.data(), size, address);
- }
- }
- catch (const std::exception&) {
- std::cout << "Invalid parameters\n";
- }
- }
- else if (cmd == "write" && args.size() > 2) {
- try {
- ULONG64 address = ParseHexAddress(args[1]);
- std::string hexData = args[2];
- // Remove 0x prefix if present
- if (hexData.substr(0, 2) == "0x") {
- hexData = hexData.substr(2);
- }
- // Convert hex string to bytes
- if (hexData.length() % 2 != 0) {
- std::cout << "Hex data must have an even number of characters\n";
- return;
- }
- std::vector<UCHAR> buffer;
- for (size_t i = 0; i < hexData.length(); i += 2) {
- std::string byteStr = hexData.substr(i, 2);
- UCHAR byte = static_cast<UCHAR>(std::stoul(byteStr, nullptr, 16));
- buffer.push_back(byte);
- }
- if (WriteMemory(address, buffer.data(), buffer.size())) {
- std::cout << "Successfully wrote " << buffer.size() << " bytes to 0x"
- << std::hex << address << std::dec << std::endl;
- }
- }
- catch (const std::exception&) {
- std::cout << "Invalid parameters\n";
- }
- }
- else if (cmd == "monitor" && args.size() > 2) {
- try {
- ULONG64 address = ParseHexAddress(args[1]);
- SIZE_T size = std::stoul(args[2]);
- int interval = 1000; // Default interval in ms
- if (args.size() > 3) {
- interval = std::stoi(args[3]);
- }
- if (size > 64) {
- std::cout << "Size too large for monitoring. Maximum is 64 bytes.\n";
- return;
- }
- MonitorValue(address, size, interval);
- }
- catch (const std::exception&) {
- std::cout << "Invalid parameters\n";
- }
- }
- else if (cmd == "pattern" && args.size() > 2) {
- try {
- SIZE_T size = std::stoul(args[1]);
- std::string pattern = args[2];
- if (size > 1024) {
- std::cout << "Size too large. Maximum is 1024 bytes.\n";
- return;
- }
- std::vector<UCHAR> buffer(size);
- // Fill the buffer with the repeating pattern
- for (SIZE_T i = 0; i < size; i++) {
- buffer[i] = pattern[i % pattern.length()];
- }
- std::cout << "Generated pattern (" << size << " bytes):\n";
- PrintMemory(buffer.data(), size, 0);
- std::cout << "Would you like to write this pattern to a specific address? (y/n): ";
- std::string response;
- std::getline(std::cin, response);
- if (response == "y" || response == "Y") {
- std::cout << "Enter address: ";
- std::string addrStr;
- std::getline(std::cin, addrStr);
- try {
- ULONG64 address = ParseHexAddress(addrStr);
- if (WriteMemory(address, buffer.data(), buffer.size())) {
- std::cout << "Successfully wrote pattern to 0x"
- << std::hex << address << std::dec << std::endl;
- }
- }
- catch (const std::exception&) {
- std::cout << "Invalid address\n";
- }
- }
- }
- catch (const std::exception&) {
- std::cout << "Invalid parameters\n";
- }
- }
- else if (cmd == "scan" && args.size() > 2) {
- ScanForValue(args[1], args[2]);
- }
- else if (cmd == "offset" && args.size() > 2) {
- try {
- std::string name = args[1];
- ULONG64 address = ParseHexAddress(args[2]);
- offsetCache[name] = address;
- std::cout << "Saved offset '" << name << "' = 0x" << std::hex << address << std::dec << std::endl;
- }
- catch (const std::exception&) {
- std::cout << "Invalid parameters\n";
- }
- }
- else if (cmd == "offsets") {
- if (offsetCache.empty()) {
- std::cout << "No offsets saved\n";
- return;
- }
- std::cout << "Saved offsets:\n";
- for (const auto& [name, address] : offsetCache) {
- std::cout << " " << std::left << std::setw(20) << name
- << " = 0x" << std::hex << address << std::dec << std::endl;
- }
- }
- else if (cmd == "calc" && args.size() > 1) {
- // Extract the expression from the rest of the command
- std::string expression;
- for (size_t i = 1; i < args.size(); i++) {
- expression += args[i];
- }
- // Simple expression calculator that can handle addition and subtraction
- // of offsets and hex values
- try {
- std::vector<std::string> tokens;
- std::string currentToken;
- char lastOp = '+';
- ULONG64 result = 0;
- // Tokenize the expression
- for (size_t i = 0; i < expression.length(); i++) {
- if (expression[i] == '+' || expression[i] == '-') {
- if (!currentToken.empty()) {
- tokens.push_back(currentToken);
- tokens.push_back(std::string(1, expression[i]));
- currentToken.clear();
- }
- }
- else {
- currentToken += expression[i];
- }
- }
- if (!currentToken.empty()) {
- tokens.push_back(currentToken);
- }
- // Evaluate the expression
- for (size_t i = 0; i < tokens.size(); i++) {
- if (tokens[i] == "+" || tokens[i] == "-") {
- lastOp = tokens[i][0];
- continue;
- }
- ULONG64 value;
- if (offsetCache.find(tokens[i]) != offsetCache.end()) {
- value = offsetCache[tokens[i]];
- }
- else {
- value = ParseHexAddress(tokens[i]);
- }
- if (lastOp == '+') {
- result += value;
- }
- else if (lastOp == '-') {
- result -= value;
- }
- }
- std::cout << "Result: 0x" << std::hex << result << std::dec << std::endl;
- }
- catch (const std::exception&) {
- std::cout << "Invalid expression\n";
- }
- }
- else if (cmd == "clear") {
- system("cls");
- }
- else if (cmd == "exit") {
- isRunning = false;
- std::cout << "Exiting...\n";
- }
- else {
- std::cout << "Unknown command. Type 'help' for a list of commands.\n";
- }
- }
- std::vector<std::string> SplitString(const std::string& input, char delimiter) {
- std::vector<std::string> tokens;
- std::string token;
- std::istringstream tokenStream(input);
- while (std::getline(tokenStream, token, delimiter)) {
- if (!token.empty()) {
- tokens.push_back(token);
- }
- }
- return tokens;
- }
- std::string ToLowerCase(const std::string& input) {
- std::string result = input;
- std::transform(result.begin(), result.end(), result.begin(),
- [](unsigned char c) { return std::tolower(c); });
- return result;
- }
- ULONG64 ParseHexAddress(const std::string& hexString) {
- std::string cleanHex = hexString;
- // Remove 0x prefix if present
- if (cleanHex.substr(0, 2) == "0x") {
- cleanHex = cleanHex.substr(2);
- }
- // Check if it's a known offset
- if (offsetCache.find(hexString) != offsetCache.end()) {
- return offsetCache[hexString];
- }
- // Calculate base + offset if in format "base+offset"
- size_t plusPos = hexString.find('+');
- if (plusPos != std::string::npos) {
- std::string baseName = hexString.substr(0, plusPos);
- std::string offsetStr = hexString.substr(plusPos + 1);
- if (offsetCache.find(baseName) != offsetCache.end()) {
- ULONG64 baseAddr = offsetCache[baseName];
- ULONG64 offset = std::stoull(offsetStr, nullptr, 16);
- return baseAddr + offset;
- }
- }
- // Parse as regular hex address
- return std::stoull(cleanHex, nullptr, 16);
- }
- void PrintMemory(UCHAR* buffer, SIZE_T size, ULONG64 address) {
- const SIZE_T bytesPerLine = 16;
- for (SIZE_T offset = 0; offset < size; offset += bytesPerLine) {
- // Print address
- std::cout << "0x" << std::hex << std::setw(16) << std::setfill('0') << (address + offset) << ": ";
- // Print hex values
- for (SIZE_T i = 0; i < bytesPerLine; i++) {
- if (offset + i < size) {
- std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(buffer[offset + i]) << " ";
- }
- else {
- std::cout << " ";
- }
- if (i == 7) {
- std::cout << " ";
- }
- }
- // Print ASCII representation
- std::cout << " | ";
- for (SIZE_T i = 0; i < bytesPerLine; i++) {
- if (offset + i < size) {
- char c = buffer[offset + i];
- if (c >= 32 && c <= 126) {
- std::cout << c;
- }
- else {
- std::cout << ".";
- }
- }
- else {
- std::cout << " ";
- }
- }
- std::cout << std::endl;
- }
- // Print as different data types for small sizes
- if (size <= 8) {
- std::cout << "\nAs values: ";
- if (size >= 1) std::cout << "INT8: " << static_cast<int>(buffer[0]) << " ";
- if (size >= 2) std::cout << "INT16: " << *reinterpret_cast<short*>(buffer) << " ";
- if (size >= 4) std::cout << "INT32: " << *reinterpret_cast<int*>(buffer) << " ";
- if (size >= 4) std::cout << "FLOAT: " << *reinterpret_cast<float*>(buffer) << " ";
- if (size >= 8) std::cout << "INT64: " << *reinterpret_cast<INT64*>(buffer) << " ";
- if (size >= 8) std::cout << "DOUBLE: " << *reinterpret_cast<double*>(buffer) << " ";
- std::cout << std::endl;
- }
- }
- void ScanForValue(const std::string& valueType, const std::string& valueStr) {
- if (targetProcessId == 0) {
- std::cout << "Please select a process first\n";
- return;
- }
- std::cout << "Memory scanning is not implemented yet. This would require additional driver support.\n";
- std::cout << "Would typically scan for " << valueType << " with value " << valueStr << ".\n";
- // In a real implementation, this would use the driver to scan process memory
- // The basic implementation would:
- // 1. Enumerate all memory regions
- // 2. Read memory in chunks
- // 3. Compare against the target value
- // 4. Report matches
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement