CTF比賽的一道javascript題

今天中午的時候,舍友發來一道javascript題目給我看,要求調用下面的函數,輸出“Yay!!”

function test(arr) {
    var random_value = "ac1a39300ce7ee8b6cff8021fd7b0b5caf5bc1c316697bd8f22e00f9fab710d6b8dba23ca80f6d80ca697e7aa26fd5f6";
    var check = "20150303";

    if((arr === null || arr === undefined)) {
        console.log("arr is null or undefined.");
        return;
    }

    if(!arr.hasOwnProperty('length')) {
        console.log("length property is null or undefined.");
        return;
    }

    if(arr.length >= 0) {
        console.log("i think you're not geek. From now on, a GEEK Only!");
        return;
    }

    if(Object.getPrototypeOf(arr) !== Array.prototype) {
        console.log("Oh.... can you give me an array?");
        return;
    }

    var length = check.length;
    for(var i=0;i<length;i++) {
        arr[i] = random_value[Math.floor(Math.random() * random_value.length)];
    }

    for(i=0;i<length;i++) {
        if(arr[i] !== check[i]) {
            console.log("Umm... i think 2015/03/03 is so special day.\nso you must set random value to 20150303 :)");
            return;
        }
    }
    console.log("Yay!!");
}

粗略看了一下題目,嘗試了下

var arr=[];
test(arr);//i think you're not geek. From now on, a GEEK Only! 

輸出了i think you’re not geek. From now on, a GEEK Only! 赤裸裸地被作者鄙視了呀。可見,在第三個判斷if(arr.length >= 0)這裏就過不去了。一般來說,數組的length屬性都不能小於0的。強制給arr.length賦值會怎麼樣呢

arr.length=-1;
//Uncaught RangeError: Invalid array length 

果然拋出了錯誤,看來這個思路不行。換條路走
自己定義一個對象試試吧

var arr={length:-1};
test(arr);//Oh.... can you give me an array? 

第三個判斷是過去了,第四個if(Object.getPrototypeOf(arr) !== Array.prototype)沒過去呢,要求是數組哦。可是數組的length屬性又不能小於0。這下子好像出現了死循環。然後我谷歌了一下Object.getPrototypeOf()
官方定義:The Object.getPrototypeOf() method returns the prototype (i.e. the value of the internal [[Prototype]] property) of the specified object.

var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true

簡單的說,就是返回對象的prototype屬性
於是我就想,那就讓arr的prototype指向Array.prototype呀。試試

var arr={length:-1};
arr.prototype=Array.prototype;
test(arr);
//Oh.... can you give me an array? 

還是不行,第四關還是過不了,我自己輸出Object.getPrototypeOf(arr)和Array.prototype看看,結果爲

Object.getPrototypeOf(arr)
//Object {}
Array.prototype
//[]

用{}這樣形式生成的還是object對象,不是數組對象。怎麼辦,換個思路。於是想到另一種生成對象的方式

var MyArr=function(){
    this.length=-1;
}
MyArr.prototype=Array.prototype;
var arr=new MyArr();
test(arr);//Umm... i think 2015/03/03 is so special day.
//so you must set random value to 20150303 :) 

太棒了,第四關過了,nice。好興奮,勝利就在眼前。這種方式構造出來的對象,使用的是Array.prototype的原型鏈。相當於new Array(),但是constructor用的是我們MyArr自己定義的。(這裏我的理解解釋不知道是不是正確,如果有誤,歡迎指出修改)
接下來第五關

var random_value = "ac1a39300ce7ee8b6cff8021fd7b0b5caf5bc1c316697bd8f22e00f9fab710d6b8dba23ca80f6d80ca697e7aa26fd5f6";
var check = "20150303";
var length = check.length;
    for(var i=0;i<length;i++) {
        arr[i] = random_value[Math.floor(Math.random() * random_value.length)];
    }

    for(i=0;i<length;i++) {
        if(arr[i] !== check[i]) {
            console.log("Umm... i think 2015/03/03 is so special day.\nso you must set random value to 20150303 :)");
            return;
        }
    }

出題者要求arr數組的內容是“20150303”。然後函數中又給arr賦值,而且賦的是隨機值。我一看,出題者使的一定是個障眼法,讓我們去糾結那些隨機數怎麼搞出”20150303”。我們不能在這裏花時間,得換個思路。想了想,有沒有一種方法,可以讓對象的值不能被修改,這樣我們在函數外賦值好後,傳入函數中,就不會被修改了。這個思路似乎可行,立馬谷歌。
找到了Object.freeze();這個方法。我們來看一下官方定義

概述EDIT
Object.freeze() 方法可以凍結一個對象。凍結對象是指那些不能添加新的屬性,不能修改已有屬性的值,不能刪除已有屬性,以及不能修改已有屬性的可枚舉性、可配置性、可寫性的對象。也就是說,這個對象永遠是不可變的。該方法返回被凍結的對象。

語法EDIT Object.freeze(obj)

這樣問題似乎都解決了,試試

var MyArr=function(){
    this.length=-1;
}
MyArr.prototype=Array.prototype
var arr=new MyArr()
arr[0]='2';
arr[1]='0';
arr[2]='1';
arr[3]='5';
arr[4]='0';
arr[5]='3';
arr[6]='0';
arr[7]='3';
Object.freeze(arr);
test(arr);//Yay!! 

終於,功夫不負有心人,問題解決了。在這個猜測、驗證、搜索和思考過程中,得到了很多鍛鍊。每解決一步都給人成就感。感謝我舍友給我發來這一道題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章