DEV Community

Darlan Guimarães
Darlan Guimarães

Posted on • Updated on

[PT-BR] Desmontagem e o IDA Pro na Análise de Programas

O processo de desmontagem, também conhecido como disassembly, é essencial na engenharia reversa e análise de programas binários. Envolve a tradução do código de máquina, compreensível apenas pelos computadores, para uma forma textual mais legível para os humanos. Ao desmontar um executável, revertemos o processo de compilação, permitindo a análise detalhada da funcionalidade interna do programa.

IDA Pro 7.5:

Entre as ferramentas disponíveis para desmontagem e análise estática de programas binários, o IDA Pro 7.5 se destaca como uma escolha popular e robusta. Com uma variedade de recursos poderosos, o IDA Pro oferece uma plataforma abrangente para entender a estrutura e o comportamento de programas binários.

Com sua capacidade:

  • Desmontagem de Código: desmonta código de uma ampla variedade de arquiteturas de processadores, permitindo a análise de programas desenvolvidos para diferentes sistemas.

  • Identificação de Funções: identifica e nomeia funções no código desmontado, facilitando a compreensão da lógica do programa.

  • Navegação pelo Código: permite a navegação eficiente pelo código desmontado, facilitando a análise de fluxo de controle e de dados.

  • Descompilação: oferece recursos de descompilação, permitindo a conversão do código de montagem para um nível mais alto de abstração, tornando-o mais próximo do código-fonte original.

O IDA Pro se destaca como uma escolha preferida para engenheiros de segurança, analistas de malware e pesquisadores de software. Vamos explorar como este poderoso conjunto de ferramentas pode ser aplicado para entender a estrutura interna de um arquivo.

Aplicação Prática

Para ilustrar o uso do IDA Pro, consideremos um exemplo simples de um programa em C. Após compilar o código em um executável, podemos analisá-lo no IDA Pro para entender sua estrutura interna e funcionamento.

Código original criado em C:

#include <stdio.h>
#include <stdlib.h>

int soma(int x, int y);

int main() {
    int a, b = 0;

    printf("Digite A: ");
    scanf("%d", &a);
    printf("Digite B: ");
    scanf("%d", &b);

    printf("\n%d + %d = %d\n", a, b, soma(a, b));
}

int soma(int x, int y) {
    int z;
    z = x + y;
    return(z);
}
Enter fullscreen mode Exit fullscreen mode

Essa imagem mostra um trecho do código assembly gerado pelo IDA Pro para o programa em C fornecido.

Imagem da geração do código de descompilação Assembly

O código assembly gerado pelo IDA Pro revela cada instrução exigida pelo executável, incluindo chamadas de funções como printf, scanf e a função soma.

É interessante notar como as chamadas de função em C são traduzidas para o código assembly pelo compilador e como o IDA Pro revela essa estrutura. Por exemplo, quando ocorre a soma no código assembly, é possível observar a instrução lea seguida por uma chamada printf com o uso do call para exibir o resultado da operação.

Análise Detalhada de Funções

Além de mostrar cada instrução chamada pelo .exe, o IDA Pro permite uma análise detalhada das funções específicas dentro do programa. Na imagem abaixo, podemos ver o código assembly da função soma do código em C após ser analisado. Essa representação revela como a função é implementada em código assembly e como ela interage com outras partes do programa.

Imagem da geração do código de descompilação Assembly mostrando as funções

Uma das vantagens do IDA Pro é sua capacidade de identificar e nomear automaticamente as funções no código assembly. Além disso, ele fornece informações úteis sobre cada função, incluindo o endereço de início, tamanho e argumentos esperados.

Por exemplo, ao analisar o código assembly da função soma, o IDA Pro pode fornecer detalhes como o endereço de início da função, o tamanho do código assembly que compõe a função e os argumentos que ela espera receber. Essas informações são essenciais para entender a estrutura e o comportamento do programa em um nível baixo do sistema.

Imagem da geração de funções utilizadas

Também oferece a capacidade de visualizar as strings utilizadas pelo programa. Essas strings podem conter mensagens de texto, nomes de variáveis, chamadas de sistema e outros dados importantes para entender a funcionalidade do programa. A visualização das strings pelo IDA Pro ajuda os analistas a identificarem rapidamente informações relevantes no código binário.

Imagem da geração de strings utilizadas

É importante notar todas as iterações com o usuário, como mensagens de entrada e saída. Por exemplo, ele pode destacar automaticamente strings como "Digite A:" e "Digite B:", que representam solicitações de entrada de dados pelo programa. Essa marcação facilita a identificação e compreensão das interações entre o programa e o usuário durante a execução.

Plugins e Extensões

Além das poderosas ferramentas padrão oferecidas pelo IDA Pro, o software também suporta uma variedade de plugins e extensões que fornecem funcionalidades adicionais para análise de programas binários. Esses plugins podem ser desenvolvidos pela comunidade ou por terceiros e oferecem uma ampla gama de recursos, desde descompilação até análise específica de vulnerabilidades.

Descompilação de Pseudocódigo

Essa ferramenta é capaz de traduzir o código de máquina em um nível mais alto de abstração, fornecendo uma representação mais próxima do código-fonte original. Por exemplo, o trecho de código C fornecido pode ser o resultado da descompilação de um programa binário, oferecendo uma visão mais legível e compreensível do funcionamento do programa.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // eax
  unsigned int v5; // [rsp+28h] [rbp-8h] BYREF
  unsigned int v6; // [rsp+2Ch] [rbp-4h] BYREF

  _main(argc, argv, envp);
  v5 = 0;
  printf("Digite A: ");
  scanf("%d", &v6);
  printf("Digite B: ");
  scanf("%d", &v5);
  v3 = soma(v6, v5);
  printf("\n%d + %d = %d\n", v6, v5, v3);
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

