首页
社区
课程
招聘
[原创]BYTECTF language bindings
发表于: 2021-10-18 16:37 15994

[原创]BYTECTF language bindings

2021-10-18 16:37
15994

题目给了一个 exe 文件和一个 out 文件,猜测是使用 exe 去加载 out 的脚本。out 似乎被加密过了,看不出来是什么文件格式。

ida7.6 打开,exe 是 golang 写的,函数名都被混淆了。

因为 gopclntab 的 magic 是 0xFFFFFFFA ,所以肯定是 go 1.16 版本以上。这里和 go 1.17 的 bindiff 结果最接近,导入 Matched Functions ,恢复大部分 go 函数,找到 main_main。

题目直接运行提示 usage: new_lang binfile ,后面加上给的 out 文件的路径以后正常运行,所以下断 ReadFile。

回溯,runtime_asmstdcall 这类 go 内置函数直接略过,第一个混淆名字的函数 dazZVaWekDxmHOBm

经典 syscall_ptr_LazyProcFind ,还是处于 go 的函数中,继续往上,直到 hDwRGqXZOHitsyulULeUIiCTqaedCidWS。

解密以后就看出来是 lua ,但是文件的 magic 和版本信息好像不太对

函数 ZjulCvXVFufJHreFwkLSR

这里确认是 lua,因为 size_t size 是 8,所以要编译 64 位的 luadec ,但是反编译不出来,怀疑替换了 opcode_table。

程序里有 luago 的字符串, github 搜了一下,找到了源码,https://github.com/zxh0/lua.go 。 git 上有很多 luago 的版本,可是都没实现 stdlib 的 string.dump 函数,而 exe 可以用这个函数,用这个判断。

LnNZNVGrFxUawfmfFtLuzZZpawrA 就是项目中 api_call.go 的 Load 函数。

尝试三种方法找到 opcode_table 的位置:

搜索字符串 MOVE 等,失败(因为出题人把 opcode 的名称都改成了 NONNAME)

根据函数调用关系找到 Execute,得到 opcodes

在 LnNZNVGrFxUawfmfFtLuzZZpawrA (Load)函数返回后,对于每一个 call ,都 F8 ,如果跑飞了,那说明 Execute 在这个 call 里,重复这个过程缩小范围(感觉有时间可以写个小工具,还是挺实用的方法)

off_51FD90 即为 opcode_table 的指针。

红框里的为一组 opcode 的结构,大小 0x20,opcode 的名称被出题人都改成一样的了。这里没法从这判断顺序。尝试两种方法:

特别感谢这位老哥,思路非常牛逼,让相同的代码在题目和我们自己编译的 lua.go 中跑,dump 出两个代码,进行对比,得到 opcode 的顺序。

我修改了一下,帮他补上了 lua 5.3 版本新增的 opcode

check_opcode.lua 要小改一下,主要把 5.1 的 opcode 换成 5.3 的

也要注意这句,因为我们的文件头和版本和原来肯定是不一样的,不要把他们也算在 opcode 的变化里了

写了个小脚本用来试 opcode(毕竟一次很难补全)

这里有几个 -1 (opcode 没有使用或者和原来一样),我们手动处理一下,首先 OP_LOADKX 和 OP_EXTRAARG 直接跟原来的值一样即可,因为根本不会用到,中间的 BXOR 是因为跟原来一样。

然后修改 luadec 中的 lopcodes.h

编译 luadec ,把 new_lang_script.out 的文件头改一下 LuaS,反编译。

逻辑很清楚,但是第 9 位到第 17 位这 9 位 flag 的验证缺失,是在 local flag1 = _(flag) 验证的,应该是个 native 函数。

找到 Execute,对运行指令的位置下断点,一直 F9,直到 flag 读入,对第 9 位下断点,断两次以后来到关键函数。

就是个异或,然后把 flag 拼起来就行了。

