年間レポート 〜2015年版〜

ぐだぽよ~、おきなわです。

先ほどメールチェックをしていたら jetpack から 2015年 の年間レポートなるものが見れるようになったので、自分用にもメモとして掲載しておこうと思います。

2015年のブログ

自分で Facebook にこのブログのことを投稿したことはないため、トップリファラーサイトとして Facebook があるのが謎です、、、

まぁ眺める分には面白かったので、興味がある方はぜひ見てみて下さい。

5 秒くらいは暇つぶし出来ます(*^_^*)

ではでは〜

FreeBSD Ports Collection からユーザ権限でインストール

ぐだぽよー、おきなわです。

最近、一ユーザとして利用しているサーバにて、いろいろソフトをインストールしたくなり、root 権限を使えなくても ports を利用出来るように設定しました。今後また同じことをしたくなった時のために、今回やったことをメモっておきたいと思います。

やりたい事

FreeBSD サーバにて、root 権限を持っていなくても Ports からソフトウェアをインストールできるようにしたい。

設定手順

以下のサイトを参考にしました。

otsune’s FreeBSD memo :: ユーザー領域にFreeBSD portsをインストールする方法

設定ファイルの作成

まず ports のインストール先などを環境変数の指定により変更します。

僕は .bash_profile に以下の用に環境変数を記述しました。


# setting for ports to install by user privileges
export __MAKE_CONF=/dev/null
export INSTALL_AS_USER=yes
export PREFIX=${HOME}/usr/local
export LOCALBASE=${HOME}/usr/local
export PKG_DBDIR=${LOCALBASE}/var/db/pkg
export PORT_DBDIR=${LOCALBASE}/var/db/pkg
export DISTDIR=${LOCALBASE}/tmp/dist
export WRKDIRPREFIX=${LOCALBASE}/tmp/work
export PORTSDIR=${HOME}/usr/ports
export PKGTOOLS_CONF=${LOCALBASE}/etc/pkgtools.conf
export DEPENDS_TARGET='install clean'
export LDCONFIG="/sbin/ldconfig -f ${LOCALBASE}/var/run/ld-elf.so.hints -i -R ${LOCALBASE}/etc/ld-elf.so.conf"
export LD_LIBRARY_PATH=${LOCALBASE}/lib
export LD_RUN_PATH=${LOCALBASE}/lib
export PATH=${LOCALBASE}/bin:${LOCALBASE}/sbin:${PATH}
export MANPATH_MAP="${LOCALBASE}/bin ${LOCALBASE}/man"
# enable .bashrc
source ~/.bashrc

view raw

.bash_profile

hosted with ❤ by GitHub

なお、各環境変数やその値の示す意味は以下の通りです。

(説明は ports/Mk/bsd.port.mk 等を参考にしています。)

  • __MAKE_CONF : make コマンドを実行する際に参照する make.conf のパスを明示的に指定します。デフォルトでは /etc/make.conf を参照するため、そちらに環境変数の記述があるとその値を使用します。そのため、今回は /dev/null を指定してシステム全体での設定が記述されている make.conf を参照しないようにします。
  • INSTALL_AS_USER : root アクセスを利用せずに現在のユーザとしてインストールを行うために利用します。
  • PREFIX : ports からのファイルのインストール先を指定します。デフォルトでは USE_LINUX_PREFIX がセットされていれば ${LINUXBASE} を、されていなければ ${LOCALBASE} を適用します。
  • LOCALBASE : ports からのファイルのインストール先を指定します。デフォルトでは /usr/local です。
  • PKG_DBDIR : どのパッケージをインストールしたかの記録を保存する場所を指定します。デフォルトでは /var/db/pkg です。
  • PORT_DBDIR : port の設定オプションを保存する場所を指定します。デフォルトでは /var/db/ports です。
  • DISTDIR : ダウンロードしたソースコードの保管場所を指定します。デフォルトでは ${PORTSDIR}/distfiles です。
  • WRKDIRPREFIX : コンパイルなどを行う際に利用する一時的な作業用ディレクトリの場所を指定します。
  • PORTSDIR : ports tree のルートディレクトリを指定します。デフォルトでは /usr/ports です。
  • PKGTOOLS_CONF : pkgtools の設定ファイルの場所を指定します。
  • DEPENDS_TARGET : 依存する ports をインストールする際の挙動を設定します。デフォルトでは install です。
  • LDCONFIG : リンカに利用可能な共有ライブラリを伝えるための変数のようです。
  • LD_LIBRARY_PATH : 共有ライブラリの場所を指定します。
  • LD_RUN_PATH : プログラム実行時に利用する共有ライブラリの場所を指定します。
  • PATH : 実行可能なコマンド群の場所を指定します。
  • MANPATH_MAP : PATH にある各ディレクトリに対して、man ページファイルの検索パスに追加すべきディレクトリを一つづつ指定します。

