走りました。
動画はここから見れます。
コンテストサイトは(生きていれば):RTACTF 2021
noalloca 156.23 sec
int main() { unsigned size; char buf[0x80]; /* Input size */ printf("size: "); scanf("%d%*c", &size); if (size > 0x80) { puts("*** buffer overflow ***"); return 1; } /* Input data */ printf("data: "); readn(buf, size-1); return 0; }
結論としては、size=0のときinteger overflowなんですが、初手人力fuzzerをしているときに+を入れたらバグったのでそのまま走りきりました(後から考えると、意味不明な行動)。比較的素早く解けました。
alloca 275.46 sec
int main() { int size; char *buf; /* Input size */ printf("size: "); scanf("%d%*c", &size); /* Input data */ printf("data: "); buf = alloca(size); readn(buf, size); return 0; }
一見するとバグが無くねと思って焦りましたが、allocaは負の方向のmitigationはないらしい、そうなんだ。ドキドキしました。-1を入れて、バッファ・オーバーフローすると良いです。
constalloca 673.13 sec
void readn(char *ptr, int size) { /* Read data up to `size` bytes into `ptr` */ for (int i = 0; i != size; i++, ptr++) { read(0, ptr, 1); if (*ptr == '\n') break; } *ptr = '\0'; // terminate by null } int main() { char title[0x18]; char *content = alloca(0x80); /* Input title */ printf("title: "); readn(title, 0x18); /* Input content */ printf("data: "); readn(content, 0x80); return 0; }
これはマジで焦りました。まず、main見るとバグがないので。 まあバグがないということは、ということでreadnをおもむろに見ると、readnにoff by one errorがあります。readnは心理的に無視しがちなので怖いですね。
次に、off-by-oneで書き込めるのは0なので、もうこういうことやろwみたいな感じで適当にソルバーを書きます
動画でいうとこの当たりで、シェル取れるスクリプトを書いていたんですね(言い訳)。
ところで、pwn-noobなので、ここでガチャ要素が生まれるということに気づかず(もうこれで解けるように"仕組まれているはず"と思って)動かないので焦ります。HELP
色々ガチャガチャやった結果、やっぱ最初ので良かったんじゃねとなり、そうこうしているとローカルでシェルが取れたので、なんかガチャ要素あるんだっけ〜と思いながら適当にremoteで3回神頼みをしたらフラグが取れたので、良かったということにしました。
speedrunならではのドキドキですね。
https://gist.github.com/moratorium08/d271aae775f978821bd076d0ff7148f1
感想
CTFは普通24時間とか48時間とか潤沢な時間があり、あんまり"時間に焦る"ということは経験しないので(といいつつ、ギリギリになるとやる気が出る問題により結構タイムアタックすることもありますが)、speedrunは競技としてだいぶ違うなとなります。腰を据えてできるかどうかは割とでかい。普通のCTFで解けない問題は能力的に解けないみたいな感じになると思っているんですが、speedrunでは能力的に解けるというだけではダメなので。
この気持ちは、数学の期末試験とか、大学入試的なドキドキですかね。うっかり、誤った方向に掘っていってしまうと終わるのとケアレスミスで時間が潰れるドキドキ感
TSG LIVEでは割と冷やしてきた経験があるのですが、今回はめちゃくちゃな冷えにはならなかったのは良かったなと思います..