总结:学到了很多,下次出题把 lua 明文执行的接口删掉

 
 
 
 
 
void **__usercall dazZVaWekDxmHOBm@<rax>()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  __int64 v2; // r8
  __int64 v3; // r14
  __int64 v4; // rax
  __int64 v5; // rcx
  __int64 v8; // [rsp-8h] [rbp-78h]
  __int64 v9; // [rsp-8h] [rbp-78h]
  __int64 v10; // [rsp+0h] [rbp-70h]
  __int64 v11; // [rsp+0h] [rbp-70h]
  __int64 v12; // [rsp+10h] [rbp-60h]
  __int64 v13; // [rsp+28h] [rbp-48h]
  void *retaddr; // [rsp+70h] [rbp+0h] BYREF
 
  while ( 1 )
  {
    if ( &retaddr <= *(v3 + 16) )
      goto LABEL_12;
    v10 = syscall___ptr_LazyProc__Find(v8);
    if ( !v4 )
      break;
    runtime_gopanic(v9, v10);
LABEL_12:
    v11 = v0;
    v12 = v1;
    v13 = v2;
    runtime_morestack_noctxt();
    v0 = v11;
    v1 = v12;
    v2 = v13;
  }
  if ( syscall_Syscall6() )
    return 0LL;
  if ( !v5 )
    return off_51FD10;
  if ( v5 == 997 )
    return off_51FD20;
  runtime_convT64(v9);
  return &off_580720;
void **__usercall dazZVaWekDxmHOBm@<rax>()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  __int64 v2; // r8
  __int64 v3; // r14
  __int64 v4; // rax
  __int64 v5; // rcx
  __int64 v8; // [rsp-8h] [rbp-78h]
  __int64 v9; // [rsp-8h] [rbp-78h]
  __int64 v10; // [rsp+0h] [rbp-70h]
  __int64 v11; // [rsp+0h] [rbp-70h]
  __int64 v12; // [rsp+10h] [rbp-60h]
  __int64 v13; // [rsp+28h] [rbp-48h]
  void *retaddr; // [rsp+70h] [rbp+0h] BYREF
 
  while ( 1 )
  {
    if ( &retaddr <= *(v3 + 16) )
      goto LABEL_12;
    v10 = syscall___ptr_LazyProc__Find(v8);
    if ( !v4 )
      break;
    runtime_gopanic(v9, v10);
LABEL_12:
    v11 = v0;
    v12 = v1;
    v13 = v2;
    runtime_morestack_noctxt();
    v0 = v11;
    v1 = v12;
    v2 = v13;
  }
  if ( syscall_Syscall6() )
    return 0LL;
  if ( !v5 )
    return off_51FD10;
  if ( v5 == 997 )
    return off_51FD20;
  runtime_convT64(v9);
  return &off_580720;
