-
-
[原创]libassist.so 一个NX Lua 自动化脚本注册码分析
-
发表于: 3天前 415
-
NX Lua 好像是一个自动化框架。
NX Lua:`com.nx.*` + `assets/script.lr`,核心都在 `libassist.so`。
路线很简单:先把脚本拿出来定逻辑,再决定动脚本还是动加载。`script.lr` 标记 `enc=1`。这个 enc=1 脚本包不能硬改,否则 UI 绑定会崩,所以后面我一直保持原包不动。
静态只做路线确认,真正干活在动态。Frida spawn 会死,改 attach。hook `lua_load` / `luaL_loadbufferx`,再 `lua_dump` 出标准 Lua 5.3 bytecode,用 unluac 反编译,核心逻辑在 `@脚本/365约车.lua`:输入 `Edreg`,设备码拼接 `WEB_PT("slwyc") + board + device + hardware + model + 初始(filetime)`,MD5 后走云端校验。结论很直接:只要替换这一个脚本即可。
我试过最直接的 enc=0 替换脚本,UI 直接 `view:null` 卡死;LSPosed 会让 JNI_OnLoad 返回 JNI_ERR;嵌入 gadget 会被 linker + execmod 砍死。最后确定走内存拦截:脚本包保持 enc=1 原样,用 native 截胡 `lua_load`。我在 `App.onCreate` 最早处插一行加载 `libfd.so`,保证 hook 先于 `AssistNative.loadLibrary()`,代码:
```smali
const-string v0, "fd"
invoke-static {v0}, Ljava/lang/System;->loadLibrary(Ljava/lang/String;)V
invoke-static {}, Lcom/nx/assist/AssistNative;->loadLibrary()V
```
`libfd.so` 构造函数先关 FDSAN,然后 inline hook `libassist.so` 里 `lua_load`/`luaL_loadbufferx`(固定 offset,运行时 base+offset 取址),只命中 `@脚本/365约车.lua` 时把 reader 换成我自己的 patch 源码:
```c
__attribute__((constructor))
static void init_fdsan_and_hook(void) {
void *h = dlopen("libc.so", RTLD_NOW);
if (h) {
void (*set_level)(int) = dlsym(h, "android_fdsan_set_error_level");
if (set_level) set_level(0);
}
// 轮询 libassist.so base,然后 inline hook lua_load / luaL_loadbufferx
}
static int name_match(const char *name) {
return name && (strstr(name, "365") || strstr(name, "365约车"));
}
int hooked_lua_load(void *L, void *reader, void *data, const char *name, const char *mode) {
if (orig_lua && name_match(name)) {
reader_state_t st = {kPatchLua, kPatchLuaLen, 0};
return orig_lua(L, (void *)(lua_reader_t)patched_reader, &st, name, "t");
}
return orig_lua ? orig_lua(L, reader, data, name, mode) : -1;
}
```
Lua patch 直接让注册通过:
```lua
function Get_REGS()
v7 = "注册登录"
v8 = 9999
v9 = "1"
v10 = ""
return true
end
```
踩坑也就一个关键点:ARM/Thumb 分支位处理错会 SIGILL,所以 hook 地址只在 __thumb__ 模式下才加 LSB。修完后稳定:logcat 能看到 `patch lua_load: @脚本/365约车.lua`,注册页直接过,UI 正常,不再 `view:null`。