Full Code of nszdhd1/UtilScript for AI

main 546d37c8d3fa cached
16 files
50.7 KB
13.8k tokens
27 symbols
1 requests
Download .txt
Repository: nszdhd1/UtilScript
Branch: main
Commit: 546d37c8d3fa
Files: 16
Total size: 50.7 KB

Directory structure:
gitextract_sd5uedio/

├── HotFix/
│   ├── HotFix.lua
│   └── hotfix.js
├── InjectFrida/
│   ├── LIEFInjectFrida.py
│   ├── SmaliInjectFrida.py
│   └── tools/
│       ├── APPkeystore.jks
│       ├── apksignerNew.jar
│       ├── baksmali-2.5.2.jar
│       └── smali-2.5.2.jar
├── README.md
├── exportCode.py
├── game/
│   ├── Frida-cocos-lua-dump.py
│   ├── Frida-mono-dump.py
│   ├── GGHook.js
│   ├── GenShin-3.2-Dump.js
│   └── yuanshenInject.py
└── lua/
    └── GGInjector64.lua

================================================
FILE CONTENTS
================================================

================================================
FILE: HotFix/HotFix.lua
================================================

--package.cpath = package.cpath .. ';C:/Users/lenovo/.Rider2018.3/config/plugins/intellij-emmylua/classes/debugger/emmy/windows/x64/?.dll'
function print_func_ref_by_csharp()
    local registry = debug.getregistry()
    for k, v in pairs(registry) do
        if type(k) == 'number' and type(v) == 'function' and registry[v] == k then
            local info = debug.getinfo(v)
            ReleaseLogger.Log("[oook]", "[HotFix]", "[print_func_ref_by_csharp]",string.format('%s:%d', info.short_src, info.linedefined))
        end
    end
end
function hotfix(filename)
    --print_func_ref_by_csharp()
    ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]","start hotfix: "..filename)
    --local dumpname = string.gsub(filename,"%.","_")
    local dumpname = filename
    local oldModule
    if package.loaded[filename] then
        oldModule = package.loaded[filename]
    elseif package.loaded[dumpname] then
        oldModule = package.loaded[dumpname]
    else
        ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",'this file nevev loaded: '..filename)
        return
    end

    package.loaded[filename] = nil
    package.loaded[dumpname] = nil

    local ok,err = pcall(require, dumpname)
    if not ok then
        package.loaded[filename] = oldModule
        ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",'reload lua file failed:'..err)
        return
    end


    ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",'loaded newMpdule '..dumpname..' ,oldModule: '..filename)
    local newModule = package.loaded[dumpname]

    if newModule == nil then
        -- try again
        require(dumpname)
        newModule = package.loaded[dumpname]
    end


    ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",'oldModule: '.. tostring(oldModule)..' ,newModule: '..tostring(newModule))

   --
   --
   -- if newModule == nil then
   --     package.loaded[filename] = oldModule
   --     ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",'replaced faild !! ')
   --     return
   -- end
   --local updated_tables = {}
   -- ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]","updated_tables:"..type(oldModule).." new:"..type(newModule))
   -- --update_table(newModule, oldModule,updated_tables)
   -- ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]","7")
   --
   -- package.loaded[filename] = newModule

    ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",'replaced succeed')

end

function ResetENV(object, name)
    local visited = {}
    local function f(object, name)
        if not object or visited[object] then return end
        visited[object] = true
        if type(object) == "function" then
            xpcall(function () setfenv(object, _G) end, CS.UnityEngine.Debug.LogError)
        elseif type(object) == "table" then
            for k, v in pairs(object) do
                f(k, tostring(k).."__key" )
                f(v, tostring(k))
            end
        end
    end
    f(object, name)
end

function update_func(new_func, old_func)
    assert("function" == type(new_func))
    assert("function" == type(old_func))

    -- Get upvalues of old function.
    local old_upvalue_map = {}
    local OldExistName = {}
    for i = 1, math.huge do
        local name, value = debug.getupvalue(old_func, i)
        if not name then break end
        old_upvalue_map[name] = value
        OldExistName[name] = true
        ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]","OldExistName "..name.." i :"..i..'-->'..tostring(value))
    end

    -- Update new upvalues with old.
    for i = 1, math.huge do
        local name, value = debug.getupvalue(new_func, i)
        if not name then break end
        --CS.UnityEngine.Debug.LogError('set up value: name:'..name..' typeof '.. type(value))
        if OldExistName[name] then
            local old_value = old_upvalue_map[name]
            if type(old_value) == "function" then
                --update_func(value,old_value)
                debug.setupvalue(new_func, i, old_value)
                ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]",name.." is function")
            else
                if old_value ~= value then
                    ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]","set "..name.."")
                    debug.setupvalue(new_func, i, old_value)
                end
            end

        else

             -- 对新添加的upvalue设置正确的环境表
            ResetENV(value,name)
        end
    end
end

function update_table(new_table, old_table, updated_tables)
    assert("table" == type(new_table))
    assert("table" == type(old_table))

    -- Compare 2 tables, and update old table.
    for key, value in pairs(new_table) do
        --CS.UnityEngine.Debug.LogError("update_table "..key..'-->'..tostring(value))
        local old_value = old_table[key]
        local type_value = type(value)
        if type_value == "function" then
            update_func(value, old_value)
            old_table[key] = value

        elseif type_value == "table" then
            if ( updated_tables[value] == nil ) then
                updated_tables[value] = true
                update_table(value, old_value,updated_tables)
            end
        end
    end

    ReleaseLogger.Log("[oook]", "[HotFix]", "[hotfix]","---- Update metatable")
    ---- Update metatable.
    local old_meta = debug.getmetatable(old_table)
    local new_meta = debug.getmetatable(new_table)
    if type(old_meta) == "table" and type(new_meta) == "table" then
        update_table(new_meta, old_meta,updated_tables)
    end
end


================================================
FILE: HotFix/hotfix.js
================================================
var lua_State = null
const LUA_PATH = "/data/data/packagename/luadump"
const APP_DIR = "/data/data/packagename"
var luaL_loadfilex,luaL_loadstring,lua_pcall,lua_tolstring,luaL_loadbufferx,LuaEnv



// 作者说只支持art
// Java.performNow(function (){
//     var FileObserver = Java.use("android.os.FileObserver");
//     var LuaFileObserver = Java.registerClass({
//         name:'com.hotfix.LuaFileObserver',
//         superClass:FileObserver,
//         implements: [FileObserver],
//         methods:{
//             $init:[{
//                 returnType: 'void',
//                 arguments:['java.lang.String'],
//                 implementation:function (p){
//                     this.$super.$init(p)
//                 }
//             }, {
//                     returnType: 'void',
//                     arguments:[''],
//                     implementation:function (){
//                         this.$super.$init()
//                     }
//                 }],
//             $new:{
//                 returnType: 'void',
//                 arguments:['java.lang.String'],
//                 implementation:function (p){
//                     this.$super.$new(p)
//                 }
//             },
//             // onEvent:{
//             //         returnType: 'void',
//             //         arguments:['int','java.lang.String'],
//             //         implementation:function(event,path){
//             //         console.log("event :"+event)
//             //         console.log("path :"+path)
//             //     }
//             // },
//             stopWatching:{
//                 returnType: 'void',
//                 arguments:[''],
//                 implementation:function (){
//                     this.$super.stopWatching()
//                 }
//             },
//             startWatching:{
//                 returnType: 'void',
//                 arguments:[''],
//                 implementation:function (){
//                     this.$super.stopWatching()
//                 }
//             },
//             finalize:{
//                 returnType: 'void',
//                 arguments:[''],
//                 implementation:function (){
//                     this.$super.stopWatching()
//                 }
//             },
//             onEvent:function(event,path){
//                 console.log("event :"+event)
//                 console.log("path :"+path)
//             }
//
//         }
//     });
//     var FileWatcher = LuaFileObserver.$new(LUA_PATH)
//     FileObserver.onEvent.implementation = function (event,path){
//         console.log("event :"+event)
//         console.log("path :"+path)
//     }
//     FileWatcher.startWatching()
// })
var  gettid = new NativeFunction(Module.findExportByName(null,"gettid"),'int',[])

