2012-03-31 33 views
6

Quiero un método C simple para poder ejecutar código de bytes hexadecimal en una máquina Linux de 64 bits. Aquí está el programa en C que tengo:¿Cómo obtener el código c para ejecutar el bytecode hexadecimal?

char code[] = "\x48\x31\xc0"; 
#include <stdio.h> 
int main(int argc, char **argv) 
{ 
     int (*func)(); 
     func = (int (*)()) code; 
     (int)(*func)(); 
     printf("%s\n","DONE"); 
} 

El código que estoy tratando de correr ("\x48\x31\xc0") obtuve por escribiendo este programa un montaje sencillo (que no tiene que hacer realmente nada)

.text 
.globl _start 
_start: 
     xorq %rax, %rax 

y luego compilarlo y objdumpándolo para obtener el bytecode.

Sin embargo, cuando ejecuto mi programa C recibo un error de segmentación. ¿Algunas ideas?

+5

Incluso si su segmento de datos es ejecutable o que no han permitido NX, ¿qué esperas que ver esto? Ejecuta una instrucción y luego la instrucción posterior (que no controla) y luego la instrucción después de eso, hasta que alcanza la memoria que no representa el código o código legítimo que desencadena una segfault. –

+1

Tendrá que agregar un código de bytes para un 'ret' porque la llamada a la función indirecta que hace debe ser una' llamada' que empuja la dirección de retorno a la pila. Al menos, esta es mi mejor estimación educada, nunca había visto algo como esto. – Chris

+0

Espero que esto no haga nada, pero quiero que se pueda ejecutar sin fallar. – Nosrettap

Respuesta

13

Aquí hay un ejemplo simple.

main.c:

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

int main() 
{ 
    /*                
     mov rax, 60   ; sys_exit 
     mov rdi, 2 
     syscall             
    */ 
    char code[] = { 
     0x48, 0xb8, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x48, 0xbf, 0x02, 0x00, 0x00, 0x00, 
     0x00, 0x00, 0x00, 0x00, 0x0f, 0x05 
    }; 

    void *buf; 

    /* copy code to executable buffer */  
    buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC, 
       MAP_PRIVATE|MAP_ANON,-1,0); 
    memcpy (buf, code, sizeof(code)); 

    /* run code */ 
    ((void (*) (void))buf)(); 

    return 0; 
} 

Ejecutar este con

./main ;echo $? 

elegí hacer un _exit (2) en la asamblea para que sea fácil de comprobar que el código se ejecuta correctamente. En la práctica, querrá agregar un ret al final de su código para devolver el control.

+0

Sí, el 'ret' es importante para regresar a la función de llamada. – Chris

+1

Gracias por la ayuda. Solo quiero agregar que objdump -d puede obtener el código de byte para un ejecutable. – Jeff

4

Su código de máquina puede estar bien, pero su CPU se opone.

Las CPU modernas administran la memoria en segmentos. En operación normal, el sistema operativo carga un nuevo programa en un segmento de texto de programa y configura una pila en un segmento de datos. El sistema operativo le dice a la CPU que nunca ejecute código en un segmento de datos. Su código está en code[], en un segmento de datos. Por lo tanto, segfault.

2

Esto requerirá un esfuerzo.

La variable code se almacena en la sección .data de su ejecutable:

$ readelf -p .data exploit 

String dump of section '.data': 
    [ 10] H1À 

H1À es el valor de la variable.

La sección .data es no ejecutable:

$ readelf -S exploit 
There are 30 section headers, starting at offset 0x1150: 
Section Headers: 
    [Nr] Name    Type    Address   Offset 
     Size    EntSize   Flags Link Info Align 
[...] 
    [24] .data    PROGBITS   0000000000601010 00001010 
     0000000000000014 0000000000000000 WA  0  0  8 

Todos los procesadores de 64 bits que conozco de apoyo páginas no ejecutables forma nativa en el PageTables. La mayoría de los procesadores de 32 bits más nuevos (los que admiten PAE) proporcionan suficiente espacio adicional en sus tablas de páginas para que el sistema operativo emule las páginas no ejecutables de hardware. Tendrá que ejecutar un sistema operativo antiguo o un procesador antiguo para obtener una sección .data marcada como ejecutable.

Dado que estas son solo banderas en el ejecutable, debe poder establecer el indicador X a través de algún otro mecanismo, pero no sé cómo hacerlo. Y es posible que su sistema operativo ni siquiera le permita tener páginas que sean ambas escribibles y ejecutables.

Cuestiones relacionadas