Question: I wonder if Perl, Python, or Ruby can be used to write a program so that it will look for 0x12345678 in the memory of another process (probably the heap, for both data and code data) and then if it is found, change it to 0x00000000? It is something similar to [Cheat Engine](http://www.cheatengine.org/), which can do something like that on Windows.

Answer: 
I initially thought this was not possible but after seeing Brian's comment, I searched CPAN and lo and behold, there is [Win32::Process::Memory](http://search.cpan.org/perldoc/Win32::Process::Memory):

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

```

The module apparently uses the [`ReadProcessMemory`](http://msdn.microsoft.com/en-us/library/ms680553.aspx) function: Here is one of my attempts:

```
#!/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 }

```

Output:

```
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

```
It is possible to do so if you have attached your program as a debugger to the process, which should be possible in those languages if wrappers around the appropriate APIs exist, or by directly accessing the windows functions through something like ctypes (for python). However, it may be easier to do in a more low-level language, since in higher level ones you'll have to be concerned with how to translate highlevel datatypes to lower ones etc.

Start by calling [OpenProcess](http://msdn.microsoft.com/en-us/library/ms684320(VS.85).aspx) on the process to debug, with the appropriate access requested (you'll need to be an Admin on the machine / have fairly high privileges to gain access). You should then be able to call functions like [ReadProcessMemory](http://msdn.microsoft.com/en-us/library/ms680553(VS.85).aspx) and [WriteProcessMemory](http://msdn.microsoft.com/en-us/library/ms681674(VS.85).aspx) to read from and write to that process's memory.

**[Edit]** Here's a quick python proof of concept of a function that successfully reads memory from another process's address space:

```
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)

```

Note that you'll need to determine where in memory to look for things - most of that address space is going to be unmapped, thought there are some standard offsets to look for things like the program code, dlls etc.