Jump to content
Sign in to follow this  
fredericopissarra

Criando funções diretamente em assembly no GCC

Recommended Posts

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?
 

  • Curtir 3
  • l33t 1

Share this post


Link to post
Share on other 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!

Share this post


Link to post
Share on other 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...

Share this post


Link to post
Share on other 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...

Share this post


Link to post
Share on other sites
Em 26/03/2019 em 06:30, fredericopissarra disse:

Para evitar que o compilador use a convenção de chamada e/ou coloque um RET no final da função.

Isso eu saquei. A dúvida era em que casos isso é necessário, mas o exemplo da ISR já é um caso. 😉

Abraço!

Share this post


Link to post
Share on other sites
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". :)

Share this post


Link to post
Share on other sites
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!!!!

Share this post


Link to post
Share on other sites

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 ! 

Edited by plancton

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...