Desarrollo seguro de aplicaciones C/C++ en Android con NDK IES Gran Capitán - 26 Enero 2016 Nacho Álvarez @neonigmacdb ✉ [email protected] http://www.nacho-alvarez.es Acerca de mí ● Ingeniero en Informática por la UCO ● Trayectoria profesional: ○ ○ ○ ○ ○ Soporte Servicio Informática UCO Desarrollo Web Desarrollo / Integración distribuciones GNU/Linux Android mobile + backend developer (WUL4) Actualmente: Área de Innovación (Redsys) 2/36 Acerca de mí ● Involucrado en la Innovación de soluciones de medios de pago 3/36 Eventos ● GDG Córdoba https://www.facebook.com/GDGCordobaESP/ ● Hack&Beers Córdoba https://twitter.com/hackandbeers ● BetaBeers Córdoba https://twitter.com/betabeersODB ● Codemotion Madrid https://www.facebook.com/Codemotion-Madrid-505998872792272/ ● FOSDEM (Free and Open Source Software Developers’ European Meeting) https://fosdem.org 4/36 Índice 1) Estructura de una app Android 2) Introducción al NDK 3) Nuestro primer programa con NDK 4) Seguridad en aplicaciones móviles a) Hacking app Android b) Hacking app nativa 5/36 Estructura de app Android 6/36 Tutoriales Android ● http://www.sgoliver.net/blog/curso-de-programacionandroid/indice-de-contenidos/ ● https://github.com/sgolivernet/curso-android-src ● https://github.com/sgolivernet/curso-android-src-as 7/36 Introducción al NDK ● Conjunto de herramientas que permiten incorporar código nativo (C/C++) en aplicaciones Android. ● Con NDK generas librerías binarias para cada arquitectura de procesador (arm, armv7, x86, etc) ● Las librerías binarias se pueden invocar desde Java por medio de JNI (Java Native Interface). 8/36 ¿Por qué usar NDK? 9/36 Estructura de app NDK 10/36 Nuestra primera app NDK public class AndroidActivity extends Activity { static { System.loadLibrary("mixed_sample"); } src/main/java/blog/neonigma/AndroidActivity.java private Context context; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate (savedInstanceState); setContentView(R.layout.main); context = this; String greeting = SayHello("neonigma"); Saludo saludo = new Saludo(greeting); Saludar.enviarSaludo(context, saludo); } public native String SayHello(String name); } 11/36 Nuestra primera app NDK public class Saludo { private String mensajeSaludo; src/main/java/blog/neonigma/Saludo.java public Saludo(String mensajeSaludo) { this.mensajeSaludo = mensajeSaludo; } public String getMensajeSaludo() { return mensajeSaludo; } } 12/36 Nuestra primera app NDK public class Saludar { src/main/java/blog/neonigma/Saludar.java public static void enviarSaludo(Context context, Saludo saludo) { Toast.makeText(context, saludo.getMensajeSaludo(), Toast.LENGTH_LONG).show(); } } 13/36 Nuestra primera app NDK #include <jni.h> #include <iostream> src/main/jni/code.cpp #include <string> #include <stdexcept> using namespace std; extern "C" { JNIEXPORT jstring JNICALL Java_blog_neonigma_AndroidActivity_SayHello(JNIEnv *env, jobject thiz, jstring name) { 14/36 Nuestra primera app NDK std::string variableImportante = "3.14"; try src/main/jni/code.cpp { const char *myName = env->GetStringUTFChars(name, 0); std::string nameCPP(myName); nameCPP = "Hello: " + nameCPP; return env->NewStringUTF(nameCPP.c_str()); } catch (exception &ex) { const char *error = "Failed"; return env->NewStringUTF(error); } } } 15/36 Nuestra primera app NDK apply plugin: 'com.android.model.application' build.gradle model { android { compileSdkVersion = 19 buildToolsVersion = "23.0.2" defaultConfig.with { applicationId = "src.blog.neonigma" minSdkVersion.apiLevel = 17 targetSdkVersion.apiLevel = 19 versionCode = 1 versionName = "1.0" } } 16/36 Nuestra primera app NDK android.ndk { build.gradle moduleName = "mixed_sample" stl = "stlport_static" CFlags.addAll("-fexceptions") cppFlags.addAll("-fexceptions") } android.buildTypes { release { minifyEnabled = false proguardFiles.add(file("proguard-rules.pro")) } } } 17/36 Demo time! 18/36 Hacking app Android ● Una app Android se empaqueta dentro de un fichero APK ● Estos ficheros son solamente ficheros ZIP conteniendo recursos y un archivo Dalvik Executable (.dex) ● Con las herramientas adecuadas, podemos extraer el código Java incluido dentro del fichero .dex ● Elementos como los recursos gráficos y el fichero AndroidManifest.xml no van ofuscados 19/36 Hacking app Android Para extraer el código de la parte Java (no nativa) ● Paso 1: extraer .dex del APK $ unzip program.apk classes.dex Archive: program.apk inflating: classes.dex ● Paso 2: utilizar dex2jar para convertir classes.dex a ficheros .class de Java $ d2j-dex2jar.sh./classes.dex dex2jar classes.dex -> ./classes-dex2jar.jar ● Paso 3: utilizamos el decompiler JD-GUI para extraer el código fuente $ ./jd-gui classes.dex.dex2jar.jar 20/36 Hacking app Android 21/36 Hacking app Android ● Necesitamos ofuscación defensiva: Proguard / Dexguard ● ProGuard optimiza, reduce y ofusca el código de aplicaciones Android ● Solo funcionará cuando hagamos la exportación a APK ● Las reglas se escriben en fichero proguard-rules.pro 22/36 Hacking app Android ● Ejemplo proguard (identificar lo que se excluye): -optimizations !code/simplification/arithmetic -keep public class * extends android.app.Activity -keep public class * extends android.app.Fragment -keep public class * extends android.support.v4.app.Fragment -keepclasseswithmembernames,includedescriptorclasses class * { native <methods>; } 23/36 Hacking app Android No obstante, hay que ir probando reglas de ofuscación.... 24/36 Desarrollo apps NDK 25/36 Hacking app nativa ● El código nativo se incluye dentro del apk como ficheros .so ● Este código está compilado y ensamblado contra una arquitectura específica (ARM, x86, …) ● En teoría es difícil leer un fichero ensamblado, pero… hay herramientas que ayudan: IDA como disassembler, apktool para desempaquetado y reempaquetado, etc. 26/36 Hacking app nativa 27/36 Hacking app nativa ● Cosas que podemos hacer: ○ Ocultar nuestras funciones y variables de la tabla de símbolos LOCAL_CFLAGS += -ffunction-sections -fdata-sections -fvisibility=hidden ○ Instructions Ofuscar el código, por ej. con O-LLVM Substitution: -mllvm -sub Bogus Control Flow: -mllvm -bcf Control Flow Flattening: -mllvm -fla Functions annotations 28/36 Hacking app nativa Sin ofuscación Con ofuscación 29/36 Caso práctico Charlemos sobre un caso real... 30/36 Ejemplo 31/36 32/36 33/36 Ejemplo práctico 34/36 Ejemplo práctico ¡Nada de ser malvadou! 35/36 Referencias ● Curso de programación Android sgoliver ● Introducció n al Desarrollo de NDK apps http://es.slideshare.net/RevistaSG/introduccion-aldesarrollo-de-ndk-apps-dev-day-4-woman-condesasama ● Conectar programas C/C++ con apps Android http://www.nacho-alvarez.es/index. php/blog/2012/05/02/conectar-programas-cc-conaplicaciones-android/ 36/36