forked from drtchops/asl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcornerstone.asl
More file actions
140 lines (117 loc) · 3.69 KB
/
cornerstone.asl
File metadata and controls
140 lines (117 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
v0.1
*/
state("Cornerstone")
{
int isLoadingLevel : 0xA33124, 0x74; // Unity's Application.isloadinglevel
}
startup
{
vars.FreeMemory = (Action<Process>)(p =>
{
p.FreeMemory((IntPtr)vars.isFmodInitPtr);
p.FreeMemory((IntPtr)vars.injectedFuncPtr);
p.FreeMemory((IntPtr)vars.oInitFmodPtr);
});
vars.CopyMemory = (Action<Process, IntPtr, IntPtr, int>)((p, src, dest, nbr) =>
{
var bytes = p.ReadBytes(src, nbr);
p.WriteBytes(dest, bytes);
});
vars.CheckInitFmodPtr = (Func<Process, IntPtr, bool>)((p, ptr) =>
{
if (ptr == IntPtr.Zero)
return false;
byte[] bytes;
if (!p.ReadBytes(ptr, 3, out bytes))
return false;
var expectedBytes = new byte[] { 0x55, 0x8B, 0xEC };
if (!bytes.SequenceEqual(expectedBytes))
return false;
return true;
});
}
init
{
// find the FMOD_Listener:Initialize function
var initFmodDeepPtr = new DeepPointer("mono.dll", 0x1F58F4, 0x4DC, 0x154);
uint ptr;
if (!initFmodDeepPtr.Deref<uint>(game, out ptr))
throw new Exception("Couldn't read the pointer path for FMOD_Listener:Initialize");
// check the pointer because it can be wrong while starting the game
vars.initFmodPtr = ptr + 0x2F0;
print("FMOD_Listener:Initialize : " + vars.initFmodPtr.ToString("X"));
if (!vars.CheckInitFmodPtr(game, (IntPtr)vars.initFmodPtr))
throw new Exception("Invalid FMOD_Listener:Initialize pointer");
vars.isFmodInitPtr = game.AllocateMemory(sizeof(int)); // our injected bool
var isFmodInitPtrBytes = BitConverter.GetBytes((uint)vars.isFmodInitPtr);
// injected function body
var initFmodDetourBytes = new List<byte>() {
0x55, // push ebp
0x8B, 0xEC, // mov ebp, esp
0xFF, 0x75, 0x08, // push ebp+8
0xC7, 0x05 // mov dword ptr [isFmodInitPtr], 01
};
initFmodDetourBytes.AddRange(isFmodInitPtrBytes);
initFmodDetourBytes.AddRange(new byte[] { 1, 0, 0, 0 });
var callOffset = initFmodDetourBytes.Count;
initFmodDetourBytes.AddRange(new byte[] {
255, 255, 255, 255, 255, // call oInitFmodPtr (placeholder)
0xC7, 0x05 // mov dword ptr [isFmodInitPtr], 00
});
initFmodDetourBytes.AddRange(isFmodInitPtrBytes);
initFmodDetourBytes.AddRange(new byte[] {
0, 0, 0, 0,
0xC9, // leave
0xC3 // ret
});
vars.injectedFuncPtr = game.AllocateMemory(initFmodDetourBytes.Count);
game.Suspend(); // it'd crash if it executed code we're in the middle of changing
try
{
// install hook
vars.oInitFmodPtr = game.WriteDetour((IntPtr)vars.initFmodPtr, 5, (IntPtr)vars.injectedFuncPtr);
// write the body of the injected function
game.WriteBytes((IntPtr)vars.injectedFuncPtr, initFmodDetourBytes.ToArray());
// replace the call placeholder
game.WriteCallInstruction((IntPtr)vars.injectedFuncPtr + callOffset, (IntPtr)vars.oInitFmodPtr);
}
catch
{
vars.FreeMemory(game);
throw;
}
finally
{
game.Resume();
}
print("isFmodInitPtr: " + vars.isFmodInitPtr.ToString("X"));
}
shutdown
{
if (game == null)
return;
game.Suspend();
try
{
// restore function prologue
vars.CopyMemory(game, (IntPtr)vars.oInitFmodPtr, (IntPtr)vars.initFmodPtr, 5);
}
catch
{
throw;
}
finally
{
game.Resume();
vars.FreeMemory(game);
}
}
update
{
vars.isFmodInit = game.ReadValue<bool>((IntPtr)vars.isFmodInitPtr);
}
isLoading
{
return current.isLoadingLevel != 0 || vars.isFmodInit;
}