void hDwRGqXZOHitsyulULeUIiCTqaedCidWS()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  __int64 v2; // rdi
  __int64 v3; // r14
  __int64 v4; // rbx
  __int64 v5; // rax
  __int64 i; // rdx
  __int64 v7; // [rsp-40h] [rbp-68h]
  __int64 v8; // [rsp-38h] [rbp-60h]
  __int64 v9; // [rsp-30h] [rbp-58h]
  __int64 v10; // [rsp-28h] [rbp-50h]
  __int64 v11; // [rsp-20h] [rbp-48h]
  __int64 v12; // [rsp-18h] [rbp-40h]
  void *retaddr; // [rsp+28h] [rbp+0h] BYREF
  __int64 v15; // [rsp+30h] [rbp+8h]
  __int64 v18; // [rsp+40h] [rbp+18h]
 
  while ( &retaddr <= *(v3 + 16) )
  {
    v15 = v0;
    v18 = v1;
    runtime_morestack_noctxt();
    v0 = v15;
    v1 = v18;
  }
  v4 = v1;
  v5 = PWTGSQGCyWF(); //v5 为 out 内容
  if ( !v2 )
  {
    for ( i = 0LL; v4 > i; ++i )
      *(v5 + i) ^= 0x55u; // out 每字节异或 0x55
    v7 = runtime_concatstring2();
    LnNZNVGrFxUawfmfFtLuzZZpawrA(v7, v8, v9, v10, v11, v12);
  }
}
void hDwRGqXZOHitsyulULeUIiCTqaedCidWS()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  __int64 v2; // rdi
  __int64 v3; // r14
  __int64 v4; // rbx
  __int64 v5; // rax
  __int64 i; // rdx
  __int64 v7; // [rsp-40h] [rbp-68h]
  __int64 v8; // [rsp-38h] [rbp-60h]
  __int64 v9; // [rsp-30h] [rbp-58h]
  __int64 v10; // [rsp-28h] [rbp-50h]
  __int64 v11; // [rsp-20h] [rbp-48h]
  __int64 v12; // [rsp-18h] [rbp-40h]
  void *retaddr; // [rsp+28h] [rbp+0h] BYREF
  __int64 v15; // [rsp+30h] [rbp+8h]
  __int64 v18; // [rsp+40h] [rbp+18h]
 
  while ( &retaddr <= *(v3 + 16) )
  {
    v15 = v0;
    v18 = v1;
    runtime_morestack_noctxt();
    v0 = v15;
    v1 = v18;
  }
  v4 = v1;
  v5 = PWTGSQGCyWF(); //v5 为 out 内容
  if ( !v2 )
  {
    for ( i = 0LL; v4 > i; ++i )
      *(v5 + i) ^= 0x55u; // out 每字节异或 0x55
    v7 = runtime_concatstring2();
    LnNZNVGrFxUawfmfFtLuzZZpawrA(v7, v8, v9, v10, v11, v12);
  }
}
 
__int64 __usercall LnNZNVGrFxUawfmfFtLuzZZpawrA@<rax>()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  _DWORD *v2; // rbx
  __int64 v3; // r8
  _BYTE *v4; // r9
  __int64 v5; // r10
  __int64 v6; // r14
  __int64 v7; // rax
  _QWORD *v8; // rax
  __int64 v9; // rsi
  __int64 v10; // rax
  _QWORD *v11; // rax
  __int64 v12; // rdx
  __int64 v13; // rsi
  __int64 v14; // rdx
  __int64 v15; // rbx
  __int64 *v16; // rax
  _QWORD *v17; // rax
  __int64 *v18; // rsi
  unsigned __int64 v19; // r8
  __int64 v20; // r9
  unsigned __int64 v21; // rcx
  __int64 v22; // r8
  __int64 v24; // [rsp-26h] [rbp-80h]
  __int64 v25; // [rsp-26h] [rbp-80h]
  __int64 v26; // [rsp-26h] [rbp-80h]
  char v27; // [rsp-26h] [rbp-80h]
  __int64 v28; // [rsp-1Eh] [rbp-78h]
  __int64 v29; // [rsp+Ah] [rbp-50h]
  __int64 v30; // [rsp+12h] [rbp-48h]
  _QWORD *v31; // [rsp+1Ah] [rbp-40h]
  _QWORD *v32; // [rsp+22h] [rbp-38h]
  _QWORD v33[4]; // [rsp+2Ah] [rbp-30h] BYREF
  void (**v34)(void); // [rsp+4Ah] [rbp-10h]
  void *retaddr; // [rsp+5Ah] [rbp+0h] BYREF
  __int64 v37; // [rsp+62h] [rbp+8h]
  __int64 v38; // [rsp+62h] [rbp+8h]
  __int64 v41; // [rsp+72h] [rbp+18h]
  __int64 v45; // [rsp+8Ah] [rbp+30h]
  _BYTE *v46; // [rsp+92h] [rbp+38h]
  __int64 v47; // [rsp+9Ah] [rbp+40h]
 
  while ( &retaddr <= *(v6 + 16) )
  {
    ......
  }
  v37 = v0;
  v33[0] = oIrjHUemhkTuYesiVzPoKmpOwAxNduMvhL;
  v33[1] = v0;
  v34 = v33;
  if ( v1 > 4 && *v2 == 0x77654EAA )//修改过的 LUA_SIGNATURE
  {
    if ( v5 != 1 || *v4 != 116 )
    {
      ZjulCvXVFufJHreFwkLSR();//以 luac 模式加载
      goto LABEL_10;
    }
LABEL_43:
    v27 = runtime_gopanic();
    runtime_deferreturn(v27);
    return 3LL;
  }
  if ( v5 == 1 && *v4 == 98 )
  {
    runtime_gopanic();
    goto LABEL_43;
  }
  v24 = runtime_slicebytetostring();
  v28 = jSJunBFoJhTHsNqpeUQxzn(v24);
