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方法处理文件权限,处理结束。。。
- ARTistGUI主要流程分析
- 分析av_open_input_file的主要流程
- eMule源码主要调用流程分析
- webrick源码分析──主要流程
- Hadoop源码分析笔记(八):HDFS主要流程
- Hadoop源码分析7: IPC流程(1) 主要类
- Hadoop源码分析33 Child的主要流程
- 【原创】k8s源码分析-----kubelet(1)主要流程
- ffplay的简化版,用于分析ffplay主要流程
- Android6.0 Telephony流程分析——PhoneApp启动主要类关系分析
- EDA设计主要流程
- 主要流程设想
- Ogre主要渲染流程
- ICS Overlay主要流程
- openssl主要流程程序代码
- openssl主要流程程序代码
- caffe训练主要流程
- caffe卷积主要流程
- 小C语言--词法分析程序
- IE6 浏览器常见兼容问题 大汇总
- PostgreSQL 多字段任意组合搜索的性能
- linux中搭建java环境
- 安装 cassandra,使用基本的cqlsh
- ARTistGUI主要流程分析
- 前端第一篇总结
- 条款06:若不想编译器自动生成的函数,就该明确拒绝
- Server returned error code = 401
- 记录一个遇到的坑 请求数据时遇见 provisional headers are shown!
- 使用mongoDB的一些新的(mongoDB报错解决)
- 机器学习入门书目推荐
- Spark Streaming基本使用介绍
- hadoop集群启动jps查看后没有DATANODE