var status = 0

function LuaFileWatcher(){

    var pthread_mutex_init = new NativeFunction(Module.findExportByName(null,"pthread_mutex_init"),'int',['pointer','pointer'])
    var pthread_mutex_lock = new NativeFunction(Module.findExportByName(null,"pthread_mutex_lock"),'int',['pointer'])
    var pthread_mutex_unlock = new NativeFunction(Module.findExportByName(null,"pthread_mutex_unlock"),'int',['pointer'])

    var inotify_init = new NativeFunction(Module.findExportByName(null,"inotify_init"),'int',[])
    var inotify_add_watch = new NativeFunction(Module.findExportByName(null,"inotify_add_watch"),'int',['int','pointer','int'])
    const read = new NativeFunction(Module.findExportByName(null,"read"),'int',['int','pointer','int']);
    var fd = inotify_init()
    var wd = inotify_add_watch(fd,Memory.allocUtf8String(LUA_PATH),256) //ALL_EVENTS = 4095,OPEN=32
    console.log("fd "+fd+",wd "+wd)
    const inotify_event_len = 0x10
    var data = Memory.alloc(inotify_event_len*10);
    while (1){
        let readlen = read(fd,data,inotify_event_len*10-1)
        if( readlen<0){
            console.log('[+] Unable to read  [!] ');
            continue
        }
        console.log(readlen,data)

        // struct inotify_event {
        //     __s32 wd;
        //     __u32 ;
        //     __u32 cookie;
        //     __u32 len;
        //     char name[0];
        // };
        for (let i = 0; i < (readlen/0x10) ; i++) {
            let readData = data.add(i*0x10)
            let envent = []
            envent.wd = readData.readS32();
            envent.mask = readData.add(4).readU32();
            envent.cookie = readData.add(8).readU32();
            envent.len = readData.add(12).readU32();
            envent.name = readData.add(16).readCString();
            console.log('open file : ',envent.name,envent.mask)
            if(envent.mask!=256)
                continue;
                var mutex = Memory.alloc(Process.pointerSize)
                pthread_mutex_init(mutex,new NativePointer(0))
                 console.log("run thread pid "+Process.id +" run "+gettid())
                pthread_mutex_lock(mutex)

                try{
                    status = 1
                    console.log('----------------------')
                    let luaname = envent.name.replaceAll("_",".")
                    console.log("luaname"+luaname)
                    var scr ='if string.find(package.path,"/data/data/package_name/luadump/") == nil then\n' +
                        '    package.path = package.path .. ";/data/data/package_name/luadump/?"\n' +
                        'end\n'+
                        'require(\"HotFixOOOK\")\n'+
                        'hotfix(\"'+luaname+'\")'
                    var luaL_loadstring_ret = luaL_loadstring(lua_State,Memory.allocUtf8String(scr))
                    console.log("luaL_loadstring_ret  : "+luaL_loadstring_ret)
                    send("load lua init ret "+ lua_pcall(lua_State,0,0,0) + "  str:"+lua_tolstring(lua_State, -1).readCString())

                }catch (e) {
                    send("err:"+e.toString())
                }finally {
                    pthread_mutex_unlock(mutex)
                    status = 0
                }

        }

    }

}

var  pthread_create = new NativeFunction(Module.findExportByName(null,"pthread_create"),'int',['pointer','pointer','pointer','pointer'])
var  pthread_join = new NativeFunction(Module.findExportByName(null,"pthread_join"),'int',['pointer','pointer'])
var LuaFileWatcherNative = new NativeCallback(LuaFileWatcher,'void',['void'])


// 启动新线程对目标目录进行文件监控。
var pthread_t = Memory.alloc(16).writeLong(0)
pthread_create(pthread_t,new NativePointer(0),LuaFileWatcherNative,new NativePointer(0))
console.log("run pthread_create pid "+Process.id +" run "+gettid())


var libil2cpp = null;
while(libil2cpp == null){
    libil2cpp = Process.findModuleByName("libil2cpp.so");
}
send(libil2cpp);

var module = null;
while(module == null){
    module = Process.findModuleByName("libxlua.so");
}
send(module);

Interceptor.attach(Module.findExportByName("libxlua.so","luaL_loadbufferx"),{
    onEnter:function(args){
        const name = Memory.readCString(args[3]);
        console.log("luaL_loadbufferx  name :",name)
    }
});



Interceptor.attach(Module.findExportByName("libxlua.so","luaL_openlibs"),{
    onEnter:function(args){
        send("lua_State:"+args[0])
        lua_State = ptr(args[0])
        luaL_loadfilex = new NativeFunction(Module.findExportByName("libxlua.so","luaL_loadfilex"),'int',['pointer','pointer'])
        luaL_loadstring = new NativeFunction(Module.findExportByName("libxlua.so","luaL_loadstring"),'int',['pointer','pointer'])
        lua_pcall = new NativeFunction(Module.findExportByName("libxlua.so","lua_pcall"),'int',['pointer','int','int','int'])
        lua_tolstring = new NativeFunction(Module.findExportByName("libxlua.so","lua_tolstring"),'pointer',['pointer','int'])

        luaL_loadbufferx = new NativeFunction(Module.findExportByName("libxlua.so","luaL_loadbufferx"),'int',['pointer','pointer','int','pointer','pointer'])

    },onLeave:function (ret) {
    }
});




================================================
FILE: InjectFrida/LIEFInjectFrida.py
================================================
import argparse
import os
import shutil
import sys
import zipfile
import lief
import sys

"""
 使用方法:
   python3 需要注入的apk  输出路径(注意结尾不要添加/) 注入so的名字(最好是第一个加载的) 
            -apksign(可选项,写了就一键签名) -persistence(反正只多一个config文件,最好加上)
"""
def getpwd():
    pwd = sys.path[0]
    if os.path.isfile(pwd):
        pwd = os.path.dirname(pwd)
    return pwd


def getpwd():
    pwd = sys.path[0]
    if os.path.isfile(pwd):
        pwd = os.path.dirname(pwd)
    return pwd

