jother編碼是我最開始想寫的內容,原因有兩點:1.原理比較簡單,不需要太多關于算法的知識。2.比較有趣,是在對javascript有了很深的理解之后催生的產物。如果你只需要知道jother編碼和解碼的方法,那么你可以直接跳過文章正文看結論部分。如果你想知道其中的原理那么你可以帶著這個疑問和我一起開始jother探索之旅。
在出發前,我們需要做一些準備工作,就如同去沙漠探險需要帶上充足的水和干糧一樣。有幾樣東西需要讀者準備一下:1.javascript匿名函數相關知識。2.遞歸思想。3.javascript變量類型基本知識。4.javascript一些基本函數。5.一顆好奇的心。
那么我們現在就出發吧。首先給出一個非官方的jother編碼定義:jother是一種運用于javascript語言中利用少量字符構造精簡的匿名函數方法對于字符串進行的編碼方式。其中少量字符包括:"!"、"+"、"("、")"、"["、"]"、"{"、"}"。只用這些字符就能完成對任意字符串的編碼,我們可以得出兩個結論:1.遞歸是不可或缺的。2.編碼壓縮率肯定是大于100%而且很高,也就是說編碼之后的長度比原長度大很多。
我們先來看一個匿名函數的例子:
#!javascript
[function(){
alert(1)
}()];
使用如果你把上面代碼保存到之間,然后把保存的文件以html后綴結尾,并在瀏覽器中打開,你會看到一個彈框,彈框的內容為"1"。如果你習慣用console.log而不喜歡alert也是可以的。 緊接著我們稍微修改一下原代碼: ?
#!javascript
alert([function(){
alert(1)
}()]);
? 保存一下,再次刷新頁面,我們可以看到先彈出了"1",后彈出了一個空白的框。
對于這個現象我們的解釋是:第一次執行了alert(1),第二次執行了alert(函數)。而函數是一個匿名函數(有返回值),所以就是彈出的就是函數本身的返回值(如果無返回值的函數則是undefined)。如果你注意到了彈框的先后次序,那很好,說明你特別細心,這個原因是由于函數入棧和出棧導致的,在alert函數調用了匿名函數,當然要等待匿名函數先返回,然后自己才能返回。通過這里我們需要注意的是,javascript在alert函數中是可以執行新的函數的,而不僅僅是輸出一個字符串。
下面我們再修改一下源代碼: ?
#!javascript
alert([]);
? 保存執行一下,你看到了什么?依然彈了一個空白的框框,這個就說明[]也是一個匿名函數,而且是最簡單的匿名函數,它也執行了。由于函數體都去掉了,所以導致僅僅留下了一個匿名函數的“空殼”。 ? 我們再接著修改源碼:
#!javascript
alert(+[]);
你發現了什么?彈出了0,不是嗎?因為我們的運算符“+”,對于無法顯示出來的空(void)的函數返回值進行了強制類型轉換,將其轉為了整形的“0”。 道生一,一生二,二生三,三生萬物。
我們只有“0”如何生“1”呢?不要急,看下面一個例子:
#!javascript
alert(![]);
? 運行以后,依然彈框了,彈出了一個false,false是什么?是bool(在javascript里通常是指"boolbean")運算符,為什么變成了false?是因為"!"對其進行了強制類型轉換。但是這又有什么用呢?不要急,我們用兩個"!"來試試:
#!javascript?
alert(!![]);
?
這次屏幕上彈出了"true",雖然仍然是bool類型,但是已經更加接近"1"了,如何把“true”變為“1”呢?不要看后面的內容,請大家思考一分鐘。 ? 我想大部分人都已經有答案了,讓我們來驗證一下: ?
#!javascript?
alert(+!![]);
對,就是這樣!使用加號進行強制類型轉換,將true轉換為"1"。有了1就好辦了,至少其他數字我們都可以表示了,下面來驗證一下你的想法:
#!javascript?
"+[]", //0
"+!![]", //1
"!![]+!![]", //2
"!![]+!![]+!![]", //3
"!![]+!![]+!![]+!![]", //4
"!![]+!![]+!![]+!![]+!![]", //5
"!![]+!![]+!![]+!![]+!![]+!![]", //6
"!![]+!![]+!![]+!![]+!![]+!![]+!![]", //7
"!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]", //8
"!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]" //9
它很酷,不是嗎? ? 只有數字還不行,我們需要字符,字符串。那么數字如何變為字符串呢?這里就有點文章可做了,我一開始想到的是ascii碼,但是如何將ascii碼轉換成字符呢?我們需要引入函數才行,但是能不能不引入新的函數?我們換一種思路來考慮這件事情:想辦法生成一個數組,然后用數組中已有的字符直接指定下標顯示。比如我們很容易就能產生的"true"、"false"。我們想要表示"a"的時候直接想辦法輸出一個"false",然后制定下標為"1"(注意這里"f"的下標為"0",所以"a"就是"1")不就可以了嗎?
我們來證實一下:
#!javascript??
alert((![])[+!![]]);
? 怎么樣?看到了a嗎?如果你回答:“看到了”,那么你肯定沒有認真去動手做。這里輸出的是“undefined”,這是為什么呢?因為![]表示的是false這個false是bool型的,當我們取一個bool型變量下標的時候javascript是不能允許的,所以這里給了一個undefined。那么我們如何想辦法將bool型轉為字符串呢?這里用到的是:"![]+[]"。
#!javascript??
alert(typeof(![]+[]));
看到了嗎?變成了string。這里就是說明了javascript在對bool類型和number類型做“+”運算的時候將其強制轉換為了string類型。大家也可以自己動手用alert(typeof(xxx))試著判斷一下之前提到的那些類型是否正確。
利用這個辦法,我們就可以表示"a"、"e"、"f"、"l"、"r"、"s"、"t"、"u"。當然還有一個很容易得到的字符串——"undefined",又可以豐富一下我們的字典。這樣,還是有很多字符無法表示,下面我們就來討論一種擴展,Object:
#!javascript???
alert({});
? 在javascript中"{}"表示一個最簡單的類,如果運行上面的代碼,會顯示"[object Object]",同樣這個object也是不能直接按數組下標獲取元素的,我們需要做一個轉換:({}+[])
#!javascript???
alert(({}+[])[+[]]);
? 這樣就可以取到第0個元素:"["。 ? 做這個擴展其實主要是為了得到一個重要的字符"o",因為我們后面要說的sort函數需要用到它。 ?
首先我們來補充一個前置概念——javascript匿名函數的原生形式
#!javascript
[]['sort']['constructor']('函數體')();
?這樣的構造可以執行任意javascript代碼。
為了吸引讀者眼球,這里先埋下伏筆:
利用jother編碼可以在不用字母和數字的情況執行任意js代碼,這個在XSS攻擊中是十分有用的,唯一的不足就是編碼太長了,如何縮短編碼,其實還是有些辦法的,而且結合真實的攻擊環境中可能允許輸入一些字符,我們就可以指替換部分代碼。比如代碼中對“alert”過濾,是否可以利用jother重新編碼函數,用匿名函數調用“alert”,在調用“alert”的時候僅替換alert中的r,這樣就形成了“ale”+xxx(jother)+“t”的形式。
下面就開始正式介紹如何利用jother編碼調用匿名函數,在第一篇內容中我們已經擁有了一些字符串,這些字符串中的每個字符我們都可以利用數組下標定位的方式取到,我們來看一下這些字符都有什么:“true”、“false”、“undefined”、“[object Object]”(注意這里有個很有用的字符空格)。我們來對比一下[]['sort']['constructor']1;我們還缺少什么?其實已經什么都不缺了。下面我們來構造這樣的一個形式,為了直觀我直接給出構造的結果:
#!javascript
[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!![]+!![]]+({}+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+(!![]+[])[+[]]+({}[[]]+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]])()
這個例子實際上等價于: ?
#!javascript
[]['sort']['constructor']('return location')()
? 注意這里是return后面的空格就是需要用前面我們提到的[object Object]來取到。
有了這個函數我們就可以獲取很多有用的字符了,比如在線的話,就可以取到"http(s)://" 這樣就有了新的字符“p”。
有了這個字符以后我們就可以利用escape和unescape函數組合出更多的字母以及特殊符合,例如利用escape(' ');得到“%20”,利用“%”和數字字母組合再unescape得到新的字符。
后面的事情就由你來自由發揮了。
當然構造一些字母的時候還有其他的技巧,比如構造出Infinity 其實是利用數字接近無窮大,原理就是想辦法達到 e的100000次方,我們在這里就不一一列出了,具體的思路可以參照附件中的jother.js,這是jother發明者寫的一段jother? encode的demo。
這里為了證明一開始提到的猜想我們給出一個不用任何字母和數字就能實現alert(1)的例子:
#!javascript
[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((![]+[])[+!![]]+(![]+[])[!![]+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]+[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+({}[[]]+[])[+[]]+({}[[]]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(![]+[])[!![]+!![]+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+([]+[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!![]+!![]]+({}+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+(!![]+[])[+[]]+({}[[]]+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]])())[!![]+!![]+!![]]+(!![]+[])[!![]+!![]+!![]])()([][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[!![]+!![]+!![]]+(![]+[])[!![]+!![]+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+([]+[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!![]+!![]]+({}+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+(!![]+[])[+[]]+({}[[]]+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]])())[!![]+!![]+!![]]+(!![]+[])[!![]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!![]+!![]+[])+(!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+(+!![]+[])+[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+({}[[]]+[])[+[]]+({}[[]]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(![]+[])[!![]+!![]+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+([]+[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!![]+!![]]+({}+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+(!![]+[])[+[]]+({}[[]]+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]])())[!![]+!![]+!![]]+(!![]+[])[!![]+!![]+!![]])()([][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(!![]+[])[!![]+!![]+!![]]+(![]+[])[!![]+!![]+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+([]+[][(![]+[])[!![]+!![]+!![]]+({}+[])[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][({}+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]]+(![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+[]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+({}+[])[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+(!![]+[])[!![]+!![]+!![]]+(!![]+[])[+[]]+({}[[]]+[])[+[]]+(!![]+[])[+!![]]+({}[[]]+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!![]+!![]]+({}+[])[+!![]]+({}+[])[!![]+!![]+!![]+!![]+!![]]+(![]+[])[+!![]]+(!![]+[])[+[]]+({}[[]]+[])[!![]+!![]+!![]+!![]+!![]]+({}+[])[+!![]]+({}[[]]+[])[+!![]])())[!![]+!![]+!![]]+(!![]+[])[!![]+!![]+!![]])()(({}+[])[+[]])[+[]]+(!![]+!![]+[])+(!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+!![]+[])))()
注意這里我們由于用到了對'('、')'的編碼,其實就要用到escape和unescape,所以要在http(s)://協議下面使用,如果是本地文件那么會取到"file://"導致無法正常執行。 ? 最后給出jother編碼和解碼的方法:
編碼:我想如果你仔細閱讀了全文,這個問題對你來說應該很簡單了。
解碼:直接使用
alert(xxx)、console(xxx)、document.write(xxx)即可(xxx為編碼內容)。
[1]: " "