Inspirado por una pregunta StackOverflow ahora eliminada . ¿Puedes encontrar una manera de ejecutar un método en particular, sin llamarlo explícitamente? Cuanto más indirecto sea, mejor.
Esto es lo que quiero decir exactamente (C se usa solo para ejemplificar, se aceptan todos los lenguajes):
// Call this.
void the_function(void)
{
printf("Hi there!\n");
}
int main(int argc, char** argv)
{
the_function(); // NO! Bad! This is a direct call.
return 0;
}
Pregunta original
popularity-contest
function
Comunidad
fuente
fuente
Respuestas:
C
Cuando se compila con GCC, el compilador reemplaza
printf("Goodbye!\n")
conputs("Goodbye!")
, que es más simple y se supone que es equivalente. He proporcionado sigilosamente miputs
función personalizada , por lo que se llama en su lugar.fuente
Bueno, ¿cómo es capaz el malware de ejecutar funciones que no se invocan en el código? ¡Desbordando tampones!
En mi sistema, la dirección de retorno de
main
se almacena 3 palabras por encima de la primera variable local. Al codificar esa dirección de retorno con la dirección de otra función,main
"regresa" a esa función. Si desea reproducir este comportamiento en otro sistema, es posible que deba ajustar 3 a otro valor.fuente
<!-- language: lang-c -->
dos líneas antes de su código para resaltarlo.Golpetazo
fuente
Python 2
Aquí hay algunas formas inspiradas por las otras respuestas:
ejecutando el código directamente
Esta es la mejor manera de no llamar realmente a la función.
usando el destructor
Usando la E / S estándar
utilizando búsquedas de atributos
El mecanismo de importación
Bueno, supongo que eso es todo ... No puedo importar nada ahora. No, espera..
Usando los corchetes get-item
[]
Utilizando variables globales. ¡Mi favorito!
hello
es un acceso ad['hello']
. Después de esto, el mundo parece gris.Meta clases;)
Usando iteradores (puede sobrecargar cualquier operador y usarlo)
Errores
Los marcos le devuelven la llamada. Casi todas las GUI tienen esta funcionalidad.
Ejecute la cadena de origen (la función debe estar en un archivo)
Decoradores
con deserialización de pepinillos (menos favoritos)
Usando serialización
Más respuestas de Python:
hasattr
globals()
e__call__
indirectamentereprlib
fuente
Javascript
Este usa JSFuck para hacer el trabajo sucio.
fuente
""
es una cadena y se[]
evalúa a 0, por""[[]]
lo que no está definida y""[[]]+""
está "sin definir". Desde allí puede extraer letras individuales:(""[[]]+"")[[]]
es "u". Entonces es más como un truco llamar a un ejecutivo con código arbitrario. Creo que eso cuenta?function anonymous() { x() }
.Pitón
Esto se establece
the_function
como la función de creación de perfiles, lo que hace que se ejecute en cada llamada de función y devolución.fuente
C#
Podemos abusar del DLR para ejecutar siempre algún código cada vez que intente llamar a cualquier método en una clase. Esto es un poco menos barato / obvio que soluciones como delegados, reflexiones, constructores estáticos, etc., porque el método que se ejecuta no solo nunca se invoca sino que ni siquiera se hace referencia a él , ni siquiera por su nombre.
Esto siempre imprime "¡Ja! ¡Te engañé!" no importa en qué intentes invocar
a
. Entonces podría escribir cona.SuperCaliFragilisticExpiAlidocious()
la misma facilidad y haría lo mismo.fuente
GNU C
Esto es muy directa, pero ciertamente no es una llamada a
hello_world
, a pesar de que la función hace ejecutar.fuente
Rubí
Inspirado por wat .
fuente
C
Puede registrar una función que se llamará al final del programa en C, si eso se ajusta a sus necesidades:
fuente
Java
Intenté esto con Java:
El método
secretMethodNotCalledInMain
se llama solo por reflexión, y no estoy buscando nada llamadosecretMethodNotCalledInMain
(en cambio estoy buscando algo no llamadomain
). Además, la parte reflexiva del código se llama fuera delmain
método cuando se activa el controlador de excepciones no capturadas del JDK.Aquí está mi información de JVM:
Aquí está la salida de mi programa:
No esperaba que los
NullPointerException
lanzados desde el código nativo manejen la reflexión. Pero, como mencionó @ johnchen902, eso se debe a que hereda algunos métodosjava.lang.Object
y terminé llamándolos ennull
s.fuente
NPE
no son errores de JDK. Se lanzan porque trataste de invocar métodos de instancia declaradosjava.lang.Object
comotoString()
connull
.C ++
Una forma en C ++ es en el constructor y / o destructor de un objeto estático:
fuente
new
, por lo que sería una respuesta interesante tener una forma de invocar uno sin élnew
. Pero no sé, los constructores estáticos se sienten como un poco tramposo.new (p) foo()
. Y puede destruir un objeto sin liberar la memoria a través dep->~foo()
.C: Hola mundo
Salida:
Para vincular el método, necesitamos que printf () se compile en algún lugar del programa, pero en realidad no es necesario llamarlo. Las funciones printf () y main () se encuentran separadas 276 bytes entre sí en el segmento de código. Este valor cambiará según el sistema operativo y el compilador. Puede encontrar las direcciones reales en su sistema con este código y luego simplemente restarlas:
fuente
*
antesmain
es realmente confuso e innecesario.main
es una función que no puede desreferenciar, por lo que implícitamente decae a un puntero de función que luego se desreferencia para producir una función nuevamente. No puede restar un int de una función, por lo que se desvanece a un puntero de función nuevamente. También podrías escribir(*****main-276)
;) Probablemente quisiste escribir(&main-276)
o en su(*(main-276))
lugar.The * before main is really confusing and unnecessary.
- ¿No es generalmente algo bueno en este sitio?main
, pero no puede encontrarlo ahora ...C (con GCC en línea asm)
Esto hará que parte del código emitido por GCC termine en un segmento diferente del archivo objeto, haciendo que el flujo de control "caiga" por la función. Tenga en cuenta que esto no funciona si GCC decide reordenar las funciones, obviamente. Probado con GCC 3.4.6 en MirBSD-current / i386, usando
-O2
. (Además, interrumpe la depuración, compilando con-g
errores ☺)fuente
PHP ≥5.4.0
Esta solución es ciertamente un desastre horrible, pero realiza la tarea que se le asignó (no se estipuló cómo bien debe realizarse).
La función para llamar sin llamar :
La solución :
Ejemplo :
Salidas posibles:
Explicacion :
Cuando se le llame,
executeFunction()
leerá el contenido del archivo que se está ejecutando actualmente (lo que significa que esto solo debe ejecutarse desde la CLI, tal como se usa$argv
), analizará los argumentos y el cuerpo de la función especificada, hackeará todo nuevamente en un nuevo fragmento de código,eval()
todo y devolver el resultado. El resultado es quegetRandomString()
nunca se llama, ya sea directa o indirectamente, pero el código en el cuerpo de la función aún se ejecuta.fuente
__construct()
método de creación cuenta en PHP ya que nunca llama a la función directamente, sino que la usanew Something()
?register_tick_function()
,register_shutdown_function()
ospl_autoload_register()
similar a la respuesta de Python de @ grc, pero siento que eso es 'hacer trampa' y tomar el camino fácil.Perl
Sí, eso es todo. No todas las subrutinas son iguales.
fuente
T-SQL
Es una característica incorporada. ¡Disparadores para la victoria!
Si realmente quieres divertirte con él, crea un montón de disparadores INSTEAD OF en April Fool's Day.
Resultados:
Muy broma. Tal lulz. Guau.
Tinker lo anotó en SQLFiddle.
fuente
JavaScript
En la consola de Firefox:
Luego, simplemente comience a escribir cualquier cosa en la consola: Firefox llama
.toString()
varias veces cuando está escribiendo en la consola.Enfoque similar es:
fuente
C
La plataforma de elección es Linux. No podemos llamar a nuestra función, por lo que haremos que nuestro enlazador lo haga en su lugar:
¿Cómo obtener la dirección mágica?
Confiamos en la especificación básica básica de Linux, que dice:
Compila el código:
gcc but_for_what_reason_exactly.c -o but_for_what_reason_exactly
Examine la dirección de
.fini_array
:objdump -h -j .fini_array but_for_what_reason_exactly
Encuentra el VMA de la misma:
y reemplazar ese valor para
ADDRESS
.fuente
VB6 y VBA
No estoy seguro de si esto califica o no, porque está llamando a un método de una clase:
Esto va en un módulo de clase:
Y este es el código de "llamada":
Esto funciona intercambiando la función vptr's para los dos Subs en la tabla vtable para la clase.
fuente
Haskell
En haskell si haces:
Se ejecutará inmediatamente sin llamarlo cuando lo ejecutes. ¡Magia!
fuente
Javascript
Fácil, solo usa
on___
eventos en JS. Por ejemplo:fuente
Java
Otra respuesta de Java de mi parte. Como puede ver en el código, llama directamente
theCalledMethod
, pero el métodonotCalledMethod
se ejecuta en su lugar.Entonces, al final estoy haciendo 2 cosas:
Ejecutándolo:
fuente
getBytes()
método, activándologetBytes("UTF-8")
. Como no tengo un OS X, ¿podrías probar si esto funciona?Pitón
fuente
Java
¡Yay, recolección de basura!
Una versión para aquellos que inevitablemente dirán que
System.gc()
no es confiable:fuente
C objetivo
(Probablemente solo si se compila con clang en Mac OS X)
Este código usa varios trucos para acceder a la función no utilizada. Primero es el valor 0x2A27. Este es un puntero etiquetado para el entero 42, que codifica el valor en el puntero para evitar la asignación de un objeto.
Siguiente es
MyClass
. Nunca se usa, pero el tiempo de ejecución llama al+load
método cuando se carga, antesmain
. Esto crea y registra dinámicamente una nueva clase, utilizandoNSValue
como su superclase. También agrega un+load
método para esa clase, utilizandoMyClass
's-unusedMethod
como implementación. Después del registro, llama al método de carga en la nueva clase (por alguna razón no se llama automáticamente).Dado que el método de carga de la nueva clase usa la misma implementación que
unusedMethod
, eso se llama efectivamente. Toma la superclase de sí mismo y agregaunusedFunction
como implementación para eldoesNotRecognizeSelector:
método de esa clase . Este método era originalmente un método de instanciaMyClass
, pero se llama como un método de clase en la nueva clase, también loself
es el nuevo objeto de clase. Por lo tanto, la superclase esNSValue
, que también es la superclase paraNSNumber
.Finalmente,
main
corre. Toma el valor del puntero y lo pega en unaNSString *
variable (la__bridge
primera conversión paravoid *
permitir que se use con o sin ARC). Luego, trata de invocarstringByAppendingString:
esa variable. Dado que en realidad es un número, que no implementa ese método,doesNotRecognizeSelector:
se llama al método en su lugar, que viaja a través de la jerarquía de clases hastaNSValue
donde se implementa utilizandounusedFunction
.Nota: la incompatibilidad con otros sistemas se debe al uso del puntero etiquetado, que no creo que haya sido implementado por otras implementaciones. Si esto fuera reemplazado por un número creado normalmente, el resto del código debería funcionar bien.
fuente
0x2A27
valor, así que no sé si eso se implementa en otro lugar. ObjFW definitivamente es interesante sin embargo.0x2A27
está etiquetado punteroJavascript
Siento que esto no parece explícitamente que está llamando a la función
fuente
C # (vía
using
)fuente
Java
Estoy aprovechando una característica especial de la serialización de Java. El
readObject
método se invoca cuando un objeto se deserializa, pero no se llama directamente, ni por mi código ni por la biblioteca de deserialización. Si profundiza en la fuente, verá que en un nivel bajo el método se llama internamente a través de la reflexión.fuente
Perl
Esto es muy facil. El siguiente código ejecuta automáticamente el código en la subrutina, incluso sin una llamada explícita.
Incluso si descomenta la llamada, se llamará solo una vez.
fuente