class LIEFInject:
    def __init__(self,args):
        has_lib = False
        with zipfile.ZipFile(args.input, 'r') as apk_file:
            for item in apk_file.infolist():
                if item.filename.endswith(".so"):
                    has_lib = True
                    break
        if not has_lib:
            print('apk can\'t find so')
            exit(1)
        self.apkpath = args.input
        self.outdir  = args.output
        self.soname  = args.soname
        self.deletelist = []
        self.toolPath = getpwd() + r"\tools"


    def injectso(self):
        injectsolist = []
        with zipfile.ZipFile(self.apkpath,'r')as apk_file:
            for item in apk_file.infolist():
                if item.filename.find(self.soname) != -1:
                    apk_file.extract(item.filename)
                    self.deletelist.append(item.filename)
                    injectsolist.append(item.filename)
        #x86有一点问题,且不支持x86_64
        for soname in injectsolist:
            # if soname.find("x86_64") != -1:
            if soname.find("x86") != -1:
                continue
            so = lief.parse(os.getcwd()+"\\"+soname)
            so.add_library("libfrida-gadget.so")
            so.write(soname+"gadget.so")


    def modifyapk(self):
        (path, filename) = os.path.split(self.apkpath)
        (file, ext) = os.path.splitext(filename)
        outapk = os.path.join(self.outdir,file+"_frida.apk")
        with zipfile.ZipFile(self.apkpath, 'r')as orig_file:
            with zipfile.ZipFile(outapk, 'w')as out_file:
                for item in orig_file.infolist():
                    if item.filename.find(self.soname) != -1 and os.path.exists(os.getcwd()+"\\"+item.filename+"gadget.so"):
                        out_file.write(os.getcwd()+"\\"+item.filename+"gadget.so",arcname=item.filename)
                        if item.filename.find("lib/armeabi-v7a") != -1:
                            out_file.write(os.path.join(self.toolPath,"frida-gadget-14.2.18-android-arm.so"),
                                           arcname="lib/armeabi-v7a/libfrida-gadget.so")
                            print("add lib/armeabi-v7a/libfrida-gadget.so")
                        if item.filename.find("lib/arm64-v8a") != -1:
                            out_file.write(os.path.join(self.toolPath, "frida-gadget-14.2.18-android-arm64.so"),
                                           arcname="lib/arm64-v8a/libfrida-gadget.so")
                            print("add lib/arm64-v8a/libfrida-gadget.so")
                        if item.filename.find("lib/x86/") != -1:
                            out_file.write(os.path.join(self.toolPath, "frida-gadget-14.2.18-android-x86.so"),
                                           arcname="lib/x86/libfrida-gadget.so")
                            print("add lib/x86/libfrida-gadget.so")
                        continue
                    if item.filename.find("META-INF") == -1:
                        out_file.writestr(item, orig_file.read(item.filename))

        shutil.rmtree("lib")
        return outapk

    def addHook(self,apk_path):
        with zipfile.ZipFile(apk_path, 'a')as apk_file:
            for item in apk_file.infolist():
                if item.filename == "lib/armeabi-v7a/libfrida-gadget.so":
                    apk_file.write(os.path.join(self.toolPath, "libfrida-gadget.config.so"),
                                   arcname="lib/armeabi-v7a/libfrida-gadget.config.so")
                    print("add lib/armeabi-v7a/libfrida-gadget.config.so")
                if item.filename == "lib/arm64-v8a/libfrida-gadget.so":
                    apk_file.write(os.path.join(self.toolPath, "libfrida-gadget.config.so"),
                                   arcname="lib/arm64-v8a/libfrida-gadget.config.so")
                    print("add lib/arm64-v8a/libfrida-gadget.config.so")
                if item.filename == "lib/x86/libfrida-gadget.so":
                    apk_file.write(os.path.join(self.toolPath, "libfrida-gadget.config.so"),
                                   arcname="lib/x86/libfrida-gadget.config.so")
                    print("add lib/x86/libfrida-gadget.config.so")
                continue



    def signApk(self,apk_path):
        keystore = os.path.join(self.toolPath,'APPkeystore.jks')
        alias = 'key0'
        pswd = 'qwer1234'
        aliaspswd = 'qwer1234'

        apkname = os.path.splitext(os.path.split(apk_path)[1])[0]
        outfile = os.path.join(os.path.split(apk_path)[0], apkname + "_Signed.apk")

        cmd = 'java -jar %s\\apksignerNew.jar sign --ks %s --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out %s %s'% \
              (self.toolPath,keystore, alias,pswd,aliaspswd,outfile,apk_path)
        # print(cmd)
        os.system(cmd)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('input', help="apk path")
    parser.add_argument('output', help="Folder to store output files")
    parser.add_argument('soname', help="the so name of apk first load  ")
    parser.add_argument('-apksign', help="Sign apk", action='store_true')
    parser.add_argument('-persistence', help="HOOK Persistence ", action='store_true')

    args = parser.parse_args()
    liefs = LIEFInject(args)
    liefs.injectso()
    out = liefs.modifyapk()
    if args.persistence:
        liefs.addHook(out)
    if args.apksign:
        liefs.signApk(out)

    print(u"sucess, new apk :"+out)



================================================
FILE: InjectFrida/SmaliInjectFrida.py
================================================
import argparse
import os
import re
import shutil
import subprocess
import zipfile


