子供が Capture The Flags の講座に参加したけど、簡単な説明後いきなりミニCTF大会だったので、さっぱり分からないだろうから、少し解き方の説明。
ドメインの秘密
ドメイン名とは、IPアドレスは覚えられないのでコンピュータにつけた名前。そのドメイン名とIPアドレスのデータベースがDNS。通常は、コンピュータ名からIPアドレスを調べる時に使う。unix や windows で DNS 情報を調べるコマンドが、nslookup。
最新の unix 環境では、nslookup ではなく、dig しか入っていないかもしれない。
その場合は、
$ sudo apt-get install dnsutils
((( 基本的使い方 ))) $ nslookup [オプション] ドメイン名 [DNSサーバ] ((( 問い合わせ例 ))) $ nslookup tsaitoh.net 8.8.8.8 # GoogleのDNSサーバに問い合わせる例(正引き) $ nslookup 64.33.3.150 8.8.8.8 # (逆引き=IPアドレスからドメイン名を調べる) $ nslookup -query=A tsaitoh.net # IPv4アドレスを調べる $ nslookup -query=AAAA www.yahoo.com # IPv6アドレスを調べる $ nslookup -query=MX tsaitoh.net 8.8.8.8 # メールサーバ情報を調べる $ nslookup -query=TXT tsaitoh.net 8.8.8.8 # SPF1というメールサーバの信頼性情報
我が家では、自宅専用のDNSサーバが動いている特殊な事例。インターネットのグローバルアドレス空間でどう見えているかを知りたい場合は、DNSサーバに 8.8.8.8 を使う。Google が、記憶しやすいIPアドレスで誰もが使っていい高速のDNSサーバを提供してくれている。
Webページを見つけろ
サーバとの通信では、IPアドレスで相手のコンピュータを見つけるけど、1台のコンピュータ内で複数のネットワークプログラムが動いていた時、どのプログラムと通信するのか区別する必要がある。そのための情報がポート番号。IPアドレスを電話番号に例えるなら、ポート番号は内線電話番号みたいなもの。
このポート番号は、プログラムによって番号は◯◯を使うべき…という値が決まっている(よく知られたポート番号)。Webサーバ(HTTP)は80番、Webサーバ暗号版(HTTPS)は443番、メールサーバ(SMTP)は25番….。
ポート番号で接続するサービスが決まるけど、学内だけで外に見せたくないWebサーバなどがある場合は、ファイアウォールで特定のポート番号を流通させないようにする場合もある。そういう場合には、通常のポート番号以外を使って通信することがある。
Webサーバに接続する時には、80番を使いたくない場合には、http://コンピュータ名:ポート番号/ と URL にポート番号付きで指定することもできる。
ポートスキャン
このポート番号が解らない時は、ポートスキャンというツールがある。ポート1番で通信してみる、ダメなら2番…という繰り返しをしてくれるツール。一番有名なツールが、nmap。ウィルスなどが仕掛けられて、外部からのネットワーク接続を受ける状態(バックドアが仕掛けられた状態)になったのを見つけるのが本来の使い方。
nmap は通常インストールされない(こんな危ないツール普通はシロートに使わせるものではない)。使いたい場合は、
$ sudo apt-get install nmap
((( 基本的使い方 ))) $ nmap [オプション] 接続先 $ sudo nmap tsaitoh.net # サーバ tsaitoh.net を調べる $ sudo nmap -A tsaitoh.net # ソフトの種類も調べてくれる。
ポート番号が解って、そのサーバソフトに接続してみる場合、telnet がよく使われる。
本来は、ネットワークの先のコンピュータを操作するためのソフト(リモート接続23番ポート)だけど、通信を暗号化しないため、セキュリティ的には危険なので、リモート接続用途で使うことは少ない。
Windowsでは、telnetは初期状態でインストールされない。unix で telnet を使いたい場合は、
$ sudo apt-get install telnet
((( 基本的使い方 ))) $ telnet コンピュータ名 [ポート番号] $ telnet tsaitoh.net 80 # 80番ポート(HTTP)に接続 GET / # トップページのHTMLが帰ってくる。 $ telnet tsaitoh.net 25 # 25番ポート(SMTP)に接続 QUIT # 接続を切る
隠れたデータ
ウィルスなどにコンピュータに感染させる場合、ファイル名などを偽っってあったりするので、ファイルの種別を調べたり、その中の命令を分析する必要がある。その場合によく用いる基本コマンド。
((( 基本的使い方 ))) $ file ファイル名 # 指定したファイルが何か簡単に調べてくれる。 $ file a.out # a.out の中身を調べる $ strings ファイル名 # ファイルの中身の文字として表示できるものを表示する。 $ strings a.out # a.out の中の文字情報を抽出 $ nm ファイル名 # オブジェクトファイルのシンボル(関数名や変数名)を表示 $ nm a.out # stripされたa.outでは抽出できない。
逆アセンブル
実行プログラムがどのような処理をしているのか内容を見たい場合は、逆アセンブル(機械語をアセンブリ言語に変換)する。ただし、一般的な実行プログラムでは、関数番地や変数名番地の情報が消されているので、OS の仕組みの知識が必要。
簡単に解析をするのであれば、objdump などを使うことが多い。ここでは、gdb を紹介する。
gdb(GNU Debugger)は、Cコンパイラ(gcc = GNU C Compiler)のためのデバッガ。linux だとプログラムが異常終了すると、coredump(実行時のメモリ内容を出力する機能) するので、この情報でプログラムの異常処理を探す時に使う。
デバッガは通常はインストールされないよな。
$ sudo apt-get install gdb
((( 基本的使い方 ))) a.out は、何らかのC言語のソースで事前に作っておくこと。 | // helloworld.c | #include <stdio.h> | int main() { | printf( "Hello World¥n" ) ; | return 0 ; | } $ gcc helloworld.c $ gdb a.out (gdb) break main # main にブレークポイントを設置 (gdb) run # プログラムを実行 (gdb) step 10 # 10行分処理を実行 (gdb) disas main # main 以降を逆アセンブル (gdb) quit ((( 異常処理とその場所を見つける ))) 異常終了するプログラムの例 | // segv.c | #include <stdio.h> | int main() { | *((int*)NULL) = 123 ; # 0番地にデータを書き込む | return 0 ; | } $ gcc -g segv.c # コンパイル時に名前情報を実行プログラムに埋め込む。 $ ulimit -c unlimited # coredump 機能を有効にする $ ./a.out Segmentation fault (コアダンプ) $ gdb a.out core # 異常終了した行が表示される