jother編碼之謎

wyzsk發表於2020-08-19
作者: do9gy · 2014/12/26 12:00

0x00 字元


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函式需要用到它。  

0x01 函式


首先我們來補充一個前置概念——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]: " "

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章