Selain mendefinisikan ulang console._commandLineAPI
, ada beberapa cara lain untuk membobol InjectedScriptHost di browser WebKit, untuk mencegah atau mengubah evaluasi ekspresi yang dimasukkan ke konsol pengembang.
Edit:
Chrome telah memperbaikinya dalam rilis sebelumnya. - yang pasti sebelum Februari 2015, saat saya menciptakan intinya pada saat itu
Jadi, inilah kemungkinan lain. Kali ini kami menghubungkan, level di atas, langsung ke InjectedScript
daripada InjectedScriptHost
sebagai lawan dari versi sebelumnya.
Yang agak menyenangkan, karena Anda bisa langsung menambal monyet InjectedScript._evaluateAndWrap
daripada harus bergantung InjectedScriptHost.evaluate
karena itu memberi Anda kontrol lebih baik atas apa yang harus terjadi.
Hal lain yang cukup menarik adalah, bahwa kita dapat mencegat hasil internal ketika ekspresi dievaluasi dan mengembalikannya kepada pengguna alih-alih perilaku normal.
Berikut adalah kode, yang melakukan hal itu, mengembalikan hasil internal ketika pengguna mengevaluasi sesuatu di konsol.
var is;
Object.defineProperty(Object.prototype,"_lastResult",{
get:function(){
return this._lR;
},
set:function(v){
if (typeof this._commandLineAPIImpl=="object") is=this;
this._lR=v;
}
});
setTimeout(function(){
var ev=is._evaluateAndWrap;
is._evaluateAndWrap=function(){
var res=ev.apply(is,arguments);
console.log();
if (arguments[2]==="completion") {
//This is the path you end up when a user types in the console and autocompletion get's evaluated
//Chrome expects a wrapped result to be returned from evaluateAndWrap.
//You can use `ev` to generate an object yourself.
//In case of the autocompletion chrome exptects an wrapped object with the properties that can be autocompleted. e.g.;
//{iGetAutoCompleted: true}
//You would then go and return that object wrapped, like
//return ev.call (is, '', '({test:true})', 'completion', true, false, true);
//Would make `test` pop up for every autocompletion.
//Note that syntax as well as every Object.prototype property get's added to that list later,
//so you won't be able to exclude things like `while` from the autocompletion list,
//unless you wou'd find a way to rewrite the getCompletions function.
//
return res; //Return the autocompletion result. If you want to break that, return nothing or an empty object
} else {
//This is the path where you end up when a user actually presses enter to evaluate an expression.
//In order to return anything as normal evaluation output, you have to return a wrapped object.
//In this case, we want to return the generated remote object.
//Since this is already a wrapped object it would be converted if we directly return it. Hence,
//`return result` would actually replicate the very normal behaviour as the result is converted.
//to output what's actually in the remote object, we have to stringify it and `evaluateAndWrap` that object again.`
//This is quite interesting;
return ev.call (is, null, '(' + JSON.stringify (res) + ')', "console", true, false, true)
}
};
},0);
Ini agak bertele-tele, tapi saya pikir saya menaruh beberapa komentar di dalamnya
Jadi biasanya, jika pengguna, misalnya, mengevaluasi [1,2,3,4]
Anda akan mengharapkan output berikut:
Setelah monkeypatching InjectedScript._evaluateAndWrap
mengevaluasi ekspresi yang sama, berikan output berikut:
Seperti yang Anda lihat panah kiri-kecil, yang menunjukkan keluaran, masih ada di sana, tapi kali ini kita mendapatkan objek. Di mana hasil dari ekspresi, array [1,2,3,4]
diwakili sebagai objek dengan semua propertinya dijelaskan.
Saya sarankan mencoba untuk mengevaluasi ekspresi ini dan itu, termasuk yang menghasilkan kesalahan. Cukup menarik.
Selain itu, kita lihat di is
- InjectedScriptHost
- objek. Ini memberikan beberapa metode untuk bermain dan mendapatkan sedikit wawasan tentang internal inspektur.
Tentu saja, Anda dapat mencegat semua informasi itu dan tetap mengembalikan hasil asli kepada pengguna.
Cukup ganti pernyataan pengembalian di jalur lain dengan console.log (res)
mengikuti a return res
. Maka Anda akan berakhir dengan yang berikut ini.
Akhir dari Edit
Ini adalah versi sebelumnya yang diperbaiki oleh Google. Karenanya bukan cara yang mungkin lagi.
Salah satunya adalah mengaitkan ke Function.prototype.call
Chrome mengevaluasi ekspresi yang dimasukkan dengan call
menggunakan fungsi eval-nya dengan InjectedScriptHost
asthisArg
var result = evalFunction.call(object, expression);
Mengingat ini, Anda dapat mendengarkan untuk thisArg
dari call
makhluk evaluate
dan mendapatkan referensi ke argumen pertama ( InjectedScriptHost
)
if (window.URL) {
var ish, _call = Function.prototype.call;
Function.prototype.call = function () { //Could be wrapped in a setter for _commandLineAPI, to redefine only when the user started typing.
if (arguments.length > 0 && this.name === "evaluate" && arguments [0].constructor.name === "InjectedScriptHost") { //If thisArg is the evaluate function and the arg0 is the ISH
ish = arguments[0];
ish.evaluate = function (e) { //Redefine the evaluation behaviour
throw new Error ('Rejected evaluation of: \n\'' + e.split ('\n').slice(1,-1).join ("\n") + '\'');
};
Function.prototype.call = _call; //Reset the Function.prototype.call
return _call.apply(this, arguments);
}
};
}
Anda dapat misalnya membuat kesalahan, bahwa evaluasi ditolak.
Berikut adalah contoh di mana ekspresi yang dimasukkan akan diteruskan ke kompiler CoffeeScript sebelum meneruskannya ke evaluate
fungsi.