[-]=======================================================================[-] Wizard Bible vol.37 (2007,11,2) [-]=======================================================================[-] x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ---- 第0章:目次 --- x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ○第1章: Black Hat Japan 2007 レポート 金床 著 ○第2章: Black Hat Japan 2007 レポート eagle0wl 著 ○第3章: 64ビット環境でのリバースエンジニアリング Kenji Aiko 著 ○第4章: Windowsシステムプログラミング Part3 〜SYSENTERとSYSEXIT〜 Kenji Aiko 著 ○第5章: 基礎暗号学講座・第12回 〜素数生成アルゴリズム〜 IPUSIRON 著 ○第6章: お知らせ ○第7章: 著者プロフィール x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第1章: Black Hat Japan 2007 レポート --- 著者:金床 x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■0x01.) はじめに  2007年の春に、秋葉原にてリバースエンジニアリング祭りが行われた(詳細は eagle0wl氏の記事 http://wizardbible.org/33/33.txt を参照)。その際に知人 数名で呑み会を行ったのだが、この席でモトニシ氏(仮名w)から「今年のBHJでは金 床さんスピーチとかどうっすか」という一言をいただいた。もしかしてスピーカ ーになればダータで参加可能か?とまず脳裏をよぎった漏れの小市民っぷりはさ ておき、この一言をきっかけにCFP(Call For Paper。発表者の募集)に応募する ことにしたのである。  今年は幸いネタ的に非常にホットな「DNS Rebinding」が持ち玉として存在して いたため、客観的に見ても(たぶんw)筆者がBHJで話すことに技術レベル的な問 題はないだろうと思われた。 ■0x02.) 資料作成  8月あたりにCFPに応募し、無事受理された。そしてBHJ本番の一ヶ月前である9 /21までに資料を作成することになった。このように締め切りがだいぶ前倒しにな っているのは当日CD-ROMや冊子の形で参加者に資料が配付されるからである。  筆者はパワーポイントを、というかMSオフィスを持っていなかったため、まず 近くのヤマダデンキに行き、パワーポイントを購入してきた。単体で25k円ほどと いう想像を絶する値段だったが、締め切りが迫っていたのでやむを得ず購入した。 これでどうやらギャラの半分が吹き飛んだようである。  パワポに触るのは実に7年ぶりだったのでスライドの作り方がよくわからず、操 作方法を覚えるのに2時間くらい使ってしまった。スライドマスターとかそのへん の概念を把握するのに苦労したのである。  日本語版の資料を締め切りぴったりに提出した後、3日ほど猶予をもらい海外の 人向けの英語バージョンを作成した。英語での言い回しが正しいかどうか、Goog leでひたすら検索する。たまに1つもヒットしない、つまり致命的に間違った英語 を書いていてorzとなる。  BHJ後に評判をきくとそこそこまともに訳せていたようで安心した。これらの資 料は近いうちにBHサイト上で入手可能になると思われる。 ■0x03.) Sunがパッチをリリース  資料完成から発表までに一ヶ月ほど時間が空くわけだが、これが見事に裏目に 出た。Sunが発表の2週間ほど前にJREのパッチを(というか最新版を)リリースし、 DNS Rebinding対策を行ったのだ。今回は特にJavaアプレットとDNS Rebindingに ついてよく調べ、しかもデモも作った後だったので、筆者的にはorzな状態であっ た。  実は筆者はこのようなDNS Rebindingのパッチは永遠にリリースされないだろう と考えていた。というのも今回Sunが採用したDNS Rebinding対策は副作用がきつ く、開発者側から不満の声があがりそうなものだからだ。その内容は「IPアドレ スを所有している人間が、明示的にあるホスト名を管理している」ことを証明す るために、DNSサーバーに逆引き設定を強要するものである。例えば218.45.25.5 でwww.jumperz.netを走らせている場合、今までは次のようなコードでJavaアプレ ットはサーバーへと接続することができた。 ----- Socket socket = new Socket( "www.jumperz.net", 110 ); -----  しかし最新版のJRE(1.6系列では1.6.0_03以降、その他の系列は調べてくだち い)では次のホスト名が218.45.25.5へと解決されない場合、セキュリティ制限に 引っかかり接続することができないのである。 ----- www.jumperz.net.auth.5.25.45.218.in-addr.arpa -----  ちなみにこれはスタンフォード大がリリースした例の論文中に記述されているアイデアを元に しているようだ。DNSの問題はDNSで解決する、という実に納得できる対策であり、 これによって確かにJavaアプレットにおいてDNS Rebindingへの対策が完了した。しか しアプレットを提供したいまじめな開発者があるIPアドレスについての逆引き設定を行 えない場合(例えば共有レンタルサーバーでのホスティングなどで権限がない場合)も多く存在 するだろうと思われるため、この対策方法はなかなか強い副作用をともなっている と言える。筆者個人としてはこの対策はとりあえず歓迎するが、そもそもJavaアプ レットやFLASHにSocketがあること自体おかしいと思っている。  Sunはセキュリティに対して非常に真面目だと思う。Adobeは正反対の性質を持ってい るような気がするので、おそらくFLASHへのこの種のパッチはリリースされないのではな いだろうか。 ■0x04.) BHJ開始  さて10月25日になり、新宿京王プラザホテルにてBHJ(ブリーフィングのほう) が開催された。今年はスピーカーであることもあり、午前9時に到着するよう家を 出発した。筆者はSOHO形態で働くプログラマーなので、これは本当に久しぶりの ラッシュアワーであった。湘南新宿ラインの横浜から大崎までは満足に両足を地 面に着けないほどの混雑であり、新宿についた時点で既にBHJのためにチャージし ていた気力をすべて使い果たした気がした。  会場が去年とまったく同じであることもあり、駅からホテルまでは迷わずまっ すぐにたどり着くことができた。受付にて、やや気合いが入り気味で硬い表情を したKanaさん(BHJのスタッフで、今回も七転八倒…じゃなくて八面六臂の大活躍 をしていた)に挨拶する。その後翻訳担当の方と打ち合わせをするために控え室 で待っていると、続々と他のスピーカーが部屋に入ってきた。全員外国人である。 ちなみに今年は日本語を話すスピーカーは(基調講演を除くと)筆者のみだ。 ■0x05.) ネイサン、ロブ、ビリーの3人組  翻訳のひとたちの会場入りがやや遅れたため、控えの部屋には外国人7人くらい + 筆者という実に気まずい空間が形成された。ちなみにこの時点では英語を話す のが半年以上ぶりなので、脳みそが英語モードにチェンジしていない。なんとな く自己紹介が開始されるが、皆早口なので筆者はその2割程度しか内容を把握する ことができない。「漏れはKanatokoです。ここ、つまり日本に住んでます」など と言うと、やや太め(失敬)の人物に「ぽまい、jumperzのやつか」ときかれる。 どうやらDNS Rebindingのデモのおかげで筆者のことを知ってくれていたようだ。 彼の名はネイサンで、「URIの使用と悪用」のスピーカーである。彼は実に陽気な 人物であると同時に非常に礼儀正しく、2日目に行われた彼らのセッションの冒頭 では「今回日本で話すことができるのは非常に光栄です」などととても丁寧な挨 拶をしていたのが印象的であった。  控え室での自己紹介後にはネイサンと(ネイサンと共にスピーチする)ロブの 2人に囲まれ、いきなりDNS Rebindingネタについて質問を浴びせられることにな った。耳も頭も英語モードにスイッチしていないので内容を掴むのに苦労したが、 どうやら「FLASHでのDNS Rebindingが(筆者のデモのように)すんなりいかない」 「閉じたポートへアクセスさせる方法を使っているのか?」などの内容だったよ うだ。そこで「筆者のサイトには3つデモがあり、ひとつはJavaScript、ひとつは FLASH、ひとつはLiveConnectだ。そして閉じたポートへアクセスさせるのはJava Scriptのやつだけだ」「FLASHはDNS Pinningしないので、閉じたポートへアクセ スさせる必要はない」と説明する。向こうもこれらについては大体分かっていた らしく、「やっぱりそうか…ヘンだな」と言っていた。どうやらGoogleのツール のひとつ、Picasaに対するDNS Rebindingでそのような事象が発生したらしい。筆 者もこれから時間をつくって調べてみるつもりである。  一方、ロブは長身の青年である。彼の英語は筆者にとって実にききとりにくく 苦労した。彼はアメリカ人にしては物静かなタイプである。そしていろいろな場 所ですれ違うたびににこやかに挨拶してくれるナイスガイだった。彼らのセッシ ョン中ではPicasaに対するDNS Rebindingの部分での説明を担当していた。  彼らのセッションの内容は3人でまとめられたもので、ネイサンとロブの他にビ リー(HoffmanではなくRiosのほう)も関わっていたのだが、この時点では会場に は来ていなかったようだ。時系列としては前後してしまうが、ここからはこの3人 とのエピソードについて記しておく。  実はビリーはBHJの1週間ほど前に筆者にメールをくれており、それは「DNS Re bindingでおまえのことを知ってるぜ。今回BHJで会えそうだな。ビールを呑ませ るのが楽しみだ!」という内容だった。  ビリーとは筆者のセッションの後に無事対面することができた。彼はベリサイ ンからマイクロソフトに転職した直後らしい。まさにラテン系といった感じの陽 気な人物で、話す英語も非常にくだけた感じだった(すぐに「hey, man!」とか言 うタイプであるw)。  ビリーはJavaアプレットのキャッシュを利用した(筆者がデモを公開している のとは違う)DNS Rebindingの攻撃ベクターを発見しており、それは今年のHITBで 発表されている(http://conference.hitb.org/hitbsecconf2007kl/?page_id=148)。 Sunが2週間前にリリースした最新版のJREではこの脆弱性も塞がれており、筆者と 一緒に「面白い脆弱性だったけど、なおっちまったな、ガハハハ」的な笑いで盛 り上がった。ちなみに彼はキュートな奥様を同伴して来日していた。  彼らのセッション「URIの使用と悪用」は少し前に大きな話題になったURIハン ドラ経由の攻撃を詳しく説明するものである。http://xs-sniper.com/blog/2007 /07/24/remote-command-execution-in-firefox-2005/を訪れたことがある人も多 いかと思うが、これはまさにビリーのサイトである。URIハンドラが登録されてい る場合、ウェブブラウザ経由でさまざまなアプリケーションが起動される可能性 があるが、これらの引数などにバッファオーバーフローやコマンドインジェクシ ョンなどの可能性がある、という内容だった。またPicasaは独自のURIをレジスト リに登録しており、これとDNS Rebindingを組み合わせることでユーザの写真が盗 まれてしまうというExploitが示された。GoogleデスクトップやPicasaは内部でウ ェブサーバーを起動しているためにDNS Rebinding攻撃に弱いらしい。この辺りは 実に興味深いので時間を作って調べてみるつもりだ。  セッションの後にその内容についていくつか質問した。まずpicasa://というU RIハンドラは通常どのように利用されるのか?ということだ。どうやらGoogleの ウェブページ内から「アルバムをダウンロード」などのリンクをクリックする際 にそのリンク先が「picasa://…」というURIになっていて、起動されたPicasaが 引数で渡されたURLにアクセスしにいく、というようなもののようだ。  また、資料の中にたびたび登場する「pwn」という単語の意味がわからなかった ために「stupidな質問だけど」と前置きしてきいてみた。するとビリーは大笑い しながら「ガハハまいったな、これはスラングの一つで、ハックしたぜ!みたい な、ownをもじったものだよ。ポニー(pony・子馬ちゃん)ともかけてる」と教え てくれた。ネイサンとロブに別の質問をした後に「pwnの意味がわからなかったか らビリーにきいた」といったら2人とも爆笑していた。  さらに彼らのプレゼン資料の表紙にあった「P\/\/N1ch1\/\/4」も意味がわ からなかったので、「最初の部分がpwnで、1はi、4はAなのはわかるんだけど、こ れ全体はどういう意味?」ときいたら「pwnと日本の挨拶をかけたんだよ。ポウンニチ ワ」と言われて4人で大爆笑である。「よし、Kanatokoにポウンニチワの使用権利を譲る ぜ。これから仕事で挨拶するときはポウンニチワを使っていいぜ!」、「トゥルルル… (電話の音)…ガチャ。ポウンニチワ、お世話になっております。こちらは○×社です。 みたいにビジネスライクな口調で使うんだ」とか好き放題言われて盛り上がった。  彼らのセッションではURIハンドラ経由でメッセンジャーをハックし、ターゲッ トのガールフレンドへと勝手に「I think we should break up... sorry but it s you not me(俺たち別れたほうがいいと思うんだ…。ゴメン。でも君のせいだ よ)」というメッセージを送ってカップルを別れさせてしまうという攻撃が紹介 されていた。実は筆者は2日目の朝の電車の中で冊子に印刷されたこの部分を読ん で吹き出してしまったので(特にsorryから後半のとどめを刺す感じがウケた)そ れを伝えると、笑いが言葉を超えて伝わったことがうれしかったらしく、喜んで いた。  3人はプレゼンテーションに対して非常に真面目に取り組んでおり、ホテルの部 屋で朝早くから入念に練習をしていたようだ。翻訳が入ることに気をつかってお り、スピーチの速度やニュアンスが伝わるかどうか(例えば、「このようなソフ トウェアがURLハンドラを登録する必要が本当にあるのでしょうか?」というよう な、スピーカーが自身に問いかけるようなニュアンスが、会場の人に質問してい るように翻訳されたりしないかどうか)が気になると言っていた。筆者は翻訳内 容はきいていなかったので質問型のニュアンスについてはわからないが、速度は 速すぎず遅すぎずちょうどよかった、と伝えておいた。  WBでおなじみケンジ氏(今回はBHJに参加していた)が筆者との会話の中で、彼ら のセッションについてなかなかよかったと言っていたので、それを打ち上げの席 でネイサンに伝えると、「それをきけて本当にうれしいよ」と言っていた。実に 真面目なのである。  ところで彼らと音楽の話になったときである。 「USのThird Eye Blindというバンドがすごく好きなんだ」と筆者。 「おっ、知ってるよ」 「彼らの曲でjumperというのがあって、それが特に好きで…」 「なるほど、あれが由来なのか!」  と、ドメイン取得してからはや9年(?)、初めてjumperz.netの由来を理解し てもらうことに成功したのがうれしかった。  彼らと筆者はネタの方向性が一致していたため会話が非常に盛り上がった。筆 者がBHJの2日間で最も長い時間会話をした外国人は間違いなくこの3人である。最 終日の夜別れるときには柄にもなくちょっとセンチになってしまったのだった。 ■0x07.) 記者会見  最初の枠でDHCPでのpassive fingerprintingのセッションを見た後に、スピー カーやスポンサー、そしてプレスなどの関係者のみでの記者会見が別室で行われ た。このときテレビ局らしい人がいたため「フーン、どっか取材来てるんだ…」 程度に思っていると、なんとNHKとのことである。筆者のとなりに座っていたオー ストリア2人組(筆者と同じ時間帯に隣の部屋でセッションを行っていた)に話し かける。「あれはUKでいったらBBCみたいなテレビ局なんだぜ」「うわ、すごいな。 BHJが放送されるのかい?」「いや、よくわからない」  プレスの中にはTIP氏(どう見ても偽プレスです。本当にありがとうございまし た。たぶんグミ指でどこかの記者のアカウントをハカーしてきたのでしょう)やハッ カージャパンのO氏がいるためなんだか恥ずかしく気まずい感じだ。取材陣に知り 合いがいるとかえって恥ずかしいのである。O氏は筆者に「ただ一人の日本人とし てスピーチする気分はどうですか」のようなことをきくかどうか迷ったが、筆者 がイヤがりそうかなと思ってやめてくれたらしい。実際、もしそんな質問をされ たら非常にイヤだったので助かったw。今度コーヒーでもごちそうさせてくだちい。  記者会見はBHJスタッフのケンタロウ氏による神レベルの翻訳により、言葉の壁 を感じさせることなく無事終了した。 ■0x08.) 筆者のセッション  1日目の昼過ぎに筆者のセッションがあった。筆者は多くの人を前に60分以上も 話をするのが初めてだったので発表の数日前から非常に緊張していた。特に発表 前1時間ほどのこの日の昼食では緊張がピークを迎えており、挙動不審で通報され そうな勢いだったと思われる。  しかし幸い発表を開始してしまってからは内容に没頭することができ、緊張せ ずにすんだ。何人かの知人からは後に「ちょっと緊張してましたよね」と突っ込 まれたが、実は筆者的には「全然おk」なレベルだったのである。  本当はデモを交えようかとも思ったのだが、いろいろな事情(PCの無線LANがう まくつながらず、しかもアダプターを忘れていたため電池切れを恐れてトラブル シューティングに時間を割けなかった)でこれは断念した。まぁ初めてのまとも なプレゼンということもあり、あまり欲張らずにいくことにしたのだ。また、デ モはどれも筆者のサイト上で誰でも実行できる状態になっていることや、ユーザ が自身の環境で実行した方がデモとしてのインパクトが大きいということもこれ を行わなかった理由のひとつである。実際スピーチ終了後に翻訳をしてくれたク リスさんが「今デモやってみたんですが、動きましたよ。これやばいじゃないで すか!」と言ってくれたので筆者的にはニンマリであった。  セッションの最中、舞台の上からHPのビリー(Hoffmanのほう)が来てくれてい たのが見えたので内心「ちょwwwビリーktkrwww」とか盛り上がっていたのであっ た。 ■0x09.) NHK  やはりテレビというのは影響力が大きいようで、この夜NHKにて筆者のセッショ ンを交えたBHJの映像が放送されると、多くの人から反応があった。筆者的には「 なんか、成り行きにまかせていたら自分が出ていた」という以上でも以下でもな いのだが、まぁネタ的には面白かったのでアレなのである(アレってどれだよ)。  実は筆者はどちらかというとテレビには出たくないほうである。NHKの人が「金 床さんのセッションの映像を放送させていただきたいのですが」といってきたと きに「イヤだベンベン」と言おうかとも思ったのだが、今回のBHJでは(人種的な 意味での)日本人スピーカーが筆者だけだったので、筆者が断ることがBHJ運営側 に迷惑をかけると悪いと思いOKした面もあったりするのである。このように筆者 は協調性が高いことで知られており、ケンジ氏からも「金床さんは協調性に富み、 通勤電車などの中にいると周囲にとけ込んでしまい、発見が困難だ」と評価され ているほどだ。  何人かに「本名でしたね」とつっこまれたのだが、これも特に大きな理由はな く、成り行きである。筆者の名刺には本名が書かれており(「金床」は小さく書 いてある)、NHKの記者と交換した際、「本名は佐藤さんなんですね。放送で本名 を出してしまってはまずいですか?」と言われたので持ち前の協調性を発揮し、 「いや、まずくはないです」と答えたのである(筆者の本名はウェブアプリケー ションセキュリティ本のあとがきにも出てるし)。というかそもそもこの会話を しているときはセッション直後で質問用ブースへ移動しなければならなかったり して非常にゴタゴタしている状況だったのだ。「どっちかというと金床で出して くだちい。本もこの名前で出版していますし、いわゆるペンネームですから」と 言っておけばよかったかとちょっと悔やんだのである。  まぁそのような筆者のくだらない事情はさておき、BHJが国際会議として公共放 送に(しかも非常にポジティブな感触で)取り上げられたことは喜ばしいことで ある。スタッフの皆さんや来日したスピーカーのみんなも喜んでいたのがよかっ た。 ■0x10.) データハウスブースとサイン会  今回のBHJではデータハウスにブースを出してもらった。会場がデータハウスに 近いこともあり、まどさんとIPUロムに筆者の「ウェブアプリケーションセキュリ ティ」をはじめ「クラッキングバイブル」や「ハッカーの教科書」、「アセンブ リ言語の教科書」など7種類のセキュリティ関連書籍を売るブースをセッティング してもらったのである。まどさんは2004年にお台場エリアで発生したテロで手に 入れた某看板をちゃっかり使うなど、相変わらずの凄腕テロリストぶりを発揮し ていた。  まどさんが骨折していたこともあり、IPUロムがデータハウススタッフとしてヘ ルプしてくれた。IPUロムには2日目に、朝っぱらから「いかにスパムメールを効 率よくさばくか」というテーマでさんざん討論をふっかけられ非常に消耗させら れた。彼曰く集合知が生かされたgmailフィルターが最強とのことである。まどさ んと漏れは監視パラノイアでgmailが受け付けないのだが、IPUロムが折れないの で最終的には殴り合いになりそうになった。  …なんてことはもちろんなく、マターリとしたブースで居心地がよかった。筆 者のセッション後には「ウェブアプリケーションセキュリティ」本を買ってくれ た人や持ってきてくれた人にサインを行うといういわゆる「サイン会」なるもの が開かれた。他人がサイン会をやっていても何とも思わないのだが、「自分のサ イン会」というのはキモくて寒気がすることをここに記しておくw。  何人かが会場にて本を買ってくれました。ありがとうございました。また急な 話にもかかわらずブースを出してくれたまどさんとIPUロム、データハウス社長に 感謝します。 ■0x11.) ファジングさっくす  自分のセッションが終わったのでホッと胸をなでおろし、OpenRCE.orgの人が行 っているファジングのセッションをみることにした。彼らが作成したpythonベー スぽいファザーの紹介といった内容で、いろいろ工夫している様子が伝わってき た。ファジングは基本的にはバッファオーバーフローなどのようなプロセスが不 正終了してしまう系の脆弱性を発見するのに向いている方法のようで、筆者が専 門としているウェブアプリケーションセキュリティの分野ではそれほど便利では なさそうに感じた。また、プログラマーならばファジングツールの独自文法を覚 えるより、自分でコードを書いてしまう方が色々応用が効いて便利なのではない かとも感じた。 ■0x12.) ポール  ポールは初日最後の枠で「.NETフレームワークでのマルチプラットフォーム型 マルウェア」のセッションを行った人物だ。彼はなんと19歳のドイツ人である。 若い。しかもおもしろいことに、英語の他に日本語もそこそこ話すことができる。  この時間はポールの反対側がビリー(Hoffman)のセッションだったのでどちら を見るか非常に迷ったのだが、.NETのマルウェアがなぜマルチプラットフォーム なのか?などいろいろ疑問があったのでポールのセッションを見てみることにし た。  どうやら.NETのランタイム環境はLinux用のものやFreeBSD用のものが存在する らしく、単一の.NETアプリケーションがWindowsはもちろんLinuxやFreeBSDでも動 作するらしい。これにはおどろいた。「マルチプラットフォーム」という概念と、 マルウェアが感染する経路についてどのような関係を持たせているのかにも興味 があったのだが、こちらは単純にメールを送り、その添付ファイルをクリックし てしまったら感染する、というものだった。ただしメールを送る先のアドレスは マルチプラットフォームのアプリケーションであるThunderbird(メールクライア ント)のアドレス帳から取り出すということで、なるほどマルチプラットフォー ムであり感心した。デモも見事に動作し、WinXPからLinux、FreeBSD、Vista、そ してまたXPへとウイルスが感染していく様子を見ることができた。ちなみにこの ウイルスは秋の風が強い日に作ったので「秋風(Akikaze)」と名付けたらしいw ■0x13.) ビリーホフマン  ポールのセッションが少し早めに終わったので、ビリーのセッションをのぞく ことができた。彼は翻訳者泣かせのマシンガントークスタイルを炸裂させる。「 Slow Down」の表示を受けると仕方がないというように水を飲む。実に情熱的で魅 せられるセッションだった。彼は会場内にいる人(主に外国人)とうまくコミュ ニケーションを取りながらセッションを進めていた。ときおり会場内が笑いに包 まれるのだが、筆者は英語力不足からこの笑いを捕捉することができずさみしか った。  ビリーもDNS Rebindingのデモを通じて筆者の存在を知ってくれていたようだ。 その後話をしたときには「Defconや本家のBlack Hatでのスピーチにもチャレンジ してみなよ!」と言ってくれた。ビリーは2日目終了後のAV2007会場にも登場し、 tkskさんをはじめとする日本人とのコミュニケーションを楽しんでいたようだ。 酒好きで陽気なナイスガイであった。 ■0x14.) レセプション  初日の夜にはレセプション(立食パーティ)があった。1年目のBHJのレセプシ ョンは(ry)な感じであったが4年目はなかなか豪華だった。多くの日本人の方と 名刺交換したり話をしたりしたのだが、業界内の事情などをここに書くと後でツッ コミが入るので詳しくは書かないでおく。「○×っていうウェブアプリスキャナー、 いまいちなんでしょ?」「ちょwwこのレセプションのスポンサーが売って(ry」な どのような会話が交わされていたのであった。ちなみに筆者はアルコールに対し てアレルギーなので一切の酒類が呑めない(3年くらい前は呑めたし日本酒ラブだ った)。そのためいい感じに酔っぱらった方がハイテンションで話しかけてくれ てもテンションを合わせることができず申し訳ないと思った。自分の意志で脳内 麻薬を分泌しテンションを上げる修行が必要のようだ。  今回はWBでおなじみのケンジ氏やe0氏などが参加していた。今までのBHJの中で も最も多く知人が参加しており、またデータハウスのブースなどもあったので普 通にオフ会として楽しかった。BHJは個人で参加するにはやや高額であるため、某 NA社のように(つか某の意味ないマジレス)会社がたくさんの社員を参加させてあげ るのはとてもいいことだと思った。きっとそれぞれの個人のモチベーション向上に繋が り、最終的には会社にとってもプラスになるだろう。 ■0x15.) 2日目  BHJ2日目は台風が来ていた。横着せずに(タクらずに)駅から歩いたのだが、途 中すごい雨と風でペインだった。ジェフいわくBHJには必ず台風か地震がセットで ついてくるらしい。ちなみに1日目の通勤ラッシュに懲りたので2日目は10:20くら いに到着するよう移動した。この時間は多少電車の中も余裕があり、プレゼン資 料が印刷された冊子を読みながら新宿へと移動した。  基調講演は最初の10分ほどきいていたのだがいまいちピンと来なかったので( 後で面白かったと言っている人もいっぱいいた)データハウスのブースでマターリし ていた。また筆者が最近作ったネタのサーバー監視ツールであるAmberjack@JUMPERZ.NETを まどさんに見せびらかし、さらに受付周辺にいたBHJスタッフの外国人の集団にも 見せびらかした。黒バックに緑の字のいかにもハカーテイストのこのツールは馬 鹿ウケで、あるスタッフは「これ絶対ダウンロードする」とメモ帳に「jumperz. net」とメモっていたw。ちなみにデモは http://www.jumperz.net/amberjack/in dex.html にある。CPUを食いまくるので速いマシンでアクセスする必要がある。 Safari・IE・FF・Operaの順に軽い。というかOperaだと重すぎてまともに動作し ない。 ■0x16.) ドミニク  このとき受付にいたドミニクとはその後もいろいろな場所で話をした。彼はや や早口ながら発音が聞き取りやすく、さらに会話の内容がいかにもギークであるた めまともに意思疎通が取れた。ちなみにAV2007にもやってきた坊主頭の彼がドミ ニクである。  彼は2年前にBHJでインタプリタ型言語のセキュリティについてスピーチを行っ たこともある人物だ。長い間C言語を使っていたが、今はRubyにぞっこんらしい。 彼とはコマンドラインツール vs GUIツール(OllyDbgやgdbなどについて)、Vim などのエディタの話、JavaScriptの話やRubyの静的分析による脆弱性発見は可能 かどうか、などについて話をした。RoRでウェブアプリケーションを作ることも多 いようだ。Rubyの話をしているときには「ここで発見された脆弱性はMatzが直し て…」などと会話中にRuby作者のまつもとさんの名前も登場した。  AV2007の席上にて、SOCで働いているくせに自宅でもハニーポットを運用してい る某T君を「彼はセキュリティのことを24時間考えているクレイジーなんだ」と紹 介すると、後で「あの監視ツール(Amberjack@JUMPERZ.NET)をjust for funのた めに作ったキミもJavaScriptクレイジーだとみんなで話していたんだぜ」とほめ 言葉(w)をいただいた。ドミニクはウェブアプリケーションの開発を行い、かつ セキュリティもやる、という筆者と似たスタイルの持ち主であったため、話がば っちりかみ合ったので楽しかった。彼はブラウザの話になると「Operaはひどいよ」 と何度となく口にしていたw ■0x17.) ポゥンニチワ  「URIの使用と悪用」のセッションをきこうと会場に行き席に着くと、ネイサン がわざわざ筆者のところに握手しに来てくれた。筆者はこのとき一人で席につい ており、まわりの席は空いていた。ネイサンはおそらく筆者に向かって「Thank you for coming along」と言っていたのだが、筆者は一瞬「along」を「alone」 かと思ってしまい、「ひとりできてくれてありがとう」って、何でだろう?とか 脳内で大ボケをかましていた。すぐに「ああ、alongだ」と分かったのであるが、 後から一人アホな自分にウケていた。 ■0x18.) ジェフ  今回いろいろな場所でジェフを見ていて、彼のすごい才能に気がついてしまっ た。彼は「日本人の話すちょっとダメな英語」を聞き取る能力がずばぬけている のだ。多くの日本人の話す英語はとくにアクセントがはっきりしないという点で 特徴があるのだが、ジェフだけがやたらとこれをきちんと聞き取れていたのが面 白かった。AV2007の席などでも日本人の誰かがしゃべった英語をジェフがまた英 語に訳して他の外国人に伝えるという場面を何度か目撃した。さすが日本ヲタで ある。 ■0x19.) 英語について  ここで英語についてメモをしておく。外国人2人以上 + 筆者、という状況だと どうしても会話の速度が速くなりがちで、ひどいときは何の話をしているのかさ っぱりわからないこともあった。逆に話がしやすいのは1対1のときで、このよう な場合向こうが話す英語もなぜか自然とゆっくりとしたものになり、かろうじて 戦いになるという感じであった。  BHJのような場所に来ている外国人はみなフレンドリーでナイスガイなので、こ ちらのダメ英語につきあわせてしまうことができる大きなチャンスだ。こちらが どんなひどい発音と文法でも「なんだこのファッキンジャパニーズは」というよ うな反応が返ってくることはまずない。一生懸命耳を傾けてくれ、こちらが言わ んとすることをくみ取ってくれるので何度も心の中で「ホント申し訳ない」と思 ったw。また、筆者は聞き取りはまぁまぁだが話すと致命的に文法が間違ってい ることがよく分かったので、これから中学校レベルの文法をやり直す予定である。 とりあえず過去の話は過去形でとかそういうレベルwww。  こちらが話をしたときに「うーん、これ通じてないな」と思ったのが「develo p(あるいはdeveloping)」である。「ボクはウェブアプリケーションを作ってる んだよ」という文脈でよく使ったのだが、いまいち通じていない。帰宅後に調べ てみると、案の定アクセントの位置が違っていたorz。筆者はloにアクセントを付 けてしまっていたのだが、正解はveのところのようだ。また「relatively」も通 じてないなぁと感じていた。筆者はこれを「リレイティブリィ」、しかも「レイ」 にアクセントを付けていたのだが、正解は「リラティブリィ」でアクセントは頭 の「リ」であったようだorz。  ちなみにオーストリアやドイツ方面の人の英語は全然ききとれなかった。英語 上達への道は長く険しいのであった…。 ■0x20.) 外国人が見た日本  BHJで話をした多くの外国人に日本の印象をきいてみた。多くの人はポジティブ な印象をあげてくれ、その内容は以下のようなものだった。 ・街がきれいである ・街が大きい ・近代化されている ・レストランなどでのサービスがきちんとしている ・地下鉄がカクイイ ・コーヒーが濃い ・電車の中でみんな静かにしている ・料理がマイウー ・みんな黒いスーツと白いシャツ(リーマンのこと)である ・人々が礼儀正しい、またフレンドリーである ・道がわかりにくい(ストリートネームなどの表示がない) ・レストランの女の子のユニフォームがカワイイ(ちょwww ・富士山の山頂でケータイが圏内だった ■0x21.) AV2007  BHJ終了後には関係者の打ち上げとAV2007を行き来することになった。AV2007は tessyさん・kawaさんをはじめとするチームチドリ主催の呑み会で、30人近い人が 来ていた。今年はライトニングトークが行えるようになっていたようで、途中抜 けるのが非常に心残りだった。  関係者の打ち上げが終わった後にはジェフ、Kanaさん、ドミニク、ビリーホフ マン、そしてUSAに入国できなかったことでニュースになったHalvar Flake氏がA V2007に参加した。日本語で行われたライトニングトークはスクリーンの小ささも あって内容が充分には伝わっていなかったようだが、何人かは積極的にコミュニ ケーションを取っていたようでよかった。筆者はドミニクがアツく語るRubyやJa vaScriptの話、そしてヒッピーの話(なんでだwww)をきいていた。 ■0x22.) まとめ  そんなわけで今年はスピーカーをやらせてもらったこともあり数多くの貴重な 体験をすることができた。DNS Rebindingのデモを公開していたために多くの人に 事前に認知してもらっていたことが印象的だった。英語はできなくてもデモやツ ールのように動くものは伝わるので、これからも積極的にゴソゴソしようとあらた めて決心した。  最後に、BHJ当日や準備でお世話になったみなさん、そして参加されたみなさん、 ありがとうございました。ひとりひとり名前をあげることはできませんが、2日間 存分に楽しめたのはみなさんのおかげです。なんか旅行にいっていたような不思 議な感覚ですね…。  みなさん、オツですた!ヽ(´ー`)ノ x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第2章: Black Hat Japan 2007 レポート --- 著者:eagle0wl x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■0x01.) はじめに  新宿・京王プラザホテルで開催された「Black Hat Japan 2007」(以下BHJと略 す)の Briefings に行ってきました。 Black Hat Japan 2007 Briefings http://www.blackhat.com/html/bh-japan-07/bh-jp-07-jp-index.html  Wizard Bibleの読者であればBlack Hat(以下BHと略す)の説明は不要だと思い ますが、レポートの体裁を成すためにあえて説明すると、世界各地で開催されて いる、情報セキュリティをテーマとしたカンファレンスです。日本での開催は20 04年からで、今回は4年目となります。主催者であるJeff Moss氏はハッカーの祭 典として名高いDEFCONの主催者でもありますが、オフ会的な雰囲気がある(←実 際に行ったことが無いので受け売り)DEFCONとは異なり、BHはプロフェッショナ ル層を意識しており、厳選された第一線の技術者をスピーカーとして迎えていま す。技術公演と称した製品アピールを廃したベンダー中立性を掲げていることも 特徴のひとつで、そういったこともあってか、参加費用は若干高めに設定されて います。  BHJの参加費用は8万円程度のため、個人で行くには躊躇する金額ですが(それ でも各国で最も安価ですが)、今回会社の経費にすることができました。BHJ初参 加の私ですが、Wizard Bible読者の皆様にその様子を伝えたいと思い、僭越なが らレポートを書いてみた次第です。なお、本稿には私の理解が至らないことによ る間違いがあるかもしれませんが、その辺は大目に見ていただけるとありがたい です(汗)。 ■0x02.) 今回の傾向  昨年度のBHJは、金床さん曰く(Wizard Bible vol.29参照)、「とにかくウェ ブアプリケーション」だったとのことですが、今回はマルウェア、(リバースコ ードエンジニアリングというよりは)コード分析方面が出てきた感があります。 ■0x03.) 1日目:会場の雰囲気  会場は新宿でしたが、近場に住んでいることもあって非常に行きやすかったで す。昨年のBHJでは、金床さんが遅く到着したがために資料が無くなってしまった ことを知ってるので、朝早くに到着。受付で事前に発行されたBHロゴ入りe-tick etを見せて、分厚い冊子と同時通訳受信用のヘッドセット・名札を受け取る。私 の名札には、本名・会社名に加え「eagle0wl」の文字が。ハンドル入り。最初は ネタになるだろうぐらいしか思っていなかったのですが、実際にできあがった名 札を見て「やってしまった感あり」であることに気付く。しかしながら、初対面 でも知ってくれている人が多く交流しやすかったので、結果としては功を奏した のかもしれません(汗)。  早く到着したこともあり、セッションが始まるまでしばし会場近辺をうろつい ていると、データハウスがブースを出していたことに気づきました。メインは当 然、今回唯一の日本人スピーカーとなる金床さん執筆の「ウェブアプリケーショ ンセキュリティ」。Wizard Bible増刊号も発行されていましたが、やはり金床特 集号(金床さんが書いた記事の再録)でした。金床さんの発表の後にはサイン会 もありましたが、「クラッキングバイブル」などデータハウス刊のハードカバー 書籍も並んでいました。  近辺をうろついた後もまだ時間があったので、配布された資料に目を通すこと にしました。BHJでは2部屋で同時にセッションが行われるため、どちらを見るか 予め吟味する必要があります。「こっちを聴きたい!」という強い意志があれば いいのですが、迷った場合、私は「(資料をみれば概要はつかめるので)資料以 上の内容の発表が行われそうか」「ありがちなテーマは避ける」を考えて選択し てみました。しかし、1日目の3コマ目はとても悩みました…(後述)。  日本人以外のスピーカー(つまり今回だと金床さん以外)は英語で発表を行う ため、受付でもらったヘッドセットを使えば同時通訳を聴くことができます。こ のヘッドセットはホテルの備品らしく、片耳だけにかけるタイプのものだったの ですが(いわゆる耳栓型ではない)、少々大きく私の耳には収まりが悪かったの で、持参していたiPodのイヤホンを流用しました。座席によっては同時通訳の音 量を大きくしないと、スピーカーからの元声に負ける場合があるので気を付けた ほうがいいかもしれません。また、同時通訳は行われますが、資料は(日本人ス ピーカーが作成したものを除き)すべて英語で記載されています。 ■0x04.) 1日目:セッション  最初のセッションは、Kenneth Geers 氏の「101号室からの手紙」を聴こうと思 ったのですが、資料に一通り目を通したところスライドを熟読すれば問題なく概 観は掴めるだろうと予想して、David LaPorte・Eric Kollmann両氏の「DHCPによ るパッシブなOSフィンガープリンティング」を聴講することにしました。パッシ ブ(受動的)にOSを特定するツールとしてp.0.fが知られていますが、DHCPでもで きるぜーという話で、DHCP Optionsの並びに着目するなどしてOSを割り出す方法 を紹介。fingerbank.orgに様々なOSのFingerprintが登録されていることを確認で きます。 FingerBank http://www.fingerbank.org/  なお、前者のセッションについての記事がZDnetで公開されているので、そちら もご覧頂けたらと思います。 セキュリティ専門家が語る「インターネットの統制状況」 http://japan.zdnet.com/security/story/0,3800079245,20359670,00.htm  昼食をはさんでの次のセッションは、BHJ2007唯一の日本人スピーカーでありW B代表(?)でもある金床さんの「DNS PinningとソケットAPIについて」を聴講し ました。金床さんの名札には「Kanatoko 金床」としか書かれておらず、本名らし き記載は見当たりませんでした。Wizard Bible vol.29のBHJ2006レポで「次回は、 「金床」の名札での参加にチャレンジしようと思う」と仰っていましたが、見事 に成功したようでお慶び申し上げます(笑)。  金床さんは、英語の同時通訳の速度を気にしながらゆっくりと喋っていたため、 理解も非常に容易でした。内容については、これまでのWizard Bibleなどで触れ られている内容を無駄なくまとめたという形なので、技術的な詳細については金 床先生の力作『ウェブアプリケーションセキュリティ』か、Wizard Bibleのバッ クナンバーをチェックすることをお勧めします。また、金床先生より後日談が掲 載されることを期待していますので、詳細はそちらに譲ることにします。  終了後は金床さんによるサイン会が開かれ、Wizard Bible増刊号(金床特集号 ?)もフリーペーパーとして配布されていました。ところで、今回NHKが取材に来 ていたのですが、その日のうちに放送されたとの事です。YouTubeでそのニュース 映像を確認することができます。 Black Hat Japan 2007 NHK news coverage http://www.youtube.com/watch?v=CQesc5vNBEo  BHJがテレビメディアで紹介されたのは今回が初めてのようです。情報セキュリ ティの重要性が一般に取り上げられたことを喜ばしく思います。  さて、3つめのセッションですが、一方が Pedram Amini & Aaron Portnoy氏の 「ファジングは最悪だ!(あなたの思うようにファジングするには)」、もう一 方がHalvar Flake氏の「マルウェアの分類とアンパッキングの自動化」なのです が、どちらを選ぶかとても悩みました。両スピーカー共にリバースエンジニアリ ング業界では非常に高名で、Pedram Amini氏はリバースエンジニアリングのポー タルサイトとも言えるOpenRCE.orgの発起人で、Aaron Portnoy氏もOpenRCE.orgに 記事を投稿しています。一方のHalvar Flake氏はドイツに構えるSABRE Security 社の創設者であり、シマンテックの主席研究員であるPeter Szor氏による、コン ピュータウイルスの歴史・技術・防御策の集大成『The art Of Computer Virus Research And Defense』の表紙にも推薦文を寄せており、マルウェア分析のエキ スパートとして知られています。また、SABRE Securityの研究員であるEro Carr era氏もBHJ2007のTrainingコース「Windowsのマルウェア検出と分析、リバースエ ンジニアリング」を担当しており、OpenRCE.orgの常連投稿者でもあります。  こういった、リバースエンジニアリングという観点で同ジャンルに属する発表 を、同時間帯にスケジュールしたことは正直理解できませんでしたが、両方とも 聴講したかった私としては、次年度以降の改善を強く望む次第です。マジで。結 局今回は、ちょうどマルウェアについて知りたかったこともあり、後者の「マル ウェアの分類〜」を選択することにしました。  Halver Flake氏の発表は非常に高度な内容でした(ウイルスについてはそれほ ど詳しくないので、追いかけ切れていません)。まず80〜90年代のウイルスシー ンを振り返り、当時のウイルス作成者は主に知的好奇心の赴くままに作成した者 と東西冷戦で暗躍したウイルサーの2通りで、そのほとんどはアセンブリ言語で書 かれ、コードの再利用も行われなかったとのこと。さらに当時は、高級言語でウ イルスを書くと笑われたものだが、今のウイルスの開発手法は通常のソフトウェ ア開発に似ており、すでに成熟しているとまで。  アンチウイルスのシグネチャ(マッチパターン)については、80年代において は簡単な文字列マッチング程度しか行われていなかったようで、さらにシグネチ ャ自体のバイト長が短かかったこともあり、わずか1バイトの変更で検出が回避さ れてしまうという、非常に脆い構造だったそうです。アンチウイルス側がこの変 化に対応するには、亜種への対抗、つまり1シグネチャで亜種も含めて検出できて、 ウイルス作者がゼロから書き直さざるを得ない状態にできればベストということ でしょう。そこで様々な検出方法を紹介していたのですが、プログラムのフロー ・構造に着目した"Structural Classfication"が非常に興味深かったです。  商用逆アセンブラ「IDA Pro」のExtensionの形で提供されるSABRE Security社 のBinDiffを用いていました。BinDiffはプログラムの流れ(フロー)をグラフ化 することができるのですが、プログラムの流れ(≒グラフの形状)を比較するこ とで、プログラムが改変された亜種にも対応することができるという具合です。 ポリモフィック・メタモフィックなウイルスだと、ジャンクコードを挿入するな どの手法でバイナリが大幅に変化するものですが、プログラムの基本構造自体は 変わらないため、問題なく検出できるということらしいです。  このBinDiffのデモが行われていましたが、ジャンクコードが入っているためバ イナリとしては異なるものの、グラフの形状はまったく変わっていないという例 が示されました。これは今回のBHJ2007の中で一番興味を引くものでした。 SABRE BinDiff http://www.sabre-security.com/products/bindiff.html  ただ、この方法にも問題はあって、"emulating packers"いわゆる独自の中間言 語と、その中間言語を解釈できる独自の仮想CPUを実装したウイルスに対しては効 果が無いとのこと(注:パッカーだと VMProtectあたりが実装しています)。こ れはBinDiffが「独自の中間言語」を解釈できないからでしょう。  ここからは私の解釈ですが、「独自の中間言語と独自の仮想CPU」を実装するこ とはかなりの労力が必要だと思います。したがって、主流と成るにはまだ時間が かかるものと思われますが、今後同様のウイルスが立て続けに出てくるかもしれ ません。その時は、また新しい検出方法が編み出されるのではないかと思ってい ます。ここまで来ると、一個人が片手間で作るものを超えており、ウイルスシー ンもここまで来たかという恐怖すら覚えます。このセッションすべてを理解でき たわけではありませんが(今も復習中)、たくさんの物が得られたと思っていま す。 OpenRCE.org http://www.openrce.org/ SABRE Security http://www.sabre-security.com/ The art Of Computer Virus Research And Defense http://www.amazon.co.jp/dp/0321304543 Fuzzing http://www.fuzzing.org/  1日目最後のセッションは、Billy Hoffman氏の「小さなハイブリッドウェブワ ームにできること」が、資料を見る限り過激そうな内容だったのですが、もの珍 しさでPaul Sebastian Ziegler氏の「.NETフレームワークでのマルチプラットフ ォーム型マルウェア「を聞くことにしました。氏は弱冠19歳ながらBHJ2007でスピ ーカーを勤めた上、レセプションで判明したのですが日本語も堪能でした。彼は 同時通訳を気にしながらゆっくりと喋っていたため、分かりやすい発表でした。  この発表では、コンセプト実証(PoC:Proof of Concept)の例として、.NETフ レームワークで実行するワームを作成し、Windows XP -> Linux -> FreeBSD -> Windows VistaそしてWindows XPに戻ってくるというデモンストレーションを実践 して見せました。もちろん、.NETワームは万能とは言いがたく、安定性やリバー スエンジニアリングが容易であったり、現時点におて主流ではありませんが、今 後主流になるかもしれないということで、理解しておかねばと思った次第。 ■0x05.) 2日目:レセプション  すべてのセッションが終了した後はレセプション(要するに懇親会)があった のですが、私はベタに名刺を交換したりしていましたが、Wizard Bible常連投稿 者であるKenji Aiko氏を発見しました。彼はどうやら、外国人スピーカーが一人 でいる所を見計らって身振り手振りでコミュニケーションを取りたかったらしい のですが、タイミングを見計らってPaul Sebastian氏に話しかけたところ、日本 語で返され拍子抜けしていたのが笑えました。私も少しだけ話の輪に入って聞い ていたのですが、日本語が堪能で驚きました。私が気にしていたOpenRCE.orgの中 の人は見かけることができませんでした。残念。  レセプションが終了後は明日のことも考え、すぐ帰宅しました。しかし突如現 れたチーターマンのせいで、ファミゲーオタの私はテンションが上がってしまい、 全然寝ることができなかったのはここだけの話。 伝説のクソゲー『チーターマン2』が15年ぶりに復活! ニコニコ動画でブーム http://news.livedoor.com/article/detail/3359112/ 伝説のクソゲー チーターマン2 http://www.nicovideo.jp/watch/sm1289422 ■0x06.) 2日目:基調講演  2日目に主催のJeff Moss氏の開会挨拶に続いて、山口英教授による基調講演が ありました。あらゆる局面においてITに依存する社会や、最近起こった大規模な システム障害と品質の問題などを絡めながら概観していましたが、全編を通して 堅いノリではなく実に興味深かったです。  セキュリティに関してはとかくマネジメントでと言われがちだが、そうではな くまず技術力での解決を目指すべきだ、それで解決できないならマネジメントや 精度でフォローしていくべきだという趣旨の発言が印象的でした。一方で、Soci o-Engineeringという概念を取り上げ、社会から切り離された研究や、社会実装で きない提案は受け入れられないとも。これは、技術自体が単体として優れていて も、社会に還元できるものでなければ意味がないということだと思いますが、技 術一辺倒で視野狭窄に陥るのではなく、そこから一歩引いて、どう社会に役立て ることができるのかを考えることがこれからの私たちに求められている、そう感 じました。 「社会状況を意識した技術開発を望む」--Black Hat Japan 基調講演 http://japan.zdnet.com/security/story/0,3800079245,20359767,00.htm  基調講演後に昼食を済ませて受付近辺をうろついていたら、BHJがスピーカー用 シャツを放出していたので、つい勢いで購入してしまいました。なかなかレアな 品物だと思います(?)。 ■0x07.) 2日目:セッション  2日目1つ目のセッションは、Nathan McFeters・Billy Rios・Rob Carter両氏の 「URIの使用と悪用」も気になってはいたのですが、やはり物珍しさを優先させる 形でNguyen Anh Quynh氏の「バーチャルマシンのハイジャックの可能性」を聴講 することにしました。詳細は復習し切れていないのであまり書きませんが、ブレ ークポイントの挿入やブレーク後のハンドリングなど、ある程度のデバッグ技術 の理解が求められる内容だったと思います。デモも多く行われ、”1バイトのイン ジェクション”でキー入力をロギングし、”3バイトのインジェクション”でキー 入力のロギングとコンソール出力を再現するというインパクトのあるものでした。 最後にこのハイジャックを逆手にとり、セキュリティポリシーに反するファイル 操作に対してアラートを上げるデモも行われました。  それぞれの節目で、「(挿入したバイトを言い当てた人には)ビールを奢りま す」という問いかけが行われましたが、流石に誰も答えられるわけでもなく。BH Jの中でもDEFCON色のある発表だったと思います。  最後のセッションは、Jacob West氏の「スタティック分析によるセキュアプロ グラミング」を聞くことにしました。  完成したプログラムに対してどうこうという話ではなく、より品質の良いコー ドを書くための方法論的な話でしたが、安全なシステムにするには、開発の初期 段階から考慮するべきであるとして、静的なプログラム分析ツールの導入につい て話していました。しかしながら、分析ツールも万能ではなく"No Silver Bulle t"(銀の弾などない)ようです。近年のツールは、単にセキュリティ的に問題の ある箇所を検出するだけではなく、修正の優先順を示すなど様々な機能もあるよ うですが、それでも完全に検出できるわけではないとも。また、実際に導入する ときも一気に行うのではなく、ツールの理解を深めながら段階的に行うべきとこ とだそうです。 「我々は過去の教訓を生かしきれていない」,米Fortify Softwareセキュリティ 担当者 http://itpro.nikkeibp.co.jp/article/NEWS/20071026/285638/ Secure Programming with Static Analysis http://www.amazon.co.jp/dp/0321424778/ Fortify Software Inc. http://www.fortifysoftware.com/ ■0x08.) 最後に  BHJ2007は、とても楽しめました。非常に高度かつ密度の高いものばかりだった ため、当然のことながら私に全てのトピックを理解できるはずもなく、配布資料 を片手にチマチマと復習しているところです。  しかし、BHJのようなエネルギーを必要とするイベントのレポートはそう簡単に 書けるものではないですね…。いつものノリでいけるだろうと思って書き始めた ものの、書きながら何度も後悔しました(苦笑)。まあ、所詮この程度というこ とで。本レポートで少しでもBHJ2007の雰囲気が伝われば幸いです。 x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第3章: 64ビット環境でのリバースエンジニアリング --- 著者:Kenji Aiko x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■0x01.) はじめに  64ビット環境では、32ビット環境に比べ、マシン語に多少の違いがある。その 違いによって、リバースエンジニアリング行為に、どの程度の影響が出るのかを 調べた。今回は、その過程をテキストにまとめたものである。  なお、OSはWindows XP(x64)、デバッガはWinDbg(x64)、コンパイラはVisu al Stdio 2005を使用した。 ■0x02.) 関数呼び出し  とりあえず、どの程度の違いがあるのか、マシン語を読んでみる。 ----- prog1.cpp(http://07c00.com/text/x64rev1/prog1.cpp) #include int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { MessageBox(GetActiveWindow(), L"This is test program.", L"Message", MB_OK); return 0; } -----  これを64ビット用にコンパイルして、WinDbgに読み込ませる。  そして、ブレイクポイントを設置して実行すると、WinMainで止まる。 ----- WinDbg(http://07c00.com/text/x64rev1/prog1.exe) 0:000> bp WinMain 0:000> bl 0 e 00000000`00401000 0001 (0001) 0:**** prog1!WinMain 0:000> g ModLoad: 000007ff`7d1f0000 000007ff`7d229000 C:\WINDOWS\system32\IMM32.DLL ModLoad: 000007ff`7fed0000 000007ff`7ffe4000 C:\WINDOWS\system32\ADVAPI32.dll ModLoad: 000007ff`7fd20000 000007ff`7fec9000 C:\WINDOWS\system32\RPCRT4.dll ModLoad: 000007ff`67b60000 000007ff`67b6d000 C:\WINDOWS\system32\LPK.DLL ModLoad: 000007ff`78be0000 000007ff`78c6a000 C:\WINDOWS\system32\USP10.dll Breakpoint 0 hit prog1!WinMain: 00000000`00401000 4883ec28 sub rsp,28h -----  ここで、アセンブルコードを出力する。 ----- WinDbg 00000000`00401000 4883ec28 sub rsp,28h 00000000`00401004 ff1536110000 call qword ptr [_imp_GetActiveWindow] 00000000`0040100a 4c8d05af110000 lea r8,[prog1!`string'] 00000000`00401011 488d15b8110000 lea rdx,[prog1!`string'] 00000000`00401018 488bc8 mov rcx,rax 00000000`0040101b 4533c9 xor r9d,r9d 00000000`0040101e ff1524110000 call qword ptr [_imp_MessageBoxW] 00000000`00401024 33c0 xor eax,eax 00000000`00401026 4883c428 add rsp,28h 00000000`0040102a c3 ret -----  よく分からないレジスタが多く使われているが、あまり気にしなくてよい。多 分、すぐ慣れる。64ビット環境では、レジスタのサイズが64ビットになって、レ ジスタの種類が約2倍になった以外はあまり変わらないので、とりあえず、64ビッ ト版の汎用レジスタrax、rcx、rdx、rbx、rsp、rbp、rsi、rdi辺りと、r8〜r15辺 りを覚えておけばよいだろう。  まぁレジスタの話は置いておいて、関数呼び出しを見てみると、スタックが使 われず、変わりにレジスタが使われている。  MessageBoxWの引数と照らし合わせてみると、どのレジスタが何番目の引数か分 かるだろう。まず、GetActiveWindowの戻り値はraxに格納されているはずだから、 00401018より、rcxが第一引数と分かる。また、MessageBoxWの最後の引数MB_OKは、 数値にすると0なので、0が入れられているレジスタを探すと、どうやらr9が該当 する(r9dはr9の下位32ビット)。ここまでくると、あとはrdxが第二引数、r8が 第三引数であると推測できる。つまり、次のようになる。 ----- MessageBoxW(ASM版) MessageBox(rcx, edx, r8, r9); -----  引数に関しては4つまでレジスタ、以後スタックという流れだが、call命令のリ ターン値については、スタックに積まれる。 ----- WinDbg 0:000> bp WinMain 0:000> g ModLoad: 000007ff`7d1f0000 000007ff`7d229000 C:\WINDOWS\system32\IMM32.DLL ModLoad: 000007ff`7fed0000 000007ff`7ffe4000 C:\WINDOWS\system32\ADVAPI32.dll ModLoad: 000007ff`7fd20000 000007ff`7fec9000 C:\WINDOWS\system32\RPCRT4.dll ModLoad: 000007ff`67b60000 000007ff`67b6d000 C:\WINDOWS\system32\LPK.DLL ModLoad: 000007ff`78be0000 000007ff`78c6a000 C:\WINDOWS\system32\USP10.dll Breakpoint 0 hit prog1!WinMain: 00000000`00401000 4883ec28 sub rsp,28h 0:000> t prog1!WinMain+0x4: 00000000`00401004 ff1536110000 call qword ptr [prog1!_imp_GetActiveWindow] 0:000> t USER32!GetActiveWindow: 00000000`78bfe020 b901000000 mov ecx,1 0:000> r rax=0000000000000000 rbx=000000000015312e rcx=0000000000400000 rdx=0000000000000000 rsi=0000000000000000 rdi=0000000000000000 rip=0000000078bfe020 rsp=000000000012fe98 rbp=0000000000000000 r8=000000000015312e r9=000000000000000a r10=0000000050000161 r11=0000000000000000 r12=0000000000000000 r13=0000000000000000 r14=0000000000000000 r15=0000000000000000 iopl=0 nv up ei pl nz na po nc cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206 USER32!GetActiveWindow: 00000000`78bfe020 b901000000 mov ecx,1 0:000> -----  GetActiveWindow関数呼び出し元は00401004だから、次の命令は0040100aとなる。 そして、rspは000000000012fe98となっているため、このアドレス(スタック)の 値を見ると、次のようになっている。 ----- WinDbg 00000000`0012fe98 0a 10 40 00 00 00 00 00 -----  スタックには、次の命令のアドレス(戻り場所)が記録されている。つまり、 関数呼び出しの際に引数をpushすることはないが、call命令による戻り場所は、 スタックに積まれることが分かった。  続いて、引数がどこまでレジスタに頼るのかを調べる。スタック(メモリ)を 使わないといっても、レジスタには限界がある。それを調べるため、次のプログ ラムを書いた。 ----- prog2.cpp(http://07c00.com/text/x64rev1/prog2.cpp) #include int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { CreateProcessAsUser(0,0,0,0,0,0,0,0,0,0,0); return 0; } -----  実行するわけではなく、マシン語が見たいだけなので、引数は適当だ。このコ ードをコンパイルしてマシン語にすると次のようになる。 ----- WinDbg(http://07c00.com/text/x64rev1/prog2.exe) 00000000`00401000 4883ec68 sub rsp,68h 00000000`00401004 33c0 xor eax,eax 00000000`00401006 4533c9 xor r9d,r9d 00000000`00401009 4533c0 xor r8d,r8d 00000000`0040100c 4889442450 mov qword ptr [rsp+50h],rax 00000000`00401011 4889442448 mov qword ptr [rsp+48h],rax 00000000`00401016 4889442440 mov qword ptr [rsp+40h],rax 00000000`0040101b 4889442438 mov qword ptr [rsp+38h],rax 00000000`00401020 89442430 mov dword ptr [rsp+30h],eax 00000000`00401024 89442428 mov dword ptr [rsp+28h],eax 00000000`00401028 33d2 xor edx,edx 00000000`0040102a 33c9 xor ecx,ecx 00000000`0040102c 4889442420 mov qword ptr [rsp+20h],rax 00000000`00401031 ff15c90f0000 call qword ptr [_imp_CreateProcessAsUserW] 00000000`00401037 33c0 xor eax,eax 00000000`00401039 4883c468 add rsp,68h 00000000`0040103d c3 ret -----  どうやら、レジスタで渡すのは引数4つまでで、それ以上はスタックを利用する ようだ。しかし、pushやpopは使わず、ローカル変数のような形で、使用するメモ リ領域を確保している。 ■0x03.) マイクロソフトx64呼出規約  マイクロソフト呼出規約によると、「rcx、rdx、r8、r9は整数型とポインタ型 の引数に使用し、xmm0、xmm1、xmm2、xmm3は浮動小数点型引数に用いられる。そ して、レジスタが足りなくなれば、スタックが使われ、戻り値はraxに格納される」 ということだ。  とにかく、プロトコルと同じように、レジスタを使うにも決まり事があるのだ ろう。詳しく知りたい方は「Calling Convention for x64 64-Bit Environments (※1)」を参照のこと。最後に、ブログにてこれを教えてくれたiya氏サンクス!。 (※1)Calling Convention for x64 64-Bit Environments http://msdn2.microsoft.com/en-us/library/ms794533.aspx ■0x04.) デバッガで解析  64ビット環境用のcrackmeを作成する。今回は、64ビットでもリバースエンジニ アリングが可能かどうかを調べるのが目的なので、もっとも容易なcrackmeを作成 する。 ----- crackme1.cpp(http://07c00.com/text/x64rev1/crackme1.cpp) #include int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { SYSTEMTIME st; GetSystemTime(&st); if(st.wYear != 1192 || st.wMonth != 5 || st.wDay != 15){ TCHAR szErrorStr[2048]; wsprintf(szErrorStr, L"このプログラムはUTC(世界標準時刻)で" L"「1192年05月15日」にしか起動できません\r\n" L"現在の日付は「%04d年%02d月%02d日」です\r\n", st.wYear, st.wMonth, st.wDay); MessageBox(GetActiveWindow(), szErrorStr, L"Message", MB_OK); return 0; } MessageBox(GetActiveWindow(), L"OK!", L"Message", MB_OK); return 0; } ----- 実行画面:http://07c00.com/text/x64rev1/a.png  見ての通り、時間指定の制限だ。GetSystemTime関数の戻り値で評価しているの で、この部分を変更してやればOK。というわけで、さっそくデバッガで開く。 ----- WinDbg(http://07c00.com/text/x64rev1/crackme1.exe) ntdll!DbgBreakPoint: 00000000`78ed3320 cc int 3 0:000> bp WinMain 0:000> bl 0 e 00000000`00401000 0001 (0001) 0:**** crackme1!WinMain 0:000> g ModLoad: 000007ff`7d1f0000 000007ff`7d229000 C:\WINDOWS\system32\IMM32.DLL ModLoad: 000007ff`7fed0000 000007ff`7ffe4000 C:\WINDOWS\system32\ADVAPI32.dll ModLoad: 000007ff`7fd20000 000007ff`7fec9000 C:\WINDOWS\system32\RPCRT4.dll ModLoad: 000007ff`67b60000 000007ff`67b6d000 C:\WINDOWS\system32\LPK.DLL ModLoad: 000007ff`78be0000 000007ff`78c6a000 C:\WINDOWS\system32\USP10.dll Breakpoint 0 hit crackme1!WinMain: 00000000`00401000 b858100000 mov eax,1058h 0:000> -----  WinMainでブレイクポイントを設置して実行する。当然WinMainで停止する。こ こで逆アセンブルする。 ----- WinDbg crackme1!WinMain: 00000000`00401000 b858100000 mov eax,1058h 00000000`00401005 e8060a0000 call crackme1!__chkstk 00000000`0040100a 482be0 sub rsp,rax 00000000`0040100d 488b05ec1f0000 mov rax,qword ptr [crackme1!__security_cookie] 00000000`00401014 4833c4 xor rax,rsp 00000000`00401017 4889842440100000 mov qword ptr [rsp+1040h],rax 00000000`0040101f 488d4c2430 lea rcx,[rsp+30h] 00000000`00401024 ff15d60f0000 call qword ptr [crackme1!_imp_GetSystemTime] 00000000`0040102a 0fb7542430 movzx edx,word ptr [rsp+30h] 00000000`0040102f 440fb75c2436 movzx r11d,word ptr [rsp+36h] 00000000`00401035 6681faa804 cmp dx,4A8h 00000000`0040103a 0fb74c2432 movzx ecx,word ptr [rsp+32h] 00000000`0040103f 751c jne crackme1!WinMain+0x5d 00000000`00401041 6683f905 cmp cx,5 00000000`00401045 7516 jne crackme1!WinMain+0x5d 00000000`00401047 664183fb0f cmp r11w,0Fh 00000000`0040104c 750f jne crackme1!WinMain+0x5d 00000000`0040104e ff15f4100000 call qword ptr [crackme1!_imp_GetActiveWindow] 00000000`00401054 488d151d120000 lea rdx,[crackme1!`string'] 00000000`0040105b eb2d jmp crackme1!WinMain+0x8a 00000000`0040105d 440fb7c9 movzx r9d,cx 00000000`00401061 440fb7c2 movzx r8d,dx 00000000`00401065 410fb7c3 movzx eax,r11w 00000000`00401069 488d1560110000 lea rdx,[crackme1!`string'] 00000000`00401070 488d4c2440 lea rcx,[rsp+40h] 00000000`00401075 89442420 mov dword ptr [rsp+20h],eax 00000000`00401079 ff15d9100000 call qword ptr [crackme1!_imp_wsprintfW] 00000000`0040107f ff15c3100000 call qword ptr [crackme1!_imp_GetActiveWindow] 00000000`00401085 488d542440 lea rdx,[rsp+40h] 00000000`0040108a 4c8d05d7110000 lea r8,[crackme1!`string'] 00000000`00401091 4533c9 xor r9d,r9d 00000000`00401094 488bc8 mov rcx,rax 00000000`00401097 ff15b3100000 call qword ptr [crackme1!_imp_MessageBoxW] 00000000`0040109d 33c0 xor eax,eax 00000000`0040109f 488b8c2440100000 mov rcx,qword ptr [rsp+1040h] 00000000`004010a7 4833cc xor rcx,rsp 00000000`004010aa e821000000 call crackme1!__security_check_cookie 00000000`004010af 4881c458100000 add rsp,1058h 00000000`004010b6 c3 ret -----  普段OllyDbgを使っているせいなのか、レジスタが多いせいなのか分からないが 、少し読みにくい。しかし、慣れればそんなでもないだろう。重要な部分は以下 だ。 ----- 条件分岐 00000000`0040101f 488d4c2430 lea rcx,[rsp+30h] 00000000`00401024 ff15d60f0000 call qword ptr [crackme1!_imp_GetSystemTime] 00000000`0040102a 0fb7542430 movzx edx,word ptr [rsp+30h] 00000000`0040102f 440fb75c2436 movzx r11d,word ptr [rsp+36h] 00000000`00401035 6681faa804 cmp dx,4A8h 00000000`0040103a 0fb74c2432 movzx ecx,word ptr [rsp+32h] 00000000`0040103f 751c jne crackme1!WinMain+0x5d 00000000`00401041 6683f905 cmp cx,5 00000000`00401045 7516 jne crackme1!WinMain+0x5d 00000000`00401047 664183fb0f cmp r11w,0Fh 00000000`0040104c 750f jne crackme1!WinMain+0x5d -----  GetSystemTime関数が呼び出されているが、この関数の引数はひとつで、構造体 のアドレスだ。よって、0040101fにて、rcxに構造体のアドレスが入れられたと分 かる。さらに、呼び出されたあと、dxレジスタに値が転送されている。よって、 アドレス00401035で、dxレジスタと0x04A8が比較されている。ちなみに04A8hは十 進数で1192。同じく、0040102fにて、r11wへ、GetSystemTime関数にて取得された 値が転送されている。ちなみに、r11は64ビットサイズで、r11dはr11の下位32ビ ット、r11wはr11dの下位16ビットだ。  このような感じで、レジスタへの転送と比較が行われ、jne命令でジャンプ先が 示されている。しかし、ジャンプしてしまったら、エラーメッセージが表示され るため、ここはジャンプさせないようにバイナリを変更しなければならない。よ って、これら3つのjne命令すべてを逆転させてやれば、クラックは完了となる。 ■0x05.) バイナリ変更  続いてバイナリを変更する。crackme1.exeをバイナリエディタで開くと、アド レス00000400以下から、コードが書かれてあるのが分かる。もしかしたらPEフォ ーマットも大幅な変更が加えられているかもしれない、と思ったが、コードセク ションのアドレスなどはいたって普通だった。64ビット環境のEXEファイルも、少 々興味があるので、見てみたい気もするが、とりあえずはjne命令の変更を行うこ とにする。 ----- crackme1.exe(変更前)(http://07c00.com/text/x64rev1/crackme1.exe) 00000430 0F B7 5C 24 36 66 81 FA A8 04 0F B7 4C 24 32 75 00000440 1C 66 83 F9 05 75 16 66 41 83 FB 0F 75 0F FF 15 -----  0000043Fから「75」が3回ほど出現しているのが分かる。よって、これら3つを 「74」に変更する。 ----- crackme1.exe(変更後)(http://07c00.com/text/x64rev1/crackme1c.exe) 00000430 0F B7 5C 24 36 66 81 FA A8 04 0F B7 4C 24 32 74 00000440 1C 66 83 F9 05 74 16 66 41 83 FB 0F 74 0F FF 15 ----- 実行画面:http://07c00.com/text/x64rev1/b.png ■0x06.) さいごに  今回は、64ビット環境でも、マシン語解析を中心としたリバースエンジニアリ ングが行えるのか、を試した。32ビット環境と比べると、レジスタのサイズが64 ビットになっていたり、アドレス(ポインタ)が64ビットになっていたりで、慣 れるまでは少々苦労するかもしれないが、やろうと思えば十分可能であることが 分かった。  32ビット環境だと、どうしても搭載するメモリは(例外はあるが一般的な考え 方としては)4Gバイトまでなので、今後コンピュータをさらに高性能化していく ためには、64ビット化は必須なのかもしれない。しかし、その場合においても、 マシン語解析によるリバースエンジニアリングが可能ならば、まだアセンブラを やる意味もあるのではないかと思う。  興味があれば、ぜひともx64のアセンブラもやってみてほしい。 x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第4章: Windowsシステムプログラミング Part3 〜SYSENTERとSYSEXIT〜 --- 著者:Kenji Aiko x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■0x01.) はじめに  このテキストは、Windowsシステムに関するプログラミングを中心に記述してい る。カーネルランドのデバッグ、SYSENTER、SYSEXITなどを中心に解説している。 ■0x02.) SYSENTER  Wizard Bible vol.36の「Windowsシステムプログラミング Part2」にて、「SY SENTERはユーザーランドとカーネルランドを繋ぐ命令であり、これをフックでき る」ことを述べた。そして、SYSENTER実行時に以下の処理が走ることを書いた。 ----- sysenter実行時の処理内容 1. CSレジスタにSYSENTER_CS_MSR(MSR-174H)の値をロード 2. EIPレジスタにSYSENTER_EIP_MSR(MSR-176H)の値をロード 3. SSレジスタにSYSENTER_CS_MSRの値に8を加算した値をロード 4. ESPレジスタにSYSENTER_ESP_MSR(MSR-175H)の値をロード 5. 特権レベル0に切り替えて、カーネルモードルーチンの実行を開始 -----  今回は、これを実際にデバッガで追い、確認する。  なお、環境は、ゲストOS「WindowsXPSP2」、ホストOS「WindowsXPSP2」、COM1 からWinDbgでリモートアクセスしている状態とする。 ----- WinDbg nt!RtlpBreakWithStatusInstruction: 804e5b25 cc int 3 -----  まずは、break(Ctrl + Break)でゲストOSを止める。続いて、現在動作中のプ ロセスを列挙する。 ----- WinDbg kd> !process 0 0 **** NT ACTIVE PROCESS DUMP **** (省略) PROCESS 8194b608 SessionId: 0 Cid: 0798 Peb: 7ffdf000 ParentCid: 0364 DirBase: 09117000 ObjectTable: e206a078 HandleCount: 143. Image: wuauclt.exe PROCESS 818e3020 SessionId: 0 Cid: 0604 Peb: 7ffdf000 ParentCid: 07d8 DirBase: 043bb000 ObjectTable: e21c5530 HandleCount: 32. Image: cmd.exe PROCESS 81944d50 SessionId: 0 Cid: 05fc Peb: 7ffdf000 ParentCid: 0604 DirBase: 0d129000 ObjectTable: e21093f0 HandleCount: 59. Image: conime.exe -----  列挙されたプロセスの中から、適当なプロセスにアタッチし、そのプロセスの ntdll!KiFastSystemCallにブレイクポイントを設置する。そして、ゲストOSを動 かす。 ----- WinDbg kd> .process /r /p 818e3020 Implicit process is now 818e3020 .cache forcedecodeuser done Loading User Symbols ......................... kd> bp ntdll!KiFastSystemCall kd> bl 0 e 7c94eb8b 0001 (0001) ntdll!KiFastSystemCall kd> g Breakpoint 0 hit ntdll!KiFastSystemCall: 001b:7c94eb8b 8bd4 mov edx,esp -----  動き出したゲストOSは、ブレイクポイントntdll!KiFastSystemCallにて、処理 が止まり、制御がデバッガに移る。ここで処理をひとつ進めると、SYSENTER命令 が見える。 ----- WinDbg kd> t ntdll!KiFastSystemCall+0x2: 001b:7c94eb8d 0f34 sysenter kd> r eax=00000032 ebx=00000110 ecx=00abfc44 edx=00abfbe8 esi=00abfca8 edi=00000000 eip=7c94eb8d esp=00abfbe8 ebp=00abfc6c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!KiFastSystemCall+0x2: 001b:7c94eb8d 0f34 sysenter -----  SYSENTER命令を呼び出す前に「レジスタの状況」を確認しておく。  そして、今度は、ntdll!KiFastSystemCallのブレイクポイントを解除し、SYSE NTER呼び出し後に実行される処理(nt!KiFastCallEntry)にブレイクポイントを 仕掛けておく。この状態でWindowsを実行する。 ----- WinDbg kd> bp nt!KiFastCallEntry kd> bd 0 kd> bl 0 d 7c94eb8b 0001 (0001) ntdll!KiFastSystemCall 1 e 804e0f6f 0001 (0001) nt!KiFastCallEntry kd> g Breakpoint 1 hit nt!KiFastCallEntry: 804e0f6f b923000000 mov ecx,23h kd> r eax=00000032 ebx=00000110 ecx=00abfc44 edx=00abfbe8 esi=00abfca8 edi=00000000 eip=804e0f6f esp=f9e73000 ebp=00abfc6c iopl=0 nv up di pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046 nt!KiFastCallEntry: 804e0f6f b923000000 mov ecx,23h -----  当然、ブレイクポイントを仕掛けたnt!KiFastCallEntryで処理が止まる。ここ で、再度レジスタの値を確認し、SYSENTER呼び出し前と、SYSENTER呼び出し後の 違いを見る。 ----- SYSENTER呼び出し前 eax=00000032 ebx=00000110 ecx=00abfc44 edx=00abfbe8 esi=00abfca8 edi=00000000 eip=7c94eb8d esp=00abfbe8 ebp=00abfc6c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ----- ----- SYSENTER呼び出し後 eax=00000032 ebx=00000110 ecx=00abfc44 edx=00abfbe8 esi=00abfca8 edi=00000000 eip=804e0f6f esp=f9e73000 ebp=00abfc6c iopl=0 nv up di pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046 ----- ----- WinDbg(MSRの値) kd> rdmsr 174 msr[174] = 00000000`00000008 kd> rdmsr 175 msr[175] = 00000000`f9e73000 kd> rdmsr 176 msr[176] = 00000000`804e0f6f -----  正確にcs、ss、eip、espがmsrの値に変わっていることが確認できる。確かにS YSENTERの処理が、情報通りであると分かった。また、他にも、fsやeflが変更さ れている。  なお、これを調べるために、rootkit氏のブログ「そもそも、no life(※1)」 の記事を大いに参考にさせていただいた。 (※1)そもそも、no life http://d.hatena.ne.jp/rootkit/20071008 ■0x03.) SYSEXIT  SYSENTERと対をなす命令として「SYSEXIT」命令がある。SYSEXITは、カーネル ランドからユーザーランドへ戻るための命令だ。  nt!KiSystemCallExit以下を逆アセンブルすると、SYSEXIT命令が使われている ことが確認できる。 ----- WinDbg nt!KiSystemCallExit: 001b:804e1170 cf iretd nt!KiSystemCallExit2: 001b:804e1171 f644240901 test byte ptr [esp+9],1 001b:804e1176 75f8 jne nt!KiSystemCallExit (804e1170) 001b:804e1178 5a pop edx 001b:804e1179 83c404 add esp,4 001b:804e117c 80642401fd and byte ptr [esp+1],0FDh 001b:804e1181 9d popfd 001b:804e1182 59 pop ecx 001b:804e1183 fb sti 001b:804e1184 0f35 sysexit -----  SYSEXIT命令にブレイクポイントを設置する。そして実行する。 ----- WinDbg kd> bp 804e1184 kd> bl 0 e 804e1184 0001 (0001) nt!KiSystemCallExit2+0x13 kd> g Breakpoint 0 hit nt!KiSystemCallExit2+0x13: 804e1184 0f35 sysexit kd> r eax=00000000 ebx=00000000 ecx=0012ed90 edx=7c94eb94 esi=0040d120 edi=004da100 eip=804e1184 esp=f7af1ddc ebp=0012edf0 iopl=0 nv up ei pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246 nt!KiSystemCallExit2+0x13: 804e1184 0f35 sysexit kd> p ntdll!KiFastSystemCallRet: 001b:7c94eb94 c3 ret kd> r eax=00000000 ebx=00000000 ecx=0012ed90 edx=7c94eb94 esi=0040d120 edi=004da100 eip=7c94eb94 esp=0012ed90 ebp=0012edf0 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246 ntdll!KiFastSystemCallRet: 001b:7c94eb94 c3 ret -----  SYSEXITから、ntdll!KiFastSystemCallRetへ処理が移ったことが分かる。ちな みに、ntdll!KiFastSystemCallRetは、SYSENTERの次の処理である。 ----- WinDbg ntdll!KiFastSystemCall: 001b:7c94eb8b 8bd4 mov edx,esp 001b:7c94eb8d 0f34 sysenter ntdll!KiFastSystemCallRet: 001b:7c94eb8f 90 nop 001b:7c94eb90 90 nop 001b:7c94eb91 90 nop 001b:7c94eb92 90 nop 001b:7c94eb93 90 nop ntdll!KiFastSystemCallRet: 001b:7c94eb94 c3 ret -----  また、場合によっては、SYSEXITの後、ntdll!KiFastSystemCallRetではなく、 ntdll!KiUserApcDispatcherへ飛ばされることもあるかもしれないが、何度か試せ ば、ntdll!KiFastSystemCallへ来ることが確認できるだろう。 ■0x04.) SYSEXITフック  SYSENTERによりcs、ss、eip、espが変更されるのならば、SYSEXITによって、こ れらのレジスタが元に戻されるはずだ。では、いったいSYSEXITが呼ばれたとき、 これらの値はどこから戻るのか? また、SYSEXITによるフックは可能なのか?  実際にデバッガで追って調べてみる。  まずはSYSEXITにブレイクポイントを仕掛ける。 ----- WinDbg kd> bp 804e1184 kd> g Breakpoint 0 hit nt!KiSystemCallExit2+0x13: 804e1184 0f35 sysexit kd> r eax=00000035 ebx=00000000 ecx=0086fcec edx=7c94eb94 esi=00000000 edi=00000001 eip=804e1184 esp=f8291ddc ebp=0086ffb4 iopl=0 nv up ei pl zr na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246 nt!KiSystemCallExit2+0x13: 804e1184 0f35 sysexit kd> p ntdll!KiFastSystemCallRet: 001b:7c94eb94 c3 ret kd> r eax=00000035 ebx=00000000 ecx=0086fcec edx=7c94eb94 esi=00000000 edi=00000001 eip=7c94eb94 esp=0086fcec ebp=0086ffb4 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246 ntdll!KiFastSystemCallRet: 001b:7c94eb94 c3 ret -----  SYSEXITによって戻った先のアドレス(eip)は「7c94eb94」だ。この値はSYSE XIT呼び出し前のedxレジスタに格納されている。また、同じようにESPの値は、S YSEXIT呼び出し前のecxレジスタにある。そしてこれらのレジスタは、スタックか ら渡されている。 ----- WinDbg nt!KiSystemCallExit: 804e1170 cf iretd nt!KiSystemCallExit2: 804e1171 f644240901 test byte ptr [esp+9],1 804e1176 75f8 jne nt!KiSystemCallExit (804e1170) 804e1178 5a pop edx 804e1179 83c404 add esp,4 804e117c 80642401fd and byte ptr [esp+1],0FDh 804e1181 9d popfd 804e1182 59 pop ecx 804e1183 fb sti 804e1184 0f35 sysexit -----  では、csやssはどこから来るのか? どうやらレジスタの中にはなさそうだ。 「System Call Optimization with the SYSENTER Instruction(※2)」によると、 これらはGDTに保存されているようだ。 (※2)System Call Optimization with the SYSENTER Instruction http://www.codeguru.com/cpp/w-p/system/devicedriverdevelopment/article.php/c8223/  SYSENTERは、固定の場所(MSR)にジャンプ先アドレスが格納されていたが、S YSEXITはEIPに入れる値をスタックからもってきているため、固定の場所とは言え なさそうだ。つまり、アドレス上書きによるSYSEXITフックはできないように思え る。だが、この考えは間違いである。  確かに、nt!KiSystemCallExit内部では、スタックからジャンプ先を取り出して いる。これは間違いない。しかし、「そもそもそのスタックに値を入れた処理は どこにあるのか?」が問題だ。  スタックからpopしてきた値は「7c94eb94」だ。これは確かにSYSENTER命令の次 の処理を指している。つまり、正確にユーザーランドに戻っている。これは分か る。だが、SYSENTERによってカーネルランドへ入ってから、nt!KiSystemCallExi tへ進んでくるまでの間のどこかで、必ずスタックに「7c94eb94」がpushされてい るはずだ。でなければ、nt!KiSystemCallExit以降の処理で、スタックから「7c9 4eb94」をpopできない。  よって、nt!KiFastCallEntryからnt!KiSystemCallExitまでの処理を追って、ユ ーザーランドへの戻りアドレスが、スタックへpushされている箇所を特定する。 ----- WinDbg nt!KiFastCallEntry: 804e0f6f b923000000 mov ecx,23h 804e0f74 6a30 push 30h 804e0f76 0fa1 pop fs 804e0f78 8ed9 mov ds,cx 804e0f7a 8ec1 mov es,cx 804e0f7c 8b0d40f0dfff mov ecx,dword ptr ds:[0FFDFF040h] 804e0f82 8b6104 mov esp,dword ptr [ecx+4] 804e0f85 6a23 push 23h 804e0f87 52 push edx 804e0f88 9c pushfd 804e0f89 6a02 push 2 804e0f8b 83c208 add edx,8 804e0f8e 9d popfd 804e0f8f 804c240102 or byte ptr [esp+1],2 804e0f94 6a1b push 1Bh 804e0f96 ff350403dfff push dword ptr ds:[0FFDF0304h] 804e0f9c 6a00 push 0 -----  nt!KiFastCallEntryからひとつずつ見ていくと、かなり早い段階でそれは見つ かる。あきらかな固定値がスタックへpushされているいくつかの箇所を辿り、そ の中に、固定アドレスの先の値がpushされている箇所(804e0f96)が見つかる。 ----- 固定アドレスの値をスタックへ格納する処理 804e0f96 ff350403dfff push dword ptr ds:[0FFDF0304h] -----  このハードコードされたアドレス0FFDF0304hの値を見てみると「94 eb 94 7c」 となっている。まさにSYSEXITの戻り先アドレスである。 ----- WinDbg ffdf0304 94 eb 94 7c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -----  つまり、SYSENTER同様、SYSEXITもフックできることが分かった。  では、SYSENTER同様、SYSEXITもフックしてみる。SYSENTERでは、フック先のコ ードをカーネル空間に置かなければならなかったので、仕方なくドライバを用意 したが、SYSEXITの場合は、ユーザー空間でよいので、新たにドライバをインスト ールする必要はない。また、SYSENTERのうしろには、フックしてくれと言わんば かりのNOPが、5バイト分空けられている。 ----- WinDbg ntdll!KiFastSystemCall: 7c94eb8b 8bd4 mov edx,esp 7c94eb8d 0f34 sysenter ntdll!KiFastSystemCallRet: 7c94eb8f 90 nop 7c94eb90 90 nop 7c94eb91 90 nop 7c94eb92 90 nop 7c94eb93 90 nop ntdll!KiFastSystemCallRet: 7c94eb94 c3 ret -----  これはまさに、フックするための領域だ。例えば、この5バイトを次のように書 き換える。 ----- WinDbg ntdll!KiFastSystemCall: 7c94eb8b 8bd4 mov edx,esp 7c94eb8d 0f34 sysenter ntdll!KiFastSystemCallRet: 7c94eb8f 93 xchg eax,ebx 7c94eb90 93 xchg eax,ebx 7c94eb91 c3 ret 7c94eb92 90 nop 7c94eb93 90 nop ntdll!KiFastSystemCallRet: 7c94eb94 90 nop -----  ついでに「7c94eb94」の命令もNOPにしておこう。そして、ハードコードされた 「ffdf0304」の値から5バイト分減算する。 ----- WinDbg ffdf0304 8f eb 94 7c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -----  これでOSを実行する。当然、正常に動作する。本来ならば7c94eb94の命令がNO Pになっているため、あきらかなエラーとなるはずだが、SYSEXITのジャンプ先を 変更し、5バイト分ずらしているため、問題なく動作する。  では、試しに「ffdf0304」の値を、「8f eb 94 7c」から元の値「94 eb 94 7c」 へ戻して、再度OSを実行してみる。7c94eb94の命令がNOPのままならば、SYSEXIT から戻った先がRETではなく、NOPということになり、OSはおかしな動作をするだ ろう。SYSEXITにて、すでにユーザーランドに戻っているため、ブルースクリーン などの致命的なダメージにはならないはずだが、OSとしての機能は果たせない。  今回の例では、SYSEXITをフックして、xchg命令を2つ実行させただけだが、も ちろん、フック中はありとあらゆる処理が挿入できる。SYSEXITの実行をログに保 存することも可能だ。といっても、そもそもSYSEXIT呼び出しをログに保存する理 由がないが、「可能である」と分かっていることは重要なことだと思う。 ■0x05.) さいごに  さて、前回に引き続き、今回はSYSEXITをフックした。SYSENTERをフックして、 次にSYSEXITをフックして、はっきり言って我ながら無意味なことをやっているな ぁ、とつくづく思う。なので、次回からは少々意味のあることをやっていきたい なぁと思う。 x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第5章: 基礎暗号学講座・第12回 〜素数生成アルゴリズム〜 --- 著者:IPUSIRON x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■0x01.) はじめに  数学において素数は重要な存在である。数学と密接な関係にある暗号の世界に おいても、素数は重要な存在である。公開鍵暗号スキームのアルゴリズムの仕様 を確認してもらえれば、多くの場合において素数をランダムに選択する必要があ ることがわかると思う。例えば、RSA暗号(WB34参照)の鍵生成アルゴリズムでは 大きな素数を2つ生成しなければならない。この部分できちんとした素数が作られ なければ、暗号の安全性が脆弱になってしまうのである。つまり、素数をランダ ムに生成するということは暗号の世界において重要と言える。  今回の記事では、素数をランダムに生成するアルゴリズム(以降、素数生成ア ルゴリズムと呼ぶことにする)を単に紹介するだけでは面白くないので、試行錯 誤しながら素数生成アルゴリズムを考えていくことにする。その後、いくつかの 素数生成アルゴリズムを紹介し、コストの面(必要となる速度・メモリ)の観点 で比較する。最後に、指定されたビット数の素数の生成について言及する。 ■0x02.) 素数生成アルゴリズム=ランダム値生成アルゴリズム+素数テスト  前回のWB35では原始元生成アルゴリズムを紹介した。その際、確定的に(100% の確率で)原始元を生成するアルゴリズムを作るよりも、ある程度大きな確率で 原始元を生成するアルゴリズムを作る方が効率がよいという話をした。このある 程度大きな確率で原始元を生成するアルゴリズムというのは、ランダムな値を生 成するアルゴリズムと、原始元判定アルゴリズムの組み合わせであった。  今回の素数生成アルゴリズムも、同様のアプローチで考えた方が高速であるこ とがわかっている。つまり、素数生成アルゴリズムを考える上で重要な部分は、 優秀な素数判定アルゴリズムを考えるという点に帰着される。素数生成アルゴリ ズムの一部として利用できるぐらい優秀な素数判定アルゴリズムのことを素数テ ストを呼ぶことにする。  まず、素数テストを定義しなければならない。次の2つの条件を満たすようなア ルゴリズムのことを素数テストと呼ぶ。 ・入力が合成数(素数でない値)だった場合、acceptまたはrejectを出力する。 ただし、acceptする確率は1/2以下とする。 ・入力が素数だった場合、必ずacceptを出力する。  つまり、素数テストに素数でない値が入力されれば1/2以上の確率でrejectされ、 素数が入力されれば必ずacceptされるということである。  理想的なアルゴリズムはaccept(素数と判定)されたものは必ず素数で、reje ct(素数でない)と判定されたものは必ず素数でないものである。しかし、この 理想的なものがないとしても、上記の定義のような素数テストさえ存在すれば、 このアルゴリズムを何度も繰り返すことで素数でないのにaccpet(素数と判定) される可能性はどんどん低くすることができる。つまり、実質的に素数テストを 多段で使ってaccpet(素数と判定)されたものはほとんど素数と考えてよいとい える。 ■0x03.) フェルマーテスト  まず素朴に考えると、素数テストのアルゴリズムとして、フェルマーの小定理 が使えるかもしれないと思うはずである。それでは本当に使えるのかどうかを確 認してみよう。  フェルマーの小定理とは「pが素数ならば、任意のa(∈{1,…,p})に対してa^ {p-1}≡1 (mod p)が成り立つ」というものであった。つまり、pが素数ならば、p -1乗すればどの値でもmod pの世界で1に一致するということである。  これを素数pの代わりに、一般の整数n(素数と合成数の混合)に対して考えて みる。ここで、aはn以下の整数なら何でもよいので、a=4としておく。 [1]n=5のとき ・4^{n-1}=4^{5-1}=4^4=16×16≡1×1 (mod 5)=1 [2]n=6のとき ・4^{n-1}=4^{6-1}=4^5≡4 (mod 6) [3]n=7のとき ・4^{n-1}=4^{7-1}=4^6≡1 (mod 7) [4]n=8のとき ・4^{n-1}=4^{8-1}=4^7≡0 (mod 8) [5]n=9のとき ・4^{n-1}=4^{9-1}=4^8≡7 (mod 9) [6]n=10のとき ・4^{n-1}=4^{10-1}=4^9≡4 (mod 10) [7]n=11のとき5 ・4^{n-1}=4^{11-1}=4^10≡1 (mod 11) [8]n=12のとき ・4^{n-1}=4^{12-1}=4^11≡4 (mod 12)  nが素数のときに4^{n-1} (mod n)が1になることは、フェルマーの小定理から当 然である。この表から、逆に4^{n-1} (mod n)が1のときに、nは素数に対応してい ることがわかる。例えば、n=5,7,11(すべて素数)のときに4^{n-1} (mod n)が1 に一致しているからである。即ち、フェルマーの小定理の逆が成り立つことが期 待できそうである(対偶が成り立つのは自明。ここではさらに逆が成り立つこと を期待している)。このフェルマーの小定理の逆の方法で、素数判定アルゴリズ ムをフェルマーテストと呼び、フェルマーテストのアルゴリズム名をFermatとす る。このFermatの入出力と内部のアルゴリズムは次のようになる。 ・入力:n:整数(ただし、n≧3) ・出力:"reject" or "accept" ----- Fermatのアルゴリズム a←{2,3,…,n-2}からランダムに選択した値 if a^{n-1} ≠ 1 (mod n) then return "reject" else return "accept" -----  ここで、nが素数ならば、「Fermat(n)="reject"」(この表記法は「Fermatにn を代入したときの出力結果が"reject"」ということを意味する)となる確率は0が 当然成り立つ。一方、nが合成数ならば、「Fermat(n)="reject"」がどんな値にな るかが不明である。1になるのが理想的だが、それは難しそうである。しかし何ら かの確率が具体的に出て欲しい。できれば1/2以上だと嬉しい(1/2以上なら素数 テストとして活用可能であることが確定するから)。それでは、「nが合成数」か つ「Fermat(n)="reject"」が成り立つときの確率を調べてみる。  ここで主張を明確にするために、次の2つの言葉を定義する。 ・「n≧2」かつ「a^{n-1}≠1 (mod n)」が成り立つとき、a(ただし1≦a<n)を 「nに対するFermat witness」と呼ぶ。 ・「n(≧3):合成数」かつ「a^{n-1}≡1 (mod n)」が成り立つとき、a(ただし 1≦a<n)を「nに対するFermat liar」と呼ぶ。  この定義より、指定されたnに対してひとつでもFermat witnessが存在したら、 nは合成数と確定できる。なぜならば、Fermat witnessということは「a^{n-1}≠ 1 (mod n)」が成り立つことを意味し、Fermatのアルゴリズムのif文の条件文に対 応している。つまり、if文の条件がTrueになり、"reject"が出力されることに対 応する。ところが、nが素数のときに"reject"が出力されることは皆無である。こ れはフェルマーの小定理から明らかである。つまり、"reject"が出力されたとき のFermatの入力は必ず合成数ということになる。  また、「nが合成数」かつ「Fermat(n)="reject"」が成り立つときの確率を調べ るには、aの総数のうちで、「nに対するFermat witness」であるようなaの個数が どれぐらいあるかを知ることができればよい。まず、aの総数はn-3個である。こ れはaは3≦a<nを満たすから明らかである。次に、「nに対するFermat witness」 のときは、定義より「a^{n-1}≠1 (mod n)」という条件が満たされたときである。  そして、nが素数か否か、aが指定されたnにおいてa^{n-1}≡1 (mod n)を満たす か否かによって分類すると、次の4つのパターンが存在する。 ------------------------------------------------------- | | nは素数 | nは合成数 | |-----------------------------------------------------| | aがa^{n-1}≠1 (mod n)を満たす | (1) | (2) | |-----------------------------------------------------| | aがa^{n-1}≡1 (mod n)を満たす | (3) | (4) | -------------------------------------------------------  フェルマーの小定理より、(1)の場合はありえないので、0個。そして、aが「n に対するFermat witness」であるときの個数は(2)、aが「nに対するFermat liar」 であるときの個数は(3)+(4)に対応している。つまり、「nに対するFermat witne ss」+「nに対するFermat liar」=n-3が成り立つ。先ほど、「nが合成数」かつ 「Fermat(n)="reject"」が成り立つときのaの個数が、nに対するFermat witness の個数と一致するとすでに述べた。よって、「nが合成数」かつ「Fermat(n)="re ject"」が成り立つときのaの個数は、「aの総数」-「nに対するFermat liar」と 言い換えることもできる。  以上のことをまとめると、目的であった「nが合成数」かつ「Fermat(n)="reje ct"」が成り立つときの確率は(nに対するFermat witnessの個数)/(n-3)、即 ち1-(nに対するFermat liarの個数)/(n-3)である。  ランダム値生成アルゴリズムでnを生成するわけだが、例えばn=143を生成して、 これを素数判定アルゴリズムFermatに入力したときの動きを見ていく。そもそも n=143は11×13のように素因数分解できるので、合成数である。しかし、我々はま だ合成数かどうかわからない、これを調べるためにFermatを使うのである。n=14 3のときの「nに対するFermat liar」、即ちa^{n-1}≡1 (mod n)を満たすようなa を知りたい。ここでは結論を述べると、a=1,12,131,142の4つだけである。例えば、 143は合成数なので、12^142 (mod 143)は1に一致するとは限らない。ところが計 算すると1に一致する。131も同様に131^142≡1 (mod 143)が成り立つので、143に 対するFermat liarのひとつである。特にa=1(なぜならば1^142≡1 (mod 143)), 142(なぜならば142^142≡-1^142 (mod 143)≡1 (mod 143))は自明なものなので、 除外して考えると、a=12,131だけになる。  このとき「Fermat(143)="reject"」が成り立つ確率が1/2以上かどうかを調べる。 まず、「Fermat(143)="accept"が成り立つ確率」=2/(143-3)=2/140=1/70<1/2が 成り立つ。よって、「Fermat(143)="reject"が成り立つ確率」>1/2になる。つま り、n=143のときはFermatを多段にすることで、合成数を判断できてうまくはじく ことができるわけだ。 ◇  次に、n=561のときを考えてみる。このn=561も3×11×17と素因数分解できるの で合成数である。  このとき「Fermat(561)="reject"」が成り立つ確率が1/2以上かどうかを調べる。 n=561のときにGCD(a,n)=1を満たすaは「nに対するFermat liar」になってしまう。 つまり、「Fermat(143)="accept"が成り立つ確率」=φ(n)/(n-3)≒φ(n)/nにな る(φという記号はオイラー関数を意味する)。なぜφ(n)が出てくるのかという と、GCD(a,n)=1であるようなaの個数、即ちZ_n^*の個数だからである。よって、 「Fermat(143)="reject"が成り立つ確率」=(1-φ(n))/nになる。ここで、nが大 きいとき、n-φ(n)<<nが成り立つので、「Fermat(143)="reject"が成り立つ確 率」<<1/2になってしまう。つまり、n=561のときはFermatを多段にしても、合 成数を判断できずうまくはじくことができない。つまり、n=561に対してはFerma tは、素数テストとしてうまく動かないということである。 ◇  このようなnはカーマイケル数と呼ばれ、無限に存在することが証明されている。 よって、例外となるのはn=561だけでなく、ランダム値生成アルゴリズムの出力で あるnでたまたまカーマイケル数が選ばれてしまえばFermatは素数テストとして有 効ではないということになる。しかも、カーマイケル数は無限に存在するので、 nがカーマイケル数かどうかをチェックしてから、Fermatの入力にするというアプ ローチも無理である。したがって、フェルマーテストは素数テストとして活用は できないという結論になる。 ■0x04.) カーマイケル数  この節ではカーマイケル数についてもう少し見てみる。素数生成アルゴリズム の話からは少しはずれるので、飛ばしてもらってもよい。  カーマイケル数には次のような性質を持つ。 [定理](Alford, Graville and Pomerance (1992)) カーマイケル数は無限個存在する。 [証明]論文読んでないから、証明わからない。後日読んでおく…。 [定理]「n(≧3):奇数のカーマイケル」 ⇔「次の3つすべてが成り立つ。 ・nは平行数を持たない ・任意のnがpと素である ・p-1がn-1の約数」 [証明]⇔を示すので、必要条件と十分条件に場合分けして証明する。 [1]⇒を示す  カーマイケル数の定義より、(n,a)=1を満たすような任意のaに対して、a^{n-1} ≡1 (mod n)が成り立つ。  また、pをnの約数の素数とし、aをnと素なmod pの原始元とする。このaは、中 国人の剰余定理?より存在が保証される。すると、原始元の定義より、a^{p-1}≡ 1 (mod p)が成り立つ。よって、a^{n-1}≡1 (mod p)が成り立つ。  次に、[定理]「g∈Gであり、e∈Zであるとする。このとき、g^e=1となるのは、 eがgの位数で割り切れるときに限る」より、aの位数p-1はn-1の約数である。  さらに、p^2がnの約数でないことを示す。背理法を用いるため、p^2がnを割り 切ると仮定する。このとき、φ(p^2)(=(p-1)p)はφ(n)の約数である。また、m od nの既約剰余群で位数pの元が存在する。よって、pはn-1の約数である。これは pがnの約数であることに矛盾する。 [2]←を示す  nは平方数を含まないとし、nのすべての素の約数pに対して、p-1をn-1の約数と する。ただし、aとnは互いに素とする。  このとき、フェルマーの小定理より、a^{p-1}≡1 (mod p)が成り立つ。n-1はp -1の倍数であるから、a^{n-1}≡1 (mod p)が成り立つ(nと素である値pごとに、 このリレーションが成り立つ)。よって、nの素因数は互いに異なっているから、 a^{n-1}≡1 (mod n)が成り立つ(複数のリレーションをひとつのリレーションに まとめた)。 □ [定理]カーマイケル数は少なくとも3つの異なる素因数を持つ。 [証明]nをカーマイケル数とすると、定義よりnは素数ではない。また、上記の定 理より、nは平方数を持たない。よって、nは素数のべき乗にはならない。つまり、 nは少なくとも2つの素因数を持つことがいえる。  次に、p,q(p>qとしても一般性を失わない)をnの素因数とし、n=pqが成り立 つと仮定する。上記の定理より、p-1はn-1=pq-1=(p-1)q+(q-1)の約数になる。よ って、p-1はq-1の約数となる。しかし、p>qより、p-1>q-1(>0)が成り立つの で、q-1の最小性より矛盾が生じる。よって、n=pqと仮定したことが間違いという ことになる。したがって、nの素因数は少なくとも3つ以上であることがいえる。 □ ■0x05.) Miller-Rabinテスト  Millerの定理と呼ばれる次の定理が存在する。 [定理]pを素数とし、rはp-1={2^s}×rを満たす奇数とする(奇数が出るまで2で割 っている)。 このとき、1≦a≦p-1なる任意の整数aに対して、次が成り立つ。 「a^r≡1 (mod p)」あるいは「a^{{2^j}×r}≡-1 (mod p)」を満たすようなj∈{ 0,…,s-1}が存在する。←(*)  ここではMillerの定理の証明はせずに、何を意味しているのか、そしてなぜ成 り立つのかという点と直観的に述べる。  pが素数のとき、「x^2≡1 (mod p)」⇒「x≡-1 or 1」が成り立つ。pが合成数 のときはこれが成り立つとは限らない。よって、素数を法とする世界で2乗して1 だったら、元の数は1 or -1である。つまり、a^rを2乗ずつしていき、1に初めて なったとき、その直前の数は-1でなければならないということである(図1参照)。 (図1)http://security2600.sakura.ne.jp/main2/image3/miller1.jpg  Millarの定理を利用した素数テストであるMiller-Rabinテスト(MRテスト)を 紹介する。このMiller-Rabinテストの入出力とアルゴリズムMRは次のようになる。 ・入力:n(n≧3の奇数) ・出力:"prime" or "composite" ----- MRのアルゴリズム s,rはn-1=2^{s}×rを満たすようにセットされる(ただし、rは奇数) i=0 i←i+1 a:{1,2,…,n-1}からランダムに選択 y[0]←a^r mod n if(y[0]==1 || y[0] == n-1) output "prime" else for(j=1;j≦s-1;j=j+1){ y[j]←y[j-1]^2 mod n if(y[j]==n-1) output "prime" } output "composite" -----  MRのアルゴリズムの中身について解説する。 ・6行目のif文の条件式の前半はMillerの定理の「a^r≡1」に対応し、後半はj=0 のときの「a^{{2^j}×r}≡1」に対応する。y[0]==n-1はmod nでy[0]=-1であるこ とに注意。 ・11行目のif文の条件式はj≠0のときのa^{{2^j}×r}≡1に対応する。  このMiller-Rabinテストの問題は次の2点である。 ・入力nが素数なのに、"composite"と出力されること→[1] ・入力nが合成数なのに、"prime"と出力されること→[2] [1]nが素数の場合  Millerの定理より、MRは"composite"を出力しない。なぜならば、いきなり1に なるか、途中で-1が出てくるかのどちらかである。よって、必ず「output "prim e"」の命令にひっかかる。 [2]nが偶数の場合  Miller-Rabinテストで、"prime"を出力する確率は(1/4)^tになる。ただし、tは 繰り返し回数とする。  以上でMiller-Rabinテストの仕様についての解説は終えた。  Miller-Rabinテストでは、「nが合成数」かつ「MR(n)="reject"」が成り立つと きの確率が1/2以上であることを期待したい。ここで主張を明確にするために、次 の2つの言葉を定義する。 ・「a^r≠1 (mod n)」かつ「任意のj∈{0,…,k-1}において、a^{{2^s}×r}≠-1 (mod n)」が成り立つとき、aを「nに対するMR-witness」と呼ぶ。 ・「n:合成数」かつ「a:nのMR-witnessでない」が成り立つとき、aを「nに対す るMR-liar」と呼ぶ。  Fermat-wintess/liarのときの議論と同様に、「nに対するMR-witness」と「nに 対するMR-liar」も次の関係式が成り立つ。 「nに対するMR-witness」+「nに対するMR-liar」=n-1 例1:意味と使い方に慣れることを目的として、Miller-Rabinテストを用いること によって、n=105が素数かどうかを判定してみる(n=105=3・5・7が成り立つので 本当は素数ではないのだが、それは気にせずアルゴリズム的にどう動くか調べる)。  n-1=104={2^3}×13が成り立つから、まずs=3,r=13とセットされる。次に、ラン ダムに選んだ整数値がa=8であったとする。すると、y[0]=8^{13}≡8 (mod 105)に なる。このy[0]はmod 105の世界で1 or 104(=n-1)ではないので、else以下のfor 文が実行される。 ・y[1]←y[0]^2≡8^2≡64 (mod 105) ・y[2]←y[1]^2≡64^2≡1 (mod 105)  後は、ずっとy[j]は1 (mod 105)になる。そのため「output "prime"」が実行さ れずに、最終的に「output "composite"」が実行される。よって、n=105は素数で はない。 ◇ 例2:次にカーマイケル数が入力されても、Miller-Rabinテストがうまく動作する ことを確認する。ここでは例として最小のカーマイケル数であるn=561=3×11×1 7を考える。先ほどのフェルマーテストではこのときに問題があった。Miller-Ra binテストではこの問題が解決されていることを確認しておかなければならない。  n-1=560={2^4}×35が成り立つので、s=4,r=35とセットされる。 ・a=2 ・a^35=2^35 (mod 561)≡263 ・a^70=166 ・a^140=67 ←a^280=1となる直前だが、mod nの世界では-1ではない ・a^280=1 ・a^560=1  a=2のとき、a^rの2乗ずつしていくと、a^{n-1}までに法nの世界で-1は一度も登 場しない。つまり、a=2はMR-witnessになる(n=561にはMR-witnessが少なくとも ひとつ存在することが確認できた)。  同様に、a=3,…,560まで調べていくと、例えばa=5のときは「nに対するMR-wit ness」になるし、a=50のときは「nに対するMR-liar」になる。よって、n=561のと きにMR-witnessとMR-liarがあることがわかった。実際には、(MR-witnessの数) >(MR-liarの数)であることがわかっている。よって、「MR(561)="reject"」が 成り立つ確率は1/2以上になる。以上により、カーマイケル数の一種であるn=561 であっても、Miller-Rabinテストは素数テストとしてうまく働くことが確認でき た。  最後に気になるのは、どのような整数nを選んだとしても、「nが合成数」かつ 「MR(n)="reject"」が成り立つ確率が1/2以上であるかどうかという点である。こ の疑問に関しては肯定的な意味で解決されている。それを定理としてまとめると 次のようになる。 [定理]「nが合成数」かつ「MR(n)="reject"」が成り立つ確率が1/2以上である。 言い換えると、「nが合成数」かつ「MR(n)="accept"」が成り立つ確率は1/2より 小さい。 [証明]nを合成数とする。「nに対するMR-liar」であるようなaの個数が、全体の 半分以下であることを示すことができればよい。ここで、全体とはZ_n^*なので、 その個数はφ(n)である。  まず、nがカーマイケル数か否かによって場合分けして考える。 [1]nがカーマイケル数でないとき  nがカーマイケル数でなければフェルマーテストであっても問題なかった。Mil ler-Rabinテストはフェルマーテストの改良版なので、アルゴリズム的に問題なく、 次の関係(集合の包含関係)が成り立つ。 (「nに対するMR-liar」であるようなaの集まり) ⊆(「nに対するFermat-liar」であるようなaの集まり) <Z_n^*  よって、「nに対するMR-liar」であるようなaの集まりの要素の個数は1/2×φ (n)以下である。 [2]nがカーマイケル数であるとき  問題はこちらの場合である。「nに対するMR-liar」(a^{{2^s}×r}≡-1 (mod n))であるようなaの集まりのままでは考えにくいので、これを包括するような集 合を新たに考え、その集合であってもZ_n^*の真部分群であることを示すことがで きればよい。a^{{2^s}×r}≡-1 (mod n)を満たすようなaの集まりをAとする。ま た、tをa^{{2^s}×r}≡1 (mod n)を満たすようなaが存在するときにおける、sの 最大値とする。このtを使って、新しい集合を、a^{{2^t}×r}≡±1 (mod n)を満 たすようなaの集まりと定義できる。この集合をBとする。A⊆Bであることに注意。 目的はB<Z_n^*を示すことである。真部分群であることを示すには、部分群であ ることと真の部分群であることの2つを示せばよい。この2つを順を追って証明し ていく。 (i)BがZ_n^*の部分群であることを示す  部分群であることを示すためには逆元の存在と演算が閉じていることをいえれ ばよい。 ・Bは逆元が存在する。なぜならば、b^{{2^t}×r}≡±1 (mod n)を満たす値であ るbは、2乗すれば必ず1に一致する。つまり、逆元は必ず存在するからである(自 分自身)。 ・c,d∈Bならば、cd∈Bが成り立つ。なぜならば、c,d∈Bより、cはc^{{2^t}×r} ≡±1 (mod n)を満たす値、dはd^{{2^t}×r}≡±1 (mod n)を満たす値である。よ って、{cd}^{{2^t}×r}≡±1 (mod n)が成り立つので、cd∈Bが成り立つ。一言で 言えば、±1をを掛ければ、結局±1になるからである。  よって、B≦Z_n^*が成り立つ。 (i)BがZ_n^*の真部分群であることを示す  これを示せば、Z_n^*からBを除いた集合が空集合であればよい。そこで背理法 を用いる。そこで、Z_n^*からBを除いた集合が空集合でないと仮定する。  カーマイケル数は3つ以上の素因子を持つので、少なくともn=n_1×n_2と記述さ れる。ただし、n_1,n_2とも奇数かつGCD(n_1,n_2)=1である。  また、{{2^t}×r}乗するとmod nの世界で-1に一致するような値がAの要素に存 在する(これはAの定義から明らか)。この値をeとする。つまり、e^{{2^t}×r} ≡-1 (mod n)が成り立つ。  ここで、a:=e (mod n_1)と定義する。すると、中国人の剰余定理より、次の連 立合同式を満たすようなa∈Zが存在する。 ・a≡e (mod n_1) ・a≡1 (mod n_2) ・ただし、GCD(n_1,n_2)=1  まず、「a^{{2^t}×r}≡e^{{2^t}×r} (mod n_1)≡-1 (mod n_1)」(この結果 を①とする)が成り立つ。また、「a^{{2^t}×r}≡1 (mod n_1)」(この結果を② とする)も成り立つ。  よって、a^{{2^t}×r}≡1と考えると②に反し、a^{{2^t}×r}≡-1と考えると① に反するので、a^{{2^t}×r}≠±1 (mod n)になる(modがnになっていることに注 意)。よって、a(∈Z_n^*)はBに属しない。  そもそもA⊆Bのように設定したはずなのに、aはAに含まれ、Bに含まれないとい うことはありえない。よって、矛盾が生じた。 □  これでMiller-Rabinテストが素数テストとして有効であることが示された。  後は、「nが合成数」かつ「MR(n)="accept"」が成り立つ確率がどのくらいの値 以下であるかどうかを評価できれば嬉しい。これがわかれば、どのくらい多段に すれば十分かどうかを正確にわかる。  証明は省くが、確率として次のような結果が知られている。 [定理]「nが合成数」かつ「MR(n)="accept"」が成り立つ確率は1/4以下である。  MR(n)をk回独立に繰り返した全体をMR_k(n)とする。MR_k(n)は内部でk回MR(n) をサブルーチンとして呼び出す。MR(n)がすべて"accept"ならばMR_k(n)も"accep t"、MR(n)がひとつでも"reject"ならばMR_k(n)は"reject"とする。つまり、1回で も"reject"が出力されたら、MR_k(n)も"accept"ということになる。  よって、次の定理が得られる。 [定理]「nが合成数」かつ「MR_k(n)="accept"」が成り立つ確率は(1/4)^k以下で ある。 [証明]MR_k(n)は内部でシーケンシャル、しかもk個それぞれが独立にMR(n)をサブ ルーチンとして呼び出すので、全体の確立は(1/4)^k以下となる。 □ ■0x06.) Miller-Rabinテストと他の素数生成アルゴリズムとの比較  Wikipedeia(http://ja.wikipedia.org/wiki/素数判定)を参照してもらえれば わかるように、素数生成アルゴリズムにはいくつか種類が存在する。その中に確 率的な素数判定アルゴリズムとして、Miller-RabinテストやSolovay-Strassenテ ストがある。まだルジャンドルの記号をWBで定義していないことと、Miller-Rab inテストの方が計算量が小さいので、Solovay-Strassenテストのアルゴリズムに ついては今回言及しない。とりあえずMiller-Rabinテストを知っておけば暗号の 実装はなんとかなると思う。 ■0x07.) 素数のランダムな選択  Miller-Rabinテストなどで効率的に素数を生成できることは示されたが、まだ 固定されたビット長の素数の生成についてはまだ言及していない。実際に多くの 暗号スキームの鍵生成アルゴリズムなどでは、固定されたビット長のランダムな 素数を生成する必要が生じる。  ここではkビットの素数を生成したいとする。そのとき、次の手順で実行すれば よい。 1:kビットの奇数nをランダムに生成する。ただし、nの最初と最後のビットを1と おき、残りのk-2ビットの数をそれぞれ独立でランダムに生成する。 2:このnが素数かどうかを調べる。  最初に素数表を使用して、nがある一定の値であるBよりも小さい素数で割り切 れるかどうかを調べる。利用するハードウェアやソフトウェアがMiller-Rabinテ ストでの割り算をどのくらい速いかによって、このBの値は決定される。Miller- Rabinテストより、試行割算法の方がずっと効率的な場合は、より大きなBを選ぶ とよい。一般的な例として、B=106と選ばれる。nの約数が見つからなければ、以 降を実行する。  次に、k回の繰り返しのMiller-RabinテストのアルゴリズムMR_kにnを入力する。 ここでnのMR-witnessが見つからなければ、nは素数である。見つからなければ、 nは合成数であるので、ステップ1に戻ってやり直す。 3:最終的に得られたnはkビットの素数とみなせる。 ■0x08.) 終わりに  今月号の記事で暗号の実装における道具が大体揃った。後は多倍長演算さえあ ればよい。多倍長演算はちょっと複雑なので、ちょっと飛ばすことにする(実装 するときは既存のライブラリを使うか、Rubyのように多倍長演算を自動的にして くれるスクリプト言語を使うとよいかもしれない)。  次回からはまた暗号技術についての解説に戻る。個人的にはすぐにデジタル署 名に入りたいが、その前にハッシュ関数について言及する。なぜならデジタル署 名の安全性を高める手法として、ハッシュ関数を利用する方法があるからである。 また、UNIXのパスワード認証におけるパスワードファイルや、掲示板のトリップ、 配布プログラムの改竄チェックなどのように、コンピュータの世界における幅広 い場面でもハッシュ関数は利用されている。こうした理由によりハッシュ関数に ついて理解を深めておくことは有用と思われるので、早めに解説しようと思いま した。  では、また来月会いましょう。 x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x --- 第6章: お知らせ --- x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ○Wizard Bible(http://wizardbible.org/)では随時、執筆ライターを募集して います。  扱う内容のテーマは広義での「under ground」です。例えばハッキングからピ ッキングなどと幅広い内容を考えています。また特殊な職業や趣味を持った方の レクチャーなども含まれます。  一回きりでも構いません。また必ず毎回連載する義務もありませんので、でき る範囲で構いません。気軽に声をかけてください。 ○Kenji AikoさんがQ&Aを作ってくれました。初めて参加する人でもわかりやすく 書かれていますので、参考にしてください。 http://wizardbible.org/wbQandA.html ○Wizard Bibleに参加希望の方は気軽にメール(ipusiron@gmail.com)ください。 x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ---- 第7章: 著者プロフィール --- x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x x0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0xx0xXx0x ■金床 ●Job: プログラマー ●Web: http://guardian.jumperz.net/, http://www.jumperz.net/ ●Mail: anvil@jumperz.net ●Comment:  BHJはお祭りとしてエンジョイさせていただきやしたヽ(´ー`)ノ ●暗号について  Javaには標準でたくさんの有用な暗号化ライブラリがあるので、自分が作るツ ールで気軽にこれらを利用することができて萌えです。特にSSLについては脆弱性 だらけのファッキンOpenSSLと決別できるのでいいです。つまりまとめると、「時代は Java」ということになります。 ■eagle0wl ●Job: ニコ厨 ●Web: http://www.mysys.org/eagle0wl/ (未だ休止中(汗)) ●Mail: masm0wl@hotmail.com ●Team(Group): backsection ●Comment:  ニコニコ動画とYouTubeが、JASRACへの著作権料支払いの契約締結に向けて協議 に入ったそうです。Yahoo!ビデオキャストは既に使用料を支払っているとのこと。  この問題は、某マイナー競技に一枚噛んでいることもあって私も関心を寄せて いるのですが、例えカスラ(ry に使用料を払ったとしても、自分で演奏したも の(これには初音ミクも含まれる)について許可されるだけで、音楽CDの音源に ついてはレーベルが持つ著作隣接権が発生するため、使用は認められないのは如 何なものかと思った次第。  しかし、それと同時に「カ(ry が無くなればすべてが解決する」と勘違いし ている輩にも同様にムカついています。そういう発想が前提だと「ならば悪者を やっつけよう」という結論にしかならないと思います。  最後に。 IPUSIRONさんに無理を言って締め切りを延ばしてもらいました。すん ませんすんません。 ●暗号について:  私も人並みにプログラマなので、有名どころの暗号アルゴリズムは一通りは把 握しているつもりで、実装で使ったこともあります。もちろん”使っただけ”で すが(笑)。  ただ、自分の中での暗号というと、Winny,Shareの暗号やソフトウェアプロテク ションのように、ソフトウェア本体を解析すれば解読できるような性質の方を真 っ先に想起してしまいますね。 ■Kenji Aiko ●Job: Programmer ●Web: http://ruffnex.oc.to/kenji/ ●Mail: kenji@ruffnex.oc.to ●Team(Group): N/A ●Comment:  10月25日、26日に「Black Hat Japan 2007」に行ってきました。たくさんのセ キュリティ関係の方々にお会いできて、とても充実した2日間を過ごせました。S peakerの方々も、とても優秀なエンジニアばかりでしたが、ほとんどが海外の方 で、日本語が通じなかったので質問しようにもできなかった…。つくづく英語の 重要さを痛感しました。  このようなセキュリティ関連のイベントは何かと刺激になるので、なるべくな ら参加した方がよいと思いますが、何分、値段が高いので、会社が参加費を出し てくれない…、というような方は、資料がネットに公開されるのを待つのもよい かもしれません。実際、技術的な内容だけならば、ネットに公開された資料だけ で十分だと思います。ただ、質問や会話などはできないので、やはり行けるなら 行った方がよいかもしれませんが…。 ●暗号について:  暗号については、研究レベルではまったく分かりませんが、実装レベルでは少 々組んだことがあります。ただ、知識としては、公開鍵暗号は「RSA」、共通鍵暗 号は「DES」と「RC4」くらい覚えておけば、まぁ大丈夫かなと(すごい適当かな)。  個人的には、暗号技術というのは少し興味があります。共通鍵暗号は、双方に 同じ鍵を持っていることで成り立つという当たり前の論理ですが、公開鍵暗号は、 暗号化に用いる鍵と復号に用いる鍵が異なるという、とても興味深い暗号理論な ので、どうやるんだろう? と興味がわきます。なので、個人的には、新しい公 開鍵暗号なんかが発明されると、とても面白そうだなぁと思います。 ■IPUSIRON ●Job: Student ●Web: http://akademeia.info/ ●Mail: ipusiron@gmail.com ●Team(Group): N/A ●Comment:  Black Hat Japan 2007において、データハウスのブースの手伝いに行ってきま した。かつてライブハウスの受け付け(会計・入退室管理)などの手伝いの経験 を活かそうと思っていたが、思っていたよりもうまくいかない点が多々あった。 まず、準備不足が挙げられる。会計7つ道具などをあらかじめ用意しておいて、臨 時のイベントのために備えておくべきだと認識した。また、お客さんへの対応や サービスなどにおいて反省すべき点もあった。例えば、外国人に対する準備(英 語による本の紹介とかコミュニケーションにおいて)も含まれる。隣にオライリ ーさんのブースがあり、色々参考になる点があったので、次回に活かしたいと思 う。  逆に思ったよりうまくいった点もあった。見本誌の用意、領収書の用意(初回 参加だと忘れがち)、セット販売のアイデアなど。  結果としては今回の経験を通じて、受け付けのやり方の学ぶことができたし、 セキュリティのイベントに参加している人たちと交流ができたことは有意義だっ たと思う。 ●暗号について:  暗号技術は単に暗号化だけでなく、署名・ハッシュ関数・認証・鍵共有・秘密 分散なども包括している。それぞれの分野は単独で存在するわけではなく、他の 分野と密接に絡み合っており、幅広く暗号技術を学習することは無駄ではない。 例えば、RSA暗号を署名化したRSA署名というものがあるが、これは簡単な攻撃に 対して脆弱である。そこで、ハッシュ関数の技術を組み込むことで、ある程度の 安全性を確保できてしまう。また、暗号以外の分野である純粋数学や応用数学な ども大きく関係している。そういった点から、暗号技術を学ぶことは大変だが、 やりがいのある学問だと思う。