Skip to content

Commit 795d399

Browse files
committed
Support Mac SceneManager without std
1 parent 1c1ab3f commit 795d399

File tree

4 files changed

+32
-23
lines changed

4 files changed

+32
-23
lines changed

src/file_format/macho.rs

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
//! Support for parsing MachO files
22
3-
use crate::Process;
3+
use crate::{Process, Address};
44

55
use core::mem;
66

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

914
struct MachOFormatOffsets {
1015
number_of_commands: usize,
@@ -35,20 +40,29 @@ impl MachOFormatOffsets {
3540
}
3641
}
3742

38-
/// Determines whether a MachO process is 64-bit or 32-bit
39-
pub fn is_64_bit(process: &Process) -> Option<bool> {
40-
// Magic mach-o header constants from:
41-
// https://opensource.apple.com/source/xnu/xnu-4570.71.2/EXTERNAL_HEADERS/mach-o/loader.h.auto.html
42-
const MH_MAGIC_32: u32 = 0xfeedface;
43-
const MH_CIGAM_32: u32 = 0xcefaedfe;
44-
const MH_MAGIC_64: u32 = 0xfeedfacf;
45-
const MH_CIGAM_64: u32 = 0xcffaedfe;
43+
/// Scans the range for a page that begins with MachO Magic
44+
pub fn scan_macho_page(process: &Process, range: (Address, u64)) -> Option<Address> {
45+
const PAGE_SIZE: u64 = 0x1000;
46+
let (addr, len) = range;
47+
// negation mod PAGE_SIZE
48+
let distance_to_page = (PAGE_SIZE - (addr.value() % PAGE_SIZE)) % PAGE_SIZE;
49+
// round up to the next multiple of PAGE_SIZE
50+
let first_page = addr + distance_to_page;
51+
for i in 0..((len - distance_to_page) / PAGE_SIZE) {
52+
let a = first_page + (i * PAGE_SIZE);
53+
match process.read::<u32>(a) {
54+
Ok(MH_MAGIC_64 | MH_CIGAM_64 | MH_MAGIC_32 | MH_CIGAM_32) => {
55+
return Some(a);
56+
}
57+
_ => ()
58+
}
59+
}
60+
None
61+
}
4662

47-
let process_path = process.get_path().ok()?;
48-
let mut process_file = File::open(process_path).ok()?;
49-
let mut buffer: [u8; 4] = [0; 4];
50-
process_file.read_exact(&mut buffer).ok();
51-
let magic: u32 = bytemuck::checked::try_from_bytes(&buffer).ok().cloned()?;
63+
/// Determines whether a MachO header at the address is 64-bit or 32-bit
64+
pub fn is_64_bit(process: &Process, address: Address) -> Option<bool> {
65+
let magic: u32 = process.read(address).ok()?;
5266
match magic {
5367
MH_MAGIC_64 | MH_CIGAM_64 => Some(true),
5468
MH_MAGIC_32 | MH_CIGAM_32 => Some(false),

src/file_format/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22
33
pub mod elf;
44
pub mod pe;
5-
#[cfg(feature = "std")]
65
pub mod macho;

src/game_engine/unity/mono.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl Module {
139139

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

145145
let process_path = process.get_path().ok()?;

src/game_engine/unity/scene.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ use core::{array, mem::MaybeUninit};
99
use crate::{
1010
file_format::pe, future::retry, signature::Signature, string::ArrayCString, Address, Address32,
1111
Address64, Error, Process,
12+
file_format::macho,
1213
};
1314

14-
#[cfg(feature = "std")]
15-
use crate::file_format::macho;
16-
1715
/// The scene manager allows you to easily identify the current scene loaded in
1816
/// the attached Unity game.
1917
///
@@ -32,7 +30,6 @@ impl SceneManager {
3230
if let Ok(unity_player) = process.get_module_range("UnityPlayer.dll") {
3331
return Self::attach_dll(process, unity_player);
3432
}
35-
#[cfg(feature = "std")]
3633
if let Ok(unity_player) = process.get_module_range("UnityPlayer.dylib") {
3734
return Self::attach_dylib(process, unity_player);
3835
}
@@ -71,11 +68,10 @@ impl SceneManager {
7168
})
7269
}
7370

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

78-
let is_64_bit = macho::is_64_bit(process)?;
74+
let is_64_bit = macho::is_64_bit(process, macho::scan_macho_page(process, unity_player)?)?;
7975
let is_il2cpp = false;
8076

8177
let address = if is_64_bit {

0 commit comments

Comments
 (0)