Skip to content

Commit

Permalink
Changed: overwrite_allocated_code now has 'ex' variant.
Browse files Browse the repository at this point in the history
This is a breaking change as signature changed, but nobody's using this lib yet so I don't care.
  • Loading branch information
Sewer56 committed Nov 26, 2023
1 parent f2e2a30 commit 354acc5
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 42 deletions.
10 changes: 7 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -227,21 +227,25 @@ Note: Rust/C port also works with FreeBSD (untested), and has partial [(limited)
=== "Rust"

```rust
Self::overwrite_allocated_code(address, size, |addr, size| {
Self::overwrite_allocated_code(source, target, size);
Self::overwrite_allocated_code_ex(source, target, size, |src, tgt, sz| {
// Do stuff with executable code
});
```

=== "C/C++"

```cpp
void do_stuff_with_executable_code(char* addr, size_t size) {
void do_stuff_with_executable_code(char* source, char* target, size_t size) {
// Modify executable code in buffer
}

overwrite_allocated_code(address, size, do_stuff_with_executable_code);
overwrite_allocated_code(source, target, size);
overwrite_allocated_code_ex(source, target, size, do_stuff_with_executable_code);
```

Alternative overload also allows you to pass a 'context' variable.

!!! warning "Not currently available in C# version. Submit an issue request or PR if you need this."

## Community Feedback
Expand Down
2 changes: 1 addition & 1 deletion src-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "reloaded-memory-buffers"
version = "3.2.2"
version = "3.3.0"
edition = "2021"
authors = [ "sewer56" ]
description = "Shared, Concurrent, Permanent Memory Allocator tied to Process Lifetime"
Expand Down
51 changes: 41 additions & 10 deletions src-rust/src/buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::utilities::disable_write_xor_execute::{
};
use crate::utilities::icache_clear::clear_instruction_cache;
use crate::utilities::mathematics::round_up;
use core::ptr::copy_nonoverlapping;
use core::u8;
use std::ptr::NonNull;

Expand Down Expand Up @@ -126,9 +127,9 @@ impl Buffers {
///
/// # Parameters
///
/// * `address` - The address of the code your callback will overwrite.
/// * `size` - The size of the code your callback will overwrite.
/// * `callback` - Your method to overwrite the code.
/// * `source` - Source address to copy bytes from.
/// * `target` - Where these bytes should be copied to. This should be an address inside a buffer.
/// * `size` - The size of the data to copy.
///
/// # Safety
///
Expand All @@ -139,15 +140,45 @@ impl Buffers {
///
/// This function can be skipped on some combinations (e.g. Windows/Linux/macOS x86/x64). But
/// should not be skipped on non-x86 architectures.
pub fn overwrite_allocated_code(
address: *const u8,
pub unsafe fn overwrite_allocated_code(source: *const u8, target: *mut u8, size: usize) {
disable_write_xor_execute(target, size);
copy_nonoverlapping(source, target, size);
restore_write_xor_execute(target, size);
clear_instruction_cache(target, target.wrapping_add(size));
}

/// Call this method in order to safely be able to overwrite existing code that was
/// allocated by the library inside one of its buffers. (e.g. Hooking/detours code.)
///
/// This callback handles various edge cases, (such as flushing caches), and flipping page permissions
/// on relevant platforms.
///
/// # Parameters
///
/// * `source` - Source address to copy bytes from.
/// * `target` - Where these bytes should be copied to. This should be an address inside a buffer.
/// * `size` - The size of the data to copy.
/// * `callback` - Your method to overwrite the code present there.
///
/// # Safety
///
/// Only use this with addresses allocated inside a Reloaded.Memory.Buffers buffer.
/// Usage with any other memory is undefined behaviour.
///
/// # Remarks
///
/// This function can be skipped on some combinations (e.g. Windows/Linux/macOS x86/x64). But
/// should not be skipped on non-x86 architectures.
pub fn overwrite_allocated_code_ex(
source: *const u8,
target: *mut u8,
size: usize,
callback: fn(*const u8, usize),
callback: fn(*const u8, *mut u8, usize),
) {
disable_write_xor_execute(address, size);
callback(address, size);
restore_write_xor_execute(address, size);
clear_instruction_cache(address as *mut u8, address.wrapping_add(size));
disable_write_xor_execute(target, size);
callback(source, target, size);
restore_write_xor_execute(target, size);
clear_instruction_cache(target, target.wrapping_add(size));
}
}

Expand Down
78 changes: 55 additions & 23 deletions src-rust/src/c/buffers_c_buffers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use std::{
ffi::{c_char, CString},
mem::{self, ManuallyDrop},
ptr,
use super::{
buffers_c_locatoritem::{
locatoritem_append_bytes, locatoritem_bytes_left, locatoritem_can_use,
locatoritem_is_allocated, locatoritem_is_taken, locatoritem_lock, locatoritem_max_address,
locatoritem_min_address, locatoritem_try_lock, locatoritem_unlock,
},
buffers_fnptr::BuffersFunctions,
};

use crate::{
buffers::Buffers,
structs::{
Expand All @@ -16,14 +18,11 @@ use crate::{
icache_clear::clear_instruction_cache,
},
};

use super::{
buffers_c_locatoritem::{
locatoritem_append_bytes, locatoritem_bytes_left, locatoritem_can_use,
locatoritem_is_allocated, locatoritem_is_taken, locatoritem_lock, locatoritem_max_address,
locatoritem_min_address, locatoritem_try_lock, locatoritem_unlock,
},
buffers_fnptr::BuffersFunctions,
use core::ptr::copy_nonoverlapping;
use std::{
ffi::{c_char, CString},
mem::{self, ManuallyDrop},
ptr,
};

/// The result of making an allocation.
Expand Down Expand Up @@ -282,9 +281,9 @@ pub extern "C" fn utilities_clear_instruction_cache(start: *mut u8, end: *mut u8
///
/// # Parameters
///
/// * `address` - The address of the code your callback will overwrite.
/// * `size` - The size of the code your callback will overwrite.
/// * `callback` - Your method to overwrite the code.
/// * `source` - Source address to copy bytes from.
/// * `target` - Where these bytes should be copied to. This should be an address inside a buffer.
/// * `size` - The size of the data to copy.
///
/// # Safety
///
Expand All @@ -295,15 +294,47 @@ pub extern "C" fn utilities_clear_instruction_cache(start: *mut u8, end: *mut u8
///
/// This function can be skipped on some combinations (e.g. Windows/Linux/macOS x86/x64). But
/// should not be skipped on non-x86 architectures.
pub extern "C" fn overwrite_allocated_code(
address: *const u8,
#[no_mangle]
pub unsafe extern "C" fn overwrite_allocated_code(source: *const u8, target: *mut u8, size: usize) {
disable_write_xor_execute(target, size);
copy_nonoverlapping(source, target, size);
restore_write_xor_execute(target, size);
clear_instruction_cache(target, source.wrapping_add(size));
}

/// Call this method in order to safely be able to overwrite existing code that was
/// allocated by the library inside one of its buffers. (e.g. Hooking/detours code.)
///
/// This callback handles various edge cases, (such as flushing caches), and flipping page permissions
/// on relevant platforms.
///
/// # Parameters
///
/// * `source` - Source address to copy bytes from.
/// * `target` - Where these bytes should be copied to. This should be an address inside a buffer.
/// * `size` - The size of the data to copy.
/// * `callback` - Your method to overwrite the code present there.
///
/// # Safety
///
/// Only use this with addresses allocated inside a Reloaded.Memory.Buffers buffer.
/// Usage with any other memory is undefined behaviour.
///
/// # Remarks
///
/// This function can be skipped on some combinations (e.g. Windows/Linux/macOS x86/x64). But
/// should not be skipped on non-x86 architectures.
#[no_mangle]
pub extern "C" fn overwrite_allocated_code_ex(
source: *const u8,
target: *mut u8,
size: usize,
callback: extern "C" fn(*const u8, usize),
callback: extern "C" fn(*const u8, *mut u8, usize),
) {
disable_write_xor_execute(address, size);
callback(address, size);
restore_write_xor_execute(address, size);
clear_instruction_cache(address as *mut u8, address.wrapping_add(size));
disable_write_xor_execute(target, size);
callback(source, target, size);
restore_write_xor_execute(target, size);
clear_instruction_cache(target, source.wrapping_add(size));
}

/// Returns all exported functions inside a struct.
Expand Down Expand Up @@ -332,6 +363,7 @@ pub extern "C" fn get_functions() -> BuffersFunctions {
locatoritem_append_bytes,
utilities_clear_instruction_cache,
overwrite_allocated_code,
overwrite_allocated_code_ex,
}
}

Expand Down
37 changes: 33 additions & 4 deletions src-rust/src/c/buffers_fnptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,9 @@ pub struct BuffersFunctions {
///
/// # Parameters
///
/// * `address` - The address of the code your callback will overwrite.
/// * `size` - The size of the code your callback will overwrite.
/// * `callback` - Your method to overwrite the code.
/// * `source` - Source address to copy bytes from.
/// * `target` - Where these bytes should be copied to. This should be an address inside a buffer.
/// * `size` - The size of the data to copy.
///
/// # Safety
///
Expand All @@ -217,5 +217,34 @@ pub struct BuffersFunctions {
/// This function can be skipped on some combinations (e.g. Windows/Linux/macOS x86/x64). But
/// should not be skipped on non-x86 architectures.
pub overwrite_allocated_code:
extern "C" fn(address: *const u8, size: usize, callback: extern "C" fn(*const u8, usize)),
unsafe extern "C" fn(source: *const u8, target: *mut u8, size: usize),

/// Call this method in order to safely be able to overwrite existing code that was
/// allocated by the library inside one of its buffers. (e.g. Hooking/detours code.)
///
/// This callback handles various edge cases, (such as flushing caches), and flipping page permissions
/// on relevant platforms.
///
/// # Parameters
///
/// * `source` - Source address to copy bytes from.
/// * `target` - Where these bytes should be copied to. This should be an address inside a buffer.
/// * `size` - The size of the data to copy.
/// * `callback` - Your method to overwrite the code present there.
///
/// # Safety
///
/// Only use this with addresses allocated inside a Reloaded.Memory.Buffers buffer.
/// Usage with any other memory is undefined behaviour.
///
/// # Remarks
///
/// This function can be skipped on some combinations (e.g. Windows/Linux/macOS x86/x64). But
/// should not be skipped on non-x86 architectures.
pub overwrite_allocated_code_ex: extern "C" fn(
source: *const u8,
target: *mut u8,
size: usize,
callback: extern "C" fn(*const u8, *mut u8, usize),
),
}

0 comments on commit 354acc5

Please sign in to comment.