Winapi 读取内存和访问被拒绝

Winapi 读取内存和访问被拒绝,winapi,pywin32,Winapi,Pywin32,我需要在本地Windows 7-64位中访问正在运行的进程的所有内存。我不熟悉winapi 这是我的问题;每当我试图打开一个进程并读取它的内存时,我得到的访问被拒绝错误 我搜索了一下,发现了一些东西。据说,如果我以管理员的身份运行主进程,并在OpenProcess上使用process\u ALL\u ACCESS,我就有足够的权利按照上面所说的去做。好的,我做到了。但一切都没有改变。在读取内存时,我仍然获得访问被拒绝 所以,我一直在搜索,发现另一个东西是启用SeDebugPrivilege。我也

我需要在本地
Windows 7-64位
中访问正在运行的进程的所有内存。我不熟悉
winapi

这是我的问题;每当我试图打开一个进程并读取它的内存时,我得到的
访问被拒绝
错误

我搜索了一下,发现了一些东西。据说,如果我以管理员的身份运行主进程,并在
OpenProcess
上使用
process\u ALL\u ACCESS
,我就有足够的权利按照上面所说的去做。好的,我做到了。但一切都没有改变。在读取内存时,我仍然获得
访问被拒绝

所以,我一直在搜索,发现另一个东西是启用
SeDebugPrivilege
。我也这样做了,但没有任何改变。我仍然得到错误

我已经在这里读到了探索和他的答案; . 但正如我所说的,我对winapi真的很陌生。我还不能解决我的问题。我需要在本地操作系统中配置什么吗

这是我使用pywin32编写的Python代码

from _ctypes import byref, sizeof, Structure
from ctypes import windll, WinError, c_buffer, c_void_p, create_string_buffer
from ctypes.wintypes import *
import win32security
import win32api
import gc
import ntsecuritycon
from struct import Struct
from win32con import PROCESS_ALL_ACCESS
from struct import calcsize

MEMORY_STATES = {0x1000: "MEM_COMMIT", 0x10000: "MEM_FREE", 0x2000: "MEM_RESERVE"}
MEMORY_PROTECTIONS = {0x10: "PAGE_EXECUTE", 0x20: "PAGE_EXECUTE_READ", 0x40: "PAGEEXECUTE_READWRITE",
                      0x80: "PAGE_EXECUTE_WRITECOPY", 0x01: "PAGE_NOACCESS", 0x04: "PAGE_READWRITE",
                      0x08: "PAGE_WRITECOPY"}
MEMORY_TYPES = {0x1000000: "MEM_IMAGE", 0x40000: "MEM_MAPPED", 0x20000: "MEM_PRIVATE"}


class MEMORY_BASIC_INFORMATION(Structure):
    _fields_ = [
        ("BaseAddress", c_void_p),
        ("AllocationBase", c_void_p),
        ("AllocationProtect", DWORD),
        ("RegionSize", UINT),
        ("State", DWORD),
        ("Protect", DWORD),
        ("Type", DWORD)
    ]


class SYSTEM_INFO(Structure):
    _fields_ = [("wProcessorArchitecture", WORD),
                ("wReserved", WORD),
                ("dwPageSize", DWORD),
                ("lpMinimumApplicationAddress", DWORD),
                ("lpMaximumApplicationAddress", DWORD),
                ("dwActiveProcessorMask", DWORD),
                ("dwNumberOfProcessors", DWORD),
                ("dwProcessorType", DWORD),
                ("dwAllocationGranularity", DWORD),
                ("wProcessorLevel", WORD),
                ("wProcessorRevision", WORD)]


class PyMEMORY_BASIC_INFORMATION:
    def __init__(self, MBI):
        self.MBI = MBI
        self.set_attributes()


    def set_attributes(self):
        self.BaseAddress = self.MBI.BaseAddress
        self.AllocationBase = self.MBI.AllocationBase
        self.AllocationProtect = MEMORY_PROTECTIONS.get(self.MBI.AllocationProtect, self.MBI.AllocationProtect)
        self.RegionSize = self.MBI.RegionSize
        self.State = MEMORY_STATES.get(self.MBI.State, self.MBI.State)
        # self.Protect = self.MBI.Protect  # uncomment this and comment next line if you want to do a bitwise check on Protect.
        self.Protect = MEMORY_PROTECTIONS.get(self.MBI.Protect, self.MBI.Protect)
        self.Type = MEMORY_TYPES.get(self.MBI.Type, self.MBI.Type)


ASSUME_ALIGNMENT = True


class TARGET:
    """Given a ctype (initialized or not) this coordinates all the information needed to read, write and compare."""

    def __init__(self, ctype):

        self.alignment = 1
        self.ctype = ctype
        # size of target data
        self.size = sizeof(ctype)
        self.type = ctype._type_

        # get the format type needed for struct.unpack/pack.
        while hasattr(self.type, "_type_"):
            self.type = self.type._type_
            # string_buffers and char arrays have _type_ 'c'
            # but that makes it slightly slower to unpack
            # so swap is for 's'.
        if self.type == "c":
            self.type = "s"
        # calculate byte alignment. this speeds up scanning substantially
        # because we can read and compare every alignment bytes
        # instead of every single byte.
        # although if we are scanning for a string the alignment is defaulted to 1 \
        # (im not sure if this is correct).
        elif ASSUME_ALIGNMENT:
            # calc alignment
            divider = 1
            for i in xrange(4):
                divider *= 2
                if not self.size % divider:
                    self.alignment = divider

        # size of target ctype.
        self.type_size = calcsize(self.type)
        # length of target / array length.
        self.length = self.size / self.type_size
        self.value = getattr(ctype, "raw", ctype.value)
        # the format string used for struct.pack/unpack.
        self.format = str(self.length) + self.type
        # efficient packer / unpacker for our own format.
        self.packer = Struct(self.format)


    def get_packed(self):

        """Gets the byte representation of the ctype value for use with WriteProcessMemory."""
        return self.packer.pack(self.value)


    def __str__(self):
        return str(self.ctype)[:10] + "..." + " <" + str(self.value)[:10] + "..." + ">"


