Como a Apple sabe que você está usando uma API privada?

109

Enviei um arquivo binário para a Apple sem nenhum código-fonte.

Além de verificar manualmente o código-fonte, como a Apple sabe o que foi usado e quais APIs você chamou?

Tattat
fonte
título alterado - suponho que você quis dizer "Como a Apple sabe ..."
Anurag

Respostas:

173

Existem 3 maneiras que eu conheço. Essas são apenas algumas especulações, já que não trabalho na equipe de revisão da Apple.

1 otool -L

Isso listará todas as bibliotecas às quais o aplicativo está vinculado. Algo claramente que você não deve usar, como IOKit e WebKit, pode ser detectado por isso.

2 nm -u

Isso listará todos os símbolos vinculados. Isso pode detectar

3. Listando seletores Objective-C, ou strings

Os seletores Objective-C são armazenados em uma região especial do binário e, portanto, a Apple pode extrair o conteúdo de lá e verificar se você usou alguns métodos Objective-C não documentados, como -[UIDevice setOrientation:].

Como os seletores são independentes da classe com a qual você está enviando mensagens, mesmo que sua classe personalizada seja -setOrientation:irrelevante para UIDevice, haverá a possibilidade de serem rejeitados.


Você pode usar o APIKit de Erica Sadun para detectar rejeição potencial devido a (falsos alarmes de) APIs privadas.


(Se você realmente realmente deseja contornar essas verificações, pode usar recursos de tempo de execução como

  • dlopen, dlsym
  • objc_getClass, sel_registerName, objc_msgSend
  • -valueForKey:; object_getInstanceVariable, object_getIvar, etc.

para obter essas bibliotecas privadas, classes, métodos e ivars. )

Kennytm
fonte
Ótima resposta. Acrescentarei apenas que, se o seu aplicativo está fazendo algo extremamente difícil de fazer sem usar uma API privada, tenho certeza de que o seu aplicativo receberá um exame mais minucioso.
Matthew Frederick
Estou curioso sobre a solução alternativa para chamar métodos privados. Acho que o compilador irá gerar uma chamada para objc_msgSend (foo, @selector (privateMethod)) para [foo privateMethod], portanto, se a Apple puder detectar a chamada direta de privateMethod, eles também poderão detectar a chamada indireta via objc_msgSend (ou performSelector :).
an0
Estou me perguntando por que você diz que não deve vincular ao IOKit e ao WebKit?
hjaltij
2
No que você executa o otool? O arquivo .app?
Rob
1
@Eric, eles poderiam , embora tal versão instrumentada provavelmente afetaria o desempenho. Independentemente disso, vendo APIs privadas entrarem na App Store repetidamente, fica claro que elas não fazem isso, ou pelo menos não fazem isso o tempo todo.
Nate
26

Você pode listar os seletores em um programa Mach-O usando o seguinte one-liner no Terminal:

otool -s __TEXT __objc_methname "$1" |expand -8 | cut -c17- | sed -n '3,$p' | perl -n -e 'print join("\n",split(/\x00/,scalar reverse (reverse unpack("(a4)*",pack("(H8)*",split(/\s/,$_))))))'
Robert Diamond
fonte
+1, @Robert Diamond, você pode descrever mais para o mesmo. Eu preciso verificar o Google analytic usa chamada UDID ou não. Obrigado
Mangesh
13

Digamos que você queira usar alguma API privada; o objetivo C permite que você construa qualquer SEL a partir de uma string:

   SEL my_sel = NSSelectorFromString([NSString stringWithFormat:\
@"%@%@%@", "se","tOr","ientation:"]);
    [UIDevice performSelector:my_sel ...];

Como um robô ou uma varredura de biblioteca pode detectar isso? Eles teriam que detectar isso usando alguma ferramenta que monitora acessos privados em tempo de execução. Mesmo se eles construíram uma ferramenta de tempo de execução, é difícil de detectar porque essa chamada pode estar oculta em algum caminho raramente exercitado.

Chris McLuvin
fonte
O usuário1203764 comenta que esse tipo de chamada pode realmente ser detectado
Rup
@Rup quer dar uma opinião sobre minha dúvida aqui sobre o uso de valueForKey, por favor? stackoverflow.com/questions/11923597/…
Dan Rosenstark
1
@Yar pergunta interessante! Mas não sou especialista o suficiente para comentar. O que Farcaller disse parece razoável para mim
Rup
Obrigado @Rup, aparentemente ninguém é especialista o suficiente neste campo :)
Dan Rosenstark
Alguém que conheço disse que acabou de receber uma ligação como essa na App Store.
bugloaf
7