なお、LD_RUN_PATH の LD_LIBRARY_PATH との違いですが、

LD_RUN_PATH で指定したパスは実行ファイルに埋めこまれますが、LD_LIBRARY_PATH はダイナミックリンカ ld-elf.so が利用します。コンパイル時に共有ライブラリの検索パスを指定するのが LD_RUN_PATH で、実行時に指定するのが LD_LIBRARY_PATH。

FreeBSD-users-jp 60135

らしいです。

必要なディレクトリやファイルの作成

設定ファイルに記述したディレクトリを作成します。

$ mkdir -p ~/usr/local/etc ~/usr/local/lib ~/usr/local/tmp/dist ~/usr/local/tmp/work ~/usr/local/var/db/pkg

ライブラリの場所を記述したファイルを作成します。

$ ldconfig -r | awk '/search/ {print $3}' | tr ":" "\n" > ~/usr/local/etc/ld-elf.so.conf
$ echo ${HOME}/usr/local/lib >> ~/usr/local/etc/ld-elf.so.conf

僕の環境の場合は

$ sysctl -n kern.osreldate

が実行出来たのでここまでですが、上記のコマンドが実行出来なかった場合は環境変数にさらなる追加記述が必要のようです。(ここでの記述はめんどくさいので省略します。参考元サイトの方にきちんと記述されていたため、そちらを参考にしてください。)

ports の展開

github にも公開されているため、そちらからダウンロードして来ても良いかもしれません。

freebsd/freebsd-ports · GitHub

$ git clone --depth 1 github:freebsd/freebsd-ports.git ~/usr/ports

もし既にシステム全体で使用している ports があるなら、そちらを利用した方が早いと思います。

.bash_profile に記述した環境変数のうち、PORTSDIR を記述しなければデフォルトの ports (/usr/ports)を利用します。

Let’s インストール

ここまでくればあとは通常通り

$ cd ~/usr/ports/editors/vim
$ make install clean

とかやるとインストールすることが出来ます。やったぜ!

 

簡単!にゃんぱす Bot を作ろう!

にゃんぱすー、おきなわです。

ついに待ちに待ったのんのんびより りぴーとの放送が始まりました!!!いぇーい!

ということで Twitter のタイムラインをにゃんぱすーで賑やかにするために、Twitter に「にゃんぱすー」と自動投稿する Bot プログラム、にゃんぱす Bot を作っていきたいと思います。

環境の事前準備

今回は Python を使って Bot プログラムを書いていきます。Python にも Twitter API を簡単に使えるように有志が作成したライブラリが多くあるのですが、ここでは tweepy を使用します。なので事前に Python の実行環境を用意し、tweepy をインストールしておいてください(pip を利用すると簡単に tweepy をインストールできます)。

では環境が既に準備されているという前提で、まずは Bot を作るために必要な情報を用意しましょう。

Bot を Twitter Apps に登録する

まず最初に Bot を動かしたいアカウントで Twitter にログインし、ログインが出来たら Twitter Application Management にアクセスします。

スクリーンショット 2015-07-09 5.23.12

Create New App をクリックします。(上の画面だと既に幾つか登録してあったため登録済みのアプリが表示されていますが、一度も登録したことがないと何も表示されず、Create New App ボタンが真ん中に表示されます。)

スクリーンショット 2015-07-09 5.28.41

作成するアプリの情報を適当に入力します。

  • Name:アプリの名前です。ほかのユーザからも見ることが出来ます
  • Description:アプリの説明です。10 文字以上 200 文字以内で書くことが出来ます
  • Website:アプリのホームページとして登録するサイトの URL を入力します
  • Callback URL:今回は使用しないため、入力しなくても大丈夫です

スクリーンショット 2015-07-09 5.28.55

アプリの情報を入力後、規約に同意するというチェックボックスをチェックし、Create your Twitter application をクリックします。

スクリーンショット 2015-07-09 5.40.11

