PYTHON – Ctypes: OSError: excepción: escritura de infracción de acceso 0xFFFFFFFFFA1C001B

Aquí hay un código para escribir valores en la memoria usando la asignación de memoria. Cuando bash ejecutar el código, aparece el error “Archivo” MMF.py “, línea 26, en memcpy (pBuf, szMsg, len (szMsg)) OSError: excepción: infracción de acceso escribiendo 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() 

Antes de nada, aquí está (casi) todo lo que necesita: [Python 3]: ctypes – Una biblioteca de funciones foránea para Python . ctypes.wintypes no se explica, pero puede ver sus exportaciones ejecutando dir(ctypes.wintypes) en la consola de Python . Tenga en cuenta que todos estos tipos son tipos de ctypes simples, los uso solo por razones de convención / consistencia / legibilidad.

Su código actualizado ( code.py ):

 #!/usr/bin/env python3 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() 

Notas :

  • Se agregaron los argtypes y restype para las funciones. Los detalles se pueden ver en las secciones ” Especificar los tipos de argumentos requeridos (prototipos de función) ” y ” Tipos de retorno “, y por supuesto MSDN para las declaraciones de funciones.
  • El 2do argumento de memcpy es una cadena de Python , que no es la misma que su dirección char * (sin mencionar que en Python 3 , las cadenas están basadas en wchar_t ) que memcpy espera, esto probablemente producirá un comportamiento indefinido
  • El valor de FILE_MAP_ALL_ACCESS es 0x000F001F (impreso el valor de VStudio 2015 ), 0x04 corresponde a FILE_MAP_READ
  • Error al convertir el valor antiguo de INVALID_HANDLE_VALUE a HANDLE , lo cambió a -1 (como en handleapi.h )
  • Estás llamando a CreateFileMappingA con un c_wchar_p . Eso establecerá un nombre que consiste solo en el 1er carácter de la cadena provista para el objeto de mapeo porque cada wcha_t consta de 2 bytes: 0x00 más el valor char correspondiente – ‘ A ‘ se representará como 0x00 0x41 (generalmente esto no es cierto – especialmente la parte 0x00 , pero en nuestro caso, lo es) – por lo que el char en el argumento lpName (debido a la poca endianidad ) será 0x00 ( NULL )
  • No es necesario importar el módulo msvcrt , solo para _getch, que también está expuesto por vcruntime140.dll ( ucrtbase.dll )
  • Según la página de arriba:

    El acceso a la biblioteca estándar de C a través de cdll.msvcrt usará una versión desactualizada de la biblioteca que puede ser incompatible con la que está usando Python.

    Por lo tanto, también agregué [Docs.MS]: función RtlCopyMemory para reemplazar memcpy (puede comentar su línea, la dejé allí solo para mostrar que funciona), como en el ejemplo ( [MS.Docs]: Creando un nombre compartido Memoria ) de la que tomó el código e intentó convertirlo ([ minwinbase.h: 36 ]: #define CopyMemory RtlCopyMemory )

  • Se cambió la convención de nomenclatura para que sea compatible con Python ( [Python]: PEP 8 – Guía de estilo para el código de Python )
  • Otros cambios (no críticos) (formato de salida, movimiento de líneas de código para una mejor estructura, etc.)

Salida :

 (py35x64_test) E:\Work\Dev\StackOverflow\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...