Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   Encrypted video file (https://forum.exetools.com/showthread.php?t=19476)

yologuy 03-30-2020 20:48

Encrypted video file
 
Hello, first of all, sorry if the wrong session.

I have an application that downloads a video file and lets you see this video later. (The idea is somehow similar to Netflix).
However, this video file is somehow encrypted and the standard tool like vlc can't open it.

I know this file contains at least a video because there is the MPEG header but after 1mb of "random" data unfortunately even removing this 1mb of random data is still not a valid MPEG file.
So current file struct is
[1mb chunk]
[MPEG header]

I'm not so experienced in data analysis, so I'm wondering do you have any tips, resource about "data mining"

Since there is an android application I will also give a try by decompiling the APK and see how the video player is doing. But I would like to extend my data analysis skills first rather than RE.

Thanks in advance

h4sh3m 03-30-2020 21:11

Hi

Can you share your video file, app, ... ?

yologuy 03-30-2020 21:32

fr.tuto.com
You can register, download the app and download some free source.

for video files, I don't know as they seem to have a lot of metadata that probably contain a user/hardware ID. I will download a file later on a VM with a fake account.

Thanks a lot :)

bolo2002 03-31-2020 23:28

https://www120.zippyshare.com/v/zYmL5gcV/file.html
https://www120.zippyshare.com/v/ndBGL6sq/file.html
Samples of videos,nice site btw,would be great to find a solution.

thanhtam1306 04-01-2020 14:11

Nice site, let me try

yologuy 04-01-2020 17:18

Ok seems to be an nodejs things built on top of ionic/angular and Cordova(for cross-platform?).

The source code is located in build/www/main.js
The var TutorialPage class is interesting stuff.

Video seems to be embedded in a vg_Player(with a crossorigin) as expect, read mp4 file.
Code:

<video [vgMedia]="media" [vgDash]="source" [vgHls]="source" #media id="singleVideo" preload="auto" type="video/mp4" crossorigin playsinline>\n </video>\n </vg-player
And the play prototype is pretty explanatory
TutorialPage.prototype.play
Which download the source, and sign/unsign it
Code:

    TutorialPage.prototype.play = function (video, autoplay, setCursor, customCursor) {
        var _this = this;
        this.source = '';
        this.isBuffering = true;
        this.disableControl = false;
        ((video.download.status == __WEBPACK_IMPORTED_MODULE_4__providers_download_status__["a" /* DownloadStatus */].STATUS_DOWNLOADED)
            ? video.download
                .getPath(true)
                .mergeMap(function (directory) {
                var basePath = directory.basePath, filePath = directory.filePath;
                return _this._signerService.isSigned(basePath + '/' + filePath.substr(1))
                    .mergeMap(function (isSigned) { return isSigned ? _this._signerService.unsign(basePath + '/' + filePath.substr(1)) : __WEBPACK_IMPORTED_MODULE_13_rxjs_Observable__["Observable"].of(''); })
                    .map(function () { return directory; });
            })
                .do(function (directory) {
                var basePath = directory.basePath, filePath = directory.filePath;
                var source = basePath + '/' + filePath.substr(1);
                if (_this.device.platform === 'iOS') {
                    source = Object(__WEBPACK_IMPORTED_MODULE_2_ionic_angular__["I" /* normalizeURL */])(source);
                }
                _this._setSource(source, autoplay, video, setCursor, customCursor);
            })
                .do(function (directory) {
                var basePath = directory.basePath, filePath = directory.filePath;
                __WEBPACK_IMPORTED_MODULE_13_rxjs_Observable__["Observable"].timer(1000)
                    .mergeMap(function () { return _this._signerService.sign(basePath + '/' + filePath.substr(1), video.id); })
                    .subscribe(function () { return null; });
            })
            : this._videoService
                .get(video.id)
                .do(function (data) { return _this._setSource(data.link, autoplay, video, setCursor, customCursor); }))
            .subscribe(function () {
            _this.api.getDefaultMedia().loadMedia();
            video.stats.lastTime = video.stats.cursor;
            if (_this._completionSubscriber) {
                _this._completionSubscriber.unsubscribe();
            }
            if (_this._playSubscriber) {
                _this._playSubscriber.unsubscribe();
            }
            setTimeout(function () {
                _this.onStartup = true;
                _this._completionSubscriber = _this.api.getDefaultMedia().subscriptions.timeUpdate.subscribe(function () { return _this._updateStats(video); });
                _this._playSubscriber = _this.api.getDefaultMedia().subscriptions.play.subscribe(function () { return _this._onPlay(video); });
            }, 400);
        });
    };

But the sign module is a C++ module compiled in Tuto.com\node_modules\signer\build\Release\signer.node which is a C++ extension so will try to give a shot tonight to decompile it
At least there is the sln file (without the .cc that would have been too nice) but the PDB is still there so it should be pretty trivial.

Thanks for the support guys :)

bolo2002 04-02-2020 22:35

Each videos are signed from and to the user account then?
Keep us informed,would be nice to find a solution.

yologuy 04-05-2020 02:46