アプリが作成出来ました。次にアプリ名の下に表示されているタブのうち、Keys and Access Tokens をクリックします。

スクリーンショット 2015-07-09 5.49.28

Consumer Key (API Key) と Consumer Secret (API Secret) が表示されると思うのでメモっといてください。あとで使用します。(上の画像ではわざと消しています。)

スクリーンショット 2015-07-09 5.49.44

下の方に Create my access token というボタンがあるので、それをクリックします。

スクリーンショット 2015-07-09 5.56.26

Access Token と Access Token Secret が表示されますのでこれもまたメモっといてください。あとで使用します。(上の画像ではわざと消しています。)

これで準備が整いました。それでは早速 Bot プログラムを書きましょう。

にゃんぱす Bot のプログラムを書く

では Python で次のようなプログラム simple_tweet.py を書きましょう。


#!/usr/bin/env python
#-*- coding:utf-8 -*-
import tweepy
# infomation to access twitter api.
consumer_key = 'XXXXXXXXXXXXXXXXXXXXXXXXX'
consumer_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
access_token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
access_token_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
# authenticate the twitter account by OAuth
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth_handler=auth)
# tweet
api.update_status(status="にゃんぱすー")

view raw

simple_tweet.py

hosted with ❤ by GitHub

7 行目から 10 行目の consumer_key などのところはそれぞれ Bot を登録した際にメモったものを書いてください。その情報を使用して 13 行目から 15 行目でアカウントの認証を OAuth 認証で行います。最後に 18 行目でツイートを行います。「にゃんぱすー」と書かれた部分を変更することでさまざまなことをつぶやくことが出来ます。

では早速動かしてみましょう。ターミナルで以下のように実行します。

$ chmod 744 simple_tweet.py
$ ./simple_tweet.py

すると以下のようにツイートができます。

上記のプログラムを決まった時間に実行することで時報などの定期的につぶやく Bot が作れるわけです。簡単ですね。

では今度は「にゃんぱすー」と挨拶されたら「にゃんぱすー」と返事をするボットを作ってみましょう。次のようなプログラム simple_bot.py を書きましょう。


#!/usr/bin/env python
#-*- coding:utf-8 -*-
import tweepy
import simplejson
import random
# infomation to access twitter api.
consumer_key = 'XXXXXXXXXXXXXXXXXXXXXXXXX'
consumer_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
access_token = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
access_token_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
# authenticate the twitter account by OAuth.
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth_handler=auth)
# get bot name
bot_name = api.me().screen_name
# create streamlistener class to modify action in userstreaming.
class myStreamListener(tweepy.StreamListener):
# define the action when data come from twitter.
def on_data(self, data):
# the style of data which come from twitter is json, so start with "{".
if data.startswith("{"):
# convert json to Python dictionary, because it is very useful.
data = simplejson.loads(data)
# define the action when catch any tweet.
if "text" in data:
# if the tweet is reply to bot and it contains keyword, return a greeting.
if data['in_reply_to_screen_name'] == bot_name and "にゃんぱすー" in data['text']:
Tweet = "@" + data['user']['screen_name'] + " にゃんぱすー" + " " * random.randint(0,10)
api.update_status(status = Tweet, in_reply_to_status_id = data['id'])
# set information to start streaming
stream = tweepy.Stream(auth=api.auth, listener=myStreamListener(), secure=True, timeout=None)
# start userstreaming
stream.userstream()

view raw

simple_bot.py

hosted with ❤ by GitHub

上記のプログラムでは userstream を使用しています。そうすることでリアルタイムで返答を返すことが出来ます。7 行目から 10 行目の consumer_key などのところは先ほどと同じように、それぞれ Bot を登録した際にメモったものを書いてください。20 行目で Bot 自身の名前を取得し、それを元に 33 行目で自分へのツイートかどうか、またツイートに「にゃんぱすー」というキーワードが含まれているかどうかを判断しています。34 行目では返事のツイートを作成しているのですが、ツイートの最後に全角スペースをランダムで付けることでツイートが重複して呟けなくなることを防いでいます。ではコマンドラインから動かしてみましょう。このプログラムは一度動作させると接続が切られるまでずっと動作し続けるので、& を付けてバックグラウンドで動作させるのがよいでしょう。

$ chmod 744 simple_bot.py
$ ./simple_bot.py &

ではボットに話しかけてみましょう。

挨拶をすると自動で返答してくれました。より Bot らしくなりましたね。

より複雑な Bot への発展

より複雑な挙動を行う Bot を作成したい場合は、上記の simple_bot.py プログラムの myStreamListener クラスの 32 行目以下を書き換えることで作ることが出来ます。なお userstream における 1 つのツイートが持つ情報ですが、例えば

というツイートだと、以下のように情報が流れてきます。


{
'lang': 'ja',
'possibly_sensitive': False,
'geo': None,
'contributors': None,
'in_reply_to_status_id_str': None,
'truncated': False,
'user': {
'profile_link_color': '00B4CC',
'following': None,
'default_profile': False,
'utc_offset': 32400,
'friends_count': 419,
'statuses_count': 57898,
'time_zone': 'Tokyo',
'listed_count': 38,
'geo_enabled': True,
'default_profile_image': False,
'favourites_count': 1551,
'profile_background_image_url': 'http://abs.twimg.com/images/themes/theme19/bg.gif',
'profile_sidebar_border_color': 'FFF8AD',
'verified': False,
'description': "九州工業大学 学生です\r\nクズです☆(ゝω・)vキャピ\r\nLet's begin FX! \r\n\\カーニバルダヨ!/",
'profile_background_tile': False,
'id': 215645258,
'profile_text_color': '333333',
'profile_background_color': 'FFF04D',
'profile_sidebar_fill_color': 'F6FFD1',
'notifications': None,
'name': 'ふぃりぴん∅おきなわ',
'followers_count': 438,
'created_at': 'Sun Nov 14 14:38:03 +0000 2010',
'protected': False,
'profile_image_url_https': 'https://pbs.twimg.com/profile_images/564047755547377667/r7uHX8kc_normal.png',
'profile_image_url': 'http://pbs.twimg.com/profile_images/564047755547377667/r7uHX8kc_normal.png',
'id_str': '215645258',
'location': '福岡/飯塚',
'is_translator': False,
'screen_name': 'take01x',
'lang': 'ja',
'profile_use_background_image': True,
'contributors_enabled': False,
'follow_request_sent': None,
'profile_background_image_url_https': 'https://abs.twimg.com/images/themes/theme19/bg.gif',
'url': 'http://www.take01x.okinawa',
'profile_banner_url': 'https://pbs.twimg.com/profile_banners/215645258/1400589127'
},
'place': None,
'source': '<a href="http://sites.google.com/site/yorufukurou/" rel="nofollow">YoruFukurou</a>',
'id_str': '618913474677059584',
'text': 'This is sample\nこれはサンプルです',
'in_reply_to_user_id': None,
'timestamp_ms': '1436395445876',
'in_reply_to_screen_name': None,
'created_at': 'Wed Jul 08 22:44:05 +0000 2015',
'favorite_count': 0,
'entities': {
'urls': [],
'hashtags': [],
'trends': [],
'user_mentions': [],
'symbols': []
},
'in_reply_to_status_id': None,
'filter_level': 'low',
'id': 618913474677059584,
'favorited': False,
'retweet_count': 0,
'in_reply_to_user_id_str': None,
'retweeted': False,
'coordinates': None
}

view raw

tweet.py

hosted with ❤ by GitHub

そのため、例えば上記の simple_bot.py プログラムの myStreamListener クラスの 32 行目以降において、ツイートしたユーザの名前にアクセスするには data[‘user’][‘screen_name’] 、ツイート本文にアクセスするには data[‘text’] と書けば良いわけです。なお、詳しいデータ構造や各値の意味については以下のサイトを参考にしてください。

Streaming message types | Twitter Developers

さいごに

だいぶ説明を省きましたが、以上のように、単純に特定のキーワードに反応して特定のツイートを行うという Bot なら比較的簡単に書くことが出来ます。

Python をこれから勉強したいという方、Twitter の Bot を作ってみたいという方はぜひ自分の Bot を作ってみてください。楽しいですよ♪

ネットエージェント新卒採用 CTF Writeup 〜後編〜

ぐだぽよー、おきなわです。

前編の記事を書いてからかなり日数があいてしまいましたが、ぼちぼち後編を書いていこうかなと思います。

以前の writeup は以下。

ネットエージェント新卒採用 CTF Writeup 〜前編〜 | おきなわのぶろぐ

 

では早速書いていきましょう。

mondai6

問題もやっと折り返しを迎えました。さて、6 問目ですが問題文には以下の URL のみ記載されていました。

http://49.212.84.208/cgi-bin/hode7hb376dgeas6df783gr4/mondai6.cgi

どうやら次は Web 問題のようですね。curl コマンドを使って早速アクセスしてみます。

$ curl http://49.212.84.208/cgi-bin/hode7hb376dgeas6df783gr4/mondai6.cgi
<HTML><BODY>use R4000
</BODY></HTML>

use R4000 と言われました。何のことや!ってことで検索してみると、どうやらマイクロプロセッサのことっぽい。

R4000 – Wikipedia

指定のマイクロプロセッサを使えってことか?と思い立ち、R4000 のエミュレータっぽいやつを探し、実行環境を整え、動かしてみました。(迷走して色々調べてたので何処のサイトを参考にしたかすら覚えていない、、、)

動かした際のスクショは以下。

よっしゃ!動いた!!と思ったのも束の間、ネットワークの設定が上手くいかない、、、繋がらない、、、もぅマヂ無理。

しかし、ここでふと、僕はある事に気づきました。

「でもサーバ側から見て判別できそうなのって User-Agent とかくらいじゃね?ってことはそこを偽装すればいいんじゃね???」

ということで早速 R4000 について再度調べ直すことに。すると以下の様な情報にたどり着きました。

 MIPSプロセッサはデジタルTVやDVDレコーダー、ネットワーク機器、プリンタなどの組み込み機器で広く利用されている。身近な例としては、米MIPS Technologiesの「R4000」コアプロセッサを2つ内蔵した、ソニーの携帯ゲーム端末「PSP(プレイステーションポータブル)」が挙げられる。

世界で最も多く出荷されたRISCプロセッサMIPSのサバイバル戦略 - TechTargetジャパン システム開発

なるほど、PSP か!!ってことで PSP の User Agent を調べる。

●PSP (PlayStation Portable)
Mozilla/4.0 (PSP PlayStation Portable); 2.00)

userAgent一覧/ユーザーエージェント一覧

ということらしいので早速 User Agent を偽装してみる。

$ curl -A "Mozilla/4.0 (PSP PlayStation Portable); 2.00)" http://49.212.84.208/cgi-bin/hode7hb376dgeas6df783gr4/mondai6.cgi
<HTML><BODY>de la Bucure?ti
</BODY></HTML>

お、なんかメッセージが変わった!!

どうやらルーマニア語で「ブカレストから?」という意味らしい。

という事はブカレストからアクセスすれば良いのか?と思い、ブカレスト付近のプロキシサーバを探し、プロキシを通してアクセスしてみるも変わらず。使用したプロキシサーバが悪いのか?!と考え、その後もプロキシを使用するという線から色々試してみるも上手くいかず。じゃあ位置情報とかか?!と思い、無理やり位置情報を投げてみたりしましたが、やっぱり上手くいかず、、、

そこでふと「最初は User Agent の偽装だったし、もしかして HTTP ヘッダーで何とかするんじゃね?」と思いつき、調べた結果 Accept Language とかじゃね?と言う事で Accept Language をルーマニア語(ro)にして再度実行。

$ curl -A "Mozilla/4.0 (PSP PlayStation Portable); 2.00)" http://49.212.84.208/cgi-bin/hode7hb376dgeas6df783gr4/mondai6.cgi --header "Accept-Language: ro"
<HTML><BODY>key: Minesweeper1990
</BODY></HTML>

上手くいった!!!

と言う事で答えは Minesweeper1990 でした。

mondai7

解凍後、以下の様な構成のディレクトリが。

mondai7
├── hint7.txt
├── mondai8.zip
└── normal.exe

次はバイナリの問題のようです。

まずは何も考えずに strings コマンドで文字を抜き出して眺めてみます。

$ strings normal.exe

特にこれといってそれっぽいものは見つからなかったため、バイナリを解析する必要があるようですね、面倒くさい。

正直 exe ファイルの解析はあまり得意ではないので、この問題は一緒に問題を解いていたなーが君に丸投げする事にしました。なので僕は直接は解いてません。

なーが君曰く、最初は動的解析を行ったところ、なかなかうまく行かなかったらしいです。その後 exe ファイルがデバッガ判定を行ってデバッガ経由で起動された時とそうでない時で動作を変えているのが上手くいかない原因ではないかと考え、静的解析に切り替えて解析を行ったところ上手くいったとのことでした。具体的(?)には正解である文字列を作成してるっぽい処理をしているところがあったため、そこの処理を追っていったとのこと。ちゃんとどうやって解いたか聞いたのですが、殆ど覚えてないです、、、やる気があればちゃんと解いて追記しようと思います。