class  SmaliInject:
    def __init__(self,args):
        has_lib = False
        with zipfile.ZipFile(args.input, 'r') as apk_file:
            for item in apk_file.infolist():
                if item.filename.endswith(".so"):
                    has_lib = True
                    break
        if has_lib:
            print('apk find so , Use LIEF inject is better')
            proceed = input("Keep running ? [Y/N]")
            if proceed == 'Y' or proceed == 'y':
                print("----- Smali inject -----")
            else:
                exit(0)
        self.apkpath = args.input
        self.outdir = args.output
        self.deletelist = []
        self.toolPath = os.getcwd() + r"\tools"
        self.decompileDir = os.getcwd() + r"\decompile"
        self.dexPath = os.getcwd() + r"\dex"
        self.dexList = []
        apkfile = zipfile.ZipFile(self.apkpath, 'r')
        for file_name in apkfile.namelist():
            if file_name.endswith(".dex") and file_name.startswith("classes"):
                if not os.path.exists(self.dexPath):
                    os.mkdir(self.dexPath)
                apkfile.extract(file_name, self.dexPath)
                self.dexList.append(os.path.join(self.dexPath, file_name))

    def injectso(self):
        target_activity = self.get_launchable_activity_aapt()
        print(target_activity)
        for dex in self.dexList:
            print(dex)
            if self.dexDecompile(dex):
                smali_path = os.path.join(self.decompileDir,target_activity.replace('.','\\'))+".smali"
                print(smali_path)
                with open(smali_path, 'r') as fp:
                    lines = fp.readlines()
                    has_clinit = False
                    start = 0
                    for i in range(len(lines)):
                        if lines[i].find(".source") != -1:
                            start = i
                        if lines[i].find(".method static constructor <clinit>()V") != -1:
                            if lines[i + 3].find(".line") != -1:
                                code_line = lines[i + 3][-3:]
                                lines.insert(i + 3, "%s%s\r" % (lines[i + 3][0:-3], str(int(code_line) - 2)))
                                print("%s%s" % (lines[i + 3][0:-3], str(int(code_line) - 2)))
                                lines.insert(i + 4, "const-string v0, \"frida-gadget\"\r")
                                lines.insert(i + 5,
                                             "invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\r")
                                has_clinit = True
                                break
                    if not has_clinit:
                        lines.insert(start + 1, ".method static constructor <clinit>()V\r")
                        lines.insert(start + 2, ".registers 1\r")
                        lines.insert(start + 3, ".line 10\r")
                        lines.insert(start + 4, "const-string v0, \"frida-gadget\"\r")
                        lines.insert(start + 5,
                                     "invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\r")
                        lines.insert(start + 6, "return-void\r")
                        lines.insert(start + 7, ".end method\r")

                    with open(smali_path, "w") as fp:
                        fp.writelines(lines)
                self.dexCompile(dex)

    def modifyapk(self):
        (path, filename) = os.path.split(self.apkpath)
        (file, ext) = os.path.splitext(filename)
        outapk = os.path.join(self.outdir, file + "_frida.apk")
        with zipfile.ZipFile(self.apkpath, 'r')as orig_file:
            with zipfile.ZipFile(outapk, 'w')as out_file:
                for item in orig_file.infolist():
                    if item.filename.startswith("classes") and item.filename.endswith(".dex"):
                        continue
                    if item.filename.find("META-INF") == -1 :
                        out_file.writestr(item, orig_file.read(item.filename))
                for dex in self.dexList:
                    out_file.write(dex,os.path.split(dex)[1])
                out_file.write(os.path.join(self.toolPath, "frida-gadget-14.2.18-android-arm.so"),
                               arcname="lib/armeabi-v7a/libfrida-gadget.so")
                print("add lib/armeabi-v7a/libfrida-gadget.so")
                out_file.write(os.path.join(self.toolPath, "frida-gadget-14.2.18-android-arm64.so"),
                               arcname="lib/arm64-v8a/libfrida-gadget.so")
                print("add lib/arm64-v8a/libfrida-gadget.so")
                out_file.write(os.path.join(self.toolPath, "frida-gadget-14.2.18-android-x86.so"),
                               arcname="lib/x86/libfrida-gadget.so")
                print("add lib/x86/libfrida-gadget.so")
        shutil.rmtree("dex")
        shutil.rmtree("decompile")
        return outapk

    def addHook(self,apk_path):
        with zipfile.ZipFile(apk_path, 'a')as apk_file:
            for item in apk_file.infolist():
                if item.filename == "lib/armeabi-v7a/libfrida-gadget.so":
                    apk_file.write(os.path.join(self.toolPath, "libfrida-gadget.config.so"),
                                   arcname="lib/armeabi-v7a/libfrida-gadget.config.so")
                    print("add lib/armeabi-v7a/libfrida-gadget.config.so")
                if item.filename == "lib/arm64-v8a/libfrida-gadget.so":
                    apk_file.write(os.path.join(self.toolPath, "libfrida-gadget.config.so"),
                                   arcname="lib/arm64-v8a/libfrida-gadget.config.so")
                    print("add lib/arm64-v8a/libfrida-gadget.config.so")
                if item.filename == "lib/x86/libfrida-gadget.so":
                    apk_file.write(os.path.join(self.toolPath, "libfrida-gadget.config.so"),
                                   arcname="lib/x86/libfrida-gadget.config.so")
                    print("add lib/x86/libfrida-gadget.config.so")
                continue

    def signApk(self,apk_path):
        keystore = os.path.join(self.toolPath,'APPkeystore.jks')
        alias = 'key0'
        pswd = 'qwer1234'
        aliaspswd = 'qwer1234'

        apkname = os.path.splitext(os.path.split(apk_path)[1])[0]
        outfile = os.path.join(os.path.split(apk_path)[0], apkname + "_Signed.apk")

        cmd = 'java -jar %s\\apksignerNew.jar sign --ks %s --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out %s %s'% \
              (self.toolPath,keystore, alias,pswd,aliaspswd,outfile,apk_path)
        os.system(cmd)

    def get_launchable_activity_aapt(self):

        aapt_path = os.path.join(self.toolPath, 'aapt.exe')
        cmd = '%s dump badging "%s" ' % (aapt_path, self.apkpath)
        p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        out,err = p.communicate()
        cmd_output = out.decode('utf-8').split('\r')
        for line in cmd_output:
            pattern = re.compile("launchable-activity: name='(\S+)'")
            match = pattern.search(line)
            if match:
                # print match.group()[27:-1]
                return match.group()[27:-1]
    def dexCompile(self,dexPath):
        baksmaliJarPath = os.path.join(self.toolPath, "smali-2.5.2.jar")
        command = 'java -jar \"%s\" assemble -o \"%s\" \"%s\"' % (baksmaliJarPath, dexPath, self.decompileDir)
        os.system(command)
        if not os.path.exists(dexPath):
            print(u"反编译失败")
    def dexDecompile(self,dexPath):
        if os.path.exists(self.decompileDir):
            shutil.rmtree(self.decompileDir)
        baksmaliJarPath = os.path.join(self.toolPath, "baksmali-2.5.2.jar")
        if not os.path.exists(dexPath):
            print(u"[dexDecompile] 文件%s不存在", dexPath)
            return False
        if not os.path.exists(baksmaliJarPath):
            print(u"[dexDecompile] 文件%s不存在", baksmaliJarPath)
            return False
        command = 'java -jar \"%s\" disassemble -o \"%s\" \"%s\"' % (baksmaliJarPath, self.decompileDir, dexPath)
        os.system(command)
        if not os.path.exists(self.decompileDir):
            print(u"[dexDecompile] 路径%s不存在", self.decompileDir)
            return False
        return True


if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument('input', help="apk path")
    parser.add_argument('output', help="Folder to store output files")
    parser.add_argument('-apksign', help="Sign apk", action='store_true')
    parser.add_argument('-persistence', help="HOOK Persistence ", action='store_true')

    args = parser.parse_args()
    tool = SmaliInject(args)
    tool.injectso()
    out = tool.modifyapk()
    if args.persistence:
        tool.addHook(out)
    if args.apksign:
        tool.signApk(out)


    print(u"sucess, new apk :"+out)

================================================
FILE: README.md
================================================
# UtilScript

frida  赛高~ o( ̄▽ ̄)d

## game 

一些脚本:

Frida-cocos-lua-dump.py dump cocos游戏的lua代码

Frida-mono-dump.py dump unity mono 的dll

