@@ -9,102 +9,95 @@ internal static class Decipherer
99 {
1010 public static string DecipherWithVersion ( string cipher , string cipherVersion )
1111 {
12- // NB: We intentionally don't cache the operations as it seems that the same operation
13- // doesn't work if the URL below isn't called
14-
1512 string jsUrl = string . Format ( "http://s.ytimg.com/yts/jsbin/html5player-{0}.js" , cipherVersion ) ;
1613 string js = HttpHelper . DownloadString ( jsUrl ) ;
1714
1815 //Find "C" in this: var A = B.sig||C (B.s)
1916 string functNamePattern = @"\.sig\s*\|\|(\w+)\(" ;
2017 var funcName = Regex . Match ( js , functNamePattern ) . Groups [ 1 ] . Value ;
21-
22- //Match nested angle braces
23- string funcBodyPattern = @"(?<brace>{([^{}]| ?(brace))*})" ;
24- //Match the function function_name (that has one argument)
18+ string funcBodyPattern = @"(?<brace>{([^{}]| ?(brace))*})" ; //Match nested angle braces
2519 string funcPattern = string . Format ( @"{0}\(\w+\){1}" , funcName , funcBodyPattern ) ;
26- var funcBody = Regex . Match ( js , funcPattern ) . Groups [ "brace" ] . Value ;
27- var lines = funcBody . Split ( ';' ) ;
20+ var funcBody = Regex . Match ( js , funcPattern ) . Groups [ "brace" ] . Value ; //Entire sig function
21+ var lines = funcBody . Split ( ';' ) ; //Each line in sig function
2822
23+ string id_Reverse = "" , id_Slice = "" , id_CharSwap = "" ; //Hold name for each cipher method
24+ string functionIdentifier = "" ;
2925 string operations = "" ;
3026
3127
32- //CYNAO - 07/08/2014, Test Fix
33- /* The previous algoritms used a.splice(), where the decipher used the method (.splice()), however it seems the new algoritm
34- * renames the method to random but unique characters (example ab.dc() = splice). This code determines what each method code is,
35- * as it is defined once using the original name.
36- */
37- string id_Reverse = "" , id_Slice = "" , id_CharSwap = "" ; //Holds the new method name for each.
38- string functionIdentifier = "" ;
28+ foreach ( var line in lines . Skip ( 1 ) . Take ( lines . Length - 2 ) ) //Matchs the funcBody with each cipher method. Only runs till all three are defined.
29+ {
30+ if ( ! string . IsNullOrEmpty ( id_Reverse ) && ! string . IsNullOrEmpty ( id_Slice ) &&
31+ ! string . IsNullOrEmpty ( id_CharSwap ) )
32+ {
33+ break ; //Break loop if all three cipher methods are defined
34+ }
3935
40- string functIDPattern = @"\w+:\bfunction\b" ; //Define as "NB:function(a,b)" where nb can be the three ciphers
41- var funcID = Regex . Match ( js , functIDPattern ) . Groups [ 1 ] . Value ;
36+ functionIdentifier = getFunctionFromLine ( line ) ;
37+ string re_Reverse = string . Format ( @"{0}:\bfunction\b\(\w+\)" , functionIdentifier ) ; //Regex for reverse (one parameter)
38+ string re_Slice = string . Format ( @"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\." , functionIdentifier ) ; //Regex for slice (return or not)
39+ string re_Swap = string . Format ( @"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b" , functionIdentifier ) ; //Regex for the char swap.
4240
43- ///CODE ADDITION: Get the three ciphers by finding the definition
44- foreach ( var line in lines . Skip ( 1 ) . Take ( lines . Length - 2 ) )
45- {
46- string newVarName ; //Previous algoritms used to be just "a." - now stores temp var name as its uneccessary
47- int locOfDot , locOfBracket , functionIDLength ;
48- locOfDot = line . IndexOf ( "." ) ; // NB.AC( - gets location of the dot.
49- locOfBracket = line . IndexOf ( "(" ) ; //NB.AC( - gets location of the bracet
50- functionIDLength = locOfBracket - ( locOfDot + 1 ) ;
51- newVarName = line . Substring ( 0 , locOfDot ) ;
52- functionIdentifier = line . Substring ( locOfDot + 1 , functionIDLength ) ; //leaving us with the function AC
53-
54- //This is what the definitions currently look like, could be changed so the regex needs improving. Messy fix.
55- string tempReverse = string . Format ( @"{0}:\bfunction\b\(\w+\)" , functionIdentifier ) ; //Reverse only one that doesnt have two parameters
56- string tempSlice = string . Format ( @"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\." , functionIdentifier ) ; //Regex for slice (return or not)
57- string tempCharSwap = string . Format ( @"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b" , functionIdentifier ) ; //Regex for the char swap.
58-
5941 Match me ;
60- if ( ( me = Regex . Match ( js , tempReverse ) ) . Success )
61- { id_Reverse = functionIdentifier ; } //If def matched the regex for reverse then the current function is a defined as the reverse cipher
42+ if ( ( me = Regex . Match ( js , re_Reverse ) ) . Success )
43+ {
44+ id_Reverse = functionIdentifier ; //If def matched the regex for reverse then the current function is a defined as the reverse
45+ }
6246
63- if ( ( me = Regex . Match ( js , tempSlice ) ) . Success )
64- { id_Slice = functionIdentifier ; } //If def matched the regex for slice then the current function is defined as the slice cipher.
47+ if ( ( me = Regex . Match ( js , re_Slice ) ) . Success )
48+ {
49+ id_Slice = functionIdentifier ; //If def matched the regex for slice then the current function is defined as the slice.
50+ }
6551
66- if ( ( me = Regex . Match ( js , tempCharSwap ) ) . Success )
67- { id_CharSwap = functionIdentifier ; } //If def matched the regex for charSwap then the current function is defined as swap cipher.
52+ if ( ( me = Regex . Match ( js , re_Swap ) ) . Success )
53+ {
54+ id_CharSwap = functionIdentifier ; //If def matched the regex for charSwap then the current function is defined as swap.
55+ }
6856
6957 }
7058
71-
7259 foreach ( var line in lines . Skip ( 1 ) . Take ( lines . Length - 2 ) )
7360 {
7461 Match m ;
75- ///DUPLICATE CODE! Improve.
76- int locOfDot ; int locOfBracket ; int functionIDLength ;
77- locOfDot = line . IndexOf ( "." ) ;
78- locOfBracket = line . IndexOf ( "(" ) ;
79- functionIDLength = locOfBracket - ( locOfDot + 1 ) ;
80- functionIdentifier = line . Substring ( locOfDot + 1 , functionIDLength ) ; //Just needed this (define it as a member?)
81-
82- string newSliceIDRegex = string . Format ( @"(?<index>\d+)\)+" , functionIdentifier ) ;
62+ functionIdentifier = getFunctionFromLine ( line ) ;
8363
8464 if ( ( m = Regex . Match ( line , @"\(\w+,(?<index>\d+)\)" ) ) . Success && functionIdentifier == id_CharSwap )
85- { operations += "w" + m . Groups [ "index" ] . Value + " " ; } //Character swap regex appears to be the same as before
86-
65+ {
66+ operations += "w" + m . Groups [ "index" ] . Value + " " ; //operation is a swap (w)
67+ }
8768
8869 if ( ( m = Regex . Match ( line , @"\(\w+,(?<index>\d+)\)" ) ) . Success && functionIdentifier == id_Slice )
89- { operations += "s" + m . Groups [ "index" ] . Value + " " ; } //Slice appears to have changed the index location???
90- //Could be wrong and the regex needs improving, seems to work on the latest algorithm though.
70+ {
71+ operations += "s" + m . Groups [ "index" ] . Value + " " ; //operation is a slice
72+ }
9173
92- if ( functionIdentifier == id_Reverse )
93- { operations += "r " ; } //Reverse operation, no regex required
74+ if ( functionIdentifier == id_Reverse ) //No regex required for reverse (reverse method has no parameters)
75+ {
76+ operations += "r " ; //operation is a reverse
77+ }
9478
9579 }
80+
9681 operations = operations . Trim ( ) ;
9782
9883 return DecipherWithOperations ( cipher , operations ) ;
9984 }
10085
86+ private static string getFunctionFromLine ( string currentLine )
87+ {
88+ Regex matchFunctionReg = new Regex ( @"\w+\.(?<functionID>\w+)\(" ) ; //lc.ac(b,c) want the ac part.
89+ Match rgMatch = matchFunctionReg . Match ( currentLine ) ;
90+ string matchedFunction = rgMatch . Groups [ "functionID" ] . Value ;
91+ return matchedFunction ; //return 'ac'
92+ }
93+
10194 private static string ApplyOperation ( string cipher , string op )
10295 {
10396 switch ( op [ 0 ] )
10497 {
10598 case 'r' :
10699 return new string ( cipher . ToCharArray ( ) . Reverse ( ) . ToArray ( ) ) ;
107-
100+
108101 case 'w' :
109102 {
110103 int index = GetOpIndex ( op ) ;
0 commit comments