Androlua逆向

去年dasctf x cbctf有道题是Androlua,学长出的一道题,来看看这个逆向流程.

介绍

首先了解Androlua:

AndroLua 是一个轻量级的移动开发框架,它将 Lua 这种简洁高效的脚本语言引入到 Android 平台上。通过 AndroLua,开发者可以利用 Lua 编程语言进行快速原型开发或者对现有应用程序进行扩展。AndroLua 支持运行 Lua 5.2 版本的代码,并提供了一系列 Android SDK 中的类库供 Lua 脚本调用,让开发者能够轻松地操作设备的各种功能,如网络通信、多媒体处理、传感器数据读取等。

逆向流程

由于是以lua为主要,所以安卓包的作用主要是调用lua文件,开头一般是调用init.lua,main.lua这些文件(放在资源目录中)

可以直接定位相关文件.

一般是不加密,可以直接提取用Lua Decompiler反编译.

倘若加密,一般是libluajava.so中的luaL_loadbufferx方法进行加密.

实战

拿学长的题目看看

private void d() {
        if (new File(this.b + "/init.lua").exists()) {
            try {
                int LloadFile = this.k.LloadFile(this.b + "/init.lua");
                if (LloadFile == 0) {
                    this.k.newTable();
                    LuaObject luaObject = this.k.getLuaObject(-1);
                    this.k.setUpValue(-2, 1);
                    int pcall = this.k.pcall(0, 0, 0);
                    if (pcall == 0) {
                        if (J == null) {
                            LuaObject field = luaObject.getField("app_key");
                            if (field.isString()) {
                                J = field.toString();
                                StatService.setAppKey(field.toString());
                            }
                            LuaObject field2 = luaObject.getField("app_channel");
                            if (field2.isString()) {
                                StatService.setAppChannel(this, field2.toString(), true);
                            }
                            StatService.setOn(this, 1);
                        }
                        LuaObject field3 = luaObject.getField("appname");
                        if (field3.isString()) {
                            setTitle(field3.getString());
                        }
                        LuaObject field4 = luaObject.getField("app_name");
                        if (field4.isString()) {
                            setTitle(field4.getString());
                        }
                        LuaObject field5 = luaObject.getField("debugmode");
                        if (field5.isBoolean()) {
                            this.F = field5.getBoolean();
                        }
                        LuaObject field6 = luaObject.getField("debug_mode");
                        if (field6.isBoolean()) {
                            this.F = field6.getBoolean();
                        }
                        LuaObject field7 = luaObject.getField("theme");
                        if (field7.isNumber()) {
                            setTheme((int) field7.getInteger());
                            return;
                        } else {
                            if (field7.isString()) {
                                setTheme(R.style.class.getField(field7.getString()).getInt(null));
                                return;
                            }
                            return;
                        }
                    }
                    LloadFile = pcall;
                }
                throw new LuaException(a(LloadFile) + ": " + this.k.toString(-1));
            } catch (Exception e) {
                sendMsg(e.getMessage());
            }
        }
    }

可以找到这个(其实压根没理解他的流程,大概就是加载)

那么我们就要去本地库看看,因为这里有加密.

但是很奇怪,我arm库找半天找不到,问了学长说有,后面看了32位的,突然反编译出来(?)

可以用unidbg来hook出来,解密lua.当然解密逻辑还蛮简单的,脚本也可以.

int __fastcall luaL_loadbufferx(int a1, _BYTE *a2, size_t byte_count, int a4, int a5)
{
  _BYTE *v9; // r0
  int v10; // r1
  int v11; // r2
  _DWORD v13[2]; // [sp+8h] [bp-28h] BYREF

  v13[0] = a2;
  v13[1] = byte_count;
  if ( *a2 == 27 && a2[1] != 76 )
  {
    v9 = malloc(byte_count);
    if ( byte_count )
    {
      *v9 = 27;
      if ( byte_count != 1 )
      {
        v10 = 0;
        v11 = 1;
        do
        {
          v10 += byte_count;
          v9[v11] = a2[v11];
          ++v11;
        }
        while ( byte_count != v11 );
      }
    }
    v13[0] = v9;
  }
  return j_lua_load(a1, (int)sub_E6AA, (int)v13, a4, a5);
}
posted @ 2025-04-16 16:55  T0fV404  阅读(141)  评论(0)    收藏  举报