Challenge

フラグを食べる grep 作ってみた【おいしい】

EXAMPLE_FILE = "/usr/share/dict/words"
FLAG_EATER = open("/dev/null", "w")
DUMMY_EATER = open("/dev/null", "w")

while True:
    file = input(f"File (Default: {EXAMPLE_FILE}, Flag: flag.txt): ")
    pattern = input("Pattern: ")
    content = open(file or EXAMPLE_FILE).read(0x10000)
    for line in content.splitlines():
        if pattern in line:
            print(line, file=FLAG_EATER if "Alpaca" in line else None)
        else:
            print(line, file=DUMMY_EATER) # dummy write to avoid timing attacks :)

Solution

概要

ファイル選択→pattern入力で一致行を出力するgrep風のプログラム

ただし、Alpacaを含む行はFLAG_EATER = open("/dev/null", "w")に出力される。

一致しない行はDUMMY_EATER = open("/dev/null", "w")に出力される。

どこに注目するか?

コメントにある通りタイミング攻撃は対策していて難しそう。

任意のパスが読めるので/proc/self配下で何か使えないか探す。

すると/proc/self/io で値が色々と増加していることに気づく。

File (Default: /usr/share/dict/words, Flag: flag.txt): /proc/self/io
Pattern: 
rchar: 33802
wchar: 64
syscr: 30
syscw: 2
read_bytes: 6262784
write_bytes: 0
cancelled_write_bytes: 0
File (Default: /usr/share/dict/words, Flag: flag.txt): /proc/self/io
Pattern: 
rchar: 33919
wchar: 230
syscr: 34
syscw: 4
read_bytes: 6496256
write_bytes: 0
cancelled_write_bytes: 0
File (Default: /usr/share/dict/words, Flag: flag.txt): /proc/self/io
Pattern: 
rchar: 34037
wchar: 397
syscr: 38
syscw: 6
read_bytes: 6496256
write_bytes: 0
cancelled_write_bytes: 0

rchar:read()などでユーザー空間に渡されたバイト数

wchar:write()などでユーザー空間から受け取ったバイト数

syscw/syscr :write/read系 syscall を呼んだ回数

read_bytes/write_bytes :実際に読んだ/書いたとみなされたバイト数

また、read_bytesの初期値は接続ごとに変わっていた。