Python ctypes 长整数错误,我该如何解决这个问题?

Python ctypes long integer error, how can i fix this?

提问人:Ali Can Gönüllü 提问时间:10/31/2023 最后编辑:Ali Can Gönüllü 更新时间:10/31/2023 访问量:65

问:

我正在使用 Python 开发内存快照/采集软件,因此我使用“pymem_snapshot”库和“winpmem”驱动程序。

import ctypes
import struct
import sys
import win32file
import win32service
import os
from ctypes import *


def CTL_CODE(DeviceType, Function, Method, Access):
    return (DeviceType << 16) | (Access << 14) | (Function << 2) | Method
    
CTRL_IOCTRL = CTL_CODE(0x22, 0x101, 3, 3) # IOCTL_SET_MODE
INFO_IOCTRL = CTL_CODE(0x22, 0x103, 3, 3)
IOCTL_REVERSE_SEARCH_QUERY = CTL_CODE(0x22, 0x104, 3, 3)

class PyMem:
    FIELDS = (["CR3", "NtBuildNumber", "KernBase", "KDBG"] +
              ["KPCR%02d" % i for i in range(32)] +
              ["PfnDataBase", "PsLoadedModuleList", "PsActiveProcessHead"] +
              ["Padding%s" % i for i in range(0xff)] +
              ["NumberOfRuns"])
    
    def GetInfo(fd):
        result = win32file.DeviceIoControl(fd, INFO_IOCTRL, b"", 102400, None)
        fmt_string = "Q" * len(PyMem.FIELDS)
        memory_parameters = dict(zip(PyMem.FIELDS, struct.unpack_from(fmt_string, result)))
        for k, v in sorted(memory_parameters.items()):
            if k.startswith("Pad"):
                continue
            if not v: continue
            print("%s: \t%#08x (%s)" % (k, v, v))

    def SetMode(fd, modeset = "pte"):
        try:
            if modeset == "iospace":
                mode = 0
            elif modeset == "physical":
                mode = 1
            elif modeset == "pte":
                mode = 2
            elif modeset == "pte_pci":
                mode = 3
            else:
                raise RuntimeError("Mode %s not supported" % str(modeset))
            win32file.DeviceIoControl(fd, CTRL_IOCTRL, struct.pack("I", mode), 0, None)
            print(f"Mode has been set to {modeset}")
        except Exception as e:
            return str(e)
    
    def service_create():
        try:
            os.system(f"net stop winpmem")  # Stop any previous instance of the driver
            os.system(f"sc delete winpmem")  # Delete any previous instance of the driver
            if ctypes.sizeof(ctypes.c_voidp) == 4:
                if os.path.isfile("winpmem_x86.sys") is True:
                    driver_path = "winpmem_x86.sys"
                else:
                    return "Driver file are not found"
            else:
                if os.path.isfile("winpmem_x64.sys") is True:
                    driver_path = "winpmem_x64.sys"
                else:
                    return "Driver file are not found"
            # Create a new instance of the driver
            driver = os.path.join(os.getcwd(), driver_path)
            hScm = win32service.OpenSCManager(None, None, win32service.SC_MANAGER_CREATE_SERVICE)
            try:
                hSvc = win32service.CreateService(hScm, "winpmem", "winpmem", win32service.SERVICE_ALL_ACCESS, win32service.SERVICE_KERNEL_DRIVER, win32service.SERVICE_DEMAND_START, win32service.SERVICE_ERROR_IGNORE, driver, None, 0, None, None, None)
            except win32service.error as e:
                print(e)
                hSvc = win32service.OpenService(hScm, "winpmem", win32service.SERVICE_ALL_ACCESS)
                
            try:
                win32service.ControlService(hSvc, win32service.SERVICE_CONTROL_STOP)
            except win32service.error:
                pass

            try:
                win32service.StartService(hSvc, [])
            except win32service.error as e:
                print("%s: will try to continue" % e)

            print("WinPMEM Started")
        except Exception as e:
            print("ERROR : WinPMEM can not created. Reason : " + str(e))

    @staticmethod
    def dump_and_save_memory(filename, memsize = int(1024 * 1024)):
        print("Creating AFF4 (Rekall) file")
        device_handle = win32file.CreateFile(
            "\\\\.\\pmem",
            win32file.GENERIC_READ | win32file.GENERIC_WRITE,
            win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
            None,
            win32file.OPEN_EXISTING,
            win32file.FILE_ATTRIBUTE_NORMAL,
            None)
        # Set Modes and get informations
        if device_handle is True:
            print("Error: open device failed.\n")
        else:
            PyMem.SetMode(device_handle)
            PyMem.GetInfo(device_handle)
            print("\nMEMSIZE : " + str(memsize))
            with open(filename + ".aff", "wb") as f:
                mem_addr = 0
                while mem_addr < memsize:
                    win32file.SetFilePointer(device_handle, mem_addr, 0) # Setting pointer
                    data = win32file.ReadFile(device_handle, memsize)[1] # Reading memory...
                    f.write(data) # Writing to file
                    mem_addr += memsize
                    offset_in_mb = mem_addr / 1024 / 1024
                    if not offset_in_mb % 50:
                        sys.stdout.write("\n%04dMB\t" % offset_in_mb)
                    sys.stdout.flush()
                    print(f"Dumped {mem_addr} / {memsize} bytes and {offset_in_mb} MB/offset ({mem_addr * 100 / memsize:.2f}%)")
                f.close()
                win32file.CloseHandle(device_handle)

