断片

です・ます調が記事によって違ったりするブログ

声でドローンを動かす

これはMCC Advent Calendar 2018 10日目の記事です。

adventar.org

昨日はid:nullnumaさんによる、Wacomのペンタブレットを分解してみたでした。

学園祭のコンテンツ関連のエントリを書いている人が誰もいなかったので、学園祭関連の話をします。

概要

学園祭で展示するコンテンツとして、声で操作するドローンのプログラムを書いた。 対象のドローンはParrot Rolling Spiderで重量55gのミニドローンとなっている。

www.parrot.com

本来はスマートフォンとRolling SpiderをBluetoothで繋いで操作して遊ぶおもちゃなのだが、 BLEでの制御部分の実装がNodeJSで使用可能なライブラリとして公開されているのでこれを使った。

github.com

声の取得について、当初はGoogle Cloud Speech API を使って取得していたが、ネットワーク環境が必要なことから(学園祭の部屋のネットワーク環境が最悪だった)断念し、ローカル内にJuliusサーバを構築し、ある程度高速に音声認識結果を取得できるようにした。

f:id:epcnt19:20181210025541p:plain

結果

Juliusは、Dictation KitのDNNを使ったものを動かしていたが、雑音の入った会場内では認識がかなり難しかった。

github.com

Rolling Spiderへの制御命令は、ドローン自体の物理的な動作を含めると、前回の命令から時間をあけて(〜5秒程度)送信する必要があり、 コントロールするのは中々難しかった。さらに、会場が狭く、実際に飛ばすと危険だったので、Rolling Spiderは飛ばないように机に括り付けてデモをやった。悲しい。

反省

Rolling Spiderがミニドローンということもあり飛行時間が5〜10分程度なので換えの予備バッテリーを複数買っておいた方が良かった。Rolling Spider自体、学園祭で使うというより安価で遊べそうだったので買ったわけだが、もう少し金を出して、Wi-Fi接続可能なドローンを買った方が遊びごたえがありそうだった。

コード

gist.github.com

おわりに

同じ部屋で展示を行っていたこちらが大変人気があり面白いコンテンツだったので、いつか解説エントリが出ることを願いつつ終わりにします。

DLLインジェクションの検証

これはMCC Advent Calendar10日目の記事です.
前回はUm6ra1(@v1ru5) さんによる,LinuxのUSBドライバを書いてみよう ~RTL2832uでLチカ~でした.

はじめに

本記事では,DLLインジェクションを実際に実装・検証していきます.DLLインジェクションとは,Windowsにおいて,プロセスに意図しないDLL(Dynamic Link Library)を埋め込む攻撃手法です.この手法はUser Mode Rootkit等のマルウェアでよく用いられるテクニックでもあります.

環境

以下の環境で検証を行いました.実装はC++を使用しました.

OS Windows10 Pro x86-64
Visual Studio Community 2015 Version 14.025431.01 Update 3

手順

基本方針としては,DLLパスを攻撃対象プロセスの仮想アドレス空間のメモリ領域に書き込み,リモートスレッドを生成する形でDLLコードを実行します.具体的には以下の手順で攻撃対象へDLLインジェクションを行います.

1. プロセスへのアタッチ -> OpenProcess()
HANDLE OpenProcess(
  DWORD dwDesiredAccess,  // アクセスフラグ
  BOOL bInheritHandle,    // ハンドルの継承オプション
  DWORD dwProcessId       // プロセス識別子
);

https://msdn.microsoft.com/ja-jp/library/cc429278.aspx

2. プロセスの仮想アドレス空間内のメモリ領域確保 -> VirtualAllocEx()
LPVOID VirtualAllocEx(
  HANDLE hProcess,         // 割り当てたいメモリを保持するプロセス
  LPVOID lpAddress,        // 割り当てたい開始アドレス
  DWORD dwSize,            // 割り当てたい領域のバイト単位のサイズ
  DWORD flAllocationType,  // 割り当てのタイプ
  DWORD flProtect          // アクセス保護のタイプ
);

https://msdn.microsoft.com/ja-jp/library/cc430225.aspx

3. 確保済みメモリ領域へDLLパスのコピー -> WriteProcessMemory()
BOOL WriteProcessMemory(
  HANDLE hProcess,               // プロセスのハンドル
  LPVOID lpBaseAddress,          // 書き込み開始アドレス
  LPVOID lpBuffer,               // データバッファ
  DWORD nSize,                   // 書き込みたいバイト数
  LPDWORD lpNumberOfBytesWritten // 実際に書き込まれたバイト数
);

https://msdn.microsoft.com/ja-jp/library/cc429067.aspx

4. リモートスレッドの生成(DLLコードの実行) -> CreateRemoteThread()
HANDLE CreateRemoteThread(
  HANDLE hProcess,        // 新しいスレッドを稼働させるプロセスを識別するハンドル
  LPSECURITY_ATTRIBUTES lpThreadAttributes,
                            // スレッドのセキュリティ属性へのポインタ
  DWORD dwStackSize,     // 初期のスタックサイズ (バイト数)
  LPTHREAD_START_ROUTINE lpStartAddress,
                           // スレッド関数へのポインタ
  LPVOID lpParameter,     // 新しいスレッドの引数へのポインタ
  DWORD dwCreationFlags,  // 作成フラグ
  LPDWORD lpThreadId      // 取得したスレッド識別子へのポインタ
);

https://msdn.microsoft.com/ja-jp/library/cc429075.aspx

CreateRemoteThread関数の実行において,lpStartAddressにLoadLibraryのアドレス,lpParameterにプロセスの仮想アドレス空間のメモリ領域に書き込まれたDLLパスのアドレスを指定するようにします.こうすることでリモートスレッドのエントリポイントがLoadLibraryによってロードされたDLLのDllMain関数となります.

HMODULE LoadLibrary(
  LPCTSTR lpFileName   // モジュールのファイル名
);

https://msdn.microsoft.com/ja-jp/library/cc429241.aspx

今回は検証用DLL(dllexample.dll)をメモ帳(notepad.exe)にインジェクションします.検証用DLLのDllMain関数部分は以下の通りです. gist.github.com また,インジェクション実行のプログラム(injector.cpp)は以下の通りです. gist.github.com 以上のプログラムを実行すると以下のような結果になり,メモ帳に対してDLLインジェクションが成功したことが確認できました. f:id:epcnt19:20171209221922p:plain

参考

おわりに

DLLインジェクションの攻撃手法自体は以前から知っていましたが,手を動かして検証したことがなかったのでやってみました.

次回はsasamijpさんによる,街中謎解きゲームの話です.
今年は某先輩専用のAdvent Calendarが開催されなかったことが残念でなりません.

セキュリティ・ミニキャンプ in やまなし 2017 に参加してきた

9月24日に開催されたセキュリティ・ミニキャンプ in やまなし の専門講座にチューターとして参加してきた.ミニキャンプは23日に一般講座も開催していたがその時は専門講座の会場設営などを行っていた(実際は電車を乗り過ごして一番遅く着いたのでほとんど設営は終わっていた).今回は専門講座で行われた技術的な内容について書いていく.

1. 手作りパケットでWebサーバと通信しよう

Scapyでhttp通信を行うプログラムを書いた.事前課題ではコネクション確立,コネクション確立後の通信,コネクションの切断の際のシーケンス番号(seq),応答確認番号(ack)の変化について調べる課題とNetcat,PythonのSocketに関して基本的な操作方法を覚えてくる課題が出された.講義では最終的にコネクション確立,確立後のHTTPリクエスト,コネクション切断までの一連の流れを書き,tcpdumpwiresharkを使用しながら実際にパケットの流れの観測と検証を行った.

gist.github.com

(www.example.comというのは今回記事として書く上での適当なホスト名であり講義で実際に使用したわけではない)

TCPのシーケンス番号,応答確認番号については,個人的にはこの辺りの説明がわかりやすいと思う.TCPの機能は正直あまり理解していない部分が多いのでRFCを読もうと思う.ちなみに知り合いのとあるイケメンパケリストはRFCの文書->疑似言語->プログラミング言語みたいな感じで翻訳していけばTCPプロトコルスタックが実装しやすいと言っていた気がする.

OSがRSTパケット(RST/ACK)を送信してしまう

