Копирование байтов из памяти в массив символов, затем запись байтов в раздел реестра через драйвер C

#c #windows #registry #driver

#c #Windows #реестр #драйвер

Вопрос:

У меня возникла проблема с моим проектом, когда я пытаюсь скопировать структуру из памяти.

Копирование структуры в массив символов и запись байтов из массива символов в раздел реестра типа REG_BINARY

Вот код, который я пока использую RtlCopyMemory для копирования байтов из памяти:

    VOID ReadVirtualMem(ULONG32 address, PVOID buffer, SIZE_T size)
{
    PEPROCESS Process;
    if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)ProcessID, amp;Process)))
    {
        KAPC_STATE  apc_state;
        KeStackAttachProcess(Process, amp;apc_state);

        if (MmIsAddressValid((PVOID)address) amp;amp; MmIsAddressValid((PVOID)(address   size)))
        {
            RtlCopyMemory(buffer, (PVOID)address, size);
        }

        KeUnstackDetachProcess(amp;apc_state);
    }

   
}
  

Приведенный выше код будет принимать несколько параметров, адрес местоположения, из которого мне нужно читать, буфер, он же вывод, в котором необходимо сохранить байты, и количество байтов, которое я хочу скопировать.

Итак, вот как я получаю байты из памяти:

 struct PlayerInformation {
    float Position;
    int Points;
    float Speed;
};

 struct PlayerInformation PlayerInfo;
 ReadVirtualMem(ReadAddress, amp;PlayerInfo, size);
  

Затем я передаю эту информацию в PVOID тип данных, чтобы я мог записать это в раздел реестра следующим образом:

 PVOID Buffer;

memcpy(amp;Buffer, amp;PlayerInfo, sizeof(struct PlayerInfo));

status = WriteToKey(L"\Registry\Machine\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", L"Bytes", REG_BINARY, Buffer, size);


    if (!NT_SUCCESS(status))
        return STATUS_UNSUCCESSFUL;
  

Приведенный выше код отлично работает только для 8 байт. Я считаю, что это связано с тем, что PVOID размер имеет только 8 байт.

Вот мой код для записи в раздел реестра:

 NTSTATUS WriteToKey(PWSTR registry_path, PWSTR value_name, ULONG type, PVOID data, ULONG length)
{

    UNICODE_STRING valname;
    UNICODE_STRING keyname;
    OBJECT_ATTRIBUTES attribs;
    HANDLE handle;
    NTSTATUS rc;
    ULONG resu<

    RtlInitUnicodeString(amp;valname, registry_path);
    RtlInitUnicodeString(amp;keyname, value_name);

    InitializeObjectAttributes(amp;attribs, amp;valname, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

    rc = ZwCreateKey(amp;handle, KEY_ALL_ACCESS, amp;attribs, 0, NULL, REG_OPTION_VOLATILE, amp;result);

    if (!NT_SUCCESS(rc))
        return STATUS_UNSUCCESSFUL;

    rc = ZwSetValueKey(handle, amp;keyname, 0, type, amp;data, length);

    if (!NT_SUCCESS(rc))
        STATUS_UNSUCCESSFUL;

    return STATUS_SUCCESS;
}
  

Мой вопрос в том, как я смогу перенести данные, скопированные из RtlCopyMemory , в структуру, превратить эту структуру в char массив и записать эти данные в путь к ключу реестра.

В c это так просто, как это:

 unsigned char b[sizeof(PlayerInfo)];
    std::cout << "Size of structure: " << sizeof(PlayerInfo) << "nn";
    memcpy(b, amp;PlayerInfo, sizeof(PlayerInfo));

    HKEY handle;
    if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Run", 0, KEY_WRITE, amp;handle) == ERROR_SUCCESS)
    {
        RegSetValueEx(handle, L"Bytes", 0, REG_BINARY, (BYTE*)amp;b, sizeof(b));
  

Но C не имеет типа данных для BYTE *, поэтому я просто немного смущен тем, как я мог бы продолжить использовать эту функцию C , которая работает отлично, и реализовать ее в коде C, чтобы она работала точно так же, как функция C .

Если вам нужны какие-либо другие подробности, я буду более чем рад предоставить вам информацию.

Заранее спасибо!

РЕДАКТИРОВАТЬ: Итак, я отредактировал свою функцию, чтобы принять PlayerInfo struct в качестве аргумента, и теперь все данные считываются правильно.

Вот обновленный код:

 NTSTATUS WriteToBytes(PWSTR registry_path, PWSTR value_name, ULONG type, struct PlayerInfo data, ULONG length)
{

    UNICODE_STRING valname;
    UNICODE_STRING keyname;
    OBJECT_ATTRIBUTES attribs;
    HANDLE handle;
    NTSTATUS rc;
    ULONG resu<

    RtlInitUnicodeString(amp;valname, registry_path);
    RtlInitUnicodeString(amp;keyname, value_name);

    InitializeObjectAttributes(amp;attribs, amp;valname, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

    rc = ZwCreateKey(amp;handle, KEY_ALL_ACCESS, amp;attribs, 0, NULL, REG_OPTION_VOLATILE, amp;result);

    if (!NT_SUCCESS(rc))
        return STATUS_UNSUCCESSFUL;

    rc = ZwSetValueKey(handle, amp;keyname, 0, type, amp;data, length);

    if (!NT_SUCCESS(rc))
        STATUS_UNSUCCESSFUL;

    return STATUS_SUCCESS;
}
  

Это работает хорошо, из того, что я вижу, ошибок нет. кто-нибудь знает, почему это работает? И не передача void* исходной функции ключа записи?

Комментарии:

1. PVOID Buffer; кажется, это неинициализированный указатель, то есть указывающий в никуда. Это не буфер, а указатель, который мог указывать на буфер. memcpy(amp;Buffer,... принимает адрес указателя и изменяет значение указателя, которое может иметь размер 8 байт. Вы, вероятно, хотите что-то вроде PVOID Buffer = (PVOID)amp;PlayerInfo;

2. Ваша функция C не «работает идеально» , как вы надеетесь. В C объекты имеют срок службы. Ваш никогда не запускается. Вам нужно будет узнать о размещении new .

3. @Bodo Я отредактировал функцию и попробовал ваш метод, но это приводит к неверным данным. Я обновил функцию, которая работает. Знаете ли вы, почему обновленная функция работает, а исходная — нет? Проверьте сообщение выше для отредактированной функции.

4. @Ballers «Я пробовал ваш метод, но это приводит к неверным данным» не сообщает, что именно вы пробовали. Не видя кода, который вызывает ваши функции, трудно сказать, что происходит не так. Передача void* также должна работать. Вы могли бы просто передать адрес и размер структуры, не копируя ее в отдельный буфер. Код PVOID Buffer; memcpy(amp;Buffer, ... определенно неправильный, как я уже писал.