Jump to content
bsd0x

Dúvidas na execução de shellcode

 Read less than a minute

Recommended Posts

 Read less than a minute

Olá, pessoal, recentemente adquiri interesse em desenvolvimento de exploits entre outros assuntos relacionados.

Ainda sou muito iniciante e estou tendo algumas dificuldades para entender alguma peculiaridades. Fiz um código em C utilizando assembly inline e o mesmo não estava compilando, achei uma solução para isso na internet que seria execução o seguinte trecho de código.

int (*ret)() = (int(*)())sc;

ret();

Minha dúvida é: qual a diferença entre usar o __asm__("jmp sc") e usar a solução acima?

Codigo completo

/*
 8049000:	b8 01 00 00 00       	mov    eax,0x1
 8049005:	bb 01 00 00 00       	mov    ebx,0x1
 804900a:	cd 80                	int    0x80


 8049000:	b8 01 00 00 00       	mov    eax,0x1
 8049005:	bb 00 00 00 00       	mov    ebx,0x0
 804900a:	cd 80                	int    0x80


*/

#include <stdio.h>

int main() {
	unsigned char sc[] = 
		"\xb8\x01\x00\x00\x00"
		"\xbb\x01\x00\x00\x00"
		"\xcd\x80";

	printf("Shellcode length: %d\n", sizeof(sc));

	//__asm__("jmp sc");

	int (*ret)() = (int(*)())sc;

	ret();
}

 

 

Share this post


Link to post
Share on other sites
Posted (edited)
 Read less than a minute

Isso, provavelmente, não funcionará, ou, pelo menos, não funcionará em qualquer "box" linux...

Em primeiro lugar, os "segmentos" de dados, num sistema paginado, pode definir as páginas com o bit NX ligdo (NX de Non eXecutable). Isso costuma ser  particularmente verdade, inclusive, para a pilha. Daí, simplesmente definir um ponteiro de função apontando para a sequência de bytes que definem as instruções simplesmente causará um segmentation fault na maioria dos "boxes" com kernels modernos.

Em segundo lugar, o uso da "int 0x80", embora também exista em sistemas amd64 (x86-64), geralmente causam problemas (especialmente com uso de ponteiros). A coisa complica se quiser criar um "shellcode" no modo amd64 (x86-64), onde referências à memória costumam ser relativas ao RIP.

O que se pode fazer com relação ao primeiro caso é alocar as páginas "executáveis" (com o bit NX desligado) usando as system calls mmap() e mprotect() [ativando o flag PROT_EXEC] - mesmo assim, dependendo da versão do kernel, existem proteções para esse tipo de tentativa... Depois, copia-se o conteúdo do "shellcode" para dentro dessas páginas. Daí salta-se para elas.

Edited by fredericopissarra

Share this post


Link to post
Share on other sites
 Read less than a minute

Quanto a dúvida: A diferença é que o operador () de C realizará um CALL... No contexto acima, tanto o JMP quanto um CALL deixarão de fazer o housekeeping necessário para destruir objetos e outras coisas necessárias da libc... Desconsiderando isso, TANTO FAZ fazer um JMP ou um CALL, NESTE CASO.

Share this post


Link to post
Share on other sites
 Read less than a minute

PS: Você deve estar pensando: "Ahhh... mas aqui funciona!"... Eu usei "provavelmente" e "pode" em vários lugares do texto... Em alguns ambientes que seguem a SysV ABI isso ai não funciona (acho que é o caso do FreeBSD e do MacOS, por exemplo).

Mas, isso aqui PODE funcionar:
 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

int main( void )
{
  int x;
  static unsigned char shcodep[] = "\x31\xc0"   // xor eax,eax
                                   "\xc3";      // ret

  int (*f)(void);

  // FIXME: PODE ser que funcione!
  // Cria página com NX desligado, privada ao processo com permissão de leitura/escrita.
  f = mmap( NULL, 
            sizeof shcodep, 
            PROT_READ | PROT_WRITE | PROT_EXEC, 
            MAP_PRIVATE | MAP_ANONYMOUS, 
            -1, 
            0 );

  if ( (ssize_t)f == -1 )
  {
    perror( "mmap" );
    return EXIT_FAILURE;
  }

  // Copia o "código" para a página alocada.
  memcpy( f, shcodep, sizeof shcodep );

  x = f();  // chama...

  munmap( f, sizeof shcodep );

  printf( "%d\n", x );

  return EXIT_SUCCESS;
}

 

Share this post


Link to post
Share on other sites
 Read less than a minute

Muito obrigado pela aula, Fred hahahaha
vou tentar aplicar isso:
 

Quote

O que se pode fazer com relação ao primeiro caso é alocar as páginas "executáveis" (com o bit NX desligado) usando as system calls mmap() e mprotect() [ativando o flag PROT_EXEC] - mesmo assim, dependendo da versão do kernel, existem proteções para esse tipo de tentativa... Depois, copia-se o conteúdo do "shellcode" para dentro dessas páginas. Daí salta-se para elas.

Abraço!

Inclusive, saudades do grupo C/asm do facebook hahahaha
 

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.


  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...