Skip to content

Instantly share code, notes, and snippets.

@st98
Last active August 29, 2015 14:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save st98/df66716a3900ddb3f1ec to your computer and use it in GitHub Desktop.
Save st98/df66716a3900ddb3f1ec to your computer and use it in GitHub Desktop.
#tkbctf4 の write-up。 (移動しました -> https://st98.github.io/diary/posts/2014-11-03-tkbctf4.html)

#tkbctf4

チーム omakase として参加した。最終的に獲得できたポイントは 626 点でチーム順位は 13 位だった。
rand (javascript 200), args (javascript 200), gradius (binary 100), monochrome bar (steganography 100) の 4 問を解いた。
rand は 3 番目に正解したので 6 点、args は最初に正解したので 20 点のボーナスポイントがあった。

解けた問題

rand (javascript 200)

  • まずグローバルオブジェクトのプロパティを確認する。
Object.keys(this) // => ["print", "quit", "version", "arguments", "g"]
  • String#split と String#join を this を返す関数にする。これで getFlag にアクセスできる。
  • getFlag + "" で getFlag の中身が読める。
String.prototype.split = String.prototype.join = function () { return String(this); };
g('print(getFlag + "")'); // => '…FLAG{7f94427ec6f49f70642d41c675b98832}'
flag: 7f94427ec6f49f70642d41c675b98832`

gradius (binary 100)

  • kkjjhlhlba と入力すると FLAG{!!D4GG3R!!} と出る。
flag: !!D4GG3R!!

monochrome bar (steganography 100)

  • 幅が 72900px、高さ 1px の png ファイルが渡される。
  • Math.sqrt(72900) === 270 なので、元の画像を 270px ずつ切って縦に並べる。
import sys
from PIL import Image

def main(name='monochrome_bar.png', width=270, *_):
  orig = Image.open(name)
  img = Image.new('RGB', (width, 72900 // width), (128, 128, 128))

  for y in range(72900 // width):
    cut = orig.crop((y * width, 0, (y + 1) * width, 1))
    img.paste(cut, (0, y))

  img.save('output.png')

  return 0

if __name__ == '__main__':
  sys.exit(main(*sys.argv[1:]))
  • QR コードが出てくるので、画像を少しいじってスキャンすると RkxBR3tDaDF0M2sxazBrMXNoMW4tbTRufQ== が出てくる。
  • Base64 でエンコードされているのでデコードすると FLAG{Ch1t3k1k0k1sh1n-m4n} が出てくる。
flag: Ch1t3k1k0k1sh1n-m4n

args (javascript 200)

  • f の中に this.args = arguments; と書かれている部分がある。
  • その後の f.bind(null, false); からその this がグローバルオブジェクトになることが分かる。
  • つまり一度 g を呼び出せばグローバル変数の args にその時の arguments が入る。
  • args.callee から f が取り出せるので、true になる引数を与えて呼び出すとフラッグが手に入る。
g();
args.callee(true); // => 'FLAG{3d2dba5b774814fa8fe87798898b7b30}'
flag: 3d2dba5b774814fa8fe87798898b7b30

解けなかった問題

amida (misc 300)

  • あみだくじ。base64 でエンコードされた画像をデコードして表示し、人力で解いて入力するプログラムを書いた。
  • ステージ 5 で諦めた。
import base64
import io
import re
import socket
import sys
import uuid
from PIL import Image

def main(host='203.178.132.117', port=42719, *_):
  s = socket.create_connection((host, port), 3)
  s.settimeout(3)

  print('[*]', s.recv(0x1000))

  while True:
    for x in range(50):
      print('[*] ', x)

      f = ''

      while True:
        r = s.recv(0x1000)
        f += re.findall(r'(?:#\d+\n)?(.+)(?:\nAnswer\?\n)?', r.decode('ascii'))[0]
        if b'\nAnswer?\n' in r:
          break

      Image.open(io.BytesIO(base64.b64decode(f))).show()

      s.send(input('> ').encode() + b'\n\n')
    print('[*]', s.recv(0x1000))

    if input() == 'q':
      break
    else:
      continue

  s.close()

  return 0

if __name__ == '__main__':
  sys.exit(main(*sys.argv[1:]))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment