为了获取程序中的lua代码,我们往往选择Hook dofile函数进行dump
然而很多有一定保护的程序里面lua没有dostring,dofile这样的函数,甚至也没有luaL_loadbuffer,
而且这些函数也不太好定位。
这里有一款方便定位的函数,也可以方便的dump代码: luaD_protectedparser
lua(源码/字节码)的解析过程会经过函数luaD_protectedparser
int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
const char *mode) {
struct SParser p;
int status;
incnny(L); /* cannot yield during parsing */
p.z = z; p.name = name; p.mode = mode;
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
decnny(L);
return status;
}
函数如上所示,Hook此函数,可以从其参数ZIO* z中取得lua代码,从char *name中取得代码名。
struct Zio {
size_t n; /* bytes still unread */
const char *p; /* current position in buffer */
lua_Reader reader; /* reader function */
void *data; /* additional data */
lua_State *L; /* Lua state (for reader) */
};
Zio结构中void* data为
typedef struct LoadS {
const char *s;
size_t size;
} LoadS;
即 ((LoadS*)z->data)->s)
就为我们想要的lua代码
这个函数可以通过f_parser函数定位,这个函数往往内联了checkmode函数
static void checkmode (lua_State *L, const char *mode, const char *x) {
if (mode && strchr(mode, x[0]) == NULL) {
luaO_pushfstring(L,
"attempt to load a %s chunk (mode is '%s')", x, mode);
luaD_throw(L, LUA_ERRSYNTAX);
}
}
static void f_parser (lua_State *L, void *ud) {
LClosure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
if (c == LUA_SIGNATURE[0]) {
checkmode(L, p->mode, "binary");
cl = luaU_undump(L, p->z, p->name);
}
else {
checkmode(L, p->mode, "text");
cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c);
}
lua_assert(cl->nupvalues == cl->p->sizeupvalues);
luaF_initupvals(L, cl);
}
搜索字符串attempt to load a
即可定位到f_parser或checkmode函数,再向上寻找一层交叉引用即是luaD_protectedparser
如果是Unity的il2cpp模式,甚至是引用了其他开源库封装lua,只要在外部dll中寻找对应的函数就可以了,它们一般都会有一堆带符号的导出函数。