Discussion Coding bases | Lua | Unity | Frida | Java

RedMundo

Platinian
Hello,

I've been experimenting with hacking and have gotten some results (yes, I got banned! 😅). What initially drew me to this was modding and creating QoL (Quality of Life) features that developers wouldn't implement for us. After addressing enough QoL improvements, I became curious about hacking, and here I am.

Let me go straight to the point with my questions. However, feel free to share your experiences or the methods you used to "fix" similar issues.


1. Game A

I believe this game uses Lua 5.1, but it might also involve LuaJIT. This is where I feel my lack of fundamental coding knowledge. I don’t think LuaJIT is a type of encryption, but I’m unsure about the correct terms. After dumping code from luaL_loadbuffer, I had to convert the output into Lua-readable files.

Code to Intercept and Modify Code (Frida):

Using Frida, I intercept libslua’s luaL_loadbuffer function to extract the game logic (classes and methods). Once the target function is found, I inject or replace the code.

  • Example of a Game Function: (side note: 2 files)
    SQL:
    -- root/../../ArtifactCat.lua
    ArtifactCat = class(BaseCat)
    
    function ArtifactCat:ctor()
    
        self._init_Cat_Pos = Vector3(0, 0, 0)
        self._Cat_Pos = nil
    end
    function ArtifactCat:GetArtSide()
        local artInfo = zzArtMgr:GetArtInfo()
    
        if not artInfo then
            return
        end
    
        local artConf = artConfigs:GetConfig(artInfo.artId)
    
        return artonf.artSide or 0
    end
    
    
    -- @MainGame.lua
    function MainGame:InitGlobal()
        -- (...)
        zzArtMgr = ArtifactCat()
        -- (...)
    end


  • Example of Function Modded: (THIS works)
    SQL:
    -- root/../../ArtifactCat.lua
    function ArtifactCat.GetArtSide(self)
        local artInfo = zzArtMgr:GetArtInfo()
    
        if not artInfo then
            return
        end
    
        local artConf = artConfigs:GetConfig(artInfo.artId)
    
        return 1 --8686: artonf.artSide or 0
    end

  • Attempted Alternative: (This Doesn’t Work)
    SQL:
    -- root/../../ArtifactCat.lua
    function ArtifactCat:GetArtSide(self)
        local artInfo = zzArtMgr:GetArtInfo()
    
        if not artInfo then
            return
        end
    
        local artConf = artConfigs:GetConfig(artInfo.artId)
    
        return 1 --8686: artonf.artSide or 0
    end

Key Point: Colon (:) vs. Dot (.):

I want to better understand why using a colon (:) works, but a dot (.) doesn’t. Is it related to how the function is defined during MainGame:InitGlobal()? I’m curious about this difference and would like guidance on where to look to deepen my understanding.


2. Game B

In this game, dumped files are already Lua-readable. I’m unsure of the Lua version used here. When I tried to inject a simple print("hello world"), it didn’t seem to produce any output. I suspect I’m missing a key detail or concept.

Intercepting GameMain:

This game also has a GameMain.lua file that I intercept.
But nothing seems to work, so my questions are:
  1. When code is injected during interception, is it added to the top or bottom of the file?
  2. Can we replace the entire file during the luaL_loadbuffer scan?

Debugging

For debugging, I use logcat to read print messages from the game’s process:

Bash:
adb shell logcat -e Unity
(Filter messages with <tag>:s for example:
Bash:
adb shell logcat -e Unity MIUIInput:s
MIUIInput:s

Other Debugging Techniques:

  1. When I dump game JSON data, I save it to a local file (debugDump.json).
  2. On my PC, I run a script to repeatedly pull the file:
    Bash:
    adb pull /data/dLogs/debugDump.json

General Observations

Initially, I used an emulator, but as the games and tools (e.g., Frida) updated, maintaining the setup became tedious. Testing became slower, so I switched to a rooted phone. However, I encountered errors—some related to frida-gadget.so files in the Python Frida folder (installed via pip).
  • Temporary Fix: I created an empty file (it worked...) to replace the local frida-gadget.so, which resolved the issue.
    Running fridaserver, created a file named frida-gadget.so at same folder where i placed firaserver (arm64),
    and that behavior is something I don’t fully understand yet.
    File Location: \AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\AC\INetCache\frida
    (sadly i can't get the error message I got at the time...)

That’s it for now.
Thank you for reading, and apologies for any language mistakes—English is not my native tongue.
 
Back
Top Bottom