题目给了一个 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
(
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
(
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 '
..
-
-
print
(
'ori_data len '
..
-
-
因为题目不支持 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
,
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 '
..
-
-
print
(
'ori_data len '
..
-
-
因为题目不支持 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_编辑
,原因: