如何编写Perl、Python或Ruby程序来更改Windows上另一个进程的内存?
我想知道是否可以使用Perl、Python或Ruby编写一个程序,以便它在另一个进程(可能是堆,用于数据和代码数据)的内存中查找0x12345678,然后如果找到,将其更改为0x00000000?它类似于,可以在Windows上执行类似操作。我最初认为这是不可能的,但在看到Brian的评论后,我搜索了CPAN,发现有: 该模块显然使用了以下功能:以下是我的一个尝试:如何编写Perl、Python或Ruby程序来更改Windows上另一个进程的内存?,python,ruby,perl,winapi,readprocessmemory,Python,Ruby,Perl,Winapi,Readprocessmemory,我想知道是否可以使用Perl、Python或Ruby编写一个程序,以便它在另一个进程(可能是堆,用于数据和代码数据)的内存中查找0x12345678,然后如果找到,将其更改为0x00000000?它类似于,可以在Windows上执行类似操作。我最初认为这是不可能的,但在看到Brian的评论后,我搜索了CPAN,发现有: 该模块显然使用了以下功能:以下是我的一个尝试: #!/usr/bin/perl use strict; use warnings; use Win32; use Win32::
#!/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($_[0], 0x20), "\n";
});
sub ErrorReport{
Win32::FormatMessage( Win32::GetLastError() );
}
END { $process->Kill(0) if $process }
输出:
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
有很多方法可以使用进程注入、延迟加载库等来实现这一点 我看不到您使用列出的工具来执行此操作。这是C语言和汇编语言国家,开始让你进入病毒编写领域。一旦你让它工作起来,任何反病毒软件包都会否决它的运行,并尝试隔离它。所以你最好真的想这么做 “权力带来很多……”
祝你好运好吧,有趣的部分是访问另一个进程的内存。CheatEngine通过在虚拟机下运行整个操作系统来实现这一点,虚拟机允许内存保护失效。还有“在调试器下运行”模型,通常意味着以提升的权限作为修改应用程序的子进程启动目标应用程序。有关这方面的很多有趣的东西,请参见
在Perl中,一旦您获得了必要的访问权限,您可能希望使用与之交互。如果您将程序作为调试器附加到进程中,则可以这样做,如果适当的API周围有包装器,在这些语言中应该可以这样做,或者通过ctypes(对于python)之类的东西直接访问windows函数。但是,使用较低级的语言可能更容易,因为在高级语言中,您必须关注如何将高级数据类型转换为低级数据类型等 首先调用要调试的进程,并请求相应的访问权限(您需要是机器上的管理员/具有相当高的权限才能获得访问权限)。然后,您应该能够调用像and这样的函数来读取和写入该进程的内存 [编辑]下面是一个函数的快速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等。可以用列出的语言之一实现整个过程,但编译语言更适合于内存扫描(如果没有其他语言,则考虑速度)。有一个名为SigScan的dll(带有源代码),虽然它是为特定的游戏定制的,但可能会被修改以满足您的需要,只需很少的努力 基于Brian的正确答案,这里有一个使用dll从python中获取地址的快速而肮脏的示例。 当然,这是特定于DLL实现的。 “模块名称”通常是作弊引擎“枚举dll和符号”对话框中显示的dll名称 以Brian的示例为指导,您可以使用自己的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)
为此,我编写了它的基本库。它只在Windows的引擎盖下调用{Read,Write}ProcessMemory
,但它也支持其他平台。例如:
my $mem = Proc::Memory->new(pid => $$);
$mem->poke(0x12345678, 'L') = 12;
那么,这是否意味着如果我运行作弊引擎和第三方应用程序或共享软件,计算机尤其容易受到攻击,因为整个计算机的内存保护已关闭?(共享软件基本上可以修改IE或Firefox进程的代码或数据)不,没有那么糟糕。CheatEngine通过一个扩展的操作集来完成其业务,并使用散列密钥验证对它的访问。因此,它不仅仅是简单地关闭内存保护,它还允许通过一个至少有一些保护的机制绕过它。这不是真的-有适当的权限,可以访问和修改另一个进程内存(这是调试器的工作方式)。如果你已经是管理员,这不是一个安全漏洞。
my $mem = Proc::Memory->new(pid => $$);
$mem->poke(0x12345678, 'L') = 12;