LABEL_10:
  v30 = v7;
  v25 = runtime_newobject();
......
__int64 __usercall LnNZNVGrFxUawfmfFtLuzZZpawrA@<rax>()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  _DWORD *v2; // rbx
  __int64 v3; // r8
  _BYTE *v4; // r9
  __int64 v5; // r10
  __int64 v6; // r14
  __int64 v7; // rax
  _QWORD *v8; // rax
  __int64 v9; // rsi
  __int64 v10; // rax
  _QWORD *v11; // rax
  __int64 v12; // rdx
  __int64 v13; // rsi
  __int64 v14; // rdx
  __int64 v15; // rbx
  __int64 *v16; // rax
  _QWORD *v17; // rax
  __int64 *v18; // rsi
  unsigned __int64 v19; // r8
  __int64 v20; // r9
  unsigned __int64 v21; // rcx
  __int64 v22; // r8
  __int64 v24; // [rsp-26h] [rbp-80h]
  __int64 v25; // [rsp-26h] [rbp-80h]
  __int64 v26; // [rsp-26h] [rbp-80h]
  char v27; // [rsp-26h] [rbp-80h]
  __int64 v28; // [rsp-1Eh] [rbp-78h]
  __int64 v29; // [rsp+Ah] [rbp-50h]
  __int64 v30; // [rsp+12h] [rbp-48h]
  _QWORD *v31; // [rsp+1Ah] [rbp-40h]
  _QWORD *v32; // [rsp+22h] [rbp-38h]
  _QWORD v33[4]; // [rsp+2Ah] [rbp-30h] BYREF
  void (**v34)(void); // [rsp+4Ah] [rbp-10h]
  void *retaddr; // [rsp+5Ah] [rbp+0h] BYREF
  __int64 v37; // [rsp+62h] [rbp+8h]
  __int64 v38; // [rsp+62h] [rbp+8h]
  __int64 v41; // [rsp+72h] [rbp+18h]
  __int64 v45; // [rsp+8Ah] [rbp+30h]
  _BYTE *v46; // [rsp+92h] [rbp+38h]
  __int64 v47; // [rsp+9Ah] [rbp+40h]
 
  while ( &retaddr <= *(v6 + 16) )
  {
    ......
  }
  v37 = v0;
  v33[0] = oIrjHUemhkTuYesiVzPoKmpOwAxNduMvhL;
  v33[1] = v0;
  v34 = v33;
  if ( v1 > 4 && *v2 == 0x77654EAA )//修改过的 LUA_SIGNATURE
  {
    if ( v5 != 1 || *v4 != 116 )
    {
      ZjulCvXVFufJHreFwkLSR();//以 luac 模式加载
      goto LABEL_10;
    }
LABEL_43:
    v27 = runtime_gopanic();
    runtime_deferreturn(v27);
    return 3LL;
  }
  if ( v5 == 1 && *v4 == 98 )
  {
    runtime_gopanic();
    goto LABEL_43;
  }
  v24 = runtime_slicebytetostring();
  v28 = jSJunBFoJhTHsNqpeUQxzn(v24);
LABEL_10:
  v30 = v7;
  v25 = runtime_newobject();
