Muito bem.
Então, aqui estamos de volta à nossa VM do Ubuntu e agora vamos fazer esse exercício juntos.
Portanto, o que queremos fazer é o seguinte.
Queremos conectar essa função, essa função de dados de linha, e queremos imprimir esses dois parâmetros toda
vez que essa função for chamada.
Portanto, toda vez que pressionarmos esse botão, esses parâmetros, esses valores desses parâmetros deverão ser
impressos em nosso terminal no console livre.
Muito bem.
Não sabemos como fazer isso no momento, mas aprenderemos neste vídeo.
Portanto, faremos o passo a passo e também continuaremos adicionando mais coisas a ele.
Mas isso diz respeito a outras seções.
Neste caso, vamos nos concentrar apenas em imprimir esses valores de parâmetros em nosso terminal.
Muito bem.
E na próxima, aprenderemos a modificá-los e manipulá-los.
Está bem.
Mas, por enquanto, vamos nos limitar a imprimi-los.
Tudo bem.
Portanto, o que precisamos é de nossa página em branco aqui.
Portanto, estamos abrindo o código do Visual Studio e agora estamos criando um novo arquivo JavaScript.
Então, vamos para um novo arquivo e seleciono aqui JavaScript.
Tudo bem.
A primeira coisa que precisamos fazer é informar ao Frida que estamos operando em um sistema
Android e que queremos nos conectar à máquina virtual Java, porque a máquina virtual Java tem a referência
a essas classes.
E esse é o ponto em que precisamos nos conectar a eles e modificá-los.
Podemos fazer isso simplesmente usando a função Java, executando esta aqui.
Portanto, essa é apenas uma chamada de função e será anexada à máquina virtual Java.
Vou encerrar isso rapidamente, pois é um pouco incômodo.
Ok, então essa é a nossa função e, dentro dela, estamos fornecendo um parâmetro, que é uma
função anônima.
Portanto, temos uma função como parâmetro e, por isso, criamos uma nova função e esse é o nosso
corpo.
Tudo bem.
Portanto, essa é a nossa função Java para executar e esse é o nosso parâmetro no momento.
Tudo bem.
E esse é o local onde precisamos inserir nosso código agora.
Está bem.
O que precisamos fazer?
A primeira coisa que precisamos fazer é obter a referência a essa classe.
Qual classe?
Vamos dar uma olhada.
Talvez.
Vamos colocar os dados lado a lado.
Sim, acho que assim fica um pouco mais fácil de acompanhar.
E lá vamos nós.
Está bem.
A classe é public class, DYSON E precisamos obter toda a referência a essa classe porque podemos ter
várias classes com esse nome.
Portanto, também precisamos ter esse nome completo do pacote.
Podemos obter a referência a essa classe com o uso do java.
Sinto muito por manter isso em primeiro plano.
Está bem.
Portanto, estamos usando o java para usar e agora estamos fornecendo todo o nome do pacote.
E este aqui.
DOT E também o nome da classe aqui.
Tudo bem.
E queremos armazenar essa variável em uma variável e nomeá-la, por exemplo, meu dicer.
Agora temos uma variável, meu Dyson, que faz referência a essa classe aqui,
a essa classe Dyson.
Muito bem.
Talvez também devêssemos anotar isso e obter uma referência em meu Dyson da classe.
DYSON Em seguida, queremos substituir o método.
E o método que queremos substituir é o método de lançamento de dados.
Portanto, precisamos usar nossa referência para acessar esse método e podemos fazer isso da seguinte maneira.
My Dyson Isso agora é uma referência a essa classe e, portanto, podemos simplesmente usar o DOT para acessar esse método.
Nesse caso, isso se chama rolar dados.
E agora queremos definir uma nova implementação para esse método aqui.
Portanto, usamos a implementação de ponto igual a e aqui estamos definindo uma nova função.
Novamente, é uma função anônima e este é agora o código ou o local onde precisamos inserir nosso
código que substitui essa função.
Certo, então o que queremos fazer?
Queremos imprimir esses parâmetros.
Tudo bem, mas como podemos acessar esses parâmetros?
Vamos dar uma olhada.
Estamos tendo dois parâmetros no momento.
Um número inteiro de tamanho de pool, um número inteiro de fase nenhum.
Portanto, com relação ao JavaScript, também temos alguns tipos.
Por exemplo, temos uma string booleana e números inteiros, mas não é como em Java, em que precisamos
definir isso com precisão.
Isso está sendo ajustado automaticamente e esse também é o lado ruim do JavaScript.
Portanto, teremos muitos problemas com relação a esses tipos mais adiante, mas aprenderemos a lidar
com esse.
Nesse caso, agora, com relação a esses tipos básicos, por exemplo, cadeias de caracteres ou números inteiros, é muito
fácil para nós.
Tudo o que precisamos fazer é simplesmente fornecer esses parâmetros em nossa função anônima aqui, e então
poderemos acessá-los.
Assim, por exemplo, aqui podemos escrever o parâmetro um e aqui podemos escrever o parâmetro dois.
Não é necessário definir os mesmos nomes ou o tipo que é agora, se estivermos lidando com números inteiros ou cadeias
de caracteres.
Mais adiante, aprenderemos como podemos fornecer parâmetros mais precisos.
Por exemplo, se tivermos um objeto em toda a classe que precisa ser fornecido aqui, precisaremos fazer isso
de forma um pouco diferente.
Mas, com relação a dois parâmetros básicos, podemos nos ater a essa abordagem aqui.
Parâmetro um e parâmetro dois.
Tudo bem.
Agora podemos simplesmente acessá-los para que possamos escrever, enviar e, por exemplo, o parâmetro um é igual.
E então simplesmente anexamos isso aqui.
Parâmetro um Portanto, essa tipificação ocorrerá automaticamente.
Isso é bom no início, mas se tornará pior mais tarde.
Portanto, se tivermos funções mais complexas, queremos conectar ou fornecer novos objetos lá.
Isso pode ser um pouco doloroso, mas, por enquanto, estamos felizes por ser tão fácil.
Tudo bem.
Portanto, esse é o parâmetro um.
E também fornecemos parâmetros para.
Além disso, Parenthood.
Tudo bem.
Isso é tudo o que precisamos fazer agora, certo?
Com certeza.
Isso não é tudo o que precisamos fazer agora, porque o que estamos fazendo agora, se tivermos esse script
dessa forma, estaremos substituindo essa função.
E isso é algo que eu gostaria de explicar a você no tablet gráfico.
Veremos o que acontece se mantivermos o script dessa forma.
Mas isso não funcionará.
Vou lhe mostrar por quê.
Está bem.
Portanto, aqui estamos de volta à mesa digitalizadora.
E agora vou mostrar o que esse script está fazendo no momento.
Portanto, estamos nos conectando à classe de dissecação e a esta aqui, ao lançamento de dados.
E agora estamos substituindo essa função.
Ainda estamos tendo nosso parâmetro por aqui.
Este é o param one e este também é o param one.
Mas agora substituímos essa função da seguinte forma e essa linha não existe mais.
Portanto, isso desapareceu completamente.
Além disso, esse loop for desapareceu completamente.
Além disso, o valor de retorno desapareceu completamente e isso agora é um grande problema.
O primeiro problema é que não recuperamos nossos valores.
Portanto, essa função não está mais retornando nenhum dado.
Portanto, não há dados sendo devolvidos.
Isso não está mais acontecendo na disfunção porque nós a substituímos por esse material.
Mas a disfunção está acontecendo agora.
Ele está pegando esses dois parâmetros e imprimindo-os.
Imprima de um em um e também imprima em um.
E este aqui.
Além de não ter mais nenhuma funcionalidade lá dentro.
Também estamos tendo outro problema.
A função está retornando um array de números inteiros e este aqui e este aqui serão usados na chamada
da função e espera-se que tenham algum valor, porque essa função sempre retornará um valor, pois não podemos
selecionar, por exemplo, dados zero.
Isso não é possível no aplicativo em relação à interface.
Com relação à liberdade, isso é possível, portanto, poderíamos substituir essa função para ter zero dados,
o que significa que estamos retornando uma matriz vazia.
Portanto, estamos retornando um valor nulo ou nem mesmo estamos retornando algo.
No entanto, essa função definitivamente não está retornando os valores corretos, o que significa que o
programa está contando com esses valores e os usará mais tarde.
Mas agora esses valores não estão sendo inicializados ou estão apenas vazios.
Portanto, se o programa ou o aplicativo, e este aqui, nosso aplicativo, tentar acessar esses
valores, ele receberá uma exceção de ponteiro nulo e falhará.
Portanto, esse é o estado em que nos encontramos no momento.
Quero dizer, conseguimos realizar nossa tarefa até agora, imprimindo esses parâmetros, mas o aplicativo não funciona
mais e isso é algo que definitivamente queremos ter.
No entanto, vamos tentar fazer isso neste estágio agora e ver o que acontece.
Muito bem.
Está bem.
Portanto, podemos usar um dispositivo real.
Ou, no meu caso, também demonstrarei isso na máquina virtual, porque esse aplicativo funciona
na máquina virtual.
Ou seja, não precisamos deslizar o diretório em relação a recursos externos, mas esse aplicativo também não
tem o diretório NLP, portanto, não tem arquivos de objetos compartilhados.
Isso significa que esse aplicativo não depende da plataforma e deve funcionar na máquina virtual.
Muito bem.
Ok, vamos esclarecer isso.
Vamos fechar esse aqui.
E agora podemos salvar o script e salvá-lo como podemos salvá-lo ou armazená-lo no diretório do aplicativo.
Então, dentro dos aplicativos, onde o temos?
Design amigável à privacidade.
Agora podemos, por exemplo, nomear esse param hook trace para que possamos usar o script diretamente no freedom ou simplesmente usar a interface
de linha de comando do freedom.
Vou lhe mostrar as duas maneiras agora mesmo.
Portanto, temos que liberar o aplicativo primeiro.
Portanto, precisamos nos conectar à nossa máquina.
Precisamos iniciar um servidor gratuito e, em seguida, precisamos nos conectar a esse servidor gratuito.
Vamos ver.
Shell do ADB.
Temos uma conexão?
Não.
Então, vamos ver se conseguimos estabelecer uma conexão.
ADB Connect.
Conecte-o.
Muito bem, agora adb shell.
Então, precisamos de privilégios de root.
E, em seguida, dentro dos dados, o local temporário aqui terá nosso servidor de dados gratuito.
No meu caso, tenho de fazê-lo.
Acho que uso a versão de 32 bits para o caso de não funcionar, simplesmente mudo para a versão de 64 bits
e depois limpo para saber qual versão é a correta para nossa liberdade aqui.
Portanto, começaremos com a versão de 32 bits.
O servidor gratuito foi iniciado, o que significa que, se você abrir um novo terminal e usar
o Free De como dash, ou seja, obter as informações pela conexão ADB existente dos processos em execução no
smartphone, poderemos ver que o Free De está funcionando até agora e que agora precisamos anexar esse processo.
Portanto, estou abrindo um novo e mantendo este em primeiro plano.
Aqui estamos com esse processo ainda em execução, e agora queremos anexá-lo a esse processo.
Vamos ver como podemos fazer isso.
O que precisamos é do nome do pacote, que obtemos no manifesto do Android.
E este aqui.
Portanto, esse aplicativo será identificado por esse nome de pacote.
E essa também é a maneira como Frieda, a maneira como Frieda usa isso para identificar esse aplicativo.
Por isso, queremos examinar esse processo com a Frieda por meio da conexão ADB.
Tudo bem.
Parece funcionar.
Estamos tendo nosso console Frieda.
E não há erros no momento.
Agora, vamos também manter isso em primeiro plano.
Está bem.
Primeiro, verificamos se o aplicativo ainda funciona.
Então, ao clicar em corantes brutos, sim, podemos ver que está funcionando e também está funcionando corretamente, acho que porque estamos
recebendo de volta valores aleatórios.
Talvez devêssemos mudar para cinco.
Sim.
Está bem.
Parece bom no momento.
Agora, pegamos todo esse script, copiamos e colamos tudo aqui e o inserimos aqui.
Está bem.
Isso parece um pouco confuso, mas funciona diretamente se você pressionar Enter, portanto, não é necessário ajustar
nada.
Médico.
Agora aplicamos nosso script a essa instância do Frida, o que significa que o Frida se
conectou à máquina virtual Java e substituiu essa função.
Isso significa que, se você estiver usando essa função em nosso aplicativo, agora estamos chamando nossa versão modificada.
Vamos ver o que acontece se clicarmos em Roll Dice.
O aplicativo travou e vamos subir e ver para que possamos ver.
Talvez seja melhor aumentar um pouco o tamanho.
Portanto, podemos ver que estamos recebendo nossas duas mensagens.
Portanto, podemos ver que o parâmetro um deve ser o número cinco e o parâmetro dois foi o número seis, absolutamente perfeito.
Isso estava correto.
Mas então temos esse erro aqui, a implementação de erro para lançar dados esperava um valor de retorno
compatível com.
E aqui estamos tendo nossa taxa de erro inteira.
Notamos agora mesmo em nosso caminho sorridente.
Tudo bem.
Freida é incrível e prestativa quando se trata de erros.
Então, Frieda nos diz: "Bem, eu me conectei ao parâmetro um e o imprimi aqui, e também
me conectei ao parâmetro dois e o imprimi aqui".
Mas essa função espera uma matriz de números inteiros e você não retorna nada.
Neste momento, você substituiu esse método, mas não está retornando nada aqui.
Por isso, estamos recebendo uma exceção de ponteiro de nó e falhamos completamente.
Então, como podemos corrigir esse problema?
Bem, isso depende, é claro, do que estamos tentando alcançar em nosso caso no momento.
Tudo o que queremos fazer é nos conectar a esse método.
Queremos imprimir esses parâmetros e, em seguida, queremos que o método original seja chamado.
Você se lembra de como podemos fazer isso?
É claro que sim.
Sim, absolutamente certo.
Precisamos chamar o método original e isso é tudo.
E podemos chamar o método original da seguinte maneira.
Esse dado foi lançado e aqui está.
Se tentarmos fazer isso agora, ainda assim fracassaremos.
A razão para isso é que agora estamos chamando o método original sem nenhum parâmetro.
Isso seria como ter esse método aqui.
Este não.
Este aqui, sem ter nenhum parâmetro.
O aplicativo ainda travará porque tentará inicializar novas matrizes e preenchê-las.
Mas não fornecemos nada aqui.
No entanto, vamos tentar fazer isso e ver como a resposta é livre.
Portanto, precisamos iniciar esse aplicativo mais uma vez porque ele sofreu uma falha.
Aqui está.
Provavelmente funciona.
Com relação ao nosso servidor Freedom, este ainda está em execução.
Tudo o que precisamos fazer é nos conectar novamente a esse processo de aplicação.
Agora estamos conectados, aumente um pouco o tamanho.
E agora pegamos nosso novo script.
Neste aqui e o aplicamos aqui.
Está bem.
Não se preocupe com isso.
Apareça aqui.
Basta pressionar Enter depois de copiar.
Colei-o aqui.
Tudo bem.
Portanto, agora estamos chamando o método original.
Mas esquecemos os parâmetros.
Fizemos isso de propósito.
E vamos ver como a Frieda reage.
Portanto, se você abrir esse aplicativo mais uma vez e clicar em rolar dados, veremos que ele trava mais
uma vez.
Então vamos ver.
Que horas são?
O erro.
E aqui temos dados de rolagem.
Os tipos de argumento não correspondem a nenhuma sobrecarga.
Voltaremos a essa sobrecarga em uma seção posterior.
Portanto, não estamos lidando com isso no momento.
Está bem.
Além desse tanque de sobrecarga aqui, podemos ver que essa função espera dois parâmetros, esses dois parâmetros inteiros,
e podemos ver que os tipos de argumentos não correspondem a nenhum deles.
Portanto, esse pode ser o caso em dois cenários.
O primeiro é que estamos fornecendo o número errado de argumentos.
E, por exemplo, ou neste exemplo, não estamos fornecendo nenhum argumento ou parâmetro.
E isso não é compatível com essa função aqui.
O caso superior seria que estamos fornecendo os tipos errados de parâmetros ali, e esse é um pouco mais
complicado.
E isso também está relacionado a essa sobrecarga.
Aprenderemos como fazer isso em outra seção.
Por enquanto, sabemos que, ok, não fornecemos nenhum parâmetro ali.
Portanto, nosso problema agora é com relação à quantidade de parâmetros que estamos fornecendo a essa função,
que é zero.
Se voltarmos aqui, veremos que não estamos fornecendo nada.
Portanto, o que precisamos fazer é simplesmente passar os parâmetros daqui de volta para a função original.
Em seguida, essa função original é chamada com os parâmetros corretos que também foram inseridos nessa função
anteriormente.
Tudo bem.
Portanto, no parâmetro um e no parâmetro dois.
Está bem.
Então, o que você fez agora?
Nós fisgamos a classe a seguir.
Transformamos isso em uma classe e definimos uma nova implementação para esse método.
Agora dizemos: imprima os dois parâmetros que você está fornecendo a essa função.
Estamos fazendo isso aqui.
E também precisamos chamar a função original que esta aqui está retornando.
Uma matriz de números inteiros nessa função requer dois parâmetros e estamos pegando os parâmetros originais,
esses dois, e passando-os simplesmente por essa função aqui.
Tudo bem.
Então, vamos ver agora mesmo se este funciona, portanto, temos que reiniciar o aplicativo mais uma vez.
Aqui está.
Vamos ver como isso funciona.
Agora estamos usando nossa linha de comando gratuita para anexar a esse processo.
Mais uma vez, colamos esse código, pressionamos enter e agora vamos ver se funciona.
Lance os dados.
E ainda recebemos um erro.
O quê?
Por que isso é tão complicado?
O motivo disso é que, no momento, não estamos devolvendo nada.
Portanto, estamos apenas chamando essa função.
Mas não estamos usando isso na declaração de retorno.
Então, vamos descobrir o que fizemos até agora e por que ainda não está funcionando.
A primeira coisa que fizemos foi substituir todo esse método aqui.
Portanto, esse foi completamente apagado.
E substituímos essa parte por apenas algumas instruções de impressão referentes a esses dois parâmetros.
Então, descobrimos que essa função aqui está retornando uma matriz de números inteiros, uma matriz
de números inteiros, e essa está sendo usada no código do aplicativo.
Portanto, se você não estiver retornando essa matriz.
Se esse não for o caso, encontraremos uma exceção.
Portanto, a minha tentação no momento era simplesmente chamar o método original, e isso deveria retornar
nosso array de números inteiros aqui.
Portanto, se voltarmos ao nosso script, este aqui, chamamos o método original aqui
mais uma vez.
Portanto, este agora deve retornar nosso array de bytes.
E este aqui.
E tudo deve funcionar, certo.
Quero dizer, também descobrimos que precisamos fornecer esses dois parâmetros ao método original.
Ligue para cá.
Portanto, esses dois.
Por que ainda está gerando erro?
O motivo disso é que este é o nosso script de teste gratuito aqui.
Vamos escrever isso aqui.
E agora substituímos esse método.
Esse foi o primeiro passo.
Mas também chamamos o método original, que é este agora.
E esta é a segunda etapa.
O problema é que esse método é chamado.
Portanto, Frieda está chamando o método original aqui.
E este está simplesmente voltando à liberdade.
Mas não estamos fazendo nada com esse valor de retorno aqui.
Portanto, esse está retornando, essa matriz de números inteiros.
Mas precisamos passá-lo também para nossa função aqui.
Portanto, aqui estamos chamando essa função.
Estamos chamando essa função do método original.
E este e este estão retornando nosso valor de retorno, que é a matriz de números inteiros.
Mas não estamos fazendo nada com esse.
O que precisamos fazer é iniciar isso em um ponto muito capaz aqui para que possamos atribuir uma nova variável ou simplesmente
retornar toda essa declaração aqui para que possamos simplesmente escrever.
Talvez.
Vou limpar isso rapidamente.
Aqui está.
Assim, poderíamos simplesmente retornar à direita.
Essa chamada de método original.
E o que este faz é o seguinte: o que estamos fazendo aqui é o nosso script de liberdade.
Este agora está chamando o método original.
Nesse método original, ele agora está retornando essa matriz de números inteiros, e essa matriz será retornada
em liberdade.
Portanto, essa é a declaração aqui, essa matriz de números inteiros.
E então ele deve funcionar.
Sei que isso é um pouco exagerado em relação à explicação, mas se não considerarmos todos os aspectos, teremos
problemas e nos perguntaremos por que as coisas não funcionam.
Portanto, manterei esta explicação bem detalhada sobre o que está acontecendo aqui.
E, sim, desculpe-me se eu o peguei emprestado nesse ponto e se você já está familiarizado com a Frieda, mas é muito
importante que saibamos tudo o que está acontecendo aqui e por que as coisas não estão mais funcionando.
Muito bem.
Agora, vamos voltar e aplicar esse pequeno patch para que este aqui finalmente funcione.
Vamos lá.
Bem, aqui estamos de volta.
Vamos limpar a tela e pronto.
Está bem.
E o que precisamos fazer é simplesmente anexar essa instrução de retorno.
Agora estamos chamando esse método original e passando o valor de retorno do método
original para o nosso método de liberdade aqui.
Isso deve funcionar agora mesmo.
Vejamos.
E isso está abrindo esse aplicativo e parece travar.
Portanto, vamos simplesmente reiniciá-lo.
Aqui está ele mais uma vez.
E vamos ver se esse aplicativo ainda está sendo aberto.
Aqui está.
Está bem.
Ele está reiniciando porque travou antes.
Vejamos, está funcionando agora.
Vamos liberar o terminal.
Onde o temos?
O que está em vermelho com todas essas mensagens de erro.
Precisamos nos conectar a esse processo mais uma vez.
Aplicamos nosso roteiro.
Pressionamos enter.
E agora vamos ver.
Jogue os dados.
Aqui está.
Podemos ver isso.
Aqui está a função que ainda está funcionando, mesmo pressionando-a várias vezes.
E podemos ver que o parâmetro um é cinco e o parâmetro dois é seis.
Então, vamos ver se podemos alterá-los aqui.
Sim, podemos ver que essas alterações também afetam nossa saída de depuração aqui.
Então, isso é incrível e extremamente útil.
Eu o utilizo bastante em relação a funções de senha e funções criptográficas.
Por exemplo, temos uma implementação do AZ e a função recebe como entrada o vetor de inicialização, a chave
e esses dois valores que precisamos descriptografar ou criptografar e a mensagem ou esse pacote ou o que quer
que tenhamos criptografado aqui, bastando conectar-nos à implementação do AZ para imprimir os valores que estão
sendo passados para essa função.
Quero dizer, neste caso, temos apenas valores inteiros, mas também podemos ter um vetor de inicialização.
E sim, a chave que está sendo usada para descriptografar e criptografar esse material.
Toda essa configuração leva apenas alguns minutos.
Se já tivermos identificado essa função, que é responsável por ela, então, sim, temos todo o material necessário
para descriptografar ou criptografar essas mensagens.
Teremos alguns exemplos mais adiante.
Mas, por enquanto, antes que eu comece a me empolgar, precisamos primeiro de alguns princípios básicos.
Tudo bem.
Está bem.
Portanto, é assim que podemos trabalhar no parâmetro de função e imprimi-lo com relação a todo o conceito aqui e também à
explicação de por que as coisas não funcionaram da maneira correta.
Acho que você pode imaginar como podemos manipular isso neste momento.
Portanto, essa é a sua tarefa na próxima seção: manipular esses parâmetros em vez de usá-los
a partir do aplicativo original.
Vamos ajustar nossos próprios parâmetros para que, independentemente do que for selecionado aqui, o número de dados
ou o número de faces, substituamos isso por nossos próprios valores estáticos.
Então, por exemplo, para sermos um pouco mais precisos, digamos que nosso desafio
seja sempre retornar para isso entre os números um e três.
Portanto, esse é o desafio para os números um e três, independentemente do que eu selecionar aqui.
Muito bem.
Tudo bem.
Portanto, essa é a tarefa para o próximo desafio, caso você tenha um pouco de dificuldade, não se preocupe.
Faremos isso juntos no próximo.
E estou realmente ansioso para vê-lo lá.