Skip to content

Commit 7b0b4a9

Browse files
committed
Add fist version of the mod loading API
1 parent 33f80d1 commit 7b0b4a9

File tree

3 files changed

+199
-0
lines changed

3 files changed

+199
-0
lines changed

Assets/Scripts/ModSystem/IMod.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
namespace ModSystem
2+
{
3+
public interface IMod
4+
{
5+
string ModId { get; }
6+
string ModVersion { get; }
7+
string ModAuthor { get; }
8+
string IsMpCompatible { get; }
9+
}
10+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Reflection;
5+
using System.Security.AccessControl;
6+
using Mono.Cecil;
7+
using UnityEngine;
8+
9+
namespace ModSystem
10+
{
11+
public class ModLoader
12+
{
13+
public Dictionary<string, IMod> LoadedMods { get; } = new();
14+
15+
public ModLoader(bool loadNow = false)
16+
{
17+
if (!loadNow) return;
18+
LoadMods();
19+
}
20+
21+
public void LoadMods()
22+
{
23+
var modPath = Path.Combine(Application.dataPath, "../Mods");
24+
25+
foreach (var dll in Directory.GetFiles(modPath, "*.dll"))
26+
{
27+
if (!ModScanner.IsModSafe(dll))
28+
{
29+
Debug.LogWarning($"Mod {Path.GetFileName(dll)} blocked due to unsafe usage.");
30+
continue;
31+
}
32+
33+
var assembly = Assembly.LoadFile(dll);
34+
foreach (var type in assembly.GetTypes())
35+
{
36+
if (!typeof(IMod).IsAssignableFrom(type) || type.IsInterface || type.IsAbstract) continue;
37+
var mod = (IMod)Activator.CreateInstance(type);
38+
LoadedMods.Add(mod.ModId, mod);
39+
Debug.Log($"Mod loaded: {mod.ModId}");
40+
}
41+
}
42+
}
43+
44+
public IMod GetMod(string modId)
45+
{
46+
if (LoadedMods.TryGetValue(modId, out var mod)) return mod;
47+
Debug.LogWarning($"Mod {modId} is not loaded.");
48+
return null;
49+
}
50+
}
51+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System;
2+
using System.Linq;
3+
using Mono.Cecil;
4+
using UnityEngine;
5+
6+
namespace ModSystem
7+
{
8+
public class ModScanner
9+
{
10+
private static readonly string[] DangerousTypes =
11+
{
12+
// Access Control & IO
13+
"System.Security.AccessControl.FileSystemAccessRule",
14+
"System.Security.AccessControl",
15+
"System.IO.FileInfo",
16+
"System.IO.FileStream",
17+
"System.IO.DirectoryInfo",
18+
"System.Security.AccessControl.DirectorySecurity",
19+
"System.IO.File",
20+
"System.IO",
21+
22+
// Networking
23+
"System.Net",
24+
25+
// Reflection & Code Emission
26+
"System.Reflection.Emit",
27+
"System.Reflection",
28+
29+
// Debugging & Diagnostics
30+
"System.Diagnostics",
31+
32+
// Interop (dangerous when interacting with native code)
33+
"System.Runtime.InteropServices",
34+
35+
// Compression (could be used to manipulate files)
36+
"System.IO.Compression",
37+
38+
// Threading & Tasks
39+
"System.Threading",
40+
41+
// Cryptography
42+
"System.Security.Cryptography",
43+
44+
// System management (WMI, etc.)
45+
"System.Management",
46+
47+
// Isolated storage (could be misused for sandboxing bypass)
48+
"System.IO.IsolatedStorage"
49+
};
50+
51+
private static readonly string[] DangerousMethods =
52+
{
53+
// Dangerous Access Control methods
54+
"SetAccessControl", // Can be used to modify file/directory security settings
55+
"AddAccessRule", // Adds a rule to the security settings, potentially granting more access
56+
"RemoveAccessRule", // Removes a rule that could restrict access, allowing broader access
57+
"SetAccessRule", // Sets a new access rule, overriding security permissions
58+
"GetAccessControl", // Can be used to read or modify file/directory security settings
59+
60+
// Dangerous File/Directory methods
61+
"CreateDirectory", // Creates a new directory, could be used to create files outside the game folder
62+
"Delete", // Deletes files or directories, could be used maliciously
63+
"Copy", // Copies files or directories, could be used to move files outside the allowed directories
64+
"Move", // Moves files or directories
65+
"AppendAllText", // Could write to files outside the game directory
66+
"WriteAllBytes", // Could write to files outside the game directory
67+
68+
// Process management methods (external execution)
69+
"Start", // Starts an external process, could run unauthorized programs
70+
"GetProcesses", // Could list all processes on the system
71+
"Kill", // Kills processes, could interfere with system processes
72+
73+
// Reflection-based methods (dangerous for code injection)
74+
"Emit", // Generates MSIL code dynamically, allowing code injection
75+
"Invoke", // Invokes methods dynamically, potentially executing malicious code
76+
"Load", // Loads assemblies dynamically, could load unauthorized or modified code
77+
"LoadFrom", // Loads an assembly from a file path, possibly from outside the game folder
78+
"GetExecutingAssembly", // Could be used to inspect or load other assemblies
79+
80+
// Networking methods (external access)
81+
"Create", // Creates a network request, could connect to unauthorized servers
82+
"GetResponse", // Gets a response from a network request, could send sensitive data
83+
"BeginGetResponse", // Begins a network request asynchronously
84+
"Connect", // Connects to a network socket, potentially to external systems
85+
"Send", // Sends data over a network socket, could send sensitive or unauthorized data
86+
87+
// Cryptographic methods (could be misused)
88+
"Aes.Create", // Creates a new AES encryption instance, could be used to hide malicious code
89+
"RSA.Create", // Creates a new RSA encryption instance
90+
"MD5.Create", // Creates a new MD5 hashing instance, could be used to hash files
91+
"HMACSHA256.Create", // Creates a new HMACSHA256 hashing instance, could be used to verify unauthorized data
92+
93+
// Threading methods (can be used to manipulate or hijack execution)
94+
"Start", // Starts a thread, could be used to run malicious code in parallel
95+
"Join", // Blocks the current thread until another thread completes, could cause hangs or exploits
96+
"Run", // Starts a new task, could be used for malicious asynchronous behavior
97+
"Wait" // Blocks the current thread until a task completes, could be used for denial-of-service attacks
98+
};
99+
100+
101+
public static bool IsModSafe(string dllPath)
102+
{
103+
try
104+
{
105+
var assembly = AssemblyDefinition.ReadAssembly(dllPath);
106+
foreach (var type in assembly.MainModule.Types)
107+
{
108+
// Check if any type is from a dangerous namespace or class
109+
if (DangerousTypes.Any(dangerousType => type.FullName.Contains(dangerousType)))
110+
{
111+
Debug.LogWarning($"[SECURITY] Dangerous type found in mod: {type.FullName}");
112+
return false; // Reject mod with dangerous type
113+
}
114+
115+
// Check if any method references dangerous access control methods
116+
foreach (var method in type.Methods)
117+
if (method.HasBody)
118+
foreach (var instruction in method.Body.Instructions)
119+
if (instruction.Operand is MethodReference methodRef)
120+
if (DangerousMethods.Any(dangerousMethod =>
121+
methodRef.FullName.Contains(dangerousMethod)))
122+
{
123+
Debug.LogWarning(
124+
$"[SECURITY] Dangerous method call detected: {methodRef.FullName}");
125+
return false; // Reject mod with dangerous method call
126+
}
127+
}
128+
}
129+
catch (Exception ex)
130+
{
131+
Debug.LogError($"[SECURITY] Failed to inspect mod: {dllPath}\n{ex.Message}");
132+
return false;
133+
}
134+
135+
return true;
136+
}
137+
}
138+
}

0 commit comments

Comments
 (0)