まどろみの思考空間スマートフォン用の表示で見るスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。読者です読者をやめる読者になる読者になるまどろみの思考空間2011-12-18チートツール(メモリエディタ)でメモリ内を覗いたり書き換えたりして遊んでみたCメモリエディタプログラミングプログラミングをしていても、イマイチポインタやメモリ構造、オーバーフローが理解できないし、イメージしづらいてってのがありました。メモリをのぞいてみようということで。それが手軽にできるツールがメモリエディタです。普段はゲームのチートとかによく使われますね。これから書くようなことを理解すればチートコードの意味も見えてくるかも。あ、エディタとしては「うさみみハリケーン」を利用させていただきました。こちらからダウンロードできます。→http://www.vector.co.jp/soft/win95/prog/se375830.htmlなんかいろいろと使い方があるみたいですが、ここではそんなに複雑なことをしません。指定アドレスを探して書き換えるだけです。自分で作ったプログラムをいじるだけなんで変数のアドレスは自分で表示させることができますしね。ことで今回利用するプログラムのほうは以下のようになります。あ、ぼくの環境はBCCでコンパイルして書き換えたりしました。したら他の環境では違う結果になるかもしれません。そこらへんはご了承ください。0;}とりあえず、このプログラムを実行してみてください。次にうさみみハリケーンを開いて対象のプロセス(実行したプログラム)を選択します。ぼくはanalysis.exeという実行ファイルを作ったのでそれを選択しました。これで好きなようにいじり放題ですね。いう風に並んでいるか確認してみます。変数aのアドレスは0x0012FF50なのでそこから見てみましょうか。アドレスを指定」をクリック、新しいウィンドウが開くのでアドレス(僕の環境では0012FF50)を入れてアドレス変更で移動。すると確かにaの変数のところに初期値の3が格納されていることがわかります。(下図)頭では分かっていたんですが、やっぱり目に見えると感動です。ついでに別の視点からも見てみます。プログラム上では初期化した変数はa→bの順でした。メモリを見るとbのほうが前、aのほうが後に配置されています。アドレスだけを見てもそれはわかりますが、メモリエディタ上でみるとbのほうに格納されている6が見えてよりわかりやすいと思います。本に書かれているようにやっぱりintは4byteってのも確認できます。00」ってのが見えます。最初これはなんでかな?と思いました。50」のはずなのに...ここにCPUの罠が。僕の使っているCPUはintel製なのでリトルエンディアン。格納されている値を逆に読んでみると見事に一致しました。いうトリックだったんですね。気づいてしまえば簡単ですけど気づかないとはまります。ちなみにこれに気づいた理由は「関数ポインタを続けて宣言しているのでメモリ上に連続して並んでいるはず」って過程で見てそのアドレス差をみると4だけずれている。00ってのもリトルエンディアンで配置されてましたね。いや、勉強になりました。見ているだけじゃ面白くないです。書き換えてみましょう。aのアドレス(0x0012FF40)のところを03から08ににしてみます。それで、プロンプト(実行しているソフト)のほうに戻り適当にaとでもいれてEnterですすめると...見事に表示されるのが8に変わっています。プログラムは変数の値をやはりメモリから呼び出しているってのが確認できます。↓これがチートの正体だったり。チートコードってのは特殊なコードでもなんでもなくて単なる変数のアドレスだったわけですね。それで、そこの値を書き換えているだけなのです。次はオーバーフローの実験。scanfは危険だから使うなと言われます。このプログラムは意図して危険さが目に見えるように作っているわけですが。dangerっていういかにも脆弱性を含んでいそうな変数のアドレスはプロンプトに表示されているように0012FF4A。その2byte先のアドレスを計算してみると...bの変数のアドレスですね。メモリエディタを見ると恐ろしいことにそこにはしっかりとbの値「6」が格納されています。ここでdangerに2byte以上の値を書き込むとどうなるのでしょうか?試してみましょう。僕はabcdefgと入れてみました。bの値がおかしなことになっています。何が?ってことでメモリエディタをのぞいてみましょう。入力後このがぞうをみてわかるように連続した61〜67までの値がdangerの範囲を突き抜けてbの範囲まで入ってしまっていますね。これがbがおかしくなった原因だと思います。今回は意図的に組み込んだためわかりやすく出ますが、ふつうはこんなにわかりやすくは出ないはずなので...考えるだけで恐ろしいバグが組み込まれそうです。ところで、ちょっと本題とはそれるのですがdangerの内容は入力したとおりに正確に表示されています。これはなんででしょうか?おそらくprintfの仕様で%sはポインタを進めていってNULLまで読みだすという仕様になっているからだと思います。最後が結構面白いもの。関数ポインタに格納されている関数を書き換えてしまいます。funcのアドレスは0x0012FF44なのでそこを見てみましょう。ここには先ほども見たようにfoo関数のポインタが入っています。これをbar関数のアドレスに書き換えてみましょう。最初の50を60に変えるだけです。それでプロンプトに戻り進めてみると...明らかに危なげな文字列が表示されています。bar関数が呼び出されてしまったわけですね。これとさっきのオーバーフローを利用すると好きな関数が実行できたりするかも...とかほんとはやりたかったんですが、勉強不足でできませんでした。理論上はできる気がします。と今回の記事はここで終了なんですが、関数の中身を書き換えたりなんてこともできそうです。Blog|ブログを報告する。