こんにちは。最近弊社ブログにチーム紹介文を書くぐらいイキっているyharimaのdeko2369です。
2018/12/23に行われたSECCON CTF国内大会の反省文として、反省点と自分のやったことをまとめて供養したいと思います。
反省点
問題がアレだったとかソレだったとかTwitterに投稿されていたりしますが、結局のところ以下の点に尽きるかなと思います。
- 単純にバイナリ力が足りなかった
バイナリコードのコードゴルフをいかに攻略できるかが今回の国内大会で上位を狙うポイントだったので、そこでゴルフ出来る実力がなかったのが一番の反省点です。
いい加減2年ぐらい積み本しているアセンブラ短歌本を読まないとアカンと感じたので短歌の「味わい深さ」を噛みしめながら勉強を進めたいと思います。
やったこと
ほぼほぼ自分以外のメンバーが問題を解いていて、じゃあ何するかと言ったらひたすらサポートに周っていたのが現実でした。つらい。あーバイナリ力ー。
Defence Flag自動投稿
やったのはDefence Flagの自動取得と投稿です。
Defence Flagが5分に1回更新されていたのですが、それを解答できた問題のDefence Flagに投稿するスクリプトを書いていました。
ついでにいちいちDefence Flagの書かれたページを見に行くのも面倒だったので、SlackにもFlagを流すようにしていました。更新されたら通知されるので結構安心感ありました。
const rp = require('request-promise');
const io = require('socket.io-client');
const { WebClient } = require('@slack/client');
let prev_flagword = '';
const socket = io('http://score.ja.seccon:8000');
socket.on('flagword', async function(data) {
words = data.flagwords;
for (const team of words) {
if (team.team_id == 5) {
const flagword = team.flagword;
if (prev_flagword !== flagword) {
console.log(flagword);
await postSlack(`defence keyword: ${flagword}`);
await updateMatsushimaToken(flagword);
prev_flagword = flagword;
}
}
}
})
function refresh() {
socket.emit('flagwords');
}
refresh();
setInterval(refresh, 3000);
async function updateMatsushimaToken(flag) {
const matsushima_url = 'http://matsushima.pwn.ja.seccon/MarinaBaySandsNo1Fhaimakaisoutyudayo';
var options = {
method: 'POST',
uri: matsushima_url,
form: {
defense_flag: flag
}
};
rp(options).then();
}
async function postSlack(message) {
try {
const token = '<token>';
const conversationId = '<channel id>';
const web = new WebClient(token);
const res = await web.chat.postMessage({ channel: conversationId, text: message });
} catch (e) {}
}
ただ、天橋立の問題のログインがどうしても突破できず、そこだけ最後まで手作業でFlag更新をしてました。まぁSlackに出てきたやつを使って更新するだけで、普通にFlagのページを監視するより楽だったので良かったかなと思います。
宮島通知
宮島という問題が30分に1度問題が更新されるので、それに気づくためにこれもBot化しました。毎時29分と59分にバイナリ担当だった @liniku さんにひたすら「MIYAJIMA yarou」と通知してました。
const cron = require('node-cron');
const { WebClient } = require('@slack/client');
cron.schedule('29,59 * * * *', async () => {
await postSlack();
});
async function postSlack() {
const token = '<token>';
const conversationId = '<channel id>';
const web = new WebClient(token);
const res = await web.chat.postMessage({ channel: conversationId, text: '@liniku MIYAJIMA yarou' });
}
まとめ
と、まぁあまりセキュリティ感はなく、どちらかというとChatOpsみたいなことをしてた国内大会でした。自分の実力不足(特にバイナリ)も否めないので来年はバイナリ力を鍛えることを目標に頑張っていきたいと思います。