Rufen Sie einen Linux-Systemaufruf aus einer Skriptsprache auf

15

Ich möchte einen Linux-Systemaufruf (oder zumindest den libc-Wrapper) direkt aus einer Skriptsprache aufrufen. Es ist mir egal, welche Skriptsprache ich verwende - es ist nur wichtig, dass sie nicht kompiliert wird (der Grund dafür ist, dass ich keinen Compiler im Abhängigkeitspfad haben möchte, aber das ist weder hier noch da). Gibt es Skriptsprachen (Shell, Python, Ruby usw.), die dies ermöglichen?

Insbesondere ist es das getrandom syscall .

joshlf
quelle
3
getrandom zieht nur zufällige bytes ab /dev/urandom. Das können Sie natürlich aus einem Shell-Skript heraus tun.
Steve
@ Steve in der Tat, es sei denn natürlich /devnoch nicht verfügbar. Aber dann wäre Perl schwer vorstellbar!
Derobert
Kritisch möchte ich, dass dies blockiert wird, bis der Entropiepool initialisiert ist, was das Lesen von / dev / urandom als Datei nicht tut.
Joshlf
5
Lesen Sie ab, /dev/randombis es entsperrt, dann lesen Sie ab /dev/urandom?
Bischof
1
"Der Grund hat im Grunde damit zu tun, dass man keinen Compiler im Abhängigkeitspfad haben möchte, aber das ist weder hier noch dort" -> Huh? Wenn Sie den Laufzeitabhängigkeitspfad meinen , dann werden Sie es auf keinen Fall tun. Sie benötigen keinen C-Compiler, um eine Binärdatei auszuführen, die aus C kompiliert wurde. Wenn Sie damit meinen, dass Sie nicht von der Kompilierbarkeit für Ihre Zielarchitektur abhängen möchten, weil Sie glauben, dass Sie diese Fähigkeit nicht haben werden, dann ist es Es ist unwahrscheinlich, dass Sie Python, Bash oder eine andere echte Skriptsprache auf dieser Plattform ausführen können.
Kevin

Antworten:

33

Perl erlaubt dies mit seiner syscallFunktion:

$ 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
⋮

Die Dokumentation enthält auch ein Beispiel für den Aufruf von write (2):

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

Ich kann jedoch nicht sagen, dass ich diese Funktion jemals verwendet habe . Naja, bevor ich das gerade bestätige, klappt das Beispiel in der Tat.

Dies scheint zu funktionieren mit 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..

Und wenn Sie in Ihrer syscall.ph kein getrandom haben, können Sie stattdessen die Nummer verwenden. Es ist 318 auf meiner Debian-Test-Box (amd64). Beachten Sie, dass Linux-Systemrufnummern architekturspezifisch sind.

derobert
quelle
2
Perl - der Plan B Hammer!
Thorbjørn Ravn Andersen
28

In Python können Sie mit dem ctypesModul auf beliebige Funktionen in dynamischen Bibliotheken zugreifen, einschließlich syscall()von 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)

Wenn Ihre libc die getrandom()Wrapper-Funktion enthält, können Sie sie auch aufrufen:

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)
cg909
quelle
Gibt es eine Möglichkeit, ein Beispiel für den getrandomdirekten Aufruf der libc- Funktion anstelle des syscall hinzuzufügen getrandom? Ist das möglich?
Joshlf
@joshlf Natürlich ist es möglich. Ich habe meine Antwort bearbeitet.
CG909
Wissen Sie, ob es eine Möglichkeit gibt, den korrekten Wert SYS_getrandomzur Laufzeit dynamisch nachzuschlagen (damit Sie ihn für die aktuelle Plattform richtig einsetzen können)? ZB durch Analysieren von /usr/includeHeader-Dateien?
Joshlf
Ich habe es nicht ausprobiert, aber vielleicht hast du Glück mit PycParser .
cg909
17

Ruby hat eine syscall(num [, args...]) → integerFunktion.

Beispielsweise:

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

Mit 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> 
lgeorget
quelle