¿Qué significa ((void

4 minutos de lectura

())buf)();  ¿significar?
avatar de usuario

sh.3.ll

((void (*)())buf)();

Estoy resolviendo un desafío de explotación binaria en picoCTF y me encontré con este fragmento de código: buf dónde

es una matriz de caracteres.

Resolví el desafío, pero parece que no puedo entender qué está haciendo exactamente. Miré este hilo pero no pude descifrarlo. ((void (*)())buf)(); Que hace

  • ¿significar? ((void (*)())buf)(); Que hace ¿significar? typedefSignifica que el autor no entiende. typedef void (*voidFuncPtrType)(); .

    aclararía este código.

    –Andrew Henle


  • 14 de enero de 2020 a las 13:39

    @AndrewHenle al diseñar desafíos de CTF, la claridad no es realmente el objetivo principal, e incluso se puede esperar algo de ofuscación como parte del desafío. Lo más probable es que el autor fuera consciente de que esta no es la forma más legible de hacer las cosas.

    – ManfP

  • 14 de enero de 2020 a las 23:19

    Significa que su programa tiene UB.

    – R.. GitHub DEJA DE AYUDAR A ICE

  • 15 de enero de 2020 a las 20:10

    Significa que la regla de declaración de tipo “espiral” de C es demasiado complicada. Hay una razón por la que prácticamente todos los demás lenguajes de tipado estático que no descienden directamente de C usan reglas de izquierda a derecha en su lugar.

    – Mason Wheeler

  • 15 de enero de 2020 a las 22:39

    @MasonWheeler “Spiral” es un mito urbano. La declaración es tanto o tan poco “espiral” como lo sería la expresión correspondiente. Los operadores simplemente se aplican en orden de precedencia y de izquierda a derecha (sin decir nada nuevo aquí, por supuesto): “Necesito desreferenciarlo, luego llamarlo, y el resultado es de tipo void”: listo, puntero a función void .

    – Peter – Reincorporar a Mónica

void (*)() 16 de enero de 2020 a las 3:47

(void (*)()) es un tipo, el tipo es “puntero a función que toma argumentos indeterminados y no devuelve ningún valor”.

(void (*)())buf es un tipo de conversión al tipo anterior. buf yesos

((void (*)())buf)() al tipo anterior.

llama a la función (sin pasar argumentos). buf En resumen: le dice al compilador que trate

  • como un puntero a una función, y para llamar a esa función. cdecl encuentro el utilidad (ositio web

    ) útil para traducir las expresiones C más complejas al inglés.

    – bta

  • 14 de enero de 2020 a las 23:49

    @bta cdecl no es útil aquí ya que la sintaxis no es una declaración. Es una llamada de función a través de un lanzamiento en un símbolo previamente declarado.

    – bolov


  • 15 de enero de 2020 a las 1:00 @bolov – En toda la declaración, no, pero lo hace explique el parte más compleja

    de eso A partir de ahí, decodificar el resto es bastante sencillo.

    – bta

  • 15 de enero de 2020 a las 1:11 buf @AvD Si donde sea copy o

    está ubicado en una dirección ejecutable y el código en sí es independiente de la posición, esto funcionará. Por supuesto, es tan no portátil como parece, pero debería funcionar en muchos entornos sin sistema operativo, así como en sistemas operativos x86 más antiguos que no configuran el bit de no ejecución (NX) en la pila y el montón.

    – wrtlprnft

  • 15 de enero de 2020 a las 4:39

    @AvD: No necesariamente fallará. A menos que el área de datos esté protegida contra la ejecución (que depende de la arquitectura y el entorno de tiempo de ejecución), puede usar este truco para compilar una función en una matriz en tiempo de ejecución y llamarla sobre la marcha. Usé este truco por primera vez hace 35 años en un DEC Vax para compilar máquinas de Turing para un experimento fallido en la evolución de la máquina de Turing.

    – TonyK


15 de enero de 2020 a las 10:40 buf puntero

se convierte en el puntero para anular la función tomando un número no especificado de parámetros y luego se elimina la referencia (es decir, se llama a la función).
avatar de usuario

Lucas buf Es un encasillado, seguido de una llamada de función. En primer lugar, voidse convierte en el puntero a una función que devuelve

. El último par de paréntesis significa que luego se llama a la función. voidConvierte la matriz de caracteres en un puntero a una función que no toma argumentos y devuelve

y luego lo llama. No es necesario eliminar la referencia del puntero debido a cómo funcionan los punteros de función.

Una explicación: void (*)() Esa “matriz de caracteres” es en realidad una matriz de código de máquina. Cuando lanzas la matriz a un

¿Ha sido útil esta solución?