これはカーネルTCPスタックがSYNを認知していない状態でサーバからのSYN/ACKを受けるため.TCPスタックがはじめのSYNを認知できないのはScapyがRawSocket経由でパケットの送信を行っているためである.ということでScapyで3ウェイハンドシェイクを行うためにはiptablesでRSTをDROPする必要がある.

$ sudo iptables -I OUTPUT -p tcp --tcp-flags RST RST -j DROP

2. ローカルプロキシで遊ぼう

講師の先生が自作したローカルプロキシ(Nodejs製)を使って与えられた課題を解決するようにプロキシのプログラムを改変した.課題は以下の通り.

必須課題

1. レスポンスがHTMLだった場合,"Bad"という文字列を"Good"に置換して返却する.
2. Basic認証を常に突破できるようにする.(userid/passwordは知っている状態)

1はヘッダのContent-Type行がtext/htmlだった場合にボディ中の"Bad"を"Good"に書き換える.2は通常時のBasic認証のHTTPを観察し,Authorization行を常にヘッダに追加するようにすればよい. これはわかっていてもJavaScriptがわからず沼にはまっている人が多く私もJavaScriptの経験が浅いので結構沼にはまった. JavaScriptやっていきたい.

ちなみにこれらは必須課題で任意課題(発展課題)もある.そちらの方はまだ検証中なので追々追記していく.

感想

初めてチュータを経験したが参加者とは違った側面の面白さや学びがあった.セキュリティ・キャンプは全国大会・地方大会含め参加者として何度かお世話になったので今後は新たな参加者の方をサポートしていく立場に回れればと思う.(一般 | 専門)講座参加者・講師・チュータの皆様,開催にあたり支援して下さった皆様,お疲れ様でした.

exitmap

はじめに

TorがOnionRoutingという仕組みで秘匿性を保っていることは既に皆さんご存知かと思います.そしてOnionRoutingにおいて,Torネットワークからクリアネット(非Torネットワーク)への架け橋となる出口ノード(ExitNode)の存在は非常に重要で,エンドtoエンドでの暗号化通信を行っていない場合,ExitNodeにはクライアントの通信内容が筒抜けになります.Torネットワークの各ノード(EntryNode,BridgeNode,RelayNode,ExitNode)は誰でもなることができるため,悪意をもって盗聴や改ざんを行うExitNodeの存在が非常に脅威となります.そこで,今回は悪意のあるExitNodeや,そういった疑いのあるExitNodeを探索するツールであるexitmapについて紹介します.

exitmap

exitmapはスウェーデンのカールスタード大学 PriSecグループとオーストリアのSBA Researchの共同研究によって2014年に開発されたもののようです. Pythonベースのプログラムになっており,内部的にStemを使用しているため,Tor本体をインストールしておく必要があります.

https://www.cs.kau.se/philwint/spoiled_onions/ github.com

イメージとしては,exitmap内でモジュール(例えば,ファイルのダウンロード・Webサーバへの接続等を行うモジュール)が評価対象のExitNodeを通じて実行され,その実行結果からNegative/Positiveを判定する感じです.モジュールは各自で開発することもできます.

使ってみる

環境

$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.10
DISTRIB_CODENAME=yakkety
DISTRIB_DESCRIPTION="Ubuntu 16.10"
$ uname -mr
4.8.0-52-generic x86_64

インストール

$ git clone https://github.com/NullHypothesis/exitmap
$ cd exitmap
$ pip install -r requirements.txt
$ cd ..

使い方

$ ./exitmap/bin/exitmap (モジュール名) のように指定します.デフォルトで入っているモジュールには以下のようなものがあります.

  • checktest
    • https://check.torproject.org/に接続し,Torと判定されるかチェックする.(ExitNodeがプロキシを刺しているかチェックする)
  • testfds
    • 単純なWebページの内容を取得できるかチェックする.(ExitNodeのファイルディスクリプタが正しく機能しているかチェックする)
  • dnspoison
    • 名前解決を行い,受信したAレコードと予想されるAレコードの比較を行う.(ExitNodeがDNSスプーフィングを行っているかチェックする)
  • dnssec
    • ExitNodeがDNSSECを検証するかどうかチェックする.
  • patchingCheck
    • ファイルのダウンロードを行い,改ざんをチェックする.
  • cloudflared
  • rtt
    • RTTをチェックする.

