本博客由闲散白帽子胖胖鹏鹏胖胖鹏潜力所写,仅仅作为个人技术交流分享,不得用做商业用途。转载请注明出处,禁止未经许可将本博客内所有内容转载、商用。
“别人吓自己不可怕,可怕的是自己吓自己”
—胖胖鹏鹏胖胖鹏
已经是决赛的最后一题了,发现是个UE4引擎。还是先打开App看一眼,哟呵还能跑能飞,开始我还以为和上一题一样,是一个能够直接看到Flag的题目,各种飞还是不行,甚至猜他把材质反着贴,把Flag藏在了材质里面。接着又去学习了UE4的开发,蓝图编程、蓝图的编译、菜单的widget等等,看了两天还是没有头绪,心急如焚。正巧赶上项目组的论文要发表了,赶紧过去改论文,就这样本来7天做题时间,花了2天梦游,又花了3天半改论文。剩下2天半要抓紧了,能做出来第一关就很满足了。可还是这个问题,校验的入口在哪里呢?
无奈还是先解包看看。发现有6个so库。其中libgnustl_shared.so、libOVRPlugin.so、libvrapi.so都是和引擎相关的库,貌似第一关的时候没用上。而libph2.so、libtmgs.so、libUE4.so就和我们比较相关了。libUE4处理用户交互、绘制界面等等一系列的函数。那么剩下的两个库有什么用呢?又是怎么加载进去的呢?为了弄清他们之间的调用关系,我搜搜了libUE4中的dlopen函数,果然有情况。
果然调用了libtmgs库,并且加载了三个函数null、maln和ths。我觉得maln这个函数特别像单词“main”。于是IDA动态调试,在maln上下断点,输入错误的验证码,点击验证。果然程序断在了这里。
其中还悄悄调用了null函数,不过我们不关心,调试的时候发现sub_271d8这个函数传入了v7也就是我们输入的验证码。而且这个函数是最后的返回结果,所以确定就是检查验证码的地方。跟进去
emmmmm没有看出来到底做了啥操作。于是这里卡住了。翻了翻ph2这个库,发现里面充斥着大量的lua字样。回首再看这段代码,难道!这是lua脚本?动态调试了一下,发现v5的头部是“.LuaS”,lua脚本无误。直接dump内存,保存成luac文件。剩下的就是反编译lua字节码,并且拿到真正的检查逻辑了。(上图函数标记的差不多了,动态调试的时候调没了)
翻了翻看雪的帖子,原来是要找到opmode和opcode,之后修改这个对应的表格,然后编译luadec就可以反编译我们的脚本了。这部分比较吃力,一直在学习lua的各种原理和底层实现,这里花了将近10几个小时。最终定位到了opmode,发现,嗯?没改?紧接着定位到opcode的部分,看了很久发现,嗯?也没改?WTF???感觉自己像个傻子,自己吓住了自己,以为这个题目很难。既然这么简单,直接使用luadec反编译吧!获得Error,size_t不匹配。翻了翻github的issue,了解了这个lua编译的时候是32位机子编译的而我的电脑是64位的,所以会出现这个问题。无奈装上虚拟机,一跑,segmentation fatal......我用各种方法尝试解决这个问题,都无果。这里耽误了4个小时。算了还是生成汇编吧。这里还是蛮顺利的。最后得到了代码。
; Disassembled using luadec 2.2 rev: 895d923 for Lua 5.3 from https://github.com/viruscamp/luadec
; Command line: -dis test.luac
; Function: 0
; Defined at line: 0
; #Upvalues: 1
; #Parameters: 0
; Is_vararg: 1
; Max Stack Size: 26
0 [-]: GETTABUP R0 U0 K0 ; R0 := U0["require"]
1 [-]: GETTABUP R1 U0 K1 ; R1 := U0["setmetatable"]
2 [-]: GETTABUP R2 U0 K2 ; R2 := U0["string"]
3 [-]: GETTABLE R2 R2 K3 ; R2 := R2["char"]
4 [-]: GETTABUP R3 U0 K4 ; R3 := U0["table"]
5 [-]: GETTABLE R3 R3 K5 ; R3 := R3["concat"]
6 [-]: LOADNIL R4 2 ; R4 to R6 := nil
7 [-]: GETTABUP R7 U0 K6 ; R7 := U0["jit"]
8 [-]: TEST R7 0 ; if R7 then goto 10 else goto 20
9 [-]: JMP R0 10 ; PC += 10 (goto 20)
10 [-]: GETTABUP R7 U0 K6 ; R7 := U0["jit"]
11 [-]: GETTABLE R7 R7 K7 ; R7 := R7["version_num"]
12 [-]: LT 0 K8 R7 ; if 20000 < R7 then goto 14 else goto 20
13 [-]: JMP R0 6 ; PC += 6 (goto 20)
14 [-]: LOADBOOL R4 1 0 ; R4 := true
15 [-]: GETTABUP R7 U0 K9 ; R7 := U0["bit"]
16 [-]: GETTABLE R5 R7 K10 ; R5 := R7["bxor"]
17 [-]: GETTABUP R7 U0 K9 ; R7 := U0["bit"]
18 [-]: GETTABLE R6 R7 K11 ; R6 := R7["band"]
19 [-]: JMP R0 16 ; PC += 16 (goto 36)
20 [-]: GETTABUP R7 U0 K12 ; R7 := U0["_VERSION"]
21 [-]: EQ 0 R7 K13 ; if R7 == "Lua 5.2" then goto 23 else goto 28
22 [-]: JMP R0 5 ; PC += 5 (goto 28)
23 [-]: GETTABUP R7 U0 K14 ; R7 := U0["bit32"]
24 [-]: GETTABLE R5 R7 K10 ; R5 := R7["bxor"]
25 [-]: GETTABUP R7 U0 K14 ; R7 := U0["bit32"]
26 [-]: GETTABLE R6 R7 K11 ; R6 := R7["band"]
27 [-]: JMP R0 8 ; PC += 8 (goto 36)
28 [-]: MOVE R7 R0 ; R7 := R0
29 [-]: LOADK R8 K9 ; R8 := "bit"
30 [-]: CALL R7 2 2 ; R7 := R7(R8)
31 [-]: SETTABUP U0 K9 R7 ; U0["bit"] := R7
32 [-]: GETTABUP R7 U0 K9 ; R7 := U0["bit"]
33 [-]: GETTABLE R5 R7 K10 ; R5 := R7["bxor"]
34 [-]: GETTABUP R7 U0 K9 ; R7 := U0["bit"]
35 [-]: GETTABLE R6 R7 K11 ; R6 := R7["band"]
36 [-]: EXTRAARG 5377203 ;
37 [-]: LOADNIL R7 1 ; R7 to R8 := nil
38 [-]: TEST R4 0 ; if R4 then goto 40 else goto 63
39 [-]: JMP R0 23 ; PC += 23 (goto 63)
40 [-]: MOVE R9 R0 ; R9 := R0
41 [-]: LOADK R10 K15 ; R10 := "ffi"
42 [-]: CALL R9 2 2 ; R9 := R9(R10)
43 [-]: GETTABLE R10 R9 K2 ; R10 := R9["string"]
44 [-]: GETTABLE R11 R9 K16 ; R11 := R9["copy"]
45 [-]: GETTABLE R12 R9 K17 ; R12 := R9["cdef"]
46 [-]: LOADK R13 K18 ; R13 := "\t\ttypedef struct { uint8_t v; } idx_t;\n\t"
47 [-]: CALL R12 2 1 ; := R12(R13)
48 [-]: GETTABLE R12 R9 K19 ; R12 := R9["typeof"]
49 [-]: LOADK R13 K20 ; R13 := "uint8_t[256]"
50 [-]: CALL R12 2 2 ; R12 := R12(R13)
51 [-]: GETTABLE R13 R9 K19 ; R13 := R9["typeof"]
52 [-]: LOADK R14 K21 ; R14 := "idx_t"
53 [-]: CALL R13 2 2 ; R13 := R13(R14)
54 [-]: GETTABLE R14 R9 K19 ; R14 := R9["typeof"]
55 [-]: LOADK R15 K22 ; R15 := "uint8_t[?]"
56 [-]: CALL R14 2 2 ; R14 := R14(R15)
57 [-]: CLOSURE R15 0 ; R15 := closure(Function #0_0)
58 [-]: MOVE R7 R15 ; R7 := R15
59 [-]: CLOSURE R15 1 ; R15 := closure(Function #0_1)
60 [-]: MOVE R8 R15 ; R8 := R15
61 [-]: JMP R10 5 ; PC += 5 (goto 67); close all upvalues in R9 to top
62 [-]: JMP R0 4 ; PC += 4 (goto 67)
63 [-]: CLOSURE R9 2 ; R9 := closure(Function #0_2)
64 [-]: MOVE R7 R9 ; R7 := R9
65 [-]: CLOSURE R9 3 ; R9 := closure(Function #0_3)
66 [-]: MOVE R8 R9 ; R8 := R9
67 [-]: CLOSURE R9 4 ; R9 := closure(Function #0_4)
68 [-]: GETTABUP R10 U0 K23 ; R10 := U0["arg"]
69 [-]: TEST R10 0 ; if R10 then goto 71 else goto 147
70 [-]: JMP R0 76 ; PC += 76 (goto 147)
71 [-]: GETTABUP R10 U0 K24 ; R10 := U0["os"]
72 [-]: GETTABLE R10 R10 K25 ; R10 := R10["clock"]
73 [-]: CLOSURE R11 5 ; R11 := closure(Function #0_5)
74 [-]: GETTABUP R12 U0 K26 ; R12 := U0["tonumber"]
75 [-]: GETTABUP R13 U0 K23 ; R13 := U0["arg"]
76 [-]: GETTABLE R13 R13 K27 ; R13 := R13[1]
77 [-]: CALL R12 2 2 ; R12 := R12(R13)
78 [-]: TEST R12 1 ; if not R12 then goto 80 else goto 81
79 [-]: JMP R0 1 ; PC += 1 (goto 81)
80 [-]: LOADK R12 K28 ; R12 := 100000
81 [-]: LOADK R13 K29 ; R13 := "Z@\024轌闅\236"
82 [-]: LOADNIL R14 0 ; R14 := nil
83 [-]: EXTRAARG 134246 ;
84 [-]: MOVE R15 R10 ; R15 := R10
85 [-]: CALL R15 1 2 ; R15 := R15()
86 [-]: MOVE R14 R15 ; R14 := R15
87 [-]: LOADK R15 K27 ; R15 := 1
88 [-]: MOVE R16 R12 ; R16 := R12
89 [-]: LOADK R17 K27 ; R17 := 1
90 [-]: FORPREP R15 4 ; R15 -= R17; pc += 4 (goto 95)
91 [-]: MOVE R19 R9 ; R19 := R9
92 [-]: LOADNIL R20 0 ; R20 := nil
93 [-]: MOVE R21 R13 ; R21 := R13
94 [-]: CALL R19 3 2 ; R19 := R19(R20 to R21)
95 [-]: FORLOOP R15 -5 ; R15 += R17; if R15 <= R16 then R18 := R15; PC += -5 , goto 91 end
96 [-]: MOVE R15 R11 ; R15 := R11
97 [-]: LOADK R16 K30 ; R16 := "%-16s %8.3f sec (%d times, #key %d)"
98 [-]: LOADK R17 K31 ; R17 := "RC4 keygen test"
99 [-]: MOVE R18 R10 ; R18 := R10
100 [-]: CALL R18 1 2 ; R18 := R18()
101 [-]: SUB R18 R18 R14 ; R18 := R18 - R14
102 [-]: MOVE R19 R12 ; R19 := R12
103 [-]: LEN R20 R13 ; R20 := #R13
104 [-]: CALL R15 6 1 ; := R15(R16 to R20)
105 [-]: GETTABUP R15 U0 K32 ; R15 := U0["collectgarbage"]
106 [-]: CALL R15 1 1 ; := R15()
107 [-]: MOVE R15 R9 ; R15 := R9
108 [-]: LOADNIL R16 0 ; R16 := nil
109 [-]: MOVE R17 R13 ; R17 := R13
110 [-]: CALL R15 3 2 ; R15 := R15(R16 to R17)
111 [-]: MOVE R16 R9 ; R16 := R9
112 [-]: LOADNIL R17 0 ; R17 := nil
113 [-]: MOVE R18 R13 ; R18 := R13
114 [-]: CALL R16 3 2 ; R16 := R16(R17 to R18)
115 [-]: LOADK R17 K33 ; R17 := "bS1hjNeePwaj6dY293F7rzmcTFjZVS9O9vAq5l69onIiZTOwZ3LrtuiWLT0Jpr3lZ0XJ11Ajw6RoyLP6Xf66lbFu68edKJK8oyGJLu9xFTQRaFXrsMu9nX4Q5qufETjU0nsN6JZxGXQZfAAcgFyvlik2tJEyovhHsEINhtXnYuj7VpUEZl8ZXAVf2Aa5cbSYVcb1wY3D2ts2kHHXVqUhKpYQ60LKGbWOB1CKkSDFR8JfL9tBmpezS9MWCh1yTUXjfFxSbEq3KV7c8qtwxKGjINoDAMWDQLO0qBGC8IitKyc1zbBUbHBPTvx9TPiGpYObQeX5Ktu7ZtiRpak2o5h9AfEXHCd4tL1F2OsQfpMZghGWnRAez32JeWksXis6X1uJAZgA6mB5Fc7CErLJCiSJVl1TbG4Z7KhypNN0MOfeVV7RY5shwQtYixzA86LNa4w8It2XyjYe6qrcYX3Eq3cKEFFfBPJXZnqwoO3W6MJ52KUrTWcOtqnnfOtWhm9FsLZM"
116 [-]: MOVE R18 R10 ; R18 := R10
117 [-]: CALL R18 1 2 ; R18 := R18()
118 [-]: MOVE R14 R18 ; R14 := R18
119 [-]: LOADK R18 K27 ; R18 := 1
120 [-]: MOVE R19 R12 ; R19 := R12
121 [-]: LOADK R20 K27 ; R20 := 1
122 [-]: FORPREP R18 13 ; R18 -= R20; pc += 13 (goto 136)
123 [-]: MOVE R22 R15 ; R22 := R15
124 [-]: MOVE R23 R17 ; R23 := R17
125 [-]: CALL R22 2 2 ; R22 := R22(R23)
126 [-]: MOVE R23 R16 ; R23 := R16
127 [-]: MOVE R24 R22 ; R24 := R22
128 [-]: CALL R23 2 2 ; R23 := R23(R24)
129 [-]: EXTRAARG 17435774 ;
130 [-]: GETTABUP R24 U0 K34 ; R24 := U0["assert"]
131 [-]: EQ 1 R17 R23 ; if R17 ~= R23 then goto 133 else goto 134
132 [-]: JMP R0 1 ; PC += 1 (goto 134)
133 [-]: LOADBOOL R25 0 1 ; R25 := false; goto 135
134 [-]: LOADBOOL R25 1 0 ; R25 := true
135 [-]: CALL R24 2 1 ; := R24(R25)
136 [-]: FORLOOP R18 -14 ; R18 += R20; if R18 <= R19 then R21 := R18; PC += -14 , goto 123 end
137 [-]: MOVE R18 R11 ; R18 := R11
138 [-]: LOADK R19 K35 ; R19 := "%-16s %8.3f sec (%d times, #key %d, #input %d)"
139 [-]: LOADK R20 K36 ; R20 := "RC4 crypt test"
140 [-]: MOVE R21 R10 ; R21 := R10
141 [-]: CALL R21 1 2 ; R21 := R21()
142 [-]: SUB R21 R21 R14 ; R21 := R21 - R14
143 [-]: MOVE R22 R12 ; R22 := R12
144 [-]: LEN R23 R13 ; R23 := #R13
145 [-]: LEN R24 R17 ; R24 := #R17
146 [-]: CALL R18 7 1 ; := R18(R19 to R24)
147 [-]: MOVE R10 R1 ; R10 := R1
148 [-]: NEWTABLE R11 0 0 ; R11 := {} (size = 0,0)
149 [-]: NEWTABLE R12 0 2 ; R12 := {} (size = 0,2)
150 [-]: SETTABLE R12 K38 R9 ; R12["__call"] := R9
151 [-]: SETTABLE R12 K39 K40 ; R12["__metatable"] := false
152 [-]: CALL R10 3 2 ; R10 := R10(R11 to R12)
153 [-]: SETTABUP U0 K37 R10 ; U0["rc4"] := R10
154 [-]: CLOSURE R10 6 ; R10 := closure(Function #0_6)
155 [-]: SETTABUP U0 K41 R10 ; U0["check"] := R10
156 [-]: RETURN R0 1 ; return
; Function: 0_0
; Defined at line: 66
; #Upvalues: 4
; #Parameters: 1
; Is_vararg: 0
; Max Stack Size: 12
0 [-]: GETUPVAL R1 U0 ; R1 := U0
1 [-]: CALL R1 1 2 ; R1 := R1()
2 [-]: LOADK R2 K0 ; R2 := 0
3 [-]: LOADK R3 K1 ; R3 := 255
4 [-]: LOADK R4 K2 ; R4 := 1
5 [-]: FORPREP R2 1 ; R2 -= R4; pc += 1 (goto 7)
6 [-]: SETTABLE R1 R5 R5 ; R1[R5] := R5
7 [-]: FORLOOP R2 -2 ; R2 += R4; if R2 <= R3 then R5 := R2; PC += -2 , goto 6 end
8 [-]: LEN R2 R0 ; R2 := #R0
9 [-]: GETUPVAL R3 U1 ; R3 := U1
10 [-]: MOVE R4 R2 ; R4 := R2
11 [-]: CALL R3 2 2 ; R3 := R3(R4)
12 [-]: GETUPVAL R4 U2 ; R4 := U2
13 [-]: MOVE R5 R3 ; R5 := R3
14 [-]: MOVE R6 R0 ; R6 := R0
15 [-]: MOVE R7 R2 ; R7 := R2
16 [-]: CALL R4 4 1 ; := R4(R5 to R7)
17 [-]: GETUPVAL R4 U3 ; R4 := U3
18 [-]: CALL R4 1 2 ; R4 := R4()
19 [-]: LOADK R5 K0 ; R5 := 0
20 [-]: LOADK R6 K1 ; R6 := 255
21 [-]: LOADK R7 K2 ; R7 := 1
22 [-]: FORPREP R5 14 ; R5 -= R7; pc += 14 (goto 37)
23 [-]: GETTABLE R9 R4 K3 ; R9 := R4["v"]
24 [-]: GETTABLE R10 R1 R8 ; R10 := R1[R8]
25 [-]: ADD R9 R9 R10 ; R9 := R9 + R10
26 [-]: MOD R10 R8 R2 ; R10 := R8 % R2
27 [-]: GETTABLE R10 R3 R10 ; R10 := R3[R10]
28 [-]: ADD R9 R9 R10 ; R9 := R9 + R10
29 [-]: SETTABLE R4 K3 R9 ; R4["v"] := R9
30 [-]: GETTABLE R9 R4 K3 ; R9 := R4["v"]
31 [-]: GETTABLE R10 R4 K3 ; R10 := R4["v"]
32 [-]: GETTABLE R10 R1 R10 ; R10 := R1[R10]
33 [-]: GETTABLE R11 R1 R8 ; R11 := R1[R8]
34 [-]: SETTABLE R1 R9 R11 ; R1[R9] := R11
35 [-]: SETTABLE R1 R8 R10 ; R1[R8] := R10
36 [-]: EXTRAARG 31198292 ;
37 [-]: FORLOOP R5 -15 ; R5 += R7; if R5 <= R6 then R8 := R5; PC += -15 , goto 23 end
38 [-]: EXTRAARG 15600870 ;
39 [-]: NEWTABLE R5 0 3 ; R5 := {} (size = 0,3)
40 [-]: GETUPVAL R6 U3 ; R6 := U3
41 [-]: CALL R6 1 2 ; R6 := R6()
42 [-]: SETTABLE R5 K4 R6 ; R5["x"] := R6
43 [-]: GETUPVAL R6 U3 ; R6 := U3
44 [-]: CALL R6 1 2 ; R6 := R6()
45 [-]: SETTABLE R5 K5 R6 ; R5["y"] := R6
46 [-]: SETTABLE R5 K6 R1 ; R5["st"] := R1
47 [-]: RETURN R5 2 ; return R5
48 [-]: RETURN R0 1 ; return
; Function: 0_1
; Defined at line: 85
; #Upvalues: 4
; #Parameters: 2
; Is_vararg: 0
; Max Stack Size: 15
0 [-]: GETTABLE R2 R0 K0 ; R2 := R0["x"]
1 [-]: GETTABLE R3 R0 K1 ; R3 := R0["y"]
2 [-]: GETTABLE R4 R0 K2 ; R4 := R0["st"]
3 [-]: EXTRAARG 6294676 ;
4 [-]: LEN R5 R1 ; R5 := #R1
5 [-]: GETUPVAL R6 U0 ; R6 := U0
6 [-]: MOVE R7 R5 ; R7 := R5
7 [-]: CALL R6 2 2 ; R6 := R6(R7)
8 [-]: GETUPVAL R7 U1 ; R7 := U1
9 [-]: MOVE R8 R6 ; R8 := R6
10 [-]: MOVE R9 R1 ; R9 := R1
11 [-]: MOVE R10 R5 ; R10 := R5
12 [-]: CALL R7 4 1 ; := R7(R8 to R10)
13 [-]: LOADK R7 K3 ; R7 := 0
14 [-]: SUB R8 R5 K4 ; R8 := R5 - 1
15 [-]: LOADK R9 K4 ; R9 := 1
16 [-]: FORPREP R7 28 ; R7 -= R9; pc += 28 (goto 45)
17 [-]: GETTABLE R11 R2 K5 ; R11 := R2["v"]
18 [-]: ADD R11 R11 K4 ; R11 := R11 + 1
19 [-]: SETTABLE R2 K5 R11 ; R2["v"] := R11
20 [-]: GETTABLE R11 R3 K5 ; R11 := R3["v"]
21 [-]: GETTABLE R12 R2 K5 ; R12 := R2["v"]
22 [-]: GETTABLE R12 R4 R12 ; R12 := R4[R12]
23 [-]: ADD R11 R11 R12 ; R11 := R11 + R12
24 [-]: SETTABLE R3 K5 R11 ; R3["v"] := R11
25 [-]: GETTABLE R11 R2 K5 ; R11 := R2["v"]
26 [-]: GETTABLE R12 R3 K5 ; R12 := R3["v"]
27 [-]: GETTABLE R13 R3 K5 ; R13 := R3["v"]
28 [-]: GETTABLE R13 R4 R13 ; R13 := R4[R13]
29 [-]: GETTABLE R14 R2 K5 ; R14 := R2["v"]
30 [-]: GETTABLE R14 R4 R14 ; R14 := R4[R14]
31 [-]: SETTABLE R4 R12 R14 ; R4[R12] := R14
32 [-]: SETTABLE R4 R11 R13 ; R4[R11] := R13
33 [-]: GETUPVAL R11 U2 ; R11 := U2
34 [-]: GETTABLE R12 R6 R10 ; R12 := R6[R10]
35 [-]: GETTABLE R13 R2 K5 ; R13 := R2["v"]
36 [-]: GETTABLE R13 R4 R13 ; R13 := R4[R13]
37 [-]: GETTABLE R14 R3 K5 ; R14 := R3["v"]
38 [-]: GETTABLE R14 R4 R14 ; R14 := R4[R14]
39 [-]: ADD R13 R13 R14 ; R13 := R13 + R14
40 [-]: MOD R13 R13 K6 ; R13 := R13 % 256
41 [-]: GETTABLE R13 R4 R13 ; R13 := R4[R13]
42 [-]: CALL R11 3 2 ; R11 := R11(R12 to R13)
43 [-]: SETTABLE R6 R10 R11 ; R6[R10] := R11
44 [-]: EXTRAARG 4983888 ;
45 [-]: FORLOOP R7 -29 ; R7 += R9; if R7 <= R8 then R10 := R7; PC += -29 , goto 17 end
46 [-]: GETUPVAL R7 U3 ; R7 := U3
47 [-]: MOVE R8 R6 ; R8 := R6
48 [-]: MOVE R9 R5 ; R9 := R5
49 [-]: TAILCALL R7 3 0 ; R7 to top := R7(R8 to R9)
50 [-]: RETURN R7 0 ; return R7 to top
51 [-]: RETURN R0 1 ; return
; Function: 0_2
; Defined at line: 105
; #Upvalues: 0
; #Parameters: 1
; Is_vararg: 0
; Max Stack Size: 12
0 [-]: NEWTABLE R1 0 0 ; R1 := {} (size = 0,0)
1 [-]: LOADK R2 K0 ; R2 := 0
2 [-]: LOADK R3 K1 ; R3 := 255
3 [-]: LOADK R4 K2 ; R4 := 1
4 [-]: FORPREP R2 1 ; R2 -= R4; pc += 1 (goto 6)
5 [-]: SETTABLE R1 R5 R5 ; R1[R5] := R5
6 [-]: FORLOOP R2 -2 ; R2 += R4; if R2 <= R3 then R5 := R2; PC += -2 , goto 5 end
7 [-]: LEN R2 R0 ; R2 := #R0
8 [-]: LOADK R3 K0 ; R3 := 0
9 [-]: LOADK R4 K0 ; R4 := 0
10 [-]: LOADK R5 K1 ; R5 := 255
11 [-]: LOADK R6 K2 ; R6 := 1
12 [-]: FORPREP R4 13 ; R4 -= R6; pc += 13 (goto 26)
13 [-]: GETTABLE R8 R1 R7 ; R8 := R1[R7]
14 [-]: ADD R8 R3 R8 ; R8 := R3 + R8
15 [-]: SELF R9 R0 K3 ; R10 := R0; R9 := R0["byte"]
16 [-]: MOD R11 R7 R2 ; R11 := R7 % R2
17 [-]: ADD R11 R11 K2 ; R11 := R11 + 1
18 [-]: CALL R9 3 2 ; R9 := R9(R10 to R11)
19 [-]: ADD R8 R8 R9 ; R8 := R8 + R9
20 [-]: MOD R3 R8 K4 ; R3 := R8 % 256
21 [-]: GETTABLE R8 R1 R3 ; R8 := R1[R3]
22 [-]: GETTABLE R9 R1 R7 ; R9 := R1[R7]
23 [-]: SETTABLE R1 R3 R9 ; R1[R3] := R9
24 [-]: SETTABLE R1 R7 R8 ; R1[R7] := R8
25 [-]: EXTRAARG 15338701 ;
26 [-]: FORLOOP R4 -14 ; R4 += R6; if R4 <= R5 then R7 := R4; PC += -14 , goto 13 end
27 [-]: EXTRAARG 21892159 ;
28 [-]: NEWTABLE R4 0 3 ; R4 := {} (size = 0,3)
29 [-]: SETTABLE R4 K5 K0 ; R4["x"] := 0
30 [-]: SETTABLE R4 K6 K0 ; R4["y"] := 0
31 [-]: SETTABLE R4 K7 R1 ; R4["st"] := R1
32 [-]: RETURN R4 2 ; return R4
33 [-]: RETURN R0 1 ; return
; Function: 0_3
; Defined at line: 121
; #Upvalues: 3
; #Parameters: 2
; Is_vararg: 0
; Max Stack Size: 15
0 [-]: GETTABLE R2 R0 K0 ; R2 := R0["x"]
1 [-]: GETTABLE R3 R0 K1 ; R3 := R0["y"]
2 [-]: GETTABLE R4 R0 K2 ; R4 := R0["st"]
3 [-]: NEWTABLE R5 0 0 ; R5 := {} (size = 0,0)
4 [-]: LOADK R6 K3 ; R6 := 1
5 [-]: LEN R7 R1 ; R7 := #R1
6 [-]: LOADK R8 K3 ; R8 := 1
7 [-]: FORPREP R6 23 ; R6 -= R8; pc += 23 (goto 31)
8 [-]: EXTRAARG 7212269 ;
9 [-]: ADD R10 R2 K3 ; R10 := R2 + 1
10 [-]: MOD R2 R10 K4 ; R2 := R10 % 256
11 [-]: GETTABLE R10 R4 R2 ; R10 := R4[R2]
12 [-]: ADD R10 R3 R10 ; R10 := R3 + R10
13 [-]: MOD R3 R10 K4 ; R3 := R10 % 256
14 [-]: GETTABLE R10 R4 R3 ; R10 := R4[R3]
15 [-]: GETTABLE R11 R4 R2 ; R11 := R4[R2]
16 [-]: SETTABLE R4 R3 R11 ; R4[R3] := R11
17 [-]: SETTABLE R4 R2 R10 ; R4[R2] := R10
18 [-]: GETUPVAL R10 U0 ; R10 := U0
19 [-]: GETUPVAL R11 U1 ; R11 := U1
20 [-]: SELF R12 R1 K5 ; R13 := R1; R12 := R1["byte"]
21 [-]: MOVE R14 R9 ; R14 := R9
22 [-]: CALL R12 3 2 ; R12 := R12(R13 to R14)
23 [-]: GETTABLE R13 R4 R2 ; R13 := R4[R2]
24 [-]: GETTABLE R14 R4 R3 ; R14 := R4[R3]
25 [-]: ADD R13 R13 R14 ; R13 := R13 + R14
26 [-]: MOD R13 R13 K4 ; R13 := R13 % 256
27 [-]: GETTABLE R13 R4 R13 ; R13 := R4[R13]
28 [-]: CALL R11 3 0 ; R11 to top := R11(R12 to R13)
29 [-]: CALL R10 0 2 ; R10 := R10(R11 to top)
30 [-]: SETTABLE R5 R9 R10 ; R5[R9] := R10
31 [-]: FORLOOP R6 -24 ; R6 += R8; if R6 <= R7 then R9 := R6; PC += -24 , goto 8 end
32 [-]: EXTRAARG 26348548 ;
33 [-]: MOVE R6 R2 ; R6 := R2
34 [-]: SETTABLE R0 K1 R3 ; R0["y"] := R3
35 [-]: SETTABLE R0 K0 R6 ; R0["x"] := R6
36 [-]: GETUPVAL R6 U2 ; R6 := U2
37 [-]: MOVE R7 R5 ; R7 := R5
38 [-]: TAILCALL R6 2 0 ; R6 to top := R6(R7)
39 [-]: RETURN R6 0 ; return R6 to top
40 [-]: RETURN R0 1 ; return
; Function: 0_4
; Defined at line: 138
; #Upvalues: 3
; #Parameters: 2
; Is_vararg: 0
; Max Stack Size: 7
0 [-]: GETUPVAL R2 U0 ; R2 := U0
1 [-]: MOVE R3 R1 ; R3 := R1
2 [-]: CALL R2 2 2 ; R2 := R2(R3)
3 [-]: GETUPVAL R3 U1 ; R3 := U1
4 [-]: MOVE R4 R2 ; R4 := R2
5 [-]: NEWTABLE R5 0 2 ; R5 := {} (size = 0,2)
6 [-]: GETUPVAL R6 U2 ; R6 := U2
7 [-]: SETTABLE R5 K0 R6 ; R5["__call"] := R6
8 [-]: SETTABLE R5 K1 K2 ; R5["__metatable"] := false
9 [-]: TAILCALL R3 3 0 ; R3 to top := R3(R4 to R5)
10 [-]: RETURN R3 0 ; return R3 to top
11 [-]: RETURN R0 1 ; return
; Function: 0_5
; Defined at line: 146
; #Upvalues: 0
; #Parameters: 1
; Is_vararg: 1
; Max Stack Size: 2
0 [-]: RETURN R0 1 ; return
; Function: 0_6
; Defined at line: 191
; #Upvalues: 1
; #Parameters: 1
; Is_vararg: 0
; Max Stack Size: 34
0 [-]: SETTABUP U0 K0 K1 ; U0["k"] := "F8998657AFE06DD5AA593D88FB3DB3E4"
1 [-]: GETTABUP R1 U0 K3 ; R1 := U0["rc4"]
2 [-]: GETTABUP R2 U0 K0 ; R2 := U0["k"]
3 [-]: CALL R1 2 2 ; R1 := R1(R2)
4 [-]: SETTABUP U0 K2 R1 ; U0["rc4_enc"] := R1
5 [-]: GETTABUP R1 U0 K3 ; R1 := U0["rc4"]
6 [-]: GETTABUP R2 U0 K0 ; R2 := U0["k"]
7 [-]: CALL R1 2 2 ; R1 := R1(R2)
8 [-]: SETTABUP U0 K4 R1 ; U0["rc4_dec"] := R1
9 [-]: SETTABUP U0 K5 R0 ; U0["plain"] := R0
10 [-]: GETTABUP R1 U0 K2 ; R1 := U0["rc4_enc"]
11 [-]: GETTABUP R2 U0 K5 ; R2 := U0["plain"]
12 [-]: CALL R1 2 2 ; R1 := R1(R2)
13 [-]: SETTABUP U0 K6 R1 ; U0["encrypted"] := R1
14 [-]: NEWTABLE R1 24 0 ; R1 := {} (size = 24,0)
15 [-]: LOADK R2 K8 ; R2 := 30
16 [-]: LOADK R3 K9 ; R3 := 201
17 [-]: LOADK R4 K10 ; R4 := 134
18 [-]: LOADK R5 K11 ; R5 := 139
19 [-]: LOADK R6 K12 ; R6 := 51
20 [-]: LOADK R7 K13 ; R7 := 104
21 [-]: LOADK R8 K14 ; R8 := 209
22 [-]: LOADK R9 K15 ; R9 := 164
23 [-]: LOADK R10 K16 ; R10 := 173
24 [-]: LOADK R11 K17 ; R11 := 123
25 [-]: LOADK R12 K10 ; R12 := 134
26 [-]: LOADK R13 K18 ; R13 := 116
27 [-]: LOADK R14 K19 ; R14 := 7
28 [-]: LOADK R15 K20 ; R15 := 28
29 [-]: LOADK R16 K21 ; R16 := 238
30 [-]: LOADK R17 K22 ; R17 := 110
31 [-]: LOADK R18 K23 ; R18 := 135
32 [-]: LOADK R19 K24 ; R19 := 120
33 [-]: LOADK R20 K25 ; R20 := 129
34 [-]: LOADK R21 K26 ; R21 := 71
35 [-]: LOADK R22 K27 ; R22 := 107
36 [-]: LOADK R23 K28 ; R23 := 187
37 [-]: LOADK R24 K29 ; R24 := 237
38 [-]: LOADK R25 K30 ; R25 := 152
39 [-]: LOADK R26 K31 ; R26 := 111
40 [-]: LOADK R27 K32 ; R27 := 202
41 [-]: LOADK R28 K33 ; R28 := 218
42 [-]: LOADK R29 K34 ; R29 := 192
43 [-]: LOADK R30 K35 ; R30 := 212
44 [-]: LOADK R31 K36 ; R31 := 86
45 [-]: LOADK R32 K33 ; R32 := 218
46 [-]: LOADK R33 K14 ; R33 := 209
47 [-]: SETLIST R1 32 1 ; R1[0] to R1[31] := R2 to R33 ; R(a)[(c-1)*FPF+i] := R(a+i), 1 <= i <= b, a=1, b=32, c=1, FPF=50
48 [-]: SETTABUP U0 K7 R1 ; U0["dst"] := R1
49 [-]: SETTABUP U0 K37 K38 ; U0["res"] := ""
50 [-]: SETTABUP U0 K39 K40 ; U0["i"] := 1
51 [-]: GETTABUP R1 U0 K39 ; R1 := U0["i"]
52 [-]: GETTABUP R2 U0 K41 ; R2 := U0["string"]
53 [-]: GETTABLE R2 R2 K42 ; R2 := R2["len"]
54 [-]: GETTABUP R3 U0 K6 ; R3 := U0["encrypted"]
55 [-]: CALL R2 2 2 ; R2 := R2(R3)
56 [-]: LE 0 R1 R2 ; if R1 <= R2 then goto 58 else goto 80
57 [-]: JMP R0 22 ; PC += 22 (goto 80)
58 [-]: GETTABUP R1 U0 K41 ; R1 := U0["string"]
59 [-]: GETTABLE R1 R1 K44 ; R1 := R1["sub"]
60 [-]: GETTABUP R2 U0 K6 ; R2 := U0["encrypted"]
61 [-]: GETTABUP R3 U0 K39 ; R3 := U0["i"]
62 [-]: GETTABUP R4 U0 K39 ; R4 := U0["i"]
63 [-]: CALL R1 4 2 ; R1 := R1(R2 to R4)
64 [-]: SETTABUP U0 K43 R1 ; U0["v"] := R1
65 [-]: GETTABUP R1 U0 K41 ; R1 := U0["string"]
66 [-]: GETTABLE R1 R1 K45 ; R1 := R1["byte"]
67 [-]: GETTABUP R2 U0 K43 ; R2 := U0["v"]
68 [-]: CALL R1 2 2 ; R1 := R1(R2)
69 [-]: GETTABUP R2 U0 K7 ; R2 := U0["dst"]
70 [-]: GETTABUP R3 U0 K39 ; R3 := U0["i"]
71 [-]: GETTABLE R2 R2 R3 ; R2 := R2[R3]
72 [-]: EQ 1 R1 R2 ; if R1 ~= R2 then goto 74 else goto 76
73 [-]: JMP R0 2 ; PC += 2 (goto 76)
74 [-]: LOADBOOL R1 0 0 ; R1 := false
75 [-]: RETURN R1 2 ; return R1
76 [-]: GETTABUP R1 U0 K39 ; R1 := U0["i"]
77 [-]: ADD R1 R1 K40 ; R1 := R1 + 1
78 [-]: SETTABUP U0 K39 R1 ; U0["i"] := R1
79 [-]: JMP R0 -29 ; PC += -29 (goto 51)
80 [-]: LOADBOOL R1 1 0 ; R1 := true
81 [-]: RETURN R1 2 ; return R1
82 [-]: RETURN R0 1 ; return
WTF!!!根本看不懂好伐。半读半猜看了最后一个函数,觉得是做了一个RC4的加密/解密。RC4作为对称流加密,加密解密操作一样的。猜测秘钥是F8998657AFE06DD5AA593D88FB3DB3E4,长度256bit。而下面的数组R1刚好也是32个数字,应该也是256bit,于是乎写了个简单的代码测试一下。
def crypt(data, key):
"""RC4 algorithm"""
x = 0
box = range(256)
for i in range(256):
x = (x + box[i] + ord(key[i % len(key)])) % 256
box[i], box[x] = box[x], box[i]
x = y = 0
out = []
for num in data:
x = (x + 1) % 256
y = (y + box[x]) % 256
box[x], box[y] = box[y], box[x]
out.append(chr(num ^ box[(box[x] + box[y]) % 256]))
return ''.join(out)
if __name__=='__main__':
key2 = 'F8998657AFE06DD5AA593D88FB3DB3E4'
data2=[30, 201, 134, 139, 51, 104, 209, 164, 173, 123, 134, 116, 7, 28, 238, 110, 135, 120, 129, 71, 107, 187, 237, 152, 111, 202, 218, 192, 212, 86, 218, 209]
encrypt_data = crypt(data2,key2)
print encrypt_data
得到结果C3F6B4473DB70B38B554F6F3C2E6058C,输入到程序里面。哈,果然通过了。
这次经历告诉我,不要把事情想得过于复杂,可以先尝试尝试,如果我早就尝试了解密,可能早就做完了第一关,甚至有可能继续做到第二关。
参考文献:
[1] lau文件格式. http://files.catwell.info/misc/mirror/lua-5.2-bytecode-vm-dirk-laurie/lua52vm.html
[2] lua手游加密与解密. https://bbs.pediy.com/thread-216969.htm
[3] 2017腾讯游戏安全技术竞赛Round2Writeup. https://www.52pojie.cn/thread-670439-1-1.html
[4] luadec. https://github.com/viruscamp/luadec