Pregunta

Imagínese que estoy haciendo algo como esto:

void *p = malloc (1000);
*((char*)p) = some_opcode;
*((char*)p+1) = another_opcode; // for the sake of the example: the opcodes are ok

....
etc...

¿Cómo puedo definir un puntero de función para llamar p como si se tratara de una función? (Estoy usando VC ++ Express 2008).

Gracias

¿Fue útil?

Solución

Un comentario no había espacio suficiente. Joe_Muc es correcta. No se debe meter en la memoria de código obtenido por malloc o new. Que se ejecutará en problemas si cambia las propiedades de página de las páginas que asigna de Windows.

Esto no es un problema becuase usando VirtualAlloc () y las API de Win32 relacionados está cada fácil: llamar VirtualAlloc () y establecer el flProtect a [PAGE_EXECUTE_READWRITE][2]

Tenga en cuenta, que probablemente debería hacer tres asignaciones, una página de protección, las páginas que necesita para su código, y luego otra página de protección. Esto le dará un poco de protección contra el mal código.

También envolver las llamadas a su código generado con control estructurado de excepciones .

A continuación, el X86 ABI de Windows (convenciones de llamada) no están bien documentados (lo sé, lo he mirado). Hay algo de información aquí , aquí , aquí la mejor manera de ver cómo funcionan las cosas es mirar el código generado por el compilador. Esto es fácil de hacer con el \FA interruptores ( hay cuatro de ellos).

Puede encontrar las convenciones de llamada de 64 bits aquí .

Además, se puede obtener todavía Macro Assembler de Microsoft MASM aquí . Recomiendo escribir el código de máquina en MASM y buscar en su salida, a continuación, haga que su generador de código máquina de hacer cosas similares.

de Intel y manuales procesador de AMD son buenas referencias - conseguirlos si no los tiene <. / p>

Otros consejos

En realidad, malloc probablemente no se corte. En Windows es probable que tenga que llamar algo así como [VirtualAlloc] ( http://msdn.microsoft.com/en-us/library/aa366887 (VS.85) .aspx) el fin de obtener una página ejecutable de la memoria.

A partir pequeña:

void main(void)
{
    char* p = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    p[0] = (char)0xC3;  // ret

    typedef void (*functype)();
    functype func = (functype)p;
    (*func)();
}

El siguiente paso para jugar bien con su código es preservar el registro EBP. Esto se deja como ejercicio. : -)

Después de escribir esto, me encontré con malloc y también trabajé. Eso puede ser porque estoy corriendo una cuenta de administrador en Windows 2000 Server. Otras versiones de Windows puede necesitar realmente la llamada VirtualAlloc. Quién sabe.

Si usted tiene los códigos de operación adecuadas en el lugar, llamar puede ser tan simple como la fundición a un puntero de función y llamar a él.

typedef void (*voidFunc)();

char *p = malloc (1000);
p[0] = some_opcode;
p[1] = another_opcode; // for the sake of the example: the opcodes are ok
p[n] = // return opcode...

((voidFunc)p)();

Ten en cuenta que a menos que marque la página como ejecutable, el procesador puede que no le permiten ejecutar código generado en el montón.

También estoy actualmente en la ejecución de código generado, y si bien las respuestas aquí no me dieron exactamente lo que necesitaba, ustedes me enviado por el camino correcto.

Si necesita marcar una página como ejecutable en sistemas POSIX (Linux, BSD, etc.), echa un vistazo a la mmap (2) función .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top