......
void __golang ZjulCvXVFufJHreFwkLSR()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  __int64 v2; // rbx
  __int64 v3; // r14
  __int64 v4; // [rsp-18h] [rbp-38h]
  __int64 v5; // [rsp-10h] [rbp-30h]
  void *retaddr; // [rsp+20h] [rbp+0h] BYREF
  __int64 v7; // [rsp+28h] [rbp+8h]
  __int64 v8; // [rsp+38h] [rbp+18h]
 
  while ( &retaddr <= *(v3 + 16) )
  {
    ......
  }
  v4 = MDGKlXiFeGzaITATislDNVCASdsieREOQofO();//检查文件头,注意 lua 版本被改成了 17
  if ( !v2 )
    runtime_panicIndex();
  PhtvIcXnnZQDYbqGLutONyDkaSpvgYsoaT(v4, v5);// 读 lua 的 prototype 信息
}
void __golang ZjulCvXVFufJHreFwkLSR()
{
  __int64 v0; // rax
  __int64 v1; // rcx
  __int64 v2; // rbx
  __int64 v3; // r14
  __int64 v4; // [rsp-18h] [rbp-38h]
  __int64 v5; // [rsp-10h] [rbp-30h]
  void *retaddr; // [rsp+20h] [rbp+0h] BYREF
  __int64 v7; // [rsp+28h] [rbp+8h]
  __int64 v8; // [rsp+38h] [rbp+18h]
 
  while ( &retaddr <= *(v3 + 16) )
  {
    ......
  }
  v4 = MDGKlXiFeGzaITATislDNVCASdsieREOQofO();//检查文件头,注意 lua 版本被改成了 17
  if ( !v2 )
    runtime_panicIndex();
  PhtvIcXnnZQDYbqGLutONyDkaSpvgYsoaT(v4, v5);// 读 lua 的 prototype 信息
}
 
 
func dostring(L LuaState, s, name string) int {
    return dochunk(L, lua_load(L, []byte(s), name, "bt"))// lua_load 封装了 Load, 加载 lua 代码后用 dochunk 运行
}
/*
dochunk -> docall -> lua_pcall -> PCall -> Call -> callLuaClosure -> runLuaClosure
*/
func (state *luaState) runLuaClosure() {
    for {
        inst := vm.Instruction(state.Fetch())
        inst.Execute(state)
        if inst.Opcode() == vm.OP_RETURN {
            break
        }
    }
}
 
func (instr Instruction) Execute(vm api.LuaVM) {
    opcodes[instr.Opcode()].action(instr, vm)//注意这里的 opcodes
}
func dostring(L LuaState, s, name string) int {
    return dochunk(L, lua_load(L, []byte(s), name, "bt"))// lua_load 封装了 Load, 加载 lua 代码后用 dochunk 运行
}
/*
dochunk -> docall -> lua_pcall -> PCall -> Call -> callLuaClosure -> runLuaClosure
*/
func (state *luaState) runLuaClosure() {
    for {
        inst := vm.Instruction(state.Fetch())
        inst.Execute(state)
        if inst.Opcode() == vm.OP_RETURN {
            break
        }
    }
}
 
