Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb247bafc0 |
@@ -10,8 +10,10 @@ Afterwards, run the runtime script (`start.bat`) and enjoy! You can now install
|
||||
|
||||
Please note that you will need to keep the emulator/proxy running whilst using DVDFab software.
|
||||
|
||||
It is recommended to run the clean-up script (`stop.bat`) to disconnect from the local proxy after you're done using it, as it can interfere with other programs.
|
||||
|
||||
## Notes
|
||||
|
||||
This project is not affiliated with StreamFab or any other subsidiary of DVDFab and is only intended to allow legitimately licensed users of the DVDFab software suite to use their rightfully purchased software offline without having to connect to an offshore authentication server.
|
||||
This project is not affiliated with StreamFab or any other subsidiary of DVDFab, and does not contain any copyrighted work.
|
||||
|
||||
It is not intended to promote or encourage piracy of any kind, and should only be used by legitimate owners of DVDFab software.
|
||||
This software is only intended to allow legitimately licensed users of the DVDFab software suite to use their rightfully purchased software without having to connect to an external authentication server, it is not intended to promote or encourage piracy of any kind, and should only be used by legitimate owners of DVDFab software.
|
||||
|
||||
132
index.js
132
index.js
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
DVDFab Server Emulator v1.1
|
||||
DVDFab Server Emulator v1.1.1
|
||||
*/
|
||||
|
||||
// Libraries
|
||||
@@ -8,14 +8,92 @@ const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const mockttp = require('mockttp');
|
||||
|
||||
// Configuration
|
||||
// Classes
|
||||
class Session {
|
||||
constructor() {
|
||||
this.DOMAINS = ['hotmail.com', 'gmail.com', 'yahoo.com', 'outlook.com', 'protonmail.com', 'yandex.com'];
|
||||
this.CHARACTERS = 'abcdefghijklmnopqrstuvwxyz0123456789.-';
|
||||
this.email = null;
|
||||
this.machine_id = null;
|
||||
this.usage = 0;
|
||||
this.update();
|
||||
}
|
||||
|
||||
generateRandomString(length) {
|
||||
return Array(length).fill(null).map(() => this.CHARACTERS.charAt(Math.floor(Math.random() * this.CHARACTERS.length))).join('');
|
||||
}
|
||||
|
||||
generateMacAddress() {
|
||||
const bytes = Array.from({ length: 12 }, () => Math.floor(Math.random() * 256));
|
||||
const mac1 = bytes.slice(0, 6).map(b => b.toString(16).padStart(2, '0')).join('-');
|
||||
const mac2 = bytes.slice(6).map(b => b.toString(16).padStart(2, '0')).join('-');
|
||||
return `${mac1}:${mac2}`;
|
||||
}
|
||||
|
||||
update() {
|
||||
const length = Math.floor(Math.random() * 10) + 5;
|
||||
this.email = `${this.generateRandomString(length)}@${this.DOMAINS[Math.floor(Math.random() * this.DOMAINS.length)]}`;
|
||||
this.machine_id = this.generateMacAddress();
|
||||
}
|
||||
|
||||
patchBoundary(data) {
|
||||
if (this.usage === 3) {
|
||||
this.usage = 0;
|
||||
this.update();
|
||||
}
|
||||
|
||||
const macRegex = /^([0-9a-f]{2}-){5}[0-9a-f]{2}(:([0-9a-f]{2}-){5}[0-9a-f]{2})?/;
|
||||
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
|
||||
const subscriptionRegex = /^365$/;
|
||||
|
||||
for (const key in data) {
|
||||
const value = data[key];
|
||||
if (macRegex.test(value)) {
|
||||
data[key] = this.machine_id;
|
||||
} else if (emailRegex.test(value)) {
|
||||
data[key] = this.email;
|
||||
} else if (subscriptionRegex.test(value)) {
|
||||
data[key] = 'trial';
|
||||
}
|
||||
}
|
||||
|
||||
this.usage++;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
// Constants
|
||||
const productList = fs.readFileSync(path.join(__dirname, 'products.txt'), 'utf8').trim().split('\n').map(Number);
|
||||
const daysLeft = Math.floor((new Date('9999-12-31T23:59:59.999Z') - new Date()) / 1000 / 60 / 60 / 24);
|
||||
const currentDate = new Date();
|
||||
const currentVersion = fs.readFileSync(path.join(__dirname, 'version.txt'), 'utf8').trim();
|
||||
const randomToken = crypto.randomBytes(16).toString('hex');
|
||||
|
||||
// Ticket
|
||||
// Functions
|
||||
function parseBoundary(data, boundary) {
|
||||
const parts = data.split(`--${boundary}`).filter(part => part.trim() && part !== '--');
|
||||
const formData = {};
|
||||
|
||||
parts.forEach(part => {
|
||||
const match = /Content-Disposition: form-data; name="([^"]+)"\r\n\r\n([\s\S]+)/.exec(part);
|
||||
if (match) {
|
||||
formData[match[1]] = match[2].trim();
|
||||
}
|
||||
});
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
function buildMultipartBody(data, boundary) {
|
||||
let body = '';
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
body += `--${boundary}\r\nContent-Disposition: form-data; name="${key}"\r\n\r\n${value}\r\n`;
|
||||
}
|
||||
body += `--${boundary}--\r\n`;
|
||||
return body;
|
||||
}
|
||||
|
||||
// Runtime
|
||||
const ticket = ['1'];
|
||||
productList.forEach((product) => {
|
||||
ticket.push(`${product}:${253402300799}`);
|
||||
@@ -35,6 +113,7 @@ ticket.push('TM:0');
|
||||
(async () => {
|
||||
const https = await mockttp.generateCACertificate();
|
||||
const proxyServer = mockttp.getLocal({ https });
|
||||
const session = new Session();
|
||||
|
||||
proxyServer.forPost(/https:\/\/.+\/auth\/v[0-5]+\//).thenReply(200,
|
||||
ticket.join('|')
|
||||
@@ -67,7 +146,7 @@ ticket.push('TM:0');
|
||||
);
|
||||
|
||||
proxyServer.forPost(/https:\/\/drm-u[0-9]+\.dvdfab\.cn\/ak\/re\/downloadex\//).thenReply(200,
|
||||
'{"R":"0","num":69420,"count":"69420"}',
|
||||
'{"R":"0","num":100,"count":"100"}',
|
||||
{ 'content-type': 'text/html; charset=UTF-8' }
|
||||
);
|
||||
|
||||
@@ -77,23 +156,42 @@ ticket.push('TM:0');
|
||||
|
||||
proxyServer.forPost(/https:\/\/.+\/\/products\/client_upgrade_license_v2/).thenCloseConnection();
|
||||
|
||||
proxyServer.forPost(/^https:\/\/.+\/ak\/uc_v[0-9]+\//).thenPassThrough({
|
||||
beforeRequest: async (originalRequest) => {
|
||||
if (originalRequest.headers['content-type'] && originalRequest.headers['content-type'].includes('multipart/form-data')) {
|
||||
const boundaryMatch = /boundary=(.+)/.exec(originalRequest.headers['content-type']);
|
||||
if (boundaryMatch) {
|
||||
const boundary = boundaryMatch[1];
|
||||
const formData = parseBoundary(originalRequest.body.buffer.toString(), boundary);
|
||||
const patchedData = session.patchBoundary(formData);
|
||||
const newBody = buildMultipartBody(patchedData, boundary);
|
||||
|
||||
originalRequest.body = Buffer.from(newBody);
|
||||
originalRequest.headers['content-length'] = Buffer.byteLength(newBody).toString();
|
||||
}
|
||||
}
|
||||
|
||||
return originalRequest;
|
||||
}
|
||||
});
|
||||
|
||||
await proxyServer.forUnmatchedRequest().thenPassThrough();
|
||||
|
||||
proxyServer.start(8000)
|
||||
|
||||
console.log();
|
||||
console.log(" +=============================================================+");
|
||||
console.log(" | DVDFab Server Emulator has started... |");
|
||||
console.log(" | You may now use any DVDFab software. |");
|
||||
console.log(" | Press CTRL-C or close this window to stop the emulator. |");
|
||||
console.log(" | You can safely ignore any errors. |");
|
||||
console.log(" +=============================================================+");
|
||||
console.log(" | If you have any problems with your network after |");
|
||||
console.log(" | disconnecting from the local proxy, please run the |");
|
||||
console.log(" | 'stop.bat' script. |");
|
||||
console.log(" +=============================================================+");
|
||||
console.log(" | If you got this script from anywhere apart from |");
|
||||
console.log(" | The CDM-Project, you likely have a malicious copy. |");
|
||||
console.log(" +=============================================================+");
|
||||
console.log(' +=============================================================+');
|
||||
console.log(' | DVDFab Server Emulator has started... |');
|
||||
console.log(' | You may now use any DVDFab software. |');
|
||||
console.log(' | Press CTRL-C or close this window to stop the emulator. |');
|
||||
console.log(' | You can safely ignore any errors. |');
|
||||
console.log(' +=============================================================+');
|
||||
console.log(' | If you have any problems with your network after |');
|
||||
console.log(' | disconnecting from the local proxy, please run the |');
|
||||
console.log(' | \'stop.bat\' script. |');
|
||||
console.log(' +=============================================================+');
|
||||
console.log(' | If you got this script from anywhere apart from |');
|
||||
console.log(' | The CDM-Project, you likely have a malicious copy. |');
|
||||
console.log(' +=============================================================+');
|
||||
console.log();
|
||||
})();
|
||||
|
||||
28
package.json
28
package.json
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "dvdfabserveremulator",
|
||||
"version": "1.0.0",
|
||||
"description": "Emulate DVDFab's license server locally.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"mockttp": "^3.15.1"
|
||||
}
|
||||
}
|
||||
{
|
||||
"name": "dvdfabserveremulator",
|
||||
"version": "1.1.1",
|
||||
"description": "A simple and efficient server emulator for DVDFab products; including DVDFab, StreamFab, MusicFab and more...",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "AGPL-3.0-only",
|
||||
"dependencies": {
|
||||
"mockttp": "^3.15.1"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user