本博客由闲散白帽子胖胖鹏鹏胖胖鹏潜力所写,仅仅作为个人技术交流分享,不得用做商业用途。转载请注明出处,禁止未经许可将本博客内所有内容转载、商用。
“别人吓自己不可怕,可怕的是自己吓自己”
—胖胖鹏鹏胖胖鹏
已经是决赛的最后一题了,发现是个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