Eu imagino que eles olhem para todos os símbolos que seu binário está tentando importar (informações sem dúvida facilmente disponíveis para eles na tabela de símbolos) e avisam você se algum desses símbolos for encontrado em sua "lista de API privada". Muito fácil de automatizar, na verdade.

Alex Martelli
fonte
1
Na verdade, posso dizer com certeza que não é esse o caso (pelo menos não é tudo o que eles fazem), com base no uso de API privada que sei que conseguiu. Se isso fosse tudo o que fosse necessário, o uso privado da API não escaparia . Minha experiência sugere que a resposta do KennyTM quase certamente está correta. Esta é uma área onde Objective-C é fundamentalmente diferente de outras linguagens, como C.
Nate
1

Um executável não é exatamente uma caixa preta. Se você chamar uma biblioteca, é uma coisa fácil de encontrar. É por isso que lamento a perda das linguagens assembly nas modernas escolas de ciência da computação. =] Ferramentas como o ldd dirão a você o que você vinculou, embora eu não me lembre de qual encarnação do ldd chegou ao mac iPhone dev kit.

Sniggerfardimungus
fonte
1
Eu freqüentemente me pergunto: se você fosse escrever seu binário para se auto-modificar, apenas gerando o código para importar uma API privada depois que alguns critérios fossem atendidos (digamos, após a data de publicação de seu aplicativo), se a Apple iria pegá-lo. Eles certamente nos reportam algumas estatísticas interessantes, como o número de nossos jogos que estão sendo executados em telefones desbloqueados.
Sniggerfardimungus de
@ user30997, O código privilegiado provavelmente só pode ser acessado por meio de uma chamada de sistema; o thread em execução muda para um privilégio superior e verifica se o privilégio anterior tem permissão para executar o código ou não. Isso é apenas um exemplo, porém, existem outras maneiras de fazer isso, mas eu altamente duvido que os desenvolvedores foram suficientes ingênuo para deixar de fora um privilégio básica de tempo de execução mecanismo de verificação como este, seria definitivamente foram publicados até agora.
L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳
1
otool -L somebinary
dvenema
fonte
1

além da investigação do símbolo ...

apple poderia muito facilmente ter uma versão do sdk que verifica cada uma das pilhas de métodos privados quando chamado para garantir que foi inserido a partir de um dos métodos designados.

Grady Player
fonte
Isso não será suficiente, porque o programa só pode chamar essa chamada privada em um momento arbitrário no futuro, dependendo de outra lógica. Para fazer esse escrutínio, a Apple deve realmente bloquear APIs privadas por completo, ou fazer com que as estruturas relatem chamadas de API privadas para a Apple automaticamente - o que prejudica significativamente o desempenho.
Motti Shneor
0

Mesmo se você estiver vinculando estaticamente, na pior das hipóteses, eles poderiam pegar amostras do código das APIs privadas em sua lista e pesquisar seu binário nelas (também relativamente fácil de automatizar).

Conhecendo a Apple, aposto que eles têm um sistema abrangente e automatizado, e qualquer incerteza provavelmente é negada ou revisada manualmente.

No final do dia, acho que provavelmente não vale a pena tentar enganar a Apple.

lavar
fonte
4
Conhecer a Apple seu processo de revisão ao encontrar qualquer incerteza envolve quebrar um conjunto de dados para capricho máximo.
APENAS MINHA OPINIÃO correta
0

Este aplicativo de desktop, App Scanner , pode escanear arquivos .app para uso privado de API, separando o arquivo Mach-O Binary. Se puder, a Apple também pode!

Andrew
fonte
0

Existem muitas ferramentas para engenharia reversa que permitem inspecionar um código

  • nm - lista os símbolos dos arquivos objeto
  • objdump - exibe informações de arquivos de objeto.
  • otool- visualizar o conteúdo dos executáveis Mach-O [Sobre]
  • strings - isso vai te dar todas as cordas.

Você pode encontrar exemplos / representação do uso desses comandos em gists para Objective-C e Swift

yoAlex5
fonte