Add proper report, os guessing and version ranges

This commit is contained in:
Nemo 2021-07-16 20:40:30 +05:30
parent e674c15ad0
commit 8ce0bc7e71
8 changed files with 169 additions and 43 deletions

View File

@ -6,20 +6,21 @@ Try to find out which Electron version is bundled inside an application.
```shell ```shell
$ npm install which-electron $ npm install which-electron
$ which-electron Google.Play.Music.Desktop.Player.OSX.zip $ which-electron Google.Play.Music.Desktop.Player.OSX.zip
Version Constraint: <v7.0.0 Version Constraint (Unsupported): <v7.0.0
Multiple guesses from fingerprinting: Fingerprint: v3.1.7-v3.1.8
[ v3.1.8 is currently not supported
'v3.1.10', 'v3.1.11',
'v3.1.12', 'v3.1.13',
'v3.1.5', 'v3.1.6',
'v3.1.7', 'v3.1.8',
'v3.1.9'
]
$ which-electron HashTag-win32-x64.zip $ which-electron HashTag-win32-x64.zip
Found Version file: v7.1.10 Found Version file: v7.1.10
v7.1.10 is currently not supported
Fingerprint: v7.1.10 Fingerprint: v7.1.10
v7.1.10 is currently not supported
$ which-electron Appium-linux-1.21.0.AppImage
Fingerprint: v7.2.4-v7.3.3
v7.3.3 is currently not supported
$ which-electron Google.Play.Music.Desktop.Player.deb $ which-electron Google.Play.Music.Desktop.Player.deb
``` ```

View File

@ -54,6 +54,9 @@ module.exports = {
if (isDirectory(e.attributes)) { if (isDirectory(e.attributes)) {
return false; return false;
} }
if (!e.file) {
return false;
}
let ext = path.extname(e.file); let ext = path.extname(e.file);
if (['.h', '.dll', '.bin', '.asar', '.dylib', '.so', '.exe'].indexOf(ext) !== -1) { if (['.h', '.dll', '.bin', '.asar', '.dylib', '.so', '.exe'].indexOf(ext) !== -1) {
return true return true

View File

@ -1,18 +1,18 @@
const DB = require("electron-fingerprints"); const DB = require("electron-fingerprints");
const fs = require("fs"); const fs = require("fs");
const hasha = require('hasha'); const hasha = require("hasha");
const allVersions = require('./versions')['all'] const allVersions = require("./versions")["all"];
function checksumFile(algorithm, path) { function checksumFile(algorithm, path) {
return new Promise(function (resolve, reject) { return new Promise(function(resolve, reject) {
let fs = require('fs'); let fs = require("fs");
let crypto = require('crypto'); let crypto = require("crypto");
let hash = crypto.createHash(algorithm).setEncoding('hex'); let hash = crypto.createHash(algorithm).setEncoding("hex");
fs.createReadStream(path) fs.createReadStream(path)
.once('error', reject) .once("error", reject)
.pipe(hash) .pipe(hash)
.once('finish', function () { .once("finish", function() {
resolve(hash.read()); resolve(hash.read());
}); });
}); });
@ -37,14 +37,18 @@ module.exports = {
} }
} }
return possibleVersions; if (possibleVersions == allVersions) {
return [];
} else {
return possibleVersions;
}
}, },
getHashes: function(dir) { getHashes: function(dir) {
let list = fs.readdirSync(dir); let list = fs.readdirSync(dir);
return list.map((f) => { return list.map((f) => {
let fn = `${dir}/${f}`; let fn = `${dir}/${f}`;
return hasha.fromFileSync(fn, {algorithm: 'sha1'}) return hasha.fromFileSync(fn, { algorithm: "sha1" });
}) });
}, },
}; };

View File

