CTF » CTF Writeup »
CTF Writeup HamaCTF¶
2017.12.2 元祖 濱せっく #1で開催されたCTFの想定解です。
問題¶
エクササイズ¶
復号してね。シェル芸でできるよ。 2n,13,rev,64 01011000001100000011001101011010001100010101001001101101010011000110110001000001010100010111001001101101011001100110000101000101010010000100000101001000010011000110011101010011010101000100011000001010
全てがFになる¶
これから何かわかりますか?
難読化シェル芸1¶
解読してみましょう
大サービス!フラグの一部を教えちゃう!
38}
zlib¶
この中にzlibされたフラグが埋もれています。
sign¶
以下のメッセージと sign.zip から何かわかりますか?
9:14 PM 05 AUG 16 Edward Snowden
b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd
難読化シェル芸2¶
解読してみましょう
大サービス!フラグの一部を教えちゃう!
fi}
想定解¶
暇だったら想定解見る前にチャレンジしてみてクレメンス
エクササイズ¶
01の羅列と「2n,13,rev,64」という言葉があります。
どうやら以下になりそうだと予想がつきます。
- 2n → 2進数を文字に?
- 13 → ROT13(シーザー暗号)
- rev → 文字列をひっくり返す(revコマンドってありますね)
- 64 → base64からデコード
この通りに変換していけばよさそうです。
早速やってみましょう!
2n(01から文字列に変換)¶
$ echo "obase=16; ibase=2; 01011000001100000011001101011010001100010101001001101101010011000110110001000001010100010111001001101101011001100110000101000101010010000100000101001000010011000110011101010011010101000100011000001010" |bc|xxd -r -p
X03Z1RmLlAQrmfaEHAHLgSTF
13(ROT13で復号)¶
$ echo X03Z1RmLlAQrmfaEHAHLgSTF |tr A-Za-z N-ZA-Mn-za-m
K03M1EzYyNDezsnRUNUYtFGS
rev(文字列をひっくり返す)¶
$ echo K03M1EzYyNDezsnRUNUYtFGS |rev
SGFtYUNURnszeDNyYzE1M30K
64(base64からデコード)¶
$ echo SGFtYUNURnszeDNyYzE1M30K|base64 -d
HamaCTF{3x3rc153}
フラグが手に入りました。
まとめるとこんな感じ¶
この一連の変換をこんな感じでシェル芸にできます。
$ echo "01011000001100000011001101011010001100010101001001101101010011000110110001000001010100010111001001101101011001100110000101000101010010000100000101001000010011000110011101010011010101000100011000001010"|cat <((echo "obase=16; ibase=2; ")) -|tr -d '\n'|echo -e $(cat)|bc|xxd -r -p|tr A-Za-z N-ZA-Mn-za-m |rev |base64 -d
HamaCTF{3x3rc153}
全てがFになる¶
とりあえず実行してみます
$ bash f
円状に画面がFで埋め尽くされたと思ったら、今度は埋められたFの一部が消されていきます。
何かを描くような処理に見えます。
$Fbash f F FF FF FF FF FF FFF F F FF F FF F F F F F F F F FF FFF FFFF F FF F FFFF FFF F FF F F FFFFF FFFF FF FFF F FFFF FF FFFF FF F F FF F F FFF F FFF FFF F F F FFFFFFFFF FF F FFFFFFF F FF F F F F F FF FFFFFFFFF FF FFFF FF FFFFFFFFFF FFFFFF FFFFFF FF FF FFF F FF F FFF FFF FFFFF FFFF F FFFFFFF FFFFFF FFFF FFFFFFFF FF FF FFF F F F FF F F F FFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFF FF FFF F F F F FFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F F F F F FFFFFF FF FFFF FFFFFFFFFFFFFFFFFFF FFFF FFFFFFFFFFFFFFFFFFFFFF FFFFF F F F F F F FFFFFFFFF FF F FFFF F FFFF FFFFFFFFF FFFFFFFF F FF F FF FFF F F F FFFF F FFF F FFF FFFFF F FFFFF FFFFFFFFFFF FFFFFF FF FFFFFFFF FFFF FFFF F F FF F F FF F F FFFF FF FF F FFFFFFFF FFFFFFFFFF FFFF FFFFFF FF FFFFFFFF FF F F FF F FF FFF FFFFFFF FFFFFFF FFFFFFFF FFFFFFFFFFFFFFFFF FFFFFFFFFF FF FF F F F F FF FFFFFFFFFF FF FFF FFFFFFF FFFFFFFFF FF FF F FFFFF FFFF FFF F FFFF FFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F F FF F F F F FFFFFFFF FFFFFFF FFFFFFFFFFFFFFFFFFF FFF FFFFFFFFF FFFFFF FFFFFFFF F FFFF FF FFFFFF FFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFF F FF F FF FF F F F F F F F FF FFF FFFFF F FFFFFF FFF FFFF FFFFFF F F FFFFF F F FF F F FFF F FF F FF FFFFF FF FF F FF FFF FF FF FFF F FF F F F F F FFF FF FFF FFFFF FFFFFFFFF F F F F F FF FF FF FFFFF FFFF F F F F F F F F F F FF F F F F F
わかりやすく整形して中身を見てみましょう。
";"を改行に置換するのが見やすくするコツです(bashの文の区切りは改行か、;なので)。
D="MjJ...中略"
C=$(tput cols)
L=$(tput lines)
if [ $C -lt 80 ] || [ $L -lt 24 ]
then echo recommend : Terminal size over 80x24
echo now "${C}x${L}"
read
fi
c="0"
while [ $c -lt 5000 ]
do x=$((($RANDOM%$C+$RANDOM%$C+$RANDOM%$C)/3))
y=$((($RANDOM%$L+$RANDOM%$L+$RANDOM%$L)/3))
printf "\033[${y};${x}fF"
c=$(($c+1))
done
c="0"
LIST=$(echo $D|base64 -d)
while [ $c -lt 500 ]
do LINE=$(echo $LIST|tr ' ' '\n'|shuf|head -1)
x=$(echo $LINE|cut -d'_' -f2)
y=$(echo $LINE|cut -d'_' -f1)
printf "\033[${y};${x}f "
c=$(($c+1))
done
案外短いシェルスクリプトでした。1つ目のwhile文の中の処理でFを画面に表示し、2つ目のwhile文でそのFをスペースで上書きしている。。あたりまで読めたらゴールは近いです。
whileで有限回数ループしていますが、どちらもループ回数が不十分のようです。
- Fで画面を埋め尽くす
- そのFをスペースで消して、何かを表示しようとしている
とりあえずループ回数を増やしてみましょう。えいやっと10倍にしてみます。
F F F F FFFFF FF F F FFFFF FFFFFF FF F FF F F FF F F FFFFFFFFFFFFFFFF FFFF FFFFFFF FF FFFF FFFFF FFFF FFFFFF FFFFFF FFFFFFFFF F F F FF FFF F FFF F F FFFFFFFFFF FFFF FFFFFFF FFFFFF FFFFFFFFF F F F FFFFF F FFF FFF FF FFFF F FFFFF FFFF FFFF FFF FFFFFF FFFFFFFFF FFF FF FFF FF F F F FFF FFF FF F F F FFFFFF FFFF FFFFFFF FFFFFF FFFFFFFFF FFF F FF F FFFF F FFF FFF F FFFF F FFFF FFFF FFFF FFFFFFF FFFFFF FFFFFFFFFFFFF F FFF FF F FFF FFF FF FF FF FF FFFF FFFFFFFF FFFF FFFFFFFFFFFFF FFF F F F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFF FFFF F FFFFF FFFF FFFFFFF F F FF FFF F F FFFFF FFFFFFF FFFFFFFFFFFFF FFF FFFFFFFFFFFFFF F FFFF FFFFFFFFFF FFFFFFF FFFF FF FFFFF F FFFFFFFFFF FFFFFFFFFFFFFFFFF FF FF FF FF FF FFFFFFFF FFF F FFFFFFFFFFFFFFF F FFF F FFFF F FFFF F FFFF F FFFF F FFFFF FFFF F FFFFFFFFF FF FFFFFFFFFFFFFFF FF F F F F FF F F FFFFFFF FFFFFFF F FFFFFFFFF FF FFFFFFFFFFFFFF FFFF F FFFFFFF FFFFFFF FFFFFFF FFFFFFF FFFFFFF FFFFFFF FFFFFFFFF FF FFFFFFFFFF F F F F FF F F F FFFFFF FFF F FFFFFFF FFFFFFFF FF FFFFF FFFFFFFFFF F F FF FF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF F FFFFFFF FFFFFFF FFF FFFFFFF FFFFFFF FFFF FFFF F FFFFFFFFFFFFFFFFFFFFFFFFFFF FFF F F FF FFFF FF FFFFFFFFFFFFFFFF FF FFFFFFFFFFFFFFFF FFF FFFFFFFFFFFFFFFFFFFFFFFFFFFF FF F FFF F FF FF FF FF FFF FFFFFFFFFFFFFFFFFFFFFFFFF F F FF FFFF F FFFFF F F FFFF F FFFF F FFFF F FFF FFFFFFFFFFFFFFFFFFFFFFF FF F FF F FFFF FF FF F F FF F FFFFFFF FFF FFFFFFFFFFFFFFFFFFFFFFF F FFF F F F FFFFFFF F FFF FF FFFFFFF FFFFFFFFFFFFF FFFFFFFFFFFF F FFFFF FF F F F FF F F F FFFFFFF F FFF FFFF FF FF FFFFF FF F F F FFFFFFFFF F F FFF FFFF F FFFF FF FF F F F
あ~、フラグっぽいのが見えます?ね。このままループ回数を調整してもフラグを得られそうですが、「Fで画面を埋める→スペースでフラグの文字を書く」から「Fで画面を埋める(コメントアウト)→Fでフラグの文字を書く」にソースコードを修正してみましょう。
D="MjJ...中略"
C=$(tput cols)
L=$(tput lines)
if [ $C -lt 80 ] || [ $L -lt 24 ]
then echo recommend : Terminal size over 80x24
echo now "${C}x${L}"
read
fi
# c="0"
# while [ $c -lt 5000 ]
# do x=$((($RANDOM%$C+$RANDOM%$C+$RANDOM%$C)/3))
# y=$((($RANDOM%$L+$RANDOM%$L+$RANDOM%$L)/3))
# printf "\033[${y};${x}fF"
# c=$(($c+1))
# done
c="0"
LIST=$(echo $D|base64 -d)
while [ $c -lt 500 ]
do LINE=$(echo $LIST|tr ' ' '\n'|shuf|head -1)
x=$(echo $LINE|cut -d'_' -f2)
y=$(echo $LINE|cut -d'_' -f1)
printf "\033[${y};${x}fF" # スペースからFに修正
c=$(($c+1))
done
実行して、フラグが得られました。
FF FF F FFFF FFF FF F FFFFFFFF FFF FFFFFFFF FF FF FF FF FF FF FF FF FF FF FFFFF FFFFFF FFFF FFFFF FF FF FF FF FF FFFFFFFF FF FF FF FF FF FF FF FFFFF FFF FF FF FF FFFFFFF FF FF FF FFFFFFF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FFFFFFF FF FF FF FF FFFF FFFFFF FF FF FFF FF FF FFFFFFF FFF FF FF FF FF FF FF FF FF FFFFFFF FFFFF FF FF FFFFFF FFFFFF FF FFFFFF FFFFFFF FFFFFF FF FF FF FF FF FF FF FF FF FF FFFF FF FF FF FF FF FF FFFFFFFF FFFFFFF FFFFFFFF F FF FFFFFFFF F FF FF FF FF FF FF FF FF FF FF FF FF FF FF FFFFF FF FFFFFFF FF FF FFFFFF FFFFFFF FFFF FFFFFF FF FF FF FFF FF FF FF FF FF FFFFFFF FFFFFFF FF FFFFFFF FFFFFF FFFFFF FF FF FF FF FF FF FF FF FF FF FF F FF FF FFF FF FF FF FFFFFF FF FF FF FFFFFFFF FF FF FF FF FF FF FF FF FF FF FF FF FF FFFFFF F FF FFFFFFF FF FFFFFF FFFFFFF FF FF FFF
HamaCTF{ThePerfectInsider!}
難読化シェル芸1¶
とりあえず実行してみます。
$ bash NandokukaShellGeiSleeps Let us decording!(≧∀≦*)
ここから、何も起きません。
中身のファイルを見ると難読化されたシェルスクリプトが見えます。
うげっ、これをデコードするのかぁ、、という気持ちになるかもしれません、が、、
echo TGV0IHVzIGRlY29yZGluZyEo4omn4oiA4ommKikK|base64 -d;read;$($'\145\143\150\157' c2xlZXAK | $'\142\141\163\145\66\64' $'\55\144' ) $($'\x65\x63\x68\x6f' NDcK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) ;$($'\145\143\150\157' c2xlZXAK | $'\142\141\163\145\66\64' $'\55\144' ) $($'\145\143\150\157' OAo= | $'\142\141\163\145\66\64' $'\55\144' ) ;$'\u0073\u006c\u0065\u0065\u0070' $(echo =oQO |rev|base64 -d) ;$'\u0073\u006c\u0065\u0065\u0070' $($'\x65\x63\x68\x6f' NQo= | $'\x62\x61\x73\x65\x36\x34' -d) ;$'\164\162\141\160' '' $'\61' $'\62' $'\63' $'\x31\x35' $'\x31\x38' $'\u0031\u0039' $(echo MjAK |base64 -d);$($'\u0065\u0063\u0068\u006f' c2xlZXAK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) $'\u0034' ;$(echo pzIuMNb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) $($'\x65\x63\x68\x6f' MzcK | $'\x62\x61\x73\x65\x36\x34' -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo ZwHX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\72' echo good going)$'\x3A' $'\x70\x6f\x77\x65\x72\x6f\x66\x66';$'\x75\x6e\x73\x65\x74' $'\x65\x78\x69\x74' $'\x6b\x69\x6c\x6c' ;$(echo c2xlZXAK |base64 -d) $(echo XHQA |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\u0065\u0063\u0068\u006f' c2xlZXAK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) $(echo KATM |rev|base64 -d) ;$'\u0073\u006c\u0065\u0065\u0070' $'\x34\x39' ;$(echo KAXZlx2c |rev|base64 -d) $'\u0034\u0039' ;$(echo p2kyMKNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo MTEK |base64 -d) ;$(echo p2kyMKNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $'\u0032\u0035' ;$($'\145\143\150\157' cmVhZAo= | $'\142\141\163\145\66\64' $'\55\144' ) ;$'\72'|$'\x67\x72\x65\x70' $'\x2d\x71' $($'\x65\x63\x68\x6f' Ogo= | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' )||$'\u003a'|$(echo =bNpyW3M |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo XRKY |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo Ogo= |base64 -d)||$($'\u003A' poweroff)$(echo =owboNWZ |rev|base64 -d) JHZ1RSomfSYjP0UyKD1BZTY/QWV7OmNGezhsbAo=|base64 -d|tr '!-~' 'P-~!-O' |base64 -d;$'\u0073\u006c\u0065\u0065\u0070' $(echo NTYwCg== |base64 -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo NTk1Cg== |base64 -d) ;$'\x63\x61\x74' $0|$'\155\144\65\163\165\155'|$'\x63\x61\x74' - <((echo '}'))|tr -d '\n -';: $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $($'\145\143\150\157' NDAK | $'\142\141\163\145\66\64' $'\55\144' ) ;$'\x75\x6e\x73\x65\x74' $'\x65\x78\x69\x74' $'\x6b\x69\x6c\x6c' ;$(echo KAXZlx2c |rev|base64 -d) $($'\u0065\u0063\u0068\u006f' MTcK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) ;$'\u0075\u006e\u0073\u0065\u0074' $'\u0065\u0078\u0069\u0074' $'\u006b\u0069\u006c\u006c';$($'\u003A' killall sh)$'\u003A' $(echo cG93ZXJvZmYK |base64 -d);$($'\u003A' echo hello)$(: poweroff);$(echo KQXZz5Wd |rev|base64 -d) $(echo =oAdphXZ |rev|base64 -d) $(echo =oAbsl2a |rev|base64 -d);$($'\x3A' echo well)$'\u003A' $($'\x65\x63\x68\x6f' ZXhpdAo= | $'\x62\x61\x73\x65\x36\x34' -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $'\62\61' ;$(echo p2kyMKNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) $'\62\65' ;$'\u003A' $($'\u0065\u0063\u0068\u006f' cG93ZXJvZmYK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' );$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo MjEK |base64 -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' $'\x2d\x64' ) $(echo XtQA |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$'\72' $(echo cG93ZXJvZmYK |base64 -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $($'\145\143\150\157' MjIK | $'\142\141\163\145\66\64' $'\55\144' ) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo XRwZ |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$'\162\145\141\144' ;$(echo XNKMyk2p |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) $(echo AGxX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\u003A' killall sh): pkill sh;$(echo =bNMuIzp |rev|tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$(echo KQXZz5Wd |rev|base64 -d) $(echo =oAdphXZ |rev|base64 -d) $(echo =oAbsl2a |rev|base64 -d);$(echo pzIuMNb= |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$'\u0073\u006c\u0065\u0065\u0070' $'\62\63' ;$(ls --help|grep ^G|cut -c9)$(ls --help|grep ^G|cut -c16)$(ls --help|grep ^G|cut -c13)$(ls --help|grep ^G|cut -c8)$(ls --help|grep ^G|cut -c10)$(xxd /bin/ls|head -1|cut -d: -f2|cut -c1)$(ls --help|grep ^G|cut -c8)$(printf "%b" $(printf '%s%x' '\x' $((0x77 ^ 0x2f)))|tr A-Z a-z)$(ls --help|grep ^G|cut -c11)$(ls --help|grep ^G|cut -c10)$(xxd /bin/ls|head -1|cut -d: -f2|cut -c1)$(printf "%b" $(printf '%s%x' '\x' $((0x77 ^ 0x1c))))$(ls --help|grep ^G|cut -c11)$(ls --help|grep ^G|cut -c12)$(ls --help|grep ^G|cut -c12);$($'\72' echo good going)$'\x3A' $($'\x65\x63\x68\x6f' c2h1dGRvd24K | $'\x62\x61\x73\x65\x36\x34' -d);$(echo KQXZz5Wd |rev|base64 -d) $(echo =oAdphXZ |rev|base64 -d) $(echo =oAbsl2a |rev|base64 -d);$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $'\x39' ;$'\x73\x6c\x65\x65\x70' $($'\x65\x63\x68\x6f' NTQK | $'\x62\x61\x73\x65\x36\x34' -d) ;$($'\x65\x63\x68\x6f' c2xlZXAK | $'\x62\x61\x73\x65\x36\x34' -d) $(echo ZmNX |tr A-Za-z N-ZA-Mn-za-m|base64 -d) ;$($'\u0065\u0063\u0068\u006f' c2xlZXAK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) $($'\145\143\150\157' NjAK | $'\142\141\163\145\66\64' $'\55\144' ) ;$($'\x3A') $'\u003A' $($'\145\143\150\157' ZXhpdAo= | $'\142\141\163\145\66\64' $'\55\144' );$(echo KAXZlx2c |rev|base64 -d) $($'\u0065\u0063\u0068\u006f' MzUK | $'\u0062\u0061\u0073\u0065\u0036\u0034' $'\u002d\u0064' ) ;
次が大事なポイントで、この問題の核心です。 「通常、シェルスクリプトをデバックするときにどうするか?」です。
(ご存知なければ、この機会に覚えていただければ!きっとこの先々役に立ちますよ!)
bashのxオプションを使うんです。いくら難読化されていても最終的に評価されたコマンドがこれで見えてしまいます。
やってみましょう!
$ bash -x NandokukaShellGeiSleeps
+ base64 -d
+ echo TGV0IHVzIGRlY29yZGluZyEo4omn4oiA4ommKikK
Let us decording!(≧∀≦*)
+ read
++ echo c2xlZXAK
++ base64 -d
++ echo NDcK
++ base64 -d
+ sleep 47
++ base64 -d
++ echo c2xlZXAK
++ echo OAo=
++ base64 -d
+ sleep 8
++ rev
++ base64 -d
++ echo =oQO
+ sleep 9
++ base64 -d
++ echo NQo=
+ sleep 5
++ base64 -d
++ echo MjAK
+ trap '' 1 2 3 15 18 19 20
++ base64 -d
++ echo c2xlZXAK
+ sleep 4
++ base64 -d
++ tr A-Za-z N-ZA-Mn-za-m
++ echo pzIuMNb=
+ read
(続く..)
見える...見えるぞ!!難読化が解かれる過程の処理が混じって見えますが、sleepと、たまにreadが実行されるだけのようです。
このまま待っていればフラグが得られそうですが...
いったい何時間待てばいいか、わかりません。このsleepとreadを、なんとかスキップできないでしょうか?
readはビルトインコマンドなのでkillできません。ENTERして進めましょう。
sleepはkillすればいいんです。
「処理中のsleepを待てないから早く進めたい」という時に使えます。シェルスクリプトを開発する際に、たまに使うちょっとしたテクニックなので、これも覚えておくと良いと思います。
でも私は、trapで全てのシグナルを捨てるように作問しました。普通にkillしてもsleepは死なないようにしています。
それでも、プロセスはkillできます。そう kill -9 ならね。
と、いうわけでターミナルを二つ起動して、一方は問題を実行(readはENTERだけ押して処理を進める)。もう一方はsleepをひたすらkillすればゴールです。
$ pkill -9 sleep $ pkill -9 sleep $ pkill -9 sleep $ pkill -9 sleep $ pkill -9 sleep . . .
+ echo JHZ1RSomfSYjP0UyKD1BZTY/QWV7OmNGezhsbAo= HamaCTF{ZZZzzzz....++ echo NTYwCg== ++ base64 -d + sleep 560 NandokukaShellGeiSleeps: 1 行: 24303 強制終了 'sleep' $(echo NTYwCg== |base64 -d)++ base64 -d ++ echo c2xlZXAK ++ base64 -d ++ echo NTk1Cg== + sleep 595 NandokukaShellGeiSleeps: 1 行: 24636 強制終了 $('echo' c2xlZXAK | 'base64' -d) $(echo NTk1Cg== |base64 -d) + md5sum + cat - /dev/fd/63 + tr -d '\n -' + cat NandokukaShellGeiSleeps ++ echo '}' 3ebc92ee5adb8d0ee4490ede8ec4bb38}++ base64 -d ++ echo c2h1dGRvd24K + : shutdown ++ echo c2xlZXAK ++ base64 -d ++ base64 -d ++ echo NDAK + sleep 40
実行結果からフラグが見えます
HamaCTF{ZZZzzzz....3ebc92ee5adb8d0ee4490ede8ec4bb38}
このフラグですが、後半がこのファイル自身のMD5ハッシュ値になっています。つまり、フラグの出力処理だけ抜き出しても正しいフラグが得られないようになっています。
zlib¶
低レイヤちっくな問題ですが、これもシェル芸で扱うことができます。
まずzlibですが、以下の仕様が重要でございます(たーなさんがwriteup書いてくれてました!)。
zlibは、たまにForensic問題でも必要になったりします。
ちなみにzlib=zipではなく、zlibがzipを包含している関係です。zlibを利用した一つの圧縮方法としてzipやgzipが実装されています。
SHELLART 300
— たーな (@tanafuji_) 2017年12月2日
zlib
問題:
この中にzlibされたフラグが埋もれています。
解法:
Zlibの仕様書見るhttps://t.co/LFApZJ8M5a
中に一文、これ大事!
Any data which may appear after ADLER32 are not part of the zlib stream.
(続く#HamaSec #Writeup
SHELLART 300
— たーな (@tanafuji_) 2017年12月2日
(続き
つまりヘッダのシグネチャがあっていればフッタ以降無視
Pythonのzlib.decompressを問題ファイルの1byte目から順に当てていき、
zlib.errorが発生しない行が正しいzlibストリームなので、それをprintして正解#HamaSec #Writeup
つまり、zlibの先頭バイトさえ合っていればお尻にゴミがくっついていてもOKという事ですねっ!
ファイルの先頭を1バイトずつずらしながらデコードできるか試していけばよさそうです。
普通にプログラミングして実装してもいいです。ここではシェル芸でやってみます。zlibの展開にはopensslが使えます。
$ for I in `seq 790` ; do cat zlib | dd bs=1 skip=${I} | openssl zlib -d > out_file_${I} 2>/dev/null ; done ; strings out_file*
シェル芸自体はもっとエレガントに書ける余地がありそう
ちょっと見やすくすると、こんな感じ。
#!/bin/bash
for I in `seq 790`
do
cat zlib | dd bs=1 skip=${I} | openssl zlib -d > out_file_${I} 2>/dev/null
done
strings out_file*
HamaCTF{HamanKarn}
sign¶
ちなsignって名付けた問題は、OSINTとWebと低レイヤの簡単な知識が必要でお気に入りなんだけど競技時間中には解かれなかったのです(´Д`。)グスン #HamaSec
— kanata (@kanata201612) 2017年12月4日
やっていきましょう!
9:14 PM 05 AUG 16 Edward Snowden¶
9:14 PM 05 AUG 16 Edward Snowden
この時、エドワード・スノーデンさんは何をしていたのでしょう?みなさんのOSINTスキルを使って調べみましょう。
さほど苦労せずに、 ffdae96f8dd292374a966ec8b57d9cc680ce1d23cb7072c522efe32a1a7e34b0という文字列を得ることが出来るはずです。
エドワード・スノーデンさん自身もこの文字列は何なのか言及せず、該当のTwitterは削除済みになっています。
sign.zip¶
展開すると circuit というファイルがあって...
$ file circuit
circuit: SVG Scalable Vector Graphics image
SVGですね。ブラウザで表示できます。
これが何かは、ちょっとした低レイヤの知識が必要です。XORの論理回路図ですね。
b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd¶
整理してみましょう。
- スノーデンさんのTweet
ffdae96f8dd292374a966ec8b57d9cc680ce1d23cb7072c522efe32a1a7e34b0
- sign.zip
XOR
- 問題文
b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd
と、いうことは¶
こうですね!
ffdae96f8dd292374a966ec8b57d9cc680ce1d23cb7072c522efe32a1a7e34b0 XOR b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd -------------------------------------------------------------------- 48616D614354467B452E536E6F7764656E7A446561646D616E5377697463687D
これをASCIIにすると
HamaCTF{E.SnowdenzDeadmanSwitch}
ちなみに、シェルスクリプトでソルバを書くとこんな感じになりました。
#!/bin/bash
S=`curl -s https://www.youtube.com/watch?v=4kBnDIN6pTw|grep '<title'|cut -c8-71`
F="b7bb840ece86d44c0fb83da6da0af8a3eeb45946aa141fa44cbc94436e1d5ccd"
C=1
while :
do
SW=`echo $S |cut -c$C-$(($C+1))`
FG=`echo $F |cut -c$C-$(($C+1))`
A1=`printf '%02X' $(( 0x$SW ^ 0x$FG ))`
echo $A1 |grep -q "00" && break
A2="$A2$A1"
C=$(($C+2))
done
echo $A2|tr A-Z a-z|xxd -ps -r
難読化シェル芸2¶
まずは実行してみましょう。
Hint通りに入力すると先に進めるようですが、No hintの時に何を入力すればいいかわかりません。
間違うと終了してしまいます。
$ bash NandokukaShellGeiInqAns Let us decording!(≧∀≦*) Hint 85UEYPQuBL 85UEYPQuBL Hint Ogwu/VmCee Ogwu/VmCee No hint
解き方は「難読化シェル芸1」と同じです。
bashのxオプションを使います。
No hintの処理の箇所を見てみましょう。
+ echo No hint No hint ++ base64 -d ++ rev ++ echo =oAZhVmc + read r ++ echo cmV2Cg== ++ base64 -d ++ echo Z3JlcAo= ++ base64 -d + rev ++ echo YmFzZTY0Cg== ++ base64 -d + base64 ++ echo =owboNWZ ++ rev ++ base64 -d + echo ++ tr A-Za-z N-ZA-Mn-za-m ++ base64 -d ++ rev ++ echo XRKY + grep -q =ogWXdTS3IkcGRXO + exit
注目するのは、「grep -q =ogWXdTS3IkcGRXO」です。これと一致しないとexitするようです。
「=ogWXdTS3IkcGRXO」はどうやって生成されているかも、このデバック内容と、ソースの該当箇所を眺めるとわかります。
入力内容をbase64した後にrevしています。つまり、=ogWXdTS3IkcGRXOをrevしてbase64デコードした内容を入力してあげればいいことになります。
$ echo =ogWXdTS3IkcGRXO|rev|base64 -d 9tFrB7I7WZ
先に進みました。またNo hintなので、同じ方法で解きます。
+ echo ++ echo ==gC2Vmc ++ rev ++ base64 -d ++ echo XRKY ++ rev ++ tr A-Za-z N-ZA-Mn-za-m ++ base64 -d + rev ++ echo LzSmMGL0Pt== ++ tr A-Za-z N-ZA-Mn-za-m ++ base64 -d + grep -q =oQMjxkUHNlM4gXS + base64 ++ echo MKucqNb= ++ tr A-Za-z N-ZA-Mn-za-m ++ base64 -d + exit
$ echo =oQMjxkUHNlM4gXS|rev|base64 -d Ix82SGRLc1
まとめると
- 85UEYPQuBL を入力
- Ogwu/VmCee を入力
- 13秒待つか、sleepをkillする
- 9tFrB7I7WZ を入力
- Ix82SGRLc1 を入力
- 33秒待つか、sleepをkillする
HamaCTF{Y0uD1dI78db6173ca3c49e83cdff6ccb0860cdf1}
NandokukaShellGeiInqAns.zip (1.416 KB) kanata, 2017/12/31 17:30
f.zip (2.338 KB) kanata, 2017/12/31 17:30
NandokukaShellGeiSleeps.zip (1.319 KB) kanata, 2017/12/31 17:30
sign.zip (3.306 KB) kanata, 2017/12/31 17:30
zlib.zip (948 Bytes) kanata, 2017/12/31 17:30
q5_circuit.jpg (6.775 KB) kanata, 2017/12/31 20:12