Skip to content

Commit

Permalink
Support Mac SceneManager without std
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKnauth committed Sep 23, 2023
1 parent 1c1ab3f commit 795d399
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 23 deletions.
44 changes: 29 additions & 15 deletions src/file_format/macho.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
//! Support for parsing MachO files
use crate::Process;
use crate::{Process, Address};

use core::mem;

use std::{fs::File, io::Read};
// Magic mach-o header constants from:
// https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html
const MH_MAGIC_32: u32 = 0xfeedface;
const MH_CIGAM_32: u32 = 0xcefaedfe;
const MH_MAGIC_64: u32 = 0xfeedfacf;
const MH_CIGAM_64: u32 = 0xcffaedfe;

struct MachOFormatOffsets {
number_of_commands: usize,
Expand Down Expand Up @@ -35,20 +40,29 @@ impl MachOFormatOffsets {
}
}

/// Determines whether a MachO process is 64-bit or 32-bit
pub fn is_64_bit(process: &Process) -> Option<bool> {
// Magic mach-o header constants from:
// https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html
const MH_MAGIC_32: u32 = 0xfeedface;
const MH_CIGAM_32: u32 = 0xcefaedfe;
const MH_MAGIC_64: u32 = 0xfeedfacf;
const MH_CIGAM_64: u32 = 0xcffaedfe;
/// Scans the range for a page that begins with MachO Magic
pub fn scan_macho_page(process: &Process, range: (Address, u64)) -> Option<Address> {
const PAGE_SIZE: u64 = 0x1000;
let (addr, len) = range;
// negation mod PAGE_SIZE
let distance_to_page = (PAGE_SIZE - (addr.value() % PAGE_SIZE)) % PAGE_SIZE;
// round up to the next multiple of PAGE_SIZE
let first_page = addr + distance_to_page;
for i in 0..((len - distance_to_page) / PAGE_SIZE) {
let a = first_page + (i * PAGE_SIZE);
match process.read::<u32>(a) {
Ok(MH_MAGIC_64 | MH_CIGAM_64 | MH_MAGIC_32 | MH_CIGAM_32) => {
return Some(a);
}
_ => ()
}
}
None
}

let process_path = process.get_path().ok()?;
let mut process_file = File::open(process_path).ok()?;
let mut buffer: [u8; 4] = [0; 4];
process_file.read_exact(&mut buffer).ok();
let magic: u32 = bytemuck::checked::try_from_bytes(&buffer).ok().cloned()?;
/// Determines whether a MachO header at the address is 64-bit or 32-bit
pub fn is_64_bit(process: &Process, address: Address) -> Option<bool> {
let magic: u32 = process.read(address).ok()?;
match magic {
MH_MAGIC_64 | MH_CIGAM_64 => Some(true),
MH_MAGIC_32 | MH_CIGAM_32 => Some(false),
Expand Down
1 change: 0 additions & 1 deletion src/file_format/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
pub mod elf;
pub mod pe;
#[cfg(feature = "std")]
pub mod macho;
2 changes: 1 addition & 1 deletion src/game_engine/unity/mono.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl Module {

#[cfg(feature = "std")]
fn attach_dylib(process: &Process, version: Version, module_range: (Address, u64)) -> Option<Self> {
let is_64_bit = macho::is_64_bit(process)?;
let is_64_bit = macho::is_64_bit(process, macho::scan_macho_page(process, module_range)?)?;
let offsets = Offsets::new(version, is_64_bit, BinaryFormat::MachO);

let process_path = process.get_path().ok()?;
Expand Down
8 changes: 2 additions & 6 deletions src/game_engine/unity/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ use core::{array, mem::MaybeUninit};
use crate::{
file_format::pe, future::retry, signature::Signature, string::ArrayCString, Address, Address32,
Address64, Error, Process,
file_format::macho,
};

#[cfg(feature = "std")]
use crate::file_format::macho;

/// The scene manager allows you to easily identify the current scene loaded in
/// the attached Unity game.
///
Expand All @@ -32,7 +30,6 @@ impl SceneManager {
if let Ok(unity_player) = process.get_module_range("UnityPlayer.dll") {
return Self::attach_dll(process, unity_player);
}
#[cfg(feature = "std")]
if let Ok(unity_player) = process.get_module_range("UnityPlayer.dylib") {
return Self::attach_dylib(process, unity_player);
}
Expand Down Expand Up @@ -71,11 +68,10 @@ impl SceneManager {
})
}

#[cfg(feature = "std")]
fn attach_dylib(process: &Process, unity_player: (Address, u64)) -> Option<Self> {
const SIG_64_BIT_DYLIB: Signature<13> = Signature::new("41 54 53 50 4C 8B ?5 ???????? 41 83");

let is_64_bit = macho::is_64_bit(process)?;
let is_64_bit = macho::is_64_bit(process, macho::scan_macho_page(process, unity_player)?)?;
let is_il2cpp = false;

let address = if is_64_bit {
Expand Down

0 comments on commit 795d399

Please sign in to comment.