Skip to content

Commit

Permalink
一个Native级的Android应用防篡改库
Browse files Browse the repository at this point in the history
  • Loading branch information
like2 authored and like2 committed Jan 26, 2022
1 parent dc60f7a commit 1127695
Show file tree
Hide file tree
Showing 58 changed files with 2,773 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 16 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added EZAndroid.keystore
Binary file not shown.
71 changes: 70 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,70 @@
# EZProtect
# EZProtect

一个Native级的Android应用防篡改库

去年在开发一个个人项目的过程中,发现自己的应用被人破解修改,并且被二次打包放到了网上,因此对应用安全防护进行了一点研究。

虽然市场上大部分App已经进行了代码混淆、签名校验和Dex加固,但是现在的破解工具太方便了。诸如脱壳、去签名、重打包等功能,手机安装MT管理器或者NP管理器后都可以一条龙完成,因此需要继续增加破解难度。

国内开发者用的最多的防篡改库可能是 https://github.com/lamster2018/EasyProtector ,该库集成了不少检测方法,但是他的重大缺点就是校验方法放在Java层,使用Xposed等框架可以轻易过掉检测,因此实现了一个Native级的Android应用防篡改库。

### 防护能力

1.防动态调试

2.防逆向分析

3.防恶意注入

4.防二次打包

5.防数据窃取

### 检测功能

#### 1.检测是否被动态调试

有经验的破解者通常会通过IDA等工具来动态调试So,以过掉So库中的检测功能,因此首先需要对动态调试进行拦截,通常采用

1.通过ptrace自添加防止被调试器挂载来反调试

2.通过系统提供的Debug.isDebuggerConnected()方法来进行判断

#### 2.检测APK的签名

非常基础的检测手段,因为容易被一键破解,因此需要配合其他手段防御

#### 3.检测APK的包名

判断opendir("/data/data/CORRECT_PACKAGE_NAME")是否等于nullptr,如果没有指定私有目录的访问权限,说明不是正确的包名

#### 4.检测是否被Xposed等框架注入

检测"/proc/self/maps"目录下的文件,如果出现包含xposed、substrate、frida等名称的文件,说明有框架正在注入

#### 5.检测PMS是否被Hook

通过检测PMS是否继承Proxy类可以知道是否已被Hook

#### 6.检测Application的className属性

大部分工具都会通过修改入口Application类,并在修改后的Application类中添加各种破解代码来实现去签名校验,它们常常费了很大的劲比如Hook了PMS,同时为了防止你读取原包做文件完整性校验可能还进行了IO重定向,但偏偏忽视了对Application类名的隐藏,经测试该检测可以防御大部分工具的一键破解

#### 7.检测Application的allowBackup属性

正常情况下应该为false,如果检测到为true,说明应用被Hook了,破解者正在尝试导出应用私有信息

#### 8.检测应用版本号

破解者为了防止应用更新导致破解失效,通常会修改此versionCode,因此需要进行检测

#### 9.检测Native与Java层获取到的APK的文件路径或者大小

因为pm命令获取到的APK文件路径通常不容易被修改,这里与通过JavaApi获取到的APK文件路径做比较,如果文件路径或者文件大小不一致时,大概率是应用被IO重定向了,或者使用了VirtualXposed等分身软件

#### 10.Apk和So文件完整性校验

可以获取到当前APK文件和此加密So包的文件信息用于服务器校验

注意,编译时需要使用Ollvm混淆,配置可以参考文章
https://blog.csdn.net/u013314647/article/details/117740784?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242
1 change: 1 addition & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
44 changes: 44 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}

android {
compileSdk 31

defaultConfig {
applicationId project.applicationId
minSdk 16
targetSdk 31
versionCode project.versionCode as int
versionName project.versionName

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}

dependencies {

api project(':app:ezprotect')
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
1 change: 1 addition & 0 deletions app/ezprotect/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
67 changes: 67 additions & 0 deletions app/ezprotect/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# 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_minimum_required(VERSION 3.18.1)

#-mllvm -fla 控制流扁平化
#-mllvm -sub 指令替换
#-mllvm -bcf 虚假控制流程
#-mllvm -sobf 字符串加密
set(CMAKE_CXX_FLAGS "-mllvm -fla -mllvm -sub -mllvm -sobf ${CMAKE_CXX_FLAGS}")

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

file(GLOB native_src
"src/main/cpp/util/*.cpp"
"src/main/cpp/protect/*.cpp"
)
add_library( # Sets the name of the library.
ezcore

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
${native_src})

# 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.

target_link_libraries( # Specifies the target library.
ezcore

# Links the target library to the log library
# included in the NDK.
${log-lib})

add_definitions("-fvisibility=hidden")

# APK签名MD5值
add_definitions(-DCORRECT_APK_SIGN="${CORRECT_APK_SIGN}")
# APK包名
add_definitions(-DCORRECT_PACKAGE_NAME="${CORRECT_PACKAGE_NAME}")
# Application名
add_definitions(-DCORRECT_APPLICATION_NAME="${CORRECT_APPLICATION_NAME}")
# 加固后的Application名 【可选】比如360免费加固后的Application名为com.stub.StubApp
add_definitions(-DCORRECT_APPLICATION_NAME_REINFORCE="")
# 版本号,破解者为了防止应用更新导致破解失效,通常会修改此versionCode,因此进行检测
add_definitions(-DCORRECT_VERSION_CODE=${CORRECT_VERSION_CODE})
49 changes: 49 additions & 0 deletions app/ezprotect/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}

android {
compileSdk 31

defaultConfig {
minSdk 16
targetSdk 31

consumerProguardFiles "consumer-rules.pro"
externalNativeBuild {
cmake {
arguments "-DANDROID_STL=c++_static",
"-DCORRECT_VERSION_CODE=" + project.versionCode,
"-DCORRECT_APPLICATION_NAME=" + "cn.ezandroid.ezprotect.MyApplication",
"-DCORRECT_PACKAGE_NAME=" + project.applicationId,
"-DCORRECT_APK_SIGN=" + "0f65981c4d8c44aaea1d9e232fbde4b1"
}
}
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
version "3.18.1"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}

ndkVersion "21.1.6352462"
}

dependencies {
}
Empty file.
21 changes: 21 additions & 0 deletions app/ezprotect/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
2 changes: 2 additions & 0 deletions app/ezprotect/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="cn.ezandroid.ezprotect.lib" />
Loading

0 comments on commit 1127695

Please sign in to comment.