class Memory(object):
    def __init__(self, process_handle, target):
        self._process_handle = process_handle
        self._target = target
        self.found = []
        self.__scann_process()


    def __scann_process(self):
        """scans a processes pages for the target value."""

        si = SYSTEM_INFO()
        psi = byref(si)
        windll.kernel32.GetSystemInfo(psi)

        base_address = si.lpMinimumApplicationAddress
        max_address = si.lpMaximumApplicationAddress

        page_address = base_address

        while page_address < max_address:
            page_address = self.__scan_page(page_address)

            if len(self.found) >= 60000000:
                print("[Warning] Scan ended early because too many addresses were found to hold the target data.")
                break

        gc.collect()
        return self.found


    def __scan_page(self, page_address):
        """Scans the entire page for TARGET instance and returns the next page address and found addresses."""

        information = self.VirtualQueryEx(page_address)
        base_address = information.BaseAddress
        region_size = information.RegionSize
        next_region = base_address + region_size
        size = self._target.size
        target_value = self._target.value
        step = self._target.alignment
        unpacker = self._target.packer.unpack

        if information.Type != "MEM_PRIVATE" or \
                        region_size < size or \
                        information.State != "MEM_COMMIT" or \
                        information.Protect not in ["PAGE_EXECUTE_READ", "PAGEEXECUTE_READWRITE", "PAGE_READWRITE"]:
            return next_region

        page_bytes = self.ReadMemory(base_address, region_size)

        for i in xrange(0, (region_size - size), step):

            partial = page_bytes[i:i + size]

            if unpacker(partial)[0] == target_value:
                self.found.append(base_address + i)

        del page_bytes  # free the buffer
        return next_region

    def ReadMemory(self, address, size):
        cbuffer = c_buffer(size)
        success = windll.kernel32.ReadProcessMemory(
            self._process_handle,
            address,
            cbuffer,
            size,
            0)

        assert success, "ReadMemory Failed with success == %s and address == %s and size == %s.\n%s" % (
            success, address, size, WinError(win32api.GetLastError()))
        return cbuffer.raw


    def VirtualQueryEx(self, address):
        MBI = MEMORY_BASIC_INFORMATION()
        MBI_pointer = byref(MBI)
        size = sizeof(MBI)
        success = windll.kernel32.VirtualQueryEx(
            self._process_handle,
            address,
            MBI_pointer,
            size)

        assert success, "VirtualQueryEx Failed with success == %s.\n%s" % (
            success, WinError(win32api.GetLastError())[1])
        assert success == size, "VirtualQueryEx Failed because not all data was written."
        return PyMEMORY_BASIC_INFORMATION(MBI)


def AdjustPrivilege(priv):
    flags = win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY
    p = win32api.GetCurrentProcess()
    htoken = win32security.OpenProcessToken(p, flags)
    id = win32security.LookupPrivilegeValue(None, priv)
    newPrivileges = [(id, win32security.SE_PRIVILEGE_ENABLED)]
    win32security.AdjustTokenPrivileges(htoken, 0, newPrivileges)
    win32api.CloseHandle(htoken)


def OpenProcess(pid=win32api.GetCurrentProcessId()):
    # ntsecuritycon.SE_DEBUG_NAME = "SeDebugPrivilege"
    AdjustPrivilege(ntsecuritycon.SE_DEBUG_NAME)

    phandle = windll.kernel32.OpenProcess( \
        PROCESS_ALL_ACCESS,
        0,
        pid)

    assert phandle, "Failed to open process!\n%s" % WinError(win32api.GetLastError())[1]
    return phandle


PID = 22852
process_handle = OpenProcess(PID)
Memory(process_handle, TARGET(create_string_buffer("1456")))
我不知道还有什么关于我的代码和我的个人Windows7操作系统的信息,我应该提供给你。如果您需要了解更多,请向我询问,我将提供它来解决该问题


我想,这是因为我的操作系统缺少配置,而不是关于
pywin32
。我将等待您的解决方案。

第1课Windows API编程:检查错误。有一个不应该被默默忽略的返回值。@IInspectable:实际上它甚至比这个更糟糕;AdjustTokenPrivileges是极少数需要检查最后一个错误代码的函数之一,即使返回代码指示成功。(但如果这是问题所在,OpenProcess可能会失败,而不是ReadMemory。)您确定目标进程中的地址不是131072吗?@IInspectable,谢谢您的教训。我会找的。但是没有问题,我评论晚了。我试图编辑我的代码,通过切割合适的零件来向您展示@HarryJohnston,请看我编辑的代码。事实上,我不是直接给出那个地址(131072)的人。我想扫描和搜索一个进程的所有内存单元。此代码正在为系统最小和最大地址之间的所有地址创建VirtualQueryEx。当它在addreses上运行时,首先它意识到需要读取一个地址(131072)(ReadProcessMemory),我得到了错误。我想,地址是有效的。
AssertionError: ReadMemory Failed with success == 0 and address == 131072 and size == 4096.
[Error 5] Access is denied.