正直なところ,各モジュールの役割についてはソースコードを読んだ方が早いです.モジュールは./exitmap/src/modules/以下に配置されています. また,exitmap本体にもいくつかのオプションがあります.詳細はhelpオプションで確認できるので,ここではいくつかの重要なオプションについて紹介します.

  • --country [Country Code]
    • ExitNodeの国を指定するオプションです.日本であればJPのように指定します.
  • --first-hop [FingerPrint]
    • EntryNode(first hop)を20バイトのフィンガープリントで指定します.
  • --exit [FingerPrint]
    • ExitNodeを20バイトのフィンガープリントで指定します.
  • --build-delay [Seconds]
    • Torのサーキットを生成する際に任意の秒数間休止します.

以下の例は全ての出口ノードに対してdnspoisonモジュールを実行した例です.今回はDNSスプーフィングの疑いのあるExitNodeは発見できませんでした.

https://gist.github.com/epcnt19/84d753545ac715a569e31cc44fed883f#file-exitmap

おわりに

悪意のあるExitNodeを発見するためには,exitmapによる継続的なスキャンや,モジュールの拡張・自作を行う必要がありそうです.ただし,継続的なスキャンという点に関してはスキャンがTorネットワークへ負荷を与えているという点に注意する必要があります.

独り言

全出口ノード数は800〜900程度だそうですが,案外少なくないですか(調べてみたら,ここ数年で結構減少してるっぽい)

https://metrics.torproject.org/relayflags.html

DECAFのセットアップ

DECAFの環境を構築したので,再度構築する時のための自分用メモ.
github.com

環境

  • ホストOS Ubuntu16.10(LTS) 64bit
  • ゲストOS① Ubuntu14.04(LTS) 64bit
  • ゲストOS② Windows XP 32bit

ホストOSの上でゲストOS①を動作させ(Virtualbox),その上でゲストOS②を動作させる(DECAF(QEMU)). ホストOS上で直接DECAFを動作させなかったのは、Ubuntu16.10上でのビルドが上手く行かなかったためで,現在原因調査中.

パッケージのインストール

$ sudo apt-get update
$ sudo apt-get install qemu binutils-dev libboost-all-dev
$ sudo apt-get build-dep qemu
$ sudo apt-get -y install build-essential linux-headers-$(uname -r)
$ sudo apt-get install zlib1g-dev libssl-dev libncurses5-dev
$ sudo apt-get install libcurl4-openssl-dev libexpat1-dev libreadline-gplv2-dev
$ sudo apt-get install uuid-dev libfuse-dev bzip2 libbz2-dev git
$ sudo apt-get -y install automake1.9 autoconf libtool
$ git clone https://github.com/sycurelab/DECAF
$ cd DECAF/decaf
$ ./configure
$ make
$ cd ..

イメージの作成

  • WindowsXP(modernIE)のVMware用イメージをダウンロードした.
  • VMWare用イメージ(vmdk)をqcow2イメージに変換したものでDECAFを起動しようとしたところ,No bootable deviceと出てしまい,ブートできなかった.原因調査中.
  • qcow2イメージではなく,rawイメージに変換したものを使用したところ,問題なく起動できた.

$ unzip IE8.XP.For.Windows.VMware.zip
$ qemu-img convert -f vmdk -O raw IE8_-_WinXP-disk1.vmdk winxp.img
$ ./decaf/i386-softmmu/qemu-system-i386 -monitor stdio -drive file=./winxp.img

さいごに

今後は以下を参考にプラグイン開発をやっていく予定.

追記

https://groups.google.com/forum/#!topic/decaf-platform-discuss/iLw8E7p559w

参考

記念撮影

f:id:epcnt19:20170501140856p:plain

onionアドレスの生成

TorのHiddenServiceの識別子として用いられるonionドメインのアドレス(以下,onionアドレス)ですが,どのように生成されるのか気になったので調べました.

仕組み

知りたかったことは以下の記事にほとんど載っていました.

