Реализовать NtCreateNamedPipeFile с помощью ctypes в Python - PullRequest
0 голосов
/ 12 июня 2018

Я пытаюсь реализовать недокументированную функцию NtCreateNamedPipeFile из NTAPI с ctypes, но я не могу заставить ее работать (у меня очень мало опыта работы с ctypes).

Во-первых,если я предоставляю все аргументы из определения функции, я получаю ошибку «ValueError: Процедура, вероятно, вызвана со слишком большим количеством аргументов (4 байта больше)».

Если я удаляю аргумент NamedPipeFileHandle (при условиичто дескриптор может быть тем, что возвращает эта функция), я получаю «OSError: [WinError 87] Параметр неверен».

Я пытался настроить типы и аргументы в моей реализации, но независимо от того, что я делаю,Я получаю тот же WinError 87. Он не очень описательный, поэтому трудно понять, что я здесь делаю неправильно (возможно, многие вещи).

Вот определения:

ULONG_PTR = ctypes.wintypes.WPARAM
FILE_READ_DATA = 0x00000001
FILE_WRITE_DATA = 0x00000002
SYNCHRONIZE = 0x00100000
FILE_READ_ATTRIBUTES = 0x80
FILE_CREATE = 0x00000002

def NtError(status):
    err = ntdll.RtlNtStatusToDosError(status)
    return ctypes.WinError(err)


class IO_STATUS_BLOCK(ctypes.Structure):
    class _STATUS(ctypes.Union):
        _fields_ = (('Status',  LONG),
                    ('Pointer', LPVOID))
    _anonymous_ = '_Status',
    _fields_ = (('_Status', _STATUS),
                ('Information', ULONG_PTR))


class UNICODE_STRING(ctypes.Structure):
    _fields_ = (('Length', USHORT),
                ('MaximumLength', USHORT),
                ('Buffer', LPWSTR))

class OBJECT_ATTRIBUTES(ctypes.Structure):
    _fields_ = (
        ('Length', ULONG),
        ('RootDirectory', HANDLE),
        ('ObjectName', UNICODE_STRING),
        ('Attributes', ULONG),
    )

ntdll = ctypes.WinDLL('ntdll')

def _decl(name, ret=None, args=()):
    fn = getattr(ntdll, name)
    fn.restype = ret
    fn.argtypes = args
    return fn

NtCreateNamedPipeFile = _decl('NtCreateNamedPipeFile', LONG,
                              (
                                   POINTER(HANDLE),
                                   DWORD,
                                   POINTER(OBJECT_ATTRIBUTES),
                                   POINTER(IO_STATUS_BLOCK),
                                   ULONG,
                                   ULONG,
                                   ULONG,
                                   BOOL,
                                   BOOL,
                                   BOOL,
                                   ULONG,
                                   ULONG,
                                   ULONG,
                                   LARGE_INTEGER))

И сам звонок:

handle = HANDLE()
iosb = IO_STATUS_BLOCK()

us_pipe_name = UNICODE_STRING()
us_pipe_name.Buffer = '\\??\\pipe\\' + name
us_pipe_name.Length = len(us_pipe_name.Buffer)
us_pipe_name.MaximumLength = len(us_pipe_name.Buffer)

obj_attrs = OBJECT_ATTRIBUTES()
obj_attrs.ObjectName = us_pipe_name

status = NtCreateNamedPipeFile(
    # ctypes.byref(handle),  # NamedPipeFileHandle
    FILE_READ_DATA | SYNCHRONIZE,  # DesiredAccess
    ctypes.byref(obj_attrs),  # ObjectAttributes
    ctypes.byref(iosb),  # IoStatusBlock
    0,  # ShareAccess
    FILE_CREATE,  # CreateDisposition
    0,  # CreateOptions
    0,  # WriteModeMessage
    0,  # ReadModeMessage
    1,  # NonBlocking
    1,  # MaxInstances
    1024,  # InBufferSize
    1024,  # OutBufferSize
    0,  # DefaultTimeout
)

if status != 0:
    exception = NtError(status)
    raise exception

Что я тут не так делаю?

...