Виклик системної виклику Linux з мови скриптів


15

Я хочу зателефонувати в syscall Linux (або, принаймні, оболонку libc) безпосередньо з мови сценаріїв. Мені все одно, яка мова сценаріїв - просто важливо, щоб вона не була складена (причина в основному пов’язана з тим, що не потрібно компілятор на шляху залежності, але це ні тут, ні там). Чи є якісь мови сценаріїв (оболонка, Python, Ruby тощо), які це дозволяють?

Зокрема, це випадковий систематичний виклик.


3
getrandom просто тягне за собою випадкові байти з /dev/urandom. Ви, звичайно, можете це зробити із сценарію оболонки.
Стів

@steve дійсно, якщо, звичайно /dev, поки що немає. Але тоді важко уявити Perl!
derobert

Критично, я хочу, щоб це блокувалося, поки пул ентропії не ініціалізується, що читання з / dev / urandom як файл не робить.
joshlf

5
Читати з /dev/randomмоменту, поки він не розблокує, а потім прочитати /dev/urandom?
єпископ

1
"причина в основному пов'язана з тим, що не потрібно компілятор на шляху залежності, але це ні тут, ні там" -> Так? Якщо ви маєте на увазі шлях залежності від часу виконання , то у будь-якому випадку ви цього не зробите. Вам не потрібен компілятор C для запуску двійкового файлу, який був зібраний з C. Якщо ви маєте на увазі, що ви не хочете залежати від здатності збирати речі для вашої цільової архітектури, тому що ви думаєте, що не зможете мати цю здатність, тоді це навряд чи ви зможете змусити Python, Bash або будь-яку іншу реальну мову сценаріїв працювати на цій платформі.
Кевін

Відповіді:


33

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 у випадковому випадку, ви можете використовувати це число замість цього. На моєму тестуванні Debian (amd64) це 318. Будьте уважні, що номери системних викликів Linux залежать від архітектури.


2
Perl - молот плану B!
Thorbjørn Ravn Andersen

28

У 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)

Ви можете додати приклад виклику функції libc getrandomбезпосередньо, а не syscall getrandom? Це можливо?
joshlf

@joshlf Звичайно, це можливо. Я відредагував свою відповідь.
cg909

Чи знаєте ви, чи є спосіб динамічно шукати правильне значення SYS_getrandomзначення під час виконання (щоб ви зрозуміли це для поточної платформи)? Наприклад, розбираючи /usr/includeфайли заголовків?
joshlf

Я не пробував цього, але ви, можливо, пощастить з Pycparser .
cg909

17

У Рубі є 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> 
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.