azot 0.4.6 → 0.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,8 +1,338 @@
1
1
  #!/usr/bin/env node
2
- import{i as m,j as y}from"./chunk-AZ3F3PAE.js";import{parseArgs as L}from"node:util";import{readdir as D,readFile as u,stat as W}from"node:fs/promises";import{join as h}from"node:path";var c=async e=>{let o=(await W(e)).isDirectory();if(o){let t=o?await D(e):[],n=t.find(r=>r.includes("client_id")),l=t.find(r=>r.includes("private_key")),p=t.find(r=>r.endsWith("wvd")),$=!!(n&&l),j=!!p;if($){let r=h(e,n),g=h(e,l),_=await u(r),F=await u(g);return m.fromPair(_,F)}else if(j){let r=h(e,p),g=await u(r);return await m.fromWvd(g)}else console.log(`Unable to find client files in ${e}`),process.exit(1)}else if(e.endsWith(".wvd")){let t=await u(e);return m.fromWvd(t)}else console.log(`Unable to find client files in ${e}`),process.exit(1)},i=(e,s=2,o=30)=>`${" ".repeat(s)}${e.padEnd(o)}`;var w=()=>{console.log(`azot client: Widevine client utilities
3
- `),console.log(`Usage: azot client <subcommand> [...flags]
4
- `),console.log("Commands:"),console.log(i("info <input>")+"print info about client that is on <input> path (*.wvd filepath or directory with id and private key)"),console.log(i("pack <input> <output>")+"pack client id and private key from <input> directory into single *.wvd file with <output> path"),console.log(i("unpack <input> <output>")+"unpack *.wvd from <input> path to separate client id and private key placed in <output> directory"),console.log(""),console.log("Flags:"),console.log(i("-h, --help")+"Display this menu and exit")};var b=async e=>{let s=await c(e);for(let[o,t]of s.info.entries())console.log(`${o}: ${t}`)};import{writeFile as U}from"node:fs/promises";import{join as q}from"node:path";var k=async(e=process.cwd(),s)=>{let o=await c(e),t=await o.toWvd(),n=`${o.info.get("company_name")}_${o.info.get("model_name")}`,l=s||q(process.cwd(),`${n}.wvd`);await U(l,t),console.log(`Client packed: ${l}`)};import{writeFile as x}from"node:fs/promises";import{join as z}from"node:path";var P=async(e=process.cwd(),s)=>{let o=await c(e),[t,n]=await o.toPair(),l=z(s||process.cwd(),"device_client_id_blob"),p=z(s||process.cwd(),"device_private_key");await x(l,t),await x(p,n),console.log(`Client unpacked: ${l}, ${p}`)};var d={info:b,pack:k,unpack:P,help:w};var C=()=>{console.log(`azot license: Make license request
5
- `),console.log(`Usage: azot license <url> [...flags]
6
- `),console.log("Commands:"),console.log(i("<url>")+"URL of license server (e.g. https://cwip-shaka-proxy.appspot.com/no_auth)"),console.log(""),console.log("Flags:"),console.log(i("-H, --header")+"headers to send with license request"),console.log(i("-p, --pssh")+"widevine PSSH data in Base64"),console.log(i("-c, --client")+"path to client (directory with id and private key or path to *.wvd file)"),console.log(i("-e, --encrypt")+"enable client encryption with service certificate, disabled by default"),console.log(i("-h, --help")+"display this menu and exit")};var f=async e=>{let s=await y({server:e.url,pssh:e.pssh,client:await c(e.clientPath||process.cwd())});for(let o of s)console.log(`${o.id}:${o.value}`);return s};f.help=C;var v={name:"azot",version:"0.4.6",description:"Research & pentesting toolkit for Google's Widevine DRM",type:"module",files:["dist","scripts"],bin:{azot:"dist/cli.js"},scripts:{prepublishOnly:"npm run build:lib",dev:"wxt","dev:firefox":"wxt -b firefox",build:"npm run build:lib && npm run build:chrome","build:lib":"tsup --entry.lib lib/main.ts --entry.cli cli/main.ts --format cjs,esm --dts --clean --minify --minify-identifiers","build:chrome":"wxt build","build:firefox":"wxt build -b firefox",zip:"wxt zip","zip:firefox":"wxt zip -b firefox",compile:"tsc --noEmit",postinstall:"node scripts/postinstall.js",test:"vitest"},repository:{type:"git",url:"https://github.com/vitalygashkov/azot"},keywords:["drm","widevine","eme","encrypted-media","media"],author:"Vitaly Gashkov <vitalygashkov@vk.com>",license:"AGPL-3.0",readmeFilename:"README.md",bugs:{url:"https://github.com/vitalygashkov/azot/issues",email:"vitalygashkov@vk.com"},funding:[{type:"individual",url:"https://boosty.to/vitalygashkov"},{type:"patreon",url:"https://www.patreon.com/vitalygashkov"}],exports:{".":{require:{types:"./dist/lib.d.cts",default:"./dist/lib.cjs"},import:{types:"./dist/lib.d.ts",default:"./dist/lib.js"}}},engines:{node:"20 || 21 || 22 || 23"},dependencies:{jsrsasign:"^11.1.0",protobufjs:"^7.4.0","solid-icons":"^1.1.0","solid-js":"^1.9.1"},devDependencies:{"@eslint/js":"^9.12.0","@types/jsrsasign":"^10.5.14","@types/node":"^22.7.5","@wxt-dev/module-solid":"^1.1.2",autoprefixer:"^10.4.17",clsx:"^2.1.1",eslint:"^9.12.0","eslint-config-prettier":"^9.1.0","eslint-plugin-prettier":"^5.2.1",globals:"^15.11.0",postcss:"^8.4.33","tailwind-merge":"^2.5.4",tailwindcss:"^3.4.1",tsup:"^8.3.0",typescript:"^5.6.2","typescript-eslint":"^8.9.0","vite-plugin-arraybuffer":"^0.0.8",vitest:"^2.1.3",wxt:"^0.19.11"}};var a=L({args:process.argv.slice(2),options:{pssh:{type:"string",short:"p"},client:{type:"string",short:"c"},encrypt:{type:"boolean",short:"e",default:!1},header:{type:"string",short:"H",multiple:!0},help:{type:"boolean",short:"h"},version:{type:"boolean",short:"v"},debug:{type:"boolean",short:"d"}},strict:!1,allowPositionals:!0}),R=()=>{console.log(`Azot is a research & pentesting toolkit for Google's Widevine DRM. (${v.version})
7
- `),console.log(`Usage: azot <command> [...flags]
8
- `),console.log("Commands:"),console.log(i("license <url>")+"Make a license request"),console.log(i("client <subcommand>")+"Additional Widevine client utilities"),console.log(""),console.log("Flags:"),console.log(i("-d, --debug")+"Enable debug level logging"),console.log(i("-v, --version")+"Print version and exit"),console.log(i("-h, --help")+"Display this menu and exit"),console.log(""),console.log("(more flags in azot license --help and azot client --help)")};(async()=>{a.values.version&&(console.log(v.version),process.exit(0));let[e,...s]=a.positionals;switch(e){case"client":{let o=s.shift(),[t,n]=s;switch(o){case"pack":d.pack(t,n);break;case"unpack":d.unpack(t,n);break;case"info":d.info(t);break;default:a.values.help?(d.help(),process.exit(0)):(console.log("Client subcommand required: pack, unpack, info"),process.exit(1))}break}case"license":{a.values.help&&(f.help(),process.exit(0));let o=s.shift();if(!o)throw new Error("License URL required");let t=a.values.pssh;if(!t)throw new Error("PSSH required");let n=a.values.client,l=a.values.encrypt,p=a.values.header;await f({url:o,pssh:t,clientPath:n,encrypt:l,headers:p});break}case"pssh":break;case"serve":break;case"test":break;default:a.values.help?(R(),process.exit(0)):(console.log("Command not found"),process.exit(1))}})();
2
+ import {
3
+ Client,
4
+ fetchDecryptionKeys
5
+ } from "./chunk-LSX4EP25.js";
6
+
7
+ // cli/main.ts
8
+ import { parseArgs } from "node:util";
9
+
10
+ // cli/utils.ts
11
+ import { readdir, readFile, stat } from "node:fs/promises";
12
+ import { join } from "node:path";
13
+ var importClient = async (input) => {
14
+ const inputStat = await stat(input);
15
+ const isDir = inputStat.isDirectory();
16
+ if (isDir) {
17
+ const entries = isDir ? await readdir(input) : [];
18
+ const idFilename = entries.find((entry) => entry.includes("client_id"));
19
+ const keyFilename = entries.find((entry) => entry.includes("private_key"));
20
+ const wvdFilename = entries.find((entry) => entry.endsWith("wvd"));
21
+ const isUnpacked = !!(idFilename && keyFilename);
22
+ const isPacked = !!wvdFilename;
23
+ if (isUnpacked) {
24
+ const idPath = join(input, idFilename);
25
+ const keyPath = join(input, keyFilename);
26
+ const id = await readFile(idPath);
27
+ const key = await readFile(keyPath);
28
+ return Client.fromPair(id, key);
29
+ } else if (isPacked) {
30
+ const wvdPath = join(input, wvdFilename);
31
+ const wvd = await readFile(wvdPath);
32
+ return await Client.fromWvd(wvd);
33
+ } else {
34
+ console.log(`Unable to find client files in ${input}`);
35
+ process.exit(1);
36
+ }
37
+ } else if (input.endsWith(".wvd")) {
38
+ const wvd = await readFile(input);
39
+ return Client.fromWvd(wvd);
40
+ } else {
41
+ console.log(`Unable to find client files in ${input}`);
42
+ process.exit(1);
43
+ }
44
+ };
45
+ var col = (str, offset = 2, width = 30) => `${" ".repeat(offset)}${str.padEnd(width)}`;
46
+
47
+ // cli/commands/client/help.ts
48
+ var help = () => {
49
+ console.log(`azot client: Widevine client utilities
50
+ `);
51
+ console.log(`Usage: azot client <subcommand> [...flags]
52
+ `);
53
+ console.log(`Commands:`);
54
+ console.log(
55
+ col(`info <input>`) + "print info about client that is on <input> path (*.wvd filepath or directory with id and private key)"
56
+ );
57
+ console.log(
58
+ col(`pack <input> <output>`) + "pack client id and private key from <input> directory into single *.wvd file with <output> path"
59
+ );
60
+ console.log(
61
+ col(`unpack <input> <output>`) + "unpack *.wvd from <input> path to separate client id and private key placed in <output> directory"
62
+ );
63
+ console.log("");
64
+ console.log(`Flags:`);
65
+ console.log(col(`-h, --help`) + "Display this menu and exit");
66
+ };
67
+
68
+ // cli/commands/client/info.ts
69
+ var info = async (input) => {
70
+ const client2 = await importClient(input);
71
+ for (const [key, value] of client2.info.entries()) {
72
+ console.log(`${key}: ${value}`);
73
+ }
74
+ };
75
+
76
+ // cli/commands/client/pack.ts
77
+ import { writeFile } from "node:fs/promises";
78
+ import { join as join2 } from "node:path";
79
+ var pack = async (input = process.cwd(), output) => {
80
+ const client2 = await importClient(input);
81
+ const wvd = await client2.toWvd();
82
+ const wvdName = `${client2.info.get("company_name")}_${client2.info.get("model_name")}`;
83
+ const wvdOutput = output || join2(process.cwd(), `${wvdName}.wvd`);
84
+ await writeFile(wvdOutput, wvd);
85
+ console.log(`Client packed: ${wvdOutput}`);
86
+ };
87
+
88
+ // cli/commands/client/unpack.ts
89
+ import { writeFile as writeFile2 } from "node:fs/promises";
90
+ import { join as join3 } from "node:path";
91
+ var unpack = async (input = process.cwd(), output) => {
92
+ const client2 = await importClient(input);
93
+ const [id, key] = await client2.toPair();
94
+ const idOutput = join3(output || process.cwd(), `device_client_id_blob`);
95
+ const keyOutput = join3(output || process.cwd(), `device_private_key`);
96
+ await writeFile2(idOutput, id);
97
+ await writeFile2(keyOutput, key);
98
+ console.log(`Client unpacked: ${idOutput}, ${keyOutput}`);
99
+ };
100
+
101
+ // cli/commands/client/index.ts
102
+ var client = { info, pack, unpack, help };
103
+
104
+ // cli/commands/license/help.ts
105
+ var help2 = () => {
106
+ console.log(`azot license: Make license request
107
+ `);
108
+ console.log(`Usage: azot license <url> [...flags]
109
+ `);
110
+ console.log(`Commands:`);
111
+ console.log(
112
+ col(`<url>`) + "URL of license server (e.g. https://cwip-shaka-proxy.appspot.com/no_auth)"
113
+ );
114
+ console.log("");
115
+ console.log(`Flags:`);
116
+ console.log(col(`-H, --header`) + "headers to send with license request");
117
+ console.log(col(`-p, --pssh`) + "widevine PSSH data in Base64");
118
+ console.log(
119
+ col(`-c, --client`) + "path to client (directory with id and private key or path to *.wvd file)"
120
+ );
121
+ console.log(
122
+ col(`-e, --encrypt`) + "enable client encryption with service certificate, disabled by default"
123
+ );
124
+ console.log(col(`-h, --help`) + "display this menu and exit");
125
+ };
126
+
127
+ // cli/commands/license/license.ts
128
+ var license = async (params) => {
129
+ const keys = await fetchDecryptionKeys({
130
+ server: params.url,
131
+ pssh: params.pssh,
132
+ client: await importClient(params.clientPath || process.cwd())
133
+ });
134
+ for (const key of keys) {
135
+ console.log(`${key.id}:${key.value}`);
136
+ }
137
+ return keys;
138
+ };
139
+ license.help = help2;
140
+
141
+ // package.json
142
+ var package_default = {
143
+ name: "azot",
144
+ version: "0.4.7",
145
+ description: "Research & pentesting toolkit for Google's Widevine DRM",
146
+ type: "module",
147
+ files: [
148
+ "dist",
149
+ "scripts"
150
+ ],
151
+ bin: {
152
+ azot: "dist/cli.js"
153
+ },
154
+ scripts: {
155
+ prepublishOnly: "npm run build:lib",
156
+ dev: "wxt",
157
+ "dev:firefox": "wxt -b firefox",
158
+ build: "npm run build:lib && npm run build:chrome",
159
+ "build:lib": "tsup --entry.lib lib/main.ts --entry.cli cli/main.ts --format cjs,esm --dts --clean",
160
+ "build:chrome": "wxt build",
161
+ "build:firefox": "wxt build -b firefox",
162
+ zip: "wxt zip",
163
+ "zip:firefox": "wxt zip -b firefox",
164
+ compile: "tsc --noEmit",
165
+ postinstall: "node scripts/postinstall.js",
166
+ test: "vitest"
167
+ },
168
+ repository: {
169
+ type: "git",
170
+ url: "https://github.com/vitalygashkov/azot"
171
+ },
172
+ keywords: [
173
+ "drm",
174
+ "widevine",
175
+ "eme",
176
+ "encrypted-media",
177
+ "media"
178
+ ],
179
+ author: "Vitaly Gashkov <vitalygashkov@vk.com>",
180
+ license: "AGPL-3.0",
181
+ readmeFilename: "README.md",
182
+ bugs: {
183
+ url: "https://github.com/vitalygashkov/azot/issues",
184
+ email: "vitalygashkov@vk.com"
185
+ },
186
+ funding: [
187
+ {
188
+ type: "individual",
189
+ url: "https://boosty.to/vitalygashkov"
190
+ },
191
+ {
192
+ type: "patreon",
193
+ url: "https://www.patreon.com/vitalygashkov"
194
+ }
195
+ ],
196
+ exports: {
197
+ ".": {
198
+ require: {
199
+ types: "./dist/lib.d.cts",
200
+ default: "./dist/lib.cjs"
201
+ },
202
+ import: {
203
+ types: "./dist/lib.d.ts",
204
+ default: "./dist/lib.js"
205
+ }
206
+ }
207
+ },
208
+ engines: {
209
+ node: "20 || 21 || 22 || 23"
210
+ },
211
+ dependencies: {
212
+ jsrsasign: "^11.1.0",
213
+ protobufjs: "^7.4.0",
214
+ "solid-icons": "^1.1.0",
215
+ "solid-js": "^1.9.1"
216
+ },
217
+ devDependencies: {
218
+ "@eslint/js": "^9.12.0",
219
+ "@types/jsrsasign": "^10.5.14",
220
+ "@types/node": "^22.7.5",
221
+ "@wxt-dev/module-solid": "^1.1.2",
222
+ autoprefixer: "^10.4.17",
223
+ clsx: "^2.1.1",
224
+ eslint: "^9.12.0",
225
+ "eslint-config-prettier": "^9.1.0",
226
+ "eslint-plugin-prettier": "^5.2.1",
227
+ globals: "^15.11.0",
228
+ postcss: "^8.4.33",
229
+ "tailwind-merge": "^2.5.4",
230
+ tailwindcss: "^3.4.1",
231
+ tsup: "^8.3.0",
232
+ typescript: "^5.6.2",
233
+ "typescript-eslint": "^8.9.0",
234
+ "vite-plugin-arraybuffer": "^0.0.8",
235
+ vitest: "^2.1.3",
236
+ wxt: "^0.19.11"
237
+ }
238
+ };
239
+
240
+ // cli/main.ts
241
+ var args = parseArgs({
242
+ args: process.argv.slice(2),
243
+ options: {
244
+ pssh: { type: "string", short: "p" },
245
+ client: { type: "string", short: "c" },
246
+ encrypt: { type: "boolean", short: "e", default: false },
247
+ header: { type: "string", short: "H", multiple: true },
248
+ help: { type: "boolean", short: "h" },
249
+ version: { type: "boolean", short: "v" },
250
+ debug: { type: "boolean", short: "d" }
251
+ },
252
+ strict: false,
253
+ allowPositionals: true
254
+ });
255
+ var help3 = () => {
256
+ console.log(
257
+ `Azot is a research & pentesting toolkit for Google's Widevine DRM. (${package_default.version})
258
+ `
259
+ );
260
+ console.log(`Usage: azot <command> [...flags]
261
+ `);
262
+ console.log(`Commands:`);
263
+ console.log(col(`license <url>`) + "Make a license request");
264
+ console.log(
265
+ col(`client <subcommand>`) + "Additional Widevine client utilities"
266
+ );
267
+ console.log("");
268
+ console.log(`Flags:`);
269
+ console.log(col(`-d, --debug`) + "Enable debug level logging");
270
+ console.log(col(`-v, --version`) + "Print version and exit");
271
+ console.log(col(`-h, --help`) + "Display this menu and exit");
272
+ console.log("");
273
+ console.log(`(more flags in azot license --help and azot client --help)`);
274
+ };
275
+ (async () => {
276
+ if (args.values.version) {
277
+ console.log(package_default.version);
278
+ process.exit(0);
279
+ }
280
+ const [command, ...positionals] = args.positionals;
281
+ switch (command) {
282
+ case "client": {
283
+ const subcommand = positionals.shift();
284
+ const [input, output] = positionals;
285
+ switch (subcommand) {
286
+ case "pack":
287
+ client.pack(input, output);
288
+ break;
289
+ case "unpack":
290
+ client.unpack(input, output);
291
+ break;
292
+ case "info":
293
+ client.info(input);
294
+ break;
295
+ default: {
296
+ if (args.values.help) {
297
+ client.help();
298
+ process.exit(0);
299
+ } else {
300
+ console.log("Client subcommand required: pack, unpack, info");
301
+ process.exit(1);
302
+ }
303
+ }
304
+ }
305
+ break;
306
+ }
307
+ case "license": {
308
+ if (args.values.help) {
309
+ license.help();
310
+ process.exit(0);
311
+ }
312
+ const url = positionals.shift();
313
+ if (!url) throw new Error("License URL required");
314
+ const pssh = args.values.pssh;
315
+ if (!pssh) throw new Error("PSSH required");
316
+ const clientPath = args.values.client;
317
+ const encrypt = args.values.encrypt;
318
+ const headers = args.values.header;
319
+ await license({ url, pssh, clientPath, encrypt, headers });
320
+ break;
321
+ }
322
+ case "pssh":
323
+ break;
324
+ case "serve":
325
+ break;
326
+ case "test":
327
+ break;
328
+ default: {
329
+ if (args.values.help) {
330
+ help3();
331
+ process.exit(0);
332
+ } else {
333
+ console.log("Command not found");
334
+ process.exit(1);
335
+ }
336
+ }
337
+ }
338
+ })();