读取内存和访问被拒绝

时间:2015-01-11 21:59:12

标签: winapi pywin32

我需要访问本地Windows 7-64bit中正在运行的进程的所有内存。我是winapi的新手。

这是我的问题;每当我尝试打开一个进程并读取其内存时,我都会遇到Access is Denied错误。

我搜索并发现了一些东西。据说,如果我以管理员身份运行主流程并在PROCESS_ALL_ACCESS上使用OpenProcess,我就有足够的权利按照说法进行操作。好的,我做到了。但没有任何改变。在读取记忆时,我仍然得到Access is Denied

所以,我一直在寻找并找到另一个启用SeDebugPrivilege的东西。我也这样做但没有改变。我仍然得到错误。

我已经在这里阅读了这个任务和他的答案; Windows Vista/Win7 Privilege Problem: SeDebugPrivilege & OpenProcess。 但正如我所说,我对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")))

这是我一直得到的错误;

AssertionError: ReadMemory Failed with success == 0 and address == 131072 and size == 4096.
[Error 5] Access is denied.

我不知道有关我的代码和个人Windows 7操作系统的其他信息,我应该提供给您。如果您需要了解更多,请向我询问,我会提供它来解决这个问题。

我想,这是关于我的操作系统缺乏配置,而不是pywin32。我等着你的解决方案。

0 个答案:

没有答案