Yeniden tanımlamanın yanı sıra console._commandLineAPI
, geliştirici konsoluna girilen ifadelerin değerlendirilmesini önlemek veya değiştirmek için WebKit tarayıcılarında InjectedScriptHost'a girmenin başka yolları da vardır.
Düzenle:
Chrome bunu geçmiş bir sürümde düzeltti. - o zaman gist'i oluşturduğum için Şubat 2015'ten önce olmalıydı
İşte başka bir olasılık. Bu kez doğrudan içine, bir seviye yukarıda, oltaya InjectedScript
yerine InjectedScriptHost
önceki sürüm aksine.
Hangi tür hoş, çünkü InjectedScript._evaluateAndWrap
güvenmek yerine doğrudan maymun yaması olabilir, çünkü InjectedScriptHost.evaluate
ne olması gerektiği üzerinde daha ince kontrol sağlar.
Bir başka ilginç şey, bir ifade değerlendirildiğinde dahili sonucu kesebileceğimiz ve bunu normal davranış yerine kullanıcıya geri döndürebileceğimizdir .
İşte tam olarak bunu yapan kod, kullanıcı konsolda bir şey değerlendirdiğinde iç sonucu döndürür.
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);
Biraz ayrıntılı, ama içine bazı yorumlar koyduğumu düşündüm
Normalde, örneğin bir kullanıcı [1,2,3,4]
aşağıdaki çıktıyı beklediğinizi değerlendirirse :
InjectedScript._evaluateAndWrap
Aynı ifadeyi değerlendiren maymun-denemeden sonra aşağıdaki çıktıyı verir:
Gördüğünüz gibi, çıktıyı gösteren küçük sol ok hala orada, ama bu sefer bir nesne alıyoruz. İfadenin sonucu, dizi [1,2,3,4]
, açıklanan tüm özellikleri ile bir nesne olarak temsil edilir.
Hata oluşturanlar da dahil olmak üzere bu ifadeyi ve bu ifadeyi değerlendirmeye çalışmanızı öneririm. Oldukça ilginç.
Ayrıca, is
- InjectedScriptHost
- nesnesine bir göz atın . Müfettişin içleriyle oynamak ve biraz içgörü elde etmek için bazı yöntemler sunar.
Tabii ki, tüm bu bilgileri ele geçirebilir ve yine de orijinal sonucu kullanıcıya geri döndürebilirsiniz.
Diğer yoldaki return deyimini console.log (res)
aşağıdaki a ile değiştirin return res
. Sonra aşağıdaki ile sonuçlanır.
Düzenleme Sonu
Bu, Google tarafından düzeltilen önceki sürümdür. Dolayısıyla artık olası bir yol değil.
Bunlardan biri Function.prototype.call
Chrome, girilen ifadeyi call
eval işlevini aşağıdaki InjectedScriptHost
gibi kullanarak değerlendirir:thisArg
var result = evalFunction.call(object, expression);
Bu göz önüne alındığında thisArg
, call
varlığını dinleyebilir evaluate
ve ilk argümana referans alabilirsiniz ( 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);
}
};
}
Örneğin, değerlendirmenin reddedildiğine dair bir hata atabilirsiniz.
Girilen ifadenin işleve geçmeden önce bir CoffeeScript derleyicisine aktarıldığı
bir örnek aşağıdadır evaluate
.