Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube signature decipher with an working example for VB.Net

I know there are many projects and I could use them. But I really want to get it running without dependencies in my VB.Net project.

So what I try to do is creating a Youtube downloader. It works great on usual videos. But these special videos like Vevo (https://www.youtube.com/watch?v=9bZkp7q19f0) and some others do not work.

They have another signature that I need to decipher. Here I need the HTMLPlayer JS file which I was able to extract(http://s.ytimg.com/yts/jsbin/html5player-de_DE-vflG4uS_k/html5player.js). And on that file I need to search for a special function and look what this one is doing and then doing the same in my code. So far so easy but on some examples I was not even able to find "sig=" or "signature=" and when I found them it did not really help me out.

So What I would like to know is how I can extract the needed information from the html5.player.js file. So as you can see here https://superuser.com/questions/773719/how-do-all-of-these-save-video-from-youtube-services-work I have that link to that file.

I also found this https://mytoolkit.codeplex.com/discussions/479171 that helped me to start. But from the start of Sign_Decipher I do not find a such called function in the js file.

Some other links I found but did not help me to get it running or where just too old:

  • Getting the signature of a youtube video
  • Youtube decipher signature not working as expected
  • How can i decrypt signature and add to the YouTube Extracted URL in objective c?
  • Best approach to decode Youtube cipher signature using PHP or JS
  • https://github.com/svnpenn/bm/blob/gh-pages/yt.js
  • https://github.com/rg3/youtube-dl/issues/1060
  • https://github.com/jeckman/YouTube-Downloader/issues/9

Some APIs which are somehow not working, too:

  • http://ytapi.gitnol.com/
  • http://api.gitnol.com/
like image 402
kwoxer Avatar asked Feb 12 '23 03:02

kwoxer


2 Answers

The linked websites you provided already contain all you have to know for solving this problem. Most of the work can be done with some simple regular expressions. These are the required steps to decode such a scrambled signature:

  1. Download the html5player.js that is used by the page of video you want to download.
  2. Determine the name of the function which is used to decode the encoded signature.
  3. Using this name, extract the function definition from the script.
  4. Run the extracted function within an JS-interpreter and simply decode the signature with it.

Getting the html5player.js

The first step should be no problem, as you have already accomplished it. Most of the script URL will always be the same (https://s.ytimg.com/yts/jsbin/html5player-VERSION/html5player.js). Only the version part changes from time to time (e.g. de_DE-vflR89yTY). That means, you just have to find the script version in the video-page and adapt the default script URL. The resulting URL will be something like this: https://s.ytimg.com/yts/jsbin/html5player-de_DE-vflR89yTY/html5player.js

Player Version: html5player-([\w\d\-]+)\\\/html5player\.js

The version can be found in the first capture group.

Extracting the Decode-Function

Before we can extract the function we have to know its name. Unfortunately the name of the decode-funtion can change from version to version, but the part of the code that makes use of this function usually doesn't change.

Decode-Function Name: \.sig\|\|([a-zA-Z0-9$]+)\(

The function name will be in the first capture group.

Now that we know the name, we can extract the function, using regex again. Just replace #NAME# with the function name.

Decode-Function Definition: function #NAME#\([^\)]+\){.*?};


Besides the actual decode-function we need to extract some utility functions the decode-function is using. These functions are contained in an object. Before we can extract the object definition from the html5player.js we have to determine the name of the object.

Just remember to use the extracted function definition as input for the regex this time.

Helper-Object Name: ;([A-Za-z0-9]+)\.

The object name will be in the first capture group.

Using the object name and some regex we can extract the object definition from the player-script just like we did it with the function definition before. Replace #NAME# with the object name from the last step.

Helper-Object Definition: var #NAME#={.*?};

Now we have everything we need restore the scrambled signature.

Decoding the Signature

The last step is to use the extracted functions to decode the signature. To accomplish this in .NET we have to parse and execute the JavaScript code. Luckily there are ready-to-use solutions which can do that for us. One of them is the JS interpreter Jint. Another option is to use one of the Script Engines available in Windows. Simon Mourier provides an convenient wrapper around these engines in the following answer: https://stackoverflow.com/a/4748886/1278838


Here is a little example program that combines all above steps and uses Simon's wrapper to decode the first signature it can find in the hard-coded video page and print both, the encoded and decoded signatures, out to the console.

The code is written in C# but it should be easy to convert it to VB .NET.

class Program
{
    private const string PlayerScriptUrlTemplate = "https://s.ytimg.com/yts/jsbin/html5player-{0}/html5player.js";
    private const string DecodeFunctionPatternTemplate = @"function #NAME#\([^\)]+\){.*?};";
    private const string HelperObjectPatternTemplate = @"var #NAME#={.*?};";

    private static readonly Regex SignatureRegex = new Regex(@"s=(?<Signature>[A-F0-9]+\.[A-F0-9]+)");
    private static readonly Regex PlayerVersionRegex = new Regex(@"html5player-(?<PlayerVersion>[\w\d\-]+)\\\/html5player\.js");
    private static readonly Regex DecodeFunctionNameRegex = new Regex(@"\.sig\|\|(?<FunctionName>[a-zA-Z0-9$]+)\(");
    private static readonly Regex HelperObjectNameRegex = new Regex(@";(?<ObjectName>[A-Za-z0-9]+)\.");

    static void Main()
    {
        const string videoUrl = "https://www.youtube.com/watch?v=6pIyg35wiB4";

        var client = new WebClient();
        var videoPageData = client.DownloadString(videoUrl);

        var encodedSignature = SignatureRegex.Match(videoPageData).Groups["Signature"].Value;

        var playerVersion = PlayerVersionRegex.Match(videoPageData).Groups["PlayerVersion"].Value;
        var playerScriptUrl = string.Format(PlayerScriptUrlTemplate, playerVersion);
        var playerScript = client.DownloadString(playerScriptUrl);

        var decodeFunctionName = DecodeFunctionNameRegex.Match(playerScript).Groups["FunctionName"].Value;
        var decodeFunction = Regex.Match(playerScript, DecodeFunctionPatternTemplate.Replace("#NAME#", decodeFunctionName)).Value;
        var helperObjectName = HelperObjectNameRegex.Match((decodeFunction)).Groups["ObjectName"].Value;
        var helperObject = Regex.Match(playerScript, HelperObjectPatternTemplate.Replace("#NAME#", helperObjectName)).Value;

        var engine = new ScriptEngine(ScriptEngine.JavaScriptLanguage);
        var decoderScript = engine.Parse(helperObject + decodeFunction);
        var decodedSignature = decoderScript.CallMethod(decodeFunctionName, encodedSignature).ToString();

        // Jint variant
        //var engine = new Engine();
        //var decoderScript = engine.Execute(helperObject).Execute(decodeFunction);
        //var decodedSignature = decoderScript.Invoke(decodeFunctionName, encodedSignature).ToString();

        Console.WriteLine("Encoded Signature\n{0}.\n{1}", encodedSignature.Split('.').First(), encodedSignature.Split('.').Last());
        Console.WriteLine();
        Console.WriteLine("Decoded Signature\n{0}.\n{1}", decodedSignature.Split('.').First(), decodedSignature.Split('.').Last());
        Console.ReadLine();
    }
}
like image 176
El Cattivo Avatar answered Feb 24 '23 05:02

El Cattivo


Sorry people but the old "html5player.js" player no longer works, it's 404 and the Url you need now looks more like https://s.ytimg.com/yts/jsbin/player-en_US-vfl_cdzrt/base.js

you starter for six is finding a function that look like this in the javascript

xr=function(a)
{
a=a.split("");
wr.rF(a,54);
wr.fs(a,75);
wr.N0(a,1);
wr.rF(a,52);
wr.N0(a,3);
wr.fs(a,31);
wr.rF(a,16);
wr.fs(a,38);
return a.join("")
}

After that i get a bit lost because the code for the wr function looks just the same and i cannot find the code for the swap,replace,split functions like Youtube have used in the past.

wr=function(a)
{
a=a.split("");
wr.rF(a,54);
wr.fs(a,75);
wr.N0(a,1);
wr.rF(a,52);
wr.N0(a,3);
wr.fs(a,31);
wr.rF(a,16);
wr.fs(a,38);
return a.join("")
}

wr.N0 i think looks like this but the javascript then goes above my pay-grade for me to follow what is going on.

N0=function(a,b){Tb(nga,b)&&tm(H_(a),a.O,b,a.Pq,a)}
like image 21
Dr Gadgir Avatar answered Feb 24 '23 07:02

Dr Gadgir