我想知道是否可以使用Perl,Python或Ruby来编写程序,以便它在另一个进程的内存中查找0x12345678(可能是堆,对于数据和代码数据)然后如果找到它,将其更改为0x00000000?它与作弊引擎类似,可以在Windows上执行类似的操作。

有帮助吗?

解决方案

我最初认为这是不可能的,但在看到Brian的评论之后,我搜索了CPAN并且看到了,有一个 Win32 :: Process :: Memory

C:\> ppm install Win32::Process::Info
C:\> ppm install Win32::Process::Memory

该模块显然使用 ReadProcessMemory 功能:这是我的一次尝试:

#!/usr/bin/perl
use strict; use warnings;

use Win32;
use Win32::Process;
use Win32::Process::Memory;

my $process;

Win32::Process::Create(
    $process,
    'C:/opt/vim/vim72/gvim.exe',
    q{},
    0,
    NORMAL_PRIORITY_CLASS,
    q{.}
) or die ErrorReport();

my $mem = Win32::Process::Memory->new({
    pid => $process->GetProcessID(),
    access => 'read/query',
});

$mem->search_sub( 'VIM', sub {
    print $mem->hexdump(

我最初认为这是不可能的,但在看到Brian的评论之后,我搜索了CPAN并且看到了,有一个 Win32 :: Process :: Memory

C:\> ppm install Win32::Process::Info
C:\> ppm install Win32::Process::Memory

该模块显然使用 ReadProcessMemory 功能:这是我的一次尝试:

C:\Temp> proc
0052A580 : 56 49 4D 20 2D 20 56 69 20 49 4D 70 72 6F 76 65 : VIM - Vi IMprove
0052A590 : 64 20 37 2E 32 20 28 32 30 30 38 20 41 75 67 20 : d 7.2 (2008 Aug

0052A5F0 :       56 49 4D 52 55 4E 54 49 4D 45 3A 20 22 00 :   VIMRUNTIME: ".
0052A600 : 20 20 66 61 6C 6C 2D 62 61 63 6B 20 66 6F 72 20 :   fall-back for
0052A610 : 24 56                                           : $V

输出:

<*>[0], 0x20), "\n"; }); sub ErrorReport{ Win32::FormatMessage( Win32::GetLastError() ); } END { $process->Kill(0) if $process }

输出:

<*>

其他提示

如果您已将程序作为调试程序附加到进程,则可以执行此操作,如果存在相应API的包装,则应该可以使用这些语言,或者通过类似ctypes的方式直接访问Windows函数(对于蟒蛇)。但是,使用更低级别的语言可能更容易,因为在更高级别的语言中,您必须关注如何将高级数据类型转换为较低级别的数据类型等。

首先致电 OpenProcess 调试,请求相应的访问权限(您需要成为计算机上的管理员/具有相当高的权限才能获得访问权限)。然后,您应该能够调用 ReadProcessMemory 等功能。并 WriteProcessMemory 来读取和写入该流程存储器中。

[编辑] 这是一个快速python概念证明一个函数的概念,它成功地从另一个进程的地址空间读取内存:

import ctypes
import ctypes.wintypes
kernel32 = ctypes.wintypes.windll.kernel32

# Various access flag definitions:
class Access:
    DELETE      = 0x00010000
    READ_CONTROL= 0x00020000
    SYNCHRONIZE = 0x00100000
    WRITE_DAC   = 0x00040000
    WRITE_OWNER = 0x00080000
    PROCESS_VM_WRITE = 0x0020
    PROCESS_VM_READ = 0x0010
    PROCESS_VM_OPERATION = 0x0008
    PROCESS_TERMINATE = 0x0001
    PROCESS_SUSPEND_RESUME = 0x0800
    PROCESS_SET_QUOTA = 0x0100
    PROCESS_SET_INFORMATION = 0x0200
    PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
    PROCESS_QUERY_INFORMATION = 0x0400
    PROCESS_DUP_HANDLE = 0x0040
    PROCESS_CREATE_THREAD = 0x0002
    PROCESS_CREATE_PROCESS = 0x0080

def read_process_mem(pid, address, size):
    """Read memory of the specified process ID."""
    buf = ctypes.create_string_buffer(size)
    gotBytes = ctypes.c_ulong(0)
    h = kernel32.OpenProcess(Access.PROCESS_VM_READ, False, pid)
    try:
        if kernel32.ReadProcessMemory(h, address, buf, size, ctypes.byref(gotBytes)):
            return buf
        else:
            # TODO: report appropriate error GetLastError
            raise Exception("Failed to access process memory.")
    finally:
        kernel32.CloseHandle(h)

请注意,您需要确定在内存中查找内容的位置 - 大多数地址空间都将取消映射,以为有一些标准偏移可用于查找程序代码,dll等内容。

嗯,有趣的部分是访问其他进程的内存。 CheatEngine通过在虚拟机下运行整个操作系统来实现这一点,该虚拟机可以防止内存保护。还有“在调试器下运行”模型,通常意味着将目标应用程序作为修改应用程序的子进程启动,并提升权限。有关很多有趣的内容,请参阅 Win32 API 关于那个。

在Perl中,一旦你获得了必要的访问权限,你可能想要使用 Win32 :: Security :: Raw

使用Process injection,延迟加载库等方法可以做到这一点。

我没有看到你从你列出的工具中做到这一点。这是C和汇编国家,并开始让你进入病毒编写领域。一旦你开始工作,任何反病毒软件包都会否决它运行并尝试隔离它。所以你最好真的想要这样做。

“随着权力的增加......”

祝你好运

可以用列出的一种语言实现整个过程,但编译语言更适合内存扫描(如果没有别的话,速度考虑因素)。有一个名为SigScan的dll(带有源代码),虽然可以针对特定游戏量身定制,但可以通过最小的努力进行修改以满足您的需求。

在Brian的正确答案的基础上,这是一个使用dll从python中获取地址的快速而肮脏的例子。 当然,这是特定于DLL的实现。 “模块名称”通常是在Cheat Engines“Enumerate DLLs and Symbols”中显示的dll名称。对话框。

以Brian的例子作为指导, MSDN 您可以使用自己的WriteProcessMemory方法轻松扩展它。

import win32defines
import win32process
import win32gui
from ctypes import *
SigScan = cdll.SigScan
kernel32 = windll.kernel32
addresses = {"Value1" : {"sigArg1" : "b0015ec390518b4c24088d4424005068", 
                          "sigArg2" : 36, 
                          "address" : None,
                          "size"    : 32
                         },
            "Value2" :{"sigArg1" : "3b05XXXXXXXX741285c0",
                          "sigArg2" : None, 
                          "address" : None,
                          "size"    : 32
                        }
        }

def read_process_mem(pid, address, size):
    """Read memory of the specified process ID."""
    buf = create_string_buffer(size)
    gotBytes = c_ulong(0)
    h = kernel32.OpenProcess(win32defines.PROCESS_VM_READ, False, pid)
    try:
        if kernel32.ReadProcessMemory(h, address, buf, size, byref(gotBytes)):
            return buf
        else:
            # TODO: report appropriate error GetLastError
            raise Exception("Failed to access process memory.")
    finally:
        kernel32.CloseHandle(h)
if __name__ == "__main__":
    pid, id = None, None
    ## HWND 
    hwnd = win32gui.FindWindowEx(0, 0, 0, "Window Name here")
    ## pid
    pid = win32process.GetWindowThreadProcessId(hwnd)[-1]
    ## Initialize the sigscan dll
    SigScan.InitializeSigScan(pid, "Module Name")
    ## Find all the addresses registered
    for key in addresses.keys():
        addresses[key]["address"] = SigScan.SigScan(addresses[key]["sigArg1"],
            addresses[key]["sigArg2"])
    ## Allow the scanner to clean up
    SigScan.FinalizeSigScan()
    for key in addresses.keys():
        if addresses[key]["address"] != None:
            print repr(read_process_mem(pid, addresses[key]["address"],
                            addresses[key]["size"]).raw)

我写了 Proc :: Memory 及其底层库 libvas 用于此目的。它只是在Windows下调用 {Read,Write} ProcessMemory ,但它也支持其他平台。例如:

my $mem = Proc::Memory->new(pid => $); 
$mem->poke(0x12345678, 'L') = 12;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top