PYTHON - Ctypes: OSError: исключение: запись нарушения прав доступа 0xFFFFFFFFFA1C001B
Вот код для записи значений в память с использованием отображения памяти. Когда я пытаюсь запустить код, я получаю сообщение об ошибке "Файл"MMF.py", строка 26, в memcpy(pBuf, szMsg, len(szMsg)) OSError: исключение: запись о нарушении прав доступа 0xFFFFFFFFFA1C001B"
import msvcrt, mmap
import ctypes
from ctypes import *
FILE_MAP_ALL_ACCESS = 0x04
INVALID_HANDLE_VALUE = 0xFFFFFFFF
SHMEMSIZE = 256
PAGE_READWRITE = 0x04
szName = ctypes.c_wchar_p("MyFileMappingObject")
szMsg = "Message from Python(ctypes) process"
hMapObject = windll.kernel32.CreateFileMappingA(INVALID_HANDLE_VALUE,None, PAGE_READWRITE, 0, SHMEMSIZE, szName)
print("Handle:",hMapObject)
if (hMapObject == 0):
print("Could not open file mapping object")
raise WinError()
pBuf = windll.kernel32.MapViewOfFile(hMapObject, FILE_MAP_ALL_ACCESS,0, 0, SHMEMSIZE)
print("Buffer Starting Addr:",pBuf)
if (pBuf == 0):
print("Could not map view of file")
raise WinError()
else:
print(len(szMsg))
memcpy = cdll.msvcrt.memcpy
memcpy(pBuf, szMsg, len(szMsg))
shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write("Message Python process")
msvcrt.getch()
windll.kernel32.UnmapViewOfFile(pBuf)
windll.kernel32.CloseHandle(hMapObject)
shmem.close()
1 ответ
Прежде всего, вот (почти) все, что вам нужно: [Python]: ctypes - библиотека сторонних функций для Python, ctypes.wintypes
не объясняется, но вы можете увидеть его экспорт, запустив dir(ctypes.wintypes)
в консоли Python. Обратите внимание, что все эти типы просты ctypes
типы, я использую их только для удобства / согласованности / читаемости.
Ваш обновленный код (code.py):
import sys
from ctypes import windll, cdll,\
c_wchar, c_size_t, c_ulonglong, c_wchar_p, c_void_p,\
sizeof,\
WinError
from ctypes.wintypes import BOOL, DWORD, HANDLE, LPCWSTR, LPCVOID, LPVOID
import mmap
if __name__ == "__main__":
print("Python {:s} on {:s}".format(sys.version, sys.platform))
FILE_MAP_ALL_ACCESS = 0x000F001F
INVALID_HANDLE_VALUE = -1
SHMEMSIZE = 0x100
PAGE_READWRITE = 0x04
kernel32_dll = windll.kernel32
msvcrt_dll = cdll.msvcrt
create_file_mapping_func = kernel32_dll.CreateFileMappingW
create_file_mapping_func.argtypes = (HANDLE, LPVOID, DWORD, DWORD, DWORD, LPCWSTR)
create_file_mapping_func.restype = HANDLE
map_view_of_file_func = kernel32_dll.MapViewOfFile
map_view_of_file_func.argtypes = (HANDLE, DWORD, DWORD, DWORD, c_ulonglong)
map_view_of_file_func.restype = LPVOID
memcpy_func = msvcrt_dll.memcpy
memcpy_func.argtypes = (c_void_p, c_void_p, c_size_t)
memcpy_func.restype = LPVOID
rtl_copy_memory_func = kernel32_dll.RtlCopyMemory
rtl_copy_memory_func.argtypes = (LPVOID, LPCVOID, c_ulonglong)
unmap_view_of_file_func = kernel32_dll.UnmapViewOfFile
unmap_view_of_file_func.argtypes = (LPCVOID,)
unmap_view_of_file_func.restype = BOOL
close_handle_func = kernel32_dll.CloseHandle
close_handle_func.argtypes = (HANDLE,)
close_handle_func.restype = BOOL
get_last_error_func = kernel32_dll.GetLastError
getch_func = msvcrt_dll._getch
file_mapping_name_ptr = c_wchar_p("MyFileMappingObject")
msg = "Message from Python(ctypes) process"
msg_ptr = c_wchar_p(msg)
mapping_handle = create_file_mapping_func(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, SHMEMSIZE, file_mapping_name_ptr)
print("Mapping object handle: 0x{:016X}".format(mapping_handle))
if not mapping_handle:
print("Could not open file mapping object: {:d}".format(get_last_error_func()))
raise WinError()
mapped_view_ptr = map_view_of_file_func(mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0, SHMEMSIZE)
print("Mapped view addr: 0x{:016X}".format(mapped_view_ptr))
if not mapped_view_ptr:
print("Could not map view of file: {:d}".format(get_last_error_func()))
close_handle_func(mapping_handle)
raise WinError()
byte_len = len(msg) * sizeof(c_wchar)
print("Message length: {:d} chars ({:d} bytes)".format(len(msg), byte_len))
memcpy_func(mapped_view_ptr, msg_ptr, byte_len)
rtl_copy_memory_func(mapped_view_ptr, msg_ptr, byte_len)
unmap_view_of_file_func(mapped_view_ptr)
close_handle_func(mapping_handle)
shmem = mmap.mmap(0, 256, "MyFileMappingObject_ctypes", mmap.ACCESS_WRITE)
shmem.write(b"Message Python process")
shmem.close()
print("Hit a key to exit...")
getch_func()
Примечания:
- Добавил
argtypes
а такжеrestype
для функций. Подробности можно увидеть в разделах " Указание обязательных типов аргументов (прототипов функций) " и " Типы возвращаемых данных ", и, конечно, MSDN для объявлений функций. memcpy
Второй аргумент - это строка Python, которая отличается отchar*
адрес (не говоря уже о том, что в Python3 строкиwchar_t
на основании) чтоmemcpy
ожидает, что это, вероятно, приведет к неопределенному поведениюFILE_MAP_ALL_ACCESS
' 0x000F001F (распечатано значение из VStudio 2015), 0x04 соответствуетFILE_MAP_READ
- Ошибка преобразования
INVALID_HANDLE_VALUE
старое значение дляHANDLE
, изменил его на -1 (как в handleapi.h) - Ты звонишь
CreateFileMappingA
сc_wchar_p
, Это установит имя, состоящее только из 1- го символа из предоставленной строки для объекта отображения, потому что каждыйwchar_t
состоит из 2 байтов: 0x00 плюс соответствующийchar
значение - " A " будет представлено как 0x00 0x41 (как правило, это не так - особенно часть 0x00, но в нашем случае, это так) - так что 2- йchar
вlpName
аргумент (из -за порядка байтов) будет 0x00 (NULL
) - Нет необходимости импортировать
msvcrt
модуль, только для_getch
который также выставляется vcruntime140.dll (ucrtbase.dll) Согласно странице выше:
Доступ к стандартной библиотеке C через
cdll.msvcrt
будет использовать устаревшую версию библиотеки, которая может быть несовместима с той, которая используется Python.Итак, я также добавил [Docs.MS]: функцию RtlCopyMemory, чтобы заменить
memcpy
(вы можете закомментировать его строку, я оставил ее там только для того, чтобы показать, что она работает), как в примере ( [MSDN]: Создание именованной общей памяти), из которого вы взяли код и попытались преобразовать его ([ minwinbase. ч: 36 ]:#define CopyMemory RtlCopyMemory
)- Изменено соглашение об именах для обеспечения совместимости с Python ( [Python]: PEP 8 - Руководство по стилю для кода Python)
- Другие (некритические) изменения (форматирование вывода, перемещение строк кода для лучшей структуры и т. Д.)
Выход:
(py35x64_test) E:\Work\Dev\Stackru\q048788549>"e:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe" code.py Python 3.5.4 (v3.5.4:3f56838, Aug 8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32 Mapping object handle: 0x000000000000012C Mapped view addr: 0x00000206E3BD0000 Message length: 35 chars (70 bytes) Hit a key to exit...