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)
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
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.