Chiama un syscall Linux da un linguaggio di scripting


15

Voglio chiamare un syscall di Linux (o almeno il wrapper libc) direttamente da un linguaggio di scripting. Non mi interessa quale linguaggio di scripting - è solo importante che non sia compilato (il motivo in sostanza ha a che fare con la mancanza di un compilatore nel percorso delle dipendenze, ma non è né qui né lì). Esistono linguaggi di scripting (shell, Python, Ruby, ecc.) Che lo consentono?

In particolare, è il syscall getrandom .


3
getrandom estrae semplicemente byte casuali da /dev/urandom. Puoi certamente farlo da uno script di shell.
steve

@steve davvero, a meno che ovviamente /devnon sia ancora disponibile. Ma poi è difficile immaginare che Perl sarebbe!
derobert

Criticamente, voglio che questo si blocchi fino a quando il pool di entropia non viene inizializzato, che la lettura da / dev / urandom come file non fa.
joshlf

5
Leggi da /dev/randomfino a quando non si sblocca, quindi leggi da /dev/urandom?
vescovo

1
"la ragione ha sostanzialmente a che fare con il non volere un compilatore nel percorso delle dipendenze, ma non è né qui né lì" -> Eh? Se intendi il percorso di dipendenza del runtime , non lo farai in nessun caso. Non hai bisogno di un compilatore C per eseguire un binario che è stato compilato da C. Se vuoi dire che non vuoi dipendere dalla capacità di compilare cose per la tua architettura di destinazione, perché pensi che non avrai quella capacità, allora è improbabile che tu sia in grado di far funzionare Python, Bash o qualsiasi altro vero linguaggio di scripting su quella piattaforma.
Kevin,

Risposte:


33

Perl lo consente con la sua syscallfunzione:

$ perldoc -f syscall
    syscall NUMBER, LIST
            Calls the system call specified as the first element of the list,
            passing the remaining elements as arguments to the system call. If
⋮

La documentazione fornisce anche un esempio di chiamata write (2):

require 'syscall.ph';        # may need to run h2ph
my $s = "hi there\n";
syscall(SYS_write(), fileno(STDOUT), $s, length $s);

Non posso dire di aver mai usato questa funzione, però. Bene, prima di ora per confermare l'esempio funziona davvero.

Questo sembra funzionare con getrandom:

$ perl -E 'require "syscall.ph"; $v = " "x8; syscall(SYS_getrandom(), $v, length $v, 0); print $v' | xxd
00000000: 5790 8a6d 714f 8dbe                      W..mqO..

E se non hai getrandom in syscall.ph, puoi invece usare il numero. Sono 318 sulla mia casella di test Debian (amd64). Attenzione che i numeri di syscall di Linux sono specifici dell'architettura.


2
Perl - il martello del piano B!
Thorbjørn Ravn Andersen,

28

In Python puoi usare il ctypesmodulo per accedere a funzioni arbitrarie in librerie dinamiche, incluso syscall()da libc:

import ctypes

SYS_getrandom = 318 # You need to check the syscall number for your target architecture

libc = ctypes.CDLL(None)
_getrandom_syscall = libc.syscall
_getrandom_syscall.restypes = ctypes.c_int
_getrandom_syscall.argtypes = ctypes.c_int, ctypes.POINTER(ctypes.c_char), ctypes.c_size_t, ctypes.c_uint

def getrandom(size, flags=0):
    buf = (ctypes.c_char * size)()
    result = _getrandom_syscall(SYS_getrandom, buf, size, flags)
    if result < 0:
        raise OSError(ctypes.get_errno(), 'getrandom() failed')
    return bytes(buf)

Se libc include la getrandom()funzione wrapper, puoi chiamarla anche:

import ctypes

libc = ctypes.CDLL(None)
_getrandom = libc.getrandom
_getrandom.restypes = ctypes.c_int
_getrandom.argtypes = ctypes.POINTER(ctypes.c_char), ctypes.c_size_t, ctypes.c_uint

def getrandom(size, flags=0):
    buf = (ctypes.c_char * size)()
    result = _getrandom(buf, size, flags)
    if result < 0:
        raise OSError(ctypes.get_errno(), 'getrandom() failed')
    return bytes(buf)

Qualche possibilità che potresti aggiungere un esempio di come chiamare la getrandomfunzione libc direttamente anziché syscall getrandom? È possibile?
joshlf,

@joshlf Certo che è possibile. Ho modificato la mia risposta.
cg909,

Sai se esiste un modo per cercare dinamicamente il valore corretto del SYS_getrandomvalore in fase di runtime (in modo da renderlo giusto per la piattaforma corrente)? Ad esempio, analizzando i /usr/includefile di intestazione?
joshlf

Non l'ho provato, ma potresti avere fortuna con Pycparser .
cg909

17

Ruby ha una syscall(num [, args...]) → integerfunzione.

Per esempio:

irb(main):010:0> syscall 1, 1, "hello\n", 6
hello
=> 6

Con getrandom():

irb(main):001:0> a = "aaaaaaaa"
=> "aaaaaaaa"
irb(main):002:0> syscall 318,a,8,0
=> 8
irb(main):003:0> a
=> "\x9Cq\xBE\xD6|\x87\u0016\xC6"
irb(main):004:0> 
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.