by editing the main.js and removing the sign video did the trick.
So now when I play the video, the file is decrypted and stays decrypted on the disk.
Then comparing both files, only the header changed. So I look briefly within the compiled signer module. There is a encryptDecrypt method that really looks interesting since it operates only on a 15bytes buffer, the exact same size that was changed in my file. I will probably get more time tomorrow. But I guess I'm on the right track :D

And of course copy/pasting the header to your video didn't work, so I guess its a kind of xor, of the first 15b of the file, I just need to find the key :)

yologuy 04-05-2020 19:24

So it read the last 48bytes Then do a 0x2E xor on it.
hxxps://i.ibb.co/bWtK403/ecrypt-decrypt.jpg

Note that the user_id and the video_id is embedded within the file (also stored at the end of the file)

So here is the data structure starting from the end:
48bytes xored with 0x2E corresponding to the header of the file.
8 null bytes(delimiter?)
UnknowInt32
8 null bytes(delimiter?)
UnknowInt32
UnknowInt32
8 null bytes(delimiter?)
UnknowInt32
video_id (int32)
user_id (int32)
EOF (for the video file)
x bytes[FileContent]
48bytes[] that needs to be replaced by the end bytes xored for the moment they seem to be useless.

So by applying that I was able to retrieve your mp4 files which are from https://fr.tuto.com/after-effects/gratuit-initiation-complete-d-after-effects-after-effects,49795.html (I didn't remove your user_id/video_id)
https://www.sendspace.com/filegroup/RMqSpPbmzMobgzR7U5kRGg


Btw you can get your user_id, just connect to tuto.com, inspect the src code and at the bottom, there is your user_id


Next step create a python script to automate this, but should be trivial will probably have more time next weekend :)

Enjoy :D

BTW hxxps://www.relyze.com/beta3.html is amazing and free for non-commercial project :D

yologuy 04-05-2020 20:29

Looks like I can't edit my post I don't know why.
Sorry for the double post.

Here the python3 script, which also removes the user_id from the video :)
Code:

import os
import shutil

headerSize = 48

def decrypt_file(encryptedFile, decryptedFile):
        shutil.copy(encryptedFile, decryptedFile)

        with open(decryptedFile, "r+b") as inputFile:
                # Remove the user ID
                videoIdEmplacement = headerSize * 2 - 3
                inputFile.seek(-videoIdEmplacement, os.SEEK_END)
                inputFile.write(bytes([0x00, 0x00, 0x00, 0x00]))

                # Read the encrypted header
                inputFile.seek(-headerSize, os.SEEK_END)
                encryptedHeader = bytearray(inputFile.read(headerSize))

                # Xor the header
                decryptedHeader = bytes([b ^ 0x2E for b in encryptedHeader])

                # Write the original file header
                inputFile.seek(0, os.SEEK_SET)
                inputFile.write(decryptedHeader)


inputVideoFile = r"inputVideoFile"
mp4VideoFile = r"outputVideoFile.mp4"

decrypt_file(inputVideoFile, mp4VideoFile)

Enjoy guys :D

Note that looking at the app, the encryption seems different on android, so just in case I'm on a PC that may differ with a mac I don't know.

bolo2002 04-06-2020 23:46

Well done thanks,videos are not mine just found it easy as they are free,time to make a standalone tool :) joke

chants 04-07-2020 05:41

Well an XOR cipher on a handful of bytes is the most partial and Ancient encryption method :). It makes sense given that encrypting video data itself with something strong especially would turn a computer into a space heater, and would probably cause stuttering and glitching. Encrypting selective consecutive frames or a good number of other options might work. Or hardware specially designed for the purpose perhaps. But the excess CPU on what is such a real time priority task makes a perfect solution impossible. Even AES with processor intrinsic would probably be too costly. Nice solutoon and script to go with it though

The post editing feature is only enabled for a fee minutes after posting, and it is beneficial since it's better to preserve mistakes and keep context in a thread then see history being rewritten to the point a thread no longer makes sense. In my experience, the edit timeout is always increasing quality of discussion. It's even used all over now, I've seen StackOverflow won't let me edit comments after some amount of minutes. Once you see the feature overused, and the difficulty it causes, you can understand the policy

bolo2002 04-07-2020 23:13

@yologuy:
by investigating code,did you see some method to get paid courses with free account?

yologuy 08-26-2021 20:47

Quote:

Originally Posted by bolo2002 (Post 119719)
@yologuy:
by investigating code,did you see some method to get paid courses with free account?

Unfortually not, all data are sent to the server, I didn't bother trying anything, but their server may have issue but yeah, the client don't do a lot except redirect to a REST API.

bolo2002 08-26-2021 23:26

Quote:

Originally Posted by yologuy (Post 123657)
Unfortually not, all data are sent to the server, I didn't bother trying anything, but their server may have issue but yeah, the client don't do a lot except redirect to a REST API.

Late reply,nice to see you again here,btw how you would adapt your script to convert a whole folder encrypted files to decrypted ones with filenames respective?
I understand how java works but often not how to get what i want.


All times are GMT +8. The time now is 17:00.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX