Gọi một tòa nhà Linux từ một ngôn ngữ kịch bản


15

Tôi muốn gọi một tòa nhà chọc trời của Linux (hoặc ít nhất là trình bao bọc libc) trực tiếp từ một ngôn ngữ kịch bản. Tôi không quan tâm ngôn ngữ kịch bản nào - điều quan trọng là nó không được biên dịch (lý do cơ bản là phải làm với việc không muốn có trình biên dịch trong đường dẫn phụ thuộc, nhưng điều đó không có ở đây cũng không có). Có ngôn ngữ script nào (shell, Python, Ruby, v.v.) cho phép điều này không?

Đặc biệt, đó là tòa nhà cao tầng .


3
getrandom chỉ đơn thuần là kéo theo byte ngẫu nhiên từ /dev/urandom. Bạn chắc chắn có thể làm điều đó từ một kịch bản shell.
steve

@steve thực sự, trừ khi tất nhiên /devlà chưa có sẵn. Nhưng sau đó thật khó để tưởng tượng Perl sẽ thế nào!
derobert

Quan trọng, tôi muốn điều này chặn cho đến khi nhóm entropy được khởi tạo, việc đọc từ / dev / urandom như một tệp không làm được.
joshlf

5
Đọc từ /dev/randomcho đến khi nó mở khóa, sau đó đọc từ /dev/urandomđâu?
giám mục

1
"Lý do cơ bản phải làm với việc không muốn trình biên dịch trong đường dẫn phụ thuộc, nhưng đó không phải ở đây cũng không có" -> Huh? Nếu bạn có nghĩa là đường dẫn phụ thuộc thời gian chạy , thì bạn sẽ không trong mọi trường hợp. Bạn không cần trình biên dịch C để chạy nhị phân được biên dịch từ C. Nếu bạn muốn nói rằng bạn không muốn phụ thuộc vào khả năng biên dịch mọi thứ cho kiến ​​trúc mục tiêu của mình, vì bạn nghĩ rằng bạn sẽ không có khả năng đó, thì nó không chắc bạn sẽ có thể làm cho Python, Bash hoặc bất kỳ ngôn ngữ kịch bản thực nào khác chạy trên nền tảng đó.
Kevin

Câu trả lời:


33

Perl cho phép điều này với syscallchức năng của nó :

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

Tài liệu này cũng đưa ra một ví dụ về cách gọi write (2):

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

Mặc dù vậy, không thể nói tôi đã từng sử dụng tính năng này. Vâng, trước đây chỉ để xác nhận ví dụ thực sự hoạt động.

Điều này dường như để làm việc với 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..

Và nếu bạn không có getrandom trong tòa nhà của mình, thì bạn có thể sử dụng số này để thay thế. Đó là 318 trên hộp thử nghiệm Debian (amd64) của tôi. Coi chừng các số tòa nhà của Linux là đặc trưng kiến ​​trúc.


2
Perl - kế hoạch B búa!
Thorbjørn Ravn Andersen

28

Trong Python, bạn có thể sử dụng ctypesmô-đun để truy cập các hàm tùy ý trong các thư viện động, bao gồm syscall()từ 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)

Nếu libc của bạn bao gồm getrandom()chức năng bao bọc, bạn cũng có thể gọi nó:

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)

Bất kỳ cơ hội nào bạn có thể thêm một ví dụ về việc gọi getrandomhàm libc trực tiếp chứ không phải là tòa nhà chọc trời getrandom? Điều đó có thể không?
joshlf

@joshlf Tất nhiên là có thể. Tôi chỉnh sửa câu trả lời của tôi.
cg909

Bạn có biết liệu có cách nào để tự động tra cứu giá trị chính xác của SYS_getrandomgiá trị trong thời gian chạy không (để bạn hiểu đúng về nền tảng hiện tại)? Ví dụ, bằng cách phân tích /usr/includetệp tiêu đề?
joshlf

Tôi đã không thử nó, nhưng bạn có thể gặp may mắn với pycparser .
cg909

17

Ruby có syscall(num [, args...]) → integerchức năng.

Ví dụ:

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

Với 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> 
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.