You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用Win32 API无法在其他进程内存中找到指定字符串,求排查

问题

我正在探索Win32技术,尝试在其他进程的内存中查找变量对应的字符串。启动记事本写入“hello”,或在Python解释器中保存变量后,均无法在其内存转储中找到目标内容。我已编写代码,为当前进程设置seDebugPrivilege权限,调用GetSystemInfo获取进程内存边界与页大小,遍历映射内存页查找“hello”的十六进制值,但始终失败。以下是我的代码:

from pymem.ressources.structure import MEMORY_BASIC_INFORMATION, SYSTEM_INFO
from ctypes import windll, wintypes as w, POINTER, c_size_t
from pymem import Pymem
from ctypes import byref, sizeof, c_ulonglong, create_string_buffer
import win32security, win32api

VIRTUALQUERYEX = windll.kernel32.VirtualQueryEx
VIRTUALQUERYEX.argtypes = w.HANDLE, w.LPCVOID, POINTER(MEMORY_BASIC_INFORMATION), c_size_t
GETSYSTEMINFO = windll.kernel32.GetSystemInfo
READPROCESSMEMORY = windll.kernel32.ReadProcessMemory
READPROCESSMEMORY.argtypes = w.HANDLE, w.LPCVOID, w.LPVOID, c_size_t, POINTER(c_size_t)
READPROCESSMEMORY.restype = w.BOOL

MEM_COMMIT = 0x1000

MEM_IMAGE_TYPE = 0x1000000
MEM_MAPPED_TYPE = 0x40000
MEM_PRIVATE_TYPE = 0x20000


def get_system_info():
    system_info = SYSTEM_INFO()
    GETSYSTEMINFO(byref(system_info))
    return system_info


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

process_handle = Pymem()
process_handle.open_process_from_id(41616)
AdjustPrivilege("seDebugPrivilege")
system_info = get_system_info()
min_addr = system_info.lpMinimumApplicationAddress
max_addr = system_info.lpMaximumApplicationAddress
page_size = system_info.dwPageSize
memory_offset = min_addr
hello = b"\x68\x65\x6C\x6C\x6F"


while memory_offset < max_addr:
    memory_basic_information = MEMORY_BASIC_INFORMATION()
    count = c_ulonglong(0)
    if VIRTUALQUERYEX(
            process_handle.process_handle,
            memory_offset,
            byref(memory_basic_information),
            sizeof(memory_basic_information)
    ) == sizeof(memory_basic_information):
        memory_offset = memory_basic_information.BaseAddress

        memory_commit_region = memory_basic_information.State & MEM_COMMIT
        memory_type_mapped = memory_basic_information.Type & (MEM_MAPPED_TYPE | MEM_IMAGE_TYPE | MEM_PRIVATE_TYPE)
        if memory_commit_region and memory_type_mapped:
            buffer = create_string_buffer(memory_basic_information.RegionSize)
            if READPROCESSMEMORY(
                process_handle.process_handle,
                memory_offset,
                buffer,
                memory_basic_information.RegionSize,
                byref(count)
            ):
                print(hello in buffer.raw)
                if hello in buffer:
                    break
                print(buffer.raw)
            memory_offset += memory_basic_information.RegionSize
        else:
            memory_offset += page_size

请问我哪里操作有误?

分析与修正

1. 权限调整时机错误

你是先打开目标进程,再提权,这会导致打开进程时的权限仍是未提升状态,后续内存读取可能因权限不足失败。正确顺序是先调用AdjustPrivilege提升权限,再打开目标进程。

2. 字符串编码不匹配

记事本默认使用Unicode(UTF-16LE)存储文本,"hello"在内存中的字节序列是b'\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00',而非你搜索的ASCII字节b"\x68\x65\x6C\x6C\x6F"。Python解释器中的字符串同样以Unicode形式存储,需对应搜索宽字符版本的字节序列。

3. 内存偏移更新逻辑错误

当VirtualQueryEx返回一个内存区域后,无论该区域是否符合读取条件,都应直接用memory_basic_information.RegionSize来更新memory_offset,而非在不符合条件时加page_size。因为一个内存区域的大小通常远大于页大小,用页大小偏移会导致重复处理同一区域的起始部分,甚至陷入循环。

4. 缓冲区搜索逻辑不一致

代码中同时使用hello in buffer.raw和hello in buffer:

  • buffer会在遇到第一个\0时截断字符串,无法搜索包含空字节的Unicode字符串;
  • 应统一使用buffer.raw来搜索整个缓冲区的字节内容。

5. ReadProcessMemory读取完整性检查

除了判断ReadProcessMemory的返回值为True,还需验证count.value是否等于请求读取的RegionSize,避免因部分内存不可读导致的搜索遗漏。

修正后的关键代码片段

# 调整顺序:先提权再打开进程
AdjustPrivilege("seDebugPrivilege")
process_handle = Pymem()
process_handle.open_process_from_id(41616)

# 替换为Unicode版本的hello字节序列
hello = b"\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00"

while memory_offset < max_addr:
    memory_basic_information = MEMORY_BASIC_INFORMATION()
    count = c_ulonglong(0)
    if VIRTUALQUERYEX(
            process_handle.process_handle,
            memory_offset,
            byref(memory_basic_information),
            sizeof(memory_basic_information)
    ) == sizeof(memory_basic_information):
        current_region_size = memory_basic_information.RegionSize
        memory_offset = memory_basic_information.BaseAddress

        memory_commit_region = memory_basic_information.State & MEM_COMMIT
        memory_type_valid = (memory_basic_information.Type & (MEM_MAPPED_TYPE | MEM_IMAGE_TYPE | MEM_PRIVATE_TYPE)) != 0
        if memory_commit_region and memory_type_valid:
            buffer = create_string_buffer(current_region_size)
            if READPROCESSMEMORY(
                process_handle.process_handle,
                memory_offset,
                buffer,
                current_region_size,
                byref(count)
            ) and count.value == current_region_size:
                if hello in buffer.raw:
                    print(f"Found target at address: {hex(memory_offset + buffer.raw.find(hello))}")
                    break
        # 无论是否处理,都用区域大小更新偏移
        memory_offset += current_region_size

内容的提问来源于stack exchange,提问作者moti shaku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:16:19