問題
解いてみた
ソースコードを見てみるとflag.txtを出力する処理がありました。
この関数を呼び出せばよさそうです。
呼び出し元を確認してみます。
main()関数の中でパスワードがあってれば呼ばれるようです。
ltrace使ってstrcmpの引数を見ようと思ったんですが、ncでつないでいるときにどうやってやるのかわかりませんでした。
なので、とりあえず名前の入力とパスワードの入力の桁数を超えてみようと思います。
名前は256文字より大きく、パスワードは64文字より大きくしてみます。
まずは名前から
末尾に変な文字列がくっつきました。
とりあえずパスワードに放り込んでみます。
できてしまった。
何が起きてるんでしょう。
42行目でnameを入力します。
CTFmanと入力した場合以下のように格納されます。
1文字目 | 2文字目 | 3文字目 | 4文字目 | 5文字目 | 6文字目 | 7文字目 |
---|---|---|---|---|---|---|
C | T | F | m | a | n | ¥0 |
48行目のstrcatは終端文字を消して文字列結合して最後に終端文字をつける。
1文字目 | 2文字目 | 中略 | 6文字目 | 7文字目 | 8文字目 | 9文字目 | 中略 | 最後-2文字目 | 最後-1文字目 | 最後文字目 |
---|---|---|---|---|---|---|---|---|---|---|
C | T | 中略 | n | \n | P | l | 中略 | d | . | ¥0 |
となります。
それで59行目でこれを表示する。
という流れです。
これは結果論ですが、メモリ上ではname変数の直後にpassword変数があるようです。
∵今回の解き方でname変数をオーバーフローさせたときにパスワードが表示されたからです。
説明します。
とりあえずnameの直後にpasswordがあると仮定します。
name配列は256文字なのでそれを超える文字を入力したときにさっきの流れはどうなるんでしょう。
やってみます。Aをたくさん入力するとします。
1文字目 | 2文字目 | 中略 | 256文字目 | 257文字目 |
---|---|---|---|---|
A | A | 中略 | A | ¥0 |
42行目でこんな感じの文字列を入力したとします。
すると48行目では以下のようになります。
1文字目 | 2文字目 | 中略 | 256文字目 | 257文字目 | 258文字目 | 中略 | 最後-2 | 最後-1 | 最後 |
---|---|---|---|---|---|---|---|---|---|
A | A | 中略 | A | \n | P | 中略 | d | . | ¥0 |
これが59行目でそのまま表示されると思いきや、56行目の処理でパスワードを変数に代入しています。
なのでname直後にあるpasswordが上書きされるので(パスワードはpが続くとして)
1文字目 | 2文字目 | 中略 | 256文字目 | 257文字目 | 258文字目 | 中略 | pass最後-1 | pass最後 |
---|---|---|---|---|---|---|---|---|
A | A | 中略 | A | p | p | 中略 | p | ¥0 |
となります。
そして59行目で文字列を表示する際に終端文字はnameにはなく直後に続くパスワードに終端文字があるのでここまで表示されてしまう。
ということですかねー。