Jump to content

Protetores de Binários


Fabiano Furtado

Recommended Posts

  • Supporter - Nibble

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.

Link to comment
Share on other sites

  • Supporter - Nibble
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.

Link to comment
Share on other sites

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

   0x08048427 <+28>:    83 7d f4 01    cmp    DWORD PTR [ebp-0xc],0x1
   0x0804842b <+32>:    75 06    jne    0x8048433 <main+40>
   0x0804842d <+34>:    90    nop
   0x0804842e <+35>:    90    nop
   0x0804842f <+36>:    90    nop
   0x08048430 <+37>:    90    nop
   0x08048431 <+38>:    eb 11    jmp    0x8048444 <main+57>

   0x08048433 <+40>:    83 ec 0c    sub    esp,0xc

E do programa alterado:

   0x08048427 <+28>:    83 7d f4 01    cmp    DWORD PTR [ebp-0xc],0x1
   0x0804842b <+32>:    75 06    jne    0x8048433 <main+40>
   0x0804842d <+34>:    68 44 84 04 08    push   0x8048444
   0x08048432 <+39>:    c3    ret    

   0x08048433 <+40>:    83 ec 0c    sub    esp,0xc
 

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

 

Abs,

Rafael

salto

salto-original

Link to comment
Share on other sites

  • Supporter - Nibble
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!

Link to comment
Share on other sites

  • Supporter - Nibble

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á.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...