bsd0x Posted July 18, 2020 at 09:23 PM Share Posted July 18, 2020 at 09:23 PM 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(); } Link to comment Share on other sites More sharing options...
fredericopissarra Posted July 19, 2020 at 12:04 AM Share Posted July 19, 2020 at 12:04 AM 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. Link to comment Share on other sites More sharing options...
fredericopissarra Posted July 19, 2020 at 12:10 AM Share Posted July 19, 2020 at 12:10 AM 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. Link to comment Share on other sites More sharing options...
fredericopissarra Posted July 19, 2020 at 12:40 AM Share Posted July 19, 2020 at 12:40 AM 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; } Link to comment Share on other sites More sharing options...
bsd0x Posted July 20, 2020 at 03:53 AM Author Share Posted July 20, 2020 at 03:53 AM 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 Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.