9
9
use core:: { array, iter, mem:: MaybeUninit } ;
10
10
11
11
use crate :: {
12
- file_format:: pe, future:: retry, signature:: Signature , string:: ArrayCString , Address , Address32 ,
13
- Address64 , Error , PointerSize , Process ,
12
+ file_format:: { macho, pe} ,
13
+ future:: retry,
14
+ signature:: Signature ,
15
+ string:: ArrayCString ,
16
+ Address , Address32 , Address64 , Error , PointerSize , Process ,
14
17
} ;
15
18
16
19
const CSTR : usize = 128 ;
@@ -30,33 +33,52 @@ pub struct SceneManager {
30
33
impl SceneManager {
31
34
/// Attaches to the scene manager in the given process.
32
35
pub fn attach ( process : & Process ) -> Option < Self > {
33
- const SIG_64_BIT : Signature < 13 > = Signature :: new ( "48 83 EC 20 4C 8B ?5 ???????? 33 F6" ) ;
36
+ const SIG_64_BIT_PE : Signature < 13 > = Signature :: new ( "48 83 EC 20 4C 8B ?5 ???????? 33 F6" ) ;
37
+ const SIG_64_BIT_MACHO : Signature < 13 > =
38
+ Signature :: new ( "41 54 53 50 4C 8B ?5 ???????? 41 83" ) ;
34
39
const SIG_32_1 : Signature < 12 > = Signature :: new ( "55 8B EC 51 A1 ???????? 53 33 DB" ) ;
35
40
const SIG_32_2 : Signature < 6 > = Signature :: new ( "53 8D 41 ?? 33 DB" ) ;
36
41
const SIG_32_3 : Signature < 14 > = Signature :: new ( "55 8B EC 83 EC 18 A1 ???????? 33 C9 53" ) ;
37
42
38
- let unity_player = process. get_module_range ( "UnityPlayer.dll" ) . ok ( ) ?;
43
+ let ( unity_player, format) = [
44
+ ( "UnityPlayer.dll" , BinaryFormat :: PE ) ,
45
+ ( "UnityPlayer.dylib" , BinaryFormat :: MachO ) ,
46
+ ]
47
+ . into_iter ( )
48
+ . find_map ( |( name, format) | Some ( ( process. get_module_range ( name) . ok ( ) ?, format) ) ) ?;
39
49
40
- let pointer_size = match pe :: MachineType :: read ( process , unity_player . 0 ) ? {
41
- pe :: MachineType :: X86_64 => PointerSize :: Bit64 ,
42
- _ => PointerSize :: Bit32 ,
50
+ let pointer_size = match format {
51
+ BinaryFormat :: PE => pe :: MachineType :: read ( process , unity_player . 0 ) ? . pointer_size ( ) ? ,
52
+ BinaryFormat :: MachO => macho :: pointer_size ( process , unity_player ) ? ,
43
53
} ;
44
54
45
55
let is_il2cpp = process. get_module_address ( "GameAssembly.dll" ) . is_ok ( ) ;
46
56
47
57
// There are multiple signatures that can be used, depending on the version of Unity
48
58
// used in the target game.
49
- let base_address: Address = if pointer_size == PointerSize :: Bit64 {
50
- let addr = SIG_64_BIT . scan_process_range ( process, unity_player) ? + 7 ;
51
- addr + 0x4 + process. read :: < i32 > ( addr) . ok ( ) ?
52
- } else if let Some ( addr) = SIG_32_1 . scan_process_range ( process, unity_player) {
53
- process. read :: < Address32 > ( addr + 5 ) . ok ( ) ?. into ( )
54
- } else if let Some ( addr) = SIG_32_2 . scan_process_range ( process, unity_player) {
55
- process. read :: < Address32 > ( addr. add_signed ( -4 ) ) . ok ( ) ?. into ( )
56
- } else if let Some ( addr) = SIG_32_3 . scan_process_range ( process, unity_player) {
57
- process. read :: < Address32 > ( addr + 7 ) . ok ( ) ?. into ( )
58
- } else {
59
- return None ;
59
+ let base_address: Address = match ( pointer_size, format) {
60
+ ( PointerSize :: Bit64 , BinaryFormat :: PE ) => {
61
+ let addr = SIG_64_BIT_PE . scan_process_range ( process, unity_player) ? + 7 ;
62
+ addr + 0x4 + process. read :: < i32 > ( addr) . ok ( ) ?
63
+ }
64
+ ( PointerSize :: Bit64 , BinaryFormat :: MachO ) => {
65
+ let addr = SIG_64_BIT_MACHO . scan_process_range ( process, unity_player) ? + 7 ;
66
+ addr + 0x4 + process. read :: < i32 > ( addr) . ok ( ) ?
67
+ }
68
+ ( PointerSize :: Bit32 , BinaryFormat :: PE ) => {
69
+ if let Some ( addr) = SIG_32_1 . scan_process_range ( process, unity_player) {
70
+ process. read :: < Address32 > ( addr + 5 ) . ok ( ) ?. into ( )
71
+ } else if let Some ( addr) = SIG_32_2 . scan_process_range ( process, unity_player) {
72
+ process. read :: < Address32 > ( addr. add_signed ( -4 ) ) . ok ( ) ?. into ( )
73
+ } else if let Some ( addr) = SIG_32_3 . scan_process_range ( process, unity_player) {
74
+ process. read :: < Address32 > ( addr + 7 ) . ok ( ) ?. into ( )
75
+ } else {
76
+ return None ;
77
+ }
78
+ }
79
+ _ => {
80
+ return None ;
81
+ }
60
82
} ;
61
83
62
84
let offsets = Offsets :: new ( pointer_size) ;
@@ -429,6 +451,12 @@ impl Transform {
429
451
}
430
452
}
431
453
454
+ #[ derive( Copy , Clone , PartialEq , Hash , Debug ) ]
455
+ enum BinaryFormat {
456
+ PE ,
457
+ MachO ,
458
+ }
459
+
432
460
struct Offsets {
433
461
scene_count : u8 ,
434
462
active_scene : u8 ,
0 commit comments