PYTHON-Ctypes:OSError:exception:写入0xfffffffa1c001b的访问冲突

2024-05-15 22:59:35 发布

您现在位置:Python中文网/ 问答频道 /正文

下面是一个代码,用于使用内存映射将值写入内存。当我试图运行代码时,我得到了错误 “文件”MMF.py“,第26行,in 内存(pBuf,szMsg,len(szMsg)) 错误:异常:写入0xfffffffa1c001b“时访问冲突

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

Tags: 内存importlenaccessctypesprintmmapmsvcrt
1条回答
网友
1楼 · 发布于 2024-05-15 22:59:35

在任何事情之前,这里有(几乎)你需要的一切:[Python 3]: ctypes - A foreign function library for Pythonctypes.wintypes没有解释,但是可以通过在Python控制台中运行dir(ctypes.wintypes)来查看其导出。注意,所有这些类型都是简单的ctypes类型,我使用它们只是为了约定/一致性/可读性。

您更新的代码(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()

注意:

  • 为函数添加argtypesrestype。详细信息可以在“指定所需的参数类型(函数原型)”和“返回类型”部分中看到,当然还有函数声明的MSDN
  • memcpy's 2nd参数是一个Python字符串,它与Python期望的地址相同(更不用说在Python 3中,字符串是基于wchar的),这可能会产生未定义的行为
  • 文件映射所有访问的值为0x000F001F(从VStudio 2015中打印出值),0x04对应于文件映射读取
  • 将无效的句柄值的旧值转换为句柄时出错,将其更改为-1(如handleapi.h
  • 你用一个wchar p调用CreateFileMappingA。它将为映射对象设置一个仅由所提供的字符串中的1st字符组成的名称,因为每个wcha t由2个字节组成:0x00加上相应的char值-'a'将表示为0x00 0x41(通常这是而不是真-尤其是0x00部分,但在我们的例子中是这样的)因此lpName参数中的2ndchar将是0x00NULL
  • 无需导入msvcrt模块,仅用于vcruntime140.dllucrtbase.dll)所公开的getch
  • 根据上一页:

    Accessing the standard C library through cdll.msvcrt will use an outdated version of the library that may be incompatible with the one being used by Python.

    因此,我还添加了[Docs.MS]: RtlCopyMemory function来替换memcpy(您可以注释掉它的行,我把它留在那里只是为了表明它是有效的),如您从中获取代码并试图转换它的示例([MS.Docs]: Creating Named Shared Memory)中所示([minwinbase.h:36]:#define CopyMemory RtlCopyMemory

  • 已将命名约定更改为符合Pythoncompliant([Python]: PEP 8 -- Style Guide for Python Code
  • 其他(非关键)更改(输出格式、移动代码行以获得更好的结构,等等…)

输出

(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...

相关问题 更多 >