From 07ca23ee42abd662f46090a1e35ca75c5da3ec17 Mon Sep 17 00:00:00 2001 From: HoLLy Date: Sun, 15 Nov 2020 00:20:19 +0100 Subject: [PATCH] Implement read/write memory --- Cargo.toml | 2 +- src/server/commands_request.rs | 47 +++++++++++++++++++++++++ src/server/commands_response.rs | 24 ++++++++++++- src/server/handler.rs | 2 ++ src/server/handlers/windows.rs | 61 ++++++++++++++++++++++++++++++--- src/server/server.rs | 2 ++ 6 files changed, 132 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 113460b..994911b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ bytes = "0.6" log = "0.4.11" pretty_env_logger = "0.4.0" tokio = { version = "0.3.3", features = ["net", "rt-multi-thread", "io-util"] } -winapi = { version = "0.3.9", features = ["processthreadsapi", "tlhelp32"], optional = true } +winapi = { version = "0.3.9", features = ["memoryapi", "processthreadsapi", "tlhelp32"], optional = true } [features] diff --git a/src/server/commands_request.rs b/src/server/commands_request.rs index ddcbac1..890631a 100644 --- a/src/server/commands_request.rs +++ b/src/server/commands_request.rs @@ -161,3 +161,50 @@ impl CERequest for GetSymbolListFromFileRequest { } } } + +#[derive(Debug)] +pub struct ReadProcessMemoryRequest { + pub handle: u32, + pub address: u64, + pub size: u32, + pub compress: bool, +} + +impl CERequest for ReadProcessMemoryRequest { + type Response = ReadProcessMemoryResponse; + + const ID: Command = CMD_READPROCESSMEMORY; + + fn read(buf: &mut dyn Buf) -> Self { + Self { + handle: buf.get_u32_le(), + address: buf.get_u64_le(), + size: buf.get_u32_le(), + compress: buf.get_u8() != 0, + } + } +} + +#[derive(Debug)] +pub struct WriteProcessMemoryRequest { + pub handle: u32, + pub address: u64, + pub data: Vec, +} + +impl CERequest for WriteProcessMemoryRequest { + type Response = WriteProcessMemoryResponse; + + const ID: Command = CMD_WRITEPROCESSMEMORY; + + fn read(buf: &mut dyn Buf) -> Self { + Self { + handle: buf.get_u32_le(), + address: buf.get_u64_le(), + data: { + let len = buf.get_u32_le(); + Vec::from(buf.take(len as usize).bytes()) + }, + } + } +} diff --git a/src/server/commands_response.rs b/src/server/commands_response.rs index c6d693c..1fbfe86 100644 --- a/src/server/commands_response.rs +++ b/src/server/commands_response.rs @@ -85,6 +85,28 @@ pub struct GetSymbolListFromFileResponse; // TODO implement impl CEResponse for GetSymbolListFromFileResponse { fn serialize(self, writer: &mut dyn BufMut) { // writing 0 for now - writer.put_i32(0); + writer.put_i32_le(0); + } +} + +#[derive(Debug)] +pub struct ReadProcessMemoryResponse { + pub data: Vec, +} + +impl CEResponse for ReadProcessMemoryResponse { + fn serialize(self, writer: &mut dyn BufMut) { + writer.put_slice(&self.data[..]); + } +} + +#[derive(Debug)] +pub struct WriteProcessMemoryResponse { + pub written: u32, +} + +impl CEResponse for WriteProcessMemoryResponse { + fn serialize(self, writer: &mut dyn BufMut) { + writer.put_u32_le(self.written); } } diff --git a/src/server/handler.rs b/src/server/handler.rs index fb829e9..8fea626 100644 --- a/src/server/handler.rs +++ b/src/server/handler.rs @@ -12,6 +12,8 @@ pub trait FullHandler: + Handler + Handler + Handler + + Handler + + Handler { fn create() -> Self; } diff --git a/src/server/handlers/windows.rs b/src/server/handlers/windows.rs index c965ad8..f8586cc 100644 --- a/src/server/handlers/windows.rs +++ b/src/server/handlers/windows.rs @@ -1,9 +1,11 @@ use crate::server::{ce_common::*, commands_request::*, commands_response::*, handler::*}; use log::warn; use winapi::{ - shared::minwindef::FALSE, + shared::minwindef::{FALSE, LPCVOID, LPVOID}, um::{ handleapi::CloseHandle, + memoryapi::ReadProcessMemory, + memoryapi::WriteProcessMemory, processthreadsapi::OpenProcess, tlhelp32::{ CreateToolhelp32Snapshot, Module32First, Module32Next, Process32First, Process32Next, @@ -50,7 +52,7 @@ where F: FnOnce(HANDLE, LPPROCESSENTRY32) -> i32, { let mut entry = std::mem::MaybeUninit::uninit().assume_init(); - let response = func(std::mem::transmute(handle), &mut entry); + let response = func(handle as HANDLE, &mut entry); if response != 0 { Process32Response { @@ -81,7 +83,7 @@ where F: FnOnce(HANDLE, LPMODULEENTRY32) -> i32, { let mut entry = std::mem::MaybeUninit::uninit().assume_init(); - let response = func(std::mem::transmute(handle), &mut entry); + let response = func(handle as HANDLE, &mut entry); if response != 0 { Module32Response { @@ -99,7 +101,7 @@ where impl Handler for WindowsHandler { fn handle(&self, req: CloseHandleRequest) -> I32Response { unsafe { - let response = CloseHandle(std::mem::transmute(req.handle)); + let response = CloseHandle(req.handle as HANDLE); I32Response { response } } @@ -133,3 +135,54 @@ impl Handler for WindowsHandler { GetSymbolListFromFileResponse } } + +impl Handler for WindowsHandler { + fn handle(&self, req: ReadProcessMemoryRequest) -> ReadProcessMemoryResponse { + let mut buffer = vec![0u8; req.size as usize]; + let mut bytes_read = 0; + let _resp = unsafe { + ReadProcessMemory( + req.handle as HANDLE, + req.address as LPVOID, + buffer.as_mut_ptr() as LPVOID, + req.size as usize, + &mut bytes_read, + ) + }; + if req.compress { + todo!() + } else { + ReadProcessMemoryResponse { data: buffer } + } + } +} + +impl Handler for WindowsHandler { + fn handle(&self, req: WriteProcessMemoryRequest) -> WriteProcessMemoryResponse { + unsafe { + let mut written = 0usize; + let mut data = req.data; + let success = WriteProcessMemory( + req.handle as HANDLE, + req.address as LPVOID, + data.as_mut_ptr() as LPCVOID, + data.len(), + &mut written, + ); + + if success == 0 { + warn!("Writing memory failed"); + } else if written != data.len() { + warn!( + "Expected to write {} bytes but wrote {}", + data.len(), + written + ); + } + + WriteProcessMemoryResponse { + written: written as u32, + } + } + } +} diff --git a/src/server/server.rs b/src/server/server.rs index 4ce7799..847b930 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -94,6 +94,8 @@ impl CheatEngineConnection { GetArchitectureRequest, OpenProcessRequest, GetSymbolListFromFileRequest, + ReadProcessMemoryRequest, + WriteProcessMemoryRequest, ) } }