bananalyzer
Version:
A simple tool for windows 10, that downloads APKs from Google playstore, analyzes them, and lists all the Google and Huawei SDKs (kits) that are integrated, along with other metadata
165 lines (164 loc) • 8.33 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.analyzeAPKs = void 0;
var debug_1 = __importDefault(require("debug"));
var decompile_1 = require("./apktool/decompile");
('use strict');
/**
* this script analyzed the apk using the tool appcheck.jar,
* then parses the bad results generated by this tool into a human readable text thats easy to read does not hurt the eye lol
*
*/
var fs_1 = __importDefault(require("fs"));
var consts_1 = require("../consts");
var AnalyzeApkToolYml_1 = __importDefault(require("./analyzer/AnalyzeApkToolYml"));
var AnalyzeKits_1 = require("./analyzer/AnalyzeKits");
var AnalyzeManifest_1 = __importDefault(require("./analyzer/AnalyzeManifest"));
var AnalyzeSdks_1 = require("./analyzer/sdkAnalyzer/AnalyzeSdks");
var rimraf_1 = __importDefault(require("rimraf"));
var frameworkDetector_1 = require("./analyzer/frameworkDetector");
var debug = (0, debug_1.default)('bananalyzer:analyzer');
/**
*
* @param {array} apks: list of downloaded apps/apk to analyze, example = [
* {packageName:"package.name":filePath:"path/to/file.apk", uploadDate:"may 27, 2021"}
* ]
* @return {AnalyzedApp[]} resolved when all apks in packageNamesObj are analyzed
*/
var analyzeAPKs = function (apks, keepDecompiledSources) {
if (keepDecompiledSources === void 0) { keepDecompiledSources = false; }
return new Promise(function (resolve, reject) { return __awaiter(void 0, void 0, void 0, function () {
var results, _i, apks_1, apk, decRes, appCheckResult, manifestResult, sdkPerDomain, apkToolYmlResult, apkFileResult, framework;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
debug('analyzer:analyzing ', apks);
if (!fs_1.default.existsSync(consts_1.APP_DATA_FOLDER))
fs_1.default.mkdirSync(consts_1.APP_DATA_FOLDER);
results = [];
_i = 0, apks_1 = apks;
_a.label = 1;
case 1:
if (!(_i < apks_1.length)) return [3 /*break*/, 8];
apk = apks_1[_i];
return [4 /*yield*/, (0, decompile_1.decompileApk)(apk)];
case 2:
decRes = _a.sent();
debug('decompile res:', decRes);
if (!!decRes.error) {
console.log('error while decoding APK: ', decRes.error);
return [3 /*break*/, 7];
}
return [4 /*yield*/, (0, AnalyzeKits_1.analyzeGmsHmsSdks)(apk)];
case 3:
appCheckResult = _a.sent();
return [4 /*yield*/, (0, AnalyzeManifest_1.default)(decRes.manifestPath)];
case 4:
manifestResult = _a.sent();
return [4 /*yield*/, (0, AnalyzeSdks_1.analyzeSdks)(decRes.decompileFolderPath)];
case 5:
sdkPerDomain = _a.sent();
sdkPerDomain.splice(0, 0, {
domain: 'HMS',
sdks: manifestResult.hmsVersions.filter(function (sdk) { return sdk.accuracy == 'high'; }),
});
apkToolYmlResult = (0, AnalyzeApkToolYml_1.default)(decRes.apkToolYmlPath);
apkFileResult = analyzeApk(apk);
return [4 /*yield*/, (0, frameworkDetector_1.getFramework)(decRes.decompileFolderPath)
// debug('apkfileresult', apkFileResult);
];
case 6:
framework = _a.sent();
// debug('apkfileresult', apkFileResult);
results.push(__assign(__assign(__assign(__assign(__assign({}, appCheckResult), manifestResult), apkToolYmlResult), apkFileResult), { framework: framework, sdkPerDomain: sdkPerDomain }));
if (!keepDecompiledSources && !!decRes.decompileFolderPath) {
debug('will delete sources');
try {
(0, rimraf_1.default)(decRes.decompileFolderPath, function (err) {
debug('rimraf done, err:', err);
});
}
catch (e) {
debug('failed to rimraf decompile folder');
debug(e);
}
}
_a.label = 7;
case 7:
_i++;
return [3 /*break*/, 1];
case 8:
resolve(results);
return [2 /*return*/];
}
});
}); });
};
exports.analyzeAPKs = analyzeAPKs;
var analyzeApk = function (apk) {
// get apk last modification time
var apkCreationTime = '';
try {
var stat = fs_1.default.statSync(apk.filePath);
// console.log(stat);
if (!!stat.mtime)
apkCreationTime = stat.mtime.toLocaleString();
}
catch (e) {
debug('failed to get stats', e);
}
return {
storeUploadDate: apk.uploadDate || '',
apkCreationTime: apkCreationTime,
};
};