@ -2,57 +2,81 @@ const path = require("path");
const osguess = require("./os"); const osguess = require("./os");
const finder = require("./finder"); const finder = require("./finder");
const zip = require("./zip"); const zip = require("./zip");
const fp = require('./fingerprint') const fp = require("./fingerprint");
const cleanup = require("rimraf");
const V = require("./version");
// Input file comes from process.argv[2] // Input file comes from process.argv[2]
const FILENAME = process.argv[2]; const FILENAME = process.argv[2];
console.log(FILENAME) console.log(FILENAME);
zip.listFileContents(FILENAME, (entries)=> { function logSupport(version) {
if (V.isSupported(version)) {
console.log(`${version} is currently supported`);
} else {
console.log(`${version} is currently not supported`);
}
}
zip.listFileContents(FILENAME, (entries) => {
let osguess1 = osguess.guessFromFilename(FILENAME);
let osguess2 = osguess.guessFromContents(entries);
if (osguess1 !== osguess2 && osguess1!==null) {
console.log(`Unsure about operating system. Going with ${osguess2}. Other option was ${osguess1}`);
}
let arch = osguess.guessArch(FILENAME, entries);
let asar = finder.asar(entries); let asar = finder.asar(entries);
let binary = finder.binary(entries); let binary = finder.binary(entries);
let versionFiles = finder.version(entries); let versionFiles = finder.version(entries);
let enm = finder.findElectronPackageInsideNodeModules(entries); let enm = finder.findElectronPackageInsideNodeModules(entries);
let filesToHash = finder.fingerprintable(entries) let filesToHash = finder.fingerprintable(entries);
zip.extractSomeFiles(FILENAME, filesToHash, (dir)=>{ zip.extractSomeFiles(FILENAME, filesToHash, (dir) => {
hashes = fp.getHashes(dir) hashes = fp.getHashes(dir);
guesses = fp.guessFromHashes('win32', 'x64', hashes) guesses = fp.guessFromHashes(osguess2, arch, hashes);
if (guesses.length == 1) { if (guesses.length == 1) {
console.log("Fingerprint: " + guesses[0]) console.log("Fingerprint: " + guesses[0]);
} else { logSupport(guesses[0])
console.log("Multiple guesses from fingerprinting:") } else if (guesses.length > 1) {
console.log(guesses) console.log("Fingerprint: " + V.asText(guesses));
logSupport(V.max(guesses))
} }
})
cleanup.sync(dir);
});
// if (binary) { // if (binary) {
// console.log(`${process.argv[2]}:${binary}`); // console.log(`${process.argv[2]}:${binary}`);
// } // }
if (versionFiles.length > 0) { if (versionFiles.length > 0) {
versionFiles.map((f) => { versionFiles.map((f) => {
zip.readFileContents(FILENAME, f, (c)=>{ zip.readFileContents(FILENAME, f, (c) => {
console.log("Found Version file: v" + c) console.log("Found Version file: v" + c);
}) logSupport(`v${c}`)
});
}); });
} }
if (asar.length > 0) { if (asar.length > 0) {
asar.forEach((a) => { asar.forEach((a) => {
console.log("Version Constraint: <v7.0.0") console.log("Version Constraint (Unsupported): <v7.0.0");
}); });
} }
if (enm) { if (enm) {
enm.forEach((a) => { enm.forEach((a) => {
zip.readFileContents(FILENAME, a, (c)=>{ zip.readFileContents(FILENAME, a, (c) => {
try { try {
let packageData = JSON.parse(c) let packageData = JSON.parse(c);
console.log("Found version in package.json file: " + packageData['version']) console.log(
}catch(e){ "Found version in package.json file: " + packageData["version"]
);
logSupport(`v${packageData["version"]}`)
} catch (e) {
// TODO: Do something // TODO: Do something
} }
}) });
}); });
} }
}); });

3
os.js
View File

@ -25,6 +25,9 @@ module.exports = {
} }
return null; return null;
}, },
guessArch(filename, entries) {
return 'x64';
},
guessFromContents(entries) { guessFromContents(entries) {
for (i in entries) { for (i in entries) {
let entry = entries[i] let entry = entries[i]

73
package-lock.json generated
View File

@ -13,7 +13,9 @@
"elfinfo": "*", "elfinfo": "*",
"hasha": "^5.2.2", "hasha": "^5.2.2",
"macho": "^1.4.0", "macho": "^1.4.0",
"node-7z": "^3.0.0" "node-7z": "^3.0.0",
"rimraf": "^3.0.2",
"semver-sort": "^0.0.4"
}, },
"bin": { "bin": {
"which-electron": "index.js" "which-electron": "index.js"
@ -385,6 +387,48 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"bin": {
"semver": "bin/semver"
}
},
"node_modules/semver-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz",
"integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/semver-sort": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/semver-sort/-/semver-sort-0.0.4.tgz",
"integrity": "sha1-NP293GprK0FhOYw8TbpWJDv+qos=",
"dependencies": {
"semver": "^5.0.3",
"semver-regex": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/signal-exit": { "node_modules/signal-exit": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
@ -698,6 +742,33 @@
"signal-exit": "^3.0.2" "signal-exit": "^3.0.2"
} }
}, },
"rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"requires": {
"glob": "^7.1.3"
}
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"semver-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz",
"integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk="
},
"semver-sort": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/semver-sort/-/semver-sort-0.0.4.tgz",
"integrity": "sha1-NP293GprK0FhOYw8TbpWJDv+qos=",
"requires": {
"semver": "^5.0.3",
"semver-regex": "^1.0.0"
}
},
"signal-exit": { "signal-exit": {
"version": "3.0.3", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",

View File

@ -32,7 +32,9 @@
"elfinfo": "*", "elfinfo": "*",
"hasha": "^5.2.2", "hasha": "^5.2.2",
"macho": "^1.4.0", "macho": "^1.4.0",
"node-7z": "^3.0.0" "node-7z": "^3.0.0",
"rimraf": "^3.0.2",
"semver-sort": "^0.0.4"
}, },
"devDependencies": { "devDependencies": {
"kuta": "*" "kuta": "*"

18
version.js Normal file
View File

@ -0,0 +1,18 @@
const semverSort = require('semver-sort');
const VERSIONS = require('./versions')
module.exports = {
asText: function(listOfVersions) {
sorted = semverSort.asc(listOfVersions);
return `${sorted[0]}-${sorted[sorted.length-1]}`
},
max: function(listOfVersions) {
sorted = semverSort.asc(listOfVersions);
return sorted[sorted.length-1];
},
isSupported: function(v) {
return (VERSIONS['supported'].indexOf(v) !== -1)
}
}