2014-04-23 55 views
0

我已經在js1k比賽中看到了一個演示,我很驚訝這個混淆算法。有人可以解釋它是如何工作的?我得到了混淆結果,但我無法理解它的工作方式(混淆算法) 這是什麼魔法? LOL這個javascript正則表達式混淆算法是如何工作的?

我已經提取這一點:

for(
    encoded_string = '... encoded string ...'; 
    g = /[^ -IM[-~]/.exec(encoded_string); 
){ 
    encoded_string = encoded_string.split(g).join(encoded_string.split(g).shift()); 
} 

// ... Use encoded_string to do what you want 

我想,也許關鍵是在正規表達式。

原代碼(http://js1k.com/2014-dragons/details/1854

如果你願意,你可以在這裏看到模糊的結果(http://jsbin.com/xeruqita/1/edit) 我已經添加了第一個VAR線。

回答

1

基本上,這個邏輯似乎從字符串中去掉一組字符的每個實例,並返回「清理過的」字符串。

我無法確定被刪除的字符組是什麼特別的(^ -IM[-~),但我可以引導您完成他們正在做的事情。 。 。

  • 設置一個for循環

    for(
    
  • 初始化循環變量

    encoded_string = '... encoded string ...'; 
    
  • 設置循環條件。 。 。注意:exec()回報null如果沒有匹配和null將評估爲false,停止循環

    g = /[^ -IM[-~]/.exec(encoded_string); 
    
  • 結束循環條件

    ) 
    
  • 這一步有多個部分。 。 。讓我去通過它在步驟

    { 
        encoded_string = encoded_string.split(g).join(encoded_string.split(g).shift()); 
    } 
    
  • 每個循環中

    ,採取EXEC(g)的結果,並使用它作爲一個輸入分割原始encoded_string(這是在兩個地方進行)。

    g是一個數組,但通過將它用作split()的輸入,它被轉換爲一個字符串。這樣做的結果是使用與字符串匹配的值(實際上,考慮到g的組成,實際上,請參閱此處的規格:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec)。

    通過使用匹配作爲「拆分器」,代碼本質上是刪除該匹配的所有實例,並保留所有剩餘字符的所有「塊」的數組(例如:如果匹配是c和字符串是abcde,分裂串將導致["ab", "de"]

  • 然後分割字符串,然後使用兩次:

    1. 它被用作一個加入源,來創建所產生的串

    2. 是「分裂陣」的第一個元素作爲「加入字符」

      所以,這第二部分讓我覺得必須有這樣的假設encoded_string值必須與一系列字符開始因爲如果是這樣,「拆分數組」的第一個字符將始終爲空字符串,這意味着join()的結果將是原始值encoded_string的值,並且所有匹配的字符都將被刪除。

      如果這種假設不成立,那麼在「拆分數組」的第一個位置將會出現一個實際字符,並且該字符將被插入到拆分數組中的所有元素之間,從而創建一個非常不同的結果字符串,從加入。

    讓我示範一些例子,以便更好地說明。 。 。

    1)我的假設是TRUE


    這使用一個小的輸入字符串,和該字符串的第一個字符相匹配的模式:

    encoded_string = "abcdeabc";

    g = /[abc]/.exec(encoded_string);

    對於第一個循環,

    • g會發現"a"的第一場比賽,
    • 「分割線」將是["", "bcde", "bc"]
    • 「加入人物」將是""
    • join()的結果將是"bcdebc"

    對於第二個循環,

    • g會發現"b"的第一場比賽,
    • 「分割線」 將是["", "cde", "c"]
    • 「加入人物」 將是""
    • join()的結果將是"cdec"

    對於第三循環,

    • g會發現"c"的第一場比賽,
    • 「分割線」 將是["", "de", ""]
    • 「加入人物」 將是""
    • join()的結果將是"de"

    將不會有更多的匹配,所以循環將在那裏結束,最後encoded string的值爲"de"

    2)我的假設是NOT TRUE


    此使用相同的輸入字符串如上述,但它使用一個圖案匹配該字符串的第一個字符:

    encoded_string = "abcdeabc";

    g = /[bcd]/.exec(encoded_string);

    對於第一個循環,

    • g會發現"b"的第一場比賽,
    • 「分割線」 將是["a", "cdea", "c"]
    • 「加入人物」 將是"a"
    • 並且join()的結果將是"aacdeaac"

    對於第二個循環,

    • g會發現"c"的第一場比賽,
    • 「分割線」 將是["aa", "deaa", ""]
    • 「加入人物」 將是"aa"
    • join()的結果將是"aaaadeaaaa"

    對於第三循環,

    • g會發現"d"的第一場比賽,
    • 「分割線」 將是["aaaa", "eaaaa"]
    • 「加入人物」 將是"aaaa"
    • join()的結果將是"aaaaaaaaeaaaa"

    將不會有更多的匹配,所以循環會在那裏結束,最終encoded string的值爲"aaaaaaaaeaaaa"

    雖然第二種方法可能可能是是作者想要做的,但我的錢是第一種方法成爲更可能的功能。 ;)


唷!這很多。希望有助於澄清!