โทร Linux syscall จากภาษาสคริปต์


15

ฉันต้องการเรียก Linux syscall (หรืออย่างน้อย libc wrapper) โดยตรงจากภาษาสคริปต์ ฉันไม่สนใจภาษาสคริปต์ใด - เป็นสิ่งสำคัญที่จะไม่รวบรวม (เหตุผลโดยทั่วไปเกี่ยวกับการไม่ต้องการคอมไพเลอร์ในเส้นทางการพึ่งพา แต่นั่นไม่ใช่ที่นี่หรือที่นั่น) มีภาษาสคริปต์ (เชลล์, Python, Ruby, etc) ที่อนุญาตสิ่งนี้หรือไม่?

โดยเฉพาะอย่างยิ่งมันเป็นsyscall สุ่ม


3
getrandom /dev/urandomเพียงดึงไบต์สุ่มจาก แน่นอนคุณสามารถทำได้จากเชลล์สคริปต์
สตีฟ

@steve แน่นอนเว้นแต่แน่นอน/devยังไม่สามารถใช้ได้ แต่ก็ยากที่จะจินตนาการว่า Perl จะเป็นเช่นนั้น!
Derobert

วิกฤตฉันต้องการสิ่งนี้เพื่อป้องกันจนกว่าจะเริ่มต้นสระว่ายน้ำเอนโทรปีซึ่งอ่านจาก / dev / urandom เป็นไฟล์ไม่ได้ทำ
joshlf

5
อ่านจาก/dev/randomจนกว่าจะปลดบล็อกแล้วอ่านจาก/dev/urandom?
อธิการ

1
"เหตุผลโดยทั่วไปเกี่ยวข้องกับการไม่ต้องการคอมไพเลอร์ในเส้นทางการพึ่งพา แต่นั่นไม่ใช่ที่นี่หรือไม่มี" -> อืม? หากคุณหมายถึงเส้นทางการพึ่งพารันไทม์คุณจะไม่ได้รับผลกระทบใด ๆ คุณไม่ต้องการคอมไพเลอร์ C เพื่อรันไบนารีที่รวบรวมจาก C. หากคุณหมายความว่าคุณไม่ต้องการพึ่งพาความสามารถในการรวบรวมสิ่งต่าง ๆ สำหรับสถาปัตยกรรมเป้าหมายของคุณเพราะคุณคิดว่าคุณจะไม่มีความสามารถนั้น ไม่น่าเป็นไปได้ที่คุณจะสามารถทำให้ Python, Bash หรือภาษาสคริปต์จริงอื่น ๆ ทำงานบนแพลตฟอร์มนั้นได้
Kevin

คำตอบ:


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
⋮

เอกสารประกอบยังมีตัวอย่างของการเรียกการเขียน (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..

และถ้าคุณไม่มี getrandom ใน syscall.ph คุณสามารถใช้ตัวเลขแทนได้ มันคือ 318 สำหรับการทดสอบ Debian ของฉัน (amd64) ระวังตัวเลข Linux syscall เป็นสถาปัตยกรรมเฉพาะ


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()ฟังก์ชั่น wrapper คุณสามารถเรียกมันว่า:

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)

โอกาสใดที่คุณสามารถเพิ่มตัวอย่างของการเรียกใช้getrandomฟังก์ชันlibc โดยตรงแทนที่จะเป็น syscall getrandom? เป็นไปได้ไหม
joshlf

@joshlf แน่นอนมันเป็นไปได้ ฉันแก้ไขคำตอบของฉัน
cg909

คุณรู้หรือไม่ว่ามีวิธีในการค้นหาค่าที่ถูกต้องของSYS_getrandomค่าที่รันไทม์แบบไดนามิก(เพื่อให้มันถูกต้องสำหรับแพลตฟอร์มปัจจุบัน)? เช่นโดยการแยก/usr/includeไฟล์ส่วนหัว?
joshlf

ผมไม่ได้ลอง แต่คุณอาจมีโชคกับpycparser
cg909

17

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> 
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.