SECCON Beginners CTF 2020 Elementary stackを理解する

こんにちは.リモート授業で一度も授業が一度も授業に現れず資料も与えられずにただただ課題のPDFが配布される授業があるのですが,中間試験はしっかりと行われることが告知されて萎えています.今回はCTF4Bから2週間弱たちましたが,解けなかった問題について考えてみました.

僕が本番で解けた問題のWrite upはこちら

Elementary stack

Pwnの問題です.本番ではチラッと覗いて難しそうだったのであまり時間をかけず他の問題を考えていましたが.楽しそうなのでこの問題について考えてみました.いくつかwrite upを梯子して僕がどのように考えたのかをメモします.実行ファイルchallmain.clibc-2.27.soが与えられました. コードは以下のようになっています.

long readlong(const char *msg, char *buf, int size) {
  printf("%s", msg);

  if (read(0, buf, size) <= 0)
    fatal("I/O error");
  buf[size - 1] = 0;

  return atol(buf);
}

int main(void) {
  int i;
  long v;
  char *buffer;
  unsigned long x[X_NUMBER];

  if ((buffer = malloc(0x20)) == NULL)
    fatal("Memory error");

  while(1) {
    i = (int)readlong("index: ", buffer, 0x20);
    v = readlong("value: ", buffer, 0x20);

    printf("x[%d] = %ld\n", i, v);
    x[i] = v;
  }
  return 0;
}

無限ループに囲まれているのでmain関数のリターンアドレスを書き換えるようなことはできなさそうです.mallocbufferの領域を保持してそこにreadを使用して値を書き込んで配列xに値を書き込んでいくプログラムのようです. mallocした場所に入力値を格納しているのですが,ローカル変数*bufferとして保持した領域のポインタを持っているのでなんとかなりそう. /bin/shをどうやって実行させるかを考えますが,今回はreadlong関数内のatolをGOT overwriteしてsystem('/bin/sh')を呼び出すべきだったようです.しかし,libcのアドレスがわからないのでsystemのアドレスがわからないんですね.ここで僕は全くわからなかったんですが,一度atol@gotprintfに書き換えることでatol(buf)printf(buf)とすることでformat string bugを発生させることが出来るそうです.なるほどすごい.format string attackでlibcのアドレスをリークすることでsystem関数を呼び出すことが出来るようになります. 手順的には以下のような感じ.

[Read More]
ctf  ctf4b  seccon  pwn 

SECCON Beginners CTF 2020解けた問題 writeup

こんにちは.福岡では緊急事態宣言は解除されましたが授業もアルバイト,ゼミもリモートのため相変わらず外出しない生活を送っています.

ctf4b

ctf4bに大学の研究室のメンバーで参加してきました.昨年は全く手が出ませんでしたが今年は結構楽しくCTFができました.(解けたとは言ってない.) 得意分野と言える分野もないので雑食でいろいろな分野を覗いてました. 僕はreadme,beginner's stack,tweetstoreをときました.また,時間内にフラグは得られませんでしたが終了後に気づいたunzipも記載します. (その他の問題も解けたら追記しようかな) では,

https://www.seccon.jp/2019/seccon_beginners/seccon_beginners_ctf_2020_5_23_1400.html

追記

pwnのelementary stackについてポストしました.

readme

Miscの問題です.問題サーバで動いているコードが配布されます.

#!/usr/bin/env python3
import os

assert os.path.isfile('/home/ctf/flag') # readme

if __name__ == '__main__':
    path = input("File: ")
    if not os.path.exists(path):
        exit("[-] File not found")
    if not os.path.isfile(path):
        exit("[-] Not a file")
    if '/' != path[0]:
        exit("[-] Use absolute path")
    if 'ctf' in path:
        exit("[-] Path not allowed")
    try:
        print(open(path, 'r').read())
    except:
        exit("[-] Permission denied")

ncコマンドでサーバに接続するとFile: と出てきてパスを入力します./home/ctf/flagを開くことができればフラグが得られそうです. しかし.入力文字列にはいくつかの制限があります.

  • 指定したパスが存在する
  • 指定したパスがファイルである
  • 指定したパスが絶対パスである
  • 指定されたパスにctfという文字列が存在しない
  • 指定したファイルが開ける

条件は以上です. ctfが許されないので/home/ctf/flagは当然の如く失敗します. ctfという文字列を使用せずにどの様にしてパスを取得するかがポイントです. 現在のプロセスが動いているカレントディレクトリを取得することができれば良さげです. そこで登場するのが/procです. /procファイルシステムは特殊なディレクトリでシステムの情報や動作しているプロセスの情報を取得することができます. あるプロセスに関する情報が欲しい場合は/proc/[pid]を参照します.自身のプロセスの情報を得たい場合は/proc/selfです. /procは面白いのでぜひいろいろ覗いてみてください. さて,/proc/self/cwdがプロセス自身のカレントディレクトリへのシンボリックリンクとなっています.が,ここで/proc/self/cwdを入れてもファイルじゃないのでダメです.そこで,/proc/self/environを入力してみます.すると環境変数がいっぱい出てきます.その中にPWD=/home/ctf/serverが見つかりました. このプロセスは/home/ctf/serverで動いてそうですね.

[Read More]
ctf  ctf4b  seccon  pwn  web