小学生にも情報教育をば。


どうもみむらです。

いきなり質問ですが、下記の2つの文章の共通点をあげてください。

A.里の秋。

静かな静かな 里の秋
お背戸に木の実の 落ちる夜は
ああ 母さんとただ二人
栗の実 煮てます いろりばた

B.静かな湖畔

静かな湖畔の 森のかげから
もう起きちゃいかがと カッコが鳴く
カッコ カッコ
カッコ カッコ カッコ

 

はい、もうわかりましたよね。

こたえは、誰しもがわかるあれです。

 

 

 

 

 

 

 

 

 

そういえば、ちまたではプログラミングが中学生から行われるということで、
大騒ぎしていることもあるようです。

参照:新学習指導要領・生きる力 – 文部科学省。
http://www.mext.go.jp/a_menu/shotou/new-cs/youryou/chu/gika.htm

2-Dー(2) より:

プログラムによる計測・制御について,次の事項を指導する。

  • ア コンピュータを利用した計測・制御の基本的な仕組みを知ること。
  • イ 情報処理の手順を考え,簡単なプログラムが作成できること。

 

でもやっぱり難しいとおもいますよー。これ。

 

なら、入門言語は Python だ! ってのもありますが、
いあー、それなら私は C# だ!! なんて(個人的に好きなだけですすいません。

いえいえ、両方ともに英語という超高いハードルがありますね。
両方ともに独自の文法というものがあって。

だからといって、なでしこも日本語に似せていますが、
どうも日本語じゃない。

 

 

もう、皆さんおわかりですね? そうあなた大正解。

 

記事の文頭に書かれている文章の答えは

x86 プロセッサで実行可能なコード

です!

 

みなさん、あの2つを読んだらこれしか思い浮かばないですよね-。

だって、Shift JIS で 「静」って 0x90, 0xC3 ですしー。

 

 

・・・すいませんでした。

 

というわけで、とりあえず、すべてが実行可能ということではないのですが、
(もはや先頭の1字だけという超お粗末なあれですが)

NOP, RET となっていて、以降は実行されないので
エラーも出さずに実行「は」されます。

 

実行してみます:

(注:下記の方法は 32bit 版の Windows もしくは、 16bit 版の Windows / DOS のみ動作します。)


1.静かな湖畔を鼻歌交じりに陽気に(必要に応じて友人と輪唱しながら)入力します。

image

(この際、エンコードは Shift-JIS で。)

2.~.com で保存します。

image

3.実行します。

image

 

というわけで、何事もなかったかのように実行され、そして終了します。

 

IDA Pro で見てみても、
image

こんな感じで至って普通です。

 


でもまぁ、これじゃ x86_64 環境のひとが動かせないので、次はこんなコード。

image

char main[] = \"静かな湖畔の森のかげから\nもう起きちゃいかがとカッコが鳴く\nカッコカッコ\nカッコ\nカッコ\nカッコ\";

 

これは @phi16_ さんに、どうやら main は関数にしなくても動くらしいよとの情報を受けて、
やってみた結果、こんなておくれな状態になりましたごめんなさい。

 

とりあえずこれを実行してみると、さっきの com と同じように実行されます。
・・が、 Visual Studio 2010 + 64bit 版 Windows の組み合わせだとエラーで落ちます。

訂正:Visual Studio2010 だと NXCOMPAT を OFF にするとしあわせ(?)になれます。 (後述)

Visual Studio 2008 とか 2005 とか使うと、そのままで幸せになれます。

 

というわけで該当部分を見てみるとこんな感じ。

image

きわめてすてきなことになっています。

かっこ、かっこ、かっこかっこかっこ-! (Not Lisp)

 


でもこれ、結構調べてみるとおもしろいんです。

exe を生成する途中に出力されるオブジェクトファイル (*.obj) の中身を見てみますと、

image

普通はこのように、 「 .text 」セクションが存在しますが、先述のコードについては、

image

「 .text 」セクションは存在せず、その代わりに 「 .data 」セクションが存在します。

 

要はどういうことか。

image

これが obj ファイルの .data セクションを見た結果。

image

これが exe ファイルの .data セクションの先頭をちょっと見た結果。

 

要は、本来 .text セクションに書かれるべきプログラムコードが、
.data セクションに書かれてしまっていて、かつそれが実行できています。

 

(12/26 修正):

このあたりですが、普通に実行できてしまうのは非常によろしくないので、
Windows Vista 以降では動かないようになっています。
( @0xbadfca11 さんからツッコミを頂きました。 )

このあたりの問題となっているのは、 CPU の NX (NoExecute) 機能となります。
(Windows XP SP2 以降ではこの機能を含めた、バッファオーバーランなどからの攻撃を守る機能を DEP と読んでいるため、以降のでは DEP と呼ぶこととします。)

参考資料:
セキュリティに関するブリーフィング Visual C++ の防御機能でコードを保護する
http://msdn.microsoft.com/ja-jp/magazine/cc337897.aspx#S3

ハードウェアDEP機能の調査:CodeZine
http://codezine.jp/article/detail/136

それが関与していることを示すために無効にして動かしてみますと、
(リンカに /NXCompat:NO を与えてリンクさせる。)

image

という感じで普通に動きます。

 

この機能の本来の目的は、バッファ・オーバーフローによる攻撃への対策です。

たとえば、

#include <stdio.h>

void main(void){
	char s[10];

	gets(&s);
}

