| 167 | } |
| 168 | |
| 169 | bool write_kernel_memory(HANDLE pid, uintptr_t address, void* buffer, SIZE_T size) |
| 170 | { |
| 171 | if (!address || !buffer || !size) |
| 172 | return false; |
| 173 | |
| 174 | NTSTATUS status = STATUS_SUCCESS; |
| 175 | PEPROCESS process; |
| 176 | PsLookupProcessByProcessId((HANDLE)pid, &process); |
| 177 | |
| 178 | KAPC_STATE state; |
| 179 | KeStackAttachProcess((PEPROCESS)process, &state); |
| 180 | |
| 181 | MEMORY_BASIC_INFORMATION info; |
| 182 | |
| 183 | status = ZwQueryVirtualMemory(ZwCurrentProcess(), (PVOID)address, MemoryBasicInformation, &info, sizeof(info), NULL); |
| 184 | if (!NT_SUCCESS(status)) |
| 185 | { |
| 186 | KeUnstackDetachProcess(&state); |
| 187 | return false; |
| 188 | } |
| 189 | |
| 190 | if (((uintptr_t)info.BaseAddress + info.RegionSize) < (address + size)) |
| 191 | { |
| 192 | KeUnstackDetachProcess(&state); |
| 193 | return false; |
| 194 | } |
| 195 | |
| 196 | if (!(info.State & MEM_COMMIT) || (info.Protect & (PAGE_GUARD | PAGE_NOACCESS))) |
| 197 | { |
| 198 | KeUnstackDetachProcess(&state); |
| 199 | return false; |
| 200 | } |
| 201 | |
| 202 | if ((info.Protect & PAGE_EXECUTE_READWRITE) || (info.Protect & PAGE_EXECUTE_WRITECOPY) |
| 203 | || (info.Protect & PAGE_READWRITE) || (info.Protect & PAGE_WRITECOPY)) |
| 204 | { |
| 205 | RtlCopyMemory((void*)address, buffer, size); |
| 206 | } |
| 207 | KeUnstackDetachProcess(&state); |
| 208 | return true; |
| 209 | } |