1

Тема: AHK: Доступ к памяти других процессов

Каждый 32-разрядный процесс имеет своё, независимое от других процессов, адресное пространство памяти, простирающееся от 0 до 0xFFFFFFFF. Это означает, что в любом процессе есть, например, адрес 0x7C800000, но у разных процессов ему будут соответствовать разные ячейки физической памяти. А у некоторых не будет соответствовать ничего, если память под этот адрес процессу не выделялась.

Отсюда необходимость дополнительных телодвижений, продемонстрированных в нижеследующем примере. Этот скрипт читает число из памяти Блокнота. Адрес взят чисто для примера - как показывает Process Explorer, по этому адресу загружается библиотека kernel32.dll.

#NoEnv

ProcessName = notepad.exe         ; Имя процесса.
ReadAddress = 0x7C800000          ; Адрес, откуда читать.
ReadSize = 4                      ; Сколько байт читать.
VarSetCapacity(Buf, ReadSize, 0)  ; Буфер, куда считывать.

PROCESS_VM_READ = 0x10            ; Права на процесс.

Process, Exist, %ProcessName%     ; Поиск процесса.

If(!ErrorLevel) {
  MsgBox, Процесс не найден.
  ExitApp
}

PID := ErrorLevel                 ; Идентификатор процесса будет в ErrorLevel.

hProcess := DllCall("OpenProcess", UInt, PROCESS_VM_READ
                                 , Int, False
                                 , UInt, PID)
If(!hProcess) {
  MsgBox, Не удалось открыть процесс.
  ExitApp
}

Ret := DllCall("ReadProcessMemory", UInt, hProcess
                                  , UInt, ReadAddress
                                  , UInt, &Buf
                                  , UInt, ReadSize
                                  , UInt, 0)

DllCall("CloseHandle", UInt, hProcess) ; Освобождение хэндла процесса.

If(!Ret) {
  MsgBox, Не удалось прочитать.
  ExitApp
}

Result := NumGet(Buf, 0, "UInt")  ; Считывание из буфера в переменную.

MsgBox, %Result%

2

Re: AHK: Доступ к памяти других процессов

Пример записи данных в память другого процесса. В данном случае записывается одно четырёхбайтное число. Если запись не удаётся, причиной может быть то, что под этот адрес память процессу не выделялась.

#NoEnv

ProcessName = program.exe         ; Имя процесса.
Address = 0x0042E1CE              ; Адрес, куда писать.
Data = 215125125                  ; Что писать.
Size = 4                          ; Сколько байт писать.

VarSetCapacity(Buf, Size, 0)      ; Буфер, для записываемых данных.

NumPut(Data, Buf, 0, "UInt")      ; Данные - в буфер.

PROCESS_VM_WRITE = 0x20           ; Права на процесс.
PROCESS_VM_OPERATION = 0x8

Process, Exist, %ProcessName%     ; Поиск процесса.

If(!ErrorLevel) {
  MsgBox, Процесс не найден.
  ExitApp
}

PID := ErrorLevel                 ; Идентификатор процесса будет в ErrorLevel.

hProcess := DllCall("OpenProcess", "UInt", PROCESS_VM_WRITE | PROCESS_VM_OPERATION
                                 , "Int",  False
                                 , "UInt", PID)
If(!hProcess) {
  MsgBox, Не удалось открыть процесс.
  ExitApp
}

Ret := DllCall("WriteProcessMemory", "UInt", hProcess
                                   , "UInt", Address
                                   , "UInt", &Buf
                                   , "UInt", Size
                                   , "UInt", 0)

DllCall("CloseHandle", "UInt", hProcess) ; Освобождение хэндла процесса.

If(!Ret) {
  MsgBox, Не удалось записать.
  ExitApp
}

MsgBox, Готово.