从脚本语言调用 Linux 系统调用

从脚本语言调用 Linux 系统调用

我想直接从脚本语言调用 Linux 系统调用(或至少是 libc 包装器)。我不在乎什么脚本语言 - 重要的是它不被编译(原因基本上与不希望依赖路径中的编译器有关,但这既不在这里也不在那里)。是否有任何脚本语言(shell、Python、Ruby 等)允许这样做?

特别是,它是随机系统调用。

答案1

Perl 的功能允许这样做syscall

$ 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

文档还给出了调用 write(2) 的示例:

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

不能说我已经曾经不过使用了这个功能。好吧,在刚才确认这个例子确实有效之前。

这似乎适用于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..

如果您的 syscall.ph 中没有 getrandom,那么您可以使用该数字。我的 Debian 测试 (amd64) 机器上的值为 318。请注意,Linux 系统调用编号是特定于体系结构的。

答案2

在Python中你可以使用ctypes模块访问动态库中的任意函数,包括syscall()来自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)

如果您的 libc 包含getrandom()包装函数,您也可以调用它:

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)

答案3

Ruby 有一个syscall(num [, args...]) → integer函数。

例如:

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

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> 

相关内容