| ... | @@ -1514,6 +1514,23 @@ pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, l | ... | @@ -1514,6 +1514,23 @@ pub fn VirtualProtect(lpAddress: ?LPVOID, dwSize: SIZE_T, flNewProtect: DWORD, l |
| 1514 | } | 1514 | } |
| 1515 | } | 1515 | } |
| 1516 | | 1516 | |
| | 1517 | pub fn VirtualProtectEx(handle: HANDLE, addr: ?LPVOID, size: usize, new_prot: DWORD, old_prot: ?*DWORD) VirtualProtectError!void { |
| | 1518 | var out_addr = addr; |
| | 1519 | var out_size = size; |
| | 1520 | switch (ntdll.NtProtectVirtualMemory( |
| | 1521 | handle, |
| | 1522 | &out_addr, |
| | 1523 | &out_size, |
| | 1524 | new_prot, |
| | 1525 | old_prot, |
| | 1526 | )) { |
| | 1527 | .SUCCESS => {}, |
| | 1528 | .INVALID_ADDRESS => return error.InvalidAddress, |
| | 1529 | // TODO: map errors |
| | 1530 | else => |rc| return std.os.windows.unexpectedStatus(rc), |
| | 1531 | } |
| | 1532 | } |
| | 1533 | |
| 1517 | pub const VirtualQueryError = error{Unexpected}; | 1534 | pub const VirtualQueryError = error{Unexpected}; |
| 1518 | | 1535 | |
| 1519 | pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T { | 1536 | pub fn VirtualQuery(lpAddress: ?LPVOID, lpBuffer: PMEMORY_BASIC_INFORMATION, dwLength: SIZE_T) VirtualQueryError!SIZE_T { |
| ... | @@ -4457,3 +4474,184 @@ pub const MODULEENTRY32 = extern struct { | ... | @@ -4457,3 +4474,184 @@ pub const MODULEENTRY32 = extern struct { |
| 4457 | szModule: [MAX_MODULE_NAME32 + 1]CHAR, | 4474 | szModule: [MAX_MODULE_NAME32 + 1]CHAR, |
| 4458 | szExePath: [MAX_PATH]CHAR, | 4475 | szExePath: [MAX_PATH]CHAR, |
| 4459 | }; | 4476 | }; |
| | 4477 | |
| | 4478 | pub const THREADINFOCLASS = enum(c_int) { |
| | 4479 | ThreadBasicInformation, |
| | 4480 | ThreadTimes, |
| | 4481 | ThreadPriority, |
| | 4482 | ThreadBasePriority, |
| | 4483 | ThreadAffinityMask, |
| | 4484 | ThreadImpersonationToken, |
| | 4485 | ThreadDescriptorTableEntry, |
| | 4486 | ThreadEnableAlignmentFaultFixup, |
| | 4487 | ThreadEventPair_Reusable, |
| | 4488 | ThreadQuerySetWin32StartAddress, |
| | 4489 | ThreadZeroTlsCell, |
| | 4490 | ThreadPerformanceCount, |
| | 4491 | ThreadAmILastThread, |
| | 4492 | ThreadIdealProcessor, |
| | 4493 | ThreadPriorityBoost, |
| | 4494 | ThreadSetTlsArrayAddress, |
| | 4495 | ThreadIsIoPending, |
| | 4496 | // Windows 2000+ from here |
| | 4497 | ThreadHideFromDebugger, |
| | 4498 | // Windows XP+ from here |
| | 4499 | ThreadBreakOnTermination, |
| | 4500 | ThreadSwitchLegacyState, |
| | 4501 | ThreadIsTerminated, |
| | 4502 | // Windows Vista+ from here |
| | 4503 | ThreadLastSystemCall, |
| | 4504 | ThreadIoPriority, |
| | 4505 | ThreadCycleTime, |
| | 4506 | ThreadPagePriority, |
| | 4507 | ThreadActualBasePriority, |
| | 4508 | ThreadTebInformation, |
| | 4509 | ThreadCSwitchMon, |
| | 4510 | // Windows 7+ from here |
| | 4511 | ThreadCSwitchPmu, |
| | 4512 | ThreadWow64Context, |
| | 4513 | ThreadGroupInformation, |
| | 4514 | ThreadUmsInformation, |
| | 4515 | ThreadCounterProfiling, |
| | 4516 | ThreadIdealProcessorEx, |
| | 4517 | // Windows 8+ from here |
| | 4518 | ThreadCpuAccountingInformation, |
| | 4519 | // Windows 8.1+ from here |
| | 4520 | ThreadSuspendCount, |
| | 4521 | // Windows 10+ from here |
| | 4522 | ThreadHeterogeneousCpuPolicy, |
| | 4523 | ThreadContainerId, |
| | 4524 | ThreadNameInformation, |
| | 4525 | ThreadSelectedCpuSets, |
| | 4526 | ThreadSystemThreadInformation, |
| | 4527 | ThreadActualGroupAffinity, |
| | 4528 | }; |
| | 4529 | |
| | 4530 | pub const PROCESSINFOCLASS = enum(c_int) { |
| | 4531 | ProcessBasicInformation, |
| | 4532 | ProcessQuotaLimits, |
| | 4533 | ProcessIoCounters, |
| | 4534 | ProcessVmCounters, |
| | 4535 | ProcessTimes, |
| | 4536 | ProcessBasePriority, |
| | 4537 | ProcessRaisePriority, |
| | 4538 | ProcessDebugPort, |
| | 4539 | ProcessExceptionPort, |
| | 4540 | ProcessAccessToken, |
| | 4541 | ProcessLdtInformation, |
| | 4542 | ProcessLdtSize, |
| | 4543 | ProcessDefaultHardErrorMode, |
| | 4544 | ProcessIoPortHandlers, |
| | 4545 | ProcessPooledUsageAndLimits, |
| | 4546 | ProcessWorkingSetWatch, |
| | 4547 | ProcessUserModeIOPL, |
| | 4548 | ProcessEnableAlignmentFaultFixup, |
| | 4549 | ProcessPriorityClass, |
| | 4550 | ProcessWx86Information, |
| | 4551 | ProcessHandleCount, |
| | 4552 | ProcessAffinityMask, |
| | 4553 | ProcessPriorityBoost, |
| | 4554 | ProcessDeviceMap, |
| | 4555 | ProcessSessionInformation, |
| | 4556 | ProcessForegroundInformation, |
| | 4557 | ProcessWow64Information, |
| | 4558 | ProcessImageFileName, |
| | 4559 | ProcessLUIDDeviceMapsEnabled, |
| | 4560 | ProcessBreakOnTermination, |
| | 4561 | ProcessDebugObjectHandle, |
| | 4562 | ProcessDebugFlags, |
| | 4563 | ProcessHandleTracing, |
| | 4564 | ProcessIoPriority, |
| | 4565 | ProcessExecuteFlags, |
| | 4566 | ProcessTlsInformation, |
| | 4567 | ProcessCookie, |
| | 4568 | ProcessImageInformation, |
| | 4569 | ProcessCycleTime, |
| | 4570 | ProcessPagePriority, |
| | 4571 | ProcessInstrumentationCallback, |
| | 4572 | ProcessThreadStackAllocation, |
| | 4573 | ProcessWorkingSetWatchEx, |
| | 4574 | ProcessImageFileNameWin32, |
| | 4575 | ProcessImageFileMapping, |
| | 4576 | ProcessAffinityUpdateMode, |
| | 4577 | ProcessMemoryAllocationMode, |
| | 4578 | ProcessGroupInformation, |
| | 4579 | ProcessTokenVirtualizationEnabled, |
| | 4580 | ProcessConsoleHostProcess, |
| | 4581 | ProcessWindowInformation, |
| | 4582 | MaxProcessInfoClass, |
| | 4583 | }; |
| | 4584 | |
| | 4585 | pub const PROCESS_BASIC_INFORMATION = extern struct { |
| | 4586 | ExitStatus: NTSTATUS, |
| | 4587 | PebBaseAddress: *PEB, |
| | 4588 | AffinityMask: ULONG_PTR, |
| | 4589 | BasePriority: KPRIORITY, |
| | 4590 | UniqueProcessId: ULONG_PTR, |
| | 4591 | InheritedFromUniqueProcessId: ULONG_PTR, |
| | 4592 | }; |
| | 4593 | |
| | 4594 | pub const ReadMemoryError = error{ |
| | 4595 | Unexpected, |
| | 4596 | }; |
| | 4597 | |
| | 4598 | pub fn ReadProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []u8) ReadMemoryError![]u8 { |
| | 4599 | var nread: usize = 0; |
| | 4600 | switch (ntdll.NtReadVirtualMemory( |
| | 4601 | handle, |
| | 4602 | addr, |
| | 4603 | buffer.ptr, |
| | 4604 | buffer.len, |
| | 4605 | &nread, |
| | 4606 | )) { |
| | 4607 | .SUCCESS => return buffer[0..nread], |
| | 4608 | // TODO: map errors |
| | 4609 | else => |rc| return unexpectedStatus(rc), |
| | 4610 | } |
| | 4611 | } |
| | 4612 | |
| | 4613 | pub const WriteMemoryError = error{ |
| | 4614 | Unexpected, |
| | 4615 | }; |
| | 4616 | |
| | 4617 | pub fn WriteProcessMemory(handle: HANDLE, addr: ?LPVOID, buffer: []const u8) WriteMemoryError!usize { |
| | 4618 | var nwritten: usize = 0; |
| | 4619 | switch (ntdll.NtWriteVirtualMemory( |
| | 4620 | handle, |
| | 4621 | addr, |
| | 4622 | @ptrCast(*const anyopaque, buffer.ptr), |
| | 4623 | buffer.len, |
| | 4624 | &nwritten, |
| | 4625 | )) { |
| | 4626 | .SUCCESS => return nwritten, |
| | 4627 | // TODO: map errors |
| | 4628 | else => |rc| return unexpectedStatus(rc), |
| | 4629 | } |
| | 4630 | } |
| | 4631 | |
| | 4632 | pub const ProcessBaseAddressError = GetProcessMemoryInfoError || ReadMemoryError; |
| | 4633 | |
| | 4634 | /// Returns the base address of the process loaded into memory. |
| | 4635 | pub fn ProcessBaseAddress(handle: HANDLE) ProcessBaseAddressError!HMODULE { |
| | 4636 | var info: PROCESS_BASIC_INFORMATION = undefined; |
| | 4637 | var nread: DWORD = 0; |
| | 4638 | const rc = ntdll.NtQueryInformationProcess( |
| | 4639 | handle, |
| | 4640 | .ProcessBasicInformation, |
| | 4641 | &info, |
| | 4642 | @sizeOf(PROCESS_BASIC_INFORMATION), |
| | 4643 | &nread, |
| | 4644 | ); |
| | 4645 | switch (rc) { |
| | 4646 | .SUCCESS => {}, |
| | 4647 | .ACCESS_DENIED => return error.AccessDenied, |
| | 4648 | .INVALID_HANDLE => return error.InvalidHandle, |
| | 4649 | .INVALID_PARAMETER => unreachable, |
| | 4650 | else => return unexpectedStatus(rc), |
| | 4651 | } |
| | 4652 | |
| | 4653 | var peb_buf: [@sizeOf(PEB)]u8 align(@alignOf(PEB)) = undefined; |
| | 4654 | const peb_out = try ReadProcessMemory(handle, info.PebBaseAddress, &peb_buf); |
| | 4655 | const ppeb = @ptrCast(*const PEB, @alignCast(@alignOf(PEB), peb_out.ptr)); |
| | 4656 | return ppeb.ImageBaseAddress; |
| | 4657 | } |