Pesquisa sobre o SDK malicioso SourMint
Kirill Efimov
16 de outubro de 2020
0 minutos de leituraColeta excessiva de dados no iOS [agosto de 2020]
Execução remota de código (RCE) no iOS [outubro de 2020]
Rastreamento de downloads no Android [outubro de 2020]
Visão geral
O SDK Mintegral é um popular SDK de publicidade para aplicativos móveis, disponível para iOS e Android. Ele é usado por milhares de apps móveis, com mais de um bilhão de downloads por mês. Desenvolvedores de aplicativos o utilizam para monetizar seus apps com anúncios de terceiros.
A equipe de pesquisa de segurança da Snyk fez duas divulgações importantes sobre o SDK Mintegral. A primeira divulgação foi publicada em agosto de 2020 e revelou coleta excessiva de dados e sequestro de cliques na versão do SDK para iOS. A segunda divulgação revelou uma backdoor na versão para iOS do SDK, que permite a execução remota de código, além de novas descobertas sobre a versão para Android.
O objetivo deste artigo é compartilhar os detalhes técnicos da nossa pesquisa e das nossas descobertas, indo além do que foi abordado nas publicações do blog.
Este artigo está dividido em três seções:
Coleta excessiva de dados, incluindo a interceptação e o registro de todas as solicitações HTTP no SDK para iOS — publicado originalmente em 24 de agosto de 2020 —, descreve os recursos de rastreamento de URLs e solicitações na versão do SDK Mintegral para iOS.
Uma backdoor na versão do SDK para iOS permite a execução remota de código — descreve os recursos de execução remota de código do MintegralAdSDK, publicado em 15 de outubro de 2020.
Rastreamento de URLs de downloads no Android — descreve diversas descobertas na versão do SDK Mintegral para Android.
Coleta excessiva de dados no iOS [agosto de 2020]
Visão geral
Esta parte da pesquisa foi feita com a versão binária do SDK Mintegral para iOS, pois a versão de código aberto ainda não estava disponível para nós em agosto de 2020. A pesquisa foi conduzida na versão 6.3.5.0 do SDK (para arquitetura x86), disponível para download no GitHub.
Identificamos que as versões 5.5.1 e posteriores do SDK Mintegral para iOS contêm funcionalidades maliciosas que levam ao vazamento de informações. Em termos simples, o SDK espiona os cliques dos usuários em links e a atividade de rede nos aplicativos afetados. A espionagem ocorre mesmo quando o SDK não foi habilitado pelo desenvolvedor ou pela plataforma de mediação de anúncios. Além disso, o SDK tenta ocultar o comportamento malicioso identificando proxies, simuladores e dispositivos com jailbreak.
Swizzling de métodos
O SDK Mintegral usa uma técnica chamada swizzling de métodos para substituir, em tempo de execução, as implementações dos métodos UIApplication openURL e SKStoreProductViewController loadProductWithParameters. Ele também registra uma classe NSURLProtocol personalizada.
Esses hooks são usados para espionar os usuários do aplicativo, enviando todas as informações sobre solicitações HTTP, URLs abertas e links da App Store em que eles clicam dentro do app.
Os cabeçalhos e as URLs das solicitações HTTP podem conter dados confidenciais. Junto com o IDFA (identificador para anunciantes), esses dados permitem que a Mintegral cometa fraude de atribuição de anúncios.
Fraude de atribuição de anúncios
Para monetizar seus aplicativos, os desenvolvedores costumam instalar plataformas de publicidade. Essas plataformas recebem receita dos anunciantes por cada instalação realizada após um usuário clicar em um anúncio. É comum os desenvolvedores usarem várias plataformas de publicidade em seus apps. Por isso, para determinar qual plataforma de anúncios deve receber o crédito pela instalação, cada clique é registrado em um provedor de atribuição, uma plataforma de mensuração móvel (MMP).
A figura abaixo mostra como funciona a funcionalidade maliciosa da Mintegral. Neste exemplo, o usuário clicou em um anúncio da “Outra Plataforma”. Mas, como a Mintegral pode interceptar todas as URLs abertas pelo aplicativo, ela pode fazer solicitações adicionais a um provedor de atribuição, fingindo que o clique foi feito em um anúncio seu. O processo completo funciona assim:
O usuário clica em um link de um anúncio no app, veiculado por uma rede de anúncios que não é a Mintegral, para instalar um novo aplicativo pela App Store.
O SDK da rede de anúncios envia as informações do clique à plataforma de back-end.
Após interceptar o evento de clique por meio de código injetado nos manipuladores de eventos do iOS usando swizzling de métodos, a Mintegral registra os dados do clique em seu servidor.
A rede de anúncios registra uma notificação de clique no provedor de atribuição.
A Mintegral também registra uma notificação de clique no provedor de atribuição.
Quando o provedor de atribuição tenta associar o evento de instalação às notificações de clique registradas, encontra duas correspondências. Usando um modelo de atribuição de último toque, o crédito é atribuído à notificação de clique da Mintegral, e a notificação da outra rede de anúncios é rejeitada.

