Source: CakeCTF 2022
Author: ptr-yudai
Luaのreversing問。main.lua
とlibflag.lua
が与えられる。
main.lua
からlibflag.lua
を呼び出しているが、libflag.lua
はLua bytecodeになっており、中身を見ることができない。
local libflag = require "libflag"
io.write("FLAG: ")
flag = io.read("*l")
if libflag.checkFlag(flag, "CakeCTF 2022") then
print("Correct!")
else
print("Wrong...")
end
$ file main.lua
main.lua: ASCII text
$ file libflag.lua
libflag.lua: Lua bytecode, version 5.3
Luaを逆アセンブルする方法を探しているとオンラインで逆アセンブルできるサイトが見つかった。libflag.lua
の逆アセンブル結果はこうなる。
-- filename:
-- version: lua53
-- line: [0, 0] id: 0
return {
checkFlag = function(r0_1, r1_1)
-- line: [1, 32] id: 1
local r2_1 = {
62,
85,
25,
84,
47,
56,
118,
71,
109,
0,
90,
71,
115,
9,
30,
58,
32,
101,
40,
20,
66,
111,
3,
92,
119,
22,
90,
11,
119,
35,
61,
102,
102,
115,
87,
89,
34,
34
}
if #r0_1 ~= #r2_1 then
return false
end
local r3_1 = {}
local r4_1 = {}
for r8_1 = 1, #r0_1, 1 do
r3_1[r8_1] = string.byte(r0_1:sub(r8_1, r8_1 + 1))
end
for r8_1 = 1, #r1_1, 1 do
r4_1[r8_1] = string.byte(r1_1:sub(r8_1, r8_1 + 1))
end
for r8_1 = 1, #r3_1, 1 do
for r12_1 = r8_1 + 1, #r3_1, 1 do
r3_1[r8_1] = r3_1[r12_1]
r3_1[r12_1] = r3_1[r8_1]
end
end
for r8_1 = 1, #r3_1, 1 do
r3_1[r8_1] = r3_1[r8_1] ~ r4_1[1 + (r8_1 - 1) % #r4_1]
if r3_1[r8_1] ~= r2_1[r8_1] then
return false
end
end
return true
end,
}
このままでは見にくいので変数名を綺麗にする。
return {
checkFlag = function(userInput, key)
local data = {
-- (略)
}
if #userInput ~= #data then
return false
end
local arr1 = {}
local arr2 = {}
for i = 1, #userInput, 1 do
arr1[i] = string.byte(userInput:sub(i, i + 1))
end
for i = 1, #key, 1 do
arr2[i] = string.byte(key:sub(i, i + 1))
end
for i = 1, #arr1, 1 do
for j = i + 1, #arr1, 1 do
arr1[i] = arr1[j]
arr1[j] = arr1[i]
end
end
for i = 1, #r3_1, 1 do
r3_1[i] = r3_1[i] ~ arr2[1 + (i - 1) % #arr2]
if r3_1[i] ~= data[i] then
return false
end
end
return true
end,
}
処理としては引数をbyte列に変換し、配列の隣の値とswapしてからxorを取っているっぽい。swap時に配列の値を直接上書きしているのが気になるが、逆アセンブルの時に省略されてしまったものだと仮定して進める。
for i = 1, #arr1, 1 do
for j = i + 1, #arr1, 1 do
arr1[i] = arr1[j]
arr1[j] = arr1[i]
end
end
solverを書く。
data = [
62, 85, 25, 84, 47, 56, 118, 71,
109, 0, 90, 71, 115, 9, 30, 58,
32, 101, 40, 20, 66, 111, 3, 92,
119, 22, 90, 11, 119, 35, 61, 102,
102, 115, 87, 89, 34, 34
]
key = "CakeCTF 2022"
flag = ""
for i in reversed(range(len(data))):
flag += chr(data[i] ^ ord(key[i % len(key)]))
print(flag)
flagが得られた。
CakeCTF{w4n1w4n1_p4n1c_uh0uh0_g0ll1r4}