├── .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 |
4 |
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 extends ZipEntry> 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
--------------------------------------------------------------------------------