Embora o código descompilado possa não ser idêntico ao código-fonte original, ele ainda oferece uma perspectiva sobre a lógica e a estrutura do programa.

Análise de Código com Estruturas Condicionais

O IDA Pro também permite a análise de estruturas condicionais, como aquelas definidas pelas instruções if, else if e else em programas em C. Vamos considerar o seguinte exemplo de código em C:

#include <stdio.h>
#include <stdlib.h>

int soma(int x, int y);

int main(){
    int a = 100;

    if (a == 0) {
        printf("Variavel A vale zero!");
    }
    else if (a < 10) {
        printf("o A é menor que 10");
    }
    else if (a < 20) {
        printf("o A é menor que 20");
    }
    else if (a == 100){
        printf("o A vale 100");
    }
    else{
        printf("Isso é um erro");
    }

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Quando compilado e analisado, obtemos uma representação em código assembly que reflete a lógica das estruturas condicionais do programa. Essa análise pode ajudar a entender como as decisões são tomadas dentro do programa e como diferentes caminhos de execução são seguidos com base nas condições definidas.

Imagem da geração do assembly mostrando a iteração do programa com as estruturas de comparação

Identifica as iterações das estruturas condicionais presentes no código original e as expressa de uma forma mais legível para os humanos. As divisões por setas ao longo do código descompilado indicam claramente as diferentes iterações através das estruturas condicionais, facilitando a compreensão do fluxo de execução.

Por exemplo, quando o código passa por um bloco if, como aquele que em assembly seria representado por cmp [rbp+var_4], 0, o IDA Pro mostra essa iteração claramente, evidenciando a comparação da região da pilha com zero para determinar se retorna 1 ou 0.
Essa representação com divisões por setas torna ainda mais claro o fluxo de execução através das estruturas condicionais, facilitando a compreensão da lógica do programa.

Descompilação de Pseudocódigo

Agora, se seguirmos o mesmo procedimento anterior e utilizarmos o descompilador para gerar um pseudocódigo a partir do novo executável, obteremos o seguinte resultado:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  _main(argc, argv, envp);
  printf("o A vale 100");
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

Isso ocorre porque o descompilador reconheceu que, no código original, a variável A sempre possui o valor 100, e por isso determinou que as outras linhas não são alcançadas.

Se alterarmos a variável A agora para receber um valor variável:

#include <stdio.h>
#include <stdlib.h>

int soma(int x, int y);

int main(){
    int a = 0;
    printf("Digite o valor para A:");
    scanf("%d", &a);

    if (a == 0) {
        printf("Variavel A vale zero!");
    }
    else if (a < 10) {
        printf("o A é menor que 10");
    }
    else if (a < 20) {
        printf("o A é menor que 20");
    }
    else if (a == 100){
        printf("o A vale 100");
    }
    else{
        printf("Isso é um erro");
    }

    return 0;
}
Enter fullscreen mode Exit fullscreen mode

Agora utilizando a ferramenta de descompilação temos o seguinte retorno:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+2Ch] [rbp-4h] BYREF

  _main(argc, argv, envp);
  v4 = 0;
  printf("Digite o valor de A:");
  scanf("%d", &v4);
  if ( v4 )
  {
    if ( v4 > 9 )
    {
      if ( v4 > 19 )
      {
        if ( v4 == 100 )
          printf("o A vale 100");
        else
          printf("Isso é um erro");
      }
      else
      {
        printf("o A é menor que 20");
      }
    }
    else
    {
      printf("o A é menor que 10");
    }
  }
  else
  {
    printf("Variavel A vale zero!");
  }
  return 0;
}
Enter fullscreen mode Exit fullscreen mode

Podemos observar que o descompilador verifica a existência da variável v4 e, em seguida, inicia o processo de verificação utilizando a estrutura IF. Embora o pseudocódigo resultante não seja perfeito, às vezes é mais simples compreendê-lo do que analisar o código assembly diretamente.

Depuração em Tempo Real:

Além de suas capacidades de análise estática também pode ser usado para depuração em tempo real, permitindo aos usuários acompanhar a execução do programa e examinar o estado dos registradores e da memória durante a execução. Isso é particularmente útil para identificar problemas e entender o comportamento dinâmico do programa.

Imagem de depuração em tempo real

Durante a depuração em tempo real exibe informações detalhadas sobre o estado dos registradores, permitindo que os usuários observem como os valores dos registradores mudam à medida que o programa é executado. Essas informações são cruciais para entender o fluxo de controle e a manipulação de dados pelo programa em tempo real.

Imagem de depuração em tempo real mostrando os registradores no processo de execução

Conclusão

Este mini artigo buscou demonstrar algumas das formas eficazes de utilização do IDA Pro e da desmontagem de código, proporcionando uma visão básica dessas ferramentas. É importante ressaltar que as técnicas apresentadas aqui representam apenas o básico, e há uma infinidade de outras maneiras de aproveitar ao máximo o potencial do IDA Pro para análise de binários. O objetivo principal é fornecer uma introdução acessível a essas ferramentas, incentivando estudos mais aprofundados e uma compreensão mais completa de suas capacidades.

Top comments (0)