#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, ...
определенно неправильный, как я уже писал.