Jump to content

Fabiano Furtado

Apoiador Nibble
  • Content Count

    46
  • Joined

  • Last visited

Posts posted by Fabiano Furtado

  1. Pessoal,

    boa noite. Estava pensando em fazer um programa em C para inserir NOPs entre duas funções quaiquer da section .text de um binário ELF.

    Seria mais para fins de estudos mesmo, sem muito objetivo prático.

    Alguém já pesquisou sobre isso? Será que vale o esforço?

    Imagino que não seja algo muito fácil de se fazer, uma vez que temos várias referências de chamadas de funções dentro de um binário.

    Desde já, agradeço.

  2. Em 18/05/2019 em 08:09, fredericopissarra disse:

    Um artiguinho meu (e o follow up mostrando como montei o gráfico animado) - escritos em Agosto de 2017:

    https://bitismyth.wordpress.com/2017/08/23/estatisticamente-insignificante/

    https://bitismyth.wordpress.com/2017/08/25/o-grafico-animado-dos-sorteios-howto/

    Muito bom os artigos!!!! Realmente fica quase impossível adivinhar esses números diante de tantas possíveis combinações.

  3. Pessoal, desenvolvi recentemente 2 programas em C para gerar e filtrar números/combinações numéricas das loterias Dupla Sena e Lotofácil (eles podem ser adaptados facilmente para outros tipos de concursos, por exemplo).

    Gostaria de um feedback de vocês pois não sei se fiz da melhor forma possível. Achei a leitura do arquivo texto contendo as combinações um pouco lenta.

    Enfim... todas as críticas são bem-vindas pois tenho certeza que poderia ter feito ele de outra maneira mais otimizada.

    https://github.com/fabianofurtado/random-lottery-numbers

    Há, basicamente, duas formas de vocês o utilizarem:

    1) Através de um arquivo texto contendo as combinações (pode ser gerada no random.org)

    2) Através do parâmetro -n onde o sistema utilizará as funções srand() e rand() da libc.

    Valeu!

  4. Pessoal,

    estou estudando alguns tópicos do livro "Reversing: Secrets of Reverse Engineering" do Eldad Eilam, ano 2005, mais espeficificamente o capítulo "10- Antireversing Techniques".
    Neste capítulo há muito conteúdo, mas a dúvida é sobre o "Garbage Byte", técnica onde se coloca bytes em posições estratégias do binário para dificultar o disassembly, combinado com os métodos que os disassemblers utilizam para fazer o reversing de forma correta. O livro apresenta duas técnicas chamadas de Linear Sweep e Recursive Traversal. Segundo o autor, este exemplo do livro...

    _asm
    {
      mov eax, 2
      cmp eax, 3
      je Junk
      mov eax, After
      jmp eax
    Junk:
      _emit 0xf
    After:
      mov eax, [SomeVariable]
      push eax
      call AFunction
    }

    ... confunde os disassemblers, independentemente da técnica utilizada (Linear Sweep ou Recursive Traversal). "A razão pela qual esse truque funciona é bem trivial - porque o disassembler não tem idéia de que a sequencia mov eax, After, jmp eax é equivalente a jmp After...".

    Neste exemplo temos 2 "pegadinhas" para os disassemblers. A primeira é um jump condicional, que sempre será incondicional pois a comparação feita sempre será com constantes (2 e 3). A segunda é esse conjunto "mov eax, After, jmp eax", já citado anteriormente.

    Bem, implementar uma nova técnica de disassembler mais inteligente é muito complicado? Pelo menos uma técnica onde se consiga avaliar os saltos baseados em constantes, como no exemplo acima. Acredito que seja complexo pois este livro é de 2005 e até hoje os disassemblers não a implementaram. Alguém já teve alguma experiência com isso? Saberia me apontar a dificuldade em se implementar tal técnica?

    Em tempo, sugiro a leitura e estudo deste livro. Estou achando excelente o seu conteúdo.

    Desde já, agradeço.

    • Curtir 1
  5. Pessoal... eu queria poder utilizar essa técnica com o ALSR ativado. Então, continuando a pesquisa sobre o assunto, descobri que precisaria do valor do EIP para fazer o "jump" para o endereço randomizado. Lendo sobre isso em https://stackoverflow.com/questions/8333413/why-cant-you-set-the-instruction-pointer-directly, descobri que não tem como ler diretamente ou escrever para o EIP usando os opcodes normais. Somente as instruções JMP, CALL ou RET é que podem alterar o EIP. Desta forma, criei uma função get_eip() para alterar o EIP para fazer o JMP incondicional.

    Segue o programa em C modificado:

    #include <stdio.h>

    void get_eip(void) {
      return;
    }

    int main(void) {
      int c = 0;
      c++;
      
      if ( c == 1 ) {
        get_eip(); // faz o JMP para 'end:' (goto end;)
        //goto end; // Comentei pois estou forcando o jump dentro da get_eip()
      }

      do {
        puts("Dentro do while");
        goto end;    
      } while (1);

      puts("antes do Fim");
      
    end:
      puts("Fim");
      
      return 0;
    }

    Depois de compilar com "gcc -Wall -m32 -O0 salto.c -o salto" (utilizando ALSR), o programa ficou assim:

    0000118d <get_eip>:                                                                                                  
        118d:       55                      push   ebp                                                                   
        118e:       89 e5                   mov    ebp,esp                                                               
        1190:       e8 6f 00 00 00          call   1204 <__x86.get_pc_thunk.ax>                                          
        1195:       05 6b 2e 00 00          add    eax,0x2e6b                                                            
        119a:       90                      nop                                                                          
        119b:       5d                      pop    ebp                                                                   
        119c:       c3                      ret                                                                          

    0000119d <main>:                                                                                                     
        119d:       8d 4c 24 04             lea    ecx,[esp+0x4]                                                         
    .....
        11c9:       75 05                   jne    11d0 <main+0x33>                                                      
        11cb:       e8 bd ff ff ff          call   118d <get_eip>                                                        
        11d0:       83 ec 0c                sub    esp,0xc                                                               
        11d3:       8d 83 08 e0 ff ff       lea    eax,[ebx-0x1ff8]
    .....
    Após a alteração dos opcodes, a função get_eip() ficou assim:

    0000118d <get_eip>:                                                                                                  
        118d:       58                      pop    eax                               ; Retira o endereco do IP da pilha e o copia em  EAX
        118e:       05 13 00 00 00          add    eax,0x13       ; Soma o IP com 0x13 para fazer o salto de 19 instruções

        1193:       50                      push   eax                          ; Joga o novo endereço do IP na pilha
        1194:       c3                      ret                                      ; Altera o EIP e altera o fluxo para a label "end" do programa em C

    Bom, resumindo, a bagaça funcionou.

    Entretanto, gostaria de saber se há alguma forma mais simples de se manipular o EIP e fazer essa operação sem o uso de call.

    Alguém mais experiente poderia ajudar nisso?

    Obrigado desde já.

    • Curtir 1
    • l33t 1
  6. 5 horas atrás, rcimatti disse:

    Claro, segue abaixo a saída do gdb do programa original:

    .........

    Aproveitei pra anexar os binários aqui no post também.

    Abs,

    Rafael

    salto

    salto-original

    Rafael, descobri o que estava fazendo de errado, graças aos seus binários!!!

    Estava compilando com o PIE ativado! E como o PIE é para suportar randomização de espaço de endereço (ASLR) em arquivos executáveis, coloquei um "-no-pie" na linha de compilação do gcc (gcc -Wall -no-pie -m32 -O0 salto.c -o salto) e deu certo!

    Como o endereçamento é dinâmico, a probabilidade de dar um Segmentation Fault é altíssima! Desabilitando isso, resolve.

    Obrigado!

    • Curtir 1
  7. 3 horas atrás, rcimatti disse:

    Bom dia Fabiano,

     

    Fiz o teste por aqui e funcionou sem problemas, será que o endereço do push está correto? Estou anexando o print do hte mostrando a parte modificada (e funcionando), se quiser o binário me avisa.

     

    Att,

    Rafael

    Oi Rafael, primeiramente, obrigado pelo retorno.

    Você pode colocar os opcodes que você usou para as novas intruções?

    Repeti o processo e ainda estou com o "Segmentation Fault".

    Desde já, agradeço.

    • Curtir 1
  8. Pessoal,

    bom dia. Estou estudando algumas técnicas de proteção de binários, me baseando no video do Fernando Mercês do Roadsec 2017 https://www.youtube.com/watch?v=cpU9U0sqzh4

    Mais especificamente, em 27'29", o Fernando mostra como substituir algumas instruções por outras equivalentes, para dificultar a análise do binário.

    Fiz exatamente isso, mas o programa da um Segmentation Fault após a alteração, e eu não tenho idéia do que pode ser. Alguma ajuda?

    Segue o programa exemplo em C que fiz para alterar o JMP:

    #include <stdio.h>
    int main(void) {
      int c = 0;
      c++;
      
      if ( c == 1 ) {
        __asm__("nop");
        __asm__("nop");
        __asm__("nop");
        __asm__("nop");
        goto end;
      }

      do {
        puts("Dentro do while");
        goto end;    
      } while (1);

      puts("antes do Fim");
      
    end:
      puts("Fim");
      
      return 0;
    }

    Compilei ele com: gcc -Wall -m32 -O0 salto.c -o salto

    Seguem as linhas originais:

        11b5:       83 7d f4 01             cmp    DWORD PTR [ebp-0xc],0x1                                                    
        11b9:       75 06                   jne    11c1 <main+0x34>                                                           
        11bb:       90                      nop                                                                               
        11bc:       90                      nop                                                                               
        11bd:       90                      nop                                                                               
        11be:       90                      nop                                                                               
        11bf:       eb 13                   jmp    11d4 <main+0x47>                                                           

        11c1:       83 ec 0c                sub    esp,0xc                                                                    
        11c4:       8d 83 08 e0 ff ff       lea    eax,[ebx-0x1ff8]                                                           
        11ca:       50                      push   eax                                                                        
        11cb:       e8 60 fe ff ff          call   1030 <puts@plt>                                                            
        11d0:       83 c4 10                add    esp,0x10                                                                   
        11d3:       90                      nop                                                                               
        11d4:       83 ec 0c                sub    esp,0xc                                                                    
        11d7:       8d 83 18 e0 ff ff       lea    eax,[ebx-0x1fe8]

    Seguem as linhas alteradas:

        11b9:       75 06                   jne    11c1 <main+0x34>                                                           
        11bb:       68 d4 11 00 00          push   0x11d4                                                                     
        11c0:       c3                      ret                                                                               

        11c1:       83 ec 0c                sub    esp,0xc                                                                    
        11c4:       8d 83 08 e0 ff ff       lea    eax,[ebx-0x1ff8]                                                           
        11ca:       50                      push   eax                                                                        
        11cb:       e8 60 fe ff ff          call   1030 <puts@plt>                                                            
        11d0:       83 c4 10                add    esp,0x10                                                                   
        11d3:       90                      nop                                                                               
        11d4:       83 ec 0c                sub    esp,0xc                                                                    
        11d7:       8d 83 18 e0 ff ff       lea    eax,[ebx-0x1fe8]

    Alguma ajuda?

    Desde já, agradeço.

    • Agradecer 1
    • l33t 1
  9. Pessoal,

    tudo bem? Estou estudando esse universo chamado C e desenvolvi uma aplicação simples que é um gerador genérico de chaves para um aplicativo qualquer. Ele soma os valores ASCII do array de caracteres gerado aleatoriamente e gera a chave baseado nesta soma. Bem simples.

    Gostaria de opiniões, críticas e sugestões.

    Link: https://github.com/fabianofurtado/my_keygen

    Agradeço desde já.

    • Curtir 4
  10. Pessoal,

    acredito que todos já saibam disso pois faz parte da matemática básca, mas é interessante pensar sobre: na matemática, só existe SOMA!

    Eu considero que a subtração, a multiplicação e a divisão são "alias" (ou atalhos) para a soma.

    Por exemplo:
    * quando fazemos 3 - 2 = 1, estamos fazendo uma soma pois, na verdade, estamos fazendo 3 + (-2) = 1
      (soma de um número positivo com um número negativo)
    * quando multiplicamos 3 * 2 = 6, estamos fazendo várias somas pois, na verdade, estamos fazendo 2 + 2 + 2 = 6
      (estamos somando N vezes um número)
      Uma coisa interessante... sabemos que o resultado de 3 * 2 = 2 * 3, mas em nível de processamento, é diferente: 3 * 2 = 2 + 2 + 2 e 2 * 3 = 3 + 3
    * quando dividimos 6 / 3 = 2, estamos fazendo soma pois, na verdade, estamos somando quantas vezes 3 "cabe dentro" de 6.
      (ou podemos pensar que a subtração é o contrário da multiplação e que a multiplicação é uma soma)

    Mas e daí? Qual a relação disso com a computação? 

    Se pensarmos em um microprocessador moderno, sabemos que ele possui instruções específicas para somar e subtrair, por exemplo. Entretanto, conseguiríamos desenvolver um microprocessador mais simples somente com a instrução de soma e chegaríamos no mesmo resultado.

    Como dizia o Fernando Mercês, o computador é uma máquina de calcular gigante! (e que só faz soma!) ;)

    É isso. Será que estou errado em pensar assim?

    Desde já, obrigado.

    • Agradecer 2
    • Curtir 2
×
×
  • Create New...