如果你想要类 GitHub 链接

但是当我想获得大容量内存(超过 2GB)时,我会出现整数错误。

我的程序(稳定版)

from src.pymem_class import PyMem

if __name__ == "__main__":
    PyMem.service_create()
    # Drivers: https://github.com/Velocidex/WinPmem/tree/master/kernel/binaries
    # Run "bcdedit /set testsigning on" command
    # Check Memory Compression with "Get-MMAgent" command
    # Disable Memory Compression with "Disable-MMAgent -mc" command
    # Restart computer
    PyMem.dump_and_save_memory("demo", int(1024 * 1024 * 1024)) # 1 GB Memory Image WORKING

我的程序(崩溃)

from src.pymem_class import PyMem

if __name__ == "__main__":
    PyMem.service_create()
    # Drivers: https://github.com/Velocidex/WinPmem/tree/master/kernel/binaries
    # Run "bcdedit /set testsigning on" command
    # Check Memory Compression with "Get-MMAgent" command
    # Disable Memory Compression with "Disable-MMAgent -mc" command
    # Restart computer
    PyMem.dump_and_save_memory("demo", int(8 * 1024 * 1024 * 1024)) # 8 GB Memory Image CRASH

崩溃日志

Traceback (most recent call last):
  File "C:\Users\dfnss\OneDrive\Desktop\pymem_snapshot\example.py", line 11, in <module>
    PyMem.dump_and_save_memory("demo", memsize)
  File "C:\Users\dfnss\OneDrive\Desktop\pymem_snapshot\src\pymem_class.py", line 51, in dump_and_save_memory
    data = win32file.ReadFile(device_handle, memsize)[1] # Reading memory...
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Second param must be an integer or writeable buffer object

我该如何解决这个问题?我什至尝试了 ChatGPT 的帮助,但没有用

感谢您的回答

python 安全 ctypes pywin32 pywin

评论

0赞 CristiFati 10/31/2023
你为什么关闭 stackoverflow.com/q/77383190/4788546?它为您当前的答案提供了答案。
0赞 Ali Can Gönüllü 10/31/2023
@CristiFati 坦率地说,我在那里解决了大部分问题,根据建议,我认为我可以在 GitHub 上使用更稳定的库更快地解决它。我发现我可以在各种软件中检查内存映像。这是我唯一无法解决的问题。我尝试了所有我能想到的方法,但没有奏效。
3赞 CristiFati 10/31/2023
是的,但是一旦您的问题得到解答,您就不会删除该问题。再次发帖:[SO]:当有人回答我的问题时,我该怎么办?
1赞 CristiFati 10/31/2023
此外,所有代码都必须发布在这里([SO]:如何创建一个最小的、可重复的示例(reprex (mcve))),而不是链接、图片......
0赞 Mark Tolonen 10/31/2023
它适用于较小的吗?Win32 ReadFile() 接受 DWORD(32 位)作为读取长度,因此最大值为 4GB-1,而你将传递 8GB。它看起来像一个 API 限制。memsize

答:

-1赞 Schnitte 10/31/2023 #1

Pymem 需要一个整数 (of ) 类型作为内存大小的参数。Python 上的数据类型范围从 -2,147,483,648 到 + 2,147,483,647 (来源:在此处输入链接描述)。这意味着您的方程在此范围内,但并非如此。intint1024 * 1024 * 10248 * 1024 * 1024 * 1024

评论

0赞 Ali Can Gönüllü 10/31/2023
谢谢你的回答,我忘了这个。当然,有一个整数限制:)
0赞 CristiFati 10/31/2023
不對。整数是无限的:docs.python.org/3/library/...
0赞 Ali Can Gönüllü 10/31/2023
那么,我可以生产什么作为这种方法的替代品呢?坦率地说,我正在寻找更清晰的答案。因为程序有点复杂