react-native-decompiler
Version:
react native decompile apk and ipa(soon)
280 lines (278 loc) • 30.7 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_extra_1 = __importDefault(require("fs-extra"));
const perf_hooks_1 = require("perf_hooks");
const prettier_1 = __importDefault(require("prettier"));
const generator_1 = __importDefault(require("@babel/generator"));
const command_line_args_1 = __importDefault(require("command-line-args"));
const chalk_1 = __importDefault(require("chalk"));
const crypto_1 = __importDefault(require("crypto"));
const eslint_1 = require("eslint");
const taggerList_1 = __importDefault(require("./taggers/taggerList"));
const editorList_1 = __importDefault(require("./editors/editorList"));
const router_1 = __importDefault(require("./router"));
const decompilerList_1 = __importDefault(require("./decompilers/decompilerList"));
const cacheParse_1 = __importDefault(require("./cacheParse"));
const eslintConfig_1 = __importDefault(require("./eslintConfig"));
const fileParserRouter_1 = __importDefault(require("./fileParsers/fileParserRouter"));
const performanceTracker_1 = __importDefault(require("./util/performanceTracker"));
const progressBar_1 = __importDefault(require("./util/progressBar"));
function calculateModulesToIgnore(argValues, modules) {
if (argValues.agressiveCache)
return [];
return modules.filter((mod) => {
const dependentModules = modules.filter((otherMod) => otherMod.dependencies.includes(mod.moduleId));
return !mod.ignored && dependentModules.length > 0 && dependentModules.every((otherMod) => otherMod.ignored || mod.dependencies.includes(otherMod.moduleId));
});
}
const argValues = command_line_args_1.default([
{ name: 'in', alias: 'i' },
{ name: 'out', alias: 'o' },
{ name: 'entry', alias: 'e', type: Number },
{ name: 'performance', alias: 'p', type: Boolean },
{ name: 'verbose', alias: 'v', type: Boolean },
{ name: 'es6', type: Boolean },
{ name: 'noEslint', type: Boolean },
{ name: 'noPrettier', type: Boolean },
{ name: 'decompileIgnored', type: Boolean },
{ name: 'agressiveCache', type: Boolean },
{ name: 'unpackOnly', type: Boolean },
{ name: 'noProgress', type: Boolean },
{ name: 'debug', type: Number },
]);
if (!argValues.in || !argValues.out) {
console.log(`react-native-decompiler
Example command: react-native-decompiler -i index.android.bundle -o ./output
Command params:
-i (required) - the path to the input file/folder
-o (required) - the path to the output folder
-e - a module ID, if specified will only decompile that module & it's dependencies. also creates cache file to speed up future load times (useful for developing new plugins)
-p - performance monitoring flag, will print out runtime for each decompiler plugin
-v - verbose flag, does not include debug logging (use DEBUG=react-native-decompiler:* env flag for that)
--es6 - attempts to decompile to ES6 module syntax.
--noEslint - does not run ESLint after doing decompilation
--noPrettier - does not run Prettier after doing decompilation
--unpackOnly - only unpacks the app with no other adjustments
--decompileIgnored - decompile ignored modules(modules are generally ignored if they are flagged as an NPM module)
--agressiveCache - skips some cache checks at the expense of possible cache desync`);
process.exit(0);
}
if (argValues.performance) {
performanceTracker_1.default.enable();
}
if (argValues.noProgress) {
progressBar_1.default.disable();
}
async function start() {
var _a;
try {
const progressBar = progressBar_1.default.getInstance();
const cacheFileName = `${argValues.out}/${(_a = argValues.entry) !== null && _a !== void 0 ? _a : 'null'}.cache`;
let startTime = perf_hooks_1.performance.now();
fs_extra_1.default.ensureDirSync(argValues.out);
if (!fs_extra_1.default.existsSync(argValues.in)) {
console.error(`${chalk_1.default.red('[!]')} "${argValues.in}" does not exist!"`);
process.exit(1);
}
console.log('Reading file...');
const fileParserRouter = new fileParserRouter_1.default();
const modules = await fileParserRouter.route(argValues);
if (modules == null || modules.length === 0) {
console.error(`${chalk_1.default.red('[!]')} No modules were found!`);
console.error(`${chalk_1.default.red('[!]')} Possible reasons:`);
console.error(`${chalk_1.default.red('[!]')} - The React Native app is unbundled. If it is, export the "js-modules" folder from the app and provide it as the --js-modules argument`);
console.error(`${chalk_1.default.red('[!]')} - The bundle is a Hermes/binary file (ex. Facebook, Instagram). These files are not supported`);
console.error(`${chalk_1.default.red('[!]')} - The provided Webpack bundle input is not or does not contain the entrypoint bundle`);
console.error(`${chalk_1.default.red('[!]')} - The provided Webpack bundle was built from V5, which is not supported`);
console.error(`${chalk_1.default.red('[!]')} - The file provided is not a React Native or Webpack bundle.`);
process.exit(1);
}
if (argValues.entry != null && (!argValues.agressiveCache)) {
console.log('Entry module provided, filtering out unused modules');
const entryModuleDependencies = new Set();
let lastDependenciesSize = 0;
entryModuleDependencies.add(argValues.entry);
while (lastDependenciesSize !== entryModuleDependencies.size) {
lastDependenciesSize = entryModuleDependencies.size;
entryModuleDependencies.forEach((moduleId) => {
const module = modules.find((mod) => (mod === null || mod === void 0 ? void 0 : mod.moduleId) === moduleId);
if (module) {
module.dependencies.forEach((dep) => entryModuleDependencies.add(dep));
}
});
}
modules.forEach((mod, i) => {
if (!entryModuleDependencies.has(mod.moduleId)) {
delete modules[i];
}
});
}
let nonIgnoredModules = modules.filter((mod) => argValues.decompileIgnored || !mod.ignored);
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
startTime = perf_hooks_1.performance.now();
console.log('Pre-parsing modules...');
progressBar.start(0, nonIgnoredModules.length);
nonIgnoredModules.forEach((module) => {
module.validate();
module.unpack();
progressBar.increment();
});
progressBar.stop();
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
if (!argValues.unpackOnly) {
startTime = perf_hooks_1.performance.now();
console.log('Tagging...');
progressBar.start(0, nonIgnoredModules.length);
const taggerRouters = nonIgnoredModules.map((m) => new router_1.default(taggerList_1.default, m, modules, argValues));
for (let pass = 1; pass <= taggerRouters[0].maxPass; pass += 1) {
taggerRouters.forEach((r) => r.runPass(pass));
if (pass === taggerRouters[0].maxPass) {
progressBar.increment();
}
}
progressBar.stop();
if (argValues.performance) {
console.log(`Traversal took ${router_1.default.traverseTimeTaken}ms`);
console.log(router_1.default.timeTaken);
router_1.default.timeTaken = {};
router_1.default.traverseTimeTaken = 0;
}
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
startTime = perf_hooks_1.performance.now();
console.log('Filtering out modules only depended on ignored modules...');
let modulesToIgnore = [];
modulesToIgnore = calculateModulesToIgnore(argValues, modules);
while (modulesToIgnore.length) {
modulesToIgnore.forEach((mod) => {
mod.ignored = true;
});
modulesToIgnore = calculateModulesToIgnore(argValues, modules);
}
if (argValues.verbose) {
console.table(modules.map((mod) => {
const dependentModules = modules.filter((otherMod) => otherMod.dependencies.includes(mod.moduleId));
return {
moduleName: mod.moduleName,
ignored: mod.ignored,
dependencies: mod.dependencies.filter((e) => e != null),
dependents: dependentModules.map((m) => m.moduleId),
};
}));
console.table(modules.filter((m) => !m.ignored || m.isNpmModule).map((mod) => {
const dependentModules = modules.filter((otherMod) => otherMod.dependencies.includes(mod.moduleId));
if (mod.isNpmModule && !dependentModules.filter((m) => !m.ignored).length)
return null;
return {
moduleName: mod.moduleName,
ignored: mod.ignored,
dependencies: mod.dependencies.filter((e) => e != null),
dependents: dependentModules.filter((m) => !m.ignored).map((m) => m.moduleId),
};
}).filter((e) => e != null));
}
nonIgnoredModules = modules.filter((mod) => argValues.decompileIgnored || !mod.ignored);
console.log(`${nonIgnoredModules.length} remain to be decompiled`);
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
startTime = perf_hooks_1.performance.now();
console.log('Decompiling...');
progressBar.start(0, nonIgnoredModules.length);
const editorRouters = nonIgnoredModules.map((m) => new router_1.default(editorList_1.default, m, modules, argValues));
for (let pass = 1; pass <= editorRouters[0].maxPass; pass += 1) {
editorRouters.forEach((r) => r.runPass(pass));
}
const decompilerRouter = nonIgnoredModules.map((m) => new router_1.default(decompilerList_1.default, m, modules, argValues));
for (let pass = 1; pass <= decompilerRouter[0].maxPass; pass += 1) {
decompilerRouter.forEach((r) => r.runPass(pass));
if (pass === decompilerRouter[0].maxPass) {
progressBar.increment();
}
}
progressBar.stop();
if (argValues.performance) {
console.log(`Traversal took ${router_1.default.traverseTimeTaken}ms`);
console.log(`Recrawl took ${router_1.default.recrawlTimeTaken}ms`);
console.log(router_1.default.timeTaken);
}
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
}
startTime = perf_hooks_1.performance.now();
console.log('Generating code...');
progressBar.start(0, nonIgnoredModules.length);
const eslint = new eslint_1.ESLint({
fix: true,
ignore: false,
useEslintrc: false,
extensions: ['.js', '.jsx'],
overrideConfig: eslintConfig_1.default,
});
const generatedFiles = await Promise.all(nonIgnoredModules.map(async (module) => {
var _a;
if (module.previousRunChecksum === crypto_1.default.createHash('md5').update(JSON.stringify(module.moduleCode.body)).digest('hex'))
return null;
const returnValue = {
name: module.moduleId,
extension: module.tags.includes('jsx') ? 'jsx' : 'js',
code: generator_1.default({
...module.originalFile.program,
type: 'Program',
body: module.moduleCode.body,
}).code,
};
if (!argValues.noEslint && !argValues.unpackOnly) {
try {
const lintedCode = await eslint.lintText(returnValue.code);
returnValue.code = (_a = lintedCode[0].output) !== null && _a !== void 0 ? _a : returnValue.code;
}
catch (e) { }
}
if (!argValues.noPrettier) {
try {
returnValue.code = prettier_1.default.format(returnValue.code, { parser: 'babel', singleQuote: true, printWidth: 180 });
}
catch (e) { }
}
progressBar.increment();
return returnValue;
}));
progressBar.stop();
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
startTime = perf_hooks_1.performance.now();
console.log('Saving...');
progressBar.start(0, nonIgnoredModules.length);
generatedFiles.forEach((file) => {
if (file == null)
return;
const filePath = `${argValues.out}/${file.name}.${file.extension}`;
if (!fs_extra_1.default.existsSync(filePath) || fs_extra_1.default.readFileSync(filePath, 'utf-8') !== file.code) {
fs_extra_1.default.writeFileSync(filePath, file.code);
}
progressBar.increment();
});
modules.forEach((m) => {
if (!m.isStatic)
return;
const filePath = `${argValues.out}/${m.moduleId}.${m.tags.includes('css') ? 'css' : '?'}`;
if (!fs_extra_1.default.existsSync(filePath) || fs_extra_1.default.readFileSync(filePath, 'utf-8') !== m.staticContent) {
fs_extra_1.default.writeFileSync(filePath, m.staticContent);
}
});
progressBar.stop();
if (!fs_extra_1.default.existsSync(cacheFileName) || !argValues.agressiveCache) {
console.log('Writing to cache...');
await new cacheParse_1.default(argValues).writeCache(cacheFileName, modules);
}
console.log(`Took ${perf_hooks_1.performance.now() - startTime}ms`);
console.log('Done!');
}
catch (e) {
console.error(`${chalk_1.default.red('[!]')} Error occurred! You should probably report this.`);
console.error(e);
process.exit(1);
}
}
start();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9tYWluLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQWlCQSx3REFBK0I7QUFDL0IsMkNBQXlDO0FBQ3pDLHdEQUFnQztBQUNoQyxpRUFBeUM7QUFDekMsMEVBQWdEO0FBQ2hELGtEQUEwQjtBQUMxQixvREFBNEI7QUFDNUIsbUNBQWdDO0FBRWhDLHNFQUE4QztBQUM5QyxzRUFBOEM7QUFDOUMsc0RBQThCO0FBQzlCLGtGQUEwRDtBQUMxRCw4REFBc0M7QUFDdEMsa0VBQTBDO0FBRTFDLHNGQUE4RDtBQUM5RCxtRkFBMkQ7QUFDM0QscUVBQTZDO0FBRTdDLFNBQVMsd0JBQXdCLENBQUMsU0FBa0IsRUFBRSxPQUFpQjtJQUNyRSxJQUFJLFNBQVMsQ0FBQyxjQUFjO1FBQUUsT0FBTyxFQUFFLENBQUM7SUFDeEMsT0FBTyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUU7UUFDNUIsTUFBTSxnQkFBZ0IsR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNwRyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sSUFBSSxHQUFHLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztJQUMvSixDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxNQUFNLFNBQVMsR0FBRywyQkFBZSxDQUFVO0lBQ3pDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFO0lB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