上記の記事によると,

  1. RSA(1024bit)の公開鍵と秘密鍵のキーペアを作成する.
  2. 公開鍵をDERエンコードする.
  3. DERエンコードされた公開鍵からSHA1ハッシュ(160bit)を生成する.
  4. 生成したハッシュ値の前半半分(80bit)を取り出し,Base32エンコードする.

という手順で生成しているようです.Base32は40bitを8文字に変換するエンコード方式で,80bitのハッシュ値から16文字の文字列にエンコードされ,これがonionアドレスとなるようです.一般的な手順でHiddenServiceの設定を行った場合,Tor側が自動でonionアドレスと秘密鍵を生成してくれます.ちなみにこれらはtorrcのHiddenServiceDir項目で指定したパスの配下にhostname,private_keyという名前で生成されます.

任意の文字列をonionアドレスにしたい

例えば,facebookcorewwwi.onion(FacebookのHiddenService)のように任意の文字列をonionアドレスに指定するための方法ですが,指定したパターンが出現するまでキーペアを生成し続ける(ブルートフォース)作業を行うことによって実現できます.そのようなツールは既にいくつも存在して,Shallotやscallionが有名なようです.

github.com github.com

試しにShallotでアドレスを生成してみたところ,1-5文字程度であればある程度高速にonionアドレスを算出できました.ちなみに,facebookcorewwwi.onionは8文字ですから一般的なマシンでのブルートフォースではまず不可能でしょう.

おわりに

TorのHiddenService,RelayNode,ExitNodeの設定方法をブログに書いていなかったのでそのうち書きます.とはいえ,HiddenService,RelayNodeに関しては以下のページに基本的な設定方法がある程度説明されているので,自分のメモ用程度にしか需要はないと思いますが.

Hidden Service - Hideki Saito Wiki Japanese
Linuxに安全にtorリレーをインストールする方法 - Qiita
Ubuntu14/CentOS6xにtor入れてrelayサーバーにする - Qiita

ブロックチェーン基盤に関するポエム

これはPDC Advent Calendar 201618日目の記事です.
前日はsiteさん(id:poketore-tech)による,HDDのファイルシステムについてでした.

はじめに
本記事では,ブロックチェーン基盤の概要について書いていきます.最近,自分の中で仮想通貨がブームになっており,有名な仮想通貨であるビットコイン(以下,BTCと書きます)の技術について調べている時間が多くありました.調べているうちにブロックチェーンやブロックチェーン基盤であるEthereum・BitcoinCoreというワードを発見したのでそれらについてのメモだと思って下さい.

ブロックチェーンとはなにか
ブロックチェーンとは「分散型台帳システム」と呼ばれていて,BTCではこの技術が大きく関係しています. ただ,BTC=ブロックチェーンという訳ではありません.BTCを構成する上で重要な技術基盤がブロックチェーンということです. 分散型台帳とは,Excelのデータシートのようなものが,P2P*1によって分散的に管理されている様子を想像してください. データシートに誰かが何かを入力すると他のノードのデータシートもネットワーク越しに更新されます. ただ,二重更新や悪意を持った更新が行われると困るので,承認のためのアルゴリズム*2が存在します.基本的にはこれだけです.

BTCとブロックチェーンの関係

BTCでは決済時に決済データ(トランザクション)をP2Pネットワークにブロードキャストします.トランザクションを受け取った各ノードは複数のトランザクションを1つのブロックという単位にまとめようとします.最も早くブロックを作成できたノードはブロックをネットワークにブロードキャストします.ブロックを受け取ったノードは電子署名によってブロックの信憑性を確かめ,正しさを確認できた場合はブロックを鎖状に連結します.この一連の働きをマイニング(採掘)といい,承認を表します.BTCにおいて,この連結されたブロック(ブロックチェーン)がデータシート(台帳)にあたるわけです.

BTCの詳細については中本哲史氏*3の論文を読んで下さい.原論文は英語ですが,有志の方により日本語化されています.
原論文
日本語版

また,書籍では「暗号技術入門 第3版 秘密の国のアリス」にBTCに関する加筆がなされているので読んでみて下さい.去年私がリクエストしたのでLiSAの図書室にあるはず.

暗号技術入門 第3版 秘密の国のアリス

暗号技術入門 第3版 秘密の国のアリス