あまりにもあからさますぎますが、上記のようなコードでは、
入力される文字数を制限することができない上、9文字を超えて入力を行うと、
以降のデータは本来確保された場所を越えて書き込みが行われます。

C言語において、変数として確保されているものは、
コンピュータ上のメモリ領域において、特に明示的に分けられているということはなく、
一つの大きなものを区切って使っているに過ぎません。

 

たとえると、
小学校で、大きな白い紙にみんなで学級新聞を書いて作るようなイメージ。

個別に分けられている、個別の紙ではなく、
大きな紙に線を引いて 「ここからここまでが、みむらくんのばしょねー。」というような、
あんな感じでメモリを使ってます。

 

でも、自分の場所に、別の人が書き込めない訳じゃないですよね。
「ここ、ぼくのばしょー!」 と、ちょっとしたバトルになりやすいですが。

 

コンピュータでも同様のことがいえて、
先ほどの例では、 s のために 10文字分しか確保されていないので、それを超えると、
他人の場所に文字を書いていることになります。

(実際には、末尾には「ここまで!」というような記号 [NULL – 0x00] まぁ、日本語で言うところでいう区点「。」 
を書き込む必要があるので、9文字を突破すると他人の場所に文字を書き込むことになります。)

小学生なら、他の人の所に書き込んでも怒られるだけですが、
コンピュータはもっとずーっと厄介で、動作に必要な情報がいくつか書き込まれています。

その一つに、リターン・アドレスがありますが、
これは言うなれば、「本の何ページまで読んであった」ということを記したメモみたいなものです。

 

攻撃者はこの構造を悪用し、
危険なコードを書き込み、その上で、このメモ部分(リターン/アドレス)を上書きして、

「今まで危険なコードの部分の直前まで読んでいた」 ことにします。

コンピュータは愚直なもので、そこの部分に戻って、危険なコードを実行することとなります。

 

前置きが長くなりましたが、これを解決する方法の一つとして、
今回のサンプルで障害となっている、DEP となります。

・・NX-bit は CPU 側が持ち合わせている、メモリ上のデータが実行可能か不可能かということを示す
フラグのことを指しますが、DEP では、これのソフトウェア実装も存在します。

 

ひとまず、平たく言えば、
本来の場所を越えて実行させようとしたときに、実行を停止してしまうというのが仕掛けとなります。

以前の記事になりますが、
Cコード中にマシン語を埋め込んで実行する。

これで利用されている VirtualProtect 命令やそれと同等のAPIは、
すべてこの機能において、該当部分のメモリを実行可能にしたり、読み書きの属性を設定したり
という機能を提供しています。

Linux / UNIX がわかる方には、メモリ版の chmod と言えばわかりやすいでしょうか。

 

今回のサンプルの場合、
小学生の例を用いるならば、別の領域に書き込んだというわけでは必ずしもありませんが、

本来、プログラムコードが置かれるべき場所とは違う場所に記録されています。

先述の dumpbin の結果を見て頂ければわかるのですが、
プログラムコードは本来、 「.text 」セクションに書かれるべきなのですが、
「.data」セクションに書かれており、明らかに違うところに書かれているのがわかるかと思います。

今回の例では、明らかにおかしいところにあるコードを実行しようとしたため、
CPU側が異常を検出して動作を停止した、ということになります。

 

この動作を、高校までの学校のテストになぞらえるならば、
プログラムコード部分は試験問題。
DEPは試験監督といえるでしょうか。

試験問題を愚直に読んで、回答する分には全く問題ないのですが、
本来あり得ない場所、たとえば机の上とか、そういう所を読みに行って、問題を解いていたとしたら、
明らかにおかしいですよね。

というわけで、カンニングじゃないのこいつ! となったら、テストを中断(実行を停止)させて、
しかるべき所に報告(Windows ではユーザにエラーとして報告)する感じになります。

今回の例では、プログラムコードを机の上とか、机の上に偶然置かれていた紙とか、
そういう所に書いています。
そりゃ、怒られるわな、ということです。

で、 NXCompat を NO にするってなによ、といえば、
その通り試験監督はいらないよ、ということを試験要項に書くようなものです。
試験監督がいなければ、何やったって基本的にはおーけーです。ばれません。

 

ということで、まぁ、ある意味小学生にもというタイトルつけておきながら、
非常に教育上よろしくないですが、こんな感じのことをしているから、
Visual Studio 2010 では動かないよーということで。

(Visual Studio 2010 では NXCompat (試験監督) がデフォルトで ON (つけること)になっています。




というわけで、非常にわかりやすいプログラムですね。日本語ですし、読めますし。

でもそういえば、この記事の頭で出したコードが、
実際に動いてしまうというのは理解していただけたかと思いますが、

この2曲は、小学校の音楽の授業で取り上げられるものです。

 

つまりなにか。

 

英語を全く使わずに、それもネイティブできれいな日本語で、
プログラムが書けてしまう。

それも、小学生でも。
意味を(正しい意味かどうかは置いておいて)プログラミングの知識なしにとらえることができる。

わかりますか、画期的ですよね!

 

・・・すいませんでした。

 

 

そんな感じで、まぁまぁ。
生存報告と同時に、めーりーくりーすまーす。

 

P.S.

某 Tさこ さん ( @????sako ) とか、
某 はせGわ さん ( @hase??wayosuke ) とかのような、

ぶっとびの先人のみなさんのようなぶっ飛び方は一切できなかったのですが、
次回、ぶっ飛べるぜ! というのがあったらぶっ飛びたいなーと思う今日この頃です。


 

関連記事