[
  {
    "path": "HotFix/HotFix.lua",
    "content": "\n--package.cpath = package.cpath .. ';C:/Users/lenovo/.Rider2018.3/config/plugins/intellij-emmylua/classes/debugger/emmy/windows/x64/?.dll'\nfunction print_func_ref_by_csharp()\n    local registry = debug.getregistry()\n    for k, v in pairs(registry) do\n        if type(k) == 'number' and type(v) == 'function' and registry[v] == k then\n            local info = debug.getinfo(v)\n            ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[print_func_ref_by_csharp]\",string.format('%s:%d', info.short_src, info.linedefined))\n        end\n    end\nend\nfunction hotfix(filename)\n    --print_func_ref_by_csharp()\n    ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",\"start hotfix: \"..filename)\n    --local dumpname = string.gsub(filename,\"%.\",\"_\")\n    local dumpname = filename\n    local oldModule\n    if package.loaded[filename] then\n        oldModule = package.loaded[filename]\n    elseif package.loaded[dumpname] then\n        oldModule = package.loaded[dumpname]\n    else\n        ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",'this file nevev loaded: '..filename)\n        return\n    end\n\n    package.loaded[filename] = nil\n    package.loaded[dumpname] = nil\n\n    local ok,err = pcall(require, dumpname)\n    if not ok then\n        package.loaded[filename] = oldModule\n        ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",'reload lua file failed:'..err)\n        return\n    end\n\n\n    ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",'loaded newMpdule '..dumpname..' ,oldModule: '..filename)\n    local newModule = package.loaded[dumpname]\n\n    if newModule == nil then\n        -- try again\n        require(dumpname)\n        newModule = package.loaded[dumpname]\n    end\n\n\n    ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",'oldModule: '.. tostring(oldModule)..' ,newModule: '..tostring(newModule))\n\n   --\n   --\n   -- if newModule == nil then\n   --     package.loaded[filename] = oldModule\n   --     ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",'replaced faild !! ')\n   --     return\n   -- end\n   --local updated_tables = {}\n   -- ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",\"updated_tables:\"..type(oldModule)..\" new:\"..type(newModule))\n   -- --update_table(newModule, oldModule,updated_tables)\n   -- ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",\"7\")\n   --\n   -- package.loaded[filename] = newModule\n\n    ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",'replaced succeed')\n\nend\n\nfunction ResetENV(object, name)\n    local visited = {}\n    local function f(object, name)\n        if not object or visited[object] then return end\n        visited[object] = true\n        if type(object) == \"function\" then\n            xpcall(function () setfenv(object, _G) end, CS.UnityEngine.Debug.LogError)\n        elseif type(object) == \"table\" then\n            for k, v in pairs(object) do\n                f(k, tostring(k)..\"__key\" )\n                f(v, tostring(k))\n            end\n        end\n    end\n    f(object, name)\nend\n\nfunction update_func(new_func, old_func)\n    assert(\"function\" == type(new_func))\n    assert(\"function\" == type(old_func))\n\n    -- Get upvalues of old function.\n    local old_upvalue_map = {}\n    local OldExistName = {}\n    for i = 1, math.huge do\n        local name, value = debug.getupvalue(old_func, i)\n        if not name then break end\n        old_upvalue_map[name] = value\n        OldExistName[name] = true\n        ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",\"OldExistName \"..name..\" i :\"..i..'-->'..tostring(value))\n    end\n\n    -- Update new upvalues with old.\n    for i = 1, math.huge do\n        local name, value = debug.getupvalue(new_func, i)\n        if not name then break end\n        --CS.UnityEngine.Debug.LogError('set up value: name:'..name..' typeof '.. type(value))\n        if OldExistName[name] then\n            local old_value = old_upvalue_map[name]\n            if type(old_value) == \"function\" then\n                --update_func(value,old_value)\n                debug.setupvalue(new_func, i, old_value)\n                ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",name..\" is function\")\n            else\n                if old_value ~= value then\n                    ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",\"set \"..name..\"\")\n                    debug.setupvalue(new_func, i, old_value)\n                end\n            end\n\n        else\n\n             -- 对新添加的upvalue设置正确的环境表\n            ResetENV(value,name)\n        end\n    end\nend\n\nfunction update_table(new_table, old_table, updated_tables)\n    assert(\"table\" == type(new_table))\n    assert(\"table\" == type(old_table))\n\n    -- Compare 2 tables, and update old table.\n    for key, value in pairs(new_table) do\n        --CS.UnityEngine.Debug.LogError(\"update_table \"..key..'-->'..tostring(value))\n        local old_value = old_table[key]\n        local type_value = type(value)\n        if type_value == \"function\" then\n            update_func(value, old_value)\n            old_table[key] = value\n\n        elseif type_value == \"table\" then\n            if ( updated_tables[value] == nil ) then\n                updated_tables[value] = true\n                update_table(value, old_value,updated_tables)\n            end\n        end\n    end\n\n    ReleaseLogger.Log(\"[oook]\", \"[HotFix]\", \"[hotfix]\",\"---- Update metatable\")\n    ---- Update metatable.\n    local old_meta = debug.getmetatable(old_table)\n    local new_meta = debug.getmetatable(new_table)\n    if type(old_meta) == \"table\" and type(new_meta) == \"table\" then\n        update_table(new_meta, old_meta,updated_tables)\n    end\nend\n"
  },
  {
    "path": "HotFix/hotfix.js",
    "content": "var lua_State = null\nconst LUA_PATH = \"/data/data/packagename/luadump\"\nconst APP_DIR = \"/data/data/packagename\"\nvar luaL_loadfilex,luaL_loadstring,lua_pcall,lua_tolstring,luaL_loadbufferx,LuaEnv\n\n\n\n// 作者说只支持art\n// Java.performNow(function (){\n//     var FileObserver = Java.use(\"android.os.FileObserver\");\n//     var LuaFileObserver = Java.registerClass({\n//         name:'com.hotfix.LuaFileObserver',\n//         superClass:FileObserver,\n//         implements: [FileObserver],\n//         methods:{\n//             $init:[{\n//                 returnType: 'void',\n//                 arguments:['java.lang.String'],\n//                 implementation:function (p){\n//                     this.$super.$init(p)\n//                 }\n//             }, {\n//                     returnType: 'void',\n//                     arguments:[''],\n//                     implementation:function (){\n//                         this.$super.$init()\n//                     }\n//                 }],\n//             $new:{\n//                 returnType: 'void',\n//                 arguments:['java.lang.String'],\n//                 implementation:function (p){\n//                     this.$super.$new(p)\n//                 }\n//             },\n//             // onEvent:{\n//             //         returnType: 'void',\n//             //         arguments:['int','java.lang.String'],\n//             //         implementation:function(event,path){\n//             //         console.log(\"event :\"+event)\n//             //         console.log(\"path :\"+path)\n//             //     }\n//             // },\n//             stopWatching:{\n//                 returnType: 'void',\n//                 arguments:[''],\n//                 implementation:function (){\n//                     this.$super.stopWatching()\n//                 }\n//             },\n//             startWatching:{\n//                 returnType: 'void',\n//                 arguments:[''],\n//                 implementation:function (){\n//                     this.$super.stopWatching()\n//                 }\n//             },\n//             finalize:{\n//                 returnType: 'void',\n//                 arguments:[''],\n//                 implementation:function (){\n//                     this.$super.stopWatching()\n//                 }\n//             },\n//             onEvent:function(event,path){\n//                 console.log(\"event :\"+event)\n//                 console.log(\"path :\"+path)\n//             }\n//\n//         }\n//     });\n//     var FileWatcher = LuaFileObserver.$new(LUA_PATH)\n//     FileObserver.onEvent.implementation = function (event,path){\n//         console.log(\"event :\"+event)\n//         console.log(\"path :\"+path)\n//     }\n//     FileWatcher.startWatching()\n// })\nvar  gettid = new NativeFunction(Module.findExportByName(null,\"gettid\"),'int',[])\n\nvar status = 0\n\nfunction LuaFileWatcher(){\n\n    var pthread_mutex_init = new NativeFunction(Module.findExportByName(null,\"pthread_mutex_init\"),'int',['pointer','pointer'])\n    var pthread_mutex_lock = new NativeFunction(Module.findExportByName(null,\"pthread_mutex_lock\"),'int',['pointer'])\n    var pthread_mutex_unlock = new NativeFunction(Module.findExportByName(null,\"pthread_mutex_unlock\"),'int',['pointer'])\n\n    var inotify_init = new NativeFunction(Module.findExportByName(null,\"inotify_init\"),'int',[])\n    var inotify_add_watch = new NativeFunction(Module.findExportByName(null,\"inotify_add_watch\"),'int',['int','pointer','int'])\n    const read = new NativeFunction(Module.findExportByName(null,\"read\"),'int',['int','pointer','int']);\n    var fd = inotify_init()\n    var wd = inotify_add_watch(fd,Memory.allocUtf8String(LUA_PATH),256) //ALL_EVENTS = 4095,OPEN=32\n    console.log(\"fd \"+fd+\",wd \"+wd)\n    const inotify_event_len = 0x10\n    var data = Memory.alloc(inotify_event_len*10);\n    while (1){\n        let readlen = read(fd,data,inotify_event_len*10-1)\n        if( readlen<0){\n            console.log('[+] Unable to read  [!] ');\n            continue\n        }\n        console.log(readlen,data)\n\n        // struct inotify_event {\n        //     __s32 wd;\n        //     __u32 ;\n        //     __u32 cookie;\n        //     __u32 len;\n        //     char name[0];\n        // };\n        for (let i = 0; i < (readlen/0x10) ; i++) {\n            let readData = data.add(i*0x10)\n            let envent = []\n            envent.wd = readData.readS32();\n            envent.mask = readData.add(4).readU32();\n            envent.cookie = readData.add(8).readU32();\n            envent.len = readData.add(12).readU32();\n            envent.name = readData.add(16).readCString();\n            console.log('open file : ',envent.name,envent.mask)\n            if(envent.mask!=256)\n                continue;\n                var mutex = Memory.alloc(Process.pointerSize)\n                pthread_mutex_init(mutex,new NativePointer(0))\n                 console.log(\"run thread pid \"+Process.id +\" run \"+gettid())\n                pthread_mutex_lock(mutex)\n\n                try{\n                    status = 1\n                    console.log('----------------------')\n                    let luaname = envent.name.replaceAll(\"_\",\".\")\n                    console.log(\"luaname\"+luaname)\n                    var scr ='if string.find(package.path,\"/data/data/package_name/luadump/\") == nil then\\n' +\n                        '    package.path = package.path .. \";/data/data/package_name/luadump/?\"\\n' +\n                        'end\\n'+\n                        'require(\\\"HotFixOOOK\\\")\\n'+\n                        'hotfix(\\\"'+luaname+'\\\")'\n                    var luaL_loadstring_ret = luaL_loadstring(lua_State,Memory.allocUtf8String(scr))\n                    console.log(\"luaL_loadstring_ret  : \"+luaL_loadstring_ret)\n                    send(\"load lua init ret \"+ lua_pcall(lua_State,0,0,0) + \"  str:\"+lua_tolstring(lua_State, -1).readCString())\n\n                }catch (e) {\n                    send(\"err:\"+e.toString())\n                }finally {\n                    pthread_mutex_unlock(mutex)\n                    status = 0\n                }\n\n        }\n\n    }\n\n}\n\nvar  pthread_create = new NativeFunction(Module.findExportByName(null,\"pthread_create\"),'int',['pointer','pointer','pointer','pointer'])\nvar  pthread_join = new NativeFunction(Module.findExportByName(null,\"pthread_join\"),'int',['pointer','pointer'])\nvar LuaFileWatcherNative = new NativeCallback(LuaFileWatcher,'void',['void'])\n\n\n// 启动新线程对目标目录进行文件监控。\nvar pthread_t = Memory.alloc(16).writeLong(0)\npthread_create(pthread_t,new NativePointer(0),LuaFileWatcherNative,new NativePointer(0))\nconsole.log(\"run pthread_create pid \"+Process.id +\" run \"+gettid())\n\n\nvar libil2cpp = null;\nwhile(libil2cpp == null){\n    libil2cpp = Process.findModuleByName(\"libil2cpp.so\");\n}\nsend(libil2cpp);\n\nvar module = null;\nwhile(module == null){\n    module = Process.findModuleByName(\"libxlua.so\");\n}\nsend(module);\n\nInterceptor.attach(Module.findExportByName(\"libxlua.so\",\"luaL_loadbufferx\"),{\n    onEnter:function(args){\n        const name = Memory.readCString(args[3]);\n        console.log(\"luaL_loadbufferx  name :\",name)\n    }\n});\n\n\n\nInterceptor.attach(Module.findExportByName(\"libxlua.so\",\"luaL_openlibs\"),{\n    onEnter:function(args){\n        send(\"lua_State:\"+args[0])\n        lua_State = ptr(args[0])\n        luaL_loadfilex = new NativeFunction(Module.findExportByName(\"libxlua.so\",\"luaL_loadfilex\"),'int',['pointer','pointer'])\n        luaL_loadstring = new NativeFunction(Module.findExportByName(\"libxlua.so\",\"luaL_loadstring\"),'int',['pointer','pointer'])\n        lua_pcall = new NativeFunction(Module.findExportByName(\"libxlua.so\",\"lua_pcall\"),'int',['pointer','int','int','int'])\n        lua_tolstring = new NativeFunction(Module.findExportByName(\"libxlua.so\",\"lua_tolstring\"),'pointer',['pointer','int'])\n\n        luaL_loadbufferx = new NativeFunction(Module.findExportByName(\"libxlua.so\",\"luaL_loadbufferx\"),'int',['pointer','pointer','int','pointer','pointer'])\n\n    },onLeave:function (ret) {\n    }\n});\n\n\n"
  },
  {
    "path": "InjectFrida/LIEFInjectFrida.py",
    "content": "import argparse\nimport os\nimport shutil\nimport sys\nimport zipfile\nimport lief\nimport sys\n\n\"\"\"\n 使用方法：\n   python3 需要注入的apk  输出路径（注意结尾不要添加/） 注入so的名字（最好是第一个加载的） \n            -apksign（可选项，写了就一键签名） -persistence(反正只多一个config文件，最好加上)\n\"\"\"\ndef getpwd():\n    pwd = sys.path[0]\n    if os.path.isfile(pwd):\n        pwd = os.path.dirname(pwd)\n    return pwd\n\n\ndef getpwd():\n    pwd = sys.path[0]\n    if os.path.isfile(pwd):\n        pwd = os.path.dirname(pwd)\n    return pwd\n\nclass LIEFInject:\n    def __init__(self,args):\n        has_lib = False\n        with zipfile.ZipFile(args.input, 'r') as apk_file:\n            for item in apk_file.infolist():\n                if item.filename.endswith(\".so\"):\n                    has_lib = True\n                    break\n        if not has_lib:\n            print('apk can\\'t find so')\n            exit(1)\n        self.apkpath = args.input\n        self.outdir  = args.output\n        self.soname  = args.soname\n        self.deletelist = []\n        self.toolPath = getpwd() + r\"\\tools\"\n\n\n    def injectso(self):\n        injectsolist = []\n        with zipfile.ZipFile(self.apkpath,'r')as apk_file:\n            for item in apk_file.infolist():\n                if item.filename.find(self.soname) != -1:\n                    apk_file.extract(item.filename)\n                    self.deletelist.append(item.filename)\n                    injectsolist.append(item.filename)\n        #x86有一点问题，且不支持x86_64\n        for soname in injectsolist:\n            # if soname.find(\"x86_64\") != -1:\n            if soname.find(\"x86\") != -1:\n                continue\n            so = lief.parse(os.getcwd()+\"\\\\\"+soname)\n            so.add_library(\"libfrida-gadget.so\")\n            so.write(soname+\"gadget.so\")\n\n\n    def modifyapk(self):\n        (path, filename) = os.path.split(self.apkpath)\n        (file, ext) = os.path.splitext(filename)\n        outapk = os.path.join(self.outdir,file+\"_frida.apk\")\n        with zipfile.ZipFile(self.apkpath, 'r')as orig_file:\n            with zipfile.ZipFile(outapk, 'w')as out_file:\n                for item in orig_file.infolist():\n                    if item.filename.find(self.soname) != -1 and os.path.exists(os.getcwd()+\"\\\\\"+item.filename+\"gadget.so\"):\n                        out_file.write(os.getcwd()+\"\\\\\"+item.filename+\"gadget.so\",arcname=item.filename)\n                        if item.filename.find(\"lib/armeabi-v7a\") != -1:\n                            out_file.write(os.path.join(self.toolPath,\"frida-gadget-14.2.18-android-arm.so\"),\n                                           arcname=\"lib/armeabi-v7a/libfrida-gadget.so\")\n                            print(\"add lib/armeabi-v7a/libfrida-gadget.so\")\n                        if item.filename.find(\"lib/arm64-v8a\") != -1:\n                            out_file.write(os.path.join(self.toolPath, \"frida-gadget-14.2.18-android-arm64.so\"),\n                                           arcname=\"lib/arm64-v8a/libfrida-gadget.so\")\n                            print(\"add lib/arm64-v8a/libfrida-gadget.so\")\n                        if item.filename.find(\"lib/x86/\") != -1:\n                            out_file.write(os.path.join(self.toolPath, \"frida-gadget-14.2.18-android-x86.so\"),\n                                           arcname=\"lib/x86/libfrida-gadget.so\")\n                            print(\"add lib/x86/libfrida-gadget.so\")\n                        continue\n                    if item.filename.find(\"META-INF\") == -1:\n                        out_file.writestr(item, orig_file.read(item.filename))\n\n        shutil.rmtree(\"lib\")\n        return outapk\n\n    def addHook(self,apk_path):\n        with zipfile.ZipFile(apk_path, 'a')as apk_file:\n            for item in apk_file.infolist():\n                if item.filename == \"lib/armeabi-v7a/libfrida-gadget.so\":\n                    apk_file.write(os.path.join(self.toolPath, \"libfrida-gadget.config.so\"),\n                                   arcname=\"lib/armeabi-v7a/libfrida-gadget.config.so\")\n                    print(\"add lib/armeabi-v7a/libfrida-gadget.config.so\")\n                if item.filename == \"lib/arm64-v8a/libfrida-gadget.so\":\n                    apk_file.write(os.path.join(self.toolPath, \"libfrida-gadget.config.so\"),\n                                   arcname=\"lib/arm64-v8a/libfrida-gadget.config.so\")\n                    print(\"add lib/arm64-v8a/libfrida-gadget.config.so\")\n                if item.filename == \"lib/x86/libfrida-gadget.so\":\n                    apk_file.write(os.path.join(self.toolPath, \"libfrida-gadget.config.so\"),\n                                   arcname=\"lib/x86/libfrida-gadget.config.so\")\n                    print(\"add lib/x86/libfrida-gadget.config.so\")\n                continue\n\n\n\n    def signApk(self,apk_path):\n        keystore = os.path.join(self.toolPath,'APPkeystore.jks')\n        alias = 'key0'\n        pswd = 'qwer1234'\n        aliaspswd = 'qwer1234'\n\n        apkname = os.path.splitext(os.path.split(apk_path)[1])[0]\n        outfile = os.path.join(os.path.split(apk_path)[0], apkname + \"_Signed.apk\")\n\n        cmd = 'java -jar %s\\\\apksignerNew.jar sign --ks %s --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out %s %s'% \\\n              (self.toolPath,keystore, alias,pswd,aliaspswd,outfile,apk_path)\n        # print(cmd)\n        os.system(cmd)\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser()\n    parser.add_argument('input', help=\"apk path\")\n    parser.add_argument('output', help=\"Folder to store output files\")\n    parser.add_argument('soname', help=\"the so name of apk first load  \")\n    parser.add_argument('-apksign', help=\"Sign apk\", action='store_true')\n    parser.add_argument('-persistence', help=\"HOOK Persistence \", action='store_true')\n\n    args = parser.parse_args()\n    liefs = LIEFInject(args)\n    liefs.injectso()\n    out = liefs.modifyapk()\n    if args.persistence:\n        liefs.addHook(out)\n    if args.apksign:\n        liefs.signApk(out)\n\n    print(u\"sucess, new apk :\"+out)\n\n"
  },
  {
    "path": "InjectFrida/SmaliInjectFrida.py",
    "content": "import argparse\nimport os\nimport re\nimport shutil\nimport subprocess\nimport zipfile\n\n\nclass  SmaliInject:\n    def __init__(self,args):\n        has_lib = False\n        with zipfile.ZipFile(args.input, 'r') as apk_file:\n            for item in apk_file.infolist():\n                if item.filename.endswith(\".so\"):\n                    has_lib = True\n                    break\n        if has_lib:\n            print('apk find so , Use LIEF inject is better')\n            proceed = input(\"Keep running ? [Y/N]\")\n            if proceed == 'Y' or proceed == 'y':\n                print(\"----- Smali inject -----\")\n            else:\n                exit(0)\n        self.apkpath = args.input\n        self.outdir = args.output\n        self.deletelist = []\n        self.toolPath = os.getcwd() + r\"\\tools\"\n        self.decompileDir = os.getcwd() + r\"\\decompile\"\n        self.dexPath = os.getcwd() + r\"\\dex\"\n        self.dexList = []\n        apkfile = zipfile.ZipFile(self.apkpath, 'r')\n        for file_name in apkfile.namelist():\n            if file_name.endswith(\".dex\") and file_name.startswith(\"classes\"):\n                if not os.path.exists(self.dexPath):\n                    os.mkdir(self.dexPath)\n                apkfile.extract(file_name, self.dexPath)\n                self.dexList.append(os.path.join(self.dexPath, file_name))\n\n    def injectso(self):\n        target_activity = self.get_launchable_activity_aapt()\n        print(target_activity)\n        for dex in self.dexList:\n            print(dex)\n            if self.dexDecompile(dex):\n                smali_path = os.path.join(self.decompileDir,target_activity.replace('.','\\\\'))+\".smali\"\n                print(smali_path)\n                with open(smali_path, 'r') as fp:\n                    lines = fp.readlines()\n                    has_clinit = False\n                    start = 0\n                    for i in range(len(lines)):\n                        if lines[i].find(\".source\") != -1:\n                            start = i\n                        if lines[i].find(\".method static constructor <clinit>()V\") != -1:\n                            if lines[i + 3].find(\".line\") != -1:\n                                code_line = lines[i + 3][-3:]\n                                lines.insert(i + 3, \"%s%s\\r\" % (lines[i + 3][0:-3], str(int(code_line) - 2)))\n                                print(\"%s%s\" % (lines[i + 3][0:-3], str(int(code_line) - 2)))\n                                lines.insert(i + 4, \"const-string v0, \\\"frida-gadget\\\"\\r\")\n                                lines.insert(i + 5,\n                                             \"invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\\r\")\n                                has_clinit = True\n                                break\n                    if not has_clinit:\n                        lines.insert(start + 1, \".method static constructor <clinit>()V\\r\")\n                        lines.insert(start + 2, \".registers 1\\r\")\n                        lines.insert(start + 3, \".line 10\\r\")\n                        lines.insert(start + 4, \"const-string v0, \\\"frida-gadget\\\"\\r\")\n                        lines.insert(start + 5,\n                                     \"invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V\\r\")\n                        lines.insert(start + 6, \"return-void\\r\")\n                        lines.insert(start + 7, \".end method\\r\")\n\n                    with open(smali_path, \"w\") as fp:\n                        fp.writelines(lines)\n                self.dexCompile(dex)\n\n    def modifyapk(self):\n        (path, filename) = os.path.split(self.apkpath)\n        (file, ext) = os.path.splitext(filename)\n        outapk = os.path.join(self.outdir, file + \"_frida.apk\")\n        with zipfile.ZipFile(self.apkpath, 'r')as orig_file:\n            with zipfile.ZipFile(outapk, 'w')as out_file:\n                for item in orig_file.infolist():\n                    if item.filename.startswith(\"classes\") and item.filename.endswith(\".dex\"):\n                        continue\n                    if item.filename.find(\"META-INF\") == -1 :\n                        out_file.writestr(item, orig_file.read(item.filename))\n                for dex in self.dexList:\n                    out_file.write(dex,os.path.split(dex)[1])\n                out_file.write(os.path.join(self.toolPath, \"frida-gadget-14.2.18-android-arm.so\"),\n                               arcname=\"lib/armeabi-v7a/libfrida-gadget.so\")\n                print(\"add lib/armeabi-v7a/libfrida-gadget.so\")\n                out_file.write(os.path.join(self.toolPath, \"frida-gadget-14.2.18-android-arm64.so\"),\n                               arcname=\"lib/arm64-v8a/libfrida-gadget.so\")\n                print(\"add lib/arm64-v8a/libfrida-gadget.so\")\n                out_file.write(os.path.join(self.toolPath, \"frida-gadget-14.2.18-android-x86.so\"),\n                               arcname=\"lib/x86/libfrida-gadget.so\")\n                print(\"add lib/x86/libfrida-gadget.so\")\n        shutil.rmtree(\"dex\")\n        shutil.rmtree(\"decompile\")\n        return outapk\n\n    def addHook(self,apk_path):\n        with zipfile.ZipFile(apk_path, 'a')as apk_file:\n            for item in apk_file.infolist():\n                if item.filename == \"lib/armeabi-v7a/libfrida-gadget.so\":\n                    apk_file.write(os.path.join(self.toolPath, \"libfrida-gadget.config.so\"),\n                                   arcname=\"lib/armeabi-v7a/libfrida-gadget.config.so\")\n                    print(\"add lib/armeabi-v7a/libfrida-gadget.config.so\")\n                if item.filename == \"lib/arm64-v8a/libfrida-gadget.so\":\n                    apk_file.write(os.path.join(self.toolPath, \"libfrida-gadget.config.so\"),\n                                   arcname=\"lib/arm64-v8a/libfrida-gadget.config.so\")\n                    print(\"add lib/arm64-v8a/libfrida-gadget.config.so\")\n                if item.filename == \"lib/x86/libfrida-gadget.so\":\n                    apk_file.write(os.path.join(self.toolPath, \"libfrida-gadget.config.so\"),\n                                   arcname=\"lib/x86/libfrida-gadget.config.so\")\n                    print(\"add lib/x86/libfrida-gadget.config.so\")\n                continue\n\n    def signApk(self,apk_path):\n        keystore = os.path.join(self.toolPath,'APPkeystore.jks')\n        alias = 'key0'\n        pswd = 'qwer1234'\n        aliaspswd = 'qwer1234'\n\n        apkname = os.path.splitext(os.path.split(apk_path)[1])[0]\n        outfile = os.path.join(os.path.split(apk_path)[0], apkname + \"_Signed.apk\")\n\n        cmd = 'java -jar %s\\\\apksignerNew.jar sign --ks %s --ks-key-alias %s --ks-pass pass:%s --key-pass pass:%s --out %s %s'% \\\n              (self.toolPath,keystore, alias,pswd,aliaspswd,outfile,apk_path)\n        os.system(cmd)\n\n    def get_launchable_activity_aapt(self):\n\n        aapt_path = os.path.join(self.toolPath, 'aapt.exe')\n        cmd = '%s dump badging \"%s\" ' % (aapt_path, self.apkpath)\n        p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)\n        out,err = p.communicate()\n        cmd_output = out.decode('utf-8').split('\\r')\n        for line in cmd_output:\n            pattern = re.compile(\"launchable-activity: name='(\\S+)'\")\n            match = pattern.search(line)\n            if match:\n                # print match.group()[27:-1]\n                return match.group()[27:-1]\n    def dexCompile(self,dexPath):\n        baksmaliJarPath = os.path.join(self.toolPath, \"smali-2.5.2.jar\")\n        command = 'java -jar \\\"%s\\\" assemble -o \\\"%s\\\" \\\"%s\\\"' % (baksmaliJarPath, dexPath, self.decompileDir)\n        os.system(command)\n        if not os.path.exists(dexPath):\n            print(u\"反编译失败\")\n    def dexDecompile(self,dexPath):\n        if os.path.exists(self.decompileDir):\n            shutil.rmtree(self.decompileDir)\n        baksmaliJarPath = os.path.join(self.toolPath, \"baksmali-2.5.2.jar\")\n        if not os.path.exists(dexPath):\n            print(u\"[dexDecompile] 文件%s不存在\", dexPath)\n            return False\n        if not os.path.exists(baksmaliJarPath):\n            print(u\"[dexDecompile] 文件%s不存在\", baksmaliJarPath)\n            return False\n        command = 'java -jar \\\"%s\\\" disassemble -o \\\"%s\\\" \\\"%s\\\"' % (baksmaliJarPath, self.decompileDir, dexPath)\n        os.system(command)\n        if not os.path.exists(self.decompileDir):\n            print(u\"[dexDecompile] 路径%s不存在\", self.decompileDir)\n            return False\n        return True\n\n\nif __name__ == \"__main__\":\n\n    parser = argparse.ArgumentParser()\n    parser.add_argument('input', help=\"apk path\")\n    parser.add_argument('output', help=\"Folder to store output files\")\n    parser.add_argument('-apksign', help=\"Sign apk\", action='store_true')\n    parser.add_argument('-persistence', help=\"HOOK Persistence \", action='store_true')\n\n    args = parser.parse_args()\n    tool = SmaliInject(args)\n    tool.injectso()\n    out = tool.modifyapk()\n    if args.persistence:\n        tool.addHook(out)\n    if args.apksign:\n        tool.signApk(out)\n\n\n    print(u\"sucess, new apk :\"+out)"
  },
  {
    "path": "README.md",
    "content": "# UtilScript\n\nfrida  赛高~ o(￣▽￣)ｄ\n\n## game \n\n一些脚本：\n\nFrida-cocos-lua-dump.py dump cocos游戏的lua代码\n\nFrida-mono-dump.py dump unity mono 的dll\n\nyuansheninject.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) 里的代码 \n\nexportCode.py 是ida 导出伪代码到 cpp文件里\n\nGGHook.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)\n\nGenShin-3.2-Dump.js 原神3.2版本符号信息dump [IL2CPP runtime dump](https://bbs.pediy.com/thread-275146.htm)\n\n## InjectFrida\n\nfrida注入apk的两种实现方式：\n\n[非root环境下frida持久化的两种方式及脚本](https://bbs.pediy.com/thread-268175.htm)\n\n使用方法：\npython3 script.py 需要注入的apk  输出路径（注意结尾不要添加/） 注入so的名字（最好是第一个加载的） apksign（可选项，写了就一键签名） -persistence(反正只多一个config文件，最好加上)\n\n## lua\n\nGGInjector64.lua  使用 gameguardian lua脚本 实现64位elf文件解析"
  },
  {
    "path": "exportCode.py",
    "content": "import idaapi\nimport idautils\n\ndef decompile(func):\n    try:\n        func_str = idaapi.decompile(func)\n    except:\n        return \" decompile faild \\n\"\n    return str(func_str)\n\ndef main():\n    if not idaapi.init_hexrays_plugin():\n        return False\n    output = GetInputFile().split('.')[0]+'.cpp'\n    f = open(output,'a')\n    for segea in Segments():\n        for funcea in idautils.Functions(segea, SegEnd(segea)):\n            code = decompile(funcea)\n            f.write(code)\n    f.close()\n\nif main():\n    idaapi.term_hexrays_plugin()\n\n\n\n\n\n"
  },
  {
    "path": "game/Frida-cocos-lua-dump.py",
    "content": "# encoding: UTF-8\n\nimport sys\nimport frida\n\n\"\"\"\n     该脚本用于dump cocos 使用的 lua 脚本\n     dump 文件保存在 /sdcard/fridadump文件夹中，\n     如果 fridadump 文件夹中存在lua文件，就会加载fridadump中的lua文件\n     游戏安全测试好帮手，(#^.^#)\n\"\"\"\n\ndevice = frida.get_usb_device()\npid = device.spawn([\"com.nayijian.guanwang\"])\nsession = device.attach(pid)\ndevice.resume(pid)\n\nscr = \"\"\"\nvar APP_NAME = \"com.nayijian.guanwang\"\n\nvar module = null;\nwhile(module == null){\n    module = Process.findModuleByName(\"libil2cpp.so\");\n}\nsend(module);\n\nInterceptor.attach(Module.findExportByName(null,\"luaL_loadbufferx\"),{\n    onEnter:function(args){\n        var name = Memory.readCString(args[3]);\n        send(name.length);\n        if(name.length < 50){\n            send(name);\n\n            this.Path = name.substring(0,name.lastIndexOf(\"/\"));\n            this.file = name.substring(name.lastIndexOf(\"/\")+1,name.length);\n            if(access(\"/sdcard/fridadump/lua/\"+this.Path) == -1){ //文件夹不存在\n                folder_mkdirs(this.Path);               \n            }\n            if(access(\"/sdcard/fridadump/lua/\"+name) == 0 ){//文件存在\n                var data = read_lua(\"/sdcard/fridadump/lua/\"+name);\n                send(data);\n                args[1] = data.data;\n                args[2] = new NativePointer(ptr(data.size));\n                send(\"do load file :\" + name);\n                \n            }else{\n                Dump(\"/sdcard/fridadump/lua/\"+name,args[1],args[2].toInt32());\n            }\n            \n        }\n\n    }\n});\n\nfunction Dump(filePath,data,datalen){\n    send(\"dump  : \"+ filePath);\n    var dumpfile = new File(filePath,\"wb\"); \n    dumpfile.write(data.readByteArray(datalen));\n    dumpfile.close();\n}\n\nfunction access(filePath){\n    var ptr_access = Module.findExportByName(\"libc.so\",\"access\");\n    var func_access = new NativeFunction(ptr_access,'int',['pointer','int']);\n    var ptr_filepath = Memory.allocUtf8String(filePath);\n    var ret = func_access(ptr_filepath,0);\n    return ret;\n}\n\nfunction mkdir(Path){\n    var ptr_mkdir = Module.findExportByName(\"libc.so\",\"mkdir\");\n    var func_mkdir = new NativeFunction(ptr_mkdir,'int',['pointer','int']);\n    var ptr_filepath = Memory.allocUtf8String(Path);\n    var ret = func_mkdir(ptr_filepath,777);\n    return ret;\n}\n\nfunction folder_mkdirs(p){\n    var p_list = p.split(\"/\");\n    var pp = \"/sdcard/fridadump/lua\";\n    for(var i = 0;i< p_list.length  ;i++){\n        pp = pp + \"/\" + p_list[i];\n        if(access(pp) != 0){\n            var x = mkdir(pp)\n            send(\"mkdir :\"+pp+\"ret :\" +x);\n        }\n    }\n    \n}\n// frida file 对象没有read \nfunction read_lua(filePath){\n    var ptr_open = Module.findExportByName(\"libc.so\",\"open\");\n    const open = new NativeFunction(ptr_open,'int',['pointer','int']);\n\n    var ptr_read = Module.findExportByName(\"libc.so\",\"read\");\n    const read = new NativeFunction(ptr_read,'int',['int','pointer','int']);\n\n    var ptr_close = Module.findExportByName(\"libc.so\",\"close\");\n    const close = new NativeFunction(ptr_close,'int',['int']);\n\n    var fd = open(Memory.allocUtf8String(filePath),0);\n    var size = get_file_size(fd);\n    if(size >0){\n        var data = Memory.alloc(size + 5);\n        if( read(fd,data,size) <0){\n            console.log('[+] Unable to read DLL [!]');\n            close(fd);\n            return 0;\n        }\n        close(fd);\n        return {data:data,size:size};\n    }\n\n}\n\nfunction get_file_size(fd){\n    var statBuff = Memory.alloc(500);\n    var fstatSymbol = Module.findExportByName('libc.so', 'fstat');\n    var fstat = new NativeFunction(fstatSymbol, 'int', ['int', 'pointer']);\n    if(fd > 0) {\n        var ret = fstat(fd, statBuff);\n        if(ret < 0) { console.log('[+] fstat --> failed [!]');\n        }\n    }\n    var size = Memory.readS32(statBuff.add(0x30));\n    if(size > 0) {\n            return size;\n        } else {\n            return 0;\n    }\n}\n\n\"\"\"\n\ndef on_message(message, data):\n    if message['type'] == 'send':\n        print(\"[*] {0}\".format(message['payload']))\n    else:\n        print(message)\n\n\nscript = session.create_script(scr)\nscript.on(\"message\", on_message)\nscript.load()\nsys.stdin.read()\n\n\n"
  },
  {
    "path": "game/Frida-mono-dump.py",
    "content": "import os\nimport sys\nimport frida\n\n\n\"\"\"\n    该脚本用于dump unity mono 的dll，\n    dll 未保护 使用  mono_image_open_from_data_with_name，\n    dll 被保护（加密，主要是TX），使用 do_mono_image_load,这是一个非导出函数，在libmono.so搜索字符串 “data-%p”即可。\n    具体原因及讲解见大佬18年帖子：https://bbs.pediy.com/thread-247487.htm\n    \n    ps.\n    需要 手动创建 两个文件夹\n    1. /sdcard/fridadump  2. /data/data/app_anme/frida\n\n\"\"\"\n\nAPP_NAME = \"com.tencent.pocket\"\n\ndef pull_dll():\n    inpath = pulldir = \"/data/data/\" + APP_NAME + \"/frida\"\n    cmd_cp = \"adb shell su -c 'cp -r \" + inpath + \" /sdcard/fridadump ' \"\n    print(cmd_cp)\n    cmd_pull = \"adb pull /sdcard/fridadump\"\n    os.system(cmd_cp)\n    os.system(cmd_pull)\n\n\ndef push_dll():\n    path = \"/data/data/\" + APP_NAME\n    cmd_push = \"adb push fridadump /sdcard\"\n    cmd_cp = \" adb shell su -c 'cp -r /sdcard/fridadump/frida \" + path +\" '\"\n    print(cmd_cp)\n    os.system(cmd_push)\n    os.system(cmd_cp)\n\n\n\n\ndevice = frida.get_usb_device()\npid = device.spawn([\"com.DefaultCompany.unity2020\"])\nsession = device.attach(pid)\ndevice.resume(pid)\n\nscr = \"\"\"\nvar DUMP_FILE_PATH = \"/data/data/com.tencent.pocket/frida/\";\nvar APP_NAME = \"com.tencent.pocket\"\nfunction DumpDll(filePath,data,datalen){\n\n    send(\"dump dll : \"+ filePath);\n    var dumpfile = new File(filePath,\"wb\");\n    dumpfile.write(data.readByteArray(datalen));\n    dumpfile.close();\n\n}\n\n\nInterceptor.attach(Module.findExportByName(null , \"dlopen\"), {\n    onEnter: function(args) {\n        var soName = args[0].readCString();\n        if(soName.indexOf(APP_NAME) != -1 && soName.indexOf(\"libmono.so\") != -1){\n            send(\"dlopen load :\"+soName);\n            this.hook = true;\n        }\n    },\n    onLeave:function(retval){\n            if(this.hook == true){\n                do_image_hook();\n            }\n    }\n});\n\n\nfunction do_image_hook(){\n\nvar module = Process.getModuleByName(\"libmono.so\");\nsend(module.base);\nInterceptor.attach(ptr(module.base).add(0x194878),{ //do_mono_image_load()\n    onEnter:function(args){\n        var images = args[0];\n        var name = images.add(20).readPointer().readCString();\n        var data = images.add(8).readPointer();\n        var length = images.add(12).readPointer()\n\n        send(name);\n        send(length);\n         var s = name.split(\"/\");\n         var filePath = DUMP_FILE_PATH + s[s.length -1];\n        DumpDll(filePath,data,length.toInt32());\n\n    }\n\n});\n\nInterceptor.attach(Module.findExportByName(\"libmono.so\",\"mono_image_open_from_data_with_name\"),{\n        onEnter:function(args){\n\n            var s = args[5].readCString().split(\"/\");\n            var filePath = DUMP_FILE_PATH + s[s.length -1];\n\n            \n               // DumpDll(filePath,args[0],args[1].toInt32());\n                \n         \n\n        }\n    });\n\n}\n\nfunction Check_dump_file(filePath){\n\n    var ptr_access = Module.findExportByName(\"libc.so\",\"access\");\n    var func_access = new NativeFunction(ptr_access,'int',['pointer','int']);\n    var ptr_filepath = Memory.allocUtf8String(filePath);\n    var ret = func_access(ptr_filepath,0);\n    return ret;\n}\n\nfunction get_file_size(fd){\n    var statBuff = Memory.alloc(500);\n    var fstatSymbol = Module.findExportByName('libc.so', 'fstat');\n    var fstat = new NativeFunction(fstatSymbol, 'int', ['int', 'pointer']);\n    if(fd > 0) {\n        var ret = fstat(fd, statBuff);\n        if(ret < 0) { console.log('[+] fstat --> failed [!]');\n        }\n    }\n    var size = Memory.readS32(statBuff.add(0x30));\n    if(size > 0) {\n            return size;\n        } else {\n            return 0;\n    }\n}\n\n// frida file 对象没有read\nfunction do_load_dll(filePath){\n    var ptr_open = Module.findExportByName(\"libc.so\",\"open\");\n    const open = new NativeFunction(ptr_open,'int',['pointer','int']);\n\n    var ptr_read = Module.findExportByName(\"libc.so\",\"read\");\n    const read = new NativeFunction(ptr_read,'int',['int','pointer','int']);\n\n    var ptr_close = Module.findExportByName(\"libc.so\",\"close\");\n    const close = new NativeFunction(ptr_close,'int',['int']);\n\n    var fd = open(Memory.allocUtf8String(filePath),0);\n    var size = get_file_size(fd);\n    if(size >0){\n        var data = Memory.alloc(size + 5);\n        if( read(fd,data,size) <0){\n            console.log('[+] Unable to read DLL [!]');\n            close(fd);\n            return 0;\n        }\n        close(fd);\n        return data;\n    }\n\n}\n\n\"\"\"\n\n\n\ndef on_message(message, data):\n    if message['type'] == 'send':\n        print(\"[*] {0}\".format(message['payload']))\n    else:\n        print(message)\n\n\nscript = session.create_script(scr)\nscript.on(\"message\", on_message)\nscript.load()\nsys.stdin.read()\n\n\n\n"
  },
  {
    "path": "game/GGHook.js",
    "content": "Java.performNow(function () {\n    Java.enumerateLoadedClasses({\n        onMatch: function (name, handle) {\n            if (name.startsWith(\"android.ext.Script$\")) {\n                if (name == \"android.ext.Script$isVisible\" || name == \"android.ext.Script$ApiFunction\"\n                    || name == \"android.ext.Script$BusyApiFunction\" || name == \"android.ext.Script$DebugFunctio\"\n                    || name.endsWith(\"$clearResults\"))\n                    return;\n                var klass = Java.use(name);\n                console.log(JSON.stringify(klass));\n                if (\"android.ext.Script$ApiFunction\" == klass.$super.$className || \"android.ext.Script$BusyApiFunction\" == klass.$super.$className) {\n                    for (var _i = 0, _a = klass.$ownMembers; _i < _a.length; _i++) {\n                        var m = _a[_i];\n                        if (m == \"a\" && typeof klass[m] == \"function\") {\n                            try {\n                                Java.use(name).a.overload().implementation = function () {\n                                    console.log(this.a());\n                                    return this.a();\n                                };\n                            }\n                            catch (e) {\n                                console.log(e);\n                                console.log(name);\n                            }\n                        }\n                        if (m == \"d\" && typeof klass[m] == \"function\") {\n                            try {\n                                Java.use(name).d.implementation = function (a) {\n                                    if (name.endsWith(\"searchNumber\")) {\n                                        console.log(\"a1 string :\", a.r(1));\n                                    }\n                                    console.log(name, \":\", a);\n                                    return this.d(a);\n                                };\n                            }\n                            catch (e) {\n                                console.log(e);\n                                console.log(name);\n                            }\n                        }\n                        if (m == \"b\" && typeof klass[m] == \"function\") {\n                            try {\n                                Java.use(name).b.implementation = function (a) {\n                                    console.log(name, \":\", a);\n                                    return this.b(a);\n                                };\n                            }\n                            catch (e) {\n                                console.log(e);\n                                console.log(name);\n                            }\n                        }\n                    }\n                }\n            }\n        },\n        onComplete: function () {\n        }\n    });\n});\nconsole.log(\"end\");"
  },
  {
    "path": "game/GenShin-3.2-Dump.js",
    "content": "let so = Process.findModuleByName(\"libil2cpp.so\")\nlet il2cpp_method_get_name = new NativeFunction(so.base.add(0x4260354),'pointer',['pointer'])\nlet il2cpp_method_get_param = new NativeFunction(so.base.add(0x425FEC4),'pointer',['pointer','int'])\nlet il2cpp_method_get_return_type = new NativeFunction(so.base.add(0x42306EC),'pointer',['pointer'])\n \nlet il2cpp_class_from_type = new NativeFunction(so.base.add(0x4251ED8),'pointer',['pointer'])\nlet il2cpp_class_get_name  = new NativeFunction(so.base.add(0x4252E48),'pointer',['pointer'])\n \n \nInterceptor.attach(so.base.add(0x4252BE4),{\n    onEnter:function (args) {\n        // console.log(\"---------il2cpp_class_get_methods--------\")\n        this.class = args[0]\n \n    },\n    onLeave:function (ret) {\n        try{\n            let classname = this.class.add(40).readPointer().readCString()\n            let namespace = this.class.add(120).readPointer().readCString()\n            let name_ptr = il2cpp_method_get_name(ret)\n            let ret_type = il2cpp_method_get_return_type(ret)\n            let ret_type_class = il2cpp_class_from_type(ret_type)\n            let ret_class_name = il2cpp_class_get_name(ret_type_class)\n \n            //InvokerMethod ret.add(16)  methodPointer ret\n             let parameters_count = ret.add(50).readU8()\n            let pstr = \"(\"\n            for(let idx = 0;idx<parameters_count;idx++){\n                let param = il2cpp_method_get_param(ret,idx)\n                let type = il2cpp_class_from_type(param)\n                let typeName = il2cpp_class_get_name(type)\n                pstr += ptr(typeName).readCString() + \"  a\"+idx +\" ,\"\n            }\n            pstr+=\");\"\n            console.log(\"[*]\"+ret.readPointer()+\"   --> \"+ptr(ret_class_name).readCString()+\"  \"+namespace+\".\"+classname+\".\"+ptr(name_ptr).readCString()+pstr)\n \n        }catch (e) {\n            console.log(e.toString())\n        }\n \n    }\n})"
  },
  {
    "path": "game/yuanshenInject.py",
    "content": "import sys\n\nimport frida\n\ndevice = frida.get_usb_device()\npid = device.spawn([\"com.miHoYo.Yuanshen\"])\nsession = device.attach(pid)\ndevice.resume(pid)\n\nscr = \"\"\"\nvar APP_NAME = \"com.miHoYo.Yuanshen\"\n\nvar module = null;\nwhile(module == null){\n    module = Process.findModuleByName(\"libil2cpp.so\");\n}\nsend(module);\n\nvar unity = Process.findModuleByName(\"libunity.so\");\nsend(unity);\n\nvar x = Interceptor.attach(ptr(unity.base).add(0xb2aecc),{\n    onEnter:function(args){\n    send(args[1]);\n    },onLeave:function(ret){\n       send(ret.sub(1).readUtf8String());\n\n    }\n});\n\nInterceptor.attach(Module.findExportByName(\"libil2cpp.so\",\"il2cpp_class_from_name\"),{\n    onEnter:function(args){\n    //send(args[1].readUtf8String()  + \"  -----  : \"+args[2].readUtf8String());\n    \n    },onLeave:function(ret){\n      \n    }\n});\n\n\n// hook SetupMethodsLocked\nvar p_size = 8;\nInterceptor.attach(ptr(module.base).add(0x72F09EC).add(0x204),{\n    onEnter:function(args){\n    var newMethod = this.context.x20\n    var pointer = newMethod.readPointer();\n    var name = newMethod.add(p_size * 2).readPointer().readCString();\n    var klass = newMethod.add(p_size * 3).readPointer();\n    var klass_name = klass.add(p_size * 2).readPointer().readCString();\n    var klass_paze = klass.add(p_size * 3).readPointer().readCString();\n    send(klass_paze+\".\"+klass_name+\":\"+name+\"    -> \"+pointer.sub(module.base));\n    },onLeave:function(ret){\n     \n    }\n});\n\n\n\n\"\"\"\n\n\n\n\ndef on_message(message, data):\n    if message['type'] == 'send':\n        print(\"[*] {0}\".format(message['payload']))\n    else:\n        print(message)\n\n\nscript = session.create_script(scr)\nscript.on(\"message\", on_message)\nscript.load()\nsys.stdin.read()\n\n\n"
  },
  {
    "path": "lua/GGInjector64.lua",
    "content": "---\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 alert(caption, text)\n\tassert(caption ~= nil, \"\\n\\n>> [alert]: error, caption was nil. <<\\n\\n\")\n\tif text == nil then\n\t\ttext = caption\n\t\tcaption = \"[Info]: Notice\"\n\tend\n\tgg.alert(caption .. \"\\n\\t- \" .. text)\nend\nfunction rwmem(address, SizeOrBuffer)\n\tassert(type(address) ~= \"string\", \"\\n\\n>> [rwmem]: error, address is string. Please check caller. <<\\n\\n\")\n\tassert(address ~= nil, \"\\n\\n>> [rwmem]: error, provided address is nil. <<\\n\\n\")\n\t_rw = {}\n\tif type(SizeOrBuffer) == \"number\" then\n\t\t_ = \"\"\n\t\tfor _ = 1, SizeOrBuffer do _rw[_] = {address = (address - 1) + _, flags = gg.TYPE_BYTE} end\n\t\tfor v, __ in ipairs(gg.getValues(_rw)) do _ = _ .. string.format(\"%02X\", __.value & 0xFF) end\n\t\treturn _\n\tend\n\tByte = {} SizeOrBuffer:gsub(\"..\", function(x)\n\t\tByte[#Byte + 1] = x _rw[#Byte] = {address = (address - 1) + #Byte, flags = gg.TYPE_BYTE, value = x .. \"h\"}\n\tend)\n\tgg.setValues(_rw)\nend\nfunction rdstr(address, strsz)\n  assert(address ~= nil, \"\\n\\n>> [rdstr]: error, provided address is nil. <<\\n\\n\")\n  if strsz == nil or type(strsz) ~= \"number\" then strsz = 128 end\n  local str = \"\"\n  for _ in rwmem(address, strsz):gmatch(\"..\") do\n    if _ == \"00\" then break end\n      str = str .. string.char(tonumber(_, 16))\n  end\n  return str\nend\n\n---------------------------\n\nfunction getLibraryBase(lib)\n    print(\"search \".. lib)\n    --print(gg.getRangesList(lib))\n\tfor _, __ in pairs(gg.getRangesList(lib)) do\n        print(sf(\"start 0x%x ~ 0x%x\",__[\"start\"], __[\"end\"]))\n\t\t--if __[\"state\"] == \"Xa\" or __[\"state\"] == \"Xs\" then\n        --    --print(sf(\"start 0x%x ~ 0x%x\",__[\"start\"], __[\"end\"]))\n        return __[\"start\"], __[\"end\"] end\n\t--end\n\treturn nil\nend\nfunction getLibInformation(LibName)\n\tlocal LibBase = getLibraryBase(LibName)\n    if LibBase == nil then\n        print(\"can't find \"..LibName)\n    end\n\tif LibBase ~= nil then\n\t\t_ = gg.getValues({\n\t\t\t{address = LibBase, flags = gg.TYPE_DWORD },\t\t-- Magic\n\t\t\t-- EI_PAD skipped --\n\t\t\t{address = LibBase + 0x12, flags = gg.TYPE_WORD },\t-- Machine\n\t\t\t{address = LibBase + 0x20, flags = gg.TYPE_DWORD },\t-- Program Header Table (PH) Offset\n\t\t\t{address = LibBase + 0x30, flags = gg.TYPE_DWORD },\t-- Flags\n\t\t\t{address = LibBase + 0x36, flags = gg.TYPE_WORD },\t-- Program Header Table (PH) Size Entry\n\t\t\t{address = LibBase + 0x38, flags = gg.TYPE_WORD },\t-- Number Of Entries In Program Header Table (PH)\n\t\t\t})\n\t\tlocal Elf = { -- Elf Information Table Structure--\n\t\t\tMagic\t\t= _[1].value,\n\t\t\tMachine \t= _[2].value,\n\t\t\tPHOffset \t= _[3].value,\n\t\t\tFlags \t\t= _[4].value,\n\t\t\tPHSize \t\t= _[5].value,\n\t\t\tPHNum\t\t= _[6].value,\n\t\t\tpHdr\t\t= {},\n\t\t\tDyn\t\t\t= {},\n\t\t\tSym\t\t\t= {},\n\t\t\tvAddress\t= LibBase\n\t\t}\n        print(sf(\"ELF info Magic %s ,PHOffset 0x%x PHNum 0x%x\",Elf.Magic,Elf.PHOffset,Elf.PHSize))\n\t\tfor _ = 1, Elf.PHNum do -- Parsing Program Header\n\t\t\tlocal _pHdr = LibBase + Elf.PHOffset + (_ * Elf.PHSize)\n\t\t\tlocal pHdr = gg.getValues({\n\t\t\t\t{ address = _pHdr, flags = gg.TYPE_DWORD }, \t\t-- p_type\n\t\t\t\t{ address = _pHdr + 8, flags = gg.TYPE_DWORD }, \t-- p_offset\n\t\t\t\t{ address = _pHdr + 0x10, flags = gg.TYPE_DWORD }, \t-- p_vaddr\n\t\t\t\t{ address = _pHdr + 0x18, flags = gg.TYPE_DWORD },\t-- p_paddr\n\t\t\t\t{ address = _pHdr + 0x20, flags = gg.TYPE_DWORD },\t-- p_filesz\n\t\t\t\t{ address = _pHdr + 0x28, flags = gg.TYPE_DWORD },\t-- p_memsz\n\t\t\t\t{ address = _pHdr + 4, flags = gg.TYPE_DWORD },\t-- p_flags\n\t\t\t\t--{ address = _pHdr + 0x30, flags = gg.TYPE_DWORD },\t-- p_align\n\t\t\t})\n\t\t\tElf.pHdr[_] = { -- All data in Program Header now in Elf.pHdr[Elf.PHNum]\n\t\t\t\tp_type\t\t= pHdr[1].value,\n\t\t\t\tp_offset\t= pHdr[2].value,\n\t\t\t\tp_vaddr\t\t= pHdr[3].value,\n\t\t\t\tp_paddr\t\t= pHdr[4].value,\n\t\t\t\tp_filesz\t= pHdr[5].value,\n\t\t\t\tp_memsz\t\t= pHdr[6].value,\n\t\t\t\tp_flags\t\t= pHdr[7].value,\n\t\t\t\t--p_align\t\t= pHdr[8].value\n\t\t\t}\n            print(sf(\"pHdr type %d offset 0x%x  p_vaddr 0x%x \",pHdr[1].value,pHdr[2].value,pHdr[3].value))\n\t\tend\n\t\tfor _ = 1, Elf.PHNum do  -- Parsing Dynamic Segment\n\t\t\tif Elf.pHdr[_].p_type == 2 then -- PT_DYNAMIC\n\t\t\t\tlocal DynCount = 0\n\t\t\t\twhile true do\n\t\t\t\t\tlocal _Dyn = gg.getValues({\n\t\t\t\t\t\t{ address = LibBase + Elf.pHdr[_].p_vaddr + (DynCount * 8), flags = gg.TYPE_DWORD }, -- d_tag\n\t\t\t\t\t\t{ address = LibBase + Elf.pHdr[_].p_vaddr + 8 + (DynCount * 8), flags = gg.TYPE_DWORD } -- d_ptr / d_val\n\t\t\t\t\t})\n\t\t\t\t\tif _Dyn[1].value == 0 and _Dyn[2].value == 0 then break end -- End of dynamic segment\n\t\t\t\t\tDynCount = DynCount + 1 -- Keep growing !\n\t\t\t\t\tElf.Dyn[DynCount] = { -- All data in Dynamic Segment now in Elf.Dyn[Section]\n\t\t\t\t\t\td_tag = _Dyn[1].value,\n\t\t\t\t\t\td_val = _Dyn[2].value,\n\t\t\t\t\t\td_ptr = _Dyn[2].value\n\t\t\t\t\t}\n\t\t\t\tend\n\t\t\tend\n\t\tend\n\t\treturn Elf\n\tend\n\treturn nil\nend\n\nfunction getSymbolAddress(ElfData, symName)\n\tassert(ElfData ~= nil, \"\\n\\n>> [getSymbolAddress]: error, provided ElfData is nil. <<\\n\\n\")\n\tfor _ = 1, #ElfData.Dyn do\n\t\t\tif 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\n\t\t\tif tonumber(ElfData.Dyn[_].d_tag) == 5 then strtab = ElfData.Dyn[_].d_ptr + ElfData.vAddress end\n\t\t\tif tonumber(ElfData.Dyn[_].d_tag) == 6 then symtab = ElfData.Dyn[_].d_ptr + ElfData.vAddress end\n\tend\n    if nChain ~= nil then\n        for _ = 1, nChain do\n            local sym = symtab + (_ * 0x18)\n            __ = gg.getValues({\n                { address = sym, flags = gg.TYPE_DWORD },\t\t-- st_name\n                { address = sym + 0x4, flags = gg.TYPE_DWORD },\t-- st_value\n            })\n            print(rdstr(strtab + __[1].value) .. \", offset:\"..sf(\"0x%x\",__[1].value))\n            if rdstr(strtab + __[1].value) == symName then\n                return ElfData.vAddress + __[2].value\n            end\n        end\n    else\n        print(\"nChain is nil\")\n    end\n\n\treturn nil\nend\n\nfunction getLib(libName)\n\tgg.toast(\"Searching for '\"..libName..\"', This may take a while. Please wait...\")\n\tlocal m_lib = getLibInformation(libName)\n\tif m_lib ~= nil then\n\t\tprint(sf(\"[getLib]: %s Architecture: 0x%08X\", libName, m_lib.Machine))\n\t\tif m_lib.Machine == 0xb7 then -- Arm 64-bits\n            return m_lib\n\t\tend\n\t\talert(\"[Error]: Unsupported Device !\", \"Currently, only Arm 64-bits device are supported.\")\n\t\tos.exit()\n\t\treturn nil\n\tend\n\n\talert(\"[Error]: Missing dependencies !\", \"One of required shared library '\" .. libName .. \"', has left us in the dark.\")\n\tos.exit()\n\treturn nil\nend\nfunction getSymbol(ElfData, Symname)\n    gg.toast(\"Searching for Symbol '\"..Symname..\"', This may take a while. Please wait...\")\n\tlocal s_address = getSymbolAddress(ElfData, Symname)\n\tif s_address ~= nil then\n\t\treturn s_address\n\tend\n\n\talert(\"[Error]: Missing dependencies !\", \"One of required symbol '\" .. Symname .. \"', has been reported missing.\")\n\tos.exit()\n\treturn nil\nend\n\n\n\n\nlocal m_libdl\t\t= getLib(\"libil2cpp.so\")\nlocal s_dlopen\t= getSymbol(m_libdl, \"il2cpp_assembly_get_image\")\nprint(\"find dlopen \"..s_dlopen)"
  }
]