ARTistGUI主要流程分析

来源:互联网 发布:u盘照片如何导入mac 编辑:程序博客网 时间:2024/06/11 09:59

通过应用层分析,ARTistGUI的主要处理函数在/ArtistGui/app/src/main/java/saarland/cispa/artist/artistgui/instrumentation/InstrumentationTask.java中,代码如下:

    @Override    public void run() {        Log.i(TAG, "Run() compiling and starting " + mRunConfig.app_package_name);        Log.i(TAG, "> apkPath:     " + mRunConfig.app_apk_file_path);        Log.i(TAG, "> codeLibName: " + mRunConfig.codeLibName);        Log.i(TAG, "> Keystore:    " + mRunConfig.keystore);        try {            ArtistThread.checkThreadCancellation();            prepareReporter();            reportProgress(10, "Preparing build environment");            String pathDex2oat = mInstrumenationStages.prepareEnvironment();            ArtistThread.checkThreadCancellation();            mInstrumenationStages.probePermissionAndDeleteOatFile();            ArtistThread.checkThreadCancellation();            reportProgress(40, "Merging CodeLib");            mInstrumenationStages.mergeCodeLib();            ArtistThread.checkThreadCancellation();            mInstrumenationStages.backupMergedApk();            ArtistThread.checkThreadCancellation();            reportProgress(50, "Compiling: " + mRunConfig.app_package_name);            mInstrumenationStages.runDex2OatCompilation(pathDex2oat);            ArtistThread.checkThreadCancellation();            reportProgress(90, "Compilation done, setting file permissions");            mInstrumenationStages.setOatFilePermissions();        } catch (InstrumentationException | ArtistInterruptedException e) {            reportResult(false);            return;        }        reportResult(true);    }

其中主要的函数为:

  • mInstrumenationStages.probePermissionAndDeleteOatFile();
  • mInstrumenationStages.mergeCodeLib();
  • mInstrumenationStages.backupMergedApk();
  • mInstrumenationStages.runDex2OatCompilation(pathDex2oat);
  • mInstrumenationStages.setOatFilePermissions();

这五个函数位于/ArtistGui/app/src/main/java/saarland/cispa/artist/artistgui/instrumentation/stages/InstrumentationStagesImpl.java,主要完成了对APK文件的处理,先看probePermissionAndDeleteOatFile:

    public void probePermissionAndDeleteOatFile() {        reportProgressDetails("Probing oat file permissions: " + mRunConfig.app_oat_file_path);        mRunConfig.oatOwner = AndroidUtils.getFileOwnerUid(mRunConfig.app_oat_file_path);        mRunConfig.oatGroup = AndroidUtils.getFileGroupId(mRunConfig.app_oat_file_path);        mRunConfig.oatPermissions = AndroidUtils.getFilePermissions(mRunConfig.app_oat_file_path);        mRunConfig.stats.oatFileSizeOriginal = new File(mRunConfig.app_oat_file_path).length();        Log.d(TAG, String.format("base.odex UID: %s GID: %s Permissions: %s Size: %s",                mRunConfig.oatOwner,                mRunConfig.oatGroup,                mRunConfig.oatPermissions,                mRunConfig.stats.oatFileSizeOriginal));        reportProgressDetails("Deleting existing oat file: " + mRunConfig.app_oat_file_path);        boolean success = deleteRootFile(mRunConfig.app_oat_file_path);        if (!success) {            Log.d(TAG, String.format("Failed to delete old base oat: %s - Continue", mRunConfig.app_oat_file_path));        }    }    private boolean deleteRootFile(final String filePath) {        final String cmd_rm_root_file = "rm " + filePath;        return ProcessExecutor.execute(cmd_rm_root_file, true,                ProcessExecutor.processName(mRunConfig.app_package_name, "rm_rootfile"));    }

