こんにちは.リモート授業で一度も授業が一度も授業に現れず資料も与えられずにただただ課題のPDFが配布される授業があるのですが,中間試験はしっかりと行われることが告知されて萎えています.今回はCTF4Bから2週間弱たちましたが,解けなかった問題について考えてみました.
僕が本番で解けた問題のWrite upはこちら.
Elementary stack
Pwnの問題です.本番ではチラッと覗いて難しそうだったのであまり時間をかけず他の問題を考えていましたが.楽しそうなのでこの問題について考えてみました.いくつかwrite upを梯子して僕がどのように考えたのかをメモします.実行ファイルchall
とmain.c
,libc-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関数のリターンアドレスを書き換えるようなことはできなさそうです.malloc
でbuffer
の領域を保持してそこにread
を使用して値を書き込んで配列xに値を書き込んでいくプログラムのようです.
mallocした場所に入力値を格納しているのですが,ローカル変数*buffer
として保持した領域のポインタを持っているのでなんとかなりそう.
/bin/sh
をどうやって実行させるかを考えますが,今回はreadlong
関数内のatol
をGOT overwriteしてsystem('/bin/sh')
を呼び出すべきだったようです.しかし,libcのアドレスがわからないのでsystem
のアドレスがわからないんですね.ここで僕は全くわからなかったんですが,一度atol@got
をprintf
に書き換えることでatol(buf)
をprintf(buf)
とすることでformat string bugを発生させることが出来るそうです.なるほどすごい.format string attackでlibcのアドレスをリークすることでsystem
関数を呼び出すことが出来るようになります.
手順的には以下のような感じ.