├── .classpath
├── .project
├── .settings
└── org.eclipse.jdt.core.prefs
├── AndroidManifest.xml
├── CydiaSubstrate.iml
├── LEEME.md
├── README.md
├── assets
└── privacy.json
├── ic_launcher-web.png
├── libs
├── android-support-v4.jar
└── substrate-api.jar
├── proguard-project.txt
├── res
├── drawable-hdpi
│ └── ic_launcher.png
├── drawable-mdpi
│ └── ic_launcher.png
├── drawable-xhdpi
│ └── ic_launcher.png
├── drawable-xxhdpi
│ └── ic_launcher.png
├── layout
│ └── activity_main.xml
├── menu
│ └── main.xml
├── values-sw600dp
│ └── dimens.xml
├── values-sw720dp-land
│ └── dimens.xml
├── values-v11
│ └── styles.xml
├── values-v14
│ └── styles.xml
└── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── src
└── ar
└── fsadosky
└── marvintoqueton
├── Main.java
├── MainActivity.java
├── MessageHandler.java
├── UpdateViewTask.java
├── Utils.java
├── hooks
├── AdapterViewHook.java
├── ButtonHook.java
├── CheckboxHook.java
├── DatePickerHook.java
├── EditTextHook.java
├── Hook.java
├── RadioGroupHook.java
├── SearchViewHook.java
├── SpinnerHook.java
├── TimePickerHook.java
├── ToggleButtonHook.java
├── ViewGroupHook.java
└── ViewHook.java
└── privacyhooks
├── ContactsHelper.java
├── DeviceDataHook.java
├── FakeLocationListener.java
├── LocationHook.java
├── PrivacyHook.java
├── Utils.java
└── WifiHook.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | Marvin-toqueton
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
3 | org.eclipse.jdt.core.compiler.compliance=1.6
4 | org.eclipse.jdt.core.compiler.source=1.6
5 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
24 |
25 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/CydiaSubstrate.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/LEEME.md:
--------------------------------------------------------------------------------
1 | # Marvin Toquetón #
2 |
3 | Herramienta de testing automático de GUI desarrollado para Marvin-dynamic-analyzer.
4 |
5 | Version 0.1
6 |
7 | El framework es utilizado para dos propósitos:
8 | * Hookear elementos de la UI para interactuar con ellos sin conocer el layout de las Views.
9 | * Modificar el acceso a identificadores específicos del dispositivo, contactos, información de la wifi e ubicación para permitir analizar si esos identificadores son transmitidos por la red o almacenados de forma insegura en el dispositivo.
10 |
11 | ## Implementación ##
12 |
13 | Toquetón instrumenta las siguientes Views para interactuar con la aplicación:
14 |
15 | * EditText
16 | * Checkbox
17 | * RadioGroup
18 | * ToggleButton
19 | * Spinner
20 | * DatePicker
21 | * TimePicker
22 | * Button
23 | * TextView
24 | * Menu
25 | * AdapterView
26 | * SearchView
27 | * ViewGroup
28 | * View
29 |
30 | Cuando una View es creada, un mensaje es enviado a un Handler que corre en el main thread de la aplicación y es responsable de interactuar con ella periódicamente. Un retraso aleatorio para interactuar con la View es ajustado cada vez dependiendo de la view y su visibilidad.
31 |
32 | Además, para extender la interacción con la aplicación, el fuzzer comienza una nueva actividad (no necesariamente exportada) continuamente cada cierto tiempo.
33 |
34 | Los métodos instrumentados para acceder a la información privada del dispositivo está basada el el proyecto [ASA](https://github.com/c0d1ngb4d/ASA/). Estos métodos hookeados devuelven la información leída desde un archivo denominado 'privacy.json' ubicado en la memoria externa del dispositivo.
35 |
36 | ## Requerimientos ##
37 |
38 | * Dispositivo rooteado con Android 4.3 o menor
39 | * Cydia Substrate
40 |
41 | ## Créditos ##
42 | * Joaquín Rinaudo ([@xeroxnir](https://www.twitter.com/xeroxnir))
43 | * Juan Heguiabehere ([@jheguia](https://www.twitter.com/jheguia))
44 |
45 | ## Contacto ##
46 | * Mandar un correo a stic en el dominio fundacionsadosky.org.ar
47 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Marvin Toquetón #
2 |
3 | Automated GUI testing utility developed for Marvin-dynamic-analyzer.
4 |
5 | Version 0.1
6 |
7 | The framework is used for two purposes:
8 |
9 | * Hook UI elements to interact with them without knowing the view layout.
10 | * Modify access to device specific identifiers, contacts, wifi and locations informations to be able to
11 | analyze if those identifiers are transmitted to the network or stored insecurely in the device
12 |
13 | ## Implementation description ##
14 |
15 | Toquetón instruments the following Views for interacting with the application:
16 |
17 | * EditText
18 | * Checkbox
19 | * RadioGroup
20 | * ToggleButton
21 | * Spinner
22 | * DatePicker
23 | * TimePicker
24 | * Button
25 | * TextView
26 | * Menu
27 | * AdapterView
28 | * SearchView
29 | * ViewGroup
30 | * View
31 |
32 | When a View is created, a message is send to a Handler running in the main thread of the application that is responsible of interacting with it periodically. A random delay for interacting with it is set depending on the type of view and it's visibility status.
33 |
34 | Also, in order to extend the interaction with the application, the fuzzer starts a new random activity (non necessarily exported) repeatedly.
35 |
36 | Instrumentation for methods that access to private information identifiers and resources is based in [ASA](https://github.com/c0d1ngb4d/ASA/) project. The methods hooked and the information return by hooks is read from a file stored in external storage named 'privacy.json'.
37 |
38 | ## Requirements ##
39 |
40 | * Android rooted device with 4.3 or lower
41 | * Cydia Substrate
42 |
43 | ## Credits ##
44 | * Joaquín Rinaudo ([@xeroxnir](https://www.twitter.com/xeroxnir))
45 | * Juan Heguiabehere ([@jheguia](https://www.twitter.com/jheguia))
46 |
47 | ## Who do I talk to? ##
48 | * Send an email to stic at fundacionsadosky.org.ar
49 |
--------------------------------------------------------------------------------
/assets/privacy.json:
--------------------------------------------------------------------------------
1 | {
2 | "android.telephony.TelephonyManager" : {
3 | "getSimOperatorName" : "QUAM-SIM",
4 | "getSimOperator" : "72201",
5 | "getNetworkOperatorName" : "QUAM-NETWORK",
6 | "getNetworkOperator" : "72207"
7 | },
8 | "com.android.internal.telephony.gsm.GSMPhone" : {
9 | "getDeviceId" : "352738061926670",
10 | "getImei" : "352738061926671",
11 | "getSubscriberId" : "722010000906017",
12 | "getLine1Number" : "1112341234"
13 | },
14 |
15 | "com.android.internal.telephony.gsm.CDMAPhone" : {
16 | "getDeviceId" : "352738061926672",
17 | "getMeid" : "352738061926673",
18 | "getSubscriberId" : "722010000906017",
19 | "getLine1Number" : "541101010101"
20 | },
21 | "com.android.internal.telephony.PhoneBase" :
22 | {
23 | "getIccSerialNumber" : "8954010111009060172f"
24 |
25 | },
26 | "android.net.wifi.WifiInfo" : {
27 | "getBSSID" : "de:ad:be:ef:aa:aa",
28 | "getIpAddress" : "192.168.0.2",
29 | "getMacAddress" : "de:ad:be:ef:bb:bb",
30 | "getSSID" : "ThizIsMyWifi"
31 | },
32 |
33 | "com.android.settings.Utils" : {
34 | "getWifiIpAddresses" : "192.168.0.2",
35 | "getDefaultIpAddresses" : "192.168.0.2"
36 | },
37 | "android.location.LocationManager" : {
38 | "requestLocationUpdates" : "-34.603773, -58.381700",
39 | "getLastKnownLocation" : "-34.603773, -58.381700"
40 | },
41 | "android.net.wifi.WifiManager" : {
42 | "getConfiguredNetworks" : "",
43 | "getScanResults" : ""
44 | }
45 | }
--------------------------------------------------------------------------------
/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/ic_launcher-web.png
--------------------------------------------------------------------------------
/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/libs/substrate-api.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/libs/substrate-api.jar
--------------------------------------------------------------------------------
/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/programa-stic/Marvin-toqueton/6e9710dc4b42e8f9b2f5326e0e2bcaf09aff60e4/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/res/values-v11/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values-v14/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FuzzingHelper
5 | Settings
6 | Restart the phone!
7 |
8 |
9 |
--------------------------------------------------------------------------------
/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/Main.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton;
2 |
3 | import java.io.File;
4 | import java.io.FileOutputStream;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 |
8 | import android.content.Context;
9 | import android.os.Environment;
10 | import android.telephony.TelephonyManager;
11 | import android.util.Log;
12 | import ar.fsadosky.marvintoqueton.hooks.*;
13 | import ar.fsadosky.marvintoqueton.privacyhooks.ContactsHelper;
14 | import ar.fsadosky.marvintoqueton.privacyhooks.DeviceDataHook;
15 | import ar.fsadosky.marvintoqueton.privacyhooks.LocationHook;
16 | import ar.fsadosky.marvintoqueton.privacyhooks.WifiHook;
17 |
18 | public class Main {
19 |
20 | static void initialize() {
21 |
22 | // gui fuzzer hooks
23 | (new EditTextHook()).hook();
24 | (new DatePickerHook()).hook();
25 | (new TimePickerHook()).hook();
26 | (new ToggleButtonHook()).hook();
27 | (new SpinnerHook()).hook();
28 | (new ButtonHook()).hook();
29 | (new RadioGroupHook()).hook();
30 | (new SearchViewHook()).hook();
31 | (new CheckboxHook()).hook();
32 | (new AdapterViewHook()).hook();
33 | (new ViewGroupHook()).hook();
34 | (new ViewHook()).hook();
35 |
36 | // privacy Hooks
37 | (new WifiHook()).hook();
38 | (new DeviceDataHook()).hook();
39 | (new LocationHook()).hook();
40 | }
41 |
42 | private static void CopyJsontoSDCard(Context c) throws IOException {
43 |
44 | File dir = Environment.getExternalStorageDirectory();
45 | InputStream in = c.getAssets().open("privacy.json");
46 | FileOutputStream out = new FileOutputStream(dir.getAbsolutePath()+"/privacy.json");
47 | byte[] buff = new byte[1024];
48 | int read = 0;
49 | try {
50 | while ((read = in.read(buff)) > 0) {
51 | out.write(buff, 0, read);
52 | }
53 | } finally {
54 | in.close();
55 | out.close();
56 | }
57 | }
58 |
59 | public static void doOnceWhenInstalled(Context context) {
60 |
61 | ContactsHelper.AddDummyContacts(context);
62 | try {
63 | Main.CopyJsontoSDCard(context);
64 | } catch (IOException e) {
65 | e.printStackTrace();
66 | }
67 | }
68 | }
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/MainActivity.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton;
2 |
3 | import android.os.Bundle;
4 | import android.app.Activity;
5 | import android.view.Menu;
6 |
7 | public class MainActivity extends Activity {
8 |
9 | @Override
10 | protected void onCreate(Bundle savedInstanceState) {
11 | super.onCreate(savedInstanceState);
12 | setContentView(R.layout.activity_main);
13 | Main.doOnceWhenInstalled(this);
14 | }
15 |
16 | @Override
17 | public boolean onCreateOptionsMenu(Menu menu) {
18 | // Inflate the menu; this adds items to the action bar if it is present.
19 | getMenuInflater().inflate(R.menu.main, menu);
20 | return true;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/MessageHandler.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton;
2 |
3 |
4 | import android.content.Context;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.os.Message;
8 | import android.util.Log;
9 | import android.view.View;
10 | import ar.fsadosky.marvintoqueton.hooks.Hook;
11 |
12 | public class MessageHandler {
13 | public static Handler handler;
14 | //Last used context in a view, used to start another activity
15 | public static Context context;
16 | //is third party app
17 | public static boolean third_party = false;
18 |
19 |
20 | public static void sendMessage(Object object, int code, long delayMillis) {
21 | Message msg = MessageHandler.getHandler().obtainMessage(code, object);
22 | MessageHandler.getHandler().sendMessageDelayed(msg, delayMillis);
23 | }
24 |
25 | public static Handler getHandler() {
26 | if (handler == null) {
27 | initMessageHandler();
28 | }
29 | return handler;
30 | }
31 |
32 | public static void initMessageHandler() {
33 | if (handler == null) {
34 | Log.d("DEBUG", "initializating handler");
35 | handler = new Handler(Looper.getMainLooper()) {
36 | @Override
37 | public void handleMessage(Message inputMessage) {
38 | try {
39 | switch (inputMessage.what) {
40 | /*case Hook.CLEAN_SERVED_VIEWS_TIMER:
41 | Hook.already_served_views.clear();
42 | //resend message again
43 | Utils.sendMessageToClearServedViews();
44 | break;*/
45 | case Hook.UPDATEVIEW:
46 | UpdateViewTask viewTask = (UpdateViewTask) inputMessage.obj;
47 | //allows changing activity
48 | if(context == null){
49 | //init if it's third_party
50 | third_party = Utils.isThirdParty(viewTask.view.getContext(), viewTask.view.getContext().getPackageName());
51 | }
52 | //updating last used context
53 | MessageHandler.context = viewTask.view.getContext();
54 |
55 | Log.d("DEBUG", "ID: " + viewTask.view.getId());
56 | Log.d("DEBUG", "Class: "
57 | + viewTask.view.getClass().getName());
58 | Log.d("DEBUG",
59 | "getVisibility: "
60 | + viewTask.view.getVisibility());
61 | // if was dettached, do not process it
62 | if (Hook.dettached_views.contains(viewTask.view)) {
63 | Hook.dettached_views.remove(viewTask.view);
64 | Log.d("DEBUG",
65 | "stopped processing detached view");
66 | return;
67 | }
68 | /*
69 | Log.d("DEBUG","Served views size"+Hook.already_served_views.size());
70 | Log.d("DEBUG","Served views "+Arrays.toString(Hook.already_served_views.toArray()));
71 | if(Hook.already_served_views.contains(viewTask.view)){
72 | //there appears to be multiple instances of the same
73 | //view, since served_already is refreshed every
74 | //min delay so stop processing this update
75 | Log.d("DEBUG",
76 | "view was served before MIN delay");
77 | return;
78 | }
79 | else{
80 | //marking as served
81 | Hook.already_served_views.add(viewTask.view);
82 | }*/
83 |
84 | // If set to repeat, send message again
85 | if (viewTask.hook.updateView(viewTask.view) && viewTask.repeat) {
86 |
87 | long newdelay = 0;
88 | // long delay for background objects
89 | if (viewTask.view.getVisibility() != View.VISIBLE) {
90 | newdelay = Utils.getRandomWaitForEvent() * 5;
91 | } else {
92 | newdelay = Utils.getRandomWaitForEvent();
93 | }
94 | Log.d("DEBUG",
95 | "ID delay is " + viewTask.view.getId());
96 | Log.d("DEBUG", "new delay is " + newdelay);
97 | handler.sendMessageDelayed(
98 | Message.obtain(inputMessage),
99 | newdelay);
100 | }
101 | break;
102 | case Hook.CHANGE_ACTIVITY:
103 | Log.d("DEBUG", "Changing activity ");
104 | //only for third_parties
105 | if( MessageHandler.context != null && third_party){
106 | Log.d("DEBUG", "Changing activity ");
107 | Utils.changeToRandomActivity(MessageHandler.context);
108 | }
109 | handler.sendMessageDelayed(
110 | Message.obtain(inputMessage),
111 | Utils.MIN_DELAY_FOR_EVENT * 5);
112 | break;
113 | }
114 | } catch (Exception e) {
115 | Log.d("DEBUG", "Ignoring exceptions ");
116 | Log.d("DEBUG", Log.getStackTraceString(e));
117 | }
118 | }
119 |
120 | };
121 | //send message to clear served views every MIN seconds
122 | //Utils.sendMessageToClearServedViews();
123 | //send message to change activity
124 | Utils.sendMessageToChangeActivity();
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/UpdateViewTask.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton;
2 |
3 | import android.view.View;
4 | import ar.fsadosky.marvintoqueton.hooks.Hook;
5 |
6 | public class UpdateViewTask{
7 | public View view;
8 | public Hook hook;
9 | public boolean repeat = false;
10 | }
11 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/Utils.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton;
2 |
3 | import java.util.Arrays;
4 | import java.util.Random;
5 |
6 | import android.content.ComponentName;
7 | import android.content.Context;
8 | import android.content.Intent;
9 | import android.content.pm.ActivityInfo;
10 | import android.content.pm.ApplicationInfo;
11 | import android.content.pm.PackageInfo;
12 | import android.content.pm.PackageManager;
13 | import android.content.pm.PackageManager.NameNotFoundException;
14 | import android.util.Log;
15 | import android.view.View;
16 | import ar.fsadosky.marvintoqueton.hooks.Hook;
17 |
18 | public class Utils {
19 |
20 | public static final int MIN_DELAY_FOR_EVENT = 10000;
21 | public static final int MAX_DELAY_FOR_EVENT = 20000;
22 | public static final String ERROR = "FUZZER_ERROR";
23 |
24 | public static boolean isThirdParty(Context context, String packageName) {
25 | PackageManager manager = context.getPackageManager();
26 | try {
27 | return !((manager.getPackageInfo(packageName, 0).applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0);
28 | } catch (NameNotFoundException e) {
29 | return false;
30 | }
31 | }
32 |
33 | public static void sendMessageToClearServedViews() {
34 | MessageHandler.sendMessage(null, Hook.CLEAN_SERVED_VIEWS_TIMER,
35 | Utils.MIN_DELAY_FOR_EVENT);
36 | }
37 |
38 | public static void sendMessageToChangeActivity() {
39 | MessageHandler.sendMessage(null, Hook.CHANGE_ACTIVITY,Utils.MIN_DELAY_FOR_EVENT * 10);
40 | }
41 |
42 | public static void repeatAtRandomEventToUpdateView(Hook hook, View hooked,
43 | long delay) {
44 | UpdateViewTask task = new UpdateViewTask();
45 | task.view = hooked;
46 | task.hook = hook;
47 | task.repeat = true;
48 | MessageHandler.sendMessage(task, Hook.UPDATEVIEW, delay);
49 | }
50 |
51 | public static void sendEventToUpdateView(Hook hook, View hooked, long delay) {
52 | UpdateViewTask task = new UpdateViewTask();
53 | task.view = hooked;
54 | task.hook = hook;
55 | MessageHandler.sendMessage(task, Hook.UPDATEVIEW, delay);
56 | }
57 |
58 | public static int randInt(int Low, int High) {
59 | Random r = new Random();
60 | int random = r.nextInt(High - Low) + Low;
61 | return random;
62 | }
63 |
64 | public static long getRandomWaitForEvent() {
65 | // get random between 500 milliseconds and 3000 (3 seconds)
66 | return randInt(MIN_DELAY_FOR_EVENT, MAX_DELAY_FOR_EVENT);
67 | }
68 |
69 | public static void changeToRandomActivity(Context context) throws NameNotFoundException {
70 | PackageManager manager = context.getPackageManager();
71 | PackageInfo info = manager.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
72 | int randomIndex = Utils.randInt(0, info.activities.length);
73 | ActivityInfo activity = info.activities[randomIndex];
74 | Intent intent = new Intent();
75 | ComponentName name =new ComponentName(activity.applicationInfo.packageName,
76 | activity.name);
77 | intent.setComponent(name);
78 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
79 | context.startActivity(intent);
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/hooks/AdapterViewHook.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton.hooks;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 | import android.widget.AdapterView;
6 | import ar.fsadosky.marvintoqueton.Utils;
7 |
8 | public class AdapterViewHook extends Hook {
9 |
10 | protected String getHookedClass() {
11 | return "android.widget.AdapterView";
12 | }
13 |
14 | protected boolean getCallMultipleTimes() {
15 | return true;
16 | }
17 |
18 | @Override
19 | public boolean updateView(View view) {
20 | AdapterView adapterview = (AdapterView) view;
21 | Log.d("DEBUG", "Setting clicking in adapter view ");
22 | if (adapterview.getCount() > 0) {
23 | int randomIndex = Utils.randInt(0, adapterview.getCount());
24 | View child = adapterview.getAdapter().getView(randomIndex, null,
25 | null);
26 | adapterview.setSelection(randomIndex);
27 | adapterview.performItemClick(child, randomIndex,
28 | adapterview.getItemIdAtPosition(randomIndex));
29 | }
30 | view.setFocusable(false);
31 | return true;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/hooks/ButtonHook.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton.hooks;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 | import android.widget.Button;
6 |
7 | public class ButtonHook extends Hook {
8 |
9 | public String getHookedClass() {
10 | return "android.widget.Button";
11 | }
12 |
13 | protected boolean getCallMultipleTimes() {
14 | return true;
15 | }
16 |
17 | @Override
18 | public boolean updateView(View view) {
19 | Log.d("DEBUG", "Pressing button ");
20 | ((Button) view).performClick();
21 | view.setFocusable(false);
22 | return true;
23 |
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/hooks/CheckboxHook.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton.hooks;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 | import android.widget.CheckBox;
6 |
7 | public class CheckboxHook extends Hook {
8 |
9 | public String getHookedClass() {
10 | return "android.widget.CheckBox";
11 | }
12 |
13 | protected boolean getCallMultipleTimes() {
14 | return true;
15 | }
16 |
17 | @Override
18 | public boolean updateView(View view) {
19 | CheckBox checkbox = (CheckBox) view;
20 | Log.d("DEBUG", "Setting checkbox " + !checkbox.isChecked());
21 | checkbox.setChecked(checkbox.isChecked());
22 | view.setFocusable(false);
23 | return true;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/hooks/DatePickerHook.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton.hooks;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 | import android.widget.DatePicker;
6 |
7 |
8 | public class DatePickerHook extends Hook {
9 |
10 | public String getHookedClass() {
11 | return "android.widget.DatePicker";
12 | }
13 |
14 | @Override
15 | public boolean updateView(View view) {
16 | Log.d("DEBUG", "Setting date ");
17 | ((DatePicker) view).updateDate(
18 | 1989, 1, 1);
19 | view.setFocusable(false);
20 | return true;
21 | }
22 |
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/hooks/EditTextHook.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton.hooks;
2 |
3 | import java.util.Locale;
4 | import java.util.regex.Matcher;
5 | import java.util.regex.Pattern;
6 |
7 | import android.text.InputType;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.EditText;
11 |
12 | public class EditTextHook extends Hook {
13 | private final static String[] mailKeywords = { "mail" };
14 | private final static String[] phoneKeywords = { "cell", "phone", "mobile" };
15 | private final static String[] passwordKeywords = { "password", "pwd",
16 | "pass", "characters" };
17 | private final static String[] nameKeywords = { "name", "lastname", "last",
18 | "last_name" };
19 | private final static String[] zipKeywords = { "zip", "postal" };
20 | private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
21 | + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
22 |
23 | public String getHookedClass() {
24 | return "android.widget.EditText";
25 | }
26 |
27 | static boolean looksLike(String match, String EMAIL_PATTERN) {
28 | if (match == null)
29 | return false;
30 | Pattern pattern = Pattern.compile(EMAIL_PATTERN);
31 | Matcher matcher = pattern.matcher(match);
32 | return matcher.matches();
33 | }
34 |
35 | static boolean hasKeywords(String match, String[] keywords) {
36 | if (match == null)
37 | return false;
38 | for (String key : keywords) {
39 | if (match.toLowerCase(Locale.getDefault()).contains(key)) {
40 | return true;
41 | }
42 | }
43 | return false;
44 | }
45 |
46 | protected String getMessage(View hooked) {
47 | return getMessageFor(hooked);
48 | }
49 |
50 | public static String getMessageFor(View hooked) {
51 | String message = null;
52 | EditText textview = (EditText) hooked;
53 |
54 | String resource_id = textview.getContext().getResources()
55 | .getResourceEntryName(textview.getId());
56 | String hint = "" + textview.getHint();
57 | int types = textview.getInputType();
58 |
59 | Log.d("DEBUG", "id " + textview.getId());
60 | Log.d("DEBUG", "name " + resource_id);
61 | Log.d("DEBUG", "hint " + hint);
62 | Log.d("DEBUG", "class " + textview.getClass().getName());
63 |
64 | if ((types & InputType.TYPE_CLASS_NUMBER) == InputType.TYPE_CLASS_NUMBER
65 | || (types & InputType.TYPE_NUMBER_FLAG_DECIMAL) == InputType.TYPE_NUMBER_FLAG_DECIMAL
66 | || (types & InputType.TYPE_NUMBER_FLAG_SIGNED) == InputType.TYPE_NUMBER_FLAG_SIGNED) {
67 | Log.d("DEBUG", "setting number");
68 | message = "23";
69 | }
70 | if ((types & InputType.TYPE_CLASS_TEXT) == InputType.TYPE_CLASS_TEXT) {
71 | Log.d("DEBUG", "setting text");
72 | message = "FuzzingText";
73 | }
74 |
75 | if ((types & InputType.TYPE_DATETIME_VARIATION_NORMAL) == InputType.TYPE_DATETIME_VARIATION_NORMAL
76 | || (types & InputType.TYPE_DATETIME_VARIATION_DATE) == InputType.TYPE_DATETIME_VARIATION_DATE) {
77 | Log.d("DEBUG", "setting date");
78 | message = "01-02-1989";
79 | }
80 |
81 | if ((types & InputType.TYPE_DATETIME_VARIATION_TIME) == InputType.TYPE_DATETIME_VARIATION_TIME) {
82 | Log.d("DEBUG", "setting time");
83 | message = "00:70:07";
84 | }
85 |
86 | if ((types & InputType.TYPE_CLASS_PHONE) == InputType.TYPE_CLASS_PHONE
87 | || hasKeywords(hint, phoneKeywords)
88 | || hasKeywords(resource_id, phoneKeywords)) {
89 | Log.d("DEBUG", "setting phone");
90 | message = "1112341234";
91 | }
92 |
93 | if ((types & InputType.TYPE_TEXT_VARIATION_PERSON_NAME) == InputType.TYPE_TEXT_VARIATION_PERSON_NAME
94 | || hasKeywords(hint, nameKeywords)
95 | || hasKeywords(resource_id, nameKeywords)) {
96 | Log.d("DEBUG", "setting name");
97 | message = "NameFuzzing";
98 | }
99 | if ((types & InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS) == InputType.TYPE_TEXT_VARIATION_POSTAL_ADDRESS
100 | || hasKeywords(hint, zipKeywords)
101 | || hasKeywords(resource_id, zipKeywords)) {
102 | Log.d("DEBUG", "setting postal code");
103 | message = "90210";
104 | }
105 | if ((types & InputType.TYPE_TEXT_VARIATION_URI) == InputType.TYPE_TEXT_VARIATION_URI) {
106 | Log.d("DEBUG", "setting URI");
107 | message = "http://www.fundacionsadosky.org.ar";
108 | }
109 | if ((types & InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS) == InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS
110 | || (types & InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
111 | || hasKeywords(hint, mailKeywords)
112 | || hasKeywords(resource_id, mailKeywords)
113 | || looksLike(hint, EMAIL_PATTERN)) {
114 | message = "fakeemailandroid@gmail.com";
115 | }
116 |
117 | if ((types & InputType.TYPE_NUMBER_VARIATION_PASSWORD) == InputType.TYPE_NUMBER_VARIATION_PASSWORD) {
118 | Log.d("DEBUG", "setting number password");
119 | message = "007007";
120 | } else if ((types & InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD) == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
121 | || (types & InputType.TYPE_TEXT_VARIATION_PASSWORD) == InputType.TYPE_TEXT_VARIATION_PASSWORD
122 | || (types & InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD) == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD
123 | || hasKeywords(hint, passwordKeywords)
124 | || hasKeywords(resource_id, passwordKeywords)) {
125 | Log.d("DEBUG", "setting password");
126 | message = "s3cr3tpass";
127 | }
128 |
129 | return message;
130 |
131 | }
132 |
133 | @Override
134 | public boolean updateView(View view) {
135 | Log.d("DEBUG", "Setting edittext " + EditTextHook.getMessageFor(view));
136 | ((EditText) view).setText(EditTextHook.getMessageFor(view));
137 | view.setFocusable(false);
138 | return true;
139 |
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/src/ar/fsadosky/marvintoqueton/hooks/Hook.java:
--------------------------------------------------------------------------------
1 | package ar.fsadosky.marvintoqueton.hooks;
2 |
3 | import java.lang.reflect.Constructor;
4 | import java.util.HashSet;
5 | import java.util.Set;
6 |
7 | import android.content.Context;
8 | import android.util.AttributeSet;
9 | import android.util.Log;
10 | import android.view.View;
11 | import android.view.View.OnAttachStateChangeListener;
12 | import android.widget.AdapterView;
13 | import android.widget.Button;
14 | import android.widget.CheckBox;
15 | import android.widget.DatePicker;
16 | import android.widget.EditText;
17 | import android.widget.RadioGroup;
18 | import android.widget.Spinner;
19 | import android.widget.TimePicker;
20 | import android.widget.ToggleButton;
21 | import ar.fsadosky.marvintoqueton.Utils;
22 |
23 | import com.saurik.substrate.MS;
24 |
25 | public abstract class Hook {
26 | final static Class hooked[] = { Button.class, CheckBox.class,
27 | EditText.class, RadioGroup.class, Spinner.class, TimePicker.class,
28 | DatePicker.class, ToggleButton.class, AdapterView.class , ViewGroupHook.class };
29 |
30 | public static final int UPDATEVIEW = 0;
31 | public static final int CLEAN_SERVED_VIEWS_TIMER = 1;
32 | public static final int CHANGE_ACTIVITY = 2;
33 |
34 | public static Set dettached_views = new HashSet();
35 | //public static Set already_served_views = new HashSet();
36 |
37 | public abstract boolean updateView(View view);
38 |
39 | public void hook() {
40 | MS.hookClassLoad(getHookedClass(), new MS.ClassLoadHook() {
41 | public void classLoaded(final Class> class_hooked) {
42 | if (getConstructor() != null) {
43 | Log.d("DEBUG", "hooking " + class_hooked.getName());
44 | MS.hookMethod(class_hooked, getConstructor(),
45 | new MS.MethodAlteration