A Snyk trabalhou com um importante provedor de atribuição para confirmar que a Mintegral usa os dados de cliques para gerar notificações falsas. Durante a investigação, o provedor conseguiu demonstrar que essas notificações falsas estavam sendo geradas e fazendo com que os cliques em anúncios fossem atribuídos incorretamente à Mintegral.
Aplicativo de demonstração
Para demonstrar o ataque, configuramos um aplicativo de demonstração. Ele mostra o hook malicioso openURL em ação. Usamos um proxy de depuração para interceptar todo o tráfego de rede.
Para inicializar o aplicativo, usamos o seguinte trecho de código da documentação da Mintegral:
Com o SDK inicializado, abrimos example.com no aplicativo clicando em um botão:
Depois de iniciar o app, vemos imediatamente algumas solicitações do SDK Mintegral no proxy:

Configurações
A resposta de _https://setting.rayjump.com/setting é um objeto JSON com várias opções. A tabela a seguir descreve os campos mais relevantes para nossa pesquisa.
Campo JSON | Descrição |
|---|---|
csw | Habilita ou desabilita a funcionalidade antidepuração. |
cou | Ative ou desative o hook do método |
cdai | URL para onde as informações vazadas são enviadas (*). |
cspn | Habilita ou desabilita o hook nos métodos do StoreKit. |
cud | Habilita ou desabilita o hook no NSURLProtocol. |
cudl | Lista de URLs rastreadas pelo NSURLProtocol (**). |
* No nosso caso, era LdxThdi1WBK/WgfPhbxQYkeXHBPwHZKsYFh=, que, após a decodificação, corresponde a https://n.systemlog.me/log.
** No nosso caso, era kBzuJd5/H+i/D+SMY7V/DFKwR0M0D+SMhBPthdSsHZPUYFT0+N==, que, após a decodificação, corresponde a ["itunes.apple.com","apps.apple.com"].
Decodificação da carga útil
Após clicar no botão que abre example.com, vemos mais duas solicitações. A primeira é uma solicitação GET para http://example.com, como esperado. A segunda é uma solicitação POST para https://n.systemlog.me/log.

O corpo da solicitação parece estar codificado em base64. Mas, na verdade, não é uma string codificada em base64. O SDK da Mintegral implementa sua própria lógica de codificação e decodificação, que pode ser encontrada em +[MTGBase base64DecodeString:] e +[MTGBase base64CleverDecodeString:]. Observe que MTGBase não está exposta nos cabeçalhos públicos do SDK e não foi projetada para ser acessível aos desenvolvedores.
Usamos o seguinte trecho de código para decodificar a carga útil:

A carga útil contém muitos dados, incluindo IDFA, IDFV, versão do sistema operacional, user agent e outros. Ela também contém um campo chamado “clever”, que, mais uma vez, está codificado. Podemos decodificá-lo usando base64DecodeString:
Como você pode ver, ele contém a URL, o rastreamento da pilha e algumas informações adicionais, como o controlador e o nome do método.
Análise mais aprofundada
Como mencionado anteriormente, o SDK Mintegral é de código fechado. Vamos analisar a versão 6.3.5.0 para a arquitetura x86.
O binário é um executável Mach-O que contém vários outros binários. O código que nos interessa está em _CXX_CXX_OperationPKTask.o.
Ao analisar a classe, encontramos +[_CXX_CXX_OperationPKTask load], que é executado automaticamente quando a classe é adicionada em tempo de execução. Isso significa que, se o SDK for instalado via CocoaPods, a lógica maliciosa será inicializada independentemente de os desenvolvedores usarem ou não o SDK.
O método load faz uma série de chamadas que nos levam a ___cxxwebk_init_vw. Esse método verifica se a flag de proteção antidepuração está habilitada e inicializa os hooks se a flag estiver desativada ou se a depuração estiver desabilitada.

A inicialização dos hooks depende da solicitação de configurações mencionada acima. A tabela a seguir mostra a relação entre os campos da resposta JSON e a classe MTGSetting:
Campo JSON | Propriedade de MTGSetting | Descrição |
|---|---|---|
csw | cSrtW | Habilita ou desabilita a funcionalidade antidepuração. |
cou | cOpenURL | Ative ou desative o hook do método |
cspn | cPackageName | Habilita ou desabilita o hook nos métodos do StoreKit. |
Lógica antidepuração

A função __cxx_cxx_op_isInSuperViewFrame retorna true nos seguintes casos:
A plataforma do dispositivo é um “simulador”.
Há um depurador conectado (implementado em
____mvpmvvm_isDebuggerAttached_block_invoke).Um dos arquivos a seguir está presente no dispositivo (indício de jailbreak):
/Applications/Cydia.app
/Library/MobileSubstrate/MobileSubstrate.dylib
/bin/bash
/usr/sbin/sshd
/etc/apt
/usr/bin/ssh
Há um proxy habilitado (usando
CFNetworkCopySystemProxySettings).
Swizzling do método openURL
A lógica mostrada na captura de tela a seguir está implementada no método ___cxxwebkmcouitninapo, chamado por ___cxxwebk_init_vw quando a flag correspondente está habilitada.

"blog-sour-mint-openurl-method-swirl" - A captura de tela acima mostra a implementação do swizzling de métodos. Ela faz as seguintes chamadas:
NSSelectorFromStringpara obter um seletor do método “openURL:”.NSClassFromStringpara obter o descritor da classeUIApplication.class_getInstanceMethodpara obter o descritor do método.method_getImplementationpara obter a implementação real do método.Em seguida, define um bloco de código que chama
_____cxxwebkmcouitninapo_block_invoke_2e, depois, chama oopenURLoriginal.method_setImplementationpara substituir o openURL original pelo bloco de código da etapa anterior.
O mesmo acontece com o método openURL:options:completionHandler:, mas antes disso é verificada a versão do sistema (o manipulador foi introduzido pela primeira vez no iOS 10).
Neste ponto, vimos como o hook foi aplicado. Agora vamos analisar a implementação do próprio hook (_____cxxwebkmcouitninapo_block_invoke_2).
Implementação do hook openURL
Na prática, a implementação está no método ___cxxwebkmcoulsz. Nele, vemos outra chamada de verificação antidepuração. Em seguida, o método verifica a flag __mc_notifyInHouse e não faz nada se ela estiver definida como 1.
Isso é feito para ignorar todos os URLs de marketing em que o usuário clica em um anúncio veiculado pela Mintegral. A captura de tela abaixo mostra a lógica correspondente em +[MTGBase mtgOpenURL:options:completionHandler:]:

O próximo trecho de código mostra que eles também serializam os dados do rastreamento da pilha e os vazam na carga útil enviada para https://n.systemlog.me/log.
Conseguimos definir um breakpoint na chamada +[_CXX_CXX_OperationPKTask _cxx_cm_log_warnings:to:ins:]. A captura de tela seguinte mostra os argumentos da chamada:

