Tutorial Loading external DLL from the server (Mono backend Unity game)

AndnixSH

PMT Elite Modder
Original poster
Staff member
Modding-Team
Jun 27, 2017
4,757
301,563
1,213
Modding World
Back in the DLL modding days, some game developers like to hide external DLL inside game assets or load from server, leaving nothing useful in Assembly-Csharp.dll. This slows down modders, but in fact it's not really hard to figure out

I know DLL are dead now, just take it as educational purposes

Let's take this game as an example Romance of Heroes:Realtime 3v3 for Android - APK Download
It loads DLL from encrypted xgame.ezfun file inside APK

Just dump memory using GameGuardian to get the decrypted extra DLL (See tutorial: How to dump decrypted DLL files using GameGuardian (NO ROOT / ROOT) (Android 2.3.3-9.0+) - Platinmods.com - Android & iOS MODs, Mobile Games & Apps)

You would mod it as usually and after that, upload to your own server

Then in Assembly-Csharp.dll, this is the code that loads and decrypt DLL either from locally or from server

C#:
//Class: GameStart
private void LoadDLL()
{
    string url = Application.streamingAssetsPath + "/xgame.ezfun";
    string path = Application.persistentDataPath + "/DLL/xgame.ezfun";
    if (this.CheckUseUpdate())
    {
        using (Stream stream = File.OpenRead(path))
        {
            byte[] array = new byte[stream.Length];
            stream.Read(array, 0, array.Length);
            stream.Close();
            this.InitCry();
            byte[] rawAssembly = this.Decrypte(array);
            Assembly xgameData = Assembly.Load(rawAssembly);
            this.m_xgameData = xgameData;
        }
    }
    else
    {
        WWW www = new WWW(url);
        while (!www.isDone)
        {
        }
        Stream stream2 = new MemoryStream(www.bytes);
        byte[] array2 = new byte[stream2.Length];
        stream2.Read(array2, 0, array2.Length);
        stream2.Close();
        this.InitCry();
        byte[] rawAssembly2 = this.Decrypte(array2);
        Assembly xgameData2 = Assembly.Load(rawAssembly2);
        this.m_xgameData = xgameData2;
    }
}
You then modify the code to load from your server, it's very simple. Avoid calling decryption tho, you don't need it

C#:
private void LoadDLL()
{
    WWW www = new WWW("https://example.com/modded.dll");
    while (!www.isDone)
    {
    }
    MemoryStream memoryStream = new MemoryStream(www.bytes);
    byte[] array2 = new byte[memoryStream.Length];
    memoryStream.Read(array2, 0, array2.Length);
    memoryStream.Close();
    this.InitCry();
    Assembly xgameData2 = Assembly.Load(array2);
    this.m_xgameData = xgameData2;
}
Another example from other games

Original code:

C#:
private void LoadGameDllFinish(string name, AssetBundle bundle)
{
    TextAsset textAsset = (TextAsset)bundle.Load("WuXiaGameE.dll", typeof(TextAsset));
    byte[] bytes = textAsset.bytes;
    this.DecryptBytes(bytes);
    Assembly assembly = Assembly.Load(bytes);
    if (assembly != null)
    {
        Type type = assembly.GetType("WuXiaGame");
        this._gameStart = type.GetMethod("Start");
        this._gameUpdate = type.GetMethod("Update");
        this._gameOnGUI = type.GetMethod("OnGUI");
        this._gameOnApplicationQuit = type.GetMethod("OnApplicationQuit");
        Type[] types = new Type[]
        {
            typeof(bool)
        };
        this._gameOnBecameInvisible = type.GetMethod("OnBecameInvisible");
        this._gameOnBecameVisible = type.GetMethod("OnBecameVisible");
        this._gameOnAppPause = type.GetMethod("OnApplicationPause", types);
        MethodInfo method = type.GetMethod("SetDistributor");
        method.Invoke(null, new object[]
        {
            "XinLangWeiBo"
        });
    }
    if (this._gameStart != null)
    {
        this._gameStart.Invoke(null, null);
    }
    bundle.Unload(true);
}
Modified code:
C#:
private void LoadGameDllFinish(string name, AssetBundle bundle)
{
    TextAsset textAsset = (TextAsset)bundle.Load("WuXiaGameE.dll", typeof(TextAsset));
    this.bytes = textAsset.bytes;
    this.DecryptBytes(this.bytes);
    WWW www = new WWW("https://example.com/modded.dll");
    while (!www.isDone)
    {
    }
    Assembly assembly = Assembly.Load(www.bytes);
    if (assembly != null)
    {
        Type type = assembly.GetType("WuXiaGame");
        this._gameStart = type.GetMethod("Start");
        this._gameUpdate = type.GetMethod("Update");
        this._gameOnGUI = type.GetMethod("OnGUI");
        this._gameOnApplicationQuit = type.GetMethod("OnApplicationQuit");
        Type[] types = new Type[]
        {
            typeof(bool)
        };
        this._gameOnBecameInvisible = type.GetMethod("OnBecameInvisible");
        this._gameOnBecameVisible = type.GetMethod("OnBecameVisible");
        this._gameOnAppPause = type.GetMethod("OnApplicationPause", types);
        type.GetMethod("SetDistributor").Invoke(null, new object[]
        {
            "XinLangWeiBo"
        });
    }
    if (this._gameStart != null)
    {
        this._gameStart.Invoke(null, null);
    }
    bundle.Unload(true);
}
 
Last edited:

Polar.Bear

Platinian
Jul 11, 2021
6
0
1
30
Russia
it will still work as long as the dll loaded from either server or locally
no bro you didn`t understand my question i mean when you said developers like to hide external DLL inside game assets or load from servers, leaving nothing useful in Assembly-Csharp.dll did you meant that developers making another copy of the dlls stored in their server to compare it with the stored dll files so they can know if the stored dll files have been moded or not and if it`s moded then the game won`t work and at the end, a crash will happen or the moded dlls won`t work but the stored one in their server will work or you meant that we will not see any functions we can mod and if that what you meant what should we do?
 

AndnixSH

PMT Elite Modder
Original poster
Staff member
Modding-Team
Jun 27, 2017
4,757
301,563
1,213
Modding World
no bro you didn`t understand my question i mean when you said developers like to hide external DLL inside game assets or load from servers, leaving nothing useful in Assembly-Csharp.dll did you meant that developers making another copy of the dlls stored in their server to compare it with the stored dll files so they can know if the stored dll files have been moded or not and if it`s moded then the game won`t work and at the end, a crash will happen or the moded dlls won`t work but the stored one in their server will work or you meant that we will not see any functions we can mod and if that what you meant what should we do?
I didn't fully understand your question. It is already explained like i said in the thread. If you don't know what i mean, don't proceed
I'm no longer interested in DLL, so i will not investigate it further.