From f794919f02b4c3bf4e43ea120d5b92a5bf2ef296 Mon Sep 17 00:00:00 2001 From: fattire Date: Thu, 15 Feb 2018 15:55:26 -0800 Subject: [PATCH 1/2] Update everything for Android 3.2a3 (big, see below) While waiting for cSploit 2.0 to come online, here's a quick refresh: * target API/sdk 27, support as far back as 14 (from 9) * update libraries and use new "implementation" build.gradle syntax * Update Java to 1.8 * Update to gradle 4.5.1 from 2.9 * Update android gradle plugin from 1.5.0 to 3.2.0-a3 * Use the google dependency repository * simplify build.gradle date stamp calculation * update ACRA (even though target end point @ iriscouch went offline). This is not really tested past the "send info" dialog (no point) * Support multi-window on chromebook. * Add Notification Channel as required by Oreo (Android 8) * Add very simple runtime permissions request * Minor changes to use .apply() instead of .commit() * Similar minor fix to use Locale with string formatting. * Minor removal of dialog theme defining itself * Fix bug in SettingsFragment where super.onViewCreated() not called * Minor fix to preferences compat xml file Th-that's all, folks! --- build.gradle | 4 +- cSploit/build.gradle | 55 +++++++++---------- cSploit/src/main/AndroidManifest.xml | 15 +++-- .../csploit/android/CSploitApplication.java | 50 ++++++++++++----- .../org/csploit/android/MainActivity.java | 50 ++++++++++++++++- .../org/csploit/android/SettingsFragment.java | 5 +- .../android/core/MultiAttackService.java | 11 ++-- .../java/org/csploit/android/core/System.java | 40 +++++++++++--- .../android/services/UpdateService.java | 41 +++++++++----- .../receivers/MsfRpcdServiceReceiver.java | 5 +- cSploit/src/main/res/values/strings.xml | 8 +++ cSploit/src/main/res/values/style.xml | 2 - cSploit/src/main/res/xml/preferences.xml | 4 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 14 files changed, 205 insertions(+), 89 deletions(-) diff --git a/build.gradle b/build.gradle index dea94eb99c..dfc3de68c0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,16 +1,18 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { + google() jcenter() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:3.2.0-alpha03' } } allprojects { repositories { + google() jcenter() mavenCentral() } diff --git a/cSploit/build.gradle b/cSploit/build.gradle index 0002b242e6..d96c10529d 100644 --- a/cSploit/build.gradle +++ b/cSploit/build.gradle @@ -1,19 +1,17 @@ buildscript { repositories { + google() jcenter() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:1.5.0' + classpath 'com.android.tools.build:gradle:3.2.0-alpha03' } } -def getDate() { - return Calendar.getInstance().getTimeInMillis(); -} - allprojects { repositories { + google() jcenter() mavenCentral() } @@ -21,28 +19,29 @@ allprojects { apply plugin: 'com.android.application' dependencies { - compile 'com.android.support:support-v4:23.1.1' - compile 'com.android.support:appcompat-v7:23.1.1' - compile 'com.android.support:design:23.1.1' - compile 'com.android.support:preference-v7:23.1.1' - compile 'org.apache.commons:commons-compress:1.10' - compile 'commons-net:commons-net:3.3' - compile 'com.github.zafarkhaja:java-semver:0.9.0' - compile 'org.unbescape:unbescape:1.1.1.RELEASE' - compile 'org.msgpack:msgpack:0.6.12' - compile 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3' - compile 'org.tukaani:xz:1.5' - compile 'ch.acra:acra:4.6.2' - testCompile 'junit:junit:4.12' + implementation 'com.android.support:support-v4:27.0.2' + implementation 'com.android.support:appcompat-v7:27.0.2' + implementation 'com.android.support:design:27.0.2' + implementation 'com.android.support:preference-v7:27.0.2' + implementation 'org.apache.commons:commons-compress:1.16.1' + implementation 'commons-net:commons-net:3.6' + implementation 'com.github.zafarkhaja:java-semver:0.9.0' + implementation 'org.unbescape:unbescape:1.1.5.RELEASE' + implementation 'org.msgpack:msgpack:0.6.12' + implementation 'com.googlecode.juniversalchardet:juniversalchardet:1.0.3' + implementation 'org.tukaani:xz:1.8' + implementation 'ch.acra:acra-http:5.1.0' + implementation 'ch.acra:acra-notification:5.1.0' + testImplementation 'junit:junit:4.12' } android { - compileSdkVersion 23 - buildToolsVersion '23.0.2' + compileSdkVersion 27 + buildToolsVersion '27.0.3' compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 } packagingOptions { @@ -51,8 +50,8 @@ android { } defaultConfig { - minSdkVersion 9 - targetSdkVersion 22 + minSdkVersion 14 + targetSdkVersion 27 versionCode 4 versionName "1.7.0-unstable" if(System.getenv("NIGHTLY_BUILD")) { @@ -81,8 +80,8 @@ android { buildTypes { debug { - buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + getDate() + "L)" - buildConfigField "String", "BUILD_NAME", "\"" + System.getenv("USER") + "\""; + buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + Calendar.getInstance().getTimeInMillis() + "L)" + buildConfigField "String", "BUILD_NAME", "\"" + System.getenv("USER") + "\"" minifyEnabled false shrinkResources false debuggable true @@ -91,8 +90,8 @@ android { multiDexEnabled true } release { - buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + getDate() + "L)" - buildConfigField "String", "BUILD_NAME", "\"" + System.getenv("USER") + "\""; + buildConfigField "java.util.Date", "BUILD_TIME", "new java.util.Date(" + Calendar.getInstance().getTimeInMillis() + "L)" + buildConfigField "String", "BUILD_NAME", "\"" + System.getenv("USER") + "\"" if (System.getenv("KEYSTORE_FILE") != null) { signingConfig signingConfigs.release } diff --git a/cSploit/src/main/AndroidManifest.xml b/cSploit/src/main/AndroidManifest.xml index 84618a1962..3c6a33db5d 100644 --- a/cSploit/src/main/AndroidManifest.xml +++ b/cSploit/src/main/AndroidManifest.xml @@ -14,14 +14,19 @@ - + android:theme="@style/AppTheme" + android:resizeableActivity="true"> + + + - - = android.os.Build.VERSION_CODES.O) { + NotificationChannel mChannel = new NotificationChannel(getString(R.string.csploitChannelId), + getString(R.string.cSploitChannelDescription), NotificationManager.IMPORTANCE_DEFAULT); + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + if (mNotificationManager != null) { + mNotificationManager.createNotificationChannel(mChannel); + } + } SharedPreferences themePrefs = getSharedPreferences("THEME", 0); if (themePrefs.getBoolean("isDark", false)) setTheme(R.style.DarkTheme); @@ -44,9 +62,35 @@ protected void onCreate(Bundle savedInstanceState) { getSupportFragmentManager().beginTransaction() .add(R.id.mainframe, f).commit(); } + verifyPerms(); } - public void onBackPressed() { - f.onBackPressed(); - } + public void verifyPerms() { + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, + Manifest.permission.READ_PHONE_STATE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, + new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_PHONE_STATE}, + MY_PERMISSIONS_WANTED); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, + String permissions[], int[] grantResults) { + switch (requestCode) { + case MY_PERMISSIONS_WANTED: { + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(this, R.string.permissions_succeed, Toast.LENGTH_LONG).show(); + } else { + Toast.makeText(this, R.string.permissions_fail, Toast.LENGTH_LONG).show(); + finish(); + } + } + } + } } \ No newline at end of file diff --git a/cSploit/src/main/java/org/csploit/android/SettingsFragment.java b/cSploit/src/main/java/org/csploit/android/SettingsFragment.java index ba6db23dd2..1aea61f5fc 100644 --- a/cSploit/src/main/java/org/csploit/android/SettingsFragment.java +++ b/cSploit/src/main/java/org/csploit/android/SettingsFragment.java @@ -99,6 +99,7 @@ public static class PrefsFrag extends PreferenceFragmentCompat implements Shared @Override public void onViewCreated(View v, Bundle savedInstanceState) { + super.onViewCreated(v, savedInstanceState); SharedPreferences themePrefs = getActivity().getSharedPreferences("THEME", 0); Boolean isDark = themePrefs.getBoolean("isDark", false); if (isDark) { @@ -140,7 +141,7 @@ public void onCreate(Bundle savedInstanceState) { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { SharedPreferences themePrefs = getActivity().getBaseContext().getSharedPreferences("THEME", 0); - themePrefs.edit().putBoolean("isDark", (Boolean) newValue).commit(); + themePrefs.edit().putBoolean("isDark", (Boolean) newValue).apply(); Toast.makeText(getActivity().getBaseContext(), getString(R.string.please_restart), Toast.LENGTH_LONG).show(); return true; } @@ -276,7 +277,7 @@ else if (checker != null && !checker.canExecuteInDir(path)) else { //noinspection ConstantConditions - getPreferenceManager().getSharedPreferences().edit().putString(key, path).commit(); + getPreferenceManager().getSharedPreferences().edit().putString(key, path).apply(); if (oldPath != null && !oldPath.equals(path)) { File current = new File(oldPath); diff --git a/cSploit/src/main/java/org/csploit/android/core/MultiAttackService.java b/cSploit/src/main/java/org/csploit/android/core/MultiAttackService.java index 8956a8c6de..3804258e70 100644 --- a/cSploit/src/main/java/org/csploit/android/core/MultiAttackService.java +++ b/cSploit/src/main/java/org/csploit/android/core/MultiAttackService.java @@ -17,6 +17,7 @@ import org.csploit.android.tools.NMap; import java.util.List; +import java.util.Locale; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -84,8 +85,9 @@ public void run() { synchronized (MultiAttackService.this) { completedTargets++; - mBuilder.setContentInfo(String.format("%d/%d", - completedTargets, totalTargets)); + mBuilder.setContentInfo(String.format(Locale.getDefault(), "%d/%d", + completedTargets, totalTargets)) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } @@ -199,7 +201,7 @@ private void setupNotification() { // get notification manager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // get notification builder - mBuilder = new NotificationCompat.Builder(this); + mBuilder = new NotificationCompat.Builder(this, getBaseContext().getString(R.string.csploitChannelId)); // create a broadcast receiver to get actions // performed on the notification by the user mReceiver = new BroadcastReceiver() { @@ -237,7 +239,8 @@ private void finishNotification() { mBuilder.setContentIntent(PendingIntent.getActivity(this, CLICK_CODE, mContentIntent, 0)) .setProgress(0,0,false) .setAutoCancel(true) - .setDeleteIntent(PendingIntent.getActivity(this, 0, new Intent(), 0)); + .setDeleteIntent(PendingIntent.getActivity(this, 0, new Intent(), 0)) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } if(mReceiver!=null) diff --git a/cSploit/src/main/java/org/csploit/android/core/System.java b/cSploit/src/main/java/org/csploit/android/core/System.java index 4c0718ebea..be85431054 100644 --- a/cSploit/src/main/java/org/csploit/android/core/System.java +++ b/cSploit/src/main/java/org/csploit/android/core/System.java @@ -36,8 +36,7 @@ import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.util.SparseIntArray; -import org.acra.ACRA; -import org.acra.ACRAConfiguration; + import org.apache.commons.compress.utils.IOUtils; import org.csploit.android.R; import org.csploit.android.WifiScannerFragment; @@ -59,9 +58,36 @@ import org.csploit.android.services.Services; import org.csploit.android.tools.ToolBox; -import java.io.*; -import java.net.*; -import java.util.*; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NoRouteToHostException; +import java.net.Socket; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Observer; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.zip.GZIPInputStream; @@ -271,12 +297,12 @@ private static void startCoreDaemon() throws SuException, DaemonException { if (ret != 0) { File log = new File(System.getCorePath(), "cSploitd.log"); DaemonException daemonException = new DaemonException("core daemon returned " + ret); - if (log.exists() && log.canRead()) { + /* if (log.exists() && log.canRead()) { ACRAConfiguration conf = ACRA.getConfig(); conf.setApplicationLogFile(log.getAbsolutePath()); ACRA.setConfig(conf); ACRA.getErrorReporter().handleException(daemonException, false); - } + }*/ throw daemonException; } } diff --git a/cSploit/src/main/java/org/csploit/android/services/UpdateService.java b/cSploit/src/main/java/org/csploit/android/services/UpdateService.java index 1a24cd2e22..dcbd717354 100644 --- a/cSploit/src/main/java/org/csploit/android/services/UpdateService.java +++ b/cSploit/src/main/java/org/csploit/android/services/UpdateService.java @@ -243,7 +243,7 @@ private void setupNotification() { // get notification manager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // get notification builder - mBuilder = new NotificationCompat.Builder(this); + mBuilder = new NotificationCompat.Builder(this, getBaseContext().getString(R.string.csploitChannelId)); // create a broadcast receiver to get actions // performed on the notification by the user mReceiver = new BroadcastReceiver() { @@ -283,7 +283,8 @@ private void finishNotification() { } else { Logger.debug("assign '"+contentIntent.toString()+"' to notification"); if(mBuilder!=null&&mNotificationManager!=null) { - mBuilder.setContentIntent(PendingIntent.getActivity(this, DOWNLOAD_COMPLETE_CODE, contentIntent, 0)); + mBuilder.setContentIntent(PendingIntent.getActivity(this, DOWNLOAD_COMPLETE_CODE, contentIntent, 0)) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } } @@ -342,7 +343,8 @@ private void verifyArchiveIntegrity() throws RuntimeException, KeyException { .setSmallIcon(android.R.drawable.ic_popup_sync) .setContentText("") .setContentInfo("") - .setProgress(100, 0, true); + .setProgress(100, 0, true) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID,mBuilder.build()); f = new File(mCurrentTask.path); @@ -385,7 +387,8 @@ private void verifyArchiveIntegrity() throws RuntimeException, KeyException { percentage = (short) (((double) counter.getBytesRead() / total) * 100); if (percentage != old_percentage) { mBuilder.setProgress(100, percentage, false) - .setContentInfo(percentage + "%"); + .setContentInfo(percentage + "%") + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); old_percentage = percentage; } @@ -455,7 +458,8 @@ private boolean haveLocalFile() throws CancellationException, SecurityException, mBuilder.setContentTitle(getString(R.string.checking)) .setSmallIcon(android.R.drawable.ic_popup_sync) .setContentText("") - .setProgress(100, 0, false); + .setProgress(100, 0, false) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID,mBuilder.build()); md5 = (mCurrentTask.md5!=null ? MessageDigest.getInstance("MD5") : null); @@ -473,7 +477,8 @@ private boolean haveLocalFile() throws CancellationException, SecurityException, percentage = (short) (((double) read_counter / total) * 100); if (percentage != previous_percentage) { mBuilder.setProgress(100, percentage, false) - .setContentInfo(percentage + "%"); + .setContentInfo(percentage + "%") + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); previous_percentage = percentage; } @@ -542,7 +547,8 @@ private void downloadFile() throws SecurityException, KeyException, IOException, mBuilder.setContentTitle(getString(R.string.downloading_update)) .setContentText(getString(R.string.connecting)) .setSmallIcon(android.R.drawable.stat_sys_download) - .setProgress(100, 0, true); + .setProgress(100, 0, true) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID,mBuilder.build()); md5 = (mCurrentTask.md5!=null ? MessageDigest.getInstance("MD5") : null); @@ -573,7 +579,8 @@ private void downloadFile() throws SecurityException, KeyException, IOException, downloaded=0; previous_percentage=-1; - mBuilder.setContentText(file.getName()); + mBuilder.setContentText(file.getName()) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); Logger.info(String.format("downloading '%s' to '%s'", mCurrentTask.url, mCurrentTask.path)); @@ -592,7 +599,8 @@ private void downloadFile() throws SecurityException, KeyException, IOException, if (percentage != previous_percentage) { mBuilder.setProgress(100, percentage, false) - .setContentInfo(percentage + "%"); + .setContentInfo(percentage + "%") + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); previous_percentage = percentage; } @@ -663,7 +671,8 @@ private void extract() throws RuntimeException, IOException, InterruptedExceptio .setContentText("") .setContentInfo("") .setSmallIcon(android.R.drawable.ic_popup_sync) - .setProgress(100, 0, false); + .setProgress(100, 0, false) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID,mBuilder.build()); Logger.info(String.format("extracting '%s' to '%s'", mCurrentTask.path, mCurrentTask.outputDir)); @@ -782,7 +791,8 @@ else if(entry.isDirectory()) percentage = (short) (((double) counter.getBytesRead() / total) * 100); if (percentage != old_percentage) { mBuilder.setProgress(100, percentage, false) - .setContentInfo(percentage + "%"); + .setContentInfo(percentage + "%") + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); old_percentage = percentage; } @@ -823,7 +833,8 @@ else if(entry.isDirectory()) Logger.info(".nomedia created"); mBuilder.setContentInfo("") - .setProgress(100, 100, true); + .setProgress(100, 100, true) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); } finally { if(is != null) @@ -843,7 +854,8 @@ private void installGems() throws RuntimeException, IOException, InterruptedExce .setContentText(getString(R.string.installing_bundle)) .setContentInfo("") .setSmallIcon(android.R.drawable.stat_sys_download) - .setProgress(100, 0, true); + .setProgress(100, 0, true) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); Child bundleInstallTask; @@ -855,7 +867,8 @@ private void installGems() throws RuntimeException, IOException, InterruptedExce bundleInstallTask = System.getTools().ruby.async("gem install bundle", mErrorReceiver); } - mBuilder.setContentText(getString(R.string.installing_msf_gems)); + mBuilder.setContentText(getString(R.string.installing_msf_gems)) + .setChannelId(getBaseContext().getString(R.string.csploitChannelId)); mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build()); // remove cache version file diff --git a/cSploit/src/main/java/org/csploit/android/services/receivers/MsfRpcdServiceReceiver.java b/cSploit/src/main/java/org/csploit/android/services/receivers/MsfRpcdServiceReceiver.java index cbd48e2661..dff6472111 100644 --- a/cSploit/src/main/java/org/csploit/android/services/receivers/MsfRpcdServiceReceiver.java +++ b/cSploit/src/main/java/org/csploit/android/services/receivers/MsfRpcdServiceReceiver.java @@ -69,12 +69,13 @@ private void showToastForStatus(Context context, MsfRpcdService.Status status) { private void updateNotificationForStatus(Context context, MsfRpcdService.Status status) { NotificationCompat.Builder mBuilder = - new NotificationCompat.Builder(context) + new NotificationCompat.Builder(context, context.getString(R.string.csploitChannelId)) .setSmallIcon(R.drawable.exploit_msf) .setContentTitle(context.getString(R.string.msf_status)) .setProgress(0, 0, status.inProgress()) .setContentText(context.getString(status.getText())) - .setColor(ContextCompat.getColor(context, status.getColor())); + .setColor(ContextCompat.getColor(context, status.getColor())) + .setChannelId(context.getString(R.string.csploitChannelId)); NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); diff --git a/cSploit/src/main/res/values/strings.xml b/cSploit/src/main/res/values/strings.xml index 643793f6bd..261c012269 100644 --- a/cSploit/src/main/res/values/strings.xml +++ b/cSploit/src/main/res/values/strings.xml @@ -537,4 +537,12 @@ delete current session and start another? any interface Error initializing %s + + + csploit_channel + cSploit-related messages + + + Sorry, you need to approve both permission requests. + Thanks! diff --git a/cSploit/src/main/res/values/style.xml b/cSploit/src/main/res/values/style.xml index 628c655cfb..401b44f90c 100644 --- a/cSploit/src/main/res/values/style.xml +++ b/cSploit/src/main/res/values/style.xml @@ -47,8 +47,6 @@ @color/background_window_dark -