├── .gitignore ├── .idea ├── .gitignore ├── codeStyles │ └── codeStyleConfig.xml ├── compiler.xml ├── libraries │ ├── Maven__com_google_code_findbugs_jsr305_1_3_9.xml │ ├── Maven__com_google_errorprone_error_prone_annotations_2_0_18.xml │ ├── Maven__com_google_guava_guava_22_0.xml │ ├── Maven__com_google_j2objc_j2objc_annotations_1_1.xml │ ├── Maven__com_luhuiguo_chinese_utils_1_0.xml │ ├── Maven__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml │ ├── Maven__org_dom4j_dom4j_2_1_1.xml │ ├── Maven__org_json_json_20180813.xml │ └── Maven__org_projectlombok_lombok_1_16_10.xml ├── misc.xml ├── modules.xml ├── uiDesigner.xml ├── vcs.xml └── workspace.xml ├── FakerAndroid.iml ├── LICENSE ├── README.md ├── cmd └── Il2Cpp.exe ├── lib ├── apksigner.jar └── apktool_2.4.1.jar ├── patch ├── Manifest-javaScaffoding │ └── AndroidManifest.xml ├── build-app │ └── build.gradle ├── build-javaScaffoding │ └── build.gradle ├── build-project │ ├── build.gradle │ ├── gradle.properties │ └── settings.gradle ├── cpp │ ├── CMakeLists.txt │ ├── Common.h │ ├── Constant.h │ ├── include │ │ └── faker.h │ └── native-lib.cpp ├── il2cpp-cpp │ ├── CMakeLists.txt │ ├── Common.h │ ├── Constant.h │ ├── include │ │ └── faker.h │ └── native-lib.cpp ├── il2cpp-java │ └── com │ │ └── faker │ │ └── android │ │ ├── FakerApp.java │ │ ├── FakerUnityActivity.java │ │ ├── JavaPatch.java │ │ ├── Logger.java │ │ ├── RefInvoke.java │ │ └── WebViewActivity.java ├── il2cpp-libs-javaScaffoding │ └── unity-classes.jar ├── java-javaScaffoding │ └── com │ │ └── fakler │ │ └── java │ │ └── scaffoding │ │ ├── TestApplication.java │ │ └── TestMainActivity.java ├── java │ └── com │ │ └── faker │ │ └── android │ │ ├── FakerActivity.java │ │ ├── FakerApp.java │ │ ├── Logger.java │ │ ├── RefInvoke.java │ │ └── WebViewActivity.java ├── jniLibs │ ├── arm64-v8a │ │ ├── libfaker.so │ │ └── libswap.so │ └── armeabi-v7a │ │ ├── libfaker.so │ │ └── libswap.so ├── libs-javaScaffoding │ └── unity-classes.jar ├── res │ ├── drawable │ │ ├── back_whait.png │ │ ├── h_splash.png │ │ └── splash.png │ ├── layout │ │ └── unity_webview_layout.xml │ ├── mipmap-anydpi-v26 │ │ ├── app_icon.xml │ │ └── app_icon_round.xml │ ├── mipmap-mdpi │ │ ├── app_icon.png │ │ ├── ic_launcher_background.png │ │ └── ic_launcher_foreground.png │ ├── values-v21 │ │ └── styles.xml │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml └── scaffolding-cpp │ ├── MonoString.cpp │ ├── MonoString.h │ ├── il2cpp-appdata.h │ ├── il2cpp-init.cpp │ └── il2cpp-init.h ├── pom.xml ├── src └── main │ └── java │ └── com │ └── facker │ └── toolchain │ ├── FakerCmd.java │ ├── FakerMain.java │ ├── FakerTransfer.java │ ├── api │ └── xbase │ │ ├── ApkTool.java │ │ ├── DecodeApk.java │ │ ├── IImporter.java │ │ ├── IWorker.java │ │ ├── IWorkerAdapter.java │ │ ├── Importer.java │ │ ├── ManifestEditor.java │ │ ├── NetworkSecurityConfigEditor.java │ │ ├── PathEditor.java │ │ ├── PublicMerge.java │ │ ├── ResMerge.java │ │ ├── Result.java │ │ ├── SourceCode.java │ │ ├── SrcDecodeApk.java │ │ ├── TextUtil.java │ │ ├── ValuesMod.java │ │ ├── Worker.java │ │ ├── WorkerAction.java │ │ ├── WorkerListener.java │ │ ├── XBridge.java │ │ ├── XMLMod.java │ │ ├── XModel.java │ │ ├── XSrcTarget.java │ │ ├── XTarget.java │ │ ├── YmlMod.java │ │ └── action │ │ ├── Check.java │ │ ├── CopyBridgeDex.java │ │ ├── GatherFlip.java │ │ ├── MergeBridgeAssets.java │ │ ├── MergeBridgeLib.java │ │ ├── MergeBridgeMainifest.java │ │ ├── MergeBridgeRes.java │ │ ├── MergeModelsAssets.java │ │ ├── MergeModelsLib.java │ │ ├── MergeModelsMainifest.java │ │ ├── MergeModelsRes.java │ │ ├── ModTargetLogo.java │ │ ├── ModXTargetYml.java │ │ └── OrlderXTargetAndXModelsDex.java │ ├── arsc │ ├── ArscChunk.java │ ├── ArscComplex.java │ ├── ArscDataType.java │ ├── ArscHeader.java │ ├── ArscParser.java │ ├── ArscParserTest.java │ ├── ArscResStringPoolRef.java │ ├── ArscResTableConfig.java │ ├── ArscResTableEntry.java │ ├── ArscResTypeSpec.java │ ├── ArscTableType.java │ ├── BuildAble.java │ ├── DefaultArscHolder.java │ ├── ResType.java │ ├── StringPoolReader.java │ └── TablePackageType.java │ ├── axml │ ├── BinXmlHelper.java │ ├── BinXmlParser.java │ ├── ByteUtil.java │ ├── DefaultIdHolder.java │ ├── GreplayXmlHelper.java │ ├── IdHolder.java │ ├── Main.java │ └── struct │ │ ├── AttributeData.java │ │ ├── AttributeType.java │ │ ├── Chunk.java │ │ ├── ChunkTypeNumber.java │ │ ├── EndNameSpaceChunk.java │ │ ├── EndTagChunk.java │ │ ├── ResourceChunk.java │ │ ├── StartNameSpaceChunk.java │ │ ├── StartTagChunk.java │ │ ├── StringChunk.java │ │ ├── StringPool.java │ │ ├── StringPoolImpl.java │ │ ├── TagChunk.java │ │ └── TextChunk.java │ ├── base │ ├── beta │ │ ├── PathUtil.java │ │ └── TestClassify.java │ ├── mod │ │ ├── ApkSignerTool.java │ │ ├── Constant.java │ │ ├── DealApk.java │ │ ├── FuckApk.java │ │ ├── HexEncoding.java │ │ ├── OptionsParser.java │ │ ├── PasswordRetriever.java │ │ └── StaticInjector.java │ ├── packer │ │ ├── Main.java │ │ ├── Packer.java │ │ └── SafeString.java │ └── utils │ │ ├── IOUtil.java │ │ ├── SignUtil.java │ │ └── ZipUtil.java │ ├── network │ └── NetworkProcesser.java │ ├── test │ ├── MSmaliBuilder.java │ ├── SmaliTest.java │ └── SplitApksMerge.java │ └── utils │ ├── AaptApk.java │ ├── ApkSignerTool.java │ ├── ApkTool.java │ ├── ApkUtils.java │ ├── FileReader.java │ ├── FileUtil.java │ ├── HexEncoding.java │ ├── IOUtil.java │ ├── Logger.java │ ├── ManifestEditor.java │ ├── OptionsParser.java │ ├── PasswordRetriever.java │ ├── SignUtil.java │ ├── SystemUtils.java │ ├── TextUtil.java │ └── ZipUtil.java └── target └── classes └── com └── facker └── toolchain ├── FakerMain.class ├── FakerMain.java ├── base ├── beta │ ├── PathUtil.class │ ├── PathUtil.java │ └── TestClassify.class ├── mod │ ├── ApkSignerTool$1.class │ ├── ApkSignerTool$ParameterException.class │ ├── ApkSignerTool$ProviderInstallSpec.class │ ├── ApkSignerTool$SignerParams.class │ ├── ApkSignerTool.class │ ├── Constant$PATH.class │ ├── Constant.class │ ├── Constant.java │ ├── DealApk.class │ ├── FuckApk.class │ ├── FuckApk.java │ ├── HexEncoding.class │ ├── OptionsParser$OptionsException.class │ ├── OptionsParser.class │ ├── PasswordRetriever.class │ ├── StaticInjector.class │ └── StaticInjector.java ├── packer │ ├── Main.class │ ├── Main.java │ ├── Packer.class │ └── SafeString.class └── utils │ ├── IOUtil.class │ ├── SignUtil.class │ └── ZipUtil.class ├── test ├── MSmaliBuilder.class ├── SmaliTest.class └── SplitApksMerge.class └── utils ├── AaptApk.class ├── ApkSignerTool$1.class ├── ApkSignerTool$ParameterException.class ├── ApkSignerTool$ProviderInstallSpec.class ├── ApkSignerTool$SignerParams.class ├── ApkSignerTool.class ├── ApkTool.class ├── ApkUtils$FileInfo.class ├── ApkUtils.class ├── ApkUtils.java ├── FileReader.class ├── FileUtil.class ├── HexEncoding.class ├── IOUtil.class ├── Logger.class ├── ManifestEditor.class ├── ManifestEditor.java ├── OptionsParser$OptionsException.class ├── OptionsParser.class ├── PasswordRetriever.class ├── SignUtil.class ├── SystemUtils.class ├── TextUtil.class └── ZipUtil.class /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /.idea/ 3 | /target/classes/com/facker/toolchain/ 4 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_code_findbugs_jsr305_1_3_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_errorprone_error_prone_annotations_2_0_18.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_guava_guava_22_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_j2objc_j2objc_annotations_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_luhuiguo_chinese_utils_1_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_codehaus_mojo_animal_sniffer_annotations_1_14.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_dom4j_dom4j_2_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_json_json_20180813.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_projectlombok_lombok_1_16_10.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /FakerAndroid.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Efaker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # FakerAndroid 3 | A tool translate apk file to common android project and support so hook and include il2cpp c++ scaffolding when apk is a il2cpp game apk 4 | ## 简介 5 | - 直接将Apk文件转换为可以进行二次开发的Android项目的工具,支持so hook,对于il2cpp的游戏apk直接生成il2cpp c++脚手架 6 | - 将痛苦的逆向环境,转化为舒服的开发环境,告别汇编,告别二进制,还有啥好说的~~ 7 | ## 特点 8 | 9 | - 基于AndroidStudio进行smali修改编译 10 | - 提供Java层代码覆盖及继承替换的脚手架 11 | - 提供so函数Hook Api 12 | - 对于il2cpp的游戏apk直接生成il2cpp c++脚手架 13 | - 无限的可能性和扩展性,能干啥你说了算~(比如把抖音改成快手,把快手改成抖音,做一个抖音快手版再做一个快手抖音版,好屌哦) 14 | 15 | ### 运行环境 16 | - Windows IntelliJ IDEA 17 | ### 入口程序 18 | - com.facker.toolchain.FakerMain 19 | ### 使用方式 20 | - ```FakerTransfer.translate(apkFilePath);``` 21 | - AndroidStudio 项目生成路径为Apk平级目录 22 | ### 生成的Android项目二次开发教程 23 | 24 | ##### 1、打开项目 25 | - Android studio直接打开工具生成的Android项目 26 | - 存在已知缺陷,res下的部分资源文件编译不过,需要手动修复,部分Manifest标签无法编译需要手动修复 27 | ##### 2、AndroidStudio安装FakerAndroid-Idea插件 28 | - [下载地址](https://github.com/Efaker/FakerAndroid-Idea/releases/tag/FakerAndroid-Idea0.0.1) 29 | - 安装教程AndroidStudio File->Settings->plugins->setting->install from disk->重新启动AndroidStudio 30 | ##### 3、调试运行项目 31 | - AndroidStudio Gradle->javaScaffoding->build->build 32 | - AndroidStudio->build->FakeSmali->等待smali文件构建完成 33 | - Run 项目(提醒:DEX缓存原因,修改smali文件后调试运行需要先卸载手机调试包,另外il2cpp game apk 第一次编译脚手架会比较慢) 34 | ##### 4、进阶 35 | - 借助javaScaffoding 使用java代码对smali 类继承 36 | 在javaScaffoding模块创建伪类,保持伪类类签名与要继承的类的smali文件路径名称对应->AndroidStudio右侧 Gradle->javaScaffoding->build->build,在主模块(app/src/main/java)中编写自己的类对伪类进行继承 37 | - 借助FakeSmali 使用java代码对smali 类替换 38 | 在主模块(app/src/main/java)编写自己的类,类签名与要替换的类的smali文件路径名称对应 39 | - 借助FakeCpp 使用jni对so函数进行hook替换 40 | 41 | 42 | - 借助il2cpp Scaffolding 和FakeCpp,使用jni对il2cpp游戏脚本进行二次开发 43 | 44 | 45 | ##### 5、遇到问题了?兄弟别走肯定能用,而且是你最佳的解决方案,咨询探讨 46 | - QQ:1404774249(加哦,咱需要知道问题去调优哦) 47 | - issues(在线解决) 48 | ##### 6、给个star?免费的 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /cmd/Il2Cpp.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/cmd/Il2Cpp.exe -------------------------------------------------------------------------------- /lib/apksigner.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/lib/apksigner.jar -------------------------------------------------------------------------------- /lib/apktool_2.4.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/lib/apktool_2.4.1.jar -------------------------------------------------------------------------------- /patch/Manifest-javaScaffoding/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /patch/build-app/build.gradle: -------------------------------------------------------------------------------- 1 | // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN 2 | apply plugin: 'com.android.application' 3 | 4 | dependencies { 5 | compileOnly files('../javaScaffoding/libs/unity-classes.jar'); 6 | compileOnly files('../javaScaffoding/build/intermediates/packaged-classes/release/classes.jar'); 7 | } 8 | 9 | android { 10 | compileSdkVersion 29 11 | buildToolsVersion '29.0.3' 12 | 13 | compileOptions { 14 | sourceCompatibility JavaVersion.VERSION_1_8 15 | targetCompatibility JavaVersion.VERSION_1_8 16 | } 17 | 18 | defaultConfig { 19 | minSdkVersion 23 20 | targetSdkVersion {targetSdkVersion} 21 | applicationId '{pkg}' 22 | ndk { 23 | abiFilters 'armeabi-v7a' 24 | } 25 | versionCode {versionCode} 26 | versionName '{versionName}' 27 | } 28 | 29 | aaptOptions { 30 | noCompress = ['.unity3d', '.ress', '.resource', '.obb'] 31 | ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~" 32 | } 33 | 34 | lintOptions { 35 | abortOnError false 36 | } 37 | externalNativeBuild { 38 | cmake { 39 | path "src/main/cpp/CMakeLists.txt" 40 | version "3.10.2" 41 | } 42 | } 43 | 44 | buildTypes { 45 | debug { 46 | minifyEnabled false 47 | useProguard false 48 | proguardFiles getDefaultProguardFile('proguard-android.txt') 49 | signingConfig signingConfigs.debug 50 | jniDebuggable true 51 | } 52 | release { 53 | minifyEnabled false 54 | useProguard false 55 | proguardFiles getDefaultProguardFile('proguard-android.txt') 56 | signingConfig signingConfigs.debug 57 | } 58 | } 59 | 60 | packagingOptions { 61 | doNotStrip '*/armeabi-v7a/*.so' 62 | } 63 | 64 | bundle { 65 | language { 66 | enableSplit = false 67 | } 68 | density { 69 | enableSplit = false 70 | } 71 | abi { 72 | enableSplit = true 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /patch/build-javaScaffoding/build.gradle: -------------------------------------------------------------------------------- 1 | // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN 2 | 3 | apply plugin: 'com.android.library' 4 | 5 | 6 | dependencies { 7 | implementation fileTree(dir: 'libs', include: ['*.jar']) 8 | } 9 | 10 | android { 11 | compileSdkVersion 29 12 | buildToolsVersion '29.0.3' 13 | 14 | compileOptions { 15 | sourceCompatibility JavaVersion.VERSION_1_8 16 | targetCompatibility JavaVersion.VERSION_1_8 17 | } 18 | 19 | defaultConfig { 20 | minSdkVersion 19 21 | targetSdkVersion 29 22 | ndk { 23 | abiFilters 'armeabi-v7a' 24 | } 25 | versionCode 1 26 | versionName '0.1' 27 | consumerProguardFiles 'proguard-unity.txt' 28 | } 29 | 30 | lintOptions { 31 | abortOnError false 32 | } 33 | 34 | aaptOptions { 35 | ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~" 36 | } 37 | 38 | packagingOptions { 39 | doNotStrip '*/armeabi-v7a/*.so' 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /patch/build-project/build.gradle: -------------------------------------------------------------------------------- 1 | // GENERATED BY UNITY. REMOVE THIS COMMENT TO PREVENT OVERWRITING WHEN EXPORTING AGAIN 2 | 3 | allprojects { 4 | buildscript { 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.4.0' 12 | 13 | } 14 | } 15 | 16 | repositories { 17 | google() 18 | jcenter() 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } 25 | -------------------------------------------------------------------------------- /patch/build-project/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx4096M 2 | android.injected.testOnly=false -------------------------------------------------------------------------------- /patch/build-project/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':javaScaffoding', ':app' -------------------------------------------------------------------------------- /patch/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | add_definitions(-DENABLE_DEBUG -DABC) 6 | cmake_minimum_required(VERSION 3.5) 7 | include_directories(src/main/cpp/include) 8 | file(GLOB native_srcc "${CMAKE_SOURCE_DIR}/*.cpp") 9 | add_library( 10 | swap #最终在build中生成的so名字 11 | SHARED 12 | IMPORTED) 13 | set_target_properties( 14 | swap #最终在build中生成的so名字 15 | PROPERTIES IMPORTED_LOCATION 16 | ../../../../src/main/jniLibs/${ANDROID_ABI}/libswap.so) #so 17 | add_library( 18 | faker #最终在build中生成的so名字 19 | SHARED 20 | IMPORTED) 21 | set_target_properties( 22 | faker #最终在build中生成的so名字 23 | PROPERTIES IMPORTED_LOCATION 24 | ../../../../src/main/jniLibs/${ANDROID_ABI}/libfaker.so) #so 25 | 26 | add_library( # Sets the name of the library. 27 | native-lib 28 | # Sets the library as a shared library. 29 | SHARED 30 | ${native_srcc} 31 | ) 32 | # Searches for a specified prebuilt library and stores the path as a 33 | # variable. Because CMake includes system libraries in the search path by 34 | # default, you only need to specify the name of the public NDK library 35 | # you want to add. CMake verifies that the library exists before 36 | # completing its build. 37 | 38 | find_library( # Sets the name of the path variable. 39 | log-lib 40 | # Specifies the name of the NDK library that 41 | # you want CMake to locate. 42 | log) 43 | # Specifies libraries CMake should link to your target library. You 44 | # can link multiple libraries, such as libraries you define in this 45 | # build script, prebuilt third-party libraries, or system libraries. 46 | 47 | target_link_libraries( # Specifies the target library. 48 | native-lib 49 | swap 50 | faker 51 | android 52 | ${log-lib}) -------------------------------------------------------------------------------- /patch/cpp/Common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #define LOG_TAG "xNative" 3 | #define DEBUG 4 | 5 | #ifdef DEBUG 6 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 7 | #define LOGD(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 8 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 9 | #else 10 | #define LOGI(...) NULL; 11 | #define LOGD(...) NULL; 12 | #define LOGE(...) NULL; 13 | #endif 14 | 15 | 16 | -------------------------------------------------------------------------------- /patch/cpp/Constant.h: -------------------------------------------------------------------------------- 1 | const char *MSG_TRIGGER_TAG_COMMON_PREFIX = "msg_trigger_tag_common_"; 2 | const char *MSG_TRIGGER_TAG_REWARD_PREFIX ="msg_trigger_tag_reward_"; 3 | const char *MSG_TRIGGER_LOCAL_PRIVACY ="msg_trigger_local_privacy"; 4 | const char *MSG_TRIGGER_LOCAL_TERMS ="msg_trigger_local_terms"; 5 | const char *MSG_TRIGGER_LOCAL_TATE ="msg_trigger_local_rate"; 6 | const char *MSG_TRIGGER_LOCAL_MORE_GAME ="msg_trigger_local_more_game"; -------------------------------------------------------------------------------- /patch/cpp/include/faker.h: -------------------------------------------------------------------------------- 1 | 2 | void onJniLoad(JavaVM *vm, void *reserved); 3 | /** 4 | * 安装修改后合并的DEX 5 | * @param env 6 | * @param instance 7 | * @param base 8 | * @param fakeDexAssetFileName 修改并合并后的DEX在Asset跟目录的文件名称 9 | */ 10 | void fakeDex(JNIEnv *env, jobject instance,jobject base,char *fakeDexAssetFileName); 11 | 12 | /** 13 | * 替换原有的application 14 | * @param env 15 | * @param instance 16 | * @param application 17 | * @param targetApp 原应用的Application名称 18 | * @return 19 | */ 20 | void fakeApp(JNIEnv *env, jobject instance,jobject application,jboolean b); 21 | 22 | /** 23 | * 获取So文件 基础地址 24 | * @param soname 例:libil2cpp.so 25 | * @return 26 | */ 27 | long baseAddr(char *soname); 28 | 29 | 30 | /** 31 | * Hook so 函数 = baseAddr+offset 函数偏移地址 32 | * @param function_address 原函数地址 33 | * @param replace_call 新函数 34 | * @param origin_call 虚构原函数,用于对原函数进行编码调用 35 | */ 36 | void fakeCpp(void *function_address, void *replace_call,void **origin_call); 37 | 38 | 39 | /** 40 | * 安装一个普通的DEX(非合并) 41 | * @param path 42 | * @return 43 | */ 44 | bool installDex(JNIEnv* env, jobject jobject, string dexPath); 45 | 46 | 47 | /** 48 | * 安装多个普通DEX(非合并) 49 | * @param path 50 | * @return 51 | */ 52 | bool installDex(JNIEnv* env, jobject jobject, vector* dexPaths); 53 | /** 54 | * 55 | * 1、获取so基础地址 56 | * 57 | * 2、hook so 函数 58 | * 59 | * 3、const char* coverIl2cppString2Char(Il2CppString *str); 60 | * 61 | * 4、dexInstaller 安装非合并DEX 62 | * 63 | * 5、fakeCpp 64 | */ 65 | 66 | 67 | -------------------------------------------------------------------------------- /patch/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Common.h" 4 | #include 5 | #include 6 | #include "Constant.h" 7 | using namespace std; 8 | #include "include/faker.h" 9 | JavaVM *global_jvm; 10 | 11 | JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { 12 | JNIEnv *env; 13 | if ((*vm).GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) == JNI_OK) { 14 | LOGI("JNI_OnLoad %s","sucess"); 15 | }else{ 16 | LOGI("JNI_OnLoad %s","erro"); 17 | } 18 | global_jvm = vm; 19 | onJniLoad(vm,reserved); 20 | return JNI_VERSION_1_6; 21 | } 22 | 23 | static jobject tmpAct; 24 | 25 | void callJava(const char *event) { 26 | JNIEnv* env; 27 | global_jvm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_4); 28 | jclass jclass1 = env->FindClass("com/faker/android/FakerActivity"); 29 | jmethodID jmethodID1 = env->GetMethodID(jclass1, "onCall", "(Ljava/lang/String;)V"); 30 | jstring enventStr = env->NewStringUTF(event); 31 | env->CallVoidMethod(tmpAct, jmethodID1, enventStr); 32 | env->DeleteLocalRef(enventStr); 33 | } 34 | 35 | 36 | extern "C" 37 | JNIEXPORT void JNICALL 38 | Java_com_faker_android_FakerApp_fakeApp(JNIEnv *env, jobject thiz, jobject application,jboolean b) { 39 | return fakeApp(env,thiz,application,b); 40 | } 41 | extern "C" 42 | JNIEXPORT void JNICALL 43 | Java_com_faker_android_FakerApp_fakeDex(JNIEnv *env, jobject thiz, jobject base) { 44 | fakeDex(env,thiz,base,"target.dfk");//安装DEX 45 | }extern "C" 46 | JNIEXPORT jstring JNICALL 47 | Java_com_faker_android_FakerActivity_init(JNIEnv *env, jobject thiz) {//替换函数 48 | tmpAct = env->NewGlobalRef(thiz); 49 | long base = baseAddr("libil2cpp.so"); 50 | //对指定的so 函数进行hook 51 | //fakeCpp((void *) Behaviour_get_isActiveAndEnabled, (void *)HookedBehaviour_get_isActiveAndEnabled ,reinterpret_cast(&Behaviour_get_isActiveAndEnabled)); 52 | std::string fackOk = "Fack_cpp_Success"; 53 | return env->NewStringUTF(fackOk.c_str()); 54 | } -------------------------------------------------------------------------------- /patch/il2cpp-cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | add_definitions(-DENABLE_DEBUG -DABC) 6 | cmake_minimum_required(VERSION 3.5) 7 | include_directories(src/main/cpp/include) 8 | 9 | if(${ANDROID_ABI} MATCHES "arm64-v8a") 10 | file(GLOB Scaffolding "${CMAKE_SOURCE_DIR}/Il2cpp-Scaffolding-ARM64/*.cpp") 11 | elseif(${ANDROID_ABI} MATCHES "armeabi-v7a") 12 | file(GLOB Scaffolding "${CMAKE_SOURCE_DIR}/Il2cpp-Scaffolding-ARM/*.cpp") 13 | endif() 14 | 15 | file(GLOB native_srcc "${CMAKE_SOURCE_DIR}/*.cpp") 16 | 17 | add_library( 18 | swap #最终在build中生成的so名字 19 | SHARED 20 | IMPORTED) 21 | set_target_properties( 22 | swap #最终在build中生成的so名字 23 | PROPERTIES IMPORTED_LOCATION 24 | ../../../../src/main/jniLibs/${ANDROID_ABI}/libswap.so) #so 25 | add_library( 26 | faker #最终在build中生成的so名字 27 | SHARED 28 | IMPORTED) 29 | set_target_properties( 30 | faker #最终在build中生成的so名字 31 | PROPERTIES IMPORTED_LOCATION 32 | ../../../../src/main/jniLibs/${ANDROID_ABI}/libfaker.so) #so 33 | 34 | add_library( # Sets the name of the library. 35 | native-lib 36 | # Sets the library as a shared library. 37 | SHARED 38 | # Provides a relative path to your source file(s). 39 | ${native_srcc} 40 | ${Scaffolding} 41 | ) 42 | # Searches for a specified prebuilt library and stores the path as a 43 | # variable. Because CMake includes system libraries in the search path by 44 | # default, you only need to specify the name of the public NDK library 45 | # you want to add. CMake verifies that the library exists before 46 | # completing its build. 47 | 48 | find_library( # Sets the name of the path variable. 49 | log-lib 50 | # Specifies the name of the NDK library that 51 | # you want CMake to locate. 52 | log) 53 | # Specifies libraries CMake should link to your target library. You 54 | # can link multiple libraries, such as libraries you define in this 55 | # build script, prebuilt third-party libraries, or system libraries. 56 | 57 | target_link_libraries( # Specifies the target library. 58 | native-lib 59 | swap 60 | faker 61 | android 62 | ${log-lib}) -------------------------------------------------------------------------------- /patch/il2cpp-cpp/Common.h: -------------------------------------------------------------------------------- 1 | #include 2 | #define LOG_TAG "xNative" 3 | #define DEBUG 4 | 5 | #ifdef DEBUG 6 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 7 | #define LOGD(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) 8 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) 9 | #else 10 | #define LOGI(...) NULL; 11 | #define LOGD(...) NULL; 12 | #define LOGE(...) NULL; 13 | #endif 14 | 15 | 16 | -------------------------------------------------------------------------------- /patch/il2cpp-cpp/Constant.h: -------------------------------------------------------------------------------- 1 | const char *MSG_TRIGGER_TAG_COMMON_PREFIX = "msg_trigger_tag_common_"; 2 | const char *MSG_TRIGGER_TAG_REWARD_PREFIX ="msg_trigger_tag_reward_"; 3 | const char *MSG_TRIGGER_LOCAL_PRIVACY ="msg_trigger_local_privacy"; 4 | const char *MSG_TRIGGER_LOCAL_TERMS ="msg_trigger_local_terms"; 5 | const char *MSG_TRIGGER_LOCAL_TATE ="msg_trigger_local_rate"; 6 | const char *MSG_TRIGGER_LOCAL_MORE_GAME ="msg_trigger_local_more_game"; -------------------------------------------------------------------------------- /patch/il2cpp-cpp/include/faker.h: -------------------------------------------------------------------------------- 1 | 2 | void onJniLoad(JavaVM *vm, void *reserved); 3 | /** 4 | * 安装修改后合并的DEX 5 | * @param env 6 | * @param instance 7 | * @param base 8 | * @param fakeDexAssetFileName 修改并合并后的DEX在Asset跟目录的文件名称 9 | */ 10 | void fakeDex(JNIEnv *env, jobject instance,jobject base,char *fakeDexAssetFileName); 11 | 12 | /** 13 | * 替换原有的application 14 | * @param env 15 | * @param instance 16 | * @param application 17 | * @param targetApp 原应用的Application名称 18 | * @return 19 | */ 20 | void fakeApp(JNIEnv *env, jobject instance,jobject application,jboolean b); 21 | 22 | /** 23 | * 获取So文件 基础地址 24 | * @param soname 例:libil2cpp.so 25 | * @return 26 | */ 27 | long baseAddr(char *soname); 28 | 29 | 30 | /** 31 | * Hook so 函数 = baseAddr+offset 函数偏移地址 32 | * @param function_address 原函数地址 33 | * @param replace_call 新函数 34 | * @param origin_call 虚构原函数,用于对原函数进行编码调用 35 | */ 36 | void fakeCpp(void *function_address, void *replace_call,void **origin_call); 37 | 38 | 39 | /** 40 | * 安装一个普通的DEX(非合并) 41 | * @param path 42 | * @return 43 | */ 44 | bool installDex(JNIEnv* env, jobject jobject, string dexPath); 45 | 46 | 47 | /** 48 | * 安装多个普通DEX(非合并) 49 | * @param path 50 | * @return 51 | */ 52 | bool installDex(JNIEnv* env, jobject jobject, vector* dexPaths); 53 | /** 54 | * 55 | * 1、获取so基础地址 56 | * 57 | * 2、hook so 函数 58 | * 59 | * 3、const char* coverIl2cppString2Char(Il2CppString *str); 60 | * 61 | * 4、dexInstaller 安装非合并DEX 62 | * 63 | * 5、fakeCpp 64 | */ 65 | 66 | 67 | -------------------------------------------------------------------------------- /patch/il2cpp-cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Common.h" 4 | #include 5 | #include 6 | #include "Constant.h" 7 | #if defined(__aarch64__) 8 | #include "Il2cpp-Scaffolding-ARM64/il2cpp-init.h" 9 | #include "Il2cpp-Scaffolding-ARM64/il2cpp-appdata.h" 10 | #elif defined(__arm__) 11 | #include "Il2cpp-Scaffolding-ARM/il2cpp-init.h" 12 | #include "Il2cpp-Scaffolding-ARM/il2cpp-appdata.h" 13 | #endif 14 | using namespace std; 15 | #include "include/faker.h" 16 | using namespace app; 17 | JavaVM *global_jvm; 18 | 19 | JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { 20 | JNIEnv *env; 21 | if ((*vm).GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) == JNI_OK) { 22 | LOGI("JNI_OnLoad %s","sucess"); 23 | }else{ 24 | LOGI("JNI_OnLoad %s","erro"); 25 | } 26 | global_jvm = vm; 27 | onJniLoad(vm,reserved); 28 | return JNI_VERSION_1_6; 29 | } 30 | 31 | const char* coverIl2cppString2Char(Il2CppString *str){ 32 | MonoString *monoString = reinterpret_cast(str); 33 | const char *s = monoString->toChars(); 34 | return s; 35 | } 36 | static jobject tmpAct; 37 | 38 | void callJava(const char *event) { 39 | JNIEnv* env; 40 | global_jvm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_4); 41 | jclass jclass1 = env->FindClass("com/faker/android/FakerUnityActivity"); 42 | jmethodID jmethodID1 = env->GetMethodID(jclass1, "onCall", "(Ljava/lang/String;)V"); 43 | jstring enventStr = env->NewStringUTF(event); 44 | env->CallVoidMethod(tmpAct, jmethodID1, enventStr); 45 | env->DeleteLocalRef(enventStr); 46 | } 47 | 48 | 49 | /** 50 | * note 该方法位于unity thread 51 | * @param klass 52 | * @return 53 | */ 54 | bool HookedBehaviour_get_isActiveAndEnabled(Behaviour *klass) { 55 | bool b = Behaviour_get_isActiveAndEnabled(klass, NULL); 56 | if(!b){ 57 | return b; 58 | } 59 | GameObject *gameObject = NULL;//Component_get_gameObject(reinterpret_cast(klass), NULL); 60 | if(gameObject==nullptr){ 61 | return b; 62 | } 63 | String *name = Object_1_get_name(reinterpret_cast(gameObject), NULL); 64 | 65 | if(name== nullptr){ 66 | return b; 67 | } 68 | 69 | const char *s = coverIl2cppString2Char(reinterpret_cast(name)); 70 | 71 | LOGI("class %p---- HookedBehaviour_get_isActiveAndEnabled GameObject Mame: %s",klass,s); 72 | if(strcmp(s,"Share")==0){ 73 | } 74 | return b; 75 | } 76 | Il2CppObject *HookedIl2cpp_runtime_invoke(const MethodInfo * method, void *obj, void **params, Il2CppException **exc){ 77 | LOGE("class %p---- HookedIl2cpp_runtime_invoke GameObject Mame: %s",method,method->name); 78 | return il2cpp_runtime_invoke(method,obj,params,exc); 79 | } 80 | 81 | extern "C" 82 | JNIEXPORT void JNICALL 83 | Java_com_faker_android_FakerApp_fakeApp(JNIEnv *env, jobject thiz, jobject application,jboolean b) { 84 | return fakeApp(env,thiz,application,b); 85 | } 86 | extern "C" 87 | JNIEXPORT void JNICALL 88 | Java_com_faker_android_FakerApp_fakeDex(JNIEnv *env, jobject thiz, jobject base) { 89 | fakeDex(env,thiz,base,"target.dfk");//安装DEX 90 | }extern "C" 91 | JNIEXPORT jstring JNICALL 92 | Java_com_faker_android_FakerUnityActivity_init(JNIEnv *env, jobject thiz) {//替换函数 93 | tmpAct = env->NewGlobalRef(thiz); 94 | long base = baseAddr("libil2cpp.so"); 95 | 96 | init_il2cpp(base); 97 | 98 | //对指定的so 函数进行hook 99 | //fakeCpp((void *) Behaviour_get_isActiveAndEnabled, (void *)HookedBehaviour_get_isActiveAndEnabled ,reinterpret_cast(&Behaviour_get_isActiveAndEnabled)); 100 | std::string fackOk = "Fack_cpp_Success"; 101 | return env->NewStringUTF(fackOk.c_str()); 102 | } -------------------------------------------------------------------------------- /patch/il2cpp-java/com/faker/android/FakerUnityActivity.java: -------------------------------------------------------------------------------- 1 | package com.faker.android; 2 | import android.os.Bundle; 3 | import android.os.Handler; 4 | import android.os.Looper; 5 | import android.os.Message; 6 | import android.view.KeyEvent; 7 | import android.view.Window; 8 | import android.widget.ImageView; 9 | import {R}; 10 | 11 | public class FakerUnityActivity extends com.unity3d.player.UnityPlayerActivity { 12 | public native String init(); 13 | static final int HANDLER_MSG_CALLJAVA = 1000; 14 | final Handler handler = new Handler(Looper.getMainLooper()) { 15 | @Override 16 | public void handleMessage(Message msg) { 17 | switch (msg.what) { 18 | case HANDLER_MSG_CALLJAVA: 19 | String cmsg = (String) msg.obj; 20 | callJava(cmsg); 21 | break; 22 | } 23 | super.handleMessage(msg); 24 | } 25 | }; 26 | ImageView imageView; 27 | @Override 28 | protected void onCreate(Bundle savedInstanceState){ 29 | requestWindowFeature(Window.FEATURE_NO_TITLE); 30 | super.onCreate(savedInstanceState); 31 | //FakeInt 32 | init(); 33 | //Init playerprefs if you need 34 | JavaPatch.coverPlayerprefs(this,"init.xml"); 35 | imageView = new ImageView(this); 36 | imageView.setImageResource(R.drawable.splash); 37 | imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); 38 | mUnityPlayer.addViewToPlayer(imageView,false); 39 | 40 | new Handler().postDelayed(new Runnable() { 41 | @Override 42 | public void run() { 43 | mUnityPlayer.removeViewFromPlayer(imageView); 44 | } 45 | },3000); 46 | } 47 | 48 | @Override 49 | public boolean onKeyDown(int keyCode, KeyEvent event) { 50 | if(keyCode==KeyEvent.KEYCODE_BACK) { 51 | return JavaPatch.onKeyDown(this,keyCode,event); 52 | } 53 | return mUnityPlayer.injectEvent(event); 54 | } 55 | //Called By Faker 56 | public void onCall(String msg) {// unity player isnot main thread transfer method to main thread 57 | Message message = new Message(); 58 | message.what =HANDLER_MSG_CALLJAVA; 59 | message.obj = msg; 60 | handler.sendMessage(message); 61 | } 62 | 63 | private void callJava(String msg){ 64 | Logger.log(msg); 65 | if(JavaPatch.Constant.MSG_TRIGGER_LOCAL_PRIVACY.equals(msg)){ 66 | } 67 | if(JavaPatch.Constant.MSG_TRIGGER_LOCAL_TERMS.equals(msg)){ 68 | } 69 | if(JavaPatch.Constant.MSG_TRIGGER_LOCAL_MORE_GAME.equals(msg)){ 70 | } 71 | if(JavaPatch.Constant.MSG_TRIGGER_LOCAL_TATE.equals(msg)){ 72 | } 73 | if(msg.startsWith(JavaPatch.Constant.MSG_TRIGGER_TAG_COMMON_PREFIX)){ 74 | } 75 | if(msg.startsWith(JavaPatch.Constant.MSG_TRIGGER_TAG_REWARD_PREFIX)){ 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /patch/il2cpp-java/com/faker/android/Logger.java: -------------------------------------------------------------------------------- 1 | package com.faker.android; 2 | 3 | import android.util.Log; 4 | 5 | public class Logger { 6 | private static final boolean DEBUG = true; 7 | private static final String TAG = "faker"; 8 | public static void log(String log){ 9 | if(DEBUG){ 10 | Log.e(TAG,log); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /patch/il2cpp-java/com/faker/android/WebViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.faker.android; 2 | import android.app.Activity; 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.webkit.WebView; 6 | import android.webkit.WebViewClient; 7 | import android.widget.TextView; 8 | import {R}; 9 | public class WebViewActivity extends Activity { 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.unity_webview_layout); 14 | String title = getIntent().getStringExtra("title"); 15 | if(title!=null){ 16 | ((TextView)findViewById(R.id.title_text)).setText(title); 17 | } 18 | findViewById(R.id.back_btn).setOnClickListener(new View.OnClickListener() { 19 | @Override 20 | public void onClick(View v) { 21 | finish(); 22 | } 23 | }); 24 | WebView webView = (WebView) findViewById(R.id.webView); 25 | webView.getSettings().setJavaScriptEnabled(true); 26 | webView.setWebViewClient(new WebViewClient()); 27 | String url = getIntent().getStringExtra("url"); 28 | webView.loadUrl(url); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /patch/il2cpp-libs-javaScaffoding/unity-classes.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/il2cpp-libs-javaScaffoding/unity-classes.jar -------------------------------------------------------------------------------- /patch/java-javaScaffoding/com/fakler/java/scaffoding/TestApplication.java: -------------------------------------------------------------------------------- 1 | package com.fakler.java.scaffoding; 2 | 3 | import android.app.Application; 4 | 5 | public class TestApplication extends Application { 6 | 7 | } 8 | -------------------------------------------------------------------------------- /patch/java-javaScaffoding/com/fakler/java/scaffoding/TestMainActivity.java: -------------------------------------------------------------------------------- 1 | package com.fakler.java.scaffoding; 2 | 3 | import com.unity3d.player.UnityPlayerActivity; 4 | 5 | public class TestMainActivity extends UnityPlayerActivity { 6 | } 7 | -------------------------------------------------------------------------------- /patch/java/com/faker/android/FakerActivity.java: -------------------------------------------------------------------------------- 1 | package com.faker.android; 2 | import android.content.Context; 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.os.Message; 7 | import android.view.KeyEvent; 8 | import android.view.Window; 9 | import android.widget.ImageView; 10 | import android.widget.Toast; 11 | import {R}; 12 | import java.util.Map; 13 | public class FakerActivity extends Activity { 14 | public native String init(); 15 | static final int HANDLER_MSG_CALLJAVA = 1000; 16 | final Handler handler = new Handler(Looper.getMainLooper()) { 17 | @Override 18 | public void handleMessage(Message msg) { 19 | switch (msg.what) { 20 | case HANDLER_MSG_CALLJAVA: 21 | String cmsg = (String) msg.obj; 22 | callJava(cmsg); 23 | break; 24 | } 25 | super.handleMessage(msg); 26 | } 27 | }; 28 | ImageView imageView; 29 | @Override 30 | protected void onCreate(Bundle savedInstanceState){ 31 | requestWindowFeature(Window.FEATURE_NO_TITLE); 32 | super.onCreate(savedInstanceState); 33 | init(); 34 | } 35 | 36 | @Override 37 | public boolean onKeyDown(int keyCode, KeyEvent event) { 38 | if(keyCode==KeyEvent.KEYCODE_BACK) { 39 | return JavaPatch.onKeyDown(this,keyCode,event); 40 | } 41 | return mUnityPlayer.injectEvent(event); 42 | } 43 | //Called By Faker 44 | public void onCall(String msg) {// unity player isnot main thread transfer method to main thread 45 | Message message = new Message(); 46 | message.what =HANDLER_MSG_CALLJAVA; 47 | message.obj = msg; 48 | handler.sendMessage(message); 49 | } 50 | 51 | private void callJava(String msg){ 52 | Logger.log(msg); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /patch/java/com/faker/android/Logger.java: -------------------------------------------------------------------------------- 1 | package com.faker.android; 2 | 3 | import android.util.Log; 4 | 5 | public class Logger { 6 | private static final boolean DEBUG = true; 7 | private static final String TAG = "faker"; 8 | public static void log(String log){ 9 | if(DEBUG){ 10 | Log.e(TAG,log); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /patch/java/com/faker/android/WebViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.faker.android; 2 | import android.app.Activity; 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.webkit.WebView; 6 | import android.webkit.WebViewClient; 7 | import android.widget.TextView; 8 | import {R}; 9 | public class WebViewActivity extends Activity { 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.unity_webview_layout); 14 | String title = getIntent().getStringExtra("title"); 15 | if(title!=null){ 16 | ((TextView)findViewById(R.id.title_text)).setText(title); 17 | } 18 | findViewById(R.id.back_btn).setOnClickListener(new View.OnClickListener() { 19 | @Override 20 | public void onClick(View v) { 21 | finish(); 22 | } 23 | }); 24 | WebView webView = (WebView) findViewById(R.id.webView); 25 | webView.getSettings().setJavaScriptEnabled(true); 26 | webView.setWebViewClient(new WebViewClient()); 27 | String url = getIntent().getStringExtra("url"); 28 | webView.loadUrl(url); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /patch/jniLibs/arm64-v8a/libfaker.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/jniLibs/arm64-v8a/libfaker.so -------------------------------------------------------------------------------- /patch/jniLibs/arm64-v8a/libswap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/jniLibs/arm64-v8a/libswap.so -------------------------------------------------------------------------------- /patch/jniLibs/armeabi-v7a/libfaker.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/jniLibs/armeabi-v7a/libfaker.so -------------------------------------------------------------------------------- /patch/jniLibs/armeabi-v7a/libswap.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/jniLibs/armeabi-v7a/libswap.so -------------------------------------------------------------------------------- /patch/libs-javaScaffoding/unity-classes.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/libs-javaScaffoding/unity-classes.jar -------------------------------------------------------------------------------- /patch/res/drawable/back_whait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/res/drawable/back_whait.png -------------------------------------------------------------------------------- /patch/res/drawable/h_splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/res/drawable/h_splash.png -------------------------------------------------------------------------------- /patch/res/drawable/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/res/drawable/splash.png -------------------------------------------------------------------------------- /patch/res/layout/unity_webview_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 20 | 21 | 28 | 29 | 30 | 34 | 35 | -------------------------------------------------------------------------------- /patch/res/mipmap-anydpi-v26/app_icon.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /patch/res/mipmap-anydpi-v26/app_icon_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /patch/res/mipmap-mdpi/app_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/res/mipmap-mdpi/app_icon.png -------------------------------------------------------------------------------- /patch/res/mipmap-mdpi/ic_launcher_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/res/mipmap-mdpi/ic_launcher_background.png -------------------------------------------------------------------------------- /patch/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/patch/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /patch/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /patch/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | #F5F5F5 7 | 8 | -------------------------------------------------------------------------------- /patch/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | New Unity Project 4 | Game view 5 | -------------------------------------------------------------------------------- /patch/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 10 | 17 | 18 | -------------------------------------------------------------------------------- /patch/scaffolding-cpp/MonoString.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by Fate on 2020-06-01. 3 | // 4 | 5 | #ifndef U3DINJECT_MASTER_MONOSTRING_H 6 | #define U3DINJECT_MASTER_MONOSTRING_H 7 | 8 | #include 9 | #include 10 | 11 | #ifdef __GNUC__ 12 | 13 | #include 14 | 15 | #endif // __GNUC__ 16 | using namespace std; 17 | 18 | class MonoString { 19 | void *klass; 20 | void *monitor; 21 | int length; 22 | char chars[1]; 23 | char *getChars() { 24 | return chars; 25 | } 26 | 27 | public: 28 | /** 29 | * 获取字符串长度 30 | * @return 31 | */ 32 | int getLength() { 33 | return length; 34 | } 35 | /** 36 | * monostring转char* 37 | * @return 38 | */ 39 | const char *toChars(); 40 | 41 | /** 42 | * monostring转string 43 | * @return 44 | */ 45 | string toString(); 46 | 47 | /** 48 | * char* 转monostring 49 | * @param s 50 | */ 51 | void setMonoString(const char *s); 52 | 53 | /** 54 | * string 转monostring 55 | * @param s 56 | */ 57 | void setMonoString(string s); 58 | }; 59 | 60 | // 从UTF16编码字符串构建,需要带BOM标记 61 | std::string utf16_to_utf8(const std::u16string &u16str); 62 | 63 | // 从UTF16 LE编码的字符串创建 64 | std::string utf16le_to_utf8(const std::u16string &u16str); 65 | 66 | // 从UTF16BE编码字符串创建 67 | std::string utf16be_to_utf8(const std::u16string &u16str); 68 | 69 | // 获取转换为UTF-16 LE编码的字符串 70 | std::u16string utf8_to_utf16le(const std::string &u8str, bool addbom = false, bool *ok = NULL); 71 | 72 | // 获取转换为UTF-16 BE的字符串 73 | std::u16string utf8_to_utf16be(const std::string &u8str, bool addbom = false, bool *ok = NULL); 74 | 75 | #endif //U3DINJECT_MASTER_MONOSTRING_H 76 | 77 | -------------------------------------------------------------------------------- /patch/scaffolding-cpp/il2cpp-appdata.h: -------------------------------------------------------------------------------- 1 | // IL2CPP application data 2 | 3 | #pragma once 4 | 5 | #include 6 | 7 | // Application-specific types 8 | #include "il2cpp-types.h" 9 | 10 | #include "MonoString.h" 11 | // IL2CPP API function pointers 12 | #include "il2cpp-api-functions-ptr.h" 13 | 14 | // IL2CPP APIs 15 | #define DO_API(r, n, p) extern r (*n) p 16 | #include "il2cpp-api-functions.h" 17 | #undef DO_API 18 | 19 | // Application-specific functions 20 | #define DO_APP_FUNC(a, r, n, p) extern r (*n) p 21 | namespace app { 22 | #include "il2cpp-functions.h" 23 | } 24 | #undef DO_APP_FUNC 25 | 26 | // TypeInfo pointers 27 | #define DO_TYPEDEF(a, n) extern n ## __Class* n ## __TypeInfo 28 | namespace app { 29 | #include "il2cpp-types-ptr.h" 30 | } 31 | #undef DO_TYPEDEF -------------------------------------------------------------------------------- /patch/scaffolding-cpp/il2cpp-init.cpp: -------------------------------------------------------------------------------- 1 | // IL2CPP application initializer 2 | 3 | #include "il2cpp-appdata.h" 4 | #include "il2cpp-init.h" 5 | // IL2CPP APIs 6 | #define DO_API(r, n, p) r (*n) p 7 | #include "il2cpp-api-functions.h" 8 | #undef DO_API 9 | 10 | // Application-specific functions 11 | #define DO_APP_FUNC(a, r, n, p) r (*n) p 12 | namespace app { 13 | #include "il2cpp-functions.h" 14 | } 15 | #undef DO_APP_FUNC 16 | 17 | // TypeInfo pointers 18 | #define DO_TYPEDEF(a, n) n ## __Class* n ## __TypeInfo 19 | namespace app { 20 | #include "il2cpp-types-ptr.h" 21 | } 22 | #undef DO_TYPEDEF 23 | 24 | // IL2CPP application initializer 25 | void init_il2cpp(long baseAddress) 26 | { 27 | // Get base address of IL2CPP module 28 | using namespace app; 29 | 30 | // Define IL2CPP API function addresses 31 | #define DO_API(r, n, p) n = (r (*) p)(baseAddress + n ## _ptr) 32 | #include "il2cpp-api-functions.h" 33 | #undef DO_API 34 | 35 | // Define function addresses 36 | #define DO_APP_FUNC(a, r, n, p) n = (r (*) p)(baseAddress + a) 37 | #include "il2cpp-functions.h" 38 | #undef DO_APP_FUNC 39 | 40 | // Define TypeInfo variables 41 | #define DO_TYPEDEF(a, n) n ## __TypeInfo = *(n ## __Class**) (baseAddress + a); 42 | #include "il2cpp-types-ptr.h" 43 | #undef DO_TYPEDEF 44 | } -------------------------------------------------------------------------------- /patch/scaffolding-cpp/il2cpp-init.h: -------------------------------------------------------------------------------- 1 | // IL2CPP application initializer 2 | 3 | #pragma once 4 | 5 | // IL2CPP application initializer 6 | void init_il2cpp(long baseAdress); -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | FakerAndroid 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | org.apache.maven.plugins 14 | maven-compiler-plugin 15 | 16 | 8 17 | 8 18 | 19 | 20 | 21 | maven-assembly-plugin 22 | 23 | false 24 | 25 | jar-with-dependencies 26 | 27 | 28 | 29 | com.facker.toolchain.FakerCmd 30 | 31 | 32 | 33 | 34 | 35 | make-assembly 36 | package 37 | 38 | assembly 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.dom4j 48 | dom4j 49 | 2.1.1 50 | 51 | 52 | org.projectlombok 53 | lombok 54 | 1.16.10 55 | 56 | 57 | com.google.guava 58 | guava 59 | 22.0 60 | 61 | 62 | org.json 63 | json 64 | 20180813 65 | 66 | 67 | com.luhuiguo 68 | chinese-utils 69 | 1.0 70 | 71 | 72 | apksigner 73 | apksigner 74 | system 75 | 1.0.0 76 | ${project.basedir}/lib/apksigner.jar 77 | 78 | 79 | 80 | apktool 81 | apktool 82 | system 83 | 2.4.1 84 | ${project.basedir}/lib/apktool_2.4.1.jar 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/FakerCmd.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain; 2 | 3 | import java.io.File; 4 | 5 | public class FakerCmd { 6 | public static void main(String[] args) { 7 | if(args.length>0){ 8 | String path = args[0]; 9 | File file = new File(path); 10 | if(file.exists()){ 11 | if(!file.getName().endsWith(".apk")){ 12 | System.out.println("非法的Apk文件路径"); 13 | }else { 14 | FakerTransfer.translate(path); 15 | } 16 | }else { 17 | System.out.println("Apk文件路径不正确"); 18 | } 19 | }else { 20 | System.out.println("请输入apk文件路径"); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/FakerMain.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain; 2 | 3 | public class FakerMain { 4 | static String apkFilePath = "C:\\Users\\Yang\\Desktop\\apk\\juan-juan-bing-qi-lin\\卷卷冰淇淋.apk"; 5 | public static void main(String[] args) { 6 | FakerTransfer.translate(apkFilePath); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/FakerTransfer.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain; 2 | 3 | import com.facker.toolchain.api.xbase.Importer; 4 | import com.facker.toolchain.api.xbase.SourceCode; 5 | import com.facker.toolchain.api.xbase.XSrcTarget; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | 10 | public class FakerTransfer { 11 | public static void translate(String apkFilePath) { 12 | File sourceCodeDir = new File("patch"); 13 | SourceCode sourceCode = new SourceCode(sourceCodeDir); 14 | File targetFile = new File(apkFilePath);//废弃 15 | XSrcTarget xSrcTarget = new XSrcTarget(targetFile); 16 | Importer importer = new Importer(xSrcTarget,sourceCode); 17 | try { 18 | importer.doImport(); 19 | } catch (IOException e) { 20 | e.printStackTrace(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/ApkTool.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import brut.androlib.Androlib; 4 | import brut.androlib.ApkDecoder; 5 | import brut.common.BrutException; 6 | import com.facker.toolchain.utils.Logger; 7 | import java.io.File; 8 | import java.util.HashMap; 9 | 10 | public class ApkTool { 11 | /** 12 | * 拆开文件 13 | * 14 | * @return 15 | */ 16 | public static boolean decodeRes(File targetApkPath, File ouputDir) { 17 | ApkDecoder decoder = new ApkDecoder(); 18 | try { 19 | decoder.setDecodeSources((short) 0); 20 | decoder.setOutDir(ouputDir); 21 | decoder.setForceDelete(true); 22 | decoder.setApkFile(targetApkPath); 23 | decoder.decode(); 24 | return true; 25 | } catch (Exception e) { 26 | e.printStackTrace(); 27 | return false; 28 | } 29 | } 30 | 31 | public static boolean decodeSrc(File targetApkPath, File ouputDir) { 32 | Logger.log("targetApkPath path " + targetApkPath.getAbsolutePath()); 33 | ApkDecoder decoder = new ApkDecoder(); 34 | try { 35 | decoder.setBaksmaliDebugMode(false); 36 | decoder.setOutDir(ouputDir); 37 | decoder.setForceDelete(true); 38 | decoder.setApkFile(targetApkPath); 39 | decoder.decode(); 40 | return true; 41 | } catch (Exception e) { 42 | e.printStackTrace(); 43 | return false; 44 | } 45 | } 46 | 47 | /** 48 | * Android 重新打包 49 | * 50 | * @return 51 | */ 52 | public static boolean build(File sourceDir, File outPutApkPath) { 53 | Androlib instance = new Androlib(); 54 | HashMap flags = new HashMap(); 55 | flags.put("forceBuildAll", Boolean.valueOf(true)); 56 | flags.put("debug", Boolean.valueOf(false)); 57 | flags.put("verbose", Boolean.valueOf(false)); 58 | flags.put("framework", Boolean.valueOf(false)); 59 | flags.put("update", Boolean.valueOf(false)); 60 | flags.put("copyOriginal", Boolean.valueOf(false)); 61 | try { 62 | instance.build(sourceDir, outPutApkPath); 63 | return true; 64 | } catch (BrutException e) { 65 | e.printStackTrace(); 66 | } 67 | return false; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/DecodeApk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import java.io.File; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | public class DecodeApk { 8 | 9 | private File originalFile; 10 | 11 | private String md5; 12 | 13 | private long id; 14 | 15 | private static String DEX_MATCHER = "classes[1-9]?\\d*\\.dex"; 16 | 17 | 18 | public long getId() { 19 | return id; 20 | } 21 | 22 | public DecodeApk(long id,File originalFile,String md5) { 23 | this.originalFile = originalFile; 24 | this.md5 = md5; 25 | this.id = id; 26 | } 27 | 28 | public File getOriginalFile() { 29 | return originalFile; 30 | } 31 | /** 32 | * 获取解压目录 33 | * @return 34 | */ 35 | public File getDecodeDir() { 36 | File file = new File(originalFile.getParent(),getClass().getSimpleName()+"_"+getId()+"_"+md5); 37 | if(!file.exists()){ 38 | file.mkdir(); 39 | } 40 | return file; 41 | } 42 | 43 | public File getMETAINF() { 44 | File file = new File(getDecodeDir(),"META-INF"); 45 | return file; 46 | } 47 | public File getAssets() { 48 | File file = new File(getDecodeDir(),"assets"); 49 | if(!file.exists()){ 50 | file.mkdir(); 51 | } 52 | return file; 53 | } 54 | 55 | public File getLibDir() { 56 | File file = new File(getDecodeDir(),"lib"); 57 | return file; 58 | } 59 | 60 | public File getXMLDir() { 61 | File file = new File(getResDir(),"xml"); 62 | return file; 63 | } 64 | 65 | public File getResDir() { 66 | File file = new File(getDecodeDir(),"res"); 67 | if(!file.exists()){ 68 | file.mkdir(); 69 | } 70 | return file; 71 | } 72 | 73 | public File getManifestFile() { 74 | File file = new File(getDecodeDir(),"AndroidManifest.xml"); 75 | return file; 76 | } 77 | 78 | public File getYmlFile() { 79 | File file = new File(getDecodeDir(),"apktool.yml"); 80 | return file; 81 | } 82 | 83 | public List getDexsFiles() { 84 | List targetDexList = new ArrayList(); 85 | for (File f : getDecodeDir().listFiles()) { 86 | if (f.getName().matches(DEX_MATCHER)) { 87 | targetDexList.add(f); 88 | } 89 | } 90 | return targetDexList; 91 | } 92 | 93 | public File getMainDexFile() { 94 | File file = new File(getDecodeDir(),"classes.dex"); 95 | return file; 96 | } 97 | 98 | public boolean decode(){ 99 | /** 100 | * 缓存逻辑判断 101 | */ 102 | return ApkTool.decodeRes(originalFile,getDecodeDir()); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/IImporter.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | 4 | import com.facker.toolchain.utils.Logger; 5 | 6 | import java.io.IOException; 7 | public abstract class IImporter { 8 | protected static String TAG = "Importer"; 9 | protected XSrcTarget xSrcTarget; 10 | 11 | protected SourceCode sourceCode; 12 | 13 | //处理DEX 14 | abstract boolean unZipTarget(); 15 | 16 | abstract boolean orlderXTarget(XSrcTarget xSrcTarget) throws IOException; 17 | 18 | abstract boolean mergeSourceCode(SourceCode sourceCode,XSrcTarget xSrcTarget) throws IOException; 19 | 20 | abstract boolean makeCppScaffolding(XSrcTarget xSrcTarget) throws IOException; 21 | 22 | abstract boolean makeJavaScaffolding(SourceCode sourceCode,XSrcTarget xSrcTarget) throws IOException; 23 | 24 | abstract boolean mergeFaker(SourceCode sourceCode,XSrcTarget xSrcTarget) throws IOException; 25 | 26 | abstract boolean modManifest(SourceCode sourceCode,XSrcTarget xSrcTarget) throws IOException; 27 | 28 | abstract boolean fixRes(SourceCode sourceCode,XSrcTarget xSrcTarget) throws IOException; 29 | 30 | //TODO 31 | protected IImporter(XSrcTarget xSrcTarget,SourceCode sourceCode) { 32 | this.xSrcTarget = xSrcTarget; 33 | this.sourceCode = sourceCode; 34 | } 35 | 36 | public void doImport() throws IOException { 37 | Logger.log(TAG, "解压中---"); 38 | if(!unZipTarget()){ 39 | Logger.log(TAG, "解压失败---"); 40 | return; 41 | } 42 | Logger.log(TAG, "正在整理Android项目目录结构---"); 43 | if(!orlderXTarget(xSrcTarget)){ 44 | Logger.log(TAG, "整理Android项目目录结构---失败"); 45 | return; 46 | } 47 | if(!makeCppScaffolding(xSrcTarget)){ 48 | 49 | } 50 | Logger.log(TAG, "正在拷贝嫁接代码---"); 51 | if(!mergeSourceCode(sourceCode,xSrcTarget)){ 52 | Logger.log(TAG, "拷贝嫁接代码---失败"); 53 | return; 54 | } 55 | if(!makeJavaScaffolding(sourceCode,xSrcTarget)){ 56 | return; 57 | } 58 | if(!mergeFaker(sourceCode,xSrcTarget)){ 59 | return; 60 | } 61 | if(!modManifest(sourceCode,xSrcTarget)){ 62 | return; 63 | } 64 | if(!fixRes(sourceCode,xSrcTarget)){ 65 | return; 66 | } 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/IWorkerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import java.util.List; 4 | 5 | public interface IWorkerAdapter { 6 | 7 | public boolean check(XBridge xBridge, List xModels, XTarget xTarget) ; 8 | 9 | public boolean gatherFlip(XTarget xTarget, WorkerListener workerListener); 10 | 11 | public boolean copyBridgeDex(XBridge xBridge, XTarget xTarget) ; 12 | 13 | public boolean mergeBridgeLib(XBridge xBridge, XTarget xTarget); 14 | 15 | public boolean mergeModelsLib(List xModels, XTarget xTarget); 16 | 17 | public boolean mergeBridgeAssets(XBridge xBridge, XTarget xTarget); 18 | 19 | public boolean mergeModelsAssets(List xModels, XTarget xTarget); 20 | 21 | public boolean mergeBridgeMainifest(XBridge xBridge, XTarget xTarget); 22 | 23 | public boolean mergeModelsMainifest(List xModels, XTarget xTarget); 24 | 25 | public boolean mergeBridgeRes(XBridge xBridge, XTarget xTarget); 26 | 27 | public boolean mergeModelsRes(List xModels, XTarget xTarget); 28 | 29 | public boolean modelTargetLogo(XTarget xTarget); 30 | 31 | public boolean handleXTargetDex(XTarget xTarget); 32 | 33 | public boolean handleModelDex(List xModels); 34 | 35 | public boolean orlderXTargetAndXModelsDex(XTarget xTarget, List xModels) ; 36 | 37 | public boolean modXTargetYml(XTarget xTarget) ; 38 | 39 | 40 | String getKeyPath(); 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/PathEditor.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import org.dom4j.Document; 4 | import org.dom4j.DocumentException; 5 | import org.dom4j.Element; 6 | import org.dom4j.io.OutputFormat; 7 | import org.dom4j.io.SAXReader; 8 | import org.dom4j.io.XMLWriter; 9 | 10 | import java.io.File; 11 | import java.io.FileWriter; 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | public class PathEditor { 16 | /** 17 | * manifest 路径 18 | */ 19 | File manifestFile; 20 | 21 | /** 22 | * 23 | */ 24 | Document document; 25 | 26 | 27 | /** 28 | * manifest 29 | */ 30 | Element resourcesElement; 31 | 32 | 33 | public PathEditor(File manifestFile) throws DocumentException { 34 | this.manifestFile = manifestFile; 35 | SAXReader reader = new SAXReader(); 36 | document = reader.read(manifestFile); 37 | resourcesElement = document.getRootElement(); 38 | } 39 | public Element getResourcesElement(){ 40 | return resourcesElement; 41 | } 42 | 43 | //拷贝节点下的所有元素 44 | public void copyElements(Element elementFrom,Element elementTo) {//TODO 如果是入口Activity的话则跳过 45 | List elementsFrom = elementFrom.elements(); 46 | List elementsTo = elementTo.elements(); 47 | for (Element elementItemFrom : elementsFrom) {//TODO 重名舍弃 48 | String fromName = elementItemFrom.attributeValue("name"); 49 | if(!isNameRepeat(elementsTo, fromName)){ 50 | Element copy = elementItemFrom.createCopy(); 51 | elementTo.add(copy); 52 | System.out.println("name 非重复元素:"+elementItemFrom.attributeValue("name")); 53 | }else{ 54 | System.out.println("name 重复元素:"+elementItemFrom.attributeValue("name")); 55 | } 56 | } 57 | } 58 | 59 | 60 | private boolean isNameRepeat(List elementsTo, String fromName) { 61 | for (Element elementItemTo: elementsTo) { 62 | String toName = elementItemTo.attributeValue("name"); 63 | if(toName.equals(fromName)){ 64 | return true; 65 | } 66 | } 67 | return false; 68 | } 69 | 70 | 71 | public void save() throws IOException { 72 | OutputFormat xmlFormat = OutputFormat.createPrettyPrint(); 73 | xmlFormat.setEncoding("UTF-8"); 74 | // 设置换行 75 | xmlFormat.setNewlines(true); 76 | // 生成缩进 77 | xmlFormat.setIndent(true); 78 | // 使用4个空格进行缩进, 可以兼容文本编辑器 79 | xmlFormat.setIndent(" "); 80 | 81 | XMLWriter writer = new XMLWriter(new FileWriter(manifestFile), xmlFormat); 82 | writer.write(document); 83 | writer.close(); 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/Result.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | public class Result { 4 | 5 | public String getErroCode() { 6 | return erroCode; 7 | } 8 | 9 | public void setErroCode(String erroCode) { 10 | this.erroCode = erroCode; 11 | } 12 | 13 | public String getOutPath() { 14 | return outPath; 15 | } 16 | 17 | public void setOutPath(String outPath) { 18 | this.outPath = outPath; 19 | } 20 | 21 | public String getErroMsg() { 22 | return erroMsg; 23 | } 24 | 25 | public void setErroMsg(String erroMsg) { 26 | this.erroMsg = erroMsg; 27 | } 28 | 29 | String erroCode; 30 | 31 | String outPath; 32 | 33 | String erroMsg; 34 | 35 | @Override 36 | public String toString() { 37 | return "Result{" + 38 | "erroCode='" + erroCode + '\'' + 39 | ", outPath='" + outPath + '\'' + 40 | ", erroMsg='" + erroMsg + '\'' + 41 | '}'; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/SourceCode.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import java.io.File; 4 | 5 | public class SourceCode { 6 | 7 | private File sourceRoot; 8 | 9 | public SourceCode(File sourceRoot) { 10 | this.sourceRoot = sourceRoot; 11 | } 12 | 13 | public File getSourceRoot() { 14 | return sourceRoot; 15 | } 16 | 17 | public File getJavaScaffodingLibs(){ 18 | return new File(sourceRoot,"libs-javaScaffoding"); 19 | } 20 | public File getJavaScaffodingJava(){ 21 | return new File(sourceRoot,"java-javaScaffoding"); 22 | } 23 | public File ManifestjavaScaffoding(){ 24 | return new File(sourceRoot,"Manifest-javaScaffoding"); 25 | } 26 | public File getSrc(){ 27 | return new File(sourceRoot,"src"); 28 | } 29 | 30 | 31 | public File getBuildGame(){ 32 | return new File(sourceRoot,"build-app"); 33 | } 34 | public File getBuildJavaScffoing(){ 35 | return new File(sourceRoot,"build-javaScaffoding"); 36 | } 37 | 38 | public File getBuildProject(){ 39 | return new File(sourceRoot,"build-project"); 40 | } 41 | 42 | public File getCpp(boolean isIl2cpp){ 43 | if(isIl2cpp){ 44 | return new File(sourceRoot,"il2cpp-cpp"); 45 | } 46 | return new File(sourceRoot,"cpp"); 47 | } 48 | public File getJava(boolean isIl2cpp){ 49 | if(isIl2cpp){ 50 | return new File(sourceRoot,"il2cpp-java"); 51 | } 52 | return new File(sourceRoot,"java"); 53 | } 54 | 55 | public File getJniLibs(){ 56 | return new File(sourceRoot,"jniLibs"); 57 | } 58 | public File getAssets(){ 59 | return new File(sourceRoot,"assets"); 60 | } 61 | 62 | public File getRes(){ 63 | return new File(sourceRoot,"res"); 64 | } 65 | public File getManifest(){ 66 | return new File(sourceRoot,"AndroidManifest.xml"); 67 | } 68 | 69 | public File getScaffolding_cpp(){ 70 | return new File(sourceRoot,"scaffolding-cpp"); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/TextUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | public class TextUtil { 4 | public static boolean isEmpty(String text) { 5 | if (text != null && !"".equals(text)) { 6 | return false; 7 | } 8 | return true; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/ValuesMod.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import org.dom4j.Document; 4 | import org.dom4j.DocumentException; 5 | import org.dom4j.Element; 6 | import org.dom4j.io.OutputFormat; 7 | import org.dom4j.io.SAXReader; 8 | import org.dom4j.io.XMLWriter; 9 | 10 | import java.io.File; 11 | import java.io.FileWriter; 12 | import java.io.IOException; 13 | import java.util.List; 14 | 15 | public class ValuesMod { 16 | /** 17 | * manifest 路径 18 | */ 19 | File manifestFile; 20 | 21 | /** 22 | * 23 | */ 24 | Document document; 25 | 26 | 27 | /** 28 | * manifest 29 | */ 30 | Element resourcesElement; 31 | 32 | 33 | public ValuesMod(File manifestFile) throws DocumentException { 34 | this.manifestFile = manifestFile; 35 | SAXReader reader = new SAXReader(); 36 | document = reader.read(manifestFile); 37 | resourcesElement = document.getRootElement(); 38 | } 39 | public Element getResourcesElement(){ 40 | return resourcesElement; 41 | } 42 | 43 | 44 | //拷贝节点下的所有元素 45 | public void copyValueElements(Element elementFrom,Element elementTo) {//TODO 如果是入口Activity的话则跳过 46 | List elementsFrom = elementFrom.elements(); 47 | List elementsTo = elementTo.elements(); 48 | 49 | for (Element elementItemFrom : elementsFrom) {//TODO 重名舍弃 50 | String fromName = elementItemFrom.attributeValue("name"); 51 | if(!isNameRepeat(elementsTo, fromName)){ 52 | Element copy = elementItemFrom.createCopy(); 53 | elementTo.add(copy); 54 | System.out.println("name 非重复元素:"+elementItemFrom.attributeValue("name")); 55 | }else{ 56 | System.out.println("name 重复元素:"+elementItemFrom.attributeValue("name")); 57 | } 58 | } 59 | } 60 | 61 | //拷贝节点元素 62 | public void copyValueElement(Element elementFrom,Element elementTo) {//TODO 如果是入口Activity的话则跳过 63 | List elementsTo = elementTo.elements(); 64 | String fromName = elementFrom.attributeValue("name"); 65 | if(!isNameRepeat(elementsTo, fromName)){ 66 | Element copy = elementFrom.createCopy(); 67 | elementTo.add(copy); 68 | System.out.println("name 非重复元素:"+elementFrom.attributeValue("name")+ "type 非重复元素:"+elementFrom.attributeValue("type")+ "id 非重复元素:"+elementFrom.attributeValue("id")); 69 | }else{ 70 | // System.out.println("name 重复元素:"+elementFrom.attributeValue("name")); 71 | } 72 | } 73 | 74 | 75 | 76 | 77 | 78 | private boolean isNameRepeat(List elementsTo, String fromName) { 79 | for (Element elementItemTo: elementsTo) { 80 | String toName = elementItemTo.attributeValue("name"); 81 | if(toName.equals(fromName)){ 82 | return true; 83 | } 84 | } 85 | return false; 86 | } 87 | 88 | 89 | public void save() throws IOException { 90 | OutputFormat xmlFormat = OutputFormat.createPrettyPrint(); 91 | xmlFormat.setEncoding("UTF-8"); 92 | // 设置换行 93 | xmlFormat.setNewlines(true); 94 | // 生成缩进 95 | xmlFormat.setIndent(true); 96 | // 使用4个空格进行缩进, 可以兼容文本编辑器 97 | xmlFormat.setIndent(" "); 98 | 99 | XMLWriter writer = new XMLWriter(new FileWriter(manifestFile), xmlFormat); 100 | writer.write(document); 101 | writer.close(); 102 | } 103 | } 104 | 105 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/WorkerAction.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | 4 | public abstract class WorkerAction { 5 | public abstract void action() throws Exception ;//方法体全部异常抛出,有必要细化异常 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/WorkerListener.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import java.io.File; 4 | import java.util.List; 5 | 6 | public interface WorkerListener { 7 | public static class WORKER { 8 | public static final String WORKING_DECODE_BRIDGE = "working_decode_bridge"; 9 | public static final String WORKING_DECODE_TARGET = "working_decode_target"; 10 | public static final String WORKING_DECODE_MODEL = "working_decode_model"; 11 | public static final String WORKING_FLIP = "working_flip"; 12 | public static final String WORKING_MERGE_BRIDGE_LIB = "working_merge_bridge_lib"; 13 | public static final String WORKING_MERGE_MODELS_LIB = "working_merge_MODELS_lib"; 14 | public static final String WORKING_MERGE_BRIDGE_ASSETS = "working_merge_bridge_assets"; 15 | public static final String WORKING_MERGE_MODELS_ASSETS = "working_merge_models_assets"; 16 | public static final String WORKING_MERGE_BRIDGE_MANIFEST = "working_merge_bridge_manifest"; 17 | public static final String WORKING_MERGE_MODELS_MANIFEST = "working_merge_models_manifest"; 18 | public static final String WORKING_MERGE_BRIDGE_RES = "working_merge_bridge_res"; 19 | public static final String WORKING_MERGE_MODELS_RES = "working_merge_models_res"; 20 | public static final String WORKING_MOD_TARGET_LOGO = "working_mod_target_logo"; 21 | public static final String WORKING_HANDLE_MODELS_DEX = "working_handle_models_dex"; 22 | public static final String WORKING_HANDLE_TARGET_DEX = "working_handle_target_dex"; 23 | public static final String WORKING_COPY_BRIDGE_DEX= "working_copy_bridge_dex"; 24 | public static final String WORKING_MODEL_TARGET_YML= "working_mod_target_yml"; 25 | 26 | 27 | 28 | 29 | 30 | public static final String WORKING_CHECK_TARGET = "working_check_target"; 31 | public static final String WORKING_PROCESS_DEX = "working_process_dex"; 32 | public static final String WORKING_ORLDER_TARGET = "working_process_dex"; 33 | public static final String WORKING_INJECTWEBCONFIG = "working_injectwebconfig"; 34 | public static final String WORKING_PROCESS_COREMANIFEST = "working_process_coremanifest"; 35 | 36 | public static final String WORKING_PROCESS_MODELMANIFEST= "working_process_modelmanifest"; 37 | public static final String WORKING_MEREGE_MODEL= "working_merege_model"; 38 | public static final String WORKING_PROCES_RUNTIME= "working_proces_runtime"; 39 | public static final String WORKING_ZIP_XTARGET= "working_zip_xtarget"; 40 | public static final String WORKING_SIGN_XTARGET= "working_sign_xtarget"; 41 | 42 | public static final String WORKING_COMPUTE_XTARGET= "working_compute_xtarget"; 43 | } 44 | public static class ERRO { 45 | public static final String ERRO_PREFIX ="erro_"; 46 | } 47 | 48 | void xflip(long id, List flips); 49 | void working(long id, String working); 50 | 51 | void erro(long id, String erro); 52 | 53 | void sucess(long id, File file, String md5); 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/XBridge.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import java.io.File; 4 | 5 | public class XBridge extends DecodeApk { 6 | public static String SO_NAME = "libopt.so"; 7 | public XBridge(long id,File originalFile, String md5) { 8 | super(id,originalFile, md5); 9 | } 10 | 11 | public String getBridgeHost() { 12 | return bridgeHost; 13 | } 14 | 15 | public void setBridgeHost(String bridgeHost) { 16 | this.bridgeHost = bridgeHost; 17 | } 18 | 19 | private String bridgeHost; 20 | 21 | private String dispatherHost; 22 | private String pingHost; 23 | 24 | public String getDispatherHost() { 25 | return dispatherHost; 26 | } 27 | 28 | public void setDispatherHost(String dispatherHost) { 29 | this.dispatherHost = dispatherHost; 30 | } 31 | 32 | public String getPingHost() { 33 | return pingHost; 34 | } 35 | 36 | public void setPingHost(String pingHost) { 37 | this.pingHost = pingHost; 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/XModel.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import java.io.File; 4 | import java.util.Map; 5 | 6 | public class XModel extends DecodeApk { 7 | 8 | public XModel(long id,File originalFile, String md5) { 9 | super(id,originalFile, md5); 10 | } 11 | private boolean local; 12 | 13 | public boolean isLocal() { 14 | return local; 15 | } 16 | public Map getParams() { 17 | return params; 18 | } 19 | 20 | public void setParams(Map params) { 21 | this.params = params; 22 | } 23 | 24 | /** 25 | * 本地化参数注入 26 | */ 27 | private Map params; 28 | 29 | public void setLocal(boolean local) { 30 | this.local = local; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/XSrcTarget.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.io.File; 7 | import java.util.Map; 8 | 9 | @Getter @Setter 10 | public class XSrcTarget extends SrcDecodeApk { 11 | 12 | private Signature signature; 13 | private String appName; 14 | 15 | private String versionName; 16 | 17 | private String packageName; 18 | 19 | private long versionCode; 20 | 21 | public XSrcTarget(File originalFile) { 22 | super(originalFile); 23 | } 24 | 25 | private File splash; 26 | 27 | private Map logos; 28 | 29 | private boolean shell; 30 | 31 | @Getter @Setter 32 | public static class Signature { 33 | 34 | private String path; 35 | private String md5; 36 | private String storePassword; 37 | private String keyAlias; 38 | 39 | private String keyPassword; 40 | } 41 | public File getPackerDexFile(){ 42 | return new File(getAssets(),"dex"); 43 | } 44 | 45 | public File getEncodeFile(){ 46 | File file = new File(getOriginalApkFile().getParent(),getId()+"_"+getOriginalApkFile().getName()); 47 | return file; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/XTarget.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.io.File; 7 | import java.util.Map; 8 | 9 | @Getter @Setter 10 | public class XTarget extends DecodeApk { 11 | 12 | private Signature signature; 13 | private String appName; 14 | 15 | private String versionName; 16 | 17 | private String packageName; 18 | 19 | private long versionCode; 20 | 21 | public XTarget(long id, File originalFile, String md5) { 22 | super(id, originalFile, md5); 23 | } 24 | 25 | private File splash; 26 | 27 | private Map logos; 28 | 29 | private boolean shell; 30 | 31 | @Getter @Setter 32 | public static class Signature { 33 | 34 | private String path; 35 | private String md5; 36 | private String storePassword; 37 | private String keyAlias; 38 | 39 | private String keyPassword; 40 | } 41 | public File getPackerDexFile(){ 42 | return new File(getAssets(),"dex"); 43 | } 44 | 45 | public File getEncodeFile(){ 46 | File file = new File(getOriginalFile().getParent(),getId()+"_"+getOriginalFile().getName()); 47 | return file; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/YmlMod.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase; 2 | import brut.androlib.meta.MetaInfo; 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | 7 | public class YmlMod { 8 | 9 | public static void main(String[] args) throws IOException { 10 | String yamlStr = "t.yml"; 11 | MetaInfo metaInfo = MetaInfo.load(new FileInputStream(new File(yamlStr))); 12 | int ov = Integer.parseInt(metaInfo.versionInfo.versionCode)+1000; 13 | metaInfo.versionInfo.versionCode =ov+""; 14 | metaInfo.save(new File(yamlStr)); 15 | } 16 | 17 | public static void modVersionCode(File apktoolYaml,String versionCode) throws IOException { 18 | MetaInfo metaInfo = null; 19 | metaInfo = MetaInfo.load(new FileInputStream(apktoolYaml)); 20 | // int ov = Integer.parseInt(metaInfo.versionInfo.versionCode)+inc; 21 | metaInfo.versionInfo.versionCode =versionCode; 22 | metaInfo.save(apktoolYaml); 23 | } 24 | public static void modVersionName(File apktoolYaml,String versionName) throws IOException { 25 | MetaInfo metaInfo = null; 26 | metaInfo = MetaInfo.load(new FileInputStream(apktoolYaml)); 27 | // int ov = Integer.parseInt(metaInfo.versionInfo.versionCode)+inc; 28 | metaInfo.versionInfo.versionName =versionName; 29 | metaInfo.save(apktoolYaml); 30 | } 31 | public static String getVersionCode(File apktoolYaml){ 32 | MetaInfo metaInfo = null; 33 | try { 34 | metaInfo = MetaInfo.load(new FileInputStream(apktoolYaml)); 35 | String versionCode = metaInfo.versionInfo.versionCode; 36 | return versionCode; 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | return null; 41 | } 42 | 43 | public static String getVersionName(File apktoolYaml){ 44 | MetaInfo metaInfo = null; 45 | try { 46 | metaInfo = MetaInfo.load(new FileInputStream(apktoolYaml)); 47 | String versionName = metaInfo.versionInfo.versionName; 48 | return versionName; 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | return null; 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/Check.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.api.xbase.WorkerAction; 4 | import com.facker.toolchain.api.xbase.XBridge; 5 | import com.facker.toolchain.api.xbase.XModel; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | 8 | import java.util.List; 9 | 10 | public class Check extends WorkerAction { 11 | private XBridge xBridge; 12 | private List xModels; 13 | private XTarget xTarget; 14 | 15 | public Check(XBridge xBridge, List xModels, XTarget xTarget){ 16 | this.xBridge = xBridge; 17 | this.xModels = xModels; 18 | } 19 | 20 | @Override 21 | public void action() throws Exception { 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/CopyBridgeDex.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.base.utils.IOUtil; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XBridge; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | 8 | import java.io.FileInputStream; 9 | import java.io.FileOutputStream; 10 | 11 | public class CopyBridgeDex extends WorkerAction { 12 | private XBridge xBridge; 13 | private XTarget xTarget; 14 | public CopyBridgeDex(XBridge xBridge, XTarget xTarget){ 15 | this.xBridge = xBridge; 16 | this.xTarget = xTarget; 17 | } 18 | @Override 19 | public void action() throws Exception { 20 | IOUtil.copy(new FileInputStream(xBridge.getMainDexFile()), new FileOutputStream(xTarget.getMainDexFile())); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/GatherFlip.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.api.xbase.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class GatherFlip extends WorkerAction { 9 | private XTarget xTarget; 10 | private WorkerListener workerListener; 11 | public GatherFlip(XTarget xTarget, WorkerListener workerListener) { 12 | this.xTarget = xTarget; 13 | this.workerListener =workerListener; 14 | } 15 | @Override 16 | public void action() throws Exception { 17 | ManifestEditor manifestMod = new ManifestEditor(xTarget.getManifestFile()); 18 | String lancherActivityName = manifestMod.getLancherActivityName(); 19 | List flips = new ArrayList<>(); 20 | List activityNames = manifestMod.getActivityNames(); 21 | for (String string :activityNames){ 22 | Worker.XFlip flip = new Worker.XFlip(); 23 | if(lancherActivityName.equals(string)){ 24 | flip.setType("Activity_LAUNCHER"); 25 | }else{ 26 | flip.setType("Activity_COMMON"); 27 | } 28 | flip.setTag(string); 29 | flips.add(flip); 30 | } 31 | workerListener.xflip(xTarget.getId(),flips); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeBridgeAssets.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.utils.FileUtil; 4 | import com.facker.toolchain.utils.Logger; 5 | import com.facker.toolchain.api.xbase.*; 6 | import org.json.JSONArray; 7 | import org.json.JSONObject; 8 | import java.io.File; 9 | import java.util.List; 10 | 11 | public class MergeBridgeAssets extends WorkerAction { 12 | 13 | private XBridge xBridge;//是否需要配置,其他信息 14 | private XTarget xTarget; 15 | private List xModels; 16 | 17 | public MergeBridgeAssets(XBridge xBridge, List xModels, XTarget xTarget){ 18 | this.xBridge = xBridge; 19 | this.xTarget = xTarget; 20 | this.xModels = xModels; 21 | } 22 | @Override 23 | public void action() throws Exception {//运行时配置 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeBridgeLib.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.base.utils.IOUtil; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XBridge; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | import java.io.File; 8 | 9 | public class MergeBridgeLib extends WorkerAction { 10 | private XBridge xBridge; 11 | private XTarget xTarget; 12 | public MergeBridgeLib(XBridge xBridge, XTarget xTarget){ 13 | this.xBridge = xBridge; 14 | this.xTarget = xTarget; 15 | } 16 | 17 | @Override 18 | public void action() throws Exception { 19 | //对老的armeabi 20 | File fileArmeabi = new File(xTarget.getLibDir(),"armeabi"); 21 | if(fileArmeabi.exists()&&fileArmeabi.isDirectory()){ 22 | IOUtil.copyDir(new File(xBridge.getLibDir(),"armeabi-v7a"),fileArmeabi); 23 | } 24 | 25 | File fileV8a = new File(xTarget.getLibDir(),"arm64-v8a"); 26 | if(fileV8a.exists()&&fileV8a.isDirectory()){ 27 | IOUtil.copyDir(new File(xBridge.getLibDir(),"arm64-v8a"),fileV8a); 28 | } 29 | 30 | File fileV7a = new File(xTarget.getLibDir(),"armeabi-v7a"); 31 | if(fileV7a.exists()&&fileV7a.isDirectory()){ 32 | IOUtil.copyDir(new File(xBridge.getLibDir(),"armeabi-v7a"),fileV7a); 33 | } 34 | 35 | File fileX86 = new File(xTarget.getLibDir(),"x86"); 36 | if(fileX86.exists()&&fileX86.isDirectory()){ 37 | IOUtil.copyDir(new File(xBridge.getLibDir(),"x86"),fileX86); 38 | } 39 | File fileX86_64 = new File(xTarget.getLibDir(),"x86_64"); 40 | 41 | if(fileX86_64.exists()&&fileX86_64.isDirectory()){ 42 | IOUtil.copyDir(new File(xBridge.getLibDir(),"x86_64"),fileX86_64); 43 | } 44 | if(!xTarget.getLibDir().exists()){ 45 | IOUtil.copyDir(xBridge.getLibDir(), xTarget.getLibDir()); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeBridgeMainifest.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | import com.facker.toolchain.base.utils.IOUtil; 3 | import com.facker.toolchain.api.xbase.*; 4 | 5 | import java.io.File; 6 | import java.util.List; 7 | 8 | public class MergeBridgeMainifest extends WorkerAction {//敲定netconfig文件 9 | private XBridge xBridge; 10 | private XTarget xTarget; 11 | public MergeBridgeMainifest(XBridge xBridge, XTarget xTarget){ 12 | this.xBridge = xBridge; 13 | this.xTarget = xTarget; 14 | } 15 | 16 | @Override 17 | public void action() throws Exception { 18 | /** 19 | * 源程序 20 | */ 21 | ManifestEditor xTargetManifestEditor = new ManifestEditor(xTarget.getManifestFile()); 22 | 23 | /** 24 | * 桥程序 25 | */ 26 | ManifestEditor xBridgeManifestEditor = new ManifestEditor(xBridge.getManifestFile()); 27 | 28 | /** 29 | * 基本修正 30 | */ 31 | String applicationName = xTargetManifestEditor.getApplicationName(); 32 | String packageName = xTargetManifestEditor.getPackagenName(); 33 | //String lancherAppName = manifestMod.getLancherActivityName(); 34 | if(!TextUtil.isEmpty(applicationName)){ 35 | xTargetManifestEditor.insertMeta("APPLICATION_CLASS_NAME",applicationName); 36 | } 37 | xTargetManifestEditor.insertMeta("pkg",packageName); 38 | xTargetManifestEditor.modApplication(xBridgeManifestEditor.getApplicationName());//动态 39 | 40 | /** 41 | * 修改启动页面名称 42 | */ 43 | if(!TextUtil.isEmpty(xTarget.getAppName())){ 44 | xTargetManifestEditor.modLancherActivityLabel(xTarget.getAppName()); 45 | } 46 | //manifestMod.modLancherActivityIntent(); 47 | 48 | /** 49 | * 目标 application 名称 50 | */ 51 | if(!TextUtil.isEmpty(xTarget.getAppName())){ 52 | xTargetManifestEditor.modApplicationLabel(xTarget.getAppName()); 53 | } 54 | 55 | /** 56 | * 修改安装包包名 57 | */ 58 | if(!TextUtil.isEmpty(xTarget.getPackageName())){ 59 | xTargetManifestEditor.modPkg(xTarget.getPackageName()); 60 | } 61 | /** 62 | * 拷贝原有App项目 63 | */ 64 | xTargetManifestEditor.copyApplicaionElements(xBridgeManifestEditor.getApplicationElement(),xTargetManifestEditor.getApplicationElement()); 65 | 66 | /** 67 | * 权限 68 | */ 69 | List usesPermissions = xBridgeManifestEditor.getUsesPermissions(); 70 | for (String usesPetmission :usesPermissions) { 71 | xTargetManifestEditor.insertUsesPermission(usesPetmission); 72 | } 73 | 74 | List permissions = xBridgeManifestEditor.getPermissions(); 75 | for (String permission :permissions) { 76 | xTargetManifestEditor.insertPermission(permission,null); 77 | } 78 | 79 | /** 80 | * netconfig 如果原来已经配置过了,保留原来的配置 ,如果没有的话,拷贝壳程序的配置名称 在 RESmerge环节会都该文件做相应处理 81 | */ 82 | if(xTargetManifestEditor.getNetworkSecurityConfig()==null){ 83 | String networkSecurityConfig = xBridgeManifestEditor.getNetworkSecurityConfig(); 84 | xTargetManifestEditor.modNetworkSecurityConfig(networkSecurityConfig); 85 | //同时拷贝 bridge 目录下的NetworkSecurityConfig文件进去 86 | File networkSecurityConfigFile = new File(xTarget.getXMLDir(),networkSecurityConfig+".xml"); 87 | if(!networkSecurityConfigFile.getParentFile().exists()){ 88 | networkSecurityConfigFile.getParentFile().mkdir(); 89 | } 90 | IOUtil.copyFile(new File(xBridge.getXMLDir(),networkSecurityConfig+".xml"),networkSecurityConfigFile); 91 | } 92 | xTargetManifestEditor.save(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeBridgeRes.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | import com.facker.toolchain.api.xbase.ResMerge; 3 | import com.facker.toolchain.api.xbase.WorkerAction; 4 | import com.facker.toolchain.api.xbase.XBridge; 5 | import com.facker.toolchain.api.xbase.XTarget; 6 | 7 | public class MergeBridgeRes extends WorkerAction { 8 | private XBridge xBridge; 9 | 10 | private XTarget xTarget; 11 | 12 | public MergeBridgeRes(XBridge xBridge, XTarget xTarget) { 13 | this.xBridge = xBridge; 14 | this.xTarget = xTarget; 15 | } 16 | @Override 17 | public void action() throws Exception { 18 | ResMerge.merge(xBridge.getResDir(),xTarget.getResDir()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeModelsAssets.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.base.utils.IOUtil; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XModel; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | import java.util.List; 8 | 9 | public class MergeModelsAssets extends WorkerAction { 10 | private List xModels;private XTarget xTarget; 11 | public MergeModelsAssets(List xModels, XTarget xTarget){ 12 | this.xModels = xModels; 13 | this.xTarget =xTarget; 14 | 15 | } 16 | @Override 17 | public void action() throws Exception { 18 | for (XModel xModel: xModels) { 19 | IOUtil.copyDir(xModel.getAssets(), xTarget.getAssets()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeModelsLib.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.base.utils.IOUtil; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XModel; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | import java.io.File; 8 | import java.util.List; 9 | 10 | public class MergeModelsLib extends WorkerAction { 11 | 12 | private List xModels; 13 | private XTarget xTarget; 14 | public MergeModelsLib(List xModels, XTarget xTarget){ 15 | this.xModels = xModels; 16 | this.xTarget = xTarget; 17 | } 18 | @Override 19 | public void action() throws Exception {//TODO 20 | for (XModel xModel :xModels) { 21 | if(xModel.getLibDir().isDirectory()){ 22 | File fileArmeabi = new File(xTarget.getLibDir(),"armeabi"); 23 | if(fileArmeabi.exists()&&fileArmeabi.isDirectory()){ 24 | IOUtil.copyDir(new File(xModel.getLibDir(),"armeabi-v7a"),fileArmeabi); 25 | } 26 | File fileV8a = new File(xTarget.getLibDir(),"arm64-v8a"); 27 | if(fileV8a.exists()&&fileV8a.isDirectory()){ 28 | IOUtil.copyDir(new File(xModel.getLibDir(),"arm64-v8a"),fileV8a); 29 | } 30 | 31 | File fileV7a = new File(xTarget.getLibDir(),"armeabi-v7a"); 32 | if(fileV7a.exists()&&fileV7a.isDirectory()){ 33 | IOUtil.copyDir(new File(xModel.getLibDir(),"armeabi-v7a"),fileV7a); 34 | } 35 | 36 | File fileX86 = new File(xTarget.getLibDir(),"x86"); 37 | if(fileX86.exists()&&fileX86.isDirectory()){ 38 | IOUtil.copyDir(new File(xModel.getLibDir(),"x86"),fileX86); 39 | } 40 | File fileX86_64 = new File(xTarget.getLibDir(),"x86_64"); 41 | 42 | if(fileX86_64.exists()&&fileX86_64.isDirectory()){ 43 | IOUtil.copyDir(new File(xModel.getLibDir(),"x86_64"),fileX86_64); 44 | } 45 | if(!xTarget.getLibDir().exists()){ 46 | IOUtil.copyDir(xModel.getLibDir(), xTarget.getLibDir()); 47 | } 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeModelsMainifest.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.api.xbase.ManifestEditor; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XModel; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | import org.dom4j.Attribute; 8 | import org.dom4j.Element; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class MergeModelsMainifest extends WorkerAction { 14 | private List xModels; 15 | private XTarget xTarget; 16 | public MergeModelsMainifest(List xModels, XTarget xTarget){ 17 | this.xModels = xModels; 18 | this.xTarget = xTarget; 19 | } 20 | @Override 21 | public void action() throws Exception{ 22 | for (XModel xModel: xModels) { 23 | ManifestEditor xTargetManifestEditor = new ManifestEditor(xTarget.getManifestFile()); 24 | ManifestEditor manifestModSdk = new ManifestEditor(xModel.getManifestFile()); 25 | 26 | //拷贝 27 | xTargetManifestEditor.copyApplicaionElements(manifestModSdk.getApplicationElement(),xTargetManifestEditor.getApplicationElement()); 28 | 29 | List usesPermissions = manifestModSdk.getUsesPermissions(); 30 | for (String usesPermission :usesPermissions) { 31 | xTargetManifestEditor.insertUsesPermission(usesPermission); 32 | } 33 | 34 | List permissions = manifestModSdk.getPermissions(); 35 | for (String permission :permissions) { 36 | xTargetManifestEditor.insertPermission(permission,"signature"); 37 | } 38 | 39 | Map localParamsMap = xModel.getParams(); 40 | if(localParamsMap!=null){ 41 | for (Map.Entry localParamEntry:localParamsMap.entrySet() ) { 42 | System.out.println("key "+localParamEntry.getKey() +" value "+localParamEntry.getValue()); 43 | xTargetManifestEditor.coverMeta(localParamEntry.getKey(),localParamEntry.getValue()); 44 | } 45 | } 46 | //对manifestd的修改 47 | String doamain = manifestModSdk.getPackagenName(); 48 | // xTargetManifestEditor.modModelProviderAuthorities(doamain,xTargetManifestEditor.getPackagenName()); 49 | //xml format 50 | formatXml(xTargetManifestEditor.getManifestElement(),doamain,xTargetManifestEditor.getPackagenName()); 51 | 52 | 53 | xTargetManifestEditor.save(); 54 | } 55 | } 56 | 57 | public void formatXml(Element node,String modelDomain,String targetPkg){ 58 | //当前节点的名称、文本内容和属性 59 | System.out.println("当前节点名称:"+node.getName());//当前节点名称 60 | System.out.println("当前节点的内容:"+node.getTextTrim());//当前节点名称 61 | List listAttr=node.attributes();//当前节点的所有属性的list 62 | for(Attribute attr:listAttr){//遍历当前节点的所有属性 63 | String name=attr.getName();//属性名称 64 | String value=attr.getValue();//属性的值 65 | System.out.println("属性名称:"+name+"属性值:"+value); 66 | if(value.contains(modelDomain)){ 67 | value = value.replace(modelDomain,targetPkg); 68 | attr.setValue(value); 69 | } 70 | } 71 | //递归遍历当前节点所有的子节点 72 | List listElement=node.elements();//所有一级子节点的list 73 | for(Element e:listElement){//遍历所有一级子节点 74 | this.formatXml(e,modelDomain,targetPkg);//递归 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/MergeModelsRes.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.api.xbase.ResMerge; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XModel; 6 | import com.facker.toolchain.api.xbase.XTarget; 7 | import java.util.List; 8 | 9 | public class MergeModelsRes extends WorkerAction { 10 | private List xModels; 11 | private XTarget xTarget; 12 | public MergeModelsRes(List xModels, XTarget xTarget){ 13 | this.xModels = xModels; 14 | this.xTarget = xTarget; 15 | } 16 | @Override 17 | public void action() throws Exception{ 18 | for (XModel xModel:xModels) { 19 | ResMerge.merge(xModel.getResDir(),xTarget.getResDir()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/ModTargetLogo.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.base.utils.IOUtil; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XTarget; 6 | 7 | import java.io.File; 8 | import java.io.IOException; 9 | import java.util.Map; 10 | 11 | public class ModTargetLogo extends WorkerAction { 12 | 13 | private XTarget xTarget; 14 | 15 | public ModTargetLogo(XTarget xTarget){ 16 | this.xTarget = xTarget; 17 | } 18 | 19 | @Override 20 | public void action() throws Exception { 21 | if(xTarget.getLogos()!=null&&!xTarget.getLogos().isEmpty()){// 22 | for(Map.Entry entry : xTarget.getLogos().entrySet()){ 23 | String mapKey = entry.getKey(); 24 | File oLogoFile = new File(xTarget.getDecodeDir(),mapKey);//原地址 25 | File mapValue = entry.getValue(); 26 | try { 27 | System.out.println("正在拷贝,本地路径"+mapValue+" 包体路径"+oLogoFile); 28 | IOUtil.copy(mapValue,oLogoFile); 29 | } catch (Exception e) { 30 | mapKey = mapKey.replace("-v4",""); 31 | oLogoFile = new File(xTarget.getDecodeDir(),mapKey);//原地址 32 | try { 33 | IOUtil.copy(mapValue,oLogoFile); 34 | } catch (IOException ex) { 35 | throw new Exception("替换logo失败"); 36 | } 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/api/xbase/action/ModXTargetYml.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.api.xbase.action; 2 | 3 | import com.facker.toolchain.api.xbase.TextUtil; 4 | import com.facker.toolchain.api.xbase.WorkerAction; 5 | import com.facker.toolchain.api.xbase.XTarget; 6 | import com.facker.toolchain.api.xbase.YmlMod; 7 | 8 | public class ModXTargetYml extends WorkerAction { 9 | private XTarget xTarget; 10 | public ModXTargetYml(XTarget xTarget){ 11 | this.xTarget = xTarget; 12 | } 13 | @Override 14 | public void action() throws Exception { 15 | if(!TextUtil.isEmpty(xTarget.getVersionName())){ 16 | YmlMod.modVersionName(xTarget.getYmlFile(),xTarget.getVersionName()); 17 | } 18 | if(0!=xTarget.getVersionCode()){ 19 | YmlMod.modVersionCode(xTarget.getYmlFile(),xTarget.getVersionCode()+""); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | public abstract class ArscChunk implements BuildAble { 4 | 5 | protected ArscHeader mHeader; 6 | 7 | ArscChunk(ArscHeader header){ 8 | mHeader = header; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscComplex.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | import java.util.LinkedHashMap; 9 | import java.util.Map; 10 | 11 | public class ArscComplex implements BuildAble { 12 | 13 | int pid; 14 | LinkedHashMap items = new LinkedHashMap<>(); 15 | 16 | public ArscComplex(DataInput stream, StringPoolReader reader) throws IOException { 17 | pid = stream.readInt(); 18 | int count = stream.readInt(); 19 | for (int i = 0; i < count; i++) { 20 | int id = stream.readInt(); 21 | if(items.containsKey(id)){ 22 | throw new RuntimeException("Data Lossing"); 23 | } 24 | items.put(id, new ArscResStringPoolRef(stream, reader)); 25 | } 26 | // System.out.printf(String.format("Complex Here %d\n", 8 + count * 12)); 27 | } 28 | 29 | public int size(){ 30 | return 12*items.size() + 8; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return items.toString(); 36 | } 37 | 38 | @Override 39 | public byte[] build() throws IOException { 40 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 41 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(outputStream); 42 | stream.writeInt(pid); 43 | stream.writeInt(items.size()); 44 | for (Map.Entry entry : items.entrySet()) { 45 | stream.writeInt(entry.getKey()); 46 | stream.write(entry.getValue().build()); 47 | } 48 | byte result[] = outputStream.toByteArray(); 49 | // assert result.length == 8 + items.size() * 12; 50 | // System.out.printf(String.format("Complex Here %d\n", result.length)); 51 | return result; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscDataType.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | public class ArscDataType { 4 | 5 | public static int TYPE_NULL = 0; 6 | public static int TYPE_REFERENCE = 1; 7 | public static int TYPE_ATTRIBUTE = 2; 8 | public static int TYPE_STRING = 3; 9 | public static int TYPE_FLOAT = 4; 10 | public static int TYPE_DIMENSION = 5; 11 | public static int TYPE_FRACTION = 6; 12 | public static int TYPE_FIRST_INT = 16; 13 | public static int TYPE_INT_DEC = 16; 14 | public static int TYPE_INT_HEX = 17; 15 | public static int TYPE_INT_BOOLEAN = 18; 16 | public static int TYPE_FIRST_COLOR_INT = 28; 17 | public static int TYPE_INT_COLOR_ARGB8 = 28; 18 | public static int TYPE_INT_COLOR_RGB8 = 29; 19 | public static int TYPE_INT_COLOR_ARGB4 = 30; 20 | public static int TYPE_INT_COLOR_RGB4 = 31; 21 | public static int TYPE_LAST_COLOR_INT = 31; 22 | public static int TYPE_LAST_INT = 31; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscHeader.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import java.io.DataInput; 4 | import java.io.DataOutput; 5 | import java.io.IOException; 6 | 7 | public class ArscHeader implements BuildAble { 8 | public final short mType; 9 | public final short mHeadSize; 10 | public int mResSize; 11 | 12 | public ArscHeader(DataInput stream) throws IOException { 13 | mType = stream.readShort(); 14 | mHeadSize = stream.readShort(); 15 | mResSize = stream.readInt(); 16 | } 17 | 18 | public ArscHeader(short mType, short mHeadSize, int mResSize) { 19 | this.mType = mType; 20 | this.mHeadSize = mHeadSize; 21 | this.mResSize = mResSize; 22 | } 23 | 24 | @Override 25 | public byte[] build() { 26 | throw new RuntimeException("Not Support"); 27 | } 28 | 29 | public void build(DataOutput output) throws IOException { 30 | output.writeShort(mType); 31 | output.writeShort(mHeadSize); 32 | output.writeInt(mResSize); 33 | } 34 | 35 | @Override 36 | public String toString() { 37 | return String.format("ArscHeader type: %mybatis-config.xml, heads: %d ress: %d", 38 | mType, mHeadSize, mResSize); 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscParser.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.annotations.Beta; 4 | import com.google.common.io.LittleEndianDataInputStream; 5 | import com.facker.toolchain.axml.ByteUtil; 6 | import com.facker.toolchain.axml.struct.StringPoolImpl; 7 | 8 | import java.io.*; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @Beta 13 | public class ArscParser { 14 | private LittleEndianDataInputStream mInputStream; 15 | public StringPoolImpl mStringPool; 16 | public final ArscHeader header; 17 | public List tablePackages = new ArrayList<>(); 18 | public List buildAbles = new ArrayList<>(); 19 | 20 | public ArscParser(File file) throws IOException { 21 | this.mInputStream = new LittleEndianDataInputStream(new BufferedInputStream(new FileInputStream(file))); 22 | header = new ArscHeader(mInputStream); 23 | int PKG_NUM = mInputStream.readInt(); 24 | System.out.printf("Type:0x%04x %d, FileSize:%d PkgNum:%d\n", 25 | header.mType, header.mHeadSize, header.mResSize, PKG_NUM); 26 | while (mInputStream.available() > 0){ 27 | ArscHeader header = new ArscHeader(mInputStream); 28 | System.out.println(header); 29 | switch (header.mType){//具体Case 参照ResType 30 | case 0x1: 31 | mStringPool = new StringPoolImpl(mInputStream, header); 32 | buildAbles.add(mStringPool); 33 | break; 34 | case 0x200: 35 | TablePackageType tablePackage = new TablePackageType(mInputStream, header); 36 | buildAbles.add(tablePackage); 37 | tablePackages.add(tablePackage); 38 | break; 39 | default: 40 | buildAbles.add(new DefaultArscHolder(mInputStream, header)); 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * 参数必须是一个小端码数据输出流 47 | * @param output 48 | */ 49 | public void write(DataOutput output) throws IOException { 50 | byte result[] = null; 51 | for (BuildAble buildAble : buildAbles) { 52 | result = ByteUtil.byteConcatEx(result, buildAble.build()); 53 | } 54 | output.writeShort(header.mType); 55 | output.writeShort(0xC);//Fixed Length 56 | output.writeInt(result.length + 0xC);//Fixed Length 57 | output.writeInt(tablePackages.size()); 58 | output.write(result); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscParserTest.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.facker.toolchain.base.beta.PathUtil; 4 | 5 | import java.io.IOException; 6 | 7 | 8 | public class ArscParserTest { 9 | ArscParser parser; 10 | 11 | public static void main(String[] args) throws IOException { 12 | ArscParserTest test = new ArscParserTest(); 13 | test.setUp(); 14 | makeXmlIn(test.parser,"hellc"); 15 | test.tearDown(); 16 | } 17 | 18 | void setUp() throws IOException { 19 | parser = new ArscParser(PathUtil.inputFile("")); 20 | } 21 | 22 | public static int makeXmlIn(ArscParser parser, String xmlName) throws IOException { 23 | String xmlStr = String.format("res/xml/%s", xmlName); 24 | final int data = parser.mStringPool.getOrCreateString(xmlStr); 25 | if(parser.tablePackages.size() > 0){ 26 | TablePackageType table = parser.tablePackages.get(0); 27 | int pos = table.hasSection("xml"); 28 | if(pos == -1){ 29 | System.out.println("Creating Xml Section"); 30 | int id = table.s1.getOrCreateString("xml") + 1; 31 | ArscHeader header = new ArscHeader((short)ResType.RES_TABLE_TYPE_SPEC_TYPE.value, (short) 16, 0); 32 | ArscResTypeSpec spec = new ArscResTypeSpec((byte)id, (byte)0, 0, table.s1, header); 33 | ArscHeader bodyHeader = new ArscHeader((short)ResType.RES_TABLE_TYPE_TYPE.value, (short)84, 0); 34 | ArscTableType tableType = new ArscTableType(id, 0, 0, 35 | ArscResTableConfig.createDefaultConfig(), table.s2, table.mPackageId, bodyHeader); 36 | spec.children.add(tableType); 37 | table.specMap.put(id, spec); 38 | } 39 | int newPos = table.s1.getOrCreateString("xml"); 40 | ArscResTypeSpec spec = table.specMap.values() 41 | .stream() 42 | .filter(x -> x.id == newPos + 1) 43 | .limit(1) 44 | .findFirst() 45 | .orElseThrow(()-> new RuntimeException("Create Section Failed...")); 46 | spec.typespecEntries.add(0); 47 | int index = table.s2.getOrCreateString(xmlName); 48 | int id = spec.children.get(0) 49 | .put(new ArscResTableEntry(index, 0, null, 50 | new ArscResStringPoolRef(3, data, 0))); 51 | return id; 52 | } 53 | throw new RuntimeException("Not A Good Arsc File"); 54 | } 55 | 56 | // void test() throws IOException { 57 | // TablePackageType table = parser.tablePackages.get(0); 58 | // int pos = table.hasSection("xml"); 59 | // table.specMap.entrySet().stream() 60 | // .filter(mybatis-config.xml -> mybatis-config.xml.getKey() == pos + 1) 61 | // .limit(1) 62 | // .map(Map.Entry::getValue) 63 | // .flatMap(mybatis-config.xml -> mybatis-config.xml.children.stream()) 64 | // .flatMap(mybatis-config.xml -> mybatis-config.xml.entries.stream()) 65 | // .forEach(mybatis-config.xml -> System.out.println(table.s2.getString(mybatis-config.xml.index))); 66 | 67 | // 68 | // ArscParser arscParser = 69 | // new ArscParser(new File("resources0.arsc")); 70 | // } 71 | 72 | void tearDown() { } 73 | } -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscResStringPoolRef.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | 9 | /** 10 | * 固定8字节的一个数据类 11 | */ 12 | public class ArscResStringPoolRef implements BuildAble { 13 | static int SIZE = 8; 14 | int size, //short 15 | data_type, //unsign byte 16 | data, //int 17 | res0;//short 18 | 19 | public ArscResStringPoolRef(int data_type, int data, int res0) { 20 | this.size = 8; 21 | this.data_type = data_type; 22 | this.data = data; 23 | this.res0 = res0; 24 | } 25 | 26 | public ArscResStringPoolRef(DataInput stream, StringPoolReader reader) throws IOException { 27 | size = stream.readUnsignedShort(); 28 | assert size == 8; 29 | res0 = stream.readUnsignedByte(); 30 | data_type = stream.readUnsignedByte(); 31 | data = stream.readInt(); 32 | } 33 | 34 | public int size(){ 35 | return 8; 36 | } 37 | 38 | @Override 39 | public String toString() { 40 | return String.format("[PoolRef: 0x%mybatis-config.xml, data: 0x%08x]", 41 | data_type, data); 42 | } 43 | 44 | @Override 45 | public byte[] build() throws IOException { 46 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 47 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(outputStream); 48 | stream.writeShort(size); 49 | stream.writeByte(res0); 50 | stream.writeByte(data_type); 51 | stream.writeInt(data); 52 | byte result[] = outputStream.toByteArray(); 53 | // assert result.length == 8; 54 | return result; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscResTableConfig.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | 9 | public class ArscResTableConfig implements BuildAble { 10 | public int size = 0, imsi = 0, locale = 0, screenType = 0, input = 0, 11 | screenSize = 0, version = 0; 12 | public Integer screenConfig = null, screenDp = null; 13 | public byte[] extraData; 14 | 15 | public ArscResTableConfig(DataInput stream) throws IOException { 16 | size = stream.readInt(); 17 | imsi = stream.readInt(); 18 | locale = stream.readInt(); 19 | screenType = stream.readInt(); 20 | input = stream.readInt(); 21 | screenSize = stream.readInt(); 22 | version = stream.readInt(); 23 | if(size >= 32){ 24 | screenConfig = stream.readInt(); 25 | if(size >= 36){ 26 | screenDp = stream.readInt(); 27 | int paddingSize = size - 36; 28 | if(paddingSize > 0){ 29 | extraData = new byte[paddingSize]; 30 | stream.readFully(extraData); 31 | } 32 | } 33 | } 34 | } 35 | 36 | protected ArscResTableConfig(){} 37 | 38 | public static ArscResTableConfig createDefaultConfig(){ 39 | ArscResTableConfig config = new ArscResTableConfig(); 40 | config.screenConfig = 0; 41 | config.screenDp = 0; 42 | config.extraData = new byte[64 - config.size()]; 43 | return config; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return "ArscResTableConfig{" + 49 | "size=" + size + 50 | '}'; 51 | } 52 | 53 | public int size(){ 54 | int s = 28; 55 | if(screenConfig != null){ 56 | s = 32; 57 | if(screenDp != null){ 58 | s = 36; 59 | if(extraData != null){ 60 | s = 36 + extraData.length; 61 | } 62 | } 63 | } 64 | return s; 65 | } 66 | 67 | @Override 68 | public byte[] build() throws IOException { 69 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 70 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(outputStream); 71 | int s = size(); 72 | stream.writeInt(s); 73 | stream.writeInt(imsi); 74 | stream.writeInt(locale); 75 | stream.writeInt(screenType); 76 | stream.writeInt(input); 77 | stream.writeInt(screenSize); 78 | stream.writeInt(version); 79 | if (s >= 32){ 80 | stream.writeInt(screenConfig); 81 | if(s >= 36){ 82 | stream.writeInt(screenDp); 83 | if(s > 36 && extraData != null){ 84 | stream.write(extraData); 85 | } 86 | } 87 | } 88 | // stream.writeInt(new_data.length + 4); 89 | // stream.write(new_data); 90 | byte result[] = outputStream.toByteArray(); 91 | return result; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscResTableEntry.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | 9 | public class ArscResTableEntry implements BuildAble { 10 | 11 | static int FLAG_COMPLEX = 1; 12 | static int FLAG_PUBLIC = 2; 13 | static int FLAG_WEAK = 4; 14 | int size, index, resId; 15 | final int flags; 16 | public ArscComplex mArscComplex; 17 | public ArscResStringPoolRef mPoolRef; 18 | public String _cacheValue; 19 | 20 | public ArscResTableEntry(int index, int flags, 21 | ArscComplex mArscComplex, ArscResStringPoolRef mPoolRef) { 22 | this.index = index; 23 | this.flags = flags; 24 | this.mArscComplex = mArscComplex; 25 | this.mPoolRef = mPoolRef; 26 | } 27 | 28 | public ArscResTableEntry(DataInput stream, int ResId, StringPoolReader reader) throws IOException { 29 | size = stream.readUnsignedShort(); 30 | flags = stream.readUnsignedShort(); 31 | index = stream.readInt(); 32 | resId = ResId; 33 | _cacheValue = reader.read(index); 34 | if(isComplex()){ 35 | mArscComplex = new ArscComplex(stream, reader); 36 | }else { 37 | mPoolRef = new ArscResStringPoolRef(stream, reader); 38 | } 39 | } 40 | 41 | public int size(){ 42 | return (isComplex() ? mArscComplex.size() : mPoolRef.size()) + 8; 43 | } 44 | 45 | public boolean isComplex(){ 46 | return (flags & FLAG_COMPLEX) != 0; 47 | } 48 | 49 | public boolean isWeak(){ 50 | return (flags & FLAG_WEAK) != 0; 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return String.format("index:%s, size:%d, flags:%mybatis-config.xml, id:0x%08x %s", 56 | _cacheValue, size, flags, resId, isComplex() ? 57 | mArscComplex.toString(): 58 | mPoolRef.toString()); 59 | } 60 | 61 | @Override 62 | public byte[] build() throws IOException { 63 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 64 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(outputStream); 65 | // 2 + 2 + 4; 66 | byte child[] = isComplex() ? mArscComplex.build() : mPoolRef.build(); 67 | stream.writeShort(isComplex() ? 16 : 8); 68 | stream.writeShort(flags); 69 | stream.writeInt(index); 70 | stream.write(child); 71 | byte result[] = outputStream.toByteArray(); 72 | return result; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ArscResTypeSpec.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | import java.util.stream.Stream; 12 | 13 | public class ArscResTypeSpec extends ArscChunk { 14 | 15 | public final List typespecEntries = new ArrayList<>(); 16 | public final byte id, res0; 17 | public final int res1; 18 | public final StringPoolReader mReader; 19 | public final List children = new ArrayList<>(); 20 | 21 | public ArscResTypeSpec(byte id, byte res0, int res1, StringPoolReader reader, ArscHeader header){ 22 | super(header); 23 | this.id = id; 24 | this.res0 = res0; 25 | this.res1 = res1; 26 | this.mReader = reader; 27 | } 28 | 29 | public ArscResTypeSpec(DataInput in, ArscHeader header, StringPoolReader reader) throws IOException { 30 | super(header); 31 | mReader = reader; 32 | id = in.readByte(); 33 | res0 = in.readByte(); 34 | res1 = in.readUnsignedShort(); 35 | int entryCount = in.readInt(); 36 | typespecEntries.clear(); 37 | typespecEntries.addAll(Stream.generate(() -> { 38 | try { 39 | return in.readInt(); 40 | } catch (IOException e) { 41 | throw new RuntimeException(e.getCause()); 42 | } 43 | }) 44 | .limit(entryCount) 45 | .collect(Collectors.toList())); 46 | } 47 | 48 | public String getId() { 49 | return mReader.read(id - 1); 50 | } 51 | 52 | public void addChild(ArscTableType table){ 53 | table.setTypeString(getId()); 54 | children.add(table); 55 | } 56 | 57 | @Override 58 | public String toString() { 59 | return String.format("id:%s, res0:%d, res1:0x%08x, " + 60 | "count:%d datas:%s," + 61 | "\nchildren: %s", getId(), 62 | res0, res1, typespecEntries.size(), 63 | typespecEntries.stream() 64 | .map(v->String.format("0x%08x", v)).collect(Collectors.joining(", ")), 65 | children.toString()); 66 | } 67 | 68 | @Override 69 | public byte[] build() throws IOException { 70 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 71 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(outputStream); 72 | mHeader.mResSize = 16 + typespecEntries.size() * 4; 73 | mHeader.build(stream); 74 | stream.writeByte(id); 75 | stream.writeByte(res0); 76 | stream.writeShort(res1); 77 | stream.writeInt(typespecEntries.size()); 78 | for (Integer entry : typespecEntries) { 79 | stream.writeInt(entry); 80 | } 81 | for (ArscTableType child : this.children) { 82 | outputStream.write(child.build()); 83 | } 84 | byte result[] = outputStream.toByteArray(); 85 | return result; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/BuildAble.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import java.io.IOException; 4 | 5 | public interface BuildAble { 6 | byte[] build() throws IOException; 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/DefaultArscHolder.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.DataInput; 7 | import java.io.IOException; 8 | 9 | public class DefaultArscHolder implements BuildAble{ 10 | public final ArscHeader header; 11 | public final byte[] stores; 12 | 13 | public DefaultArscHolder(DataInput input, ArscHeader header) throws IOException { 14 | this.header = header; 15 | stores = new byte[header.mResSize - 8]; 16 | input.readFully(stores); 17 | } 18 | 19 | @Override 20 | public byte[] build() throws IOException { 21 | ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); 22 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(outputStream); 23 | header.build(stream); 24 | stream.write(stores); 25 | return outputStream.toByteArray(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/ResType.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | public enum ResType { 4 | RES_NULL_TYPE ( 0x0000), 5 | RES_STRING_POOL_TYPE ( 0x0001), 6 | RES_TABLE_TYPE ( 0x0002), 7 | RES_XML_TYPE ( 0x0003), 8 | 9 | RES_XML_FIRST_CHUNK_TYPE ( 0x0100), 10 | RES_XML_START_NAMESPACE_TYPE( 0x0100), 11 | RES_XML_END_NAMESPACE_TYPE ( 0x0101), 12 | RES_XML_START_ELEMENT_TYPE ( 0x0102), 13 | RES_XML_END_ELEMENT_TYPE ( 0x0103), 14 | RES_XML_CDATA_TYPE ( 0x0104), 15 | RES_XML_LAST_CHUNK_TYPE ( 0x017f), 16 | RES_XML_RESOURCE_MAP_TYPE ( 0x0180), 17 | 18 | RES_TABLE_PACKAGE_TYPE ( 0x0200), 19 | RES_TABLE_TYPE_TYPE ( 0x0201), 20 | RES_TABLE_TYPE_SPEC_TYPE ( 0x0202), 21 | RES_TABLE_LIBRARY_TYPE ( 0x0203); 22 | 23 | public final short value; 24 | 25 | private ResType(Integer v){ 26 | this.value = v.shortValue(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/arsc/StringPoolReader.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.arsc; 2 | 3 | public interface StringPoolReader { 4 | 5 | public String read(int id); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/BinXmlHelper.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml; 2 | 3 | import com.facker.toolchain.axml.struct.AttributeData; 4 | 5 | import java.util.List; 6 | 7 | public class BinXmlHelper { 8 | 9 | /** 10 | * 查找最佳插入位置 11 | * @param editor 编辑器 12 | * @return 13 | */ 14 | private static int getBestPositionName(BinXmlParser editor){ 15 | List attrs = editor.memListAttr("application"); 16 | int label = 0, icon = 0; 17 | for (int i = 0; i < attrs.size(); i++) { 18 | final AttributeData data = attrs.get(i); 19 | final String name = editor.getString(data.name); 20 | if("label".equals(name)){ 21 | label = i; 22 | } 23 | if("icon".equals(name)){ 24 | icon = i; 25 | } 26 | } 27 | return Math.max(label, icon); 28 | } 29 | 30 | /** 31 | * 插入Application Name 32 | * @param editor 33 | * @param attrValue 34 | */ 35 | public static void insertApplicationName(BinXmlParser editor, String attrValue){ 36 | int sId = getApplicationNameId(editor); 37 | if(sId != -1){ 38 | editor.setStringById(sId, attrValue); 39 | return; 40 | } 41 | int newPos = editor.lookingForGoodPosition(editor.memListAttr("application") , "name"); 42 | // int bestPosition = getBestPositionName(editor) + 1; 43 | editor.memAddAttr("application", "name", attrValue, newPos); 44 | } 45 | 46 | /** 47 | * 获取已有的Application Name Id 48 | * @param editor 49 | * @return 如果有返回id,没有返回-1 50 | */ 51 | public static int getApplicationNameId(BinXmlParser editor){ 52 | List attrs = editor.memListAttr("application"); 53 | for (int i = 0; i < attrs.size(); i++) { 54 | AttributeData data = attrs.get(i); 55 | final String name = editor.getString(data.name); 56 | if("name".equals(name)){ 57 | return data.valueString; 58 | } 59 | } 60 | return -1; 61 | } 62 | 63 | public static void autoCreateNode(BinXmlParser editor, String tag, String attrName, AttributeData data){ 64 | editor.memAddAttr(tag, data, 65 | editor.lookingForGoodPosition(editor.memListAttr(tag), attrName)); 66 | } 67 | 68 | public static void modifyApplicationLabel(BinXmlParser parser, String label){ 69 | AttributeData data = parser.createAttributeData("label", label); 70 | parser.memModifyAttr("application", null, "label", data); 71 | } 72 | 73 | public static int readTargetPlatformCode(BinXmlParser parser){ 74 | String targetSdk = parser.memReadAttr("uses-sdk", null, "targetSdkVersion"); 75 | if(targetSdk != null){ 76 | return Integer.parseInt(targetSdk); 77 | } 78 | return 0; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/DefaultIdHolder.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml; 2 | 3 | import org.w3c.dom.Document; 4 | import org.w3c.dom.NamedNodeMap; 5 | import org.w3c.dom.Node; 6 | import org.w3c.dom.NodeList; 7 | import org.xml.sax.SAXException; 8 | 9 | import javax.xml.parsers.DocumentBuilder; 10 | import javax.xml.parsers.DocumentBuilderFactory; 11 | import javax.xml.parsers.ParserConfigurationException; 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | 17 | public final class DefaultIdHolder implements IdHolder { 18 | 19 | public final Map intMap = new HashMap<>(); 20 | public final Map strMap = new HashMap<>(); 21 | private static volatile DefaultIdHolder INSTANCE; 22 | 23 | public static void main(String[] args) { 24 | DefaultIdHolder.getInstance(); 25 | } 26 | 27 | public static DefaultIdHolder getInstance() { 28 | if(INSTANCE == null){ 29 | synchronized (DefaultIdHolder.class){ 30 | if(INSTANCE == null){ 31 | try { 32 | INSTANCE = new DefaultIdHolder(); 33 | } catch (ParserConfigurationException e) { 34 | e.printStackTrace(); 35 | } catch (IOException e) { 36 | e.printStackTrace(); 37 | } catch (SAXException e) { 38 | e.printStackTrace(); 39 | } 40 | } 41 | } 42 | } 43 | return INSTANCE; 44 | } 45 | 46 | public DefaultIdHolder() throws ParserConfigurationException, IOException, SAXException { 47 | DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 48 | DocumentBuilder documentBuilder = dbf.newDocumentBuilder(); 49 | Document document = documentBuilder.parse(new File("public.xml")); 50 | NodeList list = document.getElementsByTagName("public"); 51 | for (int i = 0; i < list.getLength(); i++) { 52 | Node node = list.item(i); 53 | NamedNodeMap nodeMap = node.getAttributes(); 54 | if(nodeMap.getLength() > 0 && nodeMap.getNamedItem("type") != null 55 | && nodeMap.getNamedItem("type").getNodeValue().equalsIgnoreCase("attr") 56 | && nodeMap.getNamedItem("id") != null){ 57 | int value = Integer.parseInt(nodeMap.getNamedItem("id").getNodeValue().substring(2), 16); 58 | String key = nodeMap.getNamedItem("name").getNodeValue(); 59 | intMap.put(value, key); 60 | strMap.put(key, value); 61 | } 62 | } 63 | } 64 | 65 | @Override 66 | public String get(int id) { 67 | return intMap.get(id); 68 | } 69 | 70 | @Override 71 | public Integer get(String str) { 72 | return strMap.get(str); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/IdHolder.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml; 2 | 3 | public interface IdHolder { 4 | String get(int id); 5 | Integer get(String str); 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/Main.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml; 2 | 3 | import com.facker.toolchain.base.beta.PathUtil; 4 | import com.facker.toolchain.base.utils.IOUtil; 5 | import com.facker.toolchain.axml.struct.AttributeData; 6 | 7 | import javax.swing.*; 8 | import java.io.ByteArrayInputStream; 9 | import java.io.File; 10 | import java.io.FileOutputStream; 11 | import java.util.List; 12 | 13 | public class Main { 14 | 15 | 16 | public static void main(String[] args) throws Exception { 17 | 18 | File dir = PathUtil.inputFile("", JFileChooser.FILES_AND_DIRECTORIES, false); 19 | BinXmlParser editor = new BinXmlParser(dir); 20 | // editor.resDump(); 21 | String applicationName = editor.memReadAttr("application", "application", "name"); 22 | List data = editor.memListAttr("application"); 23 | int i = editor.lookingForGoodPosition(data, "networkSecurityConfig"); 24 | editor.memAddAttr("application", editor.createAttributeData("networkSecurityConfig", 25 | "@7F00CCCC"), 26 | editor.lookingForGoodPosition(editor.memListAttr("application"), 27 | "networkSecurityConfig")); 28 | FileOutputStream fileOutputStream = new FileOutputStream(new File(dir.getParent(),"z.xml")); 29 | ByteArrayInputStream inputStream = new ByteArrayInputStream(editor.memSave()); 30 | IOUtil.copy(inputStream, fileOutputStream); 31 | } 32 | 33 | 34 | @Deprecated 35 | public static String readPath(String desc) { 36 | return ""; 37 | } 38 | 39 | public static File inputFile(String desc, int mode, boolean isSave){ 40 | JFileChooser fd = new JFileChooser(); 41 | fd.setFileSelectionMode(mode); 42 | int result = isSave ? fd.showSaveDialog(null): fd.showOpenDialog(null); 43 | if(JFileChooser.APPROVE_OPTION == result){ 44 | return fd.getSelectedFile(); 45 | }else { 46 | return inputFile(desc, mode, isSave); 47 | } 48 | } 49 | public static File inputFile(String desc){ 50 | return inputFile(desc, 0, false); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/AttributeData.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | 4 | import com.facker.toolchain.axml.ByteUtil; 5 | 6 | public class AttributeData { 7 | 8 | public int nameSpaceUri; 9 | public int name; 10 | public int valueString; 11 | public int type = 0; 12 | public int data = 0; 13 | 14 | public String optName, optValue; 15 | 16 | 17 | public void makeOpt(StringPool pool){ 18 | optName = pool.getString(name); 19 | optValue = pool.getString(valueString); 20 | } 21 | 22 | @Override 23 | public String toString() { 24 | if(optName == null){ 25 | return String.format("key:%d,value: %d, %d", name, valueString, data); 26 | }else { 27 | return String.format("key:%s, value: %s", optName, optValue); 28 | } 29 | } 30 | 31 | public int offset; 32 | 33 | public int getLen(){ 34 | return 20; 35 | } 36 | 37 | public static AttributeData createAttribute(byte[] src){ 38 | AttributeData data = new AttributeData(); 39 | data.nameSpaceUri = ByteUtil.byte2intEx(src, 0); 40 | data.name = ByteUtil.byte2intEx(src, 4); 41 | data.valueString = ByteUtil.byte2intEx(src, 8); 42 | data.type = ByteUtil.byte2intEx(src, 12); 43 | data.data = ByteUtil.byte2intEx(src, 16); 44 | return data; 45 | } 46 | 47 | public byte[] getByte(){ 48 | // byte[] bytes = new byte[20]; 49 | return ByteUtil.byteConcatEx(ByteUtil.int2Byte(nameSpaceUri), 50 | ByteUtil.int2Byte(name), ByteUtil.int2Byte(valueString), 51 | ByteUtil.int2Byte(type), ByteUtil.int2Byte(data)); 52 | } 53 | 54 | /** 55 | * 创建一个属性数据 56 | * @param uri uri id 57 | * @param name name id 58 | * @param value value id 59 | * @param type 类型 60 | * @param data1 数据 61 | * @return 62 | */ 63 | public static AttributeData createAttribute(int uri, int name, int value, int type, int data1){ 64 | AttributeData data = new AttributeData(); 65 | data.nameSpaceUri = uri; 66 | data.name = name; 67 | data.valueString = value; 68 | data.type = type; 69 | data.data = data1; 70 | return data; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/Chunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | public interface Chunk { 4 | 5 | byte[] getChunkByte(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/ChunkTypeNumber.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | /** 4 | * 5 | chunks' magic numbers 6 | enum{ 7 | CHUNK_HEAD = 0x00080003, 8 | 9 | CHUNK_STRING = 0x001c0001, 10 | CHUNK_RESOURCE = 0x00080180, 11 | 12 | CHUNK_STARTNS = 0x00100100, 13 | CHUNK_ENDNS = 0x00100101, 14 | CHUNK_STARTTAG = 0x00100102, 15 | CHUNK_ENDTAG = 0x00100103, 16 | CHUNK_TEXT = 0x00100104, 17 | }; 18 | * @author i 19 | */ 20 | public class ChunkTypeNumber { 21 | 22 | public final static int CHUNK_HEAD = 0x00080003; 23 | public final static int CHUNK_STRING = 0x001c0001; 24 | public final static int CHUNK_STARTNS = 0x00100100; 25 | public final static int CHUNK_ENDNS = 0x00100101; 26 | public final static int CHUNK_STARTTAG = 0x00100102; 27 | public final static int CHUNK_ENDTAG = 0x00100103; 28 | public final static int CHUNK_TEXT = 0x00100104; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/EndNameSpaceChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | 4 | import com.facker.toolchain.axml.ByteUtil; 5 | 6 | public class EndNameSpaceChunk{ 7 | 8 | public byte[] type = new byte[4]; 9 | public byte[] size = new byte[4]; 10 | public byte[] lineNumber = new byte[4]; 11 | public byte[] unknown = new byte[4]; 12 | public byte[] prefix = new byte[4]; 13 | public byte[] uri = new byte[4]; 14 | 15 | public static EndNameSpaceChunk createChunk(byte[] byteSrc){ 16 | 17 | EndNameSpaceChunk chunk = new EndNameSpaceChunk(); 18 | 19 | //����type 20 | chunk.type = ByteUtil.copyByte(byteSrc, 0, 4); 21 | 22 | //����size 23 | chunk.size = ByteUtil.copyByte(byteSrc, 4, 4); 24 | 25 | //�����к� 26 | chunk.lineNumber = ByteUtil.copyByte(byteSrc, 8, 4); 27 | 28 | //����unknown 29 | chunk.unknown = ByteUtil.copyByte(byteSrc, 12, 4); 30 | 31 | //����prefix(������Ҫע������кź�����ĸ��ֽ�ΪFFFF,����) 32 | chunk.prefix = ByteUtil.copyByte(byteSrc, 16, 4); 33 | 34 | //����Uri 35 | chunk.uri = ByteUtil.copyByte(byteSrc, 20, 4); 36 | 37 | return chunk; 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/EndTagChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | 4 | import com.facker.toolchain.axml.ByteUtil; 5 | 6 | public class EndTagChunk implements Chunk{ 7 | 8 | public byte[] type = new byte[4]; 9 | public byte[] size = new byte[4]; 10 | public byte[] lineNumber = new byte[4]; 11 | public byte[] unknown = new byte[4]; 12 | public byte[] uri = new byte[4]; 13 | public byte[] name = new byte[4]; 14 | 15 | public int offset; 16 | 17 | public String optName; 18 | 19 | public void makeOpt(StringPool pool){ 20 | optName = pool.getString(ByteUtil.byte2int(name)); 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return String.format("End: %s", optName == null ? "" : optName); 26 | } 27 | 28 | public EndTagChunk(){ 29 | type = ByteUtil.int2Byte(ChunkTypeNumber.CHUNK_ENDTAG); 30 | size = ByteUtil.int2Byte(24); 31 | lineNumber = new byte[4]; 32 | unknown = new byte[4]; 33 | uri = ByteUtil.int2Byte(-1); 34 | } 35 | 36 | public static EndTagChunk createChunk(int name){ 37 | EndTagChunk chunk = new EndTagChunk(); 38 | chunk.name = ByteUtil.int2Byte(name); 39 | return chunk; 40 | } 41 | 42 | public byte[] getChunkByte(){ 43 | byte[] bytes = new byte[getLen()]; 44 | bytes = ByteUtil.byteConcat(bytes, type, 0); 45 | bytes = ByteUtil.byteConcat(bytes, size, 4); 46 | bytes = ByteUtil.byteConcat(bytes, lineNumber, 8); 47 | bytes = ByteUtil.byteConcat(bytes, unknown, 12); 48 | bytes = ByteUtil.byteConcat(bytes, uri, 16); 49 | bytes = ByteUtil.byteConcat(bytes, name, 20); 50 | return bytes; 51 | } 52 | 53 | public int getLen(){ 54 | return type.length + size.length + lineNumber.length + unknown.length + uri.length + name.length; 55 | } 56 | 57 | public static EndTagChunk createChunk(byte[] byteSrc, int offset){ 58 | 59 | EndTagChunk chunk = new EndTagChunk(); 60 | 61 | chunk.offset = offset; 62 | 63 | chunk.type = ByteUtil.copyByte(byteSrc, 0, 4); 64 | 65 | chunk.size = ByteUtil.copyByte(byteSrc, 4, 4); 66 | 67 | chunk.lineNumber = ByteUtil.copyByte(byteSrc, 8, 4); 68 | 69 | chunk.unknown = ByteUtil.copyByte(byteSrc, 12, 4); 70 | 71 | chunk.uri = ByteUtil.copyByte(byteSrc, 16, 4); 72 | 73 | chunk.name = ByteUtil.copyByte(byteSrc, 20, 4); 74 | 75 | return chunk; 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/ResourceChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | import com.google.common.io.LittleEndianDataOutputStream; 4 | import com.facker.toolchain.axml.ByteUtil; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.IOException; 8 | import java.util.ArrayList; 9 | 10 | public class ResourceChunk { 11 | 12 | public byte[] type; 13 | public byte[] size; 14 | 15 | public ArrayList resourcIdList; 16 | 17 | public static ResourceChunk createChunk(byte[] byteSrc, int offset){ 18 | ResourceChunk chunk = new ResourceChunk(); 19 | chunk.type = ByteUtil.copyByte(byteSrc, 0+offset, 4); 20 | chunk.size = ByteUtil.copyByte(byteSrc, 4+offset, 4); 21 | int chunkSize = ByteUtil.byte2int(chunk.size); 22 | 23 | byte[] resourceIdByte = ByteUtil.copyByte(byteSrc, 8+offset, chunkSize-8); 24 | ArrayList resourceIdList = new ArrayList(resourceIdByte.length/4); 25 | for(int i=0;i=0 && i < resourcIdList.size(); 35 | } 36 | 37 | public int getResId(int index){ 38 | return resourcIdList.get(index); 39 | } 40 | 41 | public byte[] save() throws IOException { 42 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 43 | LittleEndianDataOutputStream stream = new LittleEndianDataOutputStream(out); 44 | stream.write(type); 45 | stream.writeInt(resourcIdList.size() * 4 + 8); 46 | for (Integer i : resourcIdList) { 47 | stream.writeInt(i); 48 | } 49 | stream.flush(); 50 | return out.toByteArray(); 51 | } 52 | 53 | 54 | 55 | 56 | public int getSize() { 57 | return ByteUtil.byte2int(size); 58 | } 59 | 60 | public int getCount(){ 61 | return getSize() / 4; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/StartNameSpaceChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | 4 | import com.facker.toolchain.axml.ByteUtil; 5 | 6 | public class StartNameSpaceChunk implements Chunk { 7 | 8 | public byte[] type = new byte[4]; 9 | public byte[] size = new byte[4]; 10 | public byte[] lineNumber = new byte[4]; 11 | public byte[] unknown = new byte[4]; 12 | public byte[] prefix = new byte[4]; 13 | public byte[] uri = new byte[4]; 14 | 15 | public static StartNameSpaceChunk createChunk(byte[] byteSrc){ 16 | 17 | StartNameSpaceChunk chunk = new StartNameSpaceChunk(); 18 | 19 | chunk.type = ByteUtil.copyByte(byteSrc, 0, 4); 20 | 21 | chunk.size = ByteUtil.copyByte(byteSrc, 4, 4); 22 | 23 | chunk.lineNumber = ByteUtil.copyByte(byteSrc, 8, 4); 24 | 25 | chunk.unknown = ByteUtil.copyByte(byteSrc, 12, 4); 26 | 27 | chunk.prefix = ByteUtil.copyByte(byteSrc, 16, 4); 28 | 29 | chunk.uri = ByteUtil.copyByte(byteSrc, 20, 4); 30 | 31 | return chunk; 32 | 33 | } 34 | 35 | @Override 36 | public byte[] getChunkByte() { 37 | return ByteUtil.byteConcatEx(type, size, lineNumber, unknown, prefix, uri); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/StringPool.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | public interface StringPool { 4 | 5 | public int IS_UTF8 = 1 << 8; 6 | 7 | /** 8 | * 获取当前池内容字节 9 | * @return 10 | */ 11 | byte[] getBytes(); 12 | 13 | 14 | /** 15 | * 获取字符串数量 16 | * @return 17 | */ 18 | int getStringCount(); 19 | 20 | int findStringId(String content); 21 | 22 | /** 23 | * 必定返回有效StringId 24 | * @param content 25 | * @return 26 | */ 27 | int getOrCreateString(String content); 28 | 29 | String getString(int id); 30 | 31 | void setStringById(int id, String content); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/TagChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | public class TagChunk { 4 | 5 | public StartTagChunk startTagChunk; 6 | public EndTagChunk endTagChunk; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/axml/struct/TextChunk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.axml.struct; 2 | 3 | import com.facker.toolchain.axml.ByteUtil; 4 | 5 | public class TextChunk implements Chunk { 6 | 7 | public byte[] type = new byte[4]; 8 | public byte[] size = new byte[4]; 9 | public byte[] org; 10 | 11 | public static TextChunk createChunk(byte[] byteSrc, int offset){ 12 | TextChunk chunk = new TextChunk(); 13 | chunk.type = ByteUtil.copyByte(byteSrc, 0, 4); 14 | chunk.size = ByteUtil.copyByte(byteSrc, 4, 4); 15 | int size = ByteUtil.byte2int(chunk.size); 16 | chunk.org = new byte[size - 8]; 17 | System.arraycopy(byteSrc, 8, chunk.org, 0, chunk.org.length); 18 | return chunk; 19 | 20 | } 21 | 22 | @Override 23 | public byte[] getChunkByte() { 24 | return ByteUtil.byteConcatEx(type, size, org); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/beta/PathUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.beta; 2 | 3 | import javax.swing.*; 4 | import java.io.File; 5 | import java.util.Scanner; 6 | 7 | public class PathUtil { 8 | @Deprecated 9 | public static String readPath(String desc) { 10 | return getString(desc); 11 | } 12 | 13 | private static String getString(String desc) { 14 | System.out.print(desc); 15 | Scanner scanner = new Scanner(System.in); 16 | String targetString = scanner.next(); 17 | scanner.close(); 18 | return targetString; 19 | } 20 | 21 | public static File inputFile(String desc, int mode, boolean isSave){ 22 | JFileChooser fd = new JFileChooser("\\"); 23 | fd.setFileSelectionMode(mode); 24 | int result = isSave ? fd.showSaveDialog(null): fd.showOpenDialog(null); 25 | if(JFileChooser.APPROVE_OPTION == result){ 26 | return fd.getSelectedFile(); 27 | }else { 28 | return inputFile(desc, mode, isSave); 29 | } 30 | } 31 | public static File inputFile(String desc){ 32 | return inputFile(desc, 0, false); 33 | } 34 | 35 | public static String getFileNameNoEx(String filePath) { 36 | String filename = getFileName(filePath); 37 | if ((filename != null) && (filename.length() > 0)) { 38 | int dot = filename.lastIndexOf('.'); 39 | if ((dot >-1) && (dot < (filename.length()))) { 40 | return filename.substring(0, dot); 41 | } 42 | } 43 | return filename; 44 | } 45 | 46 | private static String getFileName(String filePath) { 47 | File tempFile =new File(filePath.trim()); 48 | String fileName = tempFile.getName(); 49 | return fileName; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/beta/TestClassify.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.beta; 2 | 3 | import javax.swing.*; 4 | import java.io.File; 5 | import java.io.IOException; 6 | import java.util.Enumeration; 7 | import java.util.zip.ZipEntry; 8 | import java.util.zip.ZipFile; 9 | 10 | public class TestClassify { 11 | 12 | public static void main(String[] args) throws IOException { 13 | File dir = PathUtil.inputFile("", JFileChooser.FILES_AND_DIRECTORIES, false); 14 | int u3dCount = 0, cocos2dCount = 0, unknowCount = 0, ueCount = 0; 15 | for (File file : dir.listFiles()) { 16 | String target = "unknow"; 17 | if(file.isFile() && file.getName().endsWith(".apk")){ 18 | ZipFile z = new ZipFile(file); 19 | Enumeration zz = z.entries(); 20 | while (zz.hasMoreElements()){ 21 | ZipEntry entry = zz.nextElement(); 22 | if(entry.getName().contains("cocos2d.so")){ 23 | target = "cocos2d"; 24 | }else if (entry.getName().contains("unity.so")|| 25 | entry.getName().contains("assets\\bin\\Data\\Managed")){ 26 | target = "unity3d"; 27 | }else if(entry.getName().contains("UnrealEngine")) { 28 | target = "ue"; 29 | } 30 | } 31 | switch (target){ 32 | case "unknow": 33 | unknowCount++; 34 | break; 35 | case "cocos2d": 36 | cocos2dCount++; 37 | break; 38 | case "unity3d": 39 | u3dCount ++; 40 | break; 41 | case "ue": 42 | ueCount++; 43 | break; 44 | } 45 | z.close(); 46 | System.out.printf("%s Type:%s\n", file.getName(), target); 47 | } 48 | } 49 | System.out.printf("U3D:%d, Cocos:%d, ue:%d, unkonw:%d", u3dCount, cocos2dCount, ueCount, unknowCount); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/mod/Constant.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.mod; 2 | 3 | import java.io.File; 4 | 5 | public class Constant { 6 | 7 | 8 | public static class PATH { 9 | /** 10 | * ---------------------------工作空间跟路径---------------------------------------- 11 | */ 12 | 13 | 14 | public static final String ROOT_DIR = "D:\\crazy"; 15 | 16 | 17 | /** 18 | * ---------------------------配置文路径------------------------------------------- 19 | */ 20 | /** 21 | * 配置文件,文件夹路径 22 | */ 23 | public static final String CONFIG = ROOT_DIR + File.separator +"config"; 24 | 25 | /** 26 | * 签名文件路径 27 | */ 28 | public static final String CONFIG_INJECTOR_VAPP = CONFIG+ File.separator+ "vapp.jks"; 29 | 30 | /** 31 | * 源码文件夹路径 32 | */ 33 | public static final String SOURCE = ROOT_DIR + File.separator+"source"; 34 | 35 | 36 | public static final String SOURCE_PERFECT = SOURCE + File.separator+"perfect"; 37 | 38 | 39 | public static final String APK = ROOT_DIR + File.separator+"apk"; 40 | 41 | public static final String SOURCE_PERFECT_APK = APK + File.separator+"perfect"; 42 | 43 | 44 | 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/mod/DealApk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.mod; 2 | 3 | 4 | import com.facker.toolchain.base.utils.SignUtil; 5 | import com.facker.toolchain.utils.Logger; 6 | import com.facker.toolchain.api.xbase.ApkTool; 7 | 8 | import java.io.File; 9 | 10 | 11 | public class DealApk { 12 | private static final String IN_DIR = Constant.PATH.ROOT_DIR +File.separator+"apkin"; 13 | public static void main(String[] args) { 14 | // 15 | } 16 | static void multiFuck(){ 17 | File file =new File("D:\\crazy\\apkin"); 18 | File xApks[] = file.listFiles(); 19 | for (File xApk:xApks) { 20 | String name = xApk.getName(); 21 | try{ 22 | fuckApk(name,false,false,false,true); 23 | }catch (Exception e){ 24 | e.printStackTrace();; 25 | } 26 | } 27 | } 28 | static void fuckApk(String apkName,boolean coverSource,boolean rmAds,boolean rmGoolge,boolean rmFileProvider){ 29 | String filePath = makeCleaSource(apkName,coverSource); 30 | if(rmGoolge){ 31 | StaticInjector.coverGoogleDialog(filePath); 32 | } 33 | if(rmAds){ 34 | StaticInjector.rmAds(filePath); 35 | } 36 | if(rmFileProvider){ 37 | StaticInjector.rmFileProvider(filePath); 38 | } 39 | buildCleaApk(filePath); 40 | } 41 | static String makeCleaSource(String apkName,boolean coverSource){ 42 | String apkPath = IN_DIR+File.separator+apkName; 43 | String sourcePath = Constant.PATH.SOURCE_PERFECT + File.separator + apkName.replace(".apk",""); 44 | File cF = new File(sourcePath); 45 | if(cF.exists()&&!coverSource){ 46 | return sourcePath; 47 | } 48 | ApkTool.decodeSrc(new File(apkPath), new File(sourcePath)); 49 | return sourcePath; 50 | } 51 | static void buildCleaApk(String sourcePath){ 52 | File s = new File(sourcePath); 53 | String name = s.getName(); 54 | name = name.replace(" ",""); 55 | String targetApkPath = Constant.PATH.SOURCE_PERFECT_APK + File.separator +name +".apk"; 56 | ApkTool.build(new File(sourcePath), new File(targetApkPath)); 57 | SignUtil.sign(targetApkPath,Constant.PATH.CONFIG_INJECTOR_VAPP, "cn","vapp123", "vapp123"); 58 | Logger.log("安装签名完成---------,开始执行安装操作"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/mod/FuckApk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.mod; 2 | 3 | 4 | import com.android.apksig.ApkVerifier; 5 | import com.facker.toolchain.base.utils.SignUtil; 6 | import com.facker.toolchain.api.xbase.ApkTool; 7 | 8 | import java.io.File; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | 13 | public class FuckApk { 14 | private static final String IN_DIR = "apk"; 15 | private static final String KEY_PATH = "vapp.jks"; 16 | public static void main(String[] args) throws Exception { 17 | fuckApk("Brain OutV1.3.12"); 18 | build("Brain OutV1.3.12"); 19 | } 20 | 21 | 22 | public static void fuckApk(String name){ 23 | ApkTool.decodeSrc(new File(IN_DIR,name+".apk"), new File(IN_DIR,name)); 24 | } 25 | 26 | public static void build(String name){ 27 | ApkTool.build(new File(IN_DIR,name), new File(IN_DIR,"re-"+name+".apk")); 28 | SignUtil.sign(KEY_PATH, "123", "cn",new File(IN_DIR,"re-"+name+".apk").getAbsolutePath(), "123"); 29 | } 30 | 31 | 32 | public boolean verifierApkOk(File file) { 33 | try { 34 | 35 | }catch (Exception e){ } 36 | return false; 37 | } 38 | 39 | public static boolean sign(String apkPath,String ks,String alias,String ksPass,String keyPass) throws Exception { 40 | try { 41 | List params = new ArrayList<>(); 42 | params.add("sign"); 43 | params.add("--ks"); 44 | params.add(ks); 45 | params.add("--ks-pass"); 46 | params.add("pass:"+ksPass); 47 | params.add("--ks-key-alias"); 48 | params.add(alias); 49 | params.add("--key-pass"); 50 | params.add("pass:"+keyPass); 51 | params.add("--out"); 52 | params.add(apkPath); 53 | params.add(apkPath); 54 | ApkSignerTool.main(params.toArray(new String[params.size()])); 55 | ApkVerifier verifier = new ApkVerifier.Builder(new File(apkPath)).build(); 56 | if(verifier.verify().isVerified()){ 57 | return true; 58 | } 59 | return false; 60 | }catch (Exception e){ 61 | e.printStackTrace(); 62 | } 63 | return false; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/mod/HexEncoding.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.mod; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | public class HexEncoding { 6 | private static final char[] HEX_DIGITS = "0123456789abcdef".toCharArray(); 7 | 8 | private HexEncoding() { 9 | } 10 | 11 | public static String encode(byte[] data, int offset, int length) { 12 | StringBuilder result = new StringBuilder(length * 2); 13 | 14 | for(int i = 0; i < length; ++i) { 15 | byte b = data[offset + i]; 16 | result.append(HEX_DIGITS[b >>> 4 & 15]); 17 | result.append(HEX_DIGITS[b & 15]); 18 | } 19 | 20 | return result.toString(); 21 | } 22 | 23 | public static String encode(byte[] data) { 24 | return encode(data, 0, data.length); 25 | } 26 | 27 | public static String encodeRemaining(ByteBuffer data) { 28 | return encode(data.array(), data.arrayOffset() + data.position(), data.remaining()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/packer/Main.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.packer; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | class Main { 7 | private static final int a = 0x12345678; 8 | private static final int b = 0x78563412; 9 | public static void test(){ 10 | char ch = (char)a; 11 | if(0x12==ch){ 12 | System.out.println("小端!"); 13 | }else{ 14 | System.out.println("大端!"); 15 | } 16 | } 17 | 18 | public static void main(String[] args) throws IOException { 19 | Packer packer = new Packer(new File("src\\main\\assets\\dex")); 20 | packer.addFile("kl.dex", new File("Desktop\\xkp\\kl")); 21 | packer.saveToPath(); 22 | //packer.unpackFromFile(new File("Desktop\\xkp\\kl")); 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/packer/SafeString.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.packer; 2 | 3 | import com.google.common.io.LittleEndianDataInputStream; 4 | import com.google.common.io.LittleEndianDataOutputStream; 5 | 6 | import java.io.IOException; 7 | 8 | class SafeString { 9 | 10 | 11 | public SafeString(){ 12 | } 13 | 14 | public static void write(LittleEndianDataOutputStream stream, String s) throws IOException { 15 | byte bt[] = s.getBytes(); 16 | stream.writeInt(bt.length); 17 | stream.write(bt); 18 | } 19 | 20 | public static String read(LittleEndianDataInputStream stream) throws IOException { 21 | int len = stream.readInt(); 22 | byte[] buf = new byte[len]; 23 | int retLen = stream.read(buf, 0, len); 24 | if (retLen != len){ 25 | throw new IOException("File Length Not Enougth"); 26 | } 27 | return new String(buf); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/base/utils/SignUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.utils; 2 | 3 | import com.android.apksig.ApkVerifier; 4 | import com.facker.toolchain.utils.ApkSignerTool; 5 | 6 | import java.io.*; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | public class SignUtil { 11 | 12 | public static boolean sign(String apkPath,String ks,String alias,String ksPass,String keyPass) { 13 | try { 14 | List params = new ArrayList<>(); 15 | params.add("sign"); 16 | params.add("--ks"); 17 | params.add(ks); 18 | params.add("--ks-pass"); 19 | params.add("pass:"+ksPass); 20 | params.add("--ks-key-alias"); 21 | params.add(alias); 22 | params.add("--key-pass"); 23 | params.add("pass:"+keyPass); 24 | params.add("--out"); 25 | params.add(apkPath); 26 | params.add(apkPath); 27 | ApkSignerTool.main(params.toArray(new String[params.size()])); 28 | ApkVerifier verifier = new ApkVerifier.Builder(new File(apkPath)).build(); 29 | if(verifier.verify().isVerified()){ 30 | return true; 31 | } 32 | return false; 33 | }catch (Exception e){ 34 | e.printStackTrace(); 35 | } 36 | return false; 37 | } 38 | public static boolean sign(String apkPath,String ks,String alias,String ksPass,String keyPass,String outPath) throws Exception { 39 | List params = new ArrayList<>(); 40 | params.add("sign"); 41 | params.add("--ks"); 42 | params.add(ks); 43 | params.add("--ks-pass"); 44 | params.add("pass:"+ksPass); 45 | params.add("--ks-key-alias"); 46 | params.add(alias); 47 | params.add("--key-pass"); 48 | params.add("pass:"+keyPass); 49 | params.add("--out"); 50 | params.add(outPath); 51 | params.add(apkPath); 52 | ApkSignerTool.main(params.toArray(new String[params.size()])); 53 | ApkVerifier verifier = new ApkVerifier.Builder(new File(outPath)).build(); 54 | if(verifier.verify().isVerified()){ 55 | return true; 56 | } 57 | return false; 58 | } 59 | 60 | public static boolean install(String apkPath) { 61 | String command = "adb install "+apkPath; 62 | try { 63 | Process process = Runtime.getRuntime().exec(command); 64 | logOutCompileInfo(process.getErrorStream()); 65 | } catch (IOException e) { 66 | e.printStackTrace(); 67 | } 68 | return false; 69 | } 70 | 71 | private static boolean logOutCompileInfo(InputStream is) throws IOException { 72 | if (is == null) { 73 | return false; 74 | } 75 | boolean logOut = false; 76 | BufferedReader br = new BufferedReader(new InputStreamReader(is)); 77 | String line = null; 78 | while ((line = br.readLine()) != null) { 79 | System.out.print(line); 80 | logOut = true; 81 | } 82 | try { 83 | is.close(); 84 | } catch (Exception e) { 85 | e.printStackTrace(); 86 | } 87 | return logOut; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/network/NetworkProcesser.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.network; 2 | import org.dom4j.*; 3 | import org.dom4j.io.SAXReader; 4 | import org.dom4j.io.XMLWriter; 5 | 6 | import java.io.File; 7 | import java.io.FileOutputStream; 8 | import java.util.Iterator; 9 | 10 | public class NetworkProcesser { 11 | final static String networkConfig = "ianpei_network_security_config"; 12 | public static void rewriteNetworkConfig(File manifest) throws Exception{ 13 | if(manifest == null || !manifest.exists()){ 14 | throw new RuntimeException("Manifest File Not Found :NetworkProcesser"); 15 | } 16 | SAXReader reader = new SAXReader(); 17 | Document doc = reader.read(manifest); 18 | Element root = doc.getRootElement(); 19 | int targetSdkVersion = Integer.parseInt(root.attributeValue("platformBuildVersionCode", "0")); 20 | { 21 | Element applicationElement = null; 22 | for (Iterator it = root.elementIterator(); it.hasNext(); ) { 23 | Element e = it.next(); 24 | if ("application".equals(e.getName())){ 25 | applicationElement = e; 26 | for (Iterator a = e.attributeIterator(); a.hasNext(); ){ 27 | Attribute attribute = a.next(); 28 | if("networkSecurityConfig".equals(attribute.getName())){ 29 | System.out.println("networkSecurityConfig Exist!"); 30 | String value = attribute.getStringValue(); 31 | String xmlFilename = value.replace("@xml","")+".xml"; 32 | File xmlFile = new File(manifest.getParentFile(),"res/xml/"+xmlFilename); 33 | SAXReader xmlFileReader = new SAXReader(); 34 | Document xmlFileReaderDoc = reader.read(xmlFile); 35 | if("true".equals(xmlFileReaderDoc.getRootElement().element("base-config").attributeValue("cleartextTrafficPermitted"))){ 36 | return; 37 | } 38 | 39 | } 40 | } 41 | } 42 | } 43 | 44 | if(applicationElement != null){ 45 | Attribute isSelfAttr = applicationElement.attribute("networkSecurityConfig"); 46 | if(isSelfAttr!=null){ 47 | isSelfAttr.setValue(String.format("@xml/%s", networkConfig)); 48 | }else{ 49 | applicationElement.addAttribute("android:networkSecurityConfig", String.format("@xml/%s", networkConfig)); 50 | } 51 | XMLWriter xmlWriter = new XMLWriter(new FileOutputStream(manifest)); 52 | xmlWriter.write(doc); 53 | xmlWriter.close(); 54 | System.out.println("copy networkSecurityConfig ok"); 55 | } 56 | } 57 | } 58 | public static void main(String[] args) throws Exception { 59 | rewriteNetworkConfig(new File("G:\\out\\app-debug\\AndroidManifest.xml")); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/test/MSmaliBuilder.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.test; 2 | 3 | import brut.androlib.AndrolibException; 4 | import brut.androlib.mod.SmaliMod; 5 | import brut.androlib.src.SmaliBuilder; 6 | import brut.directory.DirectoryException; 7 | import brut.directory.ExtFile; 8 | import org.antlr.runtime.RecognitionException; 9 | import org.jf.dexlib2.Opcodes; 10 | import org.jf.dexlib2.writer.builder.DexBuilder; 11 | import org.jf.dexlib2.writer.io.FileDataStore; 12 | 13 | import java.io.File; 14 | import java.io.FileInputStream; 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.util.Iterator; 18 | import java.util.logging.Logger; 19 | 20 | public class MSmaliBuilder { 21 | private final ExtFile mSmaliDir; 22 | private final File mDexFile; 23 | private int mApiLevel = 0; 24 | private File javaSrc; 25 | private static final Logger LOGGER = Logger.getLogger(SmaliBuilder.class.getName()); 26 | 27 | public static void build(ExtFile smaliDir, File dexFile, int apiLevel, File javaSrc) throws AndrolibException { 28 | (new MSmaliBuilder(smaliDir, dexFile, apiLevel,javaSrc)).build(); 29 | } 30 | 31 | private MSmaliBuilder(ExtFile smaliDir, File dexFile, int apiLevel, File javaSrc) { 32 | this.mSmaliDir = smaliDir; 33 | this.mDexFile = dexFile; 34 | this.mApiLevel = apiLevel; 35 | this.javaSrc =javaSrc; 36 | } 37 | 38 | private void build() throws AndrolibException { 39 | try { 40 | DexBuilder dexBuilder; 41 | if (this.mApiLevel > 0) { 42 | dexBuilder = new DexBuilder(Opcodes.forApi(this.mApiLevel)); 43 | } else { 44 | dexBuilder = new DexBuilder(Opcodes.getDefault()); 45 | } 46 | 47 | Iterator var2 = this.mSmaliDir.getDirectory().getFiles(true).iterator(); 48 | 49 | while(var2.hasNext()) {//TODO 过滤 50 | String fileName = (String)var2.next(); 51 | //System.out.println(fileName); 52 | File fileJava = new File(javaSrc,fileName.replace(".smali",".java")); 53 | //System.out.println(fileJava.getAbsolutePath()); 54 | if(fileJava.exists()){ 55 | System.out.println(fileJava.getAbsolutePath()); 56 | continue; 57 | } 58 | this.buildFile(fileName, dexBuilder); 59 | } 60 | dexBuilder.writeTo(new FileDataStore(new File(this.mDexFile.getAbsolutePath()))); 61 | } catch (DirectoryException | IOException var4) { 62 | throw new AndrolibException(var4); 63 | } 64 | } 65 | 66 | private void buildFile(String fileName, DexBuilder dexBuilder) throws AndrolibException, IOException { 67 | File inFile = new File(this.mSmaliDir, fileName); 68 | InputStream inStream = new FileInputStream(inFile); 69 | if (fileName.endsWith(".smali")) { 70 | try { 71 | if (!SmaliMod.assembleSmaliFile(inFile, dexBuilder, this.mApiLevel, false, false)) { 72 | throw new AndrolibException("Could not smali file: " + fileName); 73 | } 74 | } catch (RecognitionException | IOException var6) { 75 | throw new AndrolibException(var6); 76 | } 77 | } else { 78 | LOGGER.warning("Unknown file type, ignoring: " + inFile); 79 | } 80 | inStream.close(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/test/SmaliTest.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.test; 2 | 3 | import brut.androlib.AndrolibException; 4 | import brut.androlib.meta.MetaInfo; 5 | import brut.directory.ExtFile; 6 | import com.facker.toolchain.test.MSmaliBuilder; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.io.FileNotFoundException; 11 | 12 | public class SmaliTest { 13 | 14 | public static void main(String[] args) { 15 | 16 | String rootPath = "C:\\Users\\Yang\\Desktop\\apk\\juan-juan-bing-qi-lin\\juan-juan-bing-qi-lin\\app\\src\\main\\smalis"; 17 | File smaliDirs[] = new File(rootPath).listFiles(); 18 | File apktoolYaml = new File("C:\\Users\\Yang\\Desktop\\apk\\juan-juan-bing-qi-lin\\juan-juan-bing-qi-lin\\app\\src\\main\\apktool.yml"); 19 | File javaSrc = new File("C:\\Users\\Yang\\Desktop\\apk\\juan-juan-bing-qi-lin\\juan-juan-bing-qi-lin\\app\\src\\main\\java"); 20 | MetaInfo metaInfo = null; 21 | try { 22 | metaInfo = MetaInfo.load(new FileInputStream(apktoolYaml)); 23 | } catch (FileNotFoundException e) { 24 | e.printStackTrace(); 25 | } 26 | for ( int i=0;i flags = new HashMap(); 54 | flags.put("forceBuildAll", Boolean.valueOf(true)); 55 | flags.put("debug", Boolean.valueOf(false)); 56 | flags.put("verbose", Boolean.valueOf(false)); 57 | flags.put("framework", Boolean.valueOf(false)); 58 | flags.put("update", Boolean.valueOf(false)); 59 | flags.put("copyOriginal", Boolean.valueOf(false)); 60 | try { 61 | instance.build(sourceDir, outPutApkPath); 62 | return true; 63 | } catch (BrutException e) { 64 | e.printStackTrace(); 65 | } 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/utils/FileReader.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.utils; 2 | 3 | import java.io.*; 4 | 5 | public class FileReader { 6 | public static String readFile(String filePath) throws IOException { 7 | StringBuffer sb = new StringBuffer(); 8 | FileReader.readToBuffer(sb, filePath); 9 | return sb.toString(); 10 | } 11 | public static void readToBuffer(StringBuffer buffer, String filePath) throws IOException { 12 | InputStream is = new FileInputStream(filePath); 13 | String line; // 用来保存每行读取的内容 14 | BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 15 | line = reader.readLine(); // 读取第一行 16 | while (line != null) { // 如果 line 为空说明读完了 17 | buffer.append(line); // 将读到的内容添加到 buffer 中 18 | buffer.append("\n"); // 添加换行符 19 | line = reader.readLine(); // 读取下一行 20 | } 21 | reader.close(); 22 | is.close(); 23 | } 24 | 25 | public static boolean delAllFile(String path) { 26 | boolean flag = false; 27 | File file = new File(path); 28 | if (!file.exists()) { 29 | return flag; 30 | } 31 | if (!file.isDirectory()) { 32 | return flag; 33 | } 34 | String[] tempList = file.list(); 35 | File temp = null; 36 | for (int i = 0; i < tempList.length; i++) { 37 | if (path.endsWith(File.separator)) { 38 | temp = new File(path + tempList[i]); 39 | } else { 40 | temp = new File(path + File.separator + tempList[i]); 41 | } 42 | if (temp.isFile()) { 43 | temp.delete(); 44 | } 45 | if (temp.isDirectory()) { 46 | delAllFile(path + "/" + tempList[i]);//先删除文件夹里面的文件 47 | delFolder(path + "/" + tempList[i]);//再删除空文件夹 48 | flag = true; 49 | } 50 | } 51 | return flag; 52 | } 53 | public static void delFolder(String folderPath) { 54 | try { 55 | delAllFile(folderPath); //删除完里面所有内容 56 | String filePath = folderPath; 57 | filePath = filePath.toString(); 58 | java.io.File myFilePath = new java.io.File(filePath); 59 | myFilePath.delete(); //删除空文件夹 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/utils/FileUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.utils; 2 | import java.io.*; 3 | import java.util.zip.CRC32; 4 | import java.util.zip.CheckedInputStream; 5 | 6 | public class FileUtil { 7 | 8 | public static void autoReplaceStr(File file, String oldstr, String newStr) throws IOException { 9 | Long fileLength = file.length(); 10 | byte[] fileContext = new byte[fileLength.intValue()]; 11 | FileInputStream in = null; 12 | PrintWriter out = null; 13 | in = new FileInputStream(file); 14 | in.read(fileContext); 15 | String str = new String(fileContext, "utf-8");//字节转换成字符 16 | str = str.replace(oldstr, newStr); 17 | out = new PrintWriter(file, "utf-8");//写入文件时的charset 18 | out.write(str); 19 | out.flush(); 20 | out.close(); 21 | in.close(); 22 | } 23 | /** 24 | * 循环删除目录 25 | * @param dir 26 | * @return 27 | */ 28 | public static boolean deleteDir(File dir) { 29 | if (dir.isDirectory()) { 30 | String[] children = dir.list(); 31 | for (int i=0; i>> 4 & 15]); 17 | result.append(HEX_DIGITS[b & 15]); 18 | } 19 | 20 | return result.toString(); 21 | } 22 | 23 | public static String encode(byte[] data) { 24 | return encode(data, 0, data.length); 25 | } 26 | 27 | public static String encodeRemaining(ByteBuffer data) { 28 | return encode(data.array(), data.arrayOffset() + data.position(), data.remaining()); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/utils/Logger.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.utils; 2 | 3 | public class Logger { 4 | public static void log(String tag,String log){ 5 | System.out.println(tag+":-------------"+log+"----------------"); 6 | } 7 | 8 | public static void log(String log){ 9 | System.out.println(log); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/utils/SignUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.utils; 2 | 3 | import com.android.apksig.ApkVerifier; 4 | 5 | import java.io.*; 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public class SignUtil { 10 | 11 | public static boolean sign(String apkPath,String ks,String alias,String ksPass,String keyPass) { 12 | try { 13 | List params = new ArrayList<>(); 14 | params.add("sign"); 15 | params.add("--ks"); 16 | params.add(ks); 17 | params.add("--ks-pass"); 18 | params.add("pass:"+ksPass); 19 | params.add("--ks-key-alias"); 20 | params.add(alias); 21 | params.add("--key-pass"); 22 | params.add("pass:"+keyPass); 23 | params.add("--out"); 24 | params.add(apkPath); 25 | params.add(apkPath); 26 | ApkSignerTool.main(params.toArray(new String[params.size()])); 27 | ApkVerifier verifier = new ApkVerifier.Builder(new File(apkPath)).build(); 28 | if(verifier.verify().isVerified()){ 29 | return true; 30 | } 31 | return false; 32 | }catch (Exception e){ 33 | e.printStackTrace(); 34 | } 35 | return false; 36 | } 37 | public static boolean sign(String apkPath,String ks,String alias,String ksPass,String keyPass,String outPath) throws Exception { 38 | List params = new ArrayList<>(); 39 | params.add("sign"); 40 | params.add("--ks"); 41 | params.add(ks); 42 | params.add("--ks-pass"); 43 | params.add("pass:"+ksPass); 44 | params.add("--ks-key-alias"); 45 | params.add(alias); 46 | params.add("--key-pass"); 47 | params.add("pass:"+keyPass); 48 | params.add("--out"); 49 | params.add(outPath); 50 | params.add(apkPath); 51 | ApkSignerTool.main(params.toArray(new String[params.size()])); 52 | ApkVerifier verifier = new ApkVerifier.Builder(new File(outPath)).build(); 53 | if(verifier.verify().isVerified()){ 54 | return true; 55 | } 56 | return false; 57 | } 58 | 59 | public static boolean install(String apkPath) { 60 | String command = "adb install "+apkPath; 61 | try { 62 | Process process = Runtime.getRuntime().exec(command); 63 | logOutCompileInfo(process.getErrorStream()); 64 | } catch (IOException e) { 65 | e.printStackTrace(); 66 | } 67 | return false; 68 | } 69 | 70 | private static boolean logOutCompileInfo(InputStream is) throws IOException { 71 | if (is == null) { 72 | return false; 73 | } 74 | boolean logOut = false; 75 | BufferedReader br = new BufferedReader(new InputStreamReader(is)); 76 | String line = null; 77 | while ((line = br.readLine()) != null) { 78 | System.out.print(line); 79 | logOut = true; 80 | } 81 | try { 82 | is.close(); 83 | } catch (Exception e) { 84 | e.printStackTrace(); 85 | } 86 | return logOut; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/utils/SystemUtils.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.utils; 2 | 3 | public class SystemUtils { 4 | 5 | public static boolean isWindows(){ 6 | return System.getProperty("os.name").toLowerCase().indexOf("windows") != -1; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/facker/toolchain/utils/TextUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.utils; 2 | 3 | public class TextUtil { 4 | public static boolean isEmpty(String text) { 5 | if (text != null && !"".equals(text)) { 6 | return false; 7 | } 8 | return true; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/FakerMain.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/FakerMain.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/FakerMain.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain; 2 | 3 | public class FakerMain { 4 | static String apkFilePath = "C:\\Users\\Yang\\Desktop\\apk\\juan-juan-bing-qi-lin\\卷卷冰淇淋.apk"; 5 | public static void main(String[] args) { 6 | FakerTransfer.translate(apkFilePath); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/beta/PathUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/beta/PathUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/beta/PathUtil.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.beta; 2 | 3 | import javax.swing.*; 4 | import java.io.File; 5 | import java.util.Scanner; 6 | 7 | public class PathUtil { 8 | @Deprecated 9 | public static String readPath(String desc) { 10 | return getString(desc); 11 | } 12 | 13 | private static String getString(String desc) { 14 | System.out.print(desc); 15 | Scanner scanner = new Scanner(System.in); 16 | String targetString = scanner.next(); 17 | scanner.close(); 18 | return targetString; 19 | } 20 | 21 | public static File inputFile(String desc, int mode, boolean isSave){ 22 | JFileChooser fd = new JFileChooser("\\"); 23 | fd.setFileSelectionMode(mode); 24 | int result = isSave ? fd.showSaveDialog(null): fd.showOpenDialog(null); 25 | if(JFileChooser.APPROVE_OPTION == result){ 26 | return fd.getSelectedFile(); 27 | }else { 28 | return inputFile(desc, mode, isSave); 29 | } 30 | } 31 | public static File inputFile(String desc){ 32 | return inputFile(desc, 0, false); 33 | } 34 | 35 | public static String getFileNameNoEx(String filePath) { 36 | String filename = getFileName(filePath); 37 | if ((filename != null) && (filename.length() > 0)) { 38 | int dot = filename.lastIndexOf('.'); 39 | if ((dot >-1) && (dot < (filename.length()))) { 40 | return filename.substring(0, dot); 41 | } 42 | } 43 | return filename; 44 | } 45 | 46 | private static String getFileName(String filePath) { 47 | File tempFile =new File(filePath.trim()); 48 | String fileName = tempFile.getName(); 49 | return fileName; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/beta/TestClassify.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/beta/TestClassify.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/ApkSignerTool$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/ApkSignerTool$1.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/ApkSignerTool$ParameterException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/ApkSignerTool$ParameterException.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/ApkSignerTool$ProviderInstallSpec.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/ApkSignerTool$ProviderInstallSpec.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/ApkSignerTool$SignerParams.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/ApkSignerTool$SignerParams.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/ApkSignerTool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/ApkSignerTool.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/Constant$PATH.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/Constant$PATH.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/Constant.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/Constant.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/Constant.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.mod; 2 | 3 | import java.io.File; 4 | 5 | public class Constant { 6 | 7 | 8 | public static class PATH { 9 | /** 10 | * ---------------------------工作空间跟路径---------------------------------------- 11 | */ 12 | 13 | 14 | public static final String ROOT_DIR = "D:\\crazy"; 15 | 16 | 17 | /** 18 | * ---------------------------配置文路径------------------------------------------- 19 | */ 20 | /** 21 | * 配置文件,文件夹路径 22 | */ 23 | public static final String CONFIG = ROOT_DIR + File.separator +"config"; 24 | 25 | /** 26 | * 签名文件路径 27 | */ 28 | public static final String CONFIG_INJECTOR_VAPP = CONFIG+ File.separator+ "vapp.jks"; 29 | 30 | /** 31 | * 源码文件夹路径 32 | */ 33 | public static final String SOURCE = ROOT_DIR + File.separator+"source"; 34 | 35 | 36 | public static final String SOURCE_PERFECT = SOURCE + File.separator+"perfect"; 37 | 38 | 39 | public static final String APK = ROOT_DIR + File.separator+"apk"; 40 | 41 | public static final String SOURCE_PERFECT_APK = APK + File.separator+"perfect"; 42 | 43 | 44 | 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/DealApk.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/DealApk.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/FuckApk.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/FuckApk.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/FuckApk.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.mod; 2 | 3 | 4 | import com.android.apksig.ApkVerifier; 5 | import com.facker.toolchain.base.utils.SignUtil; 6 | import com.facker.toolchain.api.xbase.ApkTool; 7 | 8 | import java.io.File; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | 13 | public class FuckApk { 14 | private static final String IN_DIR = "apk"; 15 | private static final String KEY_PATH = "vapp.jks"; 16 | public static void main(String[] args) throws Exception { 17 | fuckApk("Brain OutV1.3.12"); 18 | build("Brain OutV1.3.12"); 19 | } 20 | 21 | 22 | public static void fuckApk(String name){ 23 | ApkTool.decodeSrc(new File(IN_DIR,name+".apk"), new File(IN_DIR,name)); 24 | } 25 | 26 | public static void build(String name){ 27 | ApkTool.build(new File(IN_DIR,name), new File(IN_DIR,"re-"+name+".apk")); 28 | SignUtil.sign(KEY_PATH, "123", "cn",new File(IN_DIR,"re-"+name+".apk").getAbsolutePath(), "123"); 29 | } 30 | 31 | 32 | public boolean verifierApkOk(File file) { 33 | try { 34 | 35 | }catch (Exception e){ } 36 | return false; 37 | } 38 | 39 | public static boolean sign(String apkPath,String ks,String alias,String ksPass,String keyPass) throws Exception { 40 | try { 41 | List params = new ArrayList<>(); 42 | params.add("sign"); 43 | params.add("--ks"); 44 | params.add(ks); 45 | params.add("--ks-pass"); 46 | params.add("pass:"+ksPass); 47 | params.add("--ks-key-alias"); 48 | params.add(alias); 49 | params.add("--key-pass"); 50 | params.add("pass:"+keyPass); 51 | params.add("--out"); 52 | params.add(apkPath); 53 | params.add(apkPath); 54 | ApkSignerTool.main(params.toArray(new String[params.size()])); 55 | ApkVerifier verifier = new ApkVerifier.Builder(new File(apkPath)).build(); 56 | if(verifier.verify().isVerified()){ 57 | return true; 58 | } 59 | return false; 60 | }catch (Exception e){ 61 | e.printStackTrace(); 62 | } 63 | return false; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/HexEncoding.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/HexEncoding.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/OptionsParser$OptionsException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/OptionsParser$OptionsException.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/OptionsParser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/OptionsParser.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/PasswordRetriever.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/PasswordRetriever.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/mod/StaticInjector.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/mod/StaticInjector.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/packer/Main.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/packer/Main.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/packer/Main.java: -------------------------------------------------------------------------------- 1 | package com.facker.toolchain.base.packer; 2 | 3 | import java.io.File; 4 | import java.io.IOException; 5 | 6 | class Main { 7 | private static final int a = 0x12345678; 8 | private static final int b = 0x78563412; 9 | public static void test(){ 10 | char ch = (char)a; 11 | if(0x12==ch){ 12 | System.out.println("小端!"); 13 | }else{ 14 | System.out.println("大端!"); 15 | } 16 | } 17 | 18 | public static void main(String[] args) throws IOException { 19 | Packer packer = new Packer(new File("src\\main\\assets\\dex")); 20 | packer.addFile("kl.dex", new File("Desktop\\xkp\\kl")); 21 | packer.saveToPath(); 22 | //packer.unpackFromFile(new File("Desktop\\xkp\\kl")); 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/packer/Packer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/packer/Packer.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/packer/SafeString.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/packer/SafeString.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/utils/IOUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/utils/IOUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/utils/SignUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/utils/SignUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/base/utils/ZipUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/base/utils/ZipUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/test/MSmaliBuilder.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/test/MSmaliBuilder.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/test/SmaliTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/test/SmaliTest.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/test/SplitApksMerge.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/test/SplitApksMerge.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/AaptApk.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/AaptApk.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkSignerTool$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkSignerTool$1.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkSignerTool$ParameterException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkSignerTool$ParameterException.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkSignerTool$ProviderInstallSpec.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkSignerTool$ProviderInstallSpec.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkSignerTool$SignerParams.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkSignerTool$SignerParams.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkSignerTool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkSignerTool.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkTool.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkTool.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkUtils$FileInfo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkUtils$FileInfo.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ApkUtils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ApkUtils.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/FileReader.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/FileReader.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/FileUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/FileUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/HexEncoding.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/HexEncoding.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/IOUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/IOUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/Logger.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/Logger.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ManifestEditor.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ManifestEditor.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/OptionsParser$OptionsException.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/OptionsParser$OptionsException.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/OptionsParser.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/OptionsParser.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/PasswordRetriever.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/PasswordRetriever.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/SignUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/SignUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/SystemUtils.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/SystemUtils.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/TextUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/TextUtil.class -------------------------------------------------------------------------------- /target/classes/com/facker/toolchain/utils/ZipUtil.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nisemoe/FakerAndroid/ff0a2d60f0190158ce091652488b75a6732e5732/target/classes/com/facker/toolchain/utils/ZipUtil.class --------------------------------------------------------------------------------