func (instr Instruction) Execute(vm api.LuaVM) {
    opcodes[instr.Opcode()].action(instr, vm)//注意这里的 opcodes
}
__int64 __usercall swPNnkHIjlVmdLQqsILDPLymAPtAGakBvGoiL@<rax>() // Execute
{
  __int64 v0; // rax
  __int64 v1; // r14
  __int64 v2; // rsi
  __int64 v3; // rdi
  unsigned __int64 v4; // rcx
  __int64 v5; // rdi
  unsigned __int64 v6; // r8
  int v7; // edi
  unsigned __int64 v8; // rdi
  __int64 result; // rax
  void *retaddr; // [rsp+Ch] [rbp+0h] BYREF
  __int64 i; // [rsp+14h] [rbp+8h]
  __int64 v13; // [rsp+14h] [rbp+8h]
 
  while ( &retaddr <= *(v1 + 16) )
  {
    v13 = v0;
    runtime_morestack_noctxt();
    v0 = v13;
  }
  for ( i = v0; ; v0 = i )
  {
    v2 = *(v0 + 32);    //state.Fetch()
    v3 = **(v2 + 40);
    v4 = *(v3 + 40);
    v5 = *(v3 + 32);
    v6 = *(v2 + 80);
    if ( v4 <= v6 )
      runtime_panicIndex();
    v7 = *(v5 + 4 * v6);
    *(v2 + 80) = v6 + 1;
    v8 = v7 & 0x3F//inst := vm.Instruction(state.Fetch())
    if ( qword_51FD98 <= v8 )
      runtime_panicIndex();
    result = (**(off_51FD90 + 4 * v8 + 3))(); // opcodes[instr.Opcode()].action(instr, vm)
    if ( v8 == 42LL )
      break;
  }
  return result;
}
__int64 __usercall swPNnkHIjlVmdLQqsILDPLymAPtAGakBvGoiL@<rax>() // Execute
{
  __int64 v0; // rax
  __int64 v1; // r14
  __int64 v2; // rsi
  __int64 v3; // rdi
  unsigned __int64 v4; // rcx
  __int64 v5; // rdi
  unsigned __int64 v6; // r8
  int v7; // edi
  unsigned __int64 v8; // rdi
  __int64 result; // rax
  void *retaddr; // [rsp+Ch] [rbp+0h] BYREF
  __int64 i; // [rsp+14h] [rbp+8h]
  __int64 v13; // [rsp+14h] [rbp+8h]
 
  while ( &retaddr <= *(v1 + 16) )
  {
    v13 = v0;
    runtime_morestack_noctxt();
    v0 = v13;
  }
  for ( i = v0; ; v0 = i )
  {
    v2 = *(v0 + 32);    //state.Fetch()
    v3 = **(v2 + 40);
    v4 = *(v3 + 40);
    v5 = *(v3 + 32);
    v6 = *(v2 + 80);
    if ( v4 <= v6 )
      runtime_panicIndex();
    v7 = *(v5 + 4 * v6);
    *(v2 + 80) = v6 + 1;
    v8 = v7 & 0x3F//inst := vm.Instruction(state.Fetch())
    if ( qword_51FD98 <= v8 )
      runtime_panicIndex();
    result = (**(off_51FD90 + 4 * v8 + 3))(); // opcodes[instr.Opcode()].action(instr, vm)
    if ( v8 == 42LL )
      break;
  }
  return result;
}
 
 
 
