接到需求说我们APP的加密被破解了,需要更换私钥的存储方式。我说反编译可以直接看到源码,不可能完全阻止他们破解,只能说增加复杂度,建议使用付费版加壳。产品说那就加一下复杂度吧,好家伙,是时候掏出大学里学的C++了,虽然完全没印象。
下面是一些实战细节,全靠CV大法。
环境
- Android Studio 4.1.3
- Gradle 4.1.3
- Cmake 3.10.2
- ndk 21.1.6352462
- buildToolsVersion 30.0.3
- 配置
app/build.gradle
// app/build.gradle
defaultConfig {
...
//设置NDK版本(生成动态so库的时候要用)
ndkVersion "21.1.6352462"
// gradle 执行的任务名字
externalNativeBuild {
cmake {
cppFlags ""
// 过滤生成的库类型
// abiFilters 'armeabi-v7a'
// 库格式'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
}
}
}
//生成指定版本的 CMakeLists.txt 文件
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
- 创建cpp/xx
- CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
#设置CMake的最低版本
cmake_minimum_required(VERSION 3.10.2)
#这些 privateKey.cpp资源打包设置成一个名为bugly 的共享库(SHARED 替换为STATIC则设置为静态库)
# privateKey.cpp
add_library( # Sets the name of the library.
bugly
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
privateKey.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
#(设置要链接的库文件的名称 bugly)
target_link_libraries( # Specifies the target library.
bugly
# Links the target library to the log library
# included in the NDK.
${log-lib} )
- privateKey.cpp
注意方法名必须和java中的路径对应
#include <jni.h>
#include <string>
extern "C"
JNIEXPORT jstring JNICALL Java_com_jed_frame_utils_MyJniUtil_keyFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string token = "Hello Jed, love you o!!";
return env->NewStringUTF(token.c_str());
}
- 调用
String content = MyJniUtil.keyFromJNI();
Log.d(TAG, "onClick: " + content);
这个时候已经可以运行了,现在我们要把c++代码生成so库
- 更新gradle方法
- 运行生成so库的方法
- 把so库拷贝到项目中
在app/src/main文件夹下新建jniLibs文件夹,将我们的So库复制到jniLibs文件夹中
(注意:Android Studio只能识别jniLibs文件夹中So库,如果需要改变So库的识别路径,可以在app/build.gradle中指定jniLibs.srcDir)
sourceSets.main {
jniLibs.srcDir 'src/main/jni_libs'
}
- 删除so库以外的东西,build.gradle中的配置,cpp文件等等