Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev libsodium #40

Merged
merged 21 commits into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.so filter=lfs diff=lfs merge=lfs -text
*.a filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,22 @@ captures/

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx
#remote build
mainframer.sh
.mainframer

#some files that is generated from building libsodium need to be add gitignore.
aesjni/src/main/libs/
aesjni/src/main/obj/
aesjni/src/main/jni/Android.mk
aesjni/src/main/jni/sodium_include
aesjni/src/main/jni/temp


# VSCODE
.vscode


# VSCODE
.vscode
64 changes: 64 additions & 0 deletions FigureOutJNICrash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
How to locate where native crash at?
------------
1.ensure you ndk is set into environment.

2.run **ndk-stack** to analyze logcat and **symbol file** to find where crash printed.
```
//gradlew build with ndkBuild:
adb logcat | ndk-stack -sym ./aesjni/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/
//gradlew build with CMake:
adb logcat | ndk-stack -sym ./aesjni/build/intermediates/cmake/debug/obj/arm64-v8a
//if you run ndk-build command:
adb logcat | ndk-stack -sym ./aesjni/src/main/obj/local/x86/
```
> **../obj/local/x86/** and **../obj/local/armeabi-v7a/** is symbol file directory.

### Example:

I got crash logs:

```logs
$ ./test_in_executing.sh
2021-02-24 17:03:48.242 12059-12059/? A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0 in tid 12059 (test), pid 12059 (test)
2021-02-24 17:03:48.251 12063-12063/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
2021-02-24 17:03:48.251 12063-12063/? A/DEBUG: Build fingerprint: 'google/sdk_gphone_x86_arm/generic_x86_arm:11/RSR1.201013.001/6903271:userdebug/dev-keys'
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: Revision: '0'
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: ABI: 'x86'
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: Timestamp: 2021-02-24 17:03:48+0800
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: pid: 12059, tid: 12059, name: test >>> /data/local/tmp/test <<<
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: uid: 2000
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: Cause: null pointer dereference
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: eax 00000000 ebx 60915ef0 ecx f482efe0 edx f482efe0
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: edi fff9e924 esi 608f0c20
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: ebp fff9e848 esp fff9e78c eip 60857ef3
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: backtrace:
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: NOTE: Function names and BuildId information is missing for some frames due
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: NOTE: to unreadable libraries. For unwinds of apps, only shared libraries
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: NOTE: found under the lib/ directory are readable.
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: NOTE: On this device, run setenforce 0 to make the libraries readable.
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: #00 pc 0000bef3 /data/local/tmp/test
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: #01 pc 0000532e /data/local/tmp/test
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: #02 pc 000058f7 /data/local/tmp/test
2021-02-24 17:03:48.252 12063-12063/? A/DEBUG: #03 pc 000522e3 /apex/com.android.runtime/lib/bionic/libc.so (__libc_init+115) (BuildId: 6e3a0180fa6637b68c0d181c343e6806)
```

I run ndk-stack:
```log
$ adb logcat | ndk-stack -sym ./aesjni/src/main/obj/local/x86
********** Crash dump: **********
Build fingerprint: 'google/sdk_gphone_x86_arm/generic_x86_arm:11/RSR1.201013.001/6903271:userdebug/dev-keys'
pid: 12059, tid: 12059, name: test >>> /data/local/tmp/test <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
Stack frame #00 pc 0000bef3 /data/local/tmp/test: Routine crypto_aead_aes256gcm_beforenm at ??:?
Stack frame #01 pc 0000532e /data/local/tmp/test: Routine test_aead_aes256gcm at ~/Documents/git/AESJniEncrypt/aesjni/src/main/jni/main_unit_test.c:48
Stack frame #02 pc 000058f7 /data/local/tmp/test: Routine main at ~/Documents/git/AESJniEncrypt/aesjni/src/main/jni/main_unit_test.c:142
Stack frame #03 pc 000522e3 /apex/com.android.runtime/lib/bionic/libc.so (__libc_init+115) (BuildId: 6e3a0180fa6637b68c0d181c343e6806)
```

`at ~/Documents/git/AESJniEncrypt/aesjni/src/main/jni/main_unit_test.c:48` show me that
executable file crash at `line 48 from main_unit_test.c`.


51 changes: 34 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,41 @@
[中文](https://github.com/BruceWind/AESJniEncrypt/blob/master/README_zh.md)


# Reach high security in Android
- [x] Add AES algorithms to native code
# Reach high security with libsodium in Android
- [x] I have no longer supported ~~AES algorithms~~. If you still need it, check out tag: [v2.2](https://github.com/BruceWind/AESJniEncrypt/releases/tag/v2.2).
- [x] Use chacha20 instead of AES. TLS1.3 has been used **CHACHA20** on mobile device too.It is high-performance for ARM architecture.
- [x] Hide native function in JniOnload
- [x] Use signature verification to avoid being packaged again (It is prevents that hacker call your jni method directly.)
- [x] ~~key exists in the symbol table, and hides the character table~~ This scheme has been deprecated, [discard reason issues5](https://github.com/weizongwei5/AESJniEncrypt/issues/5), please see the next
- [x] ~~key exists in the symbol table, and hides the character table~~. This method has been deprecated due to [discard reason issues5](https://github.com/weizongwei5/AESJniEncrypt/issues/5)
- [x] Get the key from a complex function, to hide the key, current function is a simple solution. (Complex solution: divide the Key into several pieces, store them in different C files, and finally splicing them together. This function should be complicated to write and increase the decompiling difficulty.)

- [x] Use "obfuscator" to confuse C code, [how to deobfuscation?](https://blog.quarkslab.com/deobfuscation-recovering-an-ollvm-protected-program.html)
- [x] Added support for x86 for obfucator. There is a link at the bottom of the tutorial for configuring obfucator.
- [x] Anti-debugging the so, the current code is a relatively simple solution, there are more complicated and more sophisticated solutions, such as: each time you perform encryption and decryption sign to determine whether it is traced, you want to write more complicated after your fork
- [x] Masking the simulator when the code is run: The code comes from my another repository [Check_Emulator_In_NDK](https://github.com/Scavenges/Check_Emulator_In_NDK)
- [x] Anti-debugging, the current code is a relatively simple solution, there are more complicated and more sophisticated solutions, such as: each time you perform encryption and decryption sign to determine whether it is traced, you want to write more complicated after your fork
- [x] Detect device is emulator in runtime : The code comes from my another repo [Check_Emulator_In_NDK](https://github.com/Scavenges/Check_Emulator_In_NDK)
- [ ] TODO: Prevent SO file being code inject

```
Char * key = "NMTIzNDU2Nzg5MGFiY2RlZg"; / / Here is the key is processed and stored here, in fact the real key is: "1234567890abcdef"
```
## Build & Integration
## before you clone.
install GIT-LFS: https://git-lfs.github.com/

a. Set ndk.dir in local.properties Requires that the ndk version must be 11-13b. High version ndk has not been tested, and may doesn't compiled.
## build & run it.
1. preparation:

b. Integrate into the project, please modify the class name and method name, dont expose the encryption algorithm, modify the key storage program into the code.
run the shell : aesjni/src/main/jni/build_libsodium_for_all_android_abi.sh
2. click run app from Android Studio.

## Integration
a. generating a chacha20 key:

run `test_in_exexutaing.sh`, and look at logcat. It will generate key and nonce. You can paste it into **JNIEntry.c**.

c. Generate and modify signatures.
b. Set ndk.dir in local.properties. Some versions of ndk I have not tested. Maybe you will encounter build errors.

c.1.Generate keystore
c. Integrate into the project, please modify the class name and method name, dont expose the encryption algorithm, modify the key storage program into the code.

d. Generate and modify signatures.

d.1. Generate keystore
```
/ / Then the current directory
$ mkdir keystore
Expand All @@ -48,7 +58,7 @@ c.2. Get the hash value of the current keystore and modify the package name and

Base64 algorithm from: https://github.com/willemt/pearldb

AES128 Algorithm From: https://github.com/kokke/tiny-AES128-C
libsodium Algorithm From: https://github.com/jedisct1/libsodium

Native code obfuscator: [obfuscation-o-llvm-ndk](https://fuzion24.github.io/android/obfuscation/ndk/llvm/o-llvm/2014/07/27/android-obfuscation-o-llvm-ndk)

Expand All @@ -58,10 +68,11 @@ Native code obfuscator: [obfuscation-o-llvm-ndk](https://fuzion24.github.io/andr
![unconfused so](https://github.com/weizongwei5/AESJniEncrypt/raw/master/img/unobfscator_debugapk.png)
![confused so](https://github.com/weizongwei5/AESJniEncrypt/raw/master/img/obfscator_screen.png)

Contrast: So confused is three times the size before confusion.
Contrast: Confused SO file is three times the size before confusion.
If the size of SO file bother you, you can disable obfscator-lvvm. It is unnecessary.

### PS:
Because you need to do signature verification, i cann't provide jcenter dependencies, pls forgive me!
### In addition, I have to told you:
Because you need to do signature verification, I cann't provide jcenter dependencies, pls forgive me!

Regardless of how secure the code, I still against that the key being stored in the code.

Expand All @@ -74,7 +85,13 @@ This is my NDK configuration obfuscator tutorial: [Obfuscator-LLVM-4.0-BUILD-NDK

If you want to ask me,please click [![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/askbruce/community).

If you encounter crash, you can look into **FigureOutJNICrash.md** to find where code crash at.

-------------------
## Legal
If you live in China, you should take care about [checking apk signature](https://github.com/BruceWind/AESJniEncrypt/blob/master/aesjni/src/main/cpp/check_emulator.h#L15).
I have called PackageManger that may be misunderstood to collect list of installed apps.
You should look at [工信部整治八项违规](http://www.miit.gov.cn/n1146295/n7281315/c7507241/part/7507297.docx).

## Contributing

Expand Down
53 changes: 31 additions & 22 deletions README_zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,33 @@
[中文](https://github.com/BruceWind/AESJniEncrypt/blob/master/README_zh.md)

# 追求极致的代码安全性保障
- [x] ndk实现AES加密
- [x] 使用JniOnload 隐藏c函数
- [x] ~~ndk实现AES加密~~,性能不佳,已废弃此方式
- [ ] 使用chacha20加密,TLS1.3在移动端都用了chacha20了,性能对ARM架构CPU更好。
- [x] 使用JniOnload 隐藏C函数
- [x] 使用签名校验避免被再次打包(这是绕过破解加密算法直接调用你的jni函数)
- [x] ~~key存在符号表中,同时隐藏字符表~~ 该方案已经废弃,[废弃原因issues5](https://github.com/weizongwei5/AESJniEncrypt/issues/5),请看下一条
- [x] ~~key存在符号表中,同时隐藏字符表~~ 该方案已经废弃,[废弃原因issues5](https://github.com/weizongwei5/AESJniEncrypt/issues/5)
- [x] 手工处理隐藏key,最复杂的方案:将密钥分成不同的几段,存储在不同的代码中,最后将他们拼接起来,可以将整个操作写的很复杂,增加逆向难度。(目前代码里用的是稍微简单的方案)
- [x] 使用obfuscator混淆C的代码,[关于破解obfuscator](https://blog.quarkslab.com/deobfuscation-recovering-an-ollvm-protected-program.html)
- [x] 增加obfucator对x86的支持,具体配置obfucator的教程底部有链接。
- [x] 反动态调试 , 目前代码里是比较简单的方案, 有更复杂更高明的方案,比如:每次执行加密解密签先去判断是否被trace,想要更复杂的自己fork之后去写
- [x] 代码run的时候屏蔽模拟器 :代码来自我的另外一个仓库[Check_Emulator_In_NDK](https://github.com/Scavenges/Check_Emulator_In_NDK)
- [x] 代码运行时屏蔽模拟器 :代码来自我的另外一个仓库[Check_Emulator_In_NDK](https://github.com/Scavenges/Check_Emulator_In_NDK)
- [ ] TODO:防止so代码被code inject

```
char * key = "NMTIzNDU2Nzg5MGFiY2RlZg";//这里是key被做过处理存储在这里的,实际上真实的key是:"1234567890abcdef"
```
## 尝试编译,并跑起来
1.准备:
运行这个shell : aesjni/src/main/jni/build_libsodium_for_all_android_abi.sh
2.打开AS运行app,并查看日志。
## 集成
先安装GIT-LFS:https://git-lfs.github.com/

a.先配置local.properties中ndk.dir 要求使用ndk版本必须11-13b,新版本ndk没有测试过,或许不能编译通过。

b.集成到项目中请修改类名方法名,不要暴露加密算法,自行修改key存储到代码里的方案.

b.1. 生成 chacha20 key:

run `test_in_exexutaing.sh`,然后请看logcat. 随机生成的key & nonce会显示出来. 你需要粘贴到 **JNIEntry.c**.

c.生成和修改签名.

**c.1.生成**
Expand All @@ -36,8 +43,6 @@ $ keytool -genkey -alias client1 -keypass 123456 -keyalg RSA -keysize 1024 -vali
...
...
```

**c.2.取得当前keystore的hash值,并修改native代码中的包名和hash**
Expand All @@ -48,18 +53,10 @@ $ keytool -genkey -alias client1 -keypass 123456 -keyalg RSA -keysize 1024 -vali
## 鸣谢

Base64 算法 来自:https://github.com/willemt/pearldb

AES128 算法 来自:https://github.com/kokke/tiny-AES128-C

Libsodium 算法 来自:https://github.com/jedisct1/libsodium
Native代码混淆器:[obfuscation-o-llvm-ndk](https://fuzion24.github.io/android/obfuscation/ndk/llvm/o-llvm/2014/07/27/android-obfuscation-o-llvm-ndk)

### 贡献者

[https://github.com/larry19840909](https://github.com/larry19840909)

[https://github.com/zxp0505](https://github.com/zxp0505)

[https://github.com/baoyongzhang](https://github.com/baoyongzhang)



Expand All @@ -70,23 +67,35 @@ Native代码混淆器:[obfuscation-o-llvm-ndk](https://fuzion24.github.io/andr

对比: 混淆后的so是混淆前的三倍大小。

### PS:
如果SO文件大小对您的项目有影响,你可以选择停用SO扰乱的,因为还有其他安全检查。

### 补充:
因为需要做签名校验,所以无法提供jcenter依赖了,望见谅!!

不管代码安全性多高,我依旧反对key存到代码里。

有问题及时提:[new issues](https://github.com/weizongwei5/AESJniEncrypt/issues/new)

想要编译出混淆过native代码的so需要修改aesjni/build.gradle文件中的externalNativeBuild,并配置NDK下的Obfuscator-LLVM。

这是我的NDK配置混淆器教程:[Obfuscator-LLVM-4.0-BUILD-NDK](https://github.com/weizongwei5/Obfuscator-LLVM-4.0-BUILD-NDK)

[其他语言怎么配合加解密?](https://github.com/weizongwei5/AESJniEncrypt/issues/8)

如果要直接问我,请点这里[![Gitter chat](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/askbruce/community).

如果你遇到了崩溃,请看**FigureOutJNICrash.md**,这个是个so崩溃定位的教程。

-------------------

有问题及时提:[new issues](https://github.com/weizongwei5/AESJniEncrypt/issues/new)
## 合规
如果你生活在中国,请注意[工信部整治八项违规](http://www.miit.gov.cn/n1146295/n7281315/c7507241/part/7507297.docx).
我调用了PackageManger[检查签名](https://github.com/BruceWind/AESJniEncrypt/blob/master/aesjni/src/main/cpp/check_emulator.c#L43),我只是**读取当前安装的app**, 这可能被认为**收集了安装列表**。从规定上来讲并不违规,只是读取了,并没**收集**,收集是违规的,读取是合规的。
只是目前有可能被误认为**收集**


### 贡献者

[https://github.com/larry19840909](https://github.com/larry19840909)

[https://github.com/zxp0505](https://github.com/zxp0505)

[https://github.com/baoyongzhang](https://github.com/baoyongzhang)
87 changes: 58 additions & 29 deletions aesjni/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
cmake_minimum_required(VERSION 3.4.1) #普通版本的clang

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

add_library( # Sets the name of the library.
JNIEncrypt
# -------configure import libsodium begin------
if (${ANDROID_ABI} STREQUAL "armeabi-v7a")
set(ARCH_PREFIX "armv7-a")
elseif (${ANDROID_ABI} STREQUAL "arm64-v8a")
set(ARCH_PREFIX "armv8-a")
elseif (${ANDROID_ABI} STREQUAL "armeabi")
set(ARCH_PREFIX "armv6")
elseif (${ANDROID_ABI} STREQUAL "x86")
set(ARCH_PREFIX "i686")
elseif (${ANDROID_ABI} STREQUAL "mips")
set(ARCH_PREFIX "mips32")
else ()
#set(ARCH_PREFIX ${ANDROID_ABI})
message(FATAL_ERROR "${ANDROID_ABI} static libraries might doesn't exist.")
endif ()

# Sets the library as a shared library.
SHARED

# Provides a relative path to your source file(s).
src/main/cpp/JNIEncrypt.c
src/main/cpp/checksignature.h
src/main/cpp/checksignature.c
src/main/cpp/check_emulator.h
src/main/cpp/check_emulator.c
src/main/cpp/debugger.h
src/main/cpp/debugger.c
src/main/cpp/aes.h
src/main/cpp/base64.h
src/main/cpp/aes.c
src/main/cpp/base64.c
)
set(distribution_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/main/jni/sodium_include/libsodium-android-${ARCH_PREFIX})

# 搜索指定的预构建库并将路径存储为变量。 因为默认情况下,CMake在搜索路径中包含系统库,
# 所以您只需要指定公共NDK库的名称你想添加。 在完成构建之前,CMake验证库存在。
message(STATUS "Current build include : ${distribution_DIR} ")
add_library(libsodium STATIC IMPORTED)
set_target_properties(libsodium PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/lib/libsodium.a)
# include C export files.
include_directories(${distribution_DIR}/include)
# -------configure import libsodium end------

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 )
set(DEBUG_FILE_C "src/main/jni/debugger.c")

# 指定CMake应链接到目标库的库。 您可以链接多个库,例如在此构建脚本中定义的库,预构建的第三方库或系统库。
if (${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(DEBUG_FILE_C "src/main/jni/debugger_test.c")
endif ()

target_link_libraries( # Specifies the target library.
JNIEncrypt
add_library( # Sets the name of the library.
JNIEncrypt

# Sets the library as a shared library.
SHARED

# included in the NDK.
${log-lib} )
# Provides a relative path to your source file(s).
src/main/jni/checksignature.h
src/main/jni/checksignature.c
src/main/jni/check_emulator.h
src/main/jni/check_emulator.c
src/main/jni/debugger.h
${DEBUG_FILE_C}
src/main/jni/logger.h
src/main/jni/keys_generator.h
src/main/jni/keys_generator.c
src/main/jni/base64.h
src/main/jni/base64.c
src/main/jni/str_utils.cpp
src/main/jni/JNIEncrypt.c
)

find_library(log-lib
log)

target_link_libraries( # Specifies the target library.
JNIEncrypt
libsodium
${log-lib})
Loading