将360加固宝安装程序下载之后,解压,然后通过winodws 的dos命令来调用360加固程序,完成登录,设置,加固应用的操作。
优点:可以使用程序控制加固工作,将生成的release包在java工程中进行加固,签名,生成多渠道包等工作,不再使用客户端手动加固应用,防止出错,方便快捷。而且可以将我们创建的一个Release包在java工程中完成一系列操作,直致生成多渠道包。可谓是一键完成线上多个渠道包的创建,不再依赖手动选择加固,签名等,大大节约了我们的时间。
360加固宝官网: http://jiagu.360.cn/#/global/index
解压后是一个360jiagubao_windows_64文件夹,进入jiagu文件夹如下图。请注意下面两个红框的文件。help.txt和jiagu.jar
help.txt文件内容如下
-login
-importsign
-importmulpkg
-showsign 查看已配置的签名信息
-showmulpkg 查看已配置的多渠道信息
-help 显示帮助信息
-config 配置加固可选项
----------------------可选增强服务-------------------------------
[-crashlog] 【崩溃日志分析】
[-x86] 【x86支持】
[-analyse] 【加固数据分析】
[-nocert] 【跳过签名校验】
----------------------高级加固选项-------------------------------
[-vmp] 【全VMP保护】
[-data] 【本地数据文件保护】
[-assets] 【资源文件保护】
[-filecheck] 【文件完整性校验】
[-ptrace] 【Ptrace防注入】
[-so] 【SO文件保护】
[-dex2c] 【dex2C保护】
[-string_obfus] 【字符串加密】
[-dex_shadow] 【DexShadow】
[-so_private] 【SO防盗用】
-----------------------------------------------------------------
-config_so 配置需要加固的SO文件,以空格分隔
-config_assets 配置需要忽略的资源文件,以空格分隔
-config_so_private 配置防盗用的SO文件,以空格分隔
-showconfig 显示已配置加固项
-version 显示当前版本号
-update 升级到最新版本
-jiagu
[-autosign] 【自动签名】
[-automulpkg] 【自动多渠道】
[-pkgparam mulpkg_filepath] 【自定义文件生成多渠道】
登录成功会返回 login success字符串。
登录成功后可设置360加固宝。设置一次后,可不再修改,设置保存至本地的。也可以登录客户端手动设置,都是一样的。、
个人建议不使用它的“启用自动签名”和 使用“跳过签名校验”功能。
执行加固命令: java -jar jiagu.jar -jiagu input\input.apk output
java -jar jiagu.jar -jiagu 要加固的apk文件路径 输出apk路径
注:我使用的是相对路径, 也可以使用绝对路径。
输出的文件名规则为 源文件名 + “_版本号_” + "jiagu.apk" .如上加固输出文件为 input_6130_jiagu.apk , 其源文件为input.apk
使用程序进行加固。
加固先开始上传(上传至360加固服务器那边,应该是这样的)
上传完成开始加固
加固完成。即加固程序运行结束
脚本工具下载地址:https://download.csdn.net/download/liuyu0915/11197032
脚本加固apk工具,可以通过该工具批量加固apk, 并支持加固api,加固apk不再需要手动操作加固客户端。内部封装的是360加固宝工具。该工具可以与签名、生成渠道包工具组合起来,达到一键生成线上渠道包的功能(studio生成release包,使用该工具加固,再调用程序进行签名,最后通过创建渠道包工具生成对应的渠道包,整个流程不需要手动操作,使用简单稳定。)。
准备工作:在360加固宝官网上下载360加固宝程序并解压,找到jiagu.jar文件,并记录它的路径。360加固宝下载地址
命令行方式: java -jar 360jiagu.jar kaixin -login 360加固宝用户名 360加固宝登录密码 -input input.apk -output 输出apk路径 -jiaguJar 360加固宝中jiagu.jar的路径
示例:java -jar 360jiagu.jar kaixin -login 153****8060 mima -input C:\Users\ttkx\Desktop\input.apk -output f:\ouput -jiaguJar D:\github_\AutoCreateApk\jiagu\jiagu.jar
API调用方式: 直接调用360jiagu.jar中的api .
调用方法: JiaGuMain.runJiaGu(JiaGuConfig config). JiaGuConfig类中设置登录用户名和密码,输入apk和加固完成后输出路径,还需要传360加宝程序解压后jiagu.jar的路径。
JiaGuConfig config = JiaGuConfig.build()
.setJarFile(new File("....\jiagu.jar"))
.login("用户名****", "密码****")
.addInputApkPath(getInputApkPath("htg_input.apk"))
.addInputApkPath(getInputApkPath("app-anzhi_oas-debug.apk"))
.outputPath(mOutputPath);
JiaGuMain.runJiaGu(config);
备注:该工具没有设置360加固宝相关设置的功能,如果需要修改加固宝默认设置,可以打开客户端手动设置后关闭再使用该工具进行加固,设置一次之后就不用再设置了。建议大家不使用360加固宝的自动签名和签名校验功能。
目的: 用程序调用加固apk, 与后续签名和生成多渠道包功能连贯至一起。实现一键生成多渠道线上包的功能。
创建java工程, 然后使用java api执行windows 的dos命令,调用360加固宝程序 。最终实现加固apk.
步骤一 : 创建java工程 或是java lib 工程。
步骤二: 将360加固宝解压文件入至工程中(方便管理)。
我的目录结构如下:
步骤三: 使用java api 调用dos命令,执行加固程序
3.1 设置登录用户名和密码 , 输入文件路径 和 输出文件夹路径
3.4 检查是否登录完成 。
检查返回的字符串是否包含login success 字符串即可。
3.5检查加固是否完成
检查返回字符串是否包含 “已加固”。
备注: dos命令在程序中执行是在当前线程,当加固程序完成之后才会走下一行代码。所以当加固程序走完的时候,就能够在输出文件夹内找到对应的已加固apk文件。本人dos命令玩的太差,上面检查360加固登录和加固状态的代码写的稀烂,对返回的字符串处理很low,欢迎大神指点。
上述三的思想是创建java工程,然后调用360加固宝工具进行加固。我对其进行了二次封装。
package com.kaixin.jiagu360;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class JiaGuMain {
public static final String JAR_NAME = "jiagu.jar";
public JiaGuMain() {
}
public static void main(String[] args) {
String cmd = args[0];
String[] params = (String[])Arrays.copyOfRange(args, 1, args.length);
try {
if ("kaixin".equals(cmd)) {
disposeArgs(params);
} else {
System.err.println("请输入kaixin,不要问为什么,因为这是我写的。。。哈哈");
}
} catch (Exception var4) {
System.err.println("Error: " + var4.getMessage());
}
}
//处理输入参数
private static void disposeArgs(String[] params) {
if (params.length == 0) {
error("未发现有效参数");
} else {
JiaGuConfig config = JiaGuConfig.build();
Options options = new Options(params);
Map> paramMap = options.builder();
List loginList = (List)paramMap.get("-login");
if (loginList != null && loginList.size() == 2) {
String userName = (String)loginList.get(0);
String password = (String)loginList.get(1);
config.login(userName, password);
} else {
error("登录参数未发现或不合法");
}
List inputApkList = (List)paramMap.get("-input");
String inputApkPath;
if (inputApkList != null && inputApkList.size() > 0) {
Iterator var11 = inputApkList.iterator();
label55:
while(true) {
while(true) {
if (!var11.hasNext()) {
break label55;
}
inputApkPath = (String)var11.next();
File file = new File(inputApkPath);
if (file.exists() && file.isFile() && file.getName().endsWith(".apk")) {
config.addInputApkPath(inputApkPath);
} else {
error("输入待加固apk路径不合法: " + inputApkPath);
}
}
}
} else {
error("未发现有效的待加固apk");
}
List outputDirList = (List)paramMap.get("-output");
if (outputDirList != null && outputDirList.size() > 0) {
inputApkPath = (String)outputDirList.get(0);
config.outputPath(inputApkPath);
} else {
error("未发现输出apk路径");
}
List jarList = (List)paramMap.get("-jiaguJar");
if (jarList != null && jarList.size() > 0) {
String jarPath = (String)jarList.get(0);
File file = new File(jarPath);
if (file.exists() && file.isFile() && "jiagu.jar".equals(file.getName())) {
config.setJarFile(file);
}
}
checkJiaguJar(config);
runJiaGu(config);
}
}
private static void checkJiaguJar(JiaGuConfig config) {
File jarFile = config.getJarFile();
if (jarFile == null || !jarFile.exists()) {
jarFile = FileHelper.searchFile(new File((new File("")).getAbsolutePath()), "jiagu.jar");
config.setJarFile(jarFile);
}
if (jarFile == null || !jarFile.exists() || !jarFile.isFile() || !"jiagu.jar".equals(jarFile.getName())) {
error("未发现加固工具jiagu.jar");
}
}
private static void error(String content) {
if (content != null) {
System.err.println(content);
}
}
public static BufferedReader runCmd(String command) {
Runtime runtime = Runtime.getRuntime();
try {
File jarFile = JiaGuConfig.build().getJarFile();
if (jarFile != null && jarFile.isFile()) {
Process process = runtime.exec(command, (String[])null, jarFile.getParentFile());
return new BufferedReader(new InputStreamReader(process.getInputStream(), Charset.forName("GBK")));
} else {
error("未发现jiagu.jar文件");
return null;
}
} catch (IOException var4) {
var4.printStackTrace();
return new BufferedReader(new StringReader(var4.getMessage()));
}
}
public static boolean runJiaGu(JiaGuConfig config) {
if (config != null && config.getInputApkPath().size() > 0) {
checkJiaguJar(config);//检查360加固工具是否存在,如果不存在,在当前项目目录下搜索
boolean login_success = login360JiaGu(config);
if (login_success) {
System.out.print("加固中。。。。\n");
FileHelper.createNewDir(JiaGuConfig.getConfig().getOutputPath());
List inputApkPathList = config.getInputApkPath();
Iterator var3 = inputApkPathList.iterator();
while(var3.hasNext()) {
String inputApkPath = (String)var3.next();
jiaGuOneApk(inputApkPath, config.getOutputPath());
System.out.print("360加固完成输出路径:" + config.getOutputPath());
}
return true;
}
error("360加固宝登录不成功");
}
return false;
}
public static boolean jiaGuOneApk(String inputApkPath, String outputPath) {
String jarUtils = "java -jar jiagu.jar";
String command2 = jarUtils + " -jiagu " + inputApkPath + " " + outputPath;
BufferedReader bf = runCmd(command2);
String bf2Str = getBF2Str(bf);
System.out.print(bf2Str);
return true;
}
public static boolean login360JiaGu(JiaGuConfig config) {
String jarUtils = "java -jar jiagu.jar";
String command1 = jarUtils + " -login " + config.getUserName() + " " + config.getPassword();
BufferedReader bufferedReader = runCmd(command1);
boolean login_success = checkResultInfo(bufferedReader, "login success");
return login_success;
}
public static String getBF2Str(BufferedReader bf) {
if (bf != null) {
String line = null;
StringBuilder sb = new StringBuilder();
try {
while((line = bf.readLine()) != null) {
sb.append(line + "\n");
}
return sb.toString();
} catch (Exception var4) {
var4.getMessage();
}
}
return "";
}
public static boolean checkResultInfo(BufferedReader bufferedReader, String tag) {
if (bufferedReader != null) {
String line = null;
StringBuilder sb = new StringBuilder();
try {
while((line = bufferedReader.readLine()) != null) {
sb.append(line + "\n");
if (line.contains(tag)) {
System.out.println(line + "\n");
return true;
}
}
} catch (Exception var5) {
;
}
}
return false;
}
}
package com.kaixin.jiagu360;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Options {
private final String[] mParams;
public Options(String[] params) {
this.mParams = (String[])params.clone();
}
public Map> builder() {
Map> map = new HashMap();
if (this.mParams != null) {
int length = this.mParams.length;
List list = null;
for(int i = 0; i < length; ++i) {
String param = this.mParams[i];
if (param != null && param.length() > 0) {
if (param.startsWith("-")) {
list = this.getList(map, param);
} else if (list != null) {
list.add(param);
}
}
}
}
return map;
}
private List getList(Map> map, String key) {
if (map.get(key) == null) {
map.put(key, new ArrayList());
}
return (List)map.get(key);
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.kaixin.jiagu360;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class JiaGuConfig {
private static JiaGuConfig mConfig;
private List mInputApkPathList = new ArrayList();
private String mOutputPath;
private String mUserName;
private String mPassword;
private File mJarFile;
public static synchronized JiaGuConfig build() {
if (mConfig == null) {
mConfig = new JiaGuConfig();
}
return mConfig;
}
private JiaGuConfig() {
}
public JiaGuConfig addInputApkPath(String inputApkPath) {
this.mInputApkPathList.add(inputApkPath);
return this;
}
public JiaGuConfig outputPath(String outputPath) {
this.mOutputPath = outputPath;
return this;
}
public JiaGuConfig login(String userName, String password) {
this.mUserName = userName;
this.mPassword = password;
return this;
}
public static JiaGuConfig getConfig() {
return mConfig;
}
public List getInputApkPath() {
return this.mInputApkPathList;
}
public String getOutputPath() {
return this.mOutputPath;
}
public String getUserName() {
return this.mUserName;
}
public String getPassword() {
return this.mPassword;
}
public File getJarFile() {
return this.mJarFile;
}
public JiaGuConfig setJarFile(File mJarFile) {
this.mJarFile = mJarFile;
return this;
}
public JiaGuConfig setInputApkPathList(List inputApkPathList) {
this.mInputApkPathList = inputApkPathList;
return this;
}
}
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.kaixin.jiagu360;
import java.io.File;
public class FileHelper {
public FileHelper() {
}
public static void deleteAllFiles(File root) {
if (root != null) {
File[] files = root.listFiles();
if (files != null) {
File[] var2 = files;
int var3 = files.length;
for(int var4 = 0; var4 < var3; ++var4) {
File f = var2[var4];
if (f.isDirectory()) {
deleteAllFiles(f);
try {
f.delete();
} catch (Exception var8) {
;
}
} else if (f.exists()) {
deleteAllFiles(f);
try {
f.delete();
} catch (Exception var7) {
;
}
}
}
}
root.delete();
}
}
public static void deleteAllSonFiles(File root) {
if (root != null) {
File[] files = root.listFiles();
if (files != null) {
File[] var2 = files;
int var3 = files.length;
for(int var4 = 0; var4 < var3; ++var4) {
File f = var2[var4];
if (f.isDirectory()) {
deleteAllFiles(f);
try {
f.delete();
} catch (Exception var8) {
;
}
} else if (f.exists()) {
deleteAllFiles(f);
try {
f.delete();
} catch (Exception var7) {
;
}
}
}
}
}
}
public static boolean createNewDir(String dirPath) {
return dirPath != null && dirPath.length() > 0 ? createNewDir(new File(dirPath)) : false;
}
public static boolean createNewDir(File file) {
if (file != null) {
if (file.exists()) {
deleteAllFiles(file);
return file.mkdirs();
} else {
return file.mkdirs();
}
} else {
return false;
}
}
public static File searchFile(File file, String fileName) {
if (file != null && file.exists() && fileName != null && fileName.length() > 0) {
if (file.isFile() && fileName.equals(file.getName())) {
return file;
}
if (file.isDirectory()) {
File[] var2 = file.listFiles();
int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) {
File sonFile = var2[var4];
String absolutePath1 = sonFile.getAbsolutePath();
if (sonFile.isFile()) {
if (fileName.equals(sonFile.getName())) {
return sonFile;
}
} else if (sonFile.isDirectory()) {
File resultFile = searchFile(sonFile, fileName);
if (resultFile != null && resultFile.isFile() && fileName.equals(resultFile.getName())) {
return resultFile;
}
}
}
}
}
return null;
}
}