0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

claustra01's Daily CTFAdvent Calendar 2024

Day 12

[rev] luau (CakeCTF 2022) writeup

Last updated at Posted at 2024-12-12

Source: CakeCTF 2022
Author: ptr-yudai


Luaのreversing問。main.lualibflag.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}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?