メモリとレジスタとスタック #1

なんの話?

CTFに手を出すことにしました。現在、絶賛読書中の本がこれ↓

セキュリティコンテストチャレンジブック -CTFで学ぼう! 情報を守るための戦い方-

セキュリティコンテストチャレンジブック -CTFで学ぼう! 情報を守るための戦い方-


でも、書いてあることが理解できないことが多々あるので、メモをここに残していこうかと思っています。

今回は、バイナリ解析の中の静的解析で出てきたメモリ、レジスタ、スタック周りのことを確認していきたいと思います。
ちなみに、確認する本(積読たち)はこれ↓

コンピュータの構成と設計 第5版 上

コンピュータの構成と設計 第5版 上

コンピュータの構成と設計 第5版 下

コンピュータの構成と設計 第5版 下

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

プロセッサを支える技術  ??果てしなくスピードを追求する世界 (WEB+DB PRESS plus)

プロセッサを支える技術  ??果てしなくスピードを追求する世界 (WEB+DB PRESS plus)

おまえ誰よ

社会人2年目のペーペーです。
文系の大学を卒業して、情報系のことは全くわからずSIerに入社しました。
しかし、開発したいのにできない悶々とした日々を1年間過ごしたのち、Web系の会社でiOSエンジニアとして輪廻転成しました。
応用情報技術者まではSIerの時にとったので(資格補助目当て)、そこを入り口としてなんとかCTFに食らいついていければと思います。

本題

タイトルにもありますが、メモリ、レジスタ、スタック周りの理解を深めようと思います。CTF本の当該箇所は、バイナリ解析入門の中に出てくる静的解析の部分です。正直ここに辿り着くまでにも理解が甘いまま読み進めたところはありましたが、レジスタは大事って言ってたので、改めて復習しようと思います。

レジスタとは

以下、CTF本からの引用です。

まず、x86アーキテクチャの持つレジスタについて説明していきます。x86アーキテクチャには、EAX, ECX, EDX, EBX, ESI, EDIの6つの汎用レジスタEBP, ESP, EIPの特殊レジスタ、フラグレジスタのEFLAGSレジスタ、セグメントレジスタがあります。ESI, EDIの2つのレジスタは、まとめてインデックスレジスタと呼ばれる場合もあります。いずれのレジスタも、32bitのレジスタ長を持ちます。また、汎用レジスタのうち、EAX, ECX, EDX, EBXのレジスタの下位16bitは、それぞれAX, CX, DX, BXレジスタと呼ばれ、さらにそのうち上位8bitはAH, CH, DH, BHレジスタ、下位8bitはAL, CL, DL, BLレジスタと呼ばれます。ESI, EDIレジスタの下位16bitは、それぞれSI, DIレジスタと呼ばれます。

うんうん。なるほど。さっぱりわからん。この後に、それぞれのレジスタの使われ方が書いてありましたが、いまいちピンときませんでした。
補足として、応用情報技術者合格教本に載っていたレジスタの種類と役割を引用します。

プログラムカウンタ(PC) -> 実行する命令の格納アドレスをもつ。命令がフェッチされると自動的に+1される。
命令レジスタ(IR) -> 主記憶から読み出した命令を格納する。
汎用レジスタ(GR) -> データの一時的な保持や演算結果の格納など,使い方を自由に決められる。
スタックポインタ(SP) -> スタックの先頭アドレスを保持。
グローバルポインタ(GP) -> 静的領域の先頭アドレスを保持。
インデックス(指標)レジスタ -> アドレス修飾に使われる。
ベース(基底)レジスタ -> プログラムの先頭アドレスを保持

いろんな役割があることはわかりました。てか知ってました。応用は持ってますから。(じゃあ、何でレジスタのこと知らないんだってことに気づく勘の良いガキは嫌いだよ・・・)
でも、役割が云々じゃなくて、その役割がどう機能するんだってところを知りたいんだーーーという欲望のままにパタヘネ(上)より。

高水準言語で記述したプログラムとは異なり,算術命令のオペランドには制約がある.算術命令のオペランドは,ハードウェアに直接組み込まれている特殊な記憶領域の中から選んで使用しなければならない.その領域をレジスタ(register)と呼ぶ.

またパタヘネ(上)より、

レジスタ数には限りがある.レジスタはハードウェアを構成する基本要素であり,プログラマ側からも見える.MIPSアーキテクチャにおいては,レジスタ長は32ビットである.32ビットを一まとめにしたものは頻繁に使用されるので,MIPSアーキテクチャではそれを1つの単位として(word)と呼んでいる.

さらにここで、Google先生で「レジスタ_キャッシュ_メモリ」で検索してみると、良い記事が見つかりました。下記のブログ内で出てくる図が非常にわかりやすかったです。

malloc.hatenablog.jp

(汎用レジスタは)頻繁に算術命令で使う値を格納しておくプロセッサにめっちゃ近い記憶装置ってことなんですね。パタヘネの中でもこのようにありました。

プログラムでの変数をレジスタに割付けるのは,コンパイラの仕事である.先の例題のステートメントを再び取り上げよう.
f =( g + h )-( i + j );
変数のf,g,h,i,jをそれぞれレジスタの$s0,$s1,$s2,$s3,$s4に割付けるとする.上記のステートメントコンパイルした結果のMIPSアプリケーション・コードはどうなるか.

コンパイル結果は次のようになる.
add $t0,$s1,$s2 # g + h の結果をレジスタ$t0に代入
add $t1,$s3,$s4 # i + j の結果をレジスタ$t1に代入
sub $s0,$t0,$t1 # $t0 - $t1 つまり(g + h)-(i + j)を f に代入

コンパイルされたプログラムは前の例題とよく似ている.ただし,変数を上で示したレジスタ名に置き換えたことと,2つの一時レジスタ$t0と$t1を付け加えたことが異なる.この一時レジスタは前の例題の一時変数に相当する.

こうして見ると、あぁなるほど。確かに算術計算で使うための一時変数を格納している。応用情報の参考書からの転載を見ると役割はわかりますが、実際の動きまではよくわからないですからね。アセンブリでどう書かれているのかを知るのは非常に有効でした。

でも、正直ここまで読んで、

レジスタのことわかります (`・ω・´)キリッ 」

と言える理解にはなりませんでした。(わかる人はわかるのかも知れないが、わからないものはわからない)

まとめ

プログラムだけを見てるとマシンがどうやって実行してるのかは見えにくくなりますね。ある程度レジスタについてイメージがついてきたところですが、ここで一旦区切りとします。
今回使った本はパタヘネの上巻と応用情報の参考書だけです。ちょっと長くなりそうだったので、他の書籍で取り上げられている内容は次回以降にしていきたいと思います。(5/22 02:26:20…..もう眠い。)


追わない追記

最近、Pythonに目覚めまして、ひたすら勉強してるんですが、めちゃくちゃ面白いですね。面白いのはPythonというよりか、統計学機械学習ディープラーニングが。
話し変わるんですけど、料理ができないので家にフライパンも包丁もないんですね。電子レンジだけで生きてます。もうね、電子レンジすごい好きになりましたね。ほんと大好きです。ただ、サンマの缶詰を温めると必ず爆発するのはほんとどうにかしたい。缶詰から皿に移してるのに爆発するのは、電子レンジじゃなくてサンマの強い意思を感じるよ。。。
ということだから、AEONに売っているものを学習して、爆発しない献立を考える人工知能を作りたい。