Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 03-30-2020, 20:48
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
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
Reply With Quote
  #2  
Old 03-30-2020, 21:11
h4sh3m h4sh3m is offline
Friend
 
Join Date: Aug 2016
Location: RCE
Posts: 56
Rept. Given: 1
Rept. Rcvd 4 Times in 2 Posts
Thanks Given: 49
Thanks Rcvd at 81 Times in 35 Posts
h4sh3m Reputation: 4
Hi

Can you share your video file, app, ... ?
Reply With Quote
  #3  
Old 03-30-2020, 21:32
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
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
Reply With Quote
  #4  
Old 03-31-2020, 23:28
bolo2002 bolo2002 is offline
VIP
 
Join Date: Apr 2002
Posts: 614
Rept. Given: 111
Rept. Rcvd 14 Times in 13 Posts
Thanks Given: 217
Thanks Rcvd at 238 Times in 152 Posts
bolo2002 Reputation: 14
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.
__________________
I like this forum!
Reply With Quote
  #5  
Old 04-01-2020, 14:11
thanhtam1306 thanhtam1306 is offline
Friend
 
Join Date: Nov 2017
Posts: 11
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 39
Thanks Rcvd at 3 Times in 2 Posts
thanhtam1306 Reputation: 0
Nice site, let me try
Reply With Quote
  #6  
Old 04-01-2020, 17:18
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
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

Last edited by yologuy; 04-01-2020 at 17:33.
Reply With Quote
The Following 2 Users Say Thank You to yologuy For This Useful Post:
niculaita (04-03-2020), ziapcland (04-13-2020)
  #7  
Old 04-02-2020, 22:35
bolo2002 bolo2002 is offline
VIP
 
Join Date: Apr 2002
Posts: 614
Rept. Given: 111
Rept. Rcvd 14 Times in 13 Posts
Thanks Given: 217
Thanks Rcvd at 238 Times in 152 Posts
bolo2002 Reputation: 14
Each videos are signed from and to the user account then?
Keep us informed,would be nice to find a solution.
__________________
I like this forum!
Reply With Quote
The Following 2 Users Say Thank You to bolo2002 For This Useful Post:
niculaita (04-03-2020), tK! (09-01-2021)
  #8  
Old 04-05-2020, 02:46
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
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

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
Reply With Quote
The Following 3 Users Say Thank You to yologuy For This Useful Post:
Abaddon (04-05-2020), darkBLACK (04-05-2020), uranus64 (04-05-2020)
  #9  
Old 04-05-2020, 19:24
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
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

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

Last edited by yologuy; 04-05-2020 at 19:47.
Reply With Quote
  #10  
Old 04-05-2020, 20:29
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
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

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.
Reply With Quote
The Following 8 Users Say Thank You to yologuy For This Useful Post:
Abaddon (04-05-2020), bolo2002 (04-06-2020), cachito (04-07-2020), chants (04-07-2020), DominicCummings (09-09-2021), Mahmoudnia (04-05-2020), ziapcland (04-13-2020), Zipdecode (05-03-2020)
  #11  
Old 04-06-2020, 23:46
bolo2002 bolo2002 is offline
VIP
 
Join Date: Apr 2002
Posts: 614
Rept. Given: 111
Rept. Rcvd 14 Times in 13 Posts
Thanks Given: 217
Thanks Rcvd at 238 Times in 152 Posts
bolo2002 Reputation: 14
Well done thanks,videos are not mine just found it easy as they are free,time to make a standalone tool joke
__________________
I like this forum!
Reply With Quote
  #12  
Old 04-07-2020, 05:41
chants chants is offline
VIP
 
Join Date: Jul 2016
Posts: 725
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 666
Thanks Rcvd at 1,053 Times in 478 Posts
chants Reputation: 48
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
Reply With Quote
The Following 2 Users Say Thank You to chants For This Useful Post:
yologuy (04-08-2020), ziapcland (04-13-2020)
  #13  
Old 04-07-2020, 23:13
bolo2002 bolo2002 is offline
VIP
 
Join Date: Apr 2002
Posts: 614
Rept. Given: 111
Rept. Rcvd 14 Times in 13 Posts
Thanks Given: 217
Thanks Rcvd at 238 Times in 152 Posts
bolo2002 Reputation: 14
@yologuy:
by investigating code,did you see some method to get paid courses with free account?
__________________
I like this forum!
Reply With Quote
  #14  
Old 08-26-2021, 20:47
yologuy yologuy is offline
Friend
 
Join Date: Nov 2016
Posts: 18
Rept. Given: 0
Rept. Rcvd 0 Times in 0 Posts
Thanks Given: 5
Thanks Rcvd at 23 Times in 9 Posts
yologuy Reputation: 0
Quote:
Originally Posted by bolo2002 View Post
@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.
Reply With Quote
  #15  
Old 08-26-2021, 23:26
bolo2002 bolo2002 is offline
VIP
 
Join Date: Apr 2002
Posts: 614
Rept. Given: 111
Rept. Rcvd 14 Times in 13 Posts
Thanks Given: 217
Thanks Rcvd at 238 Times in 152 Posts
bolo2002 Reputation: 14
Quote:
Originally Posted by yologuy View Post
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.
__________________
I like this forum!
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Help with AES 128 encrypted file phroyt General Discussion 6 04-28-2020 09:57
Reversing obfuscated and encrypted JAR file Chuck954 General Discussion 8 10-11-2019 10:04
Is it possible to crack encrypted file? wenij General Discussion 8 02-19-2005 20:20


All times are GMT +8. The time now is 19:08.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( 1998 - 2024 )