質問: セキュリティの勉強をしている学生です。 いままではどのようにコードを書くかということしか考えていませんでしたが、オーバーフローなどの実践をするためにメモリを意識してC言語を書いています。 ひとまず書いたコードから ``` #include int main(){ int a; int buffer[10]; printf("a : %p\n", &a); printf("buffer : %p\n", buffer); return 0; } ``` ``` $ ./a.out a : 0x7fff57f35a08 buffer : 0x7fff57f35a10 ``` ``` #include int main(){ int buffer[10]; int b; printf("b : %p\n", &b); printf("buffer : %p\n", buffer); return 0; } ``` ``` $ ./a.out b : 0x7fff58186a08 buffer : 0x7fff58186a10 ``` 変数の宣言の順番を変えてそのアドレスを出力するだけのプログラムです。 自分が読んだサイトによると、ローカル変数はスタックに積まれるので、宣言の順番によってそれらのアドレスが変わるとなっており、そう理解しました。 が、Macで上記の2コードの出力を見ると、どちらも順番がおなじになっています。 ちなみにVagrantのCentOS7では、予想通り2つのコードで順番が変わりました。 どちらのOSでもgccを使いました。 コンパイル時はどちらもオプションなしです。 なぜMacではうまくいかないんでしょうか? 最適化のようなものが働いているんでしょうか?
回答: 最適化が働かなくても、どう割り当てられるかはコンパイラに依存します。初歩的な最適化でも条件が揃えば(レジスタで済むので)そもそもスタックに割り当てられないこともあります。 もしそのサイトが「宣言された順番に」と明言しているなら間違いです。宣言された順番に割り当てられることが保証されているのはたぶん構造体メンバだけです。 セキュリティの世界では攻撃者は移植性ではなくて、特定のターゲットを決めるでしょうから、そこはあまり重要ではないのでしょう。ターゲットがVisualStudioでビルドされているのなら、それにあわせればいいのです。 ところで64bitのMacでは、そのサイトの後半にある「戻りアドレスの書き換え」はうまくいきません。こうところも、自身の環境にあわせて調整する必要があります。メモリを意識してしていれば、修正は難しくはないと思います。