Skip to content
This repository was archived by the owner on Sep 28, 2020. It is now read-only.

Commit cc80466

Browse files
committed
Update Decipherer
*Various optimizations *Decipherer follows strategy employed by https://github.com/gantt/downloadyoutube
1 parent 3106efa commit cc80466

File tree

1 file changed

+78
-93
lines changed

1 file changed

+78
-93
lines changed
Lines changed: 78 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Linq;
34
using System.Text;
45
using System.Text.RegularExpressions;
@@ -12,132 +13,116 @@ public static string DecipherWithVersion(string cipher, string cipherVersion)
1213
string jsUrl = string.Format("http://s.ytimg.com/yts/jsbin/player-{0}.js", cipherVersion);
1314
string js = HttpHelper.DownloadString(jsUrl);
1415

15-
//Find "C" in this: var A = B.sig||C (B.s)
16-
string functNamePattern = @"\""signature"",\s?([a-zA-Z0-9\$]+)\("; //Regex Formed To Find Word or DollarSign
16+
var decodeArray = FindSignatureCode(js);
1717

18-
var funcName = Regex.Match(js, functNamePattern).Groups[1].Value;
19-
20-
if (funcName.Contains("$"))
21-
{
22-
funcName = "\\" + funcName; //Due To Dollar Sign Introduction, Need To Escape
23-
}
18+
return DecryptSignature(cipher, decodeArray);
19+
}
2420

