C言語ってきもい

仮に、こんなコードがあったとします。


//a.c
int a(void){
  return 1;
}
int b(void){
  return a();
}

//b.c
int c(void){
  return a();
}

このとき、b()==c()が真にならない可能性はあるか? というと、あります。
具体的にはx86系CPU上で*(int*)a = 0xCCC3C033;とコードを書き、その上で最適化を最高にしてコンパイルするなど。
(実際にはメモリーに書き込み属性付与など色々必要です)

なぜかというと、関数bは関数aの中身まで見えており、なおかつインライン展開した方がコストが低いと判るのでインライン展開し、実際に関数aにはアクセスしません。
ですが、関数cは関数aの存在は知っていても別ファイルなのでインライン展開できず、関数aにアクセスする機械語を生成します。
そこで、直接関数aをフックするなどして動作を変更した場合、関数cのみ動作が代わり、b()==c()は成立しなくなるというわけです。

これは完全にコンパイラ依存な上(関数cにもインライン展開されたり、関数bもインライン展開されなかったり)、まったく持って役に立たない知識ですが、一応手軽な改造対策に使えます。
たとえば、それなりに重要で、まず改造の標的となり得る関数を上記手法で別々に分けます。
そうすると、完全に同じ動作をする別の関数となるため、両者の結果を比較して同一であることを検証するようにすることで、簡易的かつ信頼性には欠けますが改造対策となります(絶対に誰もやらないだろうけど)

ただ思いついたことをだらだら書いていたらわけがわからなくなったが気にしない!

コメント / トラックバック2件

  1. C言語ってきもい?

    たまには他所さまのプログラミング記事についても言及してみることにしましょう。今回取り上げるのは、ブログ「赤の他人」の「C言語ってきもい」です。ここでは、下記のようなコー…

  2. 中の人 より:

    省略しすぎた上に読ませる気の無い文章でしたので色々誤解を招いてしまったようで……
    そういった意味合いを持った文章ではないという事だけ言っておきます。

コメントをどうぞ