Daniele
Daniele

Reputation: 186

Android NDK JNI binary code?

I just created my first Android application that uses JNI and NDK, the simple Hello-JNI to speak. With a unique function that returns a string. I signed APK unpacked and if I see the .so files that do not seem compiled natively. I expected a binary code. I read the name of function and string. My goal is to use the SDK to write native code to hide the strings that are not clouded by proguard. I used Android Studio 2.1.2

Build.gradle project

buildscript {
repositories {
    jcenter()
}
dependencies {
    //classpath 'com.android.tools.build:gradle:2.1.2'
    classpath 'com.android.tools.build:gradle-experimental:0.7.2'
    // NOTE: Do not place your application dependencies here; they belong
    // in the individual module build.gradle files
}
}

allprojects {
   repositories {
      jcenter()
}
}

task clean(type: Delete) {
   delete rootProject.buildDir
}

Build.Gradle app

apply plugin: 'com.android.model.application'

model {
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "com.danielezampieri.jniapp"
        minSdkVersion.apiLevel 18
        targetSdkVersion.apiLevel 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles.add(file('proguard-android.txt'))
        }
    }
    ndk {
        moduleName "jniapp"
    }
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.0'
compile 'com.android.support:design:23.0.0'
}

gradle-wrapper.properties

#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip

local.properties

ndk.dir=P\:\\Android\\sdk\\ndk-bundle
sdk.dir=P\:\\Android\\sdk

Upvotes: 0

Views: 957

Answers (1)

Ped7g
Ped7g

Reputation: 16606

if your string is defined in C/C++ like:

char *mySecretString = "some secret";

Then of course it is readable in .so, while it is natively compiled. Compilation is not obfuscation, but translation of code into machine code of target platform. The string is not code, but data, and binary form of ASCII string data is the very same ASCII string.

Function names don't have to be visible in .so, unless:

  • they are global/extern (then they must be visible, so the application loading the shared library can search the functions in memory by their name - during loading of library).
  • your .so file includes some debug info, use release mode, and strip as needed (I do believe the NDK in release mode strips .so files enough, but I never examined it personally, so maybe they leave some debug info even in release?).

So if you want to use native library for obfuscation:

For functions: use cryptic external function names, or add another layer of local functions called trough external (visible) function names, and make sure all debug info is stripped, so local symbols are not included.

For strings: encrypt the data by some encryption, include the encrypted data in .so file, then decrypt the strings into memory before usage by your decryption routine.

Mind you, anyone disassembling your code manually will be still able to find all that stuff out, if he puts enough effort into it.

Upvotes: 1

Related Questions