25-
string funcPattern = @"(?!h\.)" + @funcName + @"=function\(\w+\)\{.*?\}"; //Escape funcName string
26-
var funcBody = Regex.Match(js, funcPattern, RegexOptions.Singleline).Value; //Entire sig function
27-
var lines = funcBody.Split(';'); //Each line in sig function
21+
private static List<int> FindSignatureCode(string sourceCode)
22+
{
23+
var signatureFunctionName = FindMatch(sourceCode, @"\.set\s*\(""signature""\s*,\s*([a-zA-Z0-9_$][\w$]*)\(");
2824

29-
string idReverse = "", idSlice = "", idCharSwap = ""; //Hold name for each cipher method
30-
string functionIdentifier = "";
31-
string operations = "";
25+
//Optimization of Gantt's technique - functionName not needed
26+
var regExp = @"\s*\([\w$]*\)\s*{[\w$]*=[\w$]*\.split\(""""\);\n*(.+);return [\w$]*\.join";
3227

33-
foreach (var line in lines.Skip(1).Take(lines.Length - 2)) //Matches the funcBody with each cipher method. Only runs till all three are defined.
34-
{
35-
if (!string.IsNullOrEmpty(idReverse) && !string.IsNullOrEmpty(idSlice) &&
36-
!string.IsNullOrEmpty(idCharSwap))
37-
{
38-
break; //Break loop if all three cipher methods are defined
39-
}
28+
var reverseFunctionName = FindMatch(sourceCode, @"([\w$]*)\s*:\s*function\s*\(\s*[\w$]*\s*\)\s*{\s*(?:return\s*)?[\w$]*\.reverse\s*\(\s*\)\s*}");
29+
var sliceFunctionName = FindMatch(sourceCode, @"([\w$]*)\s*:\s*function\s*\(\s*[\w$]*\s*,\s*[\w$]*\s*\)\s*{\s*(?:return\s*)?[\w$]*\.(?:slice|splice)\(.+\)\s*}");
4030

41-
functionIdentifier = GetFunctionFromLine(line);
42-
string reReverse = string.Format(@"{0}:\bfunction\b\(\w+\)", functionIdentifier); //Regex for reverse (one parameter)
43-
string reSlice = string.Format(@"{0}:\bfunction\b\([a],b\).(\breturn\b)?.?\w+\.", functionIdentifier); //Regex for slice (return or not)
44-
string reSwap = string.Format(@"{0}:\bfunction\b\(\w+\,\w\).\bvar\b.\bc=a\b", functionIdentifier); //Regex for the char swap.
31+
var functionCode = FindMatch(sourceCode, regExp);
32+
functionCode = functionCode.Replace(reverseFunctionName, "reverse");
33+
functionCode = functionCode.Replace(sliceFunctionName, "slice");
34+
var functionCodePieces = functionCode.Split(';');
4535

46-
if (Regex.Match(js, reReverse).Success)
47-
{
48-
idReverse = functionIdentifier; //If def matched the regex for reverse then the current function is a defined as the reverse
49-
}
36+
List<int> decodeArray = new List<int>();
5037

51-
if (Regex.Match(js, reSlice).Success)
52-
{
53-
idSlice = functionIdentifier; //If def matched the regex for slice then the current function is defined as the slice.
54-
}
38+
var regSlice = new Regex("slice\\s*\\(\\s*.+([0-9]+)\\s*\\)");
39+
string regSwap = "\\w+\\s*\\(\\s*\\w+\\s*,\\s*([0-9]+)\\s*\\)";
40+
string regInline = "\\w+\\[0\\]\\s*=\\s*\\w+\\[([0-9]+)\\s*%\\s*\\w+\\.length\\]";
5541

56-
if (Regex.Match(js, reSwap).Success)
57-
{
58-
idCharSwap = functionIdentifier; //If def matched the regex for charSwap then the current function is defined as swap.
59-
}
60-
}
61-
62-
foreach (var line in lines.Skip(1).Take(lines.Length - 2))
42+
for (var i = 0; i < functionCodePieces.Length; i++)
6343
{
64-
Match m;
65-
functionIdentifier = GetFunctionFromLine(line);
6644

67-
if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idCharSwap)
68-
{
69-
operations += "w" + m.Groups["index"].Value + " "; //operation is a swap (w)
70-
}
45+
functionCodePieces[i] = functionCodePieces[i].Trim();
7146

72-
if ((m = Regex.Match(line, @"\(\w+,(?<index>\d+)\)")).Success && functionIdentifier == idSlice)
73-
{
74-
operations += "s" + m.Groups["index"].Value + " "; //operation is a slice
75-
}
47+
var codeLine = functionCodePieces[i];
7648

77-
if (functionIdentifier == idReverse) //No regex required for reverse (reverse method has no parameters)
49+
if (codeLine.Length > 0)
7850
{
79-
operations += "r "; //operation is a reverse
80-
}
81-
}
8251

83-
operations = operations.Trim();
52+
var arrSlice = regSlice.Match(codeLine);
8453

85-
return DecipherWithOperations(cipher, operations);
86-
}
87-
88-
private static string ApplyOperation(string cipher, string op)
89-
{
90-
switch (op[0])
91-
{
92-
case 'r':
93-
return new string(cipher.ToCharArray().Reverse().ToArray());
94-
95-
case 'w':
54+
if (arrSlice.Success && arrSlice.Length >= 2)
9655
{
97-
int index = GetOpIndex(op);
98-
return SwapFirstChar(cipher, index);
56+
var slice = int.Parse(arrSlice.Groups[1].Value);
57+
decodeArray.Add(-slice);
9958
}
100-
101-
case 's':
59+
else if (functionCodePieces[i].IndexOf("reverse") >= 0)
10260
{
103-
int index = GetOpIndex(op);
104-
return cipher.Substring(index);
61+
decodeArray.Add(0);
62+
}
63+
else if (codeLine.IndexOf("[0]") >= 0)
64+
{ // inline swap
65+
66+
if (i + 2 < functionCodePieces.Length && functionCodePieces[i + 1].IndexOf(".length") >= 0 && functionCodePieces[i + 1].IndexOf("[0]") >= 0)
67+
{
68+
69+
var inline = FindMatch(functionCodePieces[i + 1], regInline);
70+
decodeArray.Add(int.Parse(inline));
71+
72+
i += 2;
73+
74+
}
10575
}
76+
else if (codeLine.IndexOf(',') >= 0)
77+
{ // swap
78+
var swap = FindMatch(codeLine, regSwap);
79+
int swapVal = int.Parse(swap);
10680

107-
default:
108-
throw new NotImplementedException("Couldn't find cipher operation.");
81+
if (swapVal > 0)
82+
{
83+
decodeArray.Add(swapVal);
84+
}
85+
86+
}
87+
}
10988
}
89+
return decodeArray;
11090
}
11191

112-
private static string DecipherWithOperations(string cipher, string operations)
92+
private static string DecryptSignature(string sig, List<int> arr)
11393
{
114-
return operations.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries)
115-
.Aggregate(cipher, ApplyOperation);
116-
}
94+
var sigA = sig;
11795

118-
private static string GetFunctionFromLine(string currentLine)
119-
{
120-
Regex matchFunctionReg = new Regex(@"\w+\.(?<functionID>\w+)\("); //lc.ac(b,c) want the ac part.
121-
Match rgMatch = matchFunctionReg.Match(currentLine);
122-
string matchedFunction = rgMatch.Groups["functionID"].Value;
123-
return matchedFunction; //return 'ac'
96+
for (var i = 0; i < arr.Count; i++)
97+
{
98+
var act = arr[i];
99+
sigA = (act > 0) ? Swap(sigA.ToCharArray(), act) : ((act == 0) ? Reverse(sigA) : sigA.Substring(-act));
100+
}
101+
102+
return sigA;
124103
}
125104

126-
private static int GetOpIndex(string op)
105+
private static string Swap(char[] a, int b)
127106
{
128-
string parsed = new Regex(@".(\d+)").Match(op).Result("$1");
129-
int index = Int32.Parse(parsed);
107+
var c = a[0];
108+
a[0] = a[b % a.Length];
109+
a[b] = c;
130110

131-
return index;
111+
return new string(a);
132112
}
133113

134-
private static string SwapFirstChar(string cipher, int index)
114+
private static string Reverse(string s)
115+
{
116+
char[] charArray = s.ToCharArray();
117+
Array.Reverse(charArray);
118+
return new string(charArray);
119+
}
120+
private static string FindMatch(string text, string regexp)
135121
{
136-
var builder = new StringBuilder(cipher);
137-
builder[0] = cipher[index];
138-
builder[index] = cipher[0];
122+
Regex rgx = new Regex(regexp);
123+
var matches = rgx.Matches(text);
139124

140-
return builder.ToString();
125+
return matches[0].Groups[1].Value;
141126
}
142127
}
143128
}

0 commit comments

Comments
 (0)