/JniExample

A comprehensive Android JNI example project using Android Studio 3.2.1

Primary LanguageC++

JniExample & Using HP Fortify to Scan Android JNI C/C++ Code

This is a hands on JNI example project to help JNI developer. And also, I include the way how to do HP Fortify scanning for JNI C/C++ code.

HP Fortify does not directly support scanning Android JNI code base, we need some customise steps to tell HP Fortify source analyser to generate the FPR report.

Environment

  • MacOS Catalina: 10.15.16
  • HP Fortify Analyser Fortify_SCA_and_Apps_20.1.0
  • Android NDK 21.0.6113669
  • CMake 3.10.2.4988404
  • Assume project name: JNI_EXAMPLE

Create directory fortify_tools

This directory is at the same level as JniExample/app/CMakeLists.txt

Create fortify_tools/fortify_cc

This is the gcc compiler wrapper which injects the sourceanalyzer command.

#!/bin/sh

SOURCEANALYZER=$HPFORTIFY_HOME/sourceanalyzer
MEMORY="-Xmx7270M -Xms400M -Xss24M "
PROJECTID="JNI_EXAMPLE"

$SOURCEANALYZER $MEMORY -b $PROJECTID gcc $@

Create fortify_tools/fortify_cxx

This is the g++ compiler wrapper which injects the sourceanalyzer command.

#!/bin/sh

SOURCEANALYZER=$HPFORTIFY_HOME/sourceanalyzer
MEMORY="-Xmx7270M -Xms400M -Xss24M "
PROJECTID="JNI_EXAMPLE"

$SOURCEANALYZER $MEMORY -b $PROJECTID g++ $@

Change directory to dir fortify_tools

cd JniExample/app/fortify_tools

Create hpfortify_build directory

rm -rf hpfortify_build
mkdir hpfortify_build

Config cmake files using standalone CMake command

The standalone cmake build command can be found from file JniExample/app/.cxx/cmake/release/x86/build_command.txt which is generated after running below command

➜  JniExample ✗ ./gradlew :app:externalNativeBuildRelease

build_command.txt can be something similar as below

Executable : /Library/Android/sdk/cmake/3.10.2.4988404/bin/cmake
arguments : 
-H<your-working-home-dir>/JniExample/app
-DCMAKE_CXX_FLAGS=-std=c++11 -frtti -fexceptions
-DCMAKE_FIND_ROOT_PATH=<your-working-home-dir>/JniExample/app/.cxx/cmake/release/prefab/x86/prefab
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_TOOLCHAIN_FILE=<your-working-home-dir>/Library/Android/sdk/ndk/21.0.6113669/build/cmake/android.toolchain.cmake
-DANDROID_ABI=x86
-DANDROID_NDK=<your-working-home-dir>/Library/Android/sdk/ndk/21.0.6113669
-DANDROID_PLATFORM=android-16
-DCMAKE_ANDROID_ARCH_ABI=x86
-DCMAKE_ANDROID_NDK=<your-working-home-dir>/Library/Android/sdk/ndk/21.0.6113669
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=<your-working-home-dir>/JniExample/app/build/intermediates/cmake/release/obj/x86
-DCMAKE_MAKE_PROGRAM=<your-working-home-dir>/Library/Android/sdk/cmake/3.10.2.4988404/bin/ninja
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_SYSTEM_VERSION=16
-B<your-working-home-dir>/JniExample/app/.cxx/cmake/release/x86
-GNinja
jvmArgs : 

Build command args:

According to above to create the host specific CMake command for generating cmakefiles. E.g. for my case, it is as below:

➜  build-jni git:(master) ✗ /Users/myname/Library/Android/sdk/cmake/3.10.2.4988404/bin/cmake -H/Users/myname/JniExample/app \
-DCMAKE_CXX_FLAGS=-std=c++11 -frtti -fexceptions \
-DCMAKE_FIND_ROOT_PATH=/Users/myname/JniExample/app/build-jni/.cxx/cmake/release/prefab/x86/prefab \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_TOOLCHAIN_FILE=/Users/myname/Library/Android/sdk/ndk/21.0.6113669/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=x86 \
-DANDROID_NDK=/Users/myname/Library/Android/sdk/ndk/21.0.6113669 \
-DANDROID_PLATFORM=android-16 \
-DCMAKE_ANDROID_ARCH_ABI=x86 \
-DCMAKE_ANDROID_NDK=/Users/myname/Library/Android/sdk/ndk/21.0.6113669 \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/Users/myname/JniExample/app/build-jni/intermediates/cmake/release/obj/x86 \
-DCMAKE_MAKE_PROGRAM=/Users/myname/Library/Android/sdk/cmake/3.10.2.4988404/bin/ninja \
-DCMAKE_SYSTEM_NAME=Android \
-DCMAKE_SYSTEM_VERSION=16 \
-B/Users/myname/JniExample/app/build-jni/.cxx/cmake/release/x86 \
-GNinja ..

Build project

cd JniExample/app/hpfortify_build
/Users/myname/Library/Android/sdk/cmake/3.10.2.4988404/bin/cmake --build .

Manually change compiler

  1. Go to directory /Users/myname/JniExample/app/hpfortify_build/CMakeFiles/3.10.2

  2. Replace the C compiler inside CMakeCCompiler.cmake

    set(CMAKE_C_COMPILER "/Users/myname/JniExample/app/fortify_tools/fortify_cc")
  3. Replace the CXX compiler insideCMakeCXXCompiler.cmake

    set(CMAKE_CXX_COMPILER "/Users/myname/JniExample/app/fortify_tools/fortify_cxx"))

Rebuild project

/Users/myname/Library/Android/sdk/cmake/3.10.2.4988404/bin/cmake --build .

Generate Fortify report

Applications/Fortify/Fortify_SCA_and_Apps_20.1.0/bin/sourceanalyzer -b JNI_EXAMPLE -scan -f JNI_EXAMPLE.fpr

Automation

All of above manual steps can be automatically done with script hpfortify_scan_native.sh.

Run below command:

➜  fortify_tools git:(master) ✗ sh hpfortify_scan_native.sh

You will see the FPR file is generated under directory app/fortify_tools/.

Screenshot for the report

HP Fortify report

Some errors

But this error does not really matter with report generation, can simply ignore it.

References