Ir para conteúdo

Criando funções diretamente em assembly no GCC


fredericopissarra

Posts Recomendados

Não, não estou falando somente do assembly inline, mas de criar uma função inteira em assembly.

Um dos problemas que o GCC, na plataforma x86, tem é que ele não aceita (até a versão 7, pelo menos) o atributo naked numa função. Esse atributo informa ao compilador que ele não deve usar a convenção de chamada e colocar um RET na saída da função. Então, a única forma de fazer isso, ao que parece, é criando uma função em assembly:

; naked.asm
; NASM style

  section .text

  global naked_func
naked_func:
  ; faz qualquer coisa que você quiser aqui...

Eu disse "ao que parece" porque a construção abaixo é possível. E aqui mostro uma simples função que incrementa uma variável global:

/* test.c */
#include <stdio.h>

int g_int = 0;

// não pode ter o qualiificador __volatile__ porque
// o compilador precisa recalcular o offset de g_int
// com base em RIP.
//
// É a mesma coisa que:
//
//  void f( void ) { g_int++; }
//
__asm__ (
  "f:\t\n"
  "  addl $1,g_int(%rip)\t\n"
  "  ret"
);

// O compilador precisa saber que função existe e
// ela é definida aqui como extern para não emitir warnings!
extern void f( void );

int main( void )
{
  f();  // voilà!
  printf( "%d\n", g_int );
}

A função f(), acima, foi construída para o modo x86-64.
Note que a função tem apenas as instruções contidas no bloco __asm__. Poderia ser uma interrupt service routine, por exemplo, e retornar com IRETQ.

Compilando e executando:

$ gcc -O2 -o test test.c
$ ./test
1

Se você listar o código acima, verá que f é definida com apenas as instruções contidas no bloco __asm__!!

Interessante, huh?
 

Link para o comentário
Compartilhar em outros sites

Interessante mesmo! Muito obrigado pelo post!

Eu busquei por exemplos de uso do atributo naked, tipo de quando usar, sabe? Encontrei um caso no RTOS pra evitar salvar o contexto duas vezes, um exemplo de ofuscação meio fraco e alguns outros. Por acaso você tem alguns exemplos práticos de uso deste atributo? Tipo, em que situação eu usaria uma função pelada? ?

Abraço!

Link para o comentário
Compartilhar em outros sites

Para evitar que o compilador use a convenção de chamada e/ou coloque um RET no final da função.
Tentei usar uma função naked no GCC porque tentei uma função com atributo interrupt e ele também não suporta (ainda), para o x86.

Agora, no GCC 8.3, naked é suportado para x86... mas eu ainda uso a versão 7.3, default, da minha distro...

Link para o comentário
Compartilhar em outros sites

Ubuntu... Infelizmente Debian, quando tentei instalar em minha máquina, não funcionou (Dell XPS 8700)... O driver de rede não funfava!
Uso Ubuntu 18.04 aqui porque essas distros são homologadas para máquinas Dell e gosto de distros no estilo Debian.

Eu poderia instalar o pacote gcc-8-multilib-x86-64-linux-gnu, mas não gosto muito de futucar com alguns defaults... Mesmo porque esse pacote é da versão 8.2 que, acho, não implementa atributos naked para x86, ainda...

Link para o comentário
Compartilhar em outros sites

  • 4 semanas depois...
  • 1 mês depois...
  • Apoiador Nibble
Em 26/03/2019 em 05:01, Fernando Mercês disse:

Interessante mesmo! Muito obrigado pelo post!

Eu busquei por exemplos de uso do atributo naked, tipo de quando usar, sabe? Encontrei um caso no RTOS pra evitar salvar o contexto duas vezes, um exemplo de ofuscação meio fraco e alguns outros. Por acaso você tem alguns exemplos práticos de uso deste atributo? Tipo, em que situação eu usaria uma função pelada? ?

Abraço!

Fernando.... blza? Vc tem mais exemplos de ofuscação? Eu achei bem interessante, apesar de ser "meio fraco". :)

Link para o comentário
Compartilhar em outros sites

  • Apoiador Nibble
23 horas atrás, Fernando Mercês disse:

Beleza e você? Com funções naked? Não. ?

Tudo bem!

Não precisa utilizar funções naked. Pode ser ofuscação utilizando outros métodos. Por exemplo, me lembro uma vez que você postou um artigo/comentário sobre substituição de uma insrtução call por outras equivalentes (push e jmp) para enganar o decompiler.... enfim... acho que você deve ter algum material bom sobre isso.

Valeu!!!!

Link para o comentário
Compartilhar em outros sites

  • 5 meses depois...

gcc -O3 -S -masm=intel -mtune=native -fverbose-asm test.c

eu tenho que ter o arquivo test.c pronto ? 

$ gcc -O3 -S -masm=intel -mtune=native -fverbose-asm test.c
gcc: error: test.c: No such file or directory
gcc: fatal error: no input files
compilation terminated.

resu da compilação.

e aqui fala 

$ gcc -O3 -S -masm=intel -mtune=native -fverbose-asm test.c

Isso ai criará um arquivo chamado test.s (por causa da opção -S), contendo as funções descritas em
test.c com uma grande quantidade de comentários no código gerado (opção -fverbose-asm). E o

@fredericopissarra me ajude ai meu mestre ! 

Link para o comentário
Compartilhar em outros sites

5 horas atrás, plancton disse:

eu tenho que ter o arquivo test.c pronto ?

Yep... a opção -S serve para gerar o código em ASM a partir do código em C, então o programa em test.c tem que ser compilável.
Você pode usar -fverbose-asm se quiser os aqueles montes de comentários, mas para análise do código gerado ele não é necessário.

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

  • Quem Está Navegando   0 membros estão online

    • Nenhum usuário registrado visualizando esta página.
×
×
  • Criar Novo...