-- test.lua
function test()
    boy = {money = 200, t = 200}
    local t0 = 0x10
    t0 = t0 // 10 -- idiv
    function boy.goToMarket(self ,someMoney)
        self.money = self.money - someMoney
        self.money = self.t
    end
    boy:goToMarket(100)
    local t1 = 1
    local t2 = t1
    local t3 = t2 and t1 or t1
    t1 = nil
    t1 = true
    t2 = (-(t1)) - t1 * t2 / t2 % t2 ^ t2 + t2
    t3 = {}
    t3 = {"foo","bar"}
    for k , _ in t3 do
    end
    for i=10,1,-1 do
        t2 = t1 ^ t3
        t2 = t2 ^ t1 ^ 0x66
        t2 = t1 & t3
        t2 = ~t2
        t2 = t1 | t3
        t2 = t2 << 2
        t2 = t2 >> 2
    end
    function f0(...)
    end
    function f1(n)
        function f2(...)
            f0(...)
            n = 200
            print(#n .. "foobar")
            if not t2 then
                t1 = t1 > t2
                t1 = t2 <= t1
                t1 = t2 == t1
                t1 = t2 ~=t1
                t1 = not t2
            else
            end
        end
        return f2(300)
    end
    for k=1, f1(3) do
    end
end
 
return test
-- test.lua
function test()
    boy = {money = 200, t = 200}
    local t0 = 0x10
    t0 = t0 // 10 -- idiv
    function boy.goToMarket(self ,someMoney)
        self.money = self.money - someMoney
        self.money = self.t
    end
    boy:goToMarket(100)
    local t1 = 1
    local t2 = t1
    local t3 = t2 and t1 or t1
    t1 = nil
    t1 = true
    t2 = (-(t1)) - t1 * t2 / t2 % t2 ^ t2 + t2
    t3 = {}
    t3 = {"foo","bar"}
    for k , _ in t3 do
    end
    for i=10,1,-1 do
        t2 = t1 ^ t3
        t2 = t2 ^ t1 ^ 0x66
        t2 = t1 & t3
        t2 = ~t2
        t2 = t1 | t3
        t2 = t2 << 2
        t2 = t2 >> 2
    end
    function f0(...)
    end
    function f1(n)
        function f2(...)
            f0(...)
            n = 200
            print(#n .. "foobar")
            if not t2 then
                t1 = t1 > t2
                t1 = t2 <= t1
                t1 = t2 == t1
                t1 = t2 ~=t1
                t1 = not t2
            else
            end
        end
        return f2(300)
    end
    for k=1, f1(3) do
    end
end
 
return test
local bit = require('bit')
local test = require('test')
 
--local fp = io.open("test.luac","rb")
--local ori_data = fp:read("*all")
--fp:close()
local ori_data = {}
-- print('data len '.. #data)
-- print('ori_data len ' .. #ori_data)
 
-- 因为题目不支持 io.read 所以要对 check_opcode.lua 进行修改
-- 把读取注释掉,换成 local ori_data = {} , 然后我们手动读入 opc.lua 并进行替换。
 
local ori_op_name = {
    "OP_MOVE",
    "OP_LOADK",
    "OP_LOADKX",
    "OP_LOADBOOL",
    "OP_LOADNIL",
    "OP_GETUPVAL",
    "OP_GETTABUP",
    "OP_GETTABLE",
    "OP_SETTABUP",
    "OP_SETUPVAL",
    "OP_SETTABLE",
    "OP_NEWTABLE",
    "OP_SELF",
    "OP_ADD",
    "OP_SUB",
    "OP_MUL",
    "OP_MOD",
    "OP_POW",
    "OP_DIV",
    "OP_IDIV",
    "OP_BAND",
    "OP_BOR",
    "OP_BXOR",
    "OP_SHL",
    "OP_SHR",
    "OP_UNM",
    "OP_BNOT",
    "OP_NOT",
    "OP_LEN",
    "OP_CONCAT",
    "OP_JMP",
    "OP_EQ",
    "OP_LT",
    "OP_LE",
    "OP_TEST",
    "OP_TESTSET",
    "OP_CALL",
    "OP_TAILCALL",
    "OP_RETURN",
    "OP_FORLOOP",
    "OP_FORPREP",
    "OP_TFORCALL",
    "OP_TFORLOOP",
    "OP_SETLIST",
    "OP_CLOSURE",
    "OP_VARARG",
    "OP_EXTRAARG"
}
local data = string.dump(test)
local new_op = {    ["OP_MOVE"] = -1,
["OP_LOADK"] = -1,
["OP_LOADKX"] = -1,
["OP_LOADBOOL"] = -1,
["OP_LOADNIL"] = -1,
["OP_GETUPVAL"] = -1,
["OP_GETTABUP"] = -1,
["OP_GETTABLE"] = -1,
["OP_SETTABUP"] = -1,
["OP_SETUPVAL"] = -1,
["OP_SETTABLE"] = -1,
["OP_NEWTABLE"] = -1,
["OP_SELF"] = -1,
["OP_ADD"] = -1,
["OP_SUB"] = -1,
["OP_MUL"] = -1,
["OP_MOD"] = -1,
["OP_POW"] = -1,
["OP_DIV"] = -1,
["OP_IDIV"] = -1,
["OP_BAND"] = -1,
["OP_BOR"] = -1,
["OP_BXOR"] = -1,
["OP_SHL"] = -1,
["OP_SHR"] = -1,
["OP_UNM"] = -1,
["OP_BNOT"] = -1,
["OP_NOT"] = -1,
["OP_LEN"] = -1,
["OP_CONCAT"] = -1,
["OP_JMP"] = -1,
["OP_EQ"] = -1,
["OP_LT"] = -1,
["OP_LE"] = -1,
["OP_TEST"] = -1,
["OP_TESTSET"] = -1,
["OP_CALL"] = -1,
["OP_TAILCALL"] = -1,
["OP_RETURN"] = -1,
["OP_FORLOOP"] = -1,
["OP_FORPREP"] = -1,
["OP_TFORCALL"] = -1,
["OP_TFORLOOP"] = -1,
["OP_SETLIST"] = -1,
["OP_CLOSURE"] = -1,
["OP_VARARG"] = -1,
["OP_EXTRAARG"] = -1}
for i = 6, #data do
    local by_ori = ori_data[i] --string.byte(ori_data,i)
    -- 改后这里的 ori_data 是数组了
    local by_new = string.byte(data,i)
    if by_ori ~= by_new then
        local idx = bit:_and(0x3F,by_ori)
        if idx < 47 then -- 限制一个范围,如果超出了 opcode 的数量就说明这个变化有可能不是 opcode 被换导致的
            local op_name = ori_op_name[idx + 1]
            local op_idx = bit:_and(0x3F,by_new)
            new_op[op_name] = op_idx
        end
    end
end
 
print("old \t new \t name")
for idx, op_name in pairs(ori_op_name) do
    local tmp = ''
    tmp = new_op[op_name]
    print((idx - 1) .. "\t" .. tmp .. "\t" .. op_name )
end
local bit = require('bit')
local test = require('test')
 
--local fp = io.open("test.luac","rb")
--local ori_data = fp:read("*all")
--fp:close()
local ori_data = {}
-- print('data len '.. #data)
-- print('ori_data len ' .. #ori_data)
 
-- 因为题目不支持 io.read 所以要对 check_opcode.lua 进行修改
-- 把读取注释掉,换成 local ori_data = {} , 然后我们手动读入 opc.lua 并进行替换。
 
local ori_op_name = {
    "OP_MOVE",
    "OP_LOADK",
    "OP_LOADKX",
    "OP_LOADBOOL",
    "OP_LOADNIL",
    "OP_GETUPVAL",
    "OP_GETTABUP",
    "OP_GETTABLE",

[注意]APP应用上架合规检测服务,协助应用顺利上架!

最后于 2022-1-20 16:01 被v0id_编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (7)
雪    币: 8789
活跃值: (5813)
能力值: ( LV13,RANK:296 )
在线值:
发帖
回帖
粉丝
2
mark! 学习了
2021-10-18 17:14
0
雪    币: 8472
活跃值: (5071)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
3
不小心发错版了,版主能帮我移动到软件逆向版吗
2021-10-18 17:34
0
雪    币: 1810
活跃值: (3402)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
4
Void爷,膜
2021-10-18 19:18
0
雪    币: 1107
活跃值: (531)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
tql
2021-10-21 17:24
0
雪    币: 9792
活跃值: (1680)
能力值: ( LV12,RANK:261 )
在线值:
发帖
回帖
粉丝
6
Void爷,膜
2021-11-17 09:37
0
雪    币: 92
活跃值: (209)
能力值: ( LV6,RANK:95 )
在线值:
发帖
回帖
粉丝
7
老哥缺工作吗?
2022-3-8 18:53
0
雪    币: 7050
活跃值: (11289)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
8

Void爷,tql

最后于 2022-4-27 15:48 被Nameless_a编辑 ,原因:
2022-4-27 15:47
0
游客
登录 | 注册 方可回帖
返回
//