A URL que foi aberta (http://example.com?foo=bar&x=y).
A classe em que o clique ocorreu (
ViewController).O método interno em que o clique ocorreu (
openURLWithOptions:).Informações do rastreamento da pilha.
Outra função interessante é _nsh_id_by_cc, que parece ser responsável por identificar SDKs de concorrentes. A lógica relevante aparece na próxima captura de tela:

Voltando a +[_CXX_CXX_OperationPKTask _cxx_cm_log_warnings:to:ins:], depois que o payload é codificado por meio de +[MTGBase base64EncodeString:], ele cria um novo bloco de código e usa _dispatch_async para executá-lo.
Isso leva a uma série de chamadas com transformações adicionais do payload e termina em -[_MC_ApiManager AFRequestWithUrl:paras:success:failure:], que faz uma requisição POST para collectDomainUrl de MTGSetting, cujo valor padrão é https://n.systemlog.me/log.
Vídeo que demonstra como uma URL privada pode ser vazada.

Hook de SKStoreProductViewController
SKStoreProductViewController é um controlador de visualização que exibe uma página onde o usuário pode comprar conteúdo na App Store.
O método loadProductWithParameters:completionBlock: carrega uma nova tela de produto para exibição.
Em vez de entrar nos detalhes técnicos da implementação do hook, adicionamos o seguinte trecho de código ao aplicativo de demonstração:
Como resultado, vemos uma requisição POST para https://n.systemlog.me/log com o seguinte payload no campo “clever”:
Como podemos ver, o ID do produto está na requisição. Está comprovado.
Hook de NSURLProtocol
A classe NSURLProtocol permite que um desenvolvedor redefina o funcionamento do sistema de carregamento de URLs da Apple. O SDK da Mintegral registra uma implementação maliciosa de NSURLProtocol, que pode ser configurada remotamente para interceptar quaisquer requisições de saída feitas por um aplicativo e rastrear URLs e cabeçalhos HTTP, incluindo o cabeçalho Authorization.
Para quem desenvolve aplicativos, isso significa que tokens de API, cookies e cabeçalhos de autenticação básica podem ser coletados pela Mintegral.
Para entender como o SDK ativa essa parte do código malicioso, precisamos voltar a ___cxxwebk_init_vw.

A captura de tela acima mostra que a flag cud precisa estar ativada e o array cudl não pode estar vazio para ativar o hook.
A captura de tela a seguir mostra parte da função ___cxxwebkterisiuuxx, chamada pelo método acima.

O código da função ___cxxwebkterisiuuxx executa as seguintes ações:
Cria uma classe que herda de
NSURLProtocol(objc_registerClassPair,objc_allocateClassPair).Adiciona uma implementação para
canInitWithRequest:, que funciona efetivamente como um interceptador (class_addMethod).Chama
+[NSURLProtocol registerClass:]para registrar a classe no sistema de carregamento de URLs.
Em nossa pesquisa, adicionamos o seguinte trecho de código para verificar quais dados são coletados pelo código malicioso:
Como resultado, vemos uma requisição POST para https://n.systemlog.me/log com o seguinte payload no campo “clever”:
Na requisição, podemos ver a URL e o cabeçalho de autorização. Embora o corpo da requisição não esteja incluído, os cabeçalhos muitas vezes contêm dados confidenciais. Esses dados podem até incluir informações de identificação pessoal. Por exemplo, se uma API usa tokens JWT, o e-mail ou o nome de usuário podem estar armazenados no token.
Conclusão
Durante a pesquisa, observamos várias técnicas interessantes usadas pelos desenvolvedores da Mintegral para ocultar o comportamento malicioso do SDK. Como podemos ver, eles ativam os hooks apenas em aplicativos específicos e em determinadas regiões, o que permitiu que o código malicioso permanecesse ativo por mais de um ano sem chamar atenção.
Sobre a cronologia: a primeira versão (5.5.1) do SDK malicioso foi publicada em 17 de julho de 2019. Descobrimos que todas as versões posteriores mantiveram a mesma funcionalidade maliciosa.
Muitos aplicativos populares foram afetados pelas atividades maliciosas desse SDK. Esperamos que esta pesquisa, ao esclarecer a situação, incentive uma análise mais rigorosa e mais controles de privacidade nas redes de publicidade daqui para a frente.
Execução remota de código (RCE) no iOS [outubro de 2020]
Resumo
Descobrimos que a classe MTGBaseBridgeWebView, usada em todo o SDK para se comunicar com JavaScript, funciona como uma porta dos fundos e permite invocar funções arbitrárias a partir do código nativo do aplicativo.

Na imagem acima, você pode ver um esquema simplificado da execução remota de código em ação.
Análise de diferenças
Após nossa primeira divulgação pública, a Mintegral anunciou o lançamento de uma versão de código aberto do SDK.
Comparamos a nova versão de código aberto com a versão binária anterior, distribuída como cocoapod. Embora não tivéssemos o código-fonte da versão antiga, ainda era possível comparar os nomes das classes. Para isso, extraímos os arquivos .o dos binários e comparamos os símbolos com os arquivos .h da versão de código aberto.
Como esperado, o componente malicioso _CXX_CXX_OperationPKTask, descoberto anteriormente, havia sido removido, mas a comparação revelou outra coisa. As seguintes classes chamaram nossa atenção:
MTGCommandDispatcher
MTGComponentCommands
MTGRemoteCommand
MTGRemoteCommandParameterModel
MTGRemoteCommandParser
MTGInvocationBoxing
Decidimos analisar os binários mais de perto para entender para que esses arquivos eram usados.
Versões afetadas
Todas as versões do MintegralAdSDK até a 6.5.0.0, inclusive. A versão 6.6.0.0, publicada em 10 de setembro de 2020, não tem a funcionalidade de porta dos fundos descrita neste artigo.
A implementação da bridge
Começamos verificando onde a classe MTGRemoteCommandParser é usada e encontramos apenas um lugar: -(void)handleNativeObject:parameters:, na classe MTGBaseBridgeWebView.
Pela implementação, podemos ver que -(void)handleNativeObject:parameters: usa MTGRemoteCommandParser para analisar o argumento parameters e invoca o método -(void)dispatchCommand:feedback: na classe MTGCommandDispatcher.
À primeira vista, -(void)handleNativeObject:parameters: não é usado, mas não é bem assim. Vamos ver como ele pode ser invocado a partir de código JavaScript.
MTGBaseBridgeWebView implementa o método -(void)webView:decidePolicyForNavigationAction:decisionHandler: do protocolo WKNavigationDelegate. Esse método é chamado sempre que ocorre uma navegação na web view. Isso significa que podemos acioná-lo de dentro do JavaScript simplesmente chamando location.href=something. Na versão de código aberto do SDK, encontramos uma expressão regular que analisa as URLs das requisições de navegação: mv://(.+?):(.+?)/(.+?)\\?([\\s\\S]*).

-(void)callFunctionWithName:fucId:param:, na captura de tela acima, simplesmente chama self com o seletor fucName.
Então, para chamar -(void)handleNativeObject:parameters: de MTGBaseBridgeWebView, precisamos da seguinte linha de código JavaScript: location.href = 'mv://1:fucId/handleNativeObject?<parameters>'.
Vale destacar que tudo o que descrevemos acima continua válido na versão mais recente do SDK disponível no momento da redação, assim como na versão de código aberto. A única exceção é que -(void)handleNativeObject:parameters: foi removido das versões mais recentes.
Invocação remota de métodos
Não vamos descrever a implementação completa de MTGInvocationBoxing e das outras classes. Em vez disso, mostraremos como criar código JavaScript malicioso para acionar o método remoto.
A prova de conceito a seguir ataca um aplicativo de “notas simples”, que tem uma classe NoteRepository com dois métodos: +(void)save: e +(NSString*)load.
Injetamos o código JavaScript malicioso substituindo o servidor da Mintegral por uma implementação própria. O código-fonte completo deste aplicativo e do servidor está disponível aqui.
O código JavaScript malicioso para este aplicativo é o seguinte:
Valor | Decodificado |
|---|---|
hbxtJ7QU+TPXJ75ZH+SXhFQTYbzP | static_NoteRepository |
Y7KtHv== | load |
Esse código chama o método +(NSString*)load da classe NoteRepository e envia o resultado para o endpoint demo-evil-server.com/log.
Ele usa as mesmas técnicas de ofuscação descritas na seção anterior. Mas a prova de conceito já inclui código JavaScript para codificar e decodificar (consulte banner.html).
Obtendo execução remota de código (RCE) completa
No exemplo acima, vimos como o SDK pode ser usado para invocar qualquer método estático de uma classe arbitrária. Nesta seção, demonstraremos como isso pode ser aproveitado para executar qualquer código nativo.
Para fins de demonstração, mostraremos como criar um UIAlertController com a mensagem "PWNED!".
Vamos usar o seguinte código Objective-C como referência:
Precisamos descobrir como criar e manter uma instância de UIAlertController entre chamadas, como obter uma instância compartilhada do aplicativo e como chamar presentViewController:animated:completion: com essa instância.
Etapa 1: salvar uma referência à classe UIAlertController
O MTGRemoteCommandParser aceita dois tipos de referências a objetos:
static- obtém uma referência a um objeto de classe pelo nome.singleton- executa várias etapas:Obtém uma classe pelo nome (
MTGSettingno nosso exemplo).Executa o método
sharedInstancena classe. Em Objective-C:[MTGSetting sharedInstance].Usa
valueForKey:para obter propriedades separadas por pontos. No nosso caso, será[[MTGSetting sharedInstance] valueForKey:@"jsonTitles"].
Observe que jsonTitles é apenas uma instância de NSMutableDictionary. No exploit, ela é usada como armazenamento temporário para nossas referências. O MTGRemoteCommandParser aceita os seguintes tipos de parâmetros:
0- número.1- referência.2- string.4-nil.
O tipo de referência (1) permite passar uma referência a um objeto como argumento de um método. É importante observar que uniqueIdentifier é analisado exatamente da mesma forma que um uniqueIdentifier de nível superior; portanto, também há suporte ao tipo singleton.
Etapa 2: alocar uma nova instância da classe UIAlertController
Neste caso, toda a mágica acontece em singleton_MTGSetting.jsonTitles.a.alloc.init. Como já sabemos, singleton_MTGSetting.jsonTitles.a nos fornece uma referência à classe UIAlertController. Mas precisamos entender por que [[UIAlertController valueForKey:@"alloc"] valueForKey:@"init"] funciona. Na documentação de valueForKey:, sabemos que:
O padrão de busca que valueForKey: usa para encontrar o valor correto a ser retornado está descrito em Accessor Search Patterns no Key-Value Coding Programming Guide.
Descobrimos que valueForKey: pode chamar qualquer método pelo nome, desde que ele não receba argumentos.
Agora, podemos criar uma nova instância da classe UIAlertController, que será referenciada pela propriedade b do dicionário jsonTitles.
Etapa 3: definir a mensagem "PWNED!"
Esta etapa é bem simples: chamamos setMessage: na instância de UIAlertController para definir a mensagem PWNED!.
Etapa 4: salvar uma referência à classe UIApplication
Esta etapa é semelhante à etapa 1. Precisamos salvar a referência à classe UIApplication em jsonTitles.x.
Etapa 5: exibir o alerta
Esta etapa parece complicada, mas apenas combina várias técnicas das etapas anteriores. Em código Objective-C, ficaria assim:
Neste ponto, demonstramos como um alerta pode ser exibido por meio de execução remota de código. Você encontra o payload completo aqui. Para executar as etapas uma a uma, criamos um array de ações e executamos cada ação no callback window.WindVane.onSuccess (ou seja, depois que a ação anterior fosse concluída).
Vídeo que demonstra como o conteúdo da área de transferência pode ser vazado por meio da entrega do exploit em um anúncio malicioso.

Origem do exploit em JavaScript
Já vimos como o SDK da Mintegral permite a execução remota de código nativo por meio de código JavaScript. No entanto, esse código JavaScript é totalmente controlado pela Mintegral. Mas, curiosamente, é possível obter o mesmo resultado por meio de anúncios interativos criados pelos próprios anunciantes. Os anúncios são páginas da web baseadas em JavaScript.
Em teoria, um anunciante pode segmentar com precisão um grupo específico de usuários ou um conjunto específico de dispositivos, veiculando um anúncio malicioso que contém o exploit em JavaScript.
Conclusão
Só podemos especular por que a Mintegral incluiu no SDK a capacidade de invocar métodos nativos remotamente, mas, pelos nomes das classes, como MTGCommandDispatcher e MTGRemoteCommand, acreditamos que isso foi intencional. Além disso, a Mintegral removeu o código logo após nossa publicação, embora não tivéssemos conhecimento disso na época.
Rastreamento de downloads no Android [outubro de 2020]
Visão geral
Nas duas seções anteriores deste artigo de pesquisa, mostramos como a equipe de segurança da Snyk descobriu comportamentos maliciosos no SDK da Mintegral que podem ser explorados em dispositivos iOS, levando a fraude publicitária, vazamento de dados e execução remota de código (RCE). Queríamos investigar mais a distribuição Android do SDK, o que abordamos nesta seção. Em resumo, estas são nossas principais descobertas:
Rastreamento de URIs de download do Google, que afeta downloads feitos tanto pelo navegador quanto por aplicativos, incluindo downloads comuns de arquivos, anexos de e-mail e links do Google Docs.
Rastreamento de todos os downloads de APK, orgânicos ou não.
Esses dados são enviados aos servidores da Mintegral.
Comportamento observado
Ao baixar um link do Google Docs, percebemos que o aplicativo enviava as seguintes solicitações para https://n.systemlog.me:

Este é o mesmo endpoint usado no SDK para iOS para enviar dados ao servidor da Mintegral. O payload é codificado, mas podemos usar a lógica de decodificação presente no binário do SDK para obter o seguinte:
Há dois parâmetros codificados adicionais, clever e dvi. Depois de decodificá-los também, percebemos algo interessante:
Como podemos ver, a URL da planilha do Google que baixamos pelo aplicativo Google Drive é enviada ao backend no campo ul, e o nome do arquivo baixado, no campo kw, enquanto dvi contém alguns dados do dispositivo.
Possíveis usos
No caso do iOS, cliques duplicados fraudulentos eram enviados do dispositivo do cliente para os servidores da Mintegral e, em seguida, para o provedor de atribuição (MMP). Neste caso, os APKs baixados ou instalados são reportados aos servidores e podem ser usados para gerar cliques no servidor. O diagrama a seguir demonstra o fluxo de dados:

Módulo Alphab
O comportamento mencionado acima está no módulo alphab, descrito pela Mintegral como um “pacote de otimização”:

Após nossa publicação, o módulo foi removido do site da Mintegral e parece não fazer mais parte do SDK distribuído. Descompilamos o SDK e localizamos o código responsável por esse comportamento.
Classe AlphaCommonConst
Essa classe contém muitas definições de constantes codificadas diretamente no código. Algumas strings são ofuscadas usando um esquema próprio de codificação baseado em Base64, localizado na classe AlphabBase64Util, semelhante ao que observamos na distribuição para iOS.
Após decodificar, obtemos as seguintes strings:
Elas são usadas nas etapas de inicialização que discutiremos a seguir.
Receptor Alphab
No método init() da classe AlphabReceiver, o BroadcastReceiver é inicializado com algumas das strings previamente ofuscadas:
Substituindo-as pelas strings decodificadas, o código fica assim:
Podemos ver que, com o uso da API de reflexão do Java, um novo receptor de broadcast é criado para escutar dois tipos de intents:
android.intent.action.PACKAGE_ADDED- um intent de todo o sistema, acionado quando um pacote é instalado no dispositivo.alphab_net_debug_action- um intent personalizado que parece detectar depuração de rede.
Ao receber o intent, a classe AlphabReceiver cria um método ParseAndLoad():
Esse campo é usado posteriormente em uma condição:
A descompilação dos outros dois métodos nessa cláusula if revela que eles verificam se a conexão de rede atual passa por um proxy Wi-Fi ou um cliente VPN. Isso serve para impedir a depuração do aplicativo e a captura do tráfego. Esse intent permite que os desenvolvedores do SDK contornem essa funcionalidade antidepuração.
Observador Alphab
De forma semelhante, o bloco de inicialização deste ContentObserver também fica oculto em meio a reflexão e strings ofuscadas:
Após a limpeza, obtemos o seguinte:
Isso significa que o observador de conteúdo é registrado para escutar o URI content://downloads e é acionado sempre que um arquivo é baixado no dispositivo.
Ele consulta o gerenciador de downloads do Android para obter os downloads públicos:
e, após decodificar a string, obtemos o seguinte:
Se a URL de download atender a qualquer uma das condições a seguir, será gerado um relatório para https://n.systemlog.met/stlog:
Termina em
apk- para downloads manuais.Refere-se a um pacote pertencente a
com.android.vendingou contém google.com na URL - captura qualquer aplicativo do Google ou até mesmo URLs de navegador que correspondam à condição.
Abaixo está o trecho de código que envia a solicitação ao servidor https://n.systemlog.met/stlog.
que equivale a:
"E aqui podemos ver os parâmetros que observamos na solicitação capturada no nosso exemplo:
p- nome do pacote que está sendo baixado, ou seja, o aplicativov- versão do aplicativoul- URL do arquivo baixadokw- nome do arquivo baixadofl- tamanho do arquivo
Aplicativo de demonstração

Para demonstrar esse comportamento, criamos um aplicativo de demonstração que nos permitiu:
1. Ativar a flag de depuração de rede por reflexão para contornar a lógica antidepuração
2. Baixar um arquivo de uma URL que contém google.com
3. Baixar um arquivo de uma URL que termina em apk
"Capturamos as solicitações de saída usando um proxy HTTP. Depois de clicar em um dos botões de download, vemos uma solicitação sendo enviada ao endpoint do servidor:

Veja um vídeo que demonstra o comportamento de rastreamento:

Linha do tempo
Data | Evento de pesquisa |
|---|---|
5 de ago. | A equipe de pesquisa da Snyk identifica que o SDK para iOS da Mintegral coleta dados em excesso e sequestra cliques |
17 de ago. | A Snyk divulga as descobertas à Apple de forma responsável |
24 de ago. | A Snyk publica as descobertas Sour Mint para iOS |
25 de ago. | A Mintegral publica um comunicado negando as acusações sobre o SDK |
3 de set. | A IronSource anuncia a remoção da Mintegral de sua plataforma de mediação |
3 de set. | A Mintegral lança a versão 6.5.0.0 do SDK para iOS, removendo o componente malicioso e oculto _CXX_CXX_OperationPKTask |
4 de set. | A plataforma de mediação MoPub (Twitter) anuncia a descertificação da Mintegral em sua plataforma |
4 de set. | A Mintegral anuncia planos de abrir o código-fonte do SDK |
4 de set. | A equipe de pesquisa da Snyk identifica uma funcionalidade oculta de rastreamento de downloads na versão Android do SDK |
9 de set. | A Snyk divulga as descobertas sobre o SDK para Android ao Google de forma responsável |
10 de set. | A Mintegral lança a versão 6.6.0.0 do SDK para iOS, removendo o componente de backdoor MTGRemoteCommandParser |
22 de set. | A Snyk obtém o código-fonte da versão 6.6.0.0 do SDK para iOS e realiza uma análise de diferenças |
23 de set. | A Snyk identifica que a Mintegral removeu o módulo de rastreamento de downloads do Google de seu SDK para Android |
30 de set. | Por meio de uma análise de diferenças, a Snyk identifica um backdoor na versão para iOS do SDK que permite RCE |
2 de out. | A Snyk divulga as novas descobertas sobre iOS à Apple de forma responsável |
3 de out. | A Apple notifica os desenvolvedores afetados e pede que removam o código que permite RCE |
15 de out. | A Snyk publica as descobertas mais recentes sobre iOS e Android |