该方法主要调用cmd命令删除原来的oat文件。
接下来看第二个函数mergeCodeLib:

    public void mergeCodeLib() throws InstrumentationException {        Log.d(TAG, "MergeCodeLib into: " + mRunConfig.app_apk_file_path);        String pathToApkSigned;        // deactivate injection upon user wish or if no code lib is provided        if (mRunConfig.codeLib != null) {            reportProgressDetails("Injecting CodeLib");            final File appApk = new File(mRunConfig.app_apk_file_path);            final File codeLibApk = mRunConfig.codeLib;            setupCodeLib();            final MergeConfig mergeConfig = new MergeConfig(mRunConfig.codeLib.getName(),                    mRunConfig.app_apk_merged_file_path, mRunConfig.app_apk_file_path);            Dexterous dexterous = new Dexterous(mergeConfig);            dexterous.init(appApk, codeLibApk);            dexterous.mergeCodeLib();            final String pathToApk = dexterous.buildApk();            reportProgressDetails("Resigning APK");            Log.d(TAG, String.format("MergeCodeLib DONE (%s)", pathToApk));            pathToApkSigned = resignApk(pathToApk);            Log.d(TAG, String.format("MergeCodeLib Signing DONE (%s)", pathToApkSigned));            if (pathToApkSigned.isEmpty()) {                throw new InstrumentationException("Codelib Merge Failed");            }        } else {            reportProgressDetails("Not Injecting CodeLib");            Log.i(TAG, "Skip CodeLib Injection");            Log.d(TAG, "MergeCodeLib SKIPPED");        }    }    private void setupCodeLib() {        if (mRunConfig.codeLibName.startsWith(ArtistUtils.CODELIB_ASSET)) {            Log.d(TAG, "setupCodeLib() " + mRunConfig.codeLibName);            final String assetName = mRunConfig.codeLibName.replaceFirst(ArtistUtils.CODELIB_ASSET, "");            AndroidUtils.copyAsset(mContext, "codelib" + File.separator + assetName,                    mRunConfig.codeLib.getAbsolutePath());            if (!mRunConfig.codeLib.exists()) {                Log.e(TAG, " setupCodeLib: " + mRunConfig.codeLib + " FAILED");            } else {                Log.d(TAG, " setupCodeLib: " + mRunConfig.codeLib + " READY");            }        }    }    private String resignApk(final String unsignedApkPath) {        Log.d(TAG, "resignApk() " + unsignedApkPath);        String signedApkPath;        final ApkSigner apkSir = new ApkZipSir(mRunConfig.app_apk_merged_signed_file_path);        try {            signedApkPath = apkSir.signApk(mRunConfig.keystore.getAbsolutePath(), unsignedApkPath);        } catch (final IllegalArgumentException e) {            Log.e(TAG, "> Signing of APK Failed", e);            signedApkPath = "";        }        return signedApkPath;    }

其中setupCodeLib将codelib的apk文件复制到codelib文件夹下,为下一步做准备。
Dexterous用来将codelib的dex合并到目标apk的dex中去,并重新签名。

接下来进行backupMergedApk:

public void backupMergedApk() {    if (!mRunConfig.BACKUP_APK_MERGED) {        Log.v(TAG, "Skip: backupMergedApk()");        return;    }    Log.v(TAG, "backupMergedApk()");    final File sdcard = Environment.getExternalStorageDirectory();    DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss", Locale.getDefault());    Date date = new Date();    final String mergedApkBackupPath = sdcard.getAbsolutePath() + File.separator            + mRunConfig.app_package_name + "_merged_signed_" + dateFormat.format(date) + ".apk";    reportProgressDetails("Backing up Merged APK: " + mergedApkBackupPath);    final String cmd_backup_merged_apk = "cp " + mRunConfig.app_apk_merged_signed_file_path +            " " + mergedApkBackupPath;    boolean success = ProcessExecutor.execute(cmd_backup_merged_apk, true,            ProcessExecutor.processName(mRunConfig.app_package_name, "cp_backup_merged"));    if (success) {        Log.d(TAG, "backupMergedApk() Success: " + mergedApkBackupPath);    } else {        Log.e(TAG, "backupMergedApk() Failed:  " + mergedApkBackupPath);    }}

此方法将上一步生成的apk文件备份到指定目录下。

接下来进行核心功能runDex2OatCompilation来编译生成新的oat文件:

    public void runDex2OatCompilation(String pathDex2oat) throws InstrumentationException {        final String cmd_dex2oat_compile = setupDex2oatCommand(pathDex2oat);        Log.d(TAG, "dex2oat command:");        Log.d(TAG, cmd_dex2oat_compile);        Log.d(TAG, "Starting the compilation process!");        Log.d(TAG, "> Result will get placed at: " + mRunConfig.app_oat_file_path);        final String divider = "########################################################";        Log.d(TAG, divider);        Log.d(TAG, divider);        Log.d(TAG, divider);        boolean success = ProcessExecutor.execute(cmd_dex2oat_compile, true,                ProcessExecutor.processName(mRunConfig.app_package_name, "dex2artist"));        Log.d(TAG, divider);        Log.d(TAG, divider);        Log.d(TAG, divider);        if (success) {            Log.d(TAG, "Compilation was successfull");        } else {            Log.d(TAG, "Compilation failed...");            throw new InstrumentationException("Artist Injection Failed");        }    }

其中setupDex2oatCommand会生成对应指令,此指令用来将指定的apk文件中的dex生成oat文件,当然这里的dex2oat使用的是ARTist生成的新的dex2oat,下面是一个示例的setupDex2oatCommand生成的指令

  • export LD_LIBRARY_PATH=/data/app/saarland.cispa.artist.artistgui-1/lib/arm:/data/user/0/saarland.cispa.artist.artistgui/files/artist/lib/;/data/user/0/saarland.cispa.artist.artistgui/files/artist/dex2oat –oat-file=/data/app/com.xidian.testapp-1/oat/arm/base.odex –compiler-backend=Optimizing –compiler-filter=everything –generate-debug-info –compile-pic –dex-file=/data/user/0/saarland.cispa.artist.artistgui/files/base_merged-signed.apk –dex-location=/data/app/com.xidian.testapp-1/base.apk –checksum-rewriting

然后通过ProcessExecutor.processName方法就把cmd命令交给系统处理了,最终生成oat文件。

下一步通过setOatFilePermissions方法处理文件权限,处理结束。。。

原创粉丝点击