Bitcoinの技術的側面に着目した本では,MasteringBitcoinの翻訳版である「ビットコインとブロックチェーン:暗号通貨を支える技術」が良いと聞きます.私はまだ読んでいないのでどなたか買って下さい.
ビットコインとブロックチェーン:暗号通貨を支える技術

ビットコインとブロックチェーン:暗号通貨を支える技術

BitcoinCoreを使ってみる
さて,本記事の主題はBTCについてではなく,ブロックチェーンについてでした.ブロックチェーン技術を提供する基盤(ブロックチェーン基盤)としては上記に書いた通り,BitcoinCoreやEthereumが有名です.BitcoinCoreはBTCクライアントのリファレンス実装で,Ethereumは分散アプリケーションプラットフォームです.承認方法がProof of Workであることやパプリック型ブロックチェーンであることから,(私の中の感覚では),両者は似ていると思います.今回はBitcoinCoreを使ってローカル内にテストネット*4を構築し,送金やマイニングを行います.Ethereumやスマートコントラクトについては次回以降の記事に書いていきます.

実行環境は以下の通りです.

$cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.5 LTS"
$uname -mr
Linux 3.13.0-100-generic x86_64

環境構築の詳細については割愛します.以下のリンクを参考に構築しました.
http://fintechjapan.jp/articles/tec_bitcoind001.html
まず,bitcoindデーモンを起動します.
$bitcoind -regtest -daemon
次にブロック生成によって報酬を貰い,送金用のコインを獲得します.今回は適当に500ブロック生成したことにします.
$bitcoin-cli -regtest generate 500
現在の残高を確認します.ブロックを生成した報酬として12462.5BTC獲得しています.この記事を書いている2016年12月17日時点では,1BTC=93708.32 JPYとなっていますので1167839938円,およそ11億円獲得しました.すごい.

$bitcoin-cli -regtest getbalance
12462.50000000

次にアカウントを作成し,そのアカウントに対してコインを送金を行います.今回は適当に100BTC送金します.

$bitcoin-cli -regtest getnewaddress epcnt19
n3XV7ngar6RqTT7niZCn1UbmuyVfukXCXo
$bitcoin-cli -regtest sendtoaddress n3XV7ngar6RqTT7niZCn1UbmuyVfukXCXo 100
d064cb4c3ed9bcfd73b5922224a4ada9f0afd6ca4822787e7910969980e35813

この時点ではまだ送金処理は完了していません.なぜなら,マイニングによる承認がなされていないからです.マイニングを行い処理を確定させます.

$bitcoin-cli -regtest generate 1
[
  "2bc00687f82dfd2ca2edb12e3b04b3d41d833901f923807415d1a314978d70e6"
]

これでブロックが生成されたので,「アカウントepcnt19に100BTC送金する」というトランザクションが承認されたはずです.

$bitcoin-cli -regtest getbalance epcnt19
100.0000000

これで私(epcnt19)は100BTC,およそ900万円手に入れました.

おわりに
ブロックチェーンについて書くはずが,いつのまにかBTCについての話になってしまいました.ブロックチェーンの発祥はBTCですが,現在は色々なところでブロックチェーンの適応実験が行われているそうです.スマートコントラクトの話は次回以降の記事に書くことにします.これらの話が入ってくると,ブロックチェーンの本質が見えてくるはずです.ちなみに偉そうに記事を書いていますが,私はBTCのアカウントを持っていません.ただ,BTCの自動売買プログラムが今非常に面白いと感じていて,近いうちに始めたいと思っています.

明後日はCanninet_onlineさん(id:Canninet)による,「戦車日記 序章」です.

参考

ビットコイン 日本円(BTC JPY) コンバータ-Investing.com
NTT DATA BLOCKCHAIN INNOVATION|NTTデータ
bitcoin-cliを使ったBitcoinAPI入門 - Qiita
Bitcoinプログラミングの入り口 – blockchain

*1:Peer to Peerの略.主な種類として,ノード探索時に管理サーバに問い合わせるハイブリッドP2P方式と,探索自体も分散的に行うピュアP2P方式がある.

*2:Proof of Work(PoW)やPBFTが有名

*3:ビットコインの発明者.名前は日本人だが偽名であるとの見方が強い.実際の正体は不明.

*4:これをRegtestモードという