Basic

Hackerがフェイク関数を作るために、Overrideする可能性があるのは、以下の3つであるように思われる。
(a1) document (a2) document.write (a3) document.write.toString
しかし、実際(a1) はありえない。なぜなら、 window.documentはread-onlyであり、新しい値を指定できないからである。 以下のコマンドを実行した場合、
"use strict"; window.document=999;
以下のようなエラーメッセージが出る。
Uncaught TypeError: Cannot set property document of #<Window> which has only a getter at basic.php:95:16
You can see it in console...
さて、HackerがOverrideする可能性があるのは、以下の2つに絞られた。
(b1) document.write (b2) document.write.toString
(b1) は base 関数も含めると、次の3つの可能性がある。
(b1.1) document.write (b1.2) document.__proto__.write (b1.3) document.__proto__.__proto__.write
'write' という property を持つかどうか、以下に列記する。
document.hasOwnProperty('write') => false document.__proto__.hasOwnProperty('write') => false document.__proto__.__proto__.hasOwnProperty('write') => true
※ 上記に3つに関する説明は hasOwnProperty.php を参照。 これら3つは、 hasOwnPropertyを用いて (false,false,true) を確認しなければいけない。もし確認できなければ、Hackされていると結論づけられる。 次に(b2)だが、これは base 関数も含めると、次の2つの可能性がある。
(b2.1) document.write.toString (b2.2) document.write.__proto__.toString
'toString' という property を持つかどうか、以下に列記する。
document.write.hasOwnProperty('toString') => false document.write.__proto__.hasOwnProperty('toString') => true
※ 上記に2つに関する説明は hasOwnProperty.php を参照。 これら2つは、 hasOwnPropertyを用いて (false,true) を確認しなければいけない。もし確認できなければ、Hackされていると結論づけられる。
さて、以下の関数では、hasOwnProperty が false を返すのを確認しなければいけないことを理解した。
(b1.1) document.write (b1.2) document.__proto__.write (b2.1) document.write.toString
以下の関数では、hasOwnProperty は true を返すわけだが、それを確認しただけでは不十分である。
(b1.3) document.__proto__.__proto__.write (b2.2) document.write.__proto__.toString
これらの関数では、isNativeCode が true を返さなければいけない。 isNativeCode の詳細に関しては別のページに譲るが、isNativeCode は内部で、toString() を用いるので 以下の関数が重要になる。
(c1) document.__proto__.__proto__.write.toString (c2) document.write.__proto__.toString.toString
Hackerは、isNativeCode を誤動作させるために、上記の2つの関数を以下のように Override しようとする。
document.__proto__.__proto__.write.toString=function(){ return "function write() { [native code] }"; };
document.write.__proto__.toString.toString=function(){ return "function toString() { [native code] }"; };
しかし、実際、この2つの関数を別々に Override することはできないのである。 ※ その説明は toString.php を参照。 結局、Hacker は、ひとつの関数で上記の2つを Override しなければいけなくなる。 この Override を阻止するのに有効な手立ては、ダミーで document.write.toString() を 何回か呼び出すのである。
(1) document.write.toString() を n 回実行。 (2) document.write が native code であるかチェックするために、 document.write.toString() を isNativeCode 内で実行。 (3) document.write.toString が native code であるかチェックするために、 document.write.toString.toString() を isNativeCode 内で実行。 (4) document.write.toString() を m 回実行。
上記のように document.write.toString() を実行した場合、ハッカーは (n+1)回まで、"function write() { [native code] }" を返して、 それ以降は、"function toString() { [native code] }" を返さなければいけない。 内部のコードを見ることなく、この切る変えを行うのは、かなり難しい。