Java читает память другого процесса с помощью JNA

Я пытаюсь прочитать часть из памяти экземпляра Блокнота, но всегда получаю системную ошибку 299 при вызове ReadProcessMemory() ядра kernel32.

Это код, который у меня есть до сих пор:

package memreadtest;

import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinNT.HANDLE;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APIOptions;

public class MemReader {

    private final static Kernel32 kernel32 = Native.load("kernel32", Kernel32.class, W32APIOptions.DEFAULT_OPTIONS);
    private final static User32 user32 = Native.load("user32", User32.class, W32APIOptions.DEFAULT_OPTIONS);

    private final static int PROCESS_VM_READ = 0x0010;

    public static void main(String[] args) {
        int bytesToRead = 1024;

        Memory notepadDump = readProcessMemory("*Untitled - Notepad", bytesToRead);

        Memory.disposeAll();
    }

    private static Memory readProcessMemory(String winTitle, int bytesToRead) {
        Memory output = new Memory(bytesToRead);

        IntByReference pid = new IntByReference(0);

        user32.GetWindowThreadProcessId(user32.FindWindow(null, winTitle), pid);

        HANDLE handle = kernel32.OpenProcess(PROCESS_VM_READ, true, pid.getValue());

        if (!kernel32.ReadProcessMemory(handle, handle.getPointer(), output, bytesToRead, null)) {
            System.err.println("Failed to read memory of process " + pid.getValue() + ". System Error Code: " + kernel32.GetLastError());
            return null;
        }

        return output;
    }
}

Что я делаю не так?


person sasieightynine    schedule 26.12.2019    source источник
comment
handle.getPointer() в качестве второго аргумента ReadProcessMemory конечно неправильно. Я пытаюсь прочитать часть из памяти - какая конкретная часть? что вы пытаетесь прочитать?   -  person RbMm    schedule 26.12.2019
comment
Первые 1024 байта памяти, занятые процессом.   -  person sasieightynine    schedule 26.12.2019
comment
поэтому диапазон [0, 1024) ? этот диапазон всегда является недопустимой памятью (неотображенной), и какой смысл пытаться это сделать? и в любом случае я не вижу попытки чтения по адресу 0. я просматриваю адрес - handle.getPointer() - что это?   -  person RbMm    schedule 26.12.2019
comment
Конечная цель — прочитать всю память, занятую блокнотом или любым другим выбранным приложением, а затем обработать данные в виде массива байтов. Я просто подумал, что для начала было бы проще прочитать только первые x байтов.   -  person sasieightynine    schedule 26.12.2019
comment
нет смысла читать всю память. в любом случае вам нужно сначала вызвать VirtualQueryEx для получения действительных диапазонов памяти в процессе (с его типом, размером) и только после этого что-то читать.   -  person RbMm    schedule 26.12.2019
comment
Возвращаемые данные VirtualQueryEx не имеют смысла, если целевой процесс не приостановлен.   -  person IInspectable    schedule 26.12.2019
comment
Память, отображаемая процессом, не обязательно является непрерывной. Что вы на самом деле пытаетесь сделать? Но в любом случае, на вопрос, который вы задали, был дан ответ.   -  person David Heffernan    schedule 26.12.2019
comment
@IInspectable - если целевой процесс не приостановлен false. не нужно приостанавливать процесс. конечно, в любой момент можно выделить или освободить новую виртуальную память. и что ? даже если процесс приостановлен - другой процесс все еще может выделить или освободить память в целевом процессе. и что ?   -  person RbMm    schedule 26.12.2019
comment
@rbm: Правильность - это не то, о чем вам нужно беспокоиться. Для остальных из нас важна правильность. И если важна правильность, вы не можете вызывать VirtualQueryEx для процесса, который не приостановлен.   -  person IInspectable    schedule 26.12.2019
comment
@IInspectable - можно. и очень странно, что вы забыли написать, что вы не можете вызвать ReadProcessMemory для процесса, который не приостановлен   -  person RbMm    schedule 26.12.2019


Ответы (1)


Вы читаете адрес, который не является допустимым во внешнем процессе. Дескриптор процесса не должен быть допустимым адресом в процессе.

Я не уверен, что вы пытаетесь прочитать из этого процесса, но что бы это ни было, вам нужно как-то найти соответствующий адрес.

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

person David Heffernan    schedule 26.12.2019