yuansheninject.py 是喵喵子的 [使用frida获取unity il2cpp符号信息](https://nszdhd1.github.io/2020/12/04/%E4%BD%BF%E7%94%A8frida%E8%8E%B7%E5%8F%96il2cpp%E7%AC%A6%E5%8F%B7%E4%BF%A1%E6%81%AF/#more) 里的代码 

exportCode.py 是ida 导出伪代码到 cpp文件里

GGHook.js 用户获取GG脚本运行时的相关信息 [GameGuardian的Lua脚本分析](https://nszdhd1.github.io/2022/09/08/GameGuardian%E7%9A%84Lua%E8%84%9A%E6%9C%AC%E6%B7%B7%E6%B7%86%E5%88%86%E6%9E%90/#more)

GenShin-3.2-Dump.js 原神3.2版本符号信息dump [IL2CPP runtime dump](https://bbs.pediy.com/thread-275146.htm)

## InjectFrida

frida注入apk的两种实现方式:

[非root环境下frida持久化的两种方式及脚本](https://bbs.pediy.com/thread-268175.htm)

使用方法:
python3 script.py 需要注入的apk  输出路径(注意结尾不要添加/) 注入so的名字(最好是第一个加载的) apksign(可选项,写了就一键签名) -persistence(反正只多一个config文件,最好加上)

## lua

GGInjector64.lua  使用 gameguardian lua脚本 实现64位elf文件解析

================================================
FILE: exportCode.py
================================================
import idaapi
import idautils

def decompile(func):
    try:
        func_str = idaapi.decompile(func)
    except:
        return " decompile faild \n"
    return str(func_str)

def main():
    if not idaapi.init_hexrays_plugin():
        return False
    output = GetInputFile().split('.')[0]+'.cpp'
    f = open(output,'a')
    for segea in Segments():
        for funcea in idautils.Functions(segea, SegEnd(segea)):
            code = decompile(funcea)
            f.write(code)
    f.close()

if main():
    idaapi.term_hexrays_plugin()







================================================
FILE: game/Frida-cocos-lua-dump.py
================================================
# encoding: UTF-8

import sys
import frida

"""
     该脚本用于dump cocos 使用的 lua 脚本
     dump 文件保存在 /sdcard/fridadump文件夹中,
     如果 fridadump 文件夹中存在lua文件,就会加载fridadump中的lua文件
     游戏安全测试好帮手,(#^.^#)
"""

device = frida.get_usb_device()
pid = device.spawn(["com.nayijian.guanwang"])
session = device.attach(pid)
device.resume(pid)

scr = """
var APP_NAME = "com.nayijian.guanwang"

var module = null;
while(module == null){
    module = Process.findModuleByName("libil2cpp.so");
}
send(module);

Interceptor.attach(Module.findExportByName(null,"luaL_loadbufferx"),{
    onEnter:function(args){
        var name = Memory.readCString(args[3]);
        send(name.length);
        if(name.length < 50){
            send(name);

            this.Path = name.substring(0,name.lastIndexOf("/"));
            this.file = name.substring(name.lastIndexOf("/")+1,name.length);
            if(access("/sdcard/fridadump/lua/"+this.Path) == -1){ //文件夹不存在
                folder_mkdirs(this.Path);               
            }
            if(access("/sdcard/fridadump/lua/"+name) == 0 ){//文件存在
                var data = read_lua("/sdcard/fridadump/lua/"+name);
                send(data);
                args[1] = data.data;
                args[2] = new NativePointer(ptr(data.size));
                send("do load file :" + name);
                
            }else{
                Dump("/sdcard/fridadump/lua/"+name,args[1],args[2].toInt32());
            }
            
        }

    }
});

function Dump(filePath,data,datalen){
    send("dump  : "+ filePath);
    var dumpfile = new File(filePath,"wb"); 
    dumpfile.write(data.readByteArray(datalen));
    dumpfile.close();
}

function access(filePath){
    var ptr_access = Module.findExportByName("libc.so","access");
    var func_access = new NativeFunction(ptr_access,'int',['pointer','int']);
    var ptr_filepath = Memory.allocUtf8String(filePath);
    var ret = func_access(ptr_filepath,0);
    return ret;
}

function mkdir(Path){
    var ptr_mkdir = Module.findExportByName("libc.so","mkdir");
    var func_mkdir = new NativeFunction(ptr_mkdir,'int',['pointer','int']);
    var ptr_filepath = Memory.allocUtf8String(Path);
    var ret = func_mkdir(ptr_filepath,777);
    return ret;
}

function folder_mkdirs(p){
    var p_list = p.split("/");
    var pp = "/sdcard/fridadump/lua";
    for(var i = 0;i< p_list.length  ;i++){
        pp = pp + "/" + p_list[i];
        if(access(pp) != 0){
            var x = mkdir(pp)
            send("mkdir :"+pp+"ret :" +x);
        }
    }
    
}
// frida file 对象没有read 
function read_lua(filePath){
    var ptr_open = Module.findExportByName("libc.so","open");
    const open = new NativeFunction(ptr_open,'int',['pointer','int']);

    var ptr_read = Module.findExportByName("libc.so","read");
    const read = new NativeFunction(ptr_read,'int',['int','pointer','int']);

    var ptr_close = Module.findExportByName("libc.so","close");
    const close = new NativeFunction(ptr_close,'int',['int']);

    var fd = open(Memory.allocUtf8String(filePath),0);
    var size = get_file_size(fd);
    if(size >0){
        var data = Memory.alloc(size + 5);
        if( read(fd,data,size) <0){
            console.log('[+] Unable to read DLL [!]');
            close(fd);
            return 0;
        }
        close(fd);
        return {data:data,size:size};
    }

}

function get_file_size(fd){
    var statBuff = Memory.alloc(500);
    var fstatSymbol = Module.findExportByName('libc.so', 'fstat');
    var fstat = new NativeFunction(fstatSymbol, 'int', ['int', 'pointer']);
    if(fd > 0) {
        var ret = fstat(fd, statBuff);
        if(ret < 0) { console.log('[+] fstat --> failed [!]');
        }
    }
    var size = Memory.readS32(statBuff.add(0x30));
    if(size > 0) {
            return size;
        } else {
            return 0;
    }
}

"""

def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)


script = session.create_script(scr)
script.on("message", on_message)
script.load()
sys.stdin.read()




================================================
FILE: game/Frida-mono-dump.py
================================================
import os
import sys
import frida


"""
    该脚本用于dump unity mono 的dll,
    dll 未保护 使用  mono_image_open_from_data_with_name,
    dll 被保护(加密,主要是TX),使用 do_mono_image_load,这是一个非导出函数,在libmono.so搜索字符串 “data-%p”即可。
    具体原因及讲解见大佬18年帖子:https://bbs.pediy.com/thread-247487.htm
    
    ps.
    需要 手动创建 两个文件夹
    1. /sdcard/fridadump  2. /data/data/app_anme/frida

"""

APP_NAME = "com.tencent.pocket"

def pull_dll():
    inpath = pulldir = "/data/data/" + APP_NAME + "/frida"
    cmd_cp = "adb shell su -c 'cp -r " + inpath + " /sdcard/fridadump ' "
    print(cmd_cp)
    cmd_pull = "adb pull /sdcard/fridadump"
    os.system(cmd_cp)
    os.system(cmd_pull)


def push_dll():
    path = "/data/data/" + APP_NAME
    cmd_push = "adb push fridadump /sdcard"
    cmd_cp = " adb shell su -c 'cp -r /sdcard/fridadump/frida " + path +" '"
    print(cmd_cp)
    os.system(cmd_push)
    os.system(cmd_cp)




device = frida.get_usb_device()
pid = device.spawn(["com.DefaultCompany.unity2020"])
session = device.attach(pid)
device.resume(pid)

scr = """
var DUMP_FILE_PATH = "/data/data/com.tencent.pocket/frida/";
var APP_NAME = "com.tencent.pocket"
function DumpDll(filePath,data,datalen){

    send("dump dll : "+ filePath);
    var dumpfile = new File(filePath,"wb");
    dumpfile.write(data.readByteArray(datalen));
    dumpfile.close();

}


Interceptor.attach(Module.findExportByName(null , "dlopen"), {
    onEnter: function(args) {
        var soName = args[0].readCString();
        if(soName.indexOf(APP_NAME) != -1 && soName.indexOf("libmono.so") != -1){
            send("dlopen load :"+soName);
            this.hook = true;
        }
    },
    onLeave:function(retval){
            if(this.hook == true){
                do_image_hook();
            }
    }
});


function do_image_hook(){

var module = Process.getModuleByName("libmono.so");
send(module.base);
Interceptor.attach(ptr(module.base).add(0x194878),{ //do_mono_image_load()
    onEnter:function(args){
        var images = args[0];
        var name = images.add(20).readPointer().readCString();
        var data = images.add(8).readPointer();
        var length = images.add(12).readPointer()

        send(name);
        send(length);
         var s = name.split("/");
         var filePath = DUMP_FILE_PATH + s[s.length -1];
        DumpDll(filePath,data,length.toInt32());

    }

});

Interceptor.attach(Module.findExportByName("libmono.so","mono_image_open_from_data_with_name"),{
        onEnter:function(args){

            var s = args[5].readCString().split("/");
            var filePath = DUMP_FILE_PATH + s[s.length -1];

            
               // DumpDll(filePath,args[0],args[1].toInt32());
                
         

        }
    });

}

function Check_dump_file(filePath){

    var ptr_access = Module.findExportByName("libc.so","access");
    var func_access = new NativeFunction(ptr_access,'int',['pointer','int']);
    var ptr_filepath = Memory.allocUtf8String(filePath);
    var ret = func_access(ptr_filepath,0);
    return ret;
}

function get_file_size(fd){
    var statBuff = Memory.alloc(500);
    var fstatSymbol = Module.findExportByName('libc.so', 'fstat');
    var fstat = new NativeFunction(fstatSymbol, 'int', ['int', 'pointer']);
    if(fd > 0) {
        var ret = fstat(fd, statBuff);
        if(ret < 0) { console.log('[+] fstat --> failed [!]');
        }
    }
    var size = Memory.readS32(statBuff.add(0x30));
    if(size > 0) {
            return size;
        } else {
            return 0;
    }
}

// frida file 对象没有read
function do_load_dll(filePath){
    var ptr_open = Module.findExportByName("libc.so","open");
    const open = new NativeFunction(ptr_open,'int',['pointer','int']);

    var ptr_read = Module.findExportByName("libc.so","read");
    const read = new NativeFunction(ptr_read,'int',['int','pointer','int']);

    var ptr_close = Module.findExportByName("libc.so","close");
    const close = new NativeFunction(ptr_close,'int',['int']);

    var fd = open(Memory.allocUtf8String(filePath),0);
    var size = get_file_size(fd);
    if(size >0){
        var data = Memory.alloc(size + 5);
        if( read(fd,data,size) <0){
            console.log('[+] Unable to read DLL [!]');
            close(fd);
            return 0;
        }
        close(fd);
        return data;
    }

}

"""



def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)


script = session.create_script(scr)
script.on("message", on_message)
script.load()
sys.stdin.read()





================================================
FILE: game/GGHook.js
================================================
Java.performNow(function () {
    Java.enumerateLoadedClasses({
        onMatch: function (name, handle) {
            if (name.startsWith("android.ext.Script$")) {
                if (name == "android.ext.Script$isVisible" || name == "android.ext.Script$ApiFunction"
                    || name == "android.ext.Script$BusyApiFunction" || name == "android.ext.Script$DebugFunctio"
                    || name.endsWith("$clearResults"))
                    return;
                var klass = Java.use(name);
                console.log(JSON.stringify(klass));
                if ("android.ext.Script$ApiFunction" == klass.$super.$className || "android.ext.Script$BusyApiFunction" == klass.$super.$className) {
                    for (var _i = 0, _a = klass.$ownMembers; _i < _a.length; _i++) {
                        var m = _a[_i];
                        if (m == "a" && typeof klass[m] == "function") {
                            try {
                                Java.use(name).a.overload().implementation = function () {
                                    console.log(this.a());
                                    return this.a();
                                };
                            }
                            catch (e) {
                                console.log(e);
                                console.log(name);
                            }
                        }
                        if (m == "d" && typeof klass[m] == "function") {
                            try {
                                Java.use(name).d.implementation = function (a) {
                                    if (name.endsWith("searchNumber")) {
                                        console.log("a1 string :", a.r(1));
                                    }
                                    console.log(name, ":", a);
                                    return this.d(a);
                                };
                            }
                            catch (e) {
                                console.log(e);
                                console.log(name);
                            }
                        }
                        if (m == "b" && typeof klass[m] == "function") {
                            try {
                                Java.use(name).b.implementation = function (a) {
                                    console.log(name, ":", a);
                                    return this.b(a);
                                };
                            }
                            catch (e) {
                                console.log(e);
                                console.log(name);
                            }
                        }
                    }
                }
            }
        },
        onComplete: function () {
        }
    });
});
console.log("end");

================================================
FILE: game/GenShin-3.2-Dump.js
================================================
let so = Process.findModuleByName("libil2cpp.so")
let il2cpp_method_get_name = new NativeFunction(so.base.add(0x4260354),'pointer',['pointer'])
let il2cpp_method_get_param = new NativeFunction(so.base.add(0x425FEC4),'pointer',['pointer','int'])
let il2cpp_method_get_return_type = new NativeFunction(so.base.add(0x42306EC),'pointer',['pointer'])
 
let il2cpp_class_from_type = new NativeFunction(so.base.add(0x4251ED8),'pointer',['pointer'])
let il2cpp_class_get_name  = new NativeFunction(so.base.add(0x4252E48),'pointer',['pointer'])
 
 
Interceptor.attach(so.base.add(0x4252BE4),{
    onEnter:function (args) {
        // console.log("---------il2cpp_class_get_methods--------")
        this.class = args[0]
 
    },
    onLeave:function (ret) {
        try{
            let classname = this.class.add(40).readPointer().readCString()
            let namespace = this.class.add(120).readPointer().readCString()
            let name_ptr = il2cpp_method_get_name(ret)
            let ret_type = il2cpp_method_get_return_type(ret)
            let ret_type_class = il2cpp_class_from_type(ret_type)
            let ret_class_name = il2cpp_class_get_name(ret_type_class)
 
            //InvokerMethod ret.add(16)  methodPointer ret
             let parameters_count = ret.add(50).readU8()
            let pstr = "("
            for(let idx = 0;idx<parameters_count;idx++){
                let param = il2cpp_method_get_param(ret,idx)
                let type = il2cpp_class_from_type(param)
                let typeName = il2cpp_class_get_name(type)
                pstr += ptr(typeName).readCString() + "  a"+idx +" ,"
            }
            pstr+=");"
            console.log("[*]"+ret.readPointer()+"   --> "+ptr(ret_class_name).readCString()+"  "+namespace+"."+classname+"."+ptr(name_ptr).readCString()+pstr)
 
        }catch (e) {
            console.log(e.toString())
        }
 
    }
})

================================================
FILE: game/yuanshenInject.py
================================================
import sys

import frida

device = frida.get_usb_device()
pid = device.spawn(["com.miHoYo.Yuanshen"])
session = device.attach(pid)
device.resume(pid)

scr = """
var APP_NAME = "com.miHoYo.Yuanshen"

var module = null;
while(module == null){
    module = Process.findModuleByName("libil2cpp.so");
}
send(module);

var unity = Process.findModuleByName("libunity.so");
send(unity);

var x = Interceptor.attach(ptr(unity.base).add(0xb2aecc),{
    onEnter:function(args){
    send(args[1]);
    },onLeave:function(ret){
       send(ret.sub(1).readUtf8String());

    }
});

Interceptor.attach(Module.findExportByName("libil2cpp.so","il2cpp_class_from_name"),{
    onEnter:function(args){
    //send(args[1].readUtf8String()  + "  -----  : "+args[2].readUtf8String());
    
    },onLeave:function(ret){
      
    }
});


// hook SetupMethodsLocked
var p_size = 8;
Interceptor.attach(ptr(module.base).add(0x72F09EC).add(0x204),{
    onEnter:function(args){
    var newMethod = this.context.x20
    var pointer = newMethod.readPointer();
    var name = newMethod.add(p_size * 2).readPointer().readCString();
    var klass = newMethod.add(p_size * 3).readPointer();
    var klass_name = klass.add(p_size * 2).readPointer().readCString();
    var klass_paze = klass.add(p_size * 3).readPointer().readCString();
    send(klass_paze+"."+klass_name+":"+name+"    -> "+pointer.sub(module.base));
    },onLeave:function(ret){
     
    }
});



"""




def on_message(message, data):
    if message['type'] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)


script = session.create_script(scr)
script.on("message", on_message)
script.load()
sys.stdin.read()




================================================
FILE: lua/GGInjector64.lua
================================================
---
--- Created by yangtong02.
--- DateTime: 2023/2/9 13:40
--- GG lua 解析64位elf文件
---
---


sf	= string.format
function alert(caption, text)
	assert(caption ~= nil, "\n\n>> [alert]: error, caption was nil. <<\n\n")
	if text == nil then
		text = caption
		caption = "[Info]: Notice"
	end
	gg.alert(caption .. "\n\t- " .. text)
end
function rwmem(address, SizeOrBuffer)
	assert(type(address) ~= "string", "\n\n>> [rwmem]: error, address is string. Please check caller. <<\n\n")
	assert(address ~= nil, "\n\n>> [rwmem]: error, provided address is nil. <<\n\n")
	_rw = {}
	if type(SizeOrBuffer) == "number" then
		_ = ""
		for _ = 1, SizeOrBuffer do _rw[_] = {address = (address - 1) + _, flags = gg.TYPE_BYTE} end
		for v, __ in ipairs(gg.getValues(_rw)) do _ = _ .. string.format("%02X", __.value & 0xFF) end
		return _
	end
	Byte = {} SizeOrBuffer:gsub("..", function(x)
		Byte[#Byte + 1] = x _rw[#Byte] = {address = (address - 1) + #Byte, flags = gg.TYPE_BYTE, value = x .. "h"}
	end)
	gg.setValues(_rw)
end
function rdstr(address, strsz)
  assert(address ~= nil, "\n\n>> [rdstr]: error, provided address is nil. <<\n\n")
  if strsz == nil or type(strsz) ~= "number" then strsz = 128 end
  local str = ""
  for _ in rwmem(address, strsz):gmatch("..") do
    if _ == "00" then break end
      str = str .. string.char(tonumber(_, 16))
  end
  return str
end

---------------------------

function getLibraryBase(lib)
    print("search ".. lib)
    --print(gg.getRangesList(lib))
	for _, __ in pairs(gg.getRangesList(lib)) do
        print(sf("start 0x%x ~ 0x%x",__["start"], __["end"]))
		--if __["state"] == "Xa" or __["state"] == "Xs" then
        --    --print(sf("start 0x%x ~ 0x%x",__["start"], __["end"]))
        return __["start"], __["end"] end
	--end
	return nil
end
function getLibInformation(LibName)
	local LibBase = getLibraryBase(LibName)
    if LibBase == nil then
        print("can't find "..LibName)
    end
	if LibBase ~= nil then
		_ = gg.getValues({
			{address = LibBase, flags = gg.TYPE_DWORD },		-- Magic
			-- EI_PAD skipped --
			{address = LibBase + 0x12, flags = gg.TYPE_WORD },	-- Machine
			{address = LibBase + 0x20, flags = gg.TYPE_DWORD },	-- Program Header Table (PH) Offset
			{address = LibBase + 0x30, flags = gg.TYPE_DWORD },	-- Flags
			{address = LibBase + 0x36, flags = gg.TYPE_WORD },	-- Program Header Table (PH) Size Entry
			{address = LibBase + 0x38, flags = gg.TYPE_WORD },	-- Number Of Entries In Program Header Table (PH)
			})
		local Elf = { -- Elf Information Table Structure--
			Magic		= _[1].value,
			Machine 	= _[2].value,
			PHOffset 	= _[3].value,
			Flags 		= _[4].value,
			PHSize 		= _[5].value,
			PHNum		= _[6].value,
			pHdr		= {},
			Dyn			= {},
			Sym			= {},
			vAddress	= LibBase
		}
        print(sf("ELF info Magic %s ,PHOffset 0x%x PHNum 0x%x",Elf.Magic,Elf.PHOffset,Elf.PHSize))
		for _ = 1, Elf.PHNum do -- Parsing Program Header
			local _pHdr = LibBase + Elf.PHOffset + (_ * Elf.PHSize)
			local pHdr = gg.getValues({
				{ address = _pHdr, flags = gg.TYPE_DWORD }, 		-- p_type
				{ address = _pHdr + 8, flags = gg.TYPE_DWORD }, 	-- p_offset
				{ address = _pHdr + 0x10, flags = gg.TYPE_DWORD }, 	-- p_vaddr
				{ address = _pHdr + 0x18, flags = gg.TYPE_DWORD },	-- p_paddr
				{ address = _pHdr + 0x20, flags = gg.TYPE_DWORD },	-- p_filesz
				{ address = _pHdr + 0x28, flags = gg.TYPE_DWORD },	-- p_memsz
				{ address = _pHdr + 4, flags = gg.TYPE_DWORD },	-- p_flags
				--{ address = _pHdr + 0x30, flags = gg.TYPE_DWORD },	-- p_align
			})
			Elf.pHdr[_] = { -- All data in Program Header now in Elf.pHdr[Elf.PHNum]
				p_type		= pHdr[1].value,
				p_offset	= pHdr[2].value,
				p_vaddr		= pHdr[3].value,
				p_paddr		= pHdr[4].value,
				p_filesz	= pHdr[5].value,
				p_memsz		= pHdr[6].value,
				p_flags		= pHdr[7].value,
				--p_align		= pHdr[8].value
			}
            print(sf("pHdr type %d offset 0x%x  p_vaddr 0x%x ",pHdr[1].value,pHdr[2].value,pHdr[3].value))
		end
		for _ = 1, Elf.PHNum do  -- Parsing Dynamic Segment
			if Elf.pHdr[_].p_type == 2 then -- PT_DYNAMIC
				local DynCount = 0
				while true do
					local _Dyn = gg.getValues({
						{ address = LibBase + Elf.pHdr[_].p_vaddr + (DynCount * 8), flags = gg.TYPE_DWORD }, -- d_tag
						{ address = LibBase + Elf.pHdr[_].p_vaddr + 8 + (DynCount * 8), flags = gg.TYPE_DWORD } -- d_ptr / d_val
					})
					if _Dyn[1].value == 0 and _Dyn[2].value == 0 then break end -- End of dynamic segment
					DynCount = DynCount + 1 -- Keep growing !
					Elf.Dyn[DynCount] = { -- All data in Dynamic Segment now in Elf.Dyn[Section]
						d_tag = _Dyn[1].value,
						d_val = _Dyn[2].value,
						d_ptr = _Dyn[2].value
					}
				end
			end
		end
		return Elf
	end
	return nil
end

function getSymbolAddress(ElfData, symName)
	assert(ElfData ~= nil, "\n\n>> [getSymbolAddress]: error, provided ElfData is nil. <<\n\n")
	for _ = 1, #ElfData.Dyn do
			if tonumber(ElfData.Dyn[_].d_tag) == 4 then nChain = gg.getValues({{address = (ElfData.Dyn[_].d_ptr + 4) + ElfData.vAddress, flags = gg.TYPE_DWORD}})[1].value end
			if tonumber(ElfData.Dyn[_].d_tag) == 5 then strtab = ElfData.Dyn[_].d_ptr + ElfData.vAddress end
			if tonumber(ElfData.Dyn[_].d_tag) == 6 then symtab = ElfData.Dyn[_].d_ptr + ElfData.vAddress end
	end
    if nChain ~= nil then
        for _ = 1, nChain do
            local sym = symtab + (_ * 0x18)
            __ = gg.getValues({
                { address = sym, flags = gg.TYPE_DWORD },		-- st_name
                { address = sym + 0x4, flags = gg.TYPE_DWORD },	-- st_value
            })
            print(rdstr(strtab + __[1].value) .. ", offset:"..sf("0x%x",__[1].value))
            if rdstr(strtab + __[1].value) == symName then
                return ElfData.vAddress + __[2].value
            end
        end
    else
        print("nChain is nil")
    end

	return nil
end

function getLib(libName)
	gg.toast("Searching for '"..libName.."', This may take a while. Please wait...")
	local m_lib = getLibInformation(libName)
	if m_lib ~= nil then
		print(sf("[getLib]: %s Architecture: 0x%08X", libName, m_lib.Machine))
		if m_lib.Machine == 0xb7 then -- Arm 64-bits
            return m_lib
		end
		alert("[Error]: Unsupported Device !", "Currently, only Arm 64-bits device are supported.")
		os.exit()
		return nil
	end

	alert("[Error]: Missing dependencies !", "One of required shared library '" .. libName .. "', has left us in the dark.")
	os.exit()
	return nil
end
function getSymbol(ElfData, Symname)
    gg.toast("Searching for Symbol '"..Symname.."', This may take a while. Please wait...")
	local s_address = getSymbolAddress(ElfData, Symname)
	if s_address ~= nil then
		return s_address
	end

	alert("[Error]: Missing dependencies !", "One of required symbol '" .. Symname .. "', has been reported missing.")
	os.exit()
	return nil
end




local m_libdl		= getLib("libil2cpp.so")
local s_dlopen	= getSymbol(m_libdl, "il2cpp_assembly_get_image")
print("find dlopen "..s_dlopen)
Download .txt
gitextract_sd5uedio/

├── HotFix/
│   ├── HotFix.lua
│   └── hotfix.js
├── InjectFrida/
│   ├── LIEFInjectFrida.py
│   ├── SmaliInjectFrida.py
│   └── tools/
│       ├── APPkeystore.jks
│       ├── apksignerNew.jar
│       ├── baksmali-2.5.2.jar
│       └── smali-2.5.2.jar
├── README.md
├── exportCode.py
├── game/
│   ├── Frida-cocos-lua-dump.py
│   ├── Frida-mono-dump.py
│   ├── GGHook.js
│   ├── GenShin-3.2-Dump.js
│   └── yuanshenInject.py
└── lua/
    └── GGInjector64.lua
Download .txt
SYMBOL INDEX (27 symbols across 7 files)

FILE: HotFix/hotfix.js
  constant LUA_PATH (line 2) | const LUA_PATH = "/data/data/packagename/luadump"
  constant APP_DIR (line 3) | const APP_DIR = "/data/data/packagename"
  function LuaFileWatcher (line 83) | function LuaFileWatcher(){

FILE: InjectFrida/LIEFInjectFrida.py
  function getpwd (line 14) | def getpwd():
  function getpwd (line 21) | def getpwd():
  class LIEFInject (line 27) | class LIEFInject:
    method __init__ (line 28) | def __init__(self,args):
    method injectso (line 45) | def injectso(self):
    method modifyapk (line 63) | def modifyapk(self):
    method addHook (line 91) | def addHook(self,apk_path):
    method signApk (line 110) | def signApk(self,apk_path):

FILE: InjectFrida/SmaliInjectFrida.py
  class SmaliInject (line 9) | class  SmaliInject:
    method __init__ (line 10) | def __init__(self,args):
    method injectso (line 39) | def injectso(self):
    method modifyapk (line 78) | def modifyapk(self):
    method addHook (line 104) | def addHook(self,apk_path):
    method signApk (line 121) | def signApk(self,apk_path):
    method get_launchable_activity_aapt (line 134) | def get_launchable_activity_aapt(self):
    method dexCompile (line 147) | def dexCompile(self,dexPath):
    method dexDecompile (line 153) | def dexDecompile(self,dexPath):

FILE: exportCode.py
  function decompile (line 4) | def decompile(func):
  function main (line 11) | def main():

FILE: game/Frida-cocos-lua-dump.py
  function on_message (line 135) | def on_message(message, data):

FILE: game/Frida-mono-dump.py
  function pull_dll (line 20) | def pull_dll():
  function push_dll (line 29) | def push_dll():
  function on_message (line 167) | def on_message(message, data):

FILE: game/yuanshenInject.py
  function on_message (line 64) | def on_message(message, data):
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (56K chars).
[
  {
    "path": "HotFix/HotFix.lua",
    "chars": 5510,
    "preview": "\n--package.cpath = package.cpath .. ';C:/Users/lenovo/.Rider2018.3/config/plugins/intellij-emmylua/classes/debugger/emmy"
  },
  {
    "path": "HotFix/hotfix.js",
    "chars": 7956,
    "preview": "var lua_State = null\nconst LUA_PATH = \"/data/data/packagename/luadump\"\nconst APP_DIR = \"/data/data/packagename\"\nvar luaL"
  },
  {
    "path": "InjectFrida/LIEFInjectFrida.py",
    "chars": 5914,
    "preview": "import argparse\nimport os\nimport shutil\nimport sys\nimport zipfile\nimport lief\nimport sys\n\n\"\"\"\n 使用方法:\n   python3 需要注入的apk"
  },
  {
    "path": "InjectFrida/SmaliInjectFrida.py",
    "chars": 9030,
    "preview": "import argparse\nimport os\nimport re\nimport shutil\nimport subprocess\nimport zipfile\n\n\nclass  SmaliInject:\n    def __init_"
  },
  {
    "path": "README.md",
    "chars": 921,
    "preview": "# UtilScript\n\nfrida  赛高~ o( ̄▽ ̄)d\n\n## game \n\n一些脚本:\n\nFrida-cocos-lua-dump.py dump cocos游戏的lua代码\n\nFrida-mono-dump.py dump u"
  },
  {
    "path": "exportCode.py",
    "chars": 546,
    "preview": "import idaapi\nimport idautils\n\ndef decompile(func):\n    try:\n        func_str = idaapi.decompile(func)\n    except:\n     "
  },
  {
    "path": "game/Frida-cocos-lua-dump.py",
    "chars": 4096,
    "preview": "# encoding: UTF-8\n\nimport sys\nimport frida\n\n\"\"\"\n     该脚本用于dump cocos 使用的 lua 脚本\n     dump 文件保存在 /sdcard/fridadump文件夹中,\n "
  },
  {
    "path": "game/Frida-mono-dump.py",
    "chars": 4573,
    "preview": "import os\nimport sys\nimport frida\n\n\n\"\"\"\n    该脚本用于dump unity mono 的dll,\n    dll 未保护 使用  mono_image_open_from_data_with_na"
  },
  {
    "path": "game/GGHook.js",
    "chars": 2862,
    "preview": "Java.performNow(function () {\n    Java.enumerateLoadedClasses({\n        onMatch: function (name, handle) {\n            i"
  },
  {
    "path": "game/GenShin-3.2-Dump.js",
    "chars": 1893,
    "preview": "let so = Process.findModuleByName(\"libil2cpp.so\")\nlet il2cpp_method_get_name = new NativeFunction(so.base.add(0x4260354)"
  },
  {
    "path": "game/yuanshenInject.py",
    "chars": 1693,
    "preview": "import sys\n\nimport frida\n\ndevice = frida.get_usb_device()\npid = device.spawn([\"com.miHoYo.Yuanshen\"])\nsession = device.a"
  },
  {
    "path": "lua/GGInjector64.lua",
    "chars": 6955,
    "preview": "---\n--- Created by yangtong02.\n--- DateTime: 2023/2/9 13:40\n--- GG lua 解析64位elf文件\n---\n---\n\n\nsf\t= string.format\nfunction "
  }
]

// ... and 4 more files (download for full content)

About this extraction

This page contains the full source code of the nszdhd1/UtilScript GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (50.7 KB), approximately 13.8k tokens, and a symbol index with 27 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!