├── .gitignore ├── LICENSE ├── README.md ├── agent ├── build.gradle ├── lint.xml └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── WithSecure │ │ └── dz │ │ ├── Agent.java │ │ ├── EndpointAdapter.java │ │ ├── activities │ │ ├── AboutActivity.java │ │ ├── ConnectorActivity.java │ │ ├── EndpointActivity.java │ │ ├── EndpointSettingsActivity.java │ │ ├── MainActivity.java │ │ ├── ServerActivity.java │ │ ├── SettingsActivity.java │ │ └── StartBroadcastActivity.java │ │ ├── helpers │ │ └── IntentProxyToContentProvider.java │ │ ├── models │ │ ├── EndpointManager.java │ │ └── ServerSettings.java │ │ ├── providers │ │ └── Provider.java │ │ ├── receivers │ │ ├── StartMainActivityReceiver.java │ │ └── StartServiceReceiver.java │ │ ├── service_connectors │ │ ├── ClientServiceConnection.java │ │ ├── IncomingReplyHandler.java │ │ ├── ServerServiceConnection.java │ │ └── SessionServiceConnection.java │ │ ├── services │ │ ├── ClientService.java │ │ ├── ConnectorService.java │ │ ├── ServerService.java │ │ └── SessionService.java │ │ └── views │ │ ├── CheckListItemView.java │ │ ├── ConnectorStatusIndicator.java │ │ ├── EndpointListRowView.java │ │ ├── EndpointListView.java │ │ ├── ServerListRowView.java │ │ └── logger │ │ ├── LogMessageAdapter.java │ │ └── LogMessageRowView.java │ └── res │ ├── drawable-hdpi │ ├── drozer.png │ ├── ic_action_delete.png │ ├── ic_action_edit.png │ ├── ic_action_new.png │ ├── ic_action_online.png │ ├── ic_action_refresh.png │ ├── ic_action_search.png │ ├── ic_action_unknown.png │ ├── ic_input_add.png │ ├── ic_launcher.png │ ├── ic_notification.png │ ├── ic_stat_active.png │ ├── ic_stat_offline.png │ ├── ic_stat_online.png │ └── ic_stat_unknown.png │ ├── drawable-ldpi │ ├── ic_action_delete.png │ ├── ic_action_edit.png │ ├── ic_action_new.png │ ├── ic_action_online.png │ ├── ic_action_refresh.png │ ├── ic_action_unknown.png │ ├── ic_input_add.png │ ├── ic_stat_active.png │ ├── ic_stat_offline.png │ ├── ic_stat_online.png │ └── ic_stat_unknown.png │ ├── drawable-mdpi │ ├── ic_action_delete.png │ ├── ic_action_edit.png │ ├── ic_action_new.png │ ├── ic_action_online.png │ ├── ic_action_refresh.png │ ├── ic_action_search.png │ ├── ic_action_unknown.png │ ├── ic_input_add.png │ ├── ic_launcher.png │ ├── ic_notification.png │ ├── ic_stat_active.png │ ├── ic_stat_offline.png │ ├── ic_stat_online.png │ └── ic_stat_unknown.png │ ├── drawable-xhdpi │ ├── ic_action_delete.png │ ├── ic_action_edit.png │ ├── ic_action_new.png │ ├── ic_action_online.png │ ├── ic_action_refresh.png │ ├── ic_action_search.png │ ├── ic_action_unknown.png │ ├── ic_input_add.png │ ├── ic_launcher.png │ ├── ic_notification.png │ ├── ic_stat_active.png │ ├── ic_stat_offline.png │ ├── ic_stat_online.png │ └── ic_stat_unknown.png │ ├── drawable │ └── ic_stat_connecting.xml │ ├── layout-land │ └── activity_main.xml │ ├── layout-v14 │ ├── toggle_endpoint.xml │ └── toggle_server.xml │ ├── layout │ ├── activity_about.xml │ ├── activity_endpoint.xml │ ├── activity_endpoint_settings.xml │ ├── activity_main.xml │ ├── activity_server.xml │ ├── check_list_item.xml │ ├── list_view_row_endpoint.xml │ ├── list_view_row_log_message.xml │ ├── list_view_row_server.xml │ ├── notification_session.xml │ ├── toggle_endpoint.xml │ └── toggle_server.xml │ ├── menu │ ├── activity_connector.xml │ ├── activity_endpoint_settings.xml │ └── activity_main.xml │ ├── raw │ ├── agent.bks │ └── ca.bks │ ├── values-v11 │ └── styles.xml │ ├── values-v14 │ └── styles.xml │ ├── values │ ├── attrs.xml │ ├── strings.xml │ └── styles.xml │ └── xml │ ├── endpoint_headers.xml │ └── preferences.xml ├── androidlib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── WithSecure │ │ └── androidlib │ │ └── android │ │ └── app │ │ └── NotifyingService.java │ └── res │ ├── drawable │ └── ic_launcher_background.xml │ ├── layout │ └── list_view_row_log_message.xml │ ├── values-v11 │ └── styles.xml │ ├── values-v14 │ └── styles.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── docs ├── Overview.md ├── agent.md └── jsolar.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── jsolar ├── CMakeLists.txt ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── cpp │ └── libmstring │ │ └── mstring.cpp │ ├── java │ └── com │ │ └── WithSecure │ │ └── jsolar │ │ ├── api │ │ ├── APIVersionException.java │ │ ├── DeviceInfo.java │ │ ├── Frame.java │ │ ├── InvalidMessageException.java │ │ ├── UnexpectedMessageException.java │ │ ├── builders │ │ │ ├── MessageFactory.java │ │ │ ├── ReflectionResponseFactory.java │ │ │ ├── SystemRequestFactory.java │ │ │ └── SystemResponseFactory.java │ │ ├── connectors │ │ │ ├── Connection.java │ │ │ ├── Connector.java │ │ │ ├── Endpoint.java │ │ │ ├── EndpointSocketFactory.java │ │ │ ├── Server.java │ │ │ └── ServerSocketFactory.java │ │ ├── handlers │ │ │ ├── MessageHandler.java │ │ │ ├── ReflectionMessageHandler.java │ │ │ └── SystemMessageHandler.java │ │ ├── links │ │ │ ├── Client.java │ │ │ ├── Link.java │ │ │ └── Server.java │ │ ├── sessions │ │ │ ├── Session.java │ │ │ └── SessionCollection.java │ │ └── transport │ │ │ ├── SecureTransport.java │ │ │ ├── SocketTransport.java │ │ │ ├── Transport.java │ │ │ └── TransportDisconnectedException.java │ │ ├── connection │ │ ├── AbstractConnection.java │ │ ├── AbstractLink.java │ │ ├── AbstractSession.java │ │ ├── AbstractSessionCollection.java │ │ └── SecureConnection.java │ │ ├── logger │ │ ├── LogMessage.java │ │ ├── Logger.java │ │ └── OnLogMessageListener.java │ │ ├── reflection │ │ ├── ObjectStore.java │ │ ├── Reflector.java │ │ └── types │ │ │ ├── ReflectedArray.java │ │ │ ├── ReflectedBinary.java │ │ │ ├── ReflectedNull.java │ │ │ ├── ReflectedObject.java │ │ │ ├── ReflectedPrimitive.java │ │ │ ├── ReflectedString.java │ │ │ └── ReflectedType.java │ │ └── util │ │ ├── Shell.java │ │ ├── Strings.java │ │ └── Verify.java │ ├── proto │ └── protobuf.proto │ └── res │ ├── drawable-v24 │ └── ic_launcher_foreground.xml │ ├── drawable │ └── ic_launcher_background.xml │ ├── mipmap-anydpi-v26 │ ├── ic_launcher.xml │ └── ic_launcher_round.xml │ ├── mipmap-hdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-mdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── mipmap-xxxhdpi │ ├── ic_launcher.webp │ └── ic_launcher_round.webp │ ├── values │ ├── colors.xml │ └── strings.xml │ └── xml │ ├── backup_rules.xml │ └── data_extraction_rules.xml ├── settings.gradle └── tlslib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── com │ └── WithSecure │ └── common │ └── tls │ ├── X509Fingerprint.java │ └── trust_managers │ ├── KeyStoreTrustManager.java │ └── NaiveTrustManager.java └── res ├── drawable-hdpi └── ic_launcher.png ├── drawable-mdpi └── ic_launcher.png ├── drawable-xhdpi └── ic_launcher.png ├── values-v11 └── styles.xml ├── values-v14 └── styles.xml └── values ├── strings.xml └── styles.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | /*/*/build/ 3 | build/ 4 | /*/.externalNativeBuild/ 5 | 6 | # Local configuration file (sdk path, etc) 7 | local.properties 8 | 9 | # Gradle generated files 10 | .gradle/ 11 | 12 | # Signing files 13 | .signing/ 14 | 15 | # User-specific configurations 16 | .idea/libraries/ 17 | .idea/workspace.xml 18 | .idea/tasks.xml 19 | .idea/.name 20 | .idea/compiler.xml 21 | .idea/copyright/profiles_settings.xml 22 | .idea/encodings.xml 23 | .idea/misc.xml 24 | .idea/modules.xml 25 | .idea/scopes/scope_settings.xml 26 | .idea/vcs.xml 27 | .idea/ 28 | *.iml 29 | jdiesel/.cxx/ 30 | */.cxx/* -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2024, WithSecure 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | drozer-agent 2 | ====== 3 | 4 | drozer (formerly Mercury) is a leading security testing framework for Android. 5 | 6 | drozer allows you to search for security vulnerabilities in apps and devices by assuming the role of an app and interacting with the Dalvik VM, other apps' IPC endpoints and the underlying OS. 7 | 8 | drozer provides tools to help you use, share and understand public Android exploits. It helps you to deploy a drozer Agent to a device through exploitation or social engineering. Using weasel (MWR's advanced exploitation payload) drozer is able to maximise the permissions available to it by installing a full agent, injecting a limited agent into a running process, or connecting a reverse shell to act as a Remote Access Tool (RAT). 9 | 10 | drozer is open source software, maintained by WithSecure, and can be downloaded from [https://labs.withsecure.com/tools/drozer] 11 | 12 | 13 | Building Using Android Studio 14 | ----------------------------- 15 | 16 | 1. Open Android Studio and launch the Android SDK manager from it (Tools > Android > SDK Manager) 17 | 2. Check that these two components are installed and updated to the latest version. Install or upgrade 18 | them if necessary. 19 | 1. *Android SDK Platform Tools* 20 | 2. *Android Support Library* 21 | 3. *Google Play Services* 22 | 4. *Google Repository* 23 | 5. *Android NDK tools* 24 | 3. Return to Android Studio and select *Import Project* 25 | 4. Select the **drozer-agent** directory 26 | 5. Select "Import from existing model - Gradle" 27 | 28 | **IMPORTANT**: Once imported make sure the project has been synchronized with the Gradle files. 29 | 30 | License 31 | ------- 32 | 33 | drozer is released under a 3-clause BSD License. See LICENSE for full details. 34 | 35 | Contacting the Project 36 | ---------------------- 37 | 38 | drozer is Open Source software, made great by contributions from the community. 39 | 40 | For full source code, to report bugs, or to suggest features and contribute patches please see our Github project: 41 | 42 | [https://github.com/WithSecureLabs/drozer] 43 | -------------------------------------------------------------------------------- /agent/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | namespace 'com.WithSecure.dz' 5 | compileSdkVersion 33 6 | 7 | defaultConfig { 8 | applicationId "com.withsecure.dz" 9 | minSdkVersion 17 10 | targetSdkVersion 33 11 | multiDexEnabled true 12 | } 13 | 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | debuggable true 19 | jniDebuggable true 20 | } 21 | debug { 22 | debuggable true 23 | jniDebuggable true 24 | minifyEnabled false 25 | } 26 | } 27 | 28 | sourceSets { 29 | main { 30 | java.srcDirs = ['src/main/java'] 31 | res.srcDirs = ['src/main/res'] 32 | 33 | } 34 | } 35 | lint { 36 | abortOnError false 37 | checkReleaseBuilds false 38 | } 39 | } 40 | 41 | dependencies { 42 | implementation 'com.android.support:multidex:2.0.1' 43 | implementation 'com.google.android.gms:play-services-safetynet:18.0.1' 44 | implementation 'com.google.android.material:material:1.7.0' 45 | implementation 'androidx.constraintlayout:constraintlayout:2.1.4' 46 | androidTestImplementation 'androidx.test.ext:junit:1.1.4' 47 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' 48 | implementation project(':jsolar') 49 | implementation project(':tlslib') 50 | implementation project(':androidlib') 51 | } 52 | -------------------------------------------------------------------------------- /agent/lint.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/EndpointAdapter.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz; 2 | 3 | import com.WithSecure.dz.models.EndpointManager; 4 | import com.WithSecure.dz.views.EndpointListRowView; 5 | import com.WithSecure.jsolar.api.connectors.Endpoint; 6 | 7 | import android.content.Context; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.BaseAdapter; 11 | 12 | public class EndpointAdapter extends BaseAdapter { 13 | 14 | public interface OnEndpointSelectListener { 15 | 16 | public void onEndpointSelect(Endpoint endpoint); 17 | public void onEndpointToggle(Endpoint endpoint, boolean toggle); 18 | 19 | } 20 | 21 | private Context context = null; 22 | private EndpointManager endpoint_manager = null; 23 | private OnEndpointSelectListener endpoint_listener = null; 24 | 25 | public EndpointAdapter(Context context, EndpointManager endpoint_manager, OnEndpointSelectListener endpoint_listener) { 26 | this.context = context; 27 | this.endpoint_listener = endpoint_listener; 28 | this.endpoint_manager = endpoint_manager; 29 | 30 | this.endpoint_manager.setOnDatasetChangeListener(new EndpointManager.OnDatasetChangeListener() { 31 | 32 | @Override 33 | public void onDatasetChange(EndpointManager manager) { 34 | EndpointAdapter.this.notifyDataSetChanged(); 35 | } 36 | 37 | }); 38 | } 39 | 40 | @Override 41 | public int getCount() { 42 | return this.endpoint_manager.size(); 43 | } 44 | 45 | @Override 46 | public Object getItem(int pos) { 47 | return this.endpoint_manager.all().get(pos); 48 | } 49 | 50 | @Override 51 | public long getItemId(int pos) { 52 | return pos; 53 | } 54 | 55 | @Override 56 | public View getView(int pos, View copyView, ViewGroup parent) { 57 | EndpointListRowView view = new EndpointListRowView(this.context); 58 | view.setEndpoint((Endpoint)this.getItem(pos)); 59 | view.setEndpointListener(this.endpoint_listener); 60 | 61 | return view; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/activities/AboutActivity.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.activities; 2 | 3 | import com.WithSecure.dz.R; 4 | 5 | import android.os.Bundle; 6 | import android.app.Activity; 7 | import android.content.pm.PackageManager.NameNotFoundException; 8 | import android.view.Menu; 9 | import android.widget.TextView; 10 | 11 | public class AboutActivity extends Activity { 12 | 13 | private TextView description; 14 | 15 | private String getVersionName() { 16 | try { 17 | return this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName; 18 | } 19 | catch(NameNotFoundException e) { 20 | throw new RuntimeException(); 21 | } 22 | } 23 | 24 | @Override 25 | protected void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(R.layout.activity_about); 28 | 29 | this.description = (TextView)this.findViewById(R.id.about_description); 30 | this.description.setText(String.format(this.getString(R.string.about_description), this.getVersionName())); 31 | } 32 | 33 | @Override 34 | public boolean onCreateOptionsMenu(Menu menu) { 35 | return false; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/activities/ConnectorActivity.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.activities; 2 | 3 | import java.lang.ref.WeakReference; 4 | 5 | import com.WithSecure.dz.Agent; 6 | import com.WithSecure.dz.R; 7 | import com.WithSecure.jsolar.api.connectors.Connector; 8 | 9 | import android.app.Activity; 10 | import android.app.AlertDialog; 11 | import android.app.Dialog; 12 | import android.content.Context; 13 | import android.content.DialogInterface; 14 | import android.os.Bundle; 15 | import android.os.Handler; 16 | import android.os.Message; 17 | import android.view.Menu; 18 | import android.view.MenuItem; 19 | 20 | public abstract class ConnectorActivity extends Activity { 21 | 22 | public static class IncomingFingerprintHandler extends Handler { 23 | 24 | private final WeakReference context; 25 | 26 | public IncomingFingerprintHandler(Context context) { 27 | this.context = new WeakReference(context); 28 | } 29 | 30 | @Override 31 | public void handleMessage(Message msg) { 32 | ConnectorActivity context = (ConnectorActivity)this.context.get(); 33 | Bundle data = msg.getData(); 34 | 35 | if(data.getString(Connector.CONNECTOR_SSL_FINGERPRINT) != null) 36 | context.receiveFingerprint(data.getString(Connector.CONNECTOR_SSL_FINGERPRINT)); 37 | else 38 | context.receiveFingerprint(context.getString(R.string.ssl_no_fingerprint)); 39 | } 40 | 41 | } 42 | 43 | protected Dialog createInformationDialog(int titleId, int messageId) { 44 | return new AlertDialog.Builder(this) 45 | .setTitle(titleId) 46 | .setMessage(messageId) 47 | .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() { 48 | 49 | public void onClick(DialogInterface dialog, int id) {} 50 | 51 | }) 52 | .create(); 53 | } 54 | 55 | protected Dialog createInformationDialog(int titleId, String message) { 56 | return new AlertDialog.Builder(this) 57 | .setTitle(titleId) 58 | .setMessage(message) 59 | .setNeutralButton(R.string.ok, new DialogInterface.OnClickListener() { 60 | 61 | public void onClick(DialogInterface dialog, int id) {} 62 | 63 | }) 64 | .create(); 65 | } 66 | 67 | @Override 68 | public boolean onCreateOptionsMenu(Menu menu) { 69 | getMenuInflater().inflate(R.menu.activity_connector, menu); 70 | return true; 71 | } 72 | 73 | @Override 74 | public boolean onOptionsItemSelected(MenuItem item) { 75 | switch(item.getItemId()) { 76 | case R.id.show_fingerprint: 77 | this.showFingerprintDialog(); 78 | return true; 79 | 80 | case R.id.refresh_status: 81 | this.refreshStatus(); 82 | return true; 83 | 84 | default: 85 | return super.onOptionsItemSelected(item); 86 | } 87 | } 88 | 89 | @Override 90 | protected void onPause() { 91 | super.onPause(); 92 | 93 | Agent.getInstance().unbindServices(); 94 | } 95 | 96 | @Override 97 | protected void onResume() { 98 | super.onResume(); 99 | 100 | Agent.getInstance().bindServices(); 101 | } 102 | 103 | public abstract void receiveFingerprint(String fingerprint); 104 | protected abstract void refreshStatus(); 105 | protected abstract void showFingerprintDialog(); 106 | 107 | } 108 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/activities/StartBroadcastActivity.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.activities; 2 | 3 | import android.app.Activity; 4 | import android.content.ComponentName; 5 | import android.content.Intent; 6 | import android.os.Bundle; 7 | import android.os.Parcelable; 8 | import android.util.Log; 9 | 10 | import java.util.ArrayList; 11 | 12 | public class StartBroadcastActivity extends Activity { 13 | 14 | public void onCreate(Bundle bundle) { 15 | super.onCreate(bundle); 16 | startChooser(getIntent()); 17 | finish(); 18 | } 19 | 20 | /* access modifiers changed from: protected */ 21 | public void onResume() { 22 | super.onResume(); 23 | } 24 | 25 | /* access modifiers changed from: protected */ 26 | public void onDestroy() { 27 | super.onDestroy(); 28 | } 29 | 30 | /* access modifiers changed from: protected */ 31 | public void onRestart() { 32 | super.onRestart(); 33 | } 34 | 35 | /* access modifiers changed from: protected */ 36 | public void onPause() { 37 | super.onPause(); 38 | } 39 | 40 | private void startChooser(Intent intent) { 41 | if (intent != null && intent.getExtras().containsKey("yayintentyay")) { 42 | try { 43 | ArrayList arrayList = new ArrayList<>(); 44 | arrayList.add(new ComponentName(this.getPackageName(), StartBroadcastActivity.class.getName())); 45 | 46 | Intent yayparcelableyay = intent.getParcelableExtra("yayintentyay"); 47 | Intent createChooser = Intent.createChooser((Intent) yayparcelableyay, "Share"); 48 | 49 | createChooser.putExtra("android.intent.extra.EXCLUDE_COMPONENTS", (Parcelable[]) arrayList.toArray(new Parcelable[0])); 50 | 51 | createChooser.setComponent(yayparcelableyay.getComponent()); 52 | createChooser.putExtras(yayparcelableyay.getExtras()); 53 | createChooser.setAction(yayparcelableyay.getAction()); 54 | 55 | hooking(createChooser); 56 | 57 | startActivity(createChooser); 58 | } catch (Exception e) { 59 | Log.d("yaytagyay", e.getMessage()); 60 | } 61 | } 62 | } 63 | 64 | private void hooking(Intent intent){ 65 | Log.i("yaytagyay", "intent"); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/helpers/IntentProxyToContentProvider.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.helpers; 2 | 3 | import android.app.Activity; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | 7 | import java.io.File; 8 | import java.io.FileNotFoundException; 9 | import java.io.FileOutputStream; 10 | import java.io.InputStream; 11 | 12 | public class IntentProxyToContentProvider extends Activity { 13 | 14 | // This class is meant to help download files from unexported Content Providers 15 | // Assuming the unexported Content Provider has GrantURIPermissions set to True 16 | // Make sure the victim app is calling this activity 17 | // 18 | // Example of what the victim app should be doing: 19 | // Intent intent = new Intent(); 20 | // intent.setComponent(new ComponentName("com.mwr.dz", "com.mwr.dz.helpers.IntentProxyToContentProvider"); 21 | // intent.setFlags(195); 22 | // intent.setData(Uri.parse("content://"); 23 | // startActivity(intent); 24 | // 25 | // Any file downloaded will be saved to Drozer's private file directory 26 | // /data/data/com.mwr.dz/files/ 27 | 28 | String filename = "yayoutputyay"; // save file as "yayoutputyay" 29 | 30 | protected void onCreate(Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | Uri uri = Uri.parse(getIntent().getDataString()); // Get the Uri for the unexported content provider 33 | if (getIntent().getStringExtra("filename") != null) { 34 | filename = getIntent().getStringExtra("filename"); // if intent has String extra "filename", save file as this name 35 | } 36 | try { 37 | InputStream input = getContentResolver().openInputStream(uri); // Reach out to the unexported Content Provider 38 | File file = new File(getFilesDir(), filename); // make local file 39 | FileOutputStream output = new FileOutputStream(file); // also make local file 40 | try { 41 | byte[] buf = new byte[1024]; 42 | int len; 43 | while ((len = input.read(buf)) > 0) { 44 | output.write(buf, 0, len); // write local file from the file pulled from content provider 45 | } 46 | } catch (Exception e) { 47 | e.printStackTrace(); 48 | } finally { 49 | try { 50 | if (input != null) 51 | input.close(); 52 | if (output != null) 53 | output.close(); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | } 58 | } catch (FileNotFoundException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/models/ServerSettings.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.models; 2 | 3 | import android.content.SharedPreferences; 4 | import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 5 | 6 | import com.WithSecure.dz.Agent; 7 | import com.WithSecure.jsolar.api.connectors.Server; 8 | 9 | public class ServerSettings implements OnSharedPreferenceChangeListener { 10 | 11 | private Server server; 12 | 13 | private char[] getKeyPassword() { 14 | return this.getSettings().getString(Server.SERVER_KEY_PASSWORD, "drozer").toCharArray(); 15 | } 16 | 17 | private char[] getKeyStorePassword() { 18 | return this.getSettings().getString(Server.SERVER_KEYSTORE_PASSWORD, "drozer").toCharArray(); 19 | } 20 | 21 | private String getKeyStorePath() { 22 | return this.getSettings().getString(Server.SERVER_KEYSTORE_PATH, "/data/data/com.withsecure.dz/files/drozer.bks"); 23 | } 24 | 25 | private String getPassword() { 26 | return this.getSettings().getString(Server.SERVER_PASSWORD, ""); 27 | } 28 | 29 | private int getPort() { 30 | return Integer.parseInt(this.getSettings().getString(Server.SERVER_PORT, "31415")); 31 | } 32 | 33 | private SharedPreferences getSettings() { 34 | return Agent.getInstance().getSettings(); 35 | } 36 | 37 | private boolean isSSL() { 38 | return this.getSettings().getBoolean(Server.SERVER_SSL, false); 39 | } 40 | 41 | public void load(Server server) { 42 | this.server = server; 43 | 44 | server.setPort(this.getPort()); 45 | server.setPassword(this.getPassword()); 46 | server.setSSL(this.isSSL()); 47 | 48 | if(this.isSSL()) { 49 | server.setSSL(this.isSSL()); 50 | server.setKeyStorePath(this.getKeyStorePath()); 51 | server.setKeyStorePassword(this.getKeyStorePassword()); 52 | server.setKeyPassword(this.getKeyPassword()); 53 | } 54 | 55 | server.resetKeyManagerFactory(); 56 | 57 | this.getSettings().registerOnSharedPreferenceChangeListener(this); 58 | } 59 | 60 | @Override 61 | public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 62 | if(key.equals(Server.SERVER_PORT)) 63 | this.server.setPort(this.getPort()); 64 | if(key.equals(Server.SERVER_PASSWORD)) 65 | this.server.setPassword(this.getPassword()); 66 | 67 | if(key.equals(Server.SERVER_SSL)) { 68 | this.server.setSSL(this.isSSL()); 69 | server.setKeyStorePath(this.getKeyStorePath()); 70 | server.setKeyStorePassword(this.getKeyStorePassword()); 71 | server.setKeyPassword(this.getKeyPassword()); 72 | } 73 | 74 | if(key.equals(Server.SERVER_KEYSTORE_PATH)) 75 | server.setKeyStorePath(this.getKeyStorePath()); 76 | if(key.equals(Server.SERVER_KEYSTORE_PASSWORD)) 77 | server.setKeyStorePassword(this.getKeyStorePassword()); 78 | if(key.equals(Server.SERVER_KEY_PASSWORD)) 79 | server.setKeyPassword(this.getKeyPassword()); 80 | } 81 | 82 | public boolean save(Server server) { 83 | SharedPreferences.Editor editor = Agent.getInstance().getSettings().edit(); 84 | 85 | editor.remove(Server.SERVER_PORT); 86 | editor.putString(Server.SERVER_PORT, Integer.valueOf(this.getPort()).toString()); 87 | 88 | return editor.commit(); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/providers/Provider.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.providers; 2 | 3 | import android.content.ComponentName; 4 | import android.content.ContentProvider; 5 | import android.content.ContentValues; 6 | import android.content.Context; 7 | import android.content.Intent; 8 | import android.database.Cursor; 9 | import android.net.Uri; 10 | import android.util.Log; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.annotation.Nullable; 14 | 15 | public class Provider extends ContentProvider { 16 | 17 | 18 | @Override 19 | public boolean onCreate() { 20 | return false; 21 | } 22 | 23 | @Nullable 24 | @Override 25 | public Cursor query(@NonNull Uri uri, @Nullable String[] strings, @Nullable String s, @Nullable String[] strings1, @Nullable String s1) { 26 | Context context = this.getContext(); 27 | Intent yayintentyay = new Intent("android.intent.action.MAIN"); 28 | ComponentName yaycnyay = new ComponentName(context.getPackageName(), "com.WithSecure.dz.activities.MainActivity"); 29 | yayintentyay.setComponent(yaycnyay); 30 | yayintentyay.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 31 | try { 32 | context.startActivity(yayintentyay); 33 | } catch (Exception e) { 34 | Log.d("yaytagyay", e.getMessage()); 35 | } 36 | return null; 37 | } 38 | 39 | @Nullable 40 | @Override 41 | public String getType(@NonNull Uri uri) { 42 | return null; 43 | } 44 | 45 | @Nullable 46 | @Override 47 | public Uri insert(@NonNull Uri uri, @Nullable ContentValues contentValues) { 48 | return null; 49 | } 50 | 51 | @Override 52 | public int delete(@NonNull Uri uri, @Nullable String s, @Nullable String[] strings) { 53 | return 0; 54 | } 55 | 56 | @Override 57 | public int update(@NonNull Uri uri, @Nullable ContentValues contentValues, @Nullable String s, @Nullable String[] strings) { 58 | return 0; 59 | } 60 | } -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/receivers/StartMainActivityReceiver.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.receivers; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.util.Log; 8 | 9 | public class StartMainActivityReceiver extends BroadcastReceiver { 10 | 11 | @Override 12 | public void onReceive(Context context, Intent intent) { 13 | Intent yayintentyay = new Intent("android.intent.action.MAIN"); 14 | ComponentName yaycnyay = new ComponentName(context.getPackageName(), "com.WithSecure.dz.activities.MainActivity"); 15 | yayintentyay.setComponent(yaycnyay); 16 | yayintentyay.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 17 | try { 18 | context.startActivity(yayintentyay); 19 | } catch (Exception e) { 20 | Log.d("yaytagyay", e.getMessage()); 21 | } 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/receivers/StartServiceReceiver.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.receivers; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.ComponentName; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | 8 | public class StartServiceReceiver extends BroadcastReceiver { 9 | 10 | public static final String PWN_INTENT = "com.withsecure.dz.PWN"; 11 | 12 | @Override 13 | public void onReceive(Context context, Intent intent) { 14 | Intent start_service = new Intent(); 15 | start_service.putExtras(intent); 16 | 17 | if(intent.getCategories().contains("com.WithSecure.dz.START_EMBEDDED")) { 18 | start_service.addCategory("com.WithSecure.dz.START_EMBEDDED"); 19 | start_service.setComponent(new ComponentName(context.getPackageName(), "com.WithSecure.dz.services.ServerService")); 20 | } 21 | else { 22 | if(intent.getCategories().contains("com.WithSecure.dz.CREATE_ENDPOINT")) 23 | start_service.addCategory("com.WithSecure.dz.CREATE_ENDPOINT"); 24 | if(intent.getCategories().contains("com.WithSecure.dz.START_ENDPOINT")) 25 | start_service.addCategory("com.WithSecure.dz.START_ENDPOINT"); 26 | 27 | start_service.setComponent(new ComponentName(context.getPackageName(), "com.WithSecure.dz.services.ClientService")); 28 | } 29 | 30 | context.startService(start_service); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/service_connectors/ClientServiceConnection.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.service_connectors; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.ServiceConnection; 6 | import android.os.Bundle; 7 | import android.os.IBinder; 8 | import android.os.Message; 9 | import android.os.Messenger; 10 | import android.os.RemoteException; 11 | import android.util.Log; 12 | 13 | import com.WithSecure.dz.Agent; 14 | import com.WithSecure.dz.services.ClientService; 15 | import com.WithSecure.jsolar.api.connectors.Endpoint; 16 | 17 | public class ClientServiceConnection implements ServiceConnection { 18 | 19 | private Messenger service = null; 20 | private boolean bound = false; 21 | 22 | public boolean isBound() { 23 | return this.bound; 24 | } 25 | 26 | public void getDetailedEndpointStatus(int id, Messenger replyTo) throws RemoteException { 27 | Bundle data = new Bundle(); 28 | 29 | data.putInt(Endpoint.ENDPOINT_ID, id); 30 | 31 | Message msg = Message.obtain(null, ClientService.MSG_GET_DETAILED_ENDPOINT_STATUS); 32 | msg.replyTo = Agent.getInstance().getMessenger(); 33 | msg.setData(data); 34 | 35 | this.send(msg); 36 | } 37 | 38 | public void getEndpointStatuses(Messenger replyTo) throws RemoteException { 39 | Message msg = Message.obtain(null, ClientService.MSG_GET_ENDPOINTS_STATUS); 40 | msg.replyTo = replyTo; 41 | 42 | this.send(msg); 43 | } 44 | 45 | public void getPeerFingerprint(int id, Messenger replyTo) throws RemoteException { 46 | Bundle data = new Bundle(); 47 | data.putBoolean("ctrl:no_cache_messenger", true); 48 | data.putInt(Endpoint.ENDPOINT_ID, id); 49 | 50 | Message msg = Message.obtain(null, ClientService.MSG_GET_SSL_FINGERPRINT); 51 | msg.replyTo = replyTo; 52 | msg.setData(data); 53 | 54 | this.send(msg); 55 | } 56 | 57 | @Override 58 | public void onServiceConnected(ComponentName className, IBinder service) { 59 | this.service = new Messenger(service); 60 | this.bound = true; 61 | 62 | if(Agent.getInstance().getSettings().getBoolean("restore_after_crash", true)){ 63 | for(Endpoint e : Agent.getInstance().getEndpointManager().all()){ 64 | if(e.isActive()){ 65 | try { 66 | Log.d("ClientService", "Resuming connection to endpoint..."); 67 | Agent.getInstance().getClientService().startEndpoint(e, Agent.getInstance().getMessenger()); 68 | } catch (RemoteException re) { 69 | re.printStackTrace(); 70 | } 71 | } 72 | } 73 | } 74 | 75 | } 76 | 77 | @Override 78 | public void onServiceDisconnected(ComponentName className) { 79 | this.service = null; 80 | this.bound = false; 81 | } 82 | 83 | protected void send(Message msg) throws RemoteException { 84 | this.service.send(msg); 85 | } 86 | 87 | public void startEndpoint(Endpoint endpoint, Messenger replyTo) throws RemoteException { 88 | Bundle data = new Bundle(); 89 | data.putInt(Endpoint.ENDPOINT_ID, endpoint.getId()); 90 | 91 | Message msg = Message.obtain(null, ClientService.MSG_START_ENDPOINT); 92 | msg.replyTo = replyTo; 93 | msg.setData(data); 94 | 95 | this.send(msg); 96 | 97 | endpoint.enabled = true; 98 | endpoint.notifyObservers(); 99 | } 100 | 101 | public void stopEndpoint(Endpoint endpoint, Messenger replyTo) throws RemoteException { 102 | Bundle data = new Bundle(); 103 | 104 | data.putInt(Endpoint.ENDPOINT_ID, endpoint.getId()); 105 | 106 | Message msg = Message.obtain(null, ClientService.MSG_STOP_ENDPOINT); 107 | msg.replyTo = replyTo; 108 | msg.setData(data); 109 | 110 | this.send(msg); 111 | 112 | endpoint.enabled = false; 113 | endpoint.notifyObservers(); 114 | } 115 | 116 | public void unbind(Context context) { 117 | if(this.bound) { 118 | context.unbindService(this); 119 | this.bound = false; 120 | } 121 | } 122 | 123 | } 124 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/service_connectors/IncomingReplyHandler.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.service_connectors; 2 | 3 | import java.lang.ref.WeakReference; 4 | 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.Message; 8 | 9 | import com.WithSecure.dz.Agent; 10 | import com.WithSecure.dz.services.ClientService; 11 | import com.WithSecure.dz.services.ConnectorService; 12 | import com.WithSecure.dz.services.ServerService; 13 | import com.WithSecure.jsolar.api.connectors.Connector; 14 | import com.WithSecure.jsolar.api.connectors.Endpoint; 15 | import com.WithSecure.jsolar.logger.LogMessage; 16 | 17 | public class IncomingReplyHandler extends Handler { 18 | 19 | private final WeakReference agent; 20 | 21 | public IncomingReplyHandler(Agent agent) { 22 | this.agent = new WeakReference(agent); 23 | } 24 | 25 | @Override 26 | public void handleMessage(Message msg) { 27 | Agent agent = this.agent.get(); 28 | Bundle data = msg.getData(); 29 | 30 | switch(msg.what) { 31 | case ClientService.MSG_GET_DETAILED_ENDPOINT_STATUS: 32 | agent.getEndpointManager().get(data.getInt(Endpoint.ENDPOINT_ID)).setDetailedStatus(data); 33 | break; 34 | 35 | case ClientService.MSG_GET_ENDPOINTS_STATUS: 36 | for(Endpoint e : agent.getEndpointManager().all()) 37 | if(data.containsKey("endpoint-" + e.getId())) 38 | e.setStatus(Endpoint.Status.values()[data.getInt("endpoint-" + e.getId())]); 39 | break; 40 | 41 | case ServerService.MSG_GET_DETAILED_SERVER_STATUS: 42 | agent.getServerParameters().setDetailedStatus(data); 43 | break; 44 | 45 | case ServerService.MSG_GET_SERVER_STATUS: 46 | agent.getServerParameters().setStatus(Connector.Status.values()[data.getInt("server")]); 47 | break; 48 | 49 | case ConnectorService.MSG_LOG_MESSAGE: 50 | LogMessage log_message = new LogMessage(data.getBundle(Connector.CONNECTOR_LOG_MESSAGE)); 51 | if (data.containsKey(Endpoint.ENDPOINT_ID)) 52 | agent.getEndpointManager().get(data.getInt(Endpoint.ENDPOINT_ID)).getLogger().log(log_message); 53 | else 54 | agent.getServerParameters().getLogger().log(log_message); 55 | break; 56 | 57 | default: 58 | super.handleMessage(msg); 59 | } 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/service_connectors/ServerServiceConnection.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.service_connectors; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.ServiceConnection; 6 | import android.content.SharedPreferences.Editor; 7 | import android.os.Bundle; 8 | import android.os.IBinder; 9 | import android.os.Message; 10 | import android.os.Messenger; 11 | import android.os.RemoteException; 12 | 13 | import com.WithSecure.dz.Agent; 14 | import com.WithSecure.dz.services.ServerService; 15 | import com.WithSecure.jsolar.api.connectors.Server; 16 | 17 | public class ServerServiceConnection implements ServiceConnection { 18 | 19 | private Messenger service = null; 20 | private boolean bound = false; 21 | 22 | public void getDetailedServerStatus(Messenger replyTo) throws RemoteException { 23 | Message msg = Message.obtain(null, ServerService.MSG_GET_DETAILED_SERVER_STATUS); 24 | msg.replyTo = replyTo; 25 | 26 | this.send(msg); 27 | } 28 | 29 | public void getHostFingerprint(Messenger replyTo) throws RemoteException { 30 | Bundle data = new Bundle(); 31 | data.putBoolean("ctrl:no_cache_messenger", true); 32 | 33 | Message msg = Message.obtain(null, ServerService.MSG_GET_SSL_FINGERPRINT); 34 | msg.replyTo = replyTo; 35 | msg.setData(data); 36 | 37 | this.send(msg); 38 | } 39 | 40 | public void getServerStatus(Messenger replyTo) throws RemoteException { 41 | Message msg = Message.obtain(null, ServerService.MSG_GET_SERVER_STATUS); 42 | msg.replyTo = replyTo; 43 | 44 | this.send(msg); 45 | } 46 | 47 | public boolean isBound() { 48 | return this.bound; 49 | } 50 | 51 | @Override 52 | public void onServiceConnected(ComponentName className, IBinder service) { 53 | this.service = new Messenger(service); 54 | this.bound = true; 55 | if(Agent.getInstance().getSettings().getBoolean("localServerEnabled", false) && Agent.getInstance().getSettings().getBoolean("restore_after_crash", true)){ 56 | try { 57 | ServerServiceConnection ssc = Agent.getInstance().getServerService(); 58 | Server server = Agent.getInstance().getServerParameters(); 59 | Messenger messenger = Agent.getInstance().getMessenger(); 60 | 61 | ssc.startServer(server, messenger); 62 | } catch (RemoteException e) { 63 | e.printStackTrace(); 64 | } 65 | } 66 | } 67 | 68 | @Override 69 | public void onServiceDisconnected(ComponentName className) { 70 | this.service = null; 71 | this.bound = false; 72 | } 73 | 74 | protected void send(Message msg) throws RemoteException { 75 | this.service.send(msg); 76 | } 77 | 78 | public void startServer(Server server, Messenger replyTo) throws RemoteException { 79 | Message msg = Message.obtain(null, ServerService.MSG_START_SERVER); 80 | msg.replyTo = replyTo; 81 | 82 | this.send(msg); 83 | 84 | Editor edit = Agent.getInstance().getSettings().edit(); 85 | edit.putBoolean("localServerEnabled", true); 86 | edit.apply(); 87 | 88 | server.enabled = true; 89 | server.notifyObservers(); 90 | } 91 | 92 | public void stopServer(Server server, Messenger replyTo) throws RemoteException { 93 | Message msg = Message.obtain(null, ServerService.MSG_STOP_SERVER); 94 | msg.replyTo = replyTo; 95 | 96 | this.send(msg); 97 | 98 | Editor edit = Agent.getInstance().getSettings().edit(); 99 | edit.putBoolean("localServerEnabled", false); 100 | edit.apply(); 101 | 102 | server.enabled = false; 103 | server.notifyObservers(); 104 | } 105 | 106 | public void unbind(Context context) { 107 | if(this.bound) { 108 | context.unbindService(this); 109 | this.bound = false; 110 | } 111 | } 112 | 113 | } 114 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/service_connectors/SessionServiceConnection.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.service_connectors; 2 | 3 | import android.content.ComponentName; 4 | import android.content.Context; 5 | import android.content.ServiceConnection; 6 | import android.os.IBinder; 7 | import android.os.Messenger; 8 | import android.os.RemoteException; 9 | 10 | import com.WithSecure.dz.services.SessionService; 11 | 12 | public class SessionServiceConnection implements ServiceConnection { 13 | 14 | private Messenger service = null; 15 | private boolean bound = false; 16 | 17 | public boolean isBound() { 18 | return this.bound; 19 | } 20 | 21 | public void notifySessionStarted(String sessionId) { 22 | try { 23 | this.send(android.os.Message.obtain(null, SessionService.MSG_START_SESSION, sessionId)); 24 | } 25 | catch(RemoteException e) {} 26 | } 27 | 28 | public void notifySessionStopped(String sessionId) { 29 | try { 30 | this.send(android.os.Message.obtain(null, SessionService.MSG_STOP_SESSION, sessionId)); 31 | } 32 | catch(RemoteException e) {} 33 | } 34 | 35 | @Override 36 | public void onServiceConnected(ComponentName className, IBinder service) { 37 | this.service = new Messenger(service); 38 | this.bound = true; 39 | } 40 | 41 | @Override 42 | public void onServiceDisconnected(ComponentName className) { 43 | this.service = null; 44 | this.bound = false; 45 | } 46 | 47 | public void send(android.os.Message msg) throws RemoteException { 48 | this.service.send(msg); 49 | } 50 | 51 | public void unbind(Context context) { 52 | if(this.bound) { 53 | context.unbindService(this); 54 | this.bound = false; 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/services/ConnectorService.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.services; 2 | 3 | import java.lang.ref.WeakReference; 4 | import java.util.ArrayList; 5 | 6 | import com.WithSecure.jsolar.api.connectors.Connector; 7 | import com.WithSecure.jsolar.api.connectors.Endpoint; 8 | import com.WithSecure.jsolar.logger.LogMessage; 9 | import com.WithSecure.jsolar.logger.Logger; 10 | import com.WithSecure.jsolar.logger.OnLogMessageListener; 11 | 12 | import android.app.Service; 13 | import android.content.Intent; 14 | import android.os.Bundle; 15 | import android.os.Handler; 16 | import android.os.IBinder; 17 | import android.os.Message; 18 | import android.os.Messenger; 19 | import android.os.RemoteException; 20 | 21 | public abstract class ConnectorService extends Service implements OnLogMessageListener { 22 | 23 | public static final int MSG_LOG_MESSAGE = 1; 24 | 25 | /** 26 | * IncomingHandler is used to process all messages received by the 27 | * ConnectorService. It stores a reference to the incoming messenger (if 28 | * applicable) and hands the message off to the implementation for 29 | * processing. 30 | */ 31 | private static class IncomingHandler extends Handler { 32 | 33 | private final WeakReference service; 34 | 35 | public IncomingHandler(ConnectorService service) { 36 | this.service = new WeakReference(service); 37 | } 38 | 39 | @Override 40 | public void handleMessage(Message msg) { 41 | Bundle data = msg.getData(); 42 | ConnectorService service = this.service.get(); 43 | 44 | if(data == null || !data.getBoolean("ctrl:no_cache_messenger")) 45 | service.cacheMessenger(msg.replyTo); 46 | 47 | service.handleMessage(msg); 48 | } 49 | 50 | } 51 | 52 | private final Messenger messenger = new Messenger(new IncomingHandler(this)); 53 | private final ArrayList messengers = new ArrayList(); 54 | protected static boolean running = false; 55 | 56 | /** 57 | * Broadcasts a bundle of data, as a log message, to every messenger that has 58 | * previously sent us a message. 59 | */ 60 | protected void broadcastLogMessageBundle(Bundle data) { 61 | Message message = Message.obtain(null, ConnectorService.MSG_LOG_MESSAGE); 62 | message.setData(data); 63 | 64 | this.sendToAllMessengers(message); 65 | } 66 | 67 | /** 68 | * Stores a reference to a Messenger, if we haven't already stored it. 69 | */ 70 | public void cacheMessenger(Messenger messenger) { 71 | if(!this.messengers.contains(messenger)) 72 | this.messengers.add(messenger); 73 | } 74 | 75 | /** 76 | * handleMessage() is handed every message that is passed to this service, 77 | * to process and send any replies. 78 | * 79 | * Override in an implementation of Connector service. 80 | */ 81 | public abstract void handleMessage(Message msg); 82 | 83 | @Override 84 | public IBinder onBind(Intent intent) { 85 | return this.messenger.getBinder(); 86 | } 87 | 88 | @Override 89 | public void onLogMessage(Logger logger, LogMessage message) { 90 | Bundle data = new Bundle(); 91 | data.putBundle(Connector.CONNECTOR_LOG_MESSAGE, message.toBundle()); 92 | 93 | Connector connector = logger.getOwner(); 94 | 95 | if(connector instanceof Endpoint) 96 | data.putInt(Endpoint.ENDPOINT_ID, ((Endpoint)connector).getId()); 97 | this.broadcastLogMessageBundle(data); 98 | } 99 | 100 | @Override 101 | public int onStartCommand(Intent intent, int flags, int startId) { 102 | return START_REDELIVER_INTENT; 103 | } 104 | 105 | /** 106 | * Attempt to deliver a Message to all messengers that have previously sent 107 | * a message to this service, without specifying not to cache their handle. 108 | */ 109 | protected void sendToAllMessengers(Message msg) { 110 | for(Messenger m : this.messengers) { 111 | try { 112 | m.send(msg); 113 | } 114 | catch(RemoteException e) {} 115 | } 116 | } 117 | 118 | } 119 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/services/SessionService.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.services; 2 | 3 | import java.lang.ref.WeakReference; 4 | import java.util.HashSet; 5 | 6 | import android.app.PendingIntent; 7 | import android.content.Context; 8 | import android.content.Intent; 9 | import android.content.ServiceConnection; 10 | import android.os.Handler; 11 | import android.os.IBinder; 12 | import android.os.Message; 13 | import android.os.Messenger; 14 | import android.widget.RemoteViews; 15 | 16 | import com.WithSecure.androidlib.android.app.NotifyingService; 17 | import com.WithSecure.dz.R; 18 | import com.WithSecure.dz.activities.MainActivity; 19 | 20 | public class SessionService extends NotifyingService { 21 | 22 | public static final int MSG_START_SESSION = 1; 23 | public static final int MSG_STOP_SESSION = 2; 24 | 25 | private final Messenger messenger = new Messenger(new IncomingHandler(this)); 26 | private static boolean running = false; 27 | private HashSet sessions = new HashSet(); 28 | 29 | static class IncomingHandler extends Handler { 30 | 31 | private final WeakReference service; 32 | 33 | public IncomingHandler(SessionService service) { 34 | this.service = new WeakReference(service); 35 | } 36 | 37 | @Override 38 | public void handleMessage(Message msg) { 39 | SessionService service = this.service.get(); 40 | String session_id = (String)msg.obj; 41 | 42 | switch(msg.what) { 43 | case MSG_START_SESSION: 44 | service.add(session_id); 45 | 46 | service.updateNotification(); 47 | break; 48 | 49 | case MSG_STOP_SESSION: 50 | service.remove(session_id); 51 | 52 | service.updateNotification(); 53 | break; 54 | 55 | default: 56 | super.handleMessage(msg); 57 | } 58 | } 59 | 60 | } 61 | 62 | public void add(String session_id) { 63 | this.sessions.add(session_id); 64 | } 65 | 66 | @Override 67 | public IBinder onBind(Intent arg0) { 68 | return this.messenger.getBinder(); 69 | } 70 | 71 | @Override 72 | public void onCreate() { 73 | super.onCreate(); 74 | 75 | SessionService.running = true; 76 | } 77 | 78 | @Override 79 | public void onDestroy() { 80 | SessionService.running = false; 81 | } 82 | 83 | @Override 84 | protected void onCreateNotification(RemoteViews view) { 85 | view.setImageViewResource(R.id.cs_notification_icon, R.drawable.ic_notification); 86 | view.setTextViewText(R.id.cs_notification_ticker, getString(R.string.session_connected)); 87 | } 88 | 89 | public void remove(String session_id) { 90 | this.sessions.remove(session_id); 91 | } 92 | 93 | public static void startAndBindToService(Context context, ServiceConnection serviceConnection) { 94 | if(!SessionService.running) 95 | context.startService(new Intent(context, SessionService.class)); 96 | 97 | Intent intent = new Intent(context, SessionService.class); 98 | context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); 99 | } 100 | 101 | private void updateNotification() { 102 | if(!this.sessions.isEmpty()) 103 | this.showNotification(this.getString(R.string.app_name), R.layout.notification_session, R.drawable.ic_notification, PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0)); 104 | else 105 | this.hideNotification(this.getString(R.string.app_name), R.layout.notification_session); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/CheckListItemView.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views; 2 | 3 | import com.WithSecure.dz.R; 4 | 5 | import android.content.Context; 6 | import android.content.res.TypedArray; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | import android.widget.LinearLayout; 11 | import android.widget.TextView; 12 | 13 | public class CheckListItemView extends LinearLayout { 14 | 15 | private TextView label = null; 16 | private ImageView status = null; 17 | 18 | public CheckListItemView(Context context) { 19 | super(context); 20 | 21 | this.setUpView(); 22 | } 23 | 24 | public CheckListItemView(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | 27 | this.setUpView(); 28 | 29 | TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CheckListItemView); 30 | 31 | this.setLabel(a.getString(R.styleable.CheckListItemView_text)); 32 | this.setStatus(a.getBoolean(R.styleable.CheckListItemView_defaultValue, false)); 33 | 34 | a.recycle(); 35 | } 36 | 37 | public void setLabel(int resId) { 38 | this.setLabel(this.getContext().getString(resId)); 39 | } 40 | 41 | public void setLabel(String text) { 42 | this.label.setText(text); 43 | } 44 | 45 | public void setStatus(boolean status) { 46 | this.status.setImageResource(status ? android.R.drawable.button_onoff_indicator_on : android.R.drawable.button_onoff_indicator_off); 47 | } 48 | 49 | private void setUpView() { 50 | this.addView(View.inflate(this.getContext(), R.layout.check_list_item, null)); 51 | 52 | this.label = (TextView)this.findViewById(R.id.check_list_item_label); 53 | this.status = (ImageView)this.findViewById(R.id.check_list_item_status); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/ConnectorStatusIndicator.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views; 2 | 3 | import java.util.Observable; 4 | import java.util.Observer; 5 | 6 | import com.WithSecure.dz.R; 7 | import com.WithSecure.jsolar.api.connectors.Connector; 8 | 9 | import android.content.Context; 10 | import android.graphics.drawable.AnimationDrawable; 11 | import android.util.AttributeSet; 12 | import android.view.Gravity; 13 | import android.widget.ImageView; 14 | import android.widget.LinearLayout; 15 | 16 | public class ConnectorStatusIndicator extends LinearLayout implements Observer { 17 | 18 | private AnimationDrawable animation = null; 19 | private Connector connector_parameters = null; 20 | private ImageView status_image = null; 21 | 22 | public ConnectorStatusIndicator(Context context) { 23 | super(context); 24 | 25 | this.setUpView(); 26 | } 27 | 28 | public ConnectorStatusIndicator(Context context, AttributeSet attrs) { 29 | super(context, attrs); 30 | 31 | this.setUpView(); 32 | } 33 | 34 | public void setConnector(Connector connector_parameters) { 35 | if(this.connector_parameters != null) 36 | this.connector_parameters.deleteObserver(this); 37 | 38 | this.connector_parameters = connector_parameters; 39 | 40 | this.connector_parameters.addObserver(this); 41 | } 42 | 43 | private void setUpView() { 44 | this.animation = (AnimationDrawable)getResources().getDrawable(R.drawable.ic_stat_connecting); 45 | 46 | this.status_image = new ImageView(this.getContext()); 47 | this.addView(this.status_image); 48 | 49 | this.setGravity(Gravity.CENTER_VERTICAL); 50 | } 51 | 52 | @Override 53 | public void update(Observable observable, Object data) { 54 | Connector connector_parameters = (Connector)observable; 55 | 56 | switch(connector_parameters.getStatus()) { 57 | case ACTIVE: 58 | this.status_image.setImageDrawable(getResources().getDrawable(R.drawable.ic_stat_active)); 59 | break; 60 | 61 | case CONNECTING: 62 | this.status_image.setImageDrawable(this.animation); 63 | 64 | this.status_image.post(new Runnable() { 65 | 66 | @Override 67 | public void run() { 68 | if(animation.isRunning()) 69 | animation.stop(); 70 | 71 | animation.start(); 72 | } 73 | 74 | }); 75 | break; 76 | 77 | case OFFLINE: 78 | this.status_image.setImageDrawable(getResources().getDrawable(R.drawable.ic_stat_offline)); 79 | break; 80 | 81 | case ONLINE: 82 | this.status_image.setImageDrawable(getResources().getDrawable(R.drawable.ic_stat_online)); 83 | break; 84 | 85 | case UNKNOWN: 86 | this.status_image.setImageDrawable(getResources().getDrawable(R.drawable.ic_stat_unknown)); 87 | break; 88 | 89 | case UPDATING: 90 | this.status_image.setImageDrawable(getResources().getDrawable(R.drawable.ic_stat_unknown)); 91 | break; 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/EndpointListRowView.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views; 2 | 3 | import java.util.Observable; 4 | import java.util.Observer; 5 | 6 | import com.WithSecure.dz.EndpointAdapter; 7 | import com.WithSecure.dz.R; 8 | import com.WithSecure.jsolar.api.connectors.Endpoint; 9 | 10 | import android.content.Context; 11 | import android.util.AttributeSet; 12 | import android.view.View; 13 | import android.widget.CompoundButton; 14 | import android.widget.LinearLayout; 15 | import android.widget.RelativeLayout; 16 | import android.widget.TextView; 17 | import android.widget.ToggleButton; 18 | 19 | public class EndpointListRowView extends LinearLayout implements Observer, CompoundButton.OnCheckedChangeListener, View.OnClickListener { 20 | 21 | private Endpoint endpoint = null; 22 | private TextView endpoint_connection_string_field = null; 23 | private RelativeLayout endpoint_detail_layout = null; 24 | private TextView endpoint_name_field = null; 25 | private ConnectorStatusIndicator endpoint_status_indicator = null; 26 | private ToggleButton endpoint_toggle_button = null; 27 | 28 | private EndpointAdapter.OnEndpointSelectListener endpoint_listener = null; 29 | 30 | private volatile boolean setting_endpoint = false; 31 | 32 | public EndpointListRowView(Context context) { 33 | super(context); 34 | 35 | this.setUpView(); 36 | } 37 | 38 | public EndpointListRowView(Context context, AttributeSet attrs) { 39 | super(context, attrs); 40 | 41 | this.setUpView(); 42 | } 43 | 44 | public void setEndpoint(Endpoint endpoint) { 45 | if(this.endpoint != null) 46 | this.endpoint.deleteObserver(this); 47 | 48 | this.setting_endpoint = true; 49 | this.endpoint = endpoint; 50 | 51 | this.endpoint_connection_string_field.setText(this.endpoint.toConnectionString()); 52 | this.endpoint_name_field.setText(this.endpoint.getName()); 53 | this.endpoint_status_indicator.setConnector(this.endpoint); 54 | this.endpoint_toggle_button.setChecked(this.endpoint.isEnabled()); 55 | this.setting_endpoint = false; 56 | 57 | this.endpoint.addObserver(this); 58 | } 59 | 60 | public void setEndpointListener(EndpointAdapter.OnEndpointSelectListener endpoint_listener) { 61 | this.endpoint_listener = endpoint_listener; 62 | } 63 | 64 | private void setUpView() { 65 | this.addView(View.inflate(this.getContext(), R.layout.list_view_row_endpoint, null)); 66 | 67 | this.endpoint_connection_string_field = (TextView)this.findViewById(R.id.endpoint_connection_string); 68 | this.endpoint_detail_layout = (RelativeLayout)this.findViewById(R.id.list_view_row_endpoint); 69 | this.endpoint_name_field = (TextView)this.findViewById(R.id.endpoint_name); 70 | this.endpoint_status_indicator = (ConnectorStatusIndicator)this.findViewById(R.id.endpoint_status_indicator); 71 | this.endpoint_toggle_button = (ToggleButton)this.findViewById(R.id.endpoint_toggle); 72 | 73 | this.endpoint_detail_layout.setOnClickListener(this); 74 | this.endpoint_toggle_button.setOnCheckedChangeListener(this); 75 | } 76 | 77 | @Override 78 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 79 | if(!this.setting_endpoint && this.endpoint_listener != null) 80 | this.endpoint_listener.onEndpointToggle(this.endpoint, isChecked); 81 | } 82 | 83 | @Override 84 | public void onClick(View v) { 85 | if(this.endpoint_listener != null) 86 | this.endpoint_listener.onEndpointSelect(this.endpoint); 87 | } 88 | 89 | @Override 90 | public void update(Observable observable, Object data) { 91 | this.setEndpoint((Endpoint)observable); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/EndpointListView.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.ListView; 6 | 7 | public class EndpointListView extends ListView { 8 | 9 | public EndpointListView(Context context, AttributeSet attrs) { 10 | super(context, attrs); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/ServerListRowView.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views; 2 | 3 | import java.util.Observable; 4 | import java.util.Observer; 5 | 6 | import android.content.Context; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | import android.widget.CompoundButton.OnCheckedChangeListener; 10 | import android.widget.CompoundButton; 11 | import android.widget.LinearLayout; 12 | import android.widget.TextView; 13 | import android.widget.ToggleButton; 14 | 15 | import com.WithSecure.dz.R; 16 | import com.WithSecure.jsolar.api.connectors.Server; 17 | import com.WithSecure.jsolar.api.connectors.Server.OnChangeListener; 18 | 19 | public class ServerListRowView extends LinearLayout implements Observer, OnCheckedChangeListener { 20 | 21 | public interface OnServerViewListener { 22 | 23 | public void onToggle(boolean toggle); 24 | 25 | } 26 | 27 | private TextView adb_server_port_field = null; 28 | private ConnectorStatusIndicator adb_server_status_indicator = null; 29 | private ToggleButton adb_server_toggle_button = null; 30 | private Server server_parameters = null; 31 | 32 | private OnServerViewListener server_view_listener; 33 | 34 | private volatile boolean setting_server = false; 35 | 36 | public ServerListRowView(Context context) { 37 | super(context); 38 | 39 | this.initView(); 40 | } 41 | 42 | public ServerListRowView(Context context, AttributeSet attrs) { 43 | super(context, attrs); 44 | 45 | this.initView(); 46 | } 47 | 48 | private void initView() { 49 | this.addView(View.inflate(this.getContext(), R.layout.list_view_row_server, null)); 50 | 51 | this.setBackgroundResource(android.R.drawable.list_selector_background); 52 | 53 | this.adb_server_port_field = (TextView)this.findViewById(R.id.adb_server_port); 54 | this.adb_server_status_indicator = (ConnectorStatusIndicator)this.findViewById(R.id.adb_server_status_indicator); 55 | this.adb_server_toggle_button = (ToggleButton)this.findViewById(R.id.adb_server_toggle); 56 | 57 | this.adb_server_toggle_button.setOnCheckedChangeListener(this); 58 | } 59 | 60 | @Override 61 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 62 | if(!this.setting_server) 63 | this.server_view_listener.onToggle(isChecked); 64 | } 65 | 66 | public void setServerParameters(Server server_parameters) { 67 | this.setting_server = true; 68 | this.server_parameters = server_parameters; 69 | 70 | this.adb_server_port_field.setText(Integer.valueOf(this.server_parameters.getPort()).toString()); 71 | this.adb_server_status_indicator.setConnector(this.server_parameters); 72 | this.adb_server_toggle_button.setChecked(this.server_parameters.isEnabled()); 73 | this.setting_server = false; 74 | 75 | this.server_parameters.setOnChangeListener(new OnChangeListener() { 76 | 77 | @Override 78 | public void onChange(Server parameters) { 79 | ServerListRowView.this.setServerParameters(parameters); 80 | } 81 | 82 | }); 83 | this.server_parameters.addObserver(this); 84 | } 85 | 86 | public void setServerViewListener(OnServerViewListener listener) { 87 | this.server_view_listener = listener; 88 | } 89 | 90 | @Override 91 | public void update(Observable observable, Object data) { 92 | this.setServerParameters((Server)observable); 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/logger/LogMessageAdapter.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views.logger; 2 | 3 | import com.WithSecure.jsolar.logger.LogMessage; 4 | import com.WithSecure.jsolar.logger.Logger; 5 | import com.WithSecure.jsolar.logger.OnLogMessageListener; 6 | 7 | import android.content.Context; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.BaseAdapter; 11 | 12 | public class LogMessageAdapter extends BaseAdapter implements OnLogMessageListener { 13 | 14 | private Context context = null; 15 | private Logger logger = null; 16 | 17 | public LogMessageAdapter(Context context, Logger logger) { 18 | this.context = context; 19 | this.logger = logger; 20 | 21 | this.logger.addOnLogMessageListener(this); 22 | } 23 | 24 | @Override 25 | public int getCount() { 26 | return this.logger.getLogMessages().size(); 27 | } 28 | 29 | @Override 30 | public Object getItem(int pos) { 31 | return this.logger.getLogMessages().get(pos); 32 | } 33 | 34 | @Override 35 | public long getItemId(int pos) { 36 | return pos; 37 | } 38 | 39 | @Override 40 | public View getView(int pos, View copyView, ViewGroup parent) { 41 | LogMessageRowView view = new LogMessageRowView(this.context); 42 | 43 | view.setLogMessage((LogMessage)this.getItem(pos)); 44 | 45 | return view; 46 | } 47 | 48 | @Override 49 | public void onLogMessage(Logger logger, LogMessage message) { 50 | this.notifyDataSetChanged(); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /agent/src/main/java/com/WithSecure/dz/views/logger/LogMessageRowView.java: -------------------------------------------------------------------------------- 1 | package com.WithSecure.dz.views.logger; 2 | 3 | import com.WithSecure.dz.R; 4 | import com.WithSecure.jsolar.logger.LogMessage; 5 | 6 | import android.content.Context; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | import android.widget.LinearLayout; 10 | import android.widget.TextView; 11 | 12 | public class LogMessageRowView extends LinearLayout { 13 | 14 | private LogMessage message = null; 15 | private TextView message_label = null; 16 | private TextView message_message = null; 17 | 18 | public LogMessageRowView(Context context) { 19 | super(context); 20 | 21 | this.setUpView(); 22 | } 23 | 24 | public LogMessageRowView(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | 27 | this.setUpView(); 28 | } 29 | 30 | private void setLevel(int level) { 31 | switch(level) { 32 | case LogMessage.ASSERT: 33 | this.message_label.setText(R.string.log_level_tag_assert); 34 | this.message_label.setBackgroundColor(0xffff0000); 35 | this.message_label.setTextColor(0xffffffff); 36 | break; 37 | 38 | case LogMessage.DEBUG: 39 | this.message_label.setText(R.string.log_level_tag_debug); 40 | this.message_label.setBackgroundColor(0xff00ff00); 41 | this.message_label.setTextColor(0xff000000); 42 | break; 43 | 44 | case LogMessage.ERROR: 45 | this.message_label.setText(R.string.log_level_tag_error); 46 | this.message_label.setBackgroundColor(0xffff0000); 47 | this.message_label.setTextColor(0xffffffff); 48 | break; 49 | 50 | case LogMessage.INFO: 51 | this.message_label.setText(R.string.log_level_tag_info); 52 | break; 53 | 54 | case LogMessage.VERBOSE: 55 | this.message_label.setText(R.string.log_level_tag_verbose); 56 | this.message_label.setBackgroundColor(0xff00ff00); 57 | this.message_label.setTextColor(0xff000000); 58 | break; 59 | 60 | case LogMessage.WARN: 61 | this.message_label.setText(R.string.log_level_tag_warn); 62 | this.message_label.setBackgroundColor(0xffffa500); 63 | this.message_label.setTextColor(0xff000000); 64 | break; 65 | 66 | default: 67 | this.message_label.setText(R.string.log_level_tag_unknown); 68 | break; 69 | } 70 | } 71 | 72 | public void setLogMessage(LogMessage message) { 73 | this.message = message; 74 | 75 | this.setLevel(this.message.getLevel()); 76 | this.message_message.setText(this.message.getMessage()); 77 | } 78 | 79 | private void setUpView() { 80 | this.addView(View.inflate(this.getContext(), R.layout.list_view_row_log_message, null)); 81 | 82 | this.message_label = (TextView)this.findViewById(R.id.log_message_level); 83 | this.message_message = (TextView)this.findViewById(R.id.log_message_message); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/drozer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/drozer.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_delete.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_edit.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_new.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_refresh.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_search.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_action_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_action_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_input_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_input_add.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_notification.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_stat_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_stat_active.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_stat_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_stat_offline.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_stat_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_stat_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-hdpi/ic_stat_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-hdpi/ic_stat_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_action_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_action_delete.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_action_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_action_edit.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_action_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_action_new.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_action_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_action_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_action_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_action_refresh.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_action_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_action_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_input_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_input_add.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_stat_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_stat_active.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_stat_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_stat_offline.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_stat_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_stat_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-ldpi/ic_stat_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-ldpi/ic_stat_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_delete.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_edit.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_new.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_refresh.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_search.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_action_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_action_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_input_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_input_add.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_notification.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_stat_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_stat_active.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_stat_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_stat_offline.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_stat_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_stat_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-mdpi/ic_stat_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-mdpi/ic_stat_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_delete.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_edit.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_new.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_refresh.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_search.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_action_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_action_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_input_add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_input_add.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_notification.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_stat_active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_stat_active.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_stat_offline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_stat_offline.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_stat_online.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_stat_online.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable-xhdpi/ic_stat_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ReversecLabs/drozer-agent/a730ac85bc68f0f3c3f938b975dbcc2880f8052e/agent/src/main/res/drawable-xhdpi/ic_stat_unknown.png -------------------------------------------------------------------------------- /agent/src/main/res/drawable/ic_stat_connecting.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /agent/src/main/res/layout-land/activity_main.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 16 | 17 | 23 | 24 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /agent/src/main/res/layout-v14/toggle_endpoint.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /agent/src/main/res/layout-v14/toggle_server.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /agent/src/main/res/layout/activity_about.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 20 | 21 | 30 | 31 | 41 | 42 | -------------------------------------------------------------------------------- /agent/src/main/res/layout/activity_endpoint.xml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 18 | 19 | 20 | 21 | 31 | 38 | 45 | 52 | 59 | 66 | 67 | 77 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /agent/src/main/res/layout/activity_endpoint_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 14 | 15 |