ちなみに今回の答えは TochuKasou だったらしいです。

mondai8

解凍後、以下の様な構成のディレクトリが。

mondai8
├── mondai8.tc
├── mondai8.txt
└── mondai9.zip

そして問題は以下の文章のみ。

TrueCrypt pass:mondai8

漢字8文字

どうやら mondai8.tc が TrueCrypt で暗号化されたイメージファイルのようなので、まずはそれを素直にマウント。マウントすると何枚かの画像ファイルなどがありました。

mondai8/
├── $RECYCLE.BIN
│   └── desktop.ini
├── Beale_1.svg
├── Crete_-_Phaistos_disk_-_side_A.JPG
├── Dorabella-cipher-image.png
├── Linear_A_tablets_filt.jpg
├── dagapeyeff_cipher.jpg
└── gold_bar.jpg

基本的にイメージファイル等を扱う問題では消されたデータを復元して解いていく流れのものが多いため、見えている画像ファイル達はどうせダミーだろうなぁと思いながらも一応 google 画像検索で検索をかけてみると以下の記事がヒット。

いまだ解読されていない歴史的な10種の暗号 – GIGAZINE

画像ファイルは全てこのサイトから辿れるものと全く同じだったため、ダミーだと確認出来ました。次に消されたファイルの復元を行います。私は Autopsy を使って復元を行いました。まずおもむろに Autopsy を起動します。

$ autopsy
============================================================================
Autopsy Forensic Browser
http://www.sleuthkit.org/autopsy/
ver 2.24
============================================================================
Evidence Locker: /usr/local/var/lib/autopsy
Start Time: Fri May 22 20:59:31 2015
Remote Host: localhost
Local Port: 9999

Open an HTML browser on the remote host and paste this URL in it:

http://localhost:9999/autopsy

Keep this process running and use <ctrl-c> to exit

その後ブラウザで http://localhost:9999/autopsy にアクセスすると以下の画面に。

スクリーンショット 2015-05-22 21.03.45

まずは解析を行うための準備を行う。NEW CASE を選択。

スクリーンショット 2015-05-22 21.08.07

上の画像のように Case Name、Description、Investigator Names を適当に入力し、NEW CASE をクリック。

スクリーンショット 2015-05-22 21.10.12

リストから先ほど作った CASE を選択し、ホストを追加するために ADD HOST を選択。

スクリーンショット 2015-05-22 21.11.13

デフォルトで値が入っているので、そのまま ADD HOST を選択。

スクリーンショット 2015-05-22 21.11.28

確認画面が表示されるので、解析するイメージを選択するために ADD IMAGE をクリック。

スクリーンショット 2015-05-22 21.43.36

ADD IMAGE FILE をクリック。

スクリーンショット 2015-06-07 21.15.11

解析したいイメージファイル(今回は TrueCrypt で複合化したイメージファイル)のパスを上の画像のように絶対パスで記入し、Type と Import Method を選択し、NEXT を選択。今回は Type は Disk、Import Method は Symlink を選択。

スクリーンショット 2015-06-07 21.15.46

ディスクイメージの種類を選択するよう言われるため、Volume Image を選択し、OK をクリック。

スクリーンショット 2015-05-22 22.04.43

MD5 ハッシュを計算するか聞かれるので Ignore を選択し、マウントポイントを適当に /Volumes/c/ とかにして ADD を選択。

スクリーンショット 2015-05-22 22.04.53

確認メッセージが出るので OK を選択。

スクリーンショット 2015-05-22 22.05.24

これで解析を行う準備が整いました。早速やっていきましょう。ANALYZE を選択。

スクリーンショット 2015-05-22 22.05.41

上のタブの FILE ANALYSIS を選択。

スクリーンショット 2015-05-22 22.06.34

すると普通のファイルが青色で、消されたファイルが赤色で表示されます。

ここでファイル名を眺めていると、今日の本.xlsx という如何にも怪しいファイルを発見。ファイル名をクリックするとファイルをダウンロード出来るため、今日の本.xlsx  をクリックします。すると autopsy というファイル名でダウンロードできます。ダウンロード後、適当に book.xlsx などと名前を変更し、開いたところ、エラーを吐いて開けず。そこでバイナリエディタでファイルを開いてみましょう。私はバイナリエディタとして 0xED を使用しました。

スクリーンショット 2015-06-07 22.20.53

ファイルの先頭に余計な部分(PK の前までの部分)があったため、その部分を削除・保存して再度開くと無事開くことが出来ました。

開いた Excel ファイルには 3 つのシートがあり、1 つ目のシートには a から z に対応する数字が、2 つ目のシートには奇談クラブという小説(?)の一部が、3 つ目のシートには password という key が書かれていました。どうやら暗号のようなのですが、最初はどうやって解いていけば良いのか全く思いつきませんでしが。ところが一緒に解いていたなーが君が「これって 1 つ目のシートに書かれた a から z に対応した数字がそれぞれ行番号と何番目の文字かを表してるんじゃない?」的なことを言い出しました。つまり “a” は 2 シート目の 62 行目の 11 文字目である “気” に対応して居るのではないか、ということです。そのように解釈すると a から z の対応表は以下のようになります。

この表を見ながら key である password を各文字置き換えると 意気揚揚明鏡止水 となりました。それが答えでした。

mondai9

解答後のディレクトリ構成は以下の通り。

mondai9
├── mondai10.tc
└── mondai9.pkt

file コマンドを使ってファイルを調べてみます。

$ file mondai9.pkt
mondai9.pkt: tcpdump capture file (little-endian) - version 2.4 (Ethernet, capture length 65535)

今度はキャプチャされたパケットを眺める問題のようです。というわけでおもむろに wireshark を立ち上げて読み込んで眺めてみましょう。

スクリーンショット 2015-06-08 7.27.43

とりあえず http 通信でサーバに向けた通信のみを見てみます。

スクリーンショット 2015-06-08 8.39.42

何かファイルをアップロードしているようなので、パケットからアップロードしているファイルを取り出します。すると zip ファイルが 1 つ、docx ファイルが 1 つ、xls ファイルが 2 つの合計 4 つのファイルを抽出することが出来ました。

meast_ecn_notes_fill.zip
空港代码.xls
صحيفة.docx
第一批基地名单.xls

まずは zip ファイルを解凍しようとしたのですが、パスワードが設定されていたため、再度パケットを眺めながらそれらしい文字列を探して試してみましたが解凍できず、、、次にその他のファイルも開いてみましたが、どのファイルも何も書かれていませんでした。他に思いつく事も無かったため、おもむろに docx を解凍し、pass という単語で文字列検索をしてみました。

$ unzip -q صحيفة.docx
$ grep -R "pass" .
./docProps/core.xml:<cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title></dc:title><dc:subject></dc:subject><dc:creator>user</dc:creator><cp:keywords></cp:keywords><dc:description><strong><strong>password: lastonemile</strong></strong></dc:description><cp:lastModifiedBy>杉浦 隆幸</cp:lastModifiedBy><cp:revision>4</cp:revision><dcterms:created xsi:type="dcterms:W3CDTF">2013-12-13T12:04:00Z</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">2015-03-20T02:31:00Z</dcterms:modified></cp:coreProperties>

お、パスワード書いてある!ってことで答えは lastonemile でした。

結局パスワードの掛かった zip ファイルはダミーだったみたいだけど、中には何が入ってたんだろ、、、

mondai10

ついに最終問題です。最後の問題は実際に指定された場所まで行って問題の入った SD カードを回収しないといけないとのこと。場所は 4 箇所あり、関東に 2 つ、関西に 2 つありました。しかし私が最後まで解いた時には既に関東に置かれたものは回収され、関西に置かれたものしか残っていませんでした。関西と言えど、さすがに福岡から行くのは大変なため、関西に居る知り合いに頼むことにしました。誰に頼もうかと思っていたところ、僕となーが君の共通の知り合いであるおわたん君なら行ってくれるのではないかということで頼んでみたところ、行ってくれる事になりました。下記は彼が取りに行った時のことを書いた記事です。

あの日 kansai1 で起こったできごとをボクたちはまだ知らない – にゃるにゃる

どうやらすでに回収されていたようでした、、、ごめんねおわたん、、、ということで最後に残った kansai2 を回収することに。しかし再度おわたん君に頼むのはちょっと可愛そうだし、結構遠いようだったので、別の方に頼むことにしました。大学の講義で知り合った人達がいる Slack のグループに誰か取りに行ってくれないか投げてみたところ、りらっくま君という子が行ってくれる事に。下記は彼が取りに行った時のことを書いてもらった記事です。

ネットエージェント – SDCardFindingBattle【kansai2】 | larufa’s blog @ テキトー

kansai2 の SD カードは無事回収してもらうことが出来ました!!!やったぜ!!!!!!!

さて、SD カードを送ってもらい、無事問題に取り組むことができるようになりました。まずはカードを Read only でマウントすると、入っていたのは Truecrypt で暗号化されたイメージファイルのみ。ということで、イメージファイルを渡された時の常套手段である削除されたファイルの復元を試みますが、それらしいファイルは出てこず、、、しかしこの時、復元したファイルの中に Mac でマウントすると自動で作成されるディレクトリがあり、ある可能性に気づきました。

「もしかして、書き込んでしまって復元できなくなった、、、??????」

実は SD カードを郵送して貰う前に、取りに行ってくれた人に中身のデータだけ先に送って貰っていたのです。もしかしたらその時に、、、

「いやでも、一度しくじったら解けなくなるような問題出すかなぁ、、、」と思い、その後はファイルの復元ではなく、他の解き方を模索しましたが結局進まず、色々試しましたが解けず。やっぱりファイルの復元だったのかな、、、

これはもう分かんないわ、、、ってことでソーシャルエンジニアリング(?)の出番です。既に最終問題まで解いてその write up を書いている方が居たので、その記事を参考に解くことにしました。

ネットエージェント最終面接問題 Write-up エクストリームCTF編 – 犬アイコンのみっきー

この記事によると、どうやら最後の問題はやはり削除されたファイルを復元して解くようです。この方が解いた問題の場合、答えは山名+最高点の標高を英数字で9文字だったようなので、それを参考にしました。今回 SD カードが置いてあった高雄山という名前とその標高である428 をくっつけた takao428 でイメージファイルが複合出来ました。

これで全問突破です!やったぜ!!!!!!!

さいごに

問題を解いた感想ですが、解くのにかなり時間が掛かったので、CTF ってやっぱり普段からリハビリしてないとダメなんだなと実感しました。ですが、仲間とワイワイ言いながら問題に取り組むのはやっぱり楽しかったので、時間は掛かったけど挑戦して良かったなと思いました。ただ一つ残念だったことは僕自身が実際に山に登って SD カードの回収に行かなかったことです。他の友人も誘ってみんなでキャッキャ言いながら回収しに行きたかったな、、、

終了ステータスを見える化しよう!

やっはろー、おきなわです。

皆さんは普段プログラムやコマンドを実行した後、ちゃんと終了ステータスを確認したりしてますか?

確認しないよ〜って人はプログラムやコマンドが正常に動作した事をどうやって確かめてますか?

私は作業中は基本的に終了ステータスを確認するようにしています。そうしておいたほうが経験上、何かと便利なので。そんな終了ステータスですが、もちろん毎回

$ echo $?

と打って確認している訳ではありません。見える化をしてひと目で分かるようにしています。

というわけで今回はこういう風に見える化してるよ!という紹介をしたいと思います。ちなみに私は普段 bash を使っているので今回は bash での設定の話になります。

他のシェルを使ってる方はまぁ、頑張ってください(*^_^*)

とまぁ前置きが長くなってしまいましたが、私がやっている見える化は .bashrc に以下の一文を追加しているだけです。

PS1="[ \`if [ \$? = 0 ]; then echo \[\e[1m\e[32m\]\u\[\e[0m\]; else echo \[\e[1m\e[31m\]\u\[\e[0m\]; fi\` @ \[\e[1m\e[31m\]\h\[\e[0m\] \[\e[33m\]\[\e[1m\]\w\[\e[0m\] ]\$ "

詳しくは説明しませんが PS1 を設定することでシェルの表示を変更する事が出来ます。コレを上手く利用することで、コマンドの終了ステータスが 0 以外ならユーザ名が赤色に、0 なら緑色になるようにしています。

ちなみにこんな感じで表示されます。

表示例

これで正常終了したかそうじゃないかが一目でわかりますね。

またホスト名やカレントディレクトリの表示色も変えて目立つようにしています。よく複数のホストにまたがって作業を行うので、サーバを間違えないように目立つようにしています。

地味に便利なので一度お試しあれ☆(ゝω・)vキャピ