├── .gitignore ├── .github └── FUNDING.yml ├── go.mod ├── handle.go ├── ntdll.go ├── handle_generated.go ├── unicode_string_generated.go ├── misc.go ├── misc_generated.go ├── io_generated.go ├── thread.go ├── io.go ├── rtl.go ├── thread_generated.go ├── rtl_generated.go ├── examples ├── lsmod │ └── lsmod.go ├── lsobj │ └── lsobj.go └── ls-proc-vm │ └── ls-proc-vm.go ├── lsa.go ├── LICENSE ├── ntstatus.go ├── security.go ├── atom.go ├── util.go ├── unicode_string.go ├── lsa_generated.go ├── security_generated.go ├── section.go ├── README.md ├── atom_generated.go ├── statuscrawler.go ├── section_generated.go ├── memory_generated.go ├── object_generated.go ├── process.go ├── object.go ├── registry.go ├── systeminformation.go ├── memory.go ├── token.go ├── systeminformation_generated.go ├── token_generated.go ├── process_generated.go └── mkcode.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: hillu 2 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/hillu/go-ntdll 2 | 3 | go 1.11 4 | 5 | require github.com/PuerkitoBio/goquery v1.7.1 // indirect 6 | -------------------------------------------------------------------------------- /handle.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS WINAPI NtClose( 9 | _In_ HANDLE Handle 10 | ); 11 | */ 12 | -------------------------------------------------------------------------------- /ntdll.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | import "syscall" 4 | 5 | var modntdll = syscall.NewLazyDLL("ntdll") 6 | 7 | type Handle syscall.Handle 8 | 9 | func fromBool(b bool) (r uintptr) { 10 | if b { 11 | r = 1 12 | } 13 | return 14 | } 15 | -------------------------------------------------------------------------------- /handle_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- handle.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | var ( 7 | procNtClose = modntdll.NewProc("NtClose") 8 | ) 9 | 10 | func NtClose( 11 | Handle Handle, 12 | ) NtStatus { 13 | r0, _, _ := procNtClose.Call(uintptr(Handle)) 14 | return NtStatus(r0) 15 | } 16 | -------------------------------------------------------------------------------- /unicode_string_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- unicode_string.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | // UnicodeString has been derived from the UNICODE_STRING struct definition. 7 | type UnicodeString struct { 8 | Length uint16 9 | MaximumLength uint16 10 | Buffer *uint16 11 | } 12 | -------------------------------------------------------------------------------- /misc.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | type: 8 | typedef struct _GUID { 9 | DWORD Data1; 10 | WORD Data2; 11 | WORD Data3; 12 | BYTE Data4[8]; 13 | } GUID; 14 | */ 15 | 16 | // type Uuid Guid 17 | 18 | /* 19 | type: 20 | typedef struct _LIST_ENTRY { 21 | PLIST_ENTRY Flink; 22 | PLIST_ENTRY Blink; 23 | } LIST_ENTRY,*PLIST_ENTRY; 24 | */ 25 | -------------------------------------------------------------------------------- /misc_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- misc.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | // Guid has been derived from the GUID struct definition. 7 | type Guid struct { 8 | Data1 uint32 9 | Data2 uint16 10 | Data3 uint16 11 | Data4 [8]byte 12 | } 13 | 14 | // ListEntry has been derived from the LIST_ENTRY struct definition. 15 | type ListEntry struct { 16 | Flink *ListEntry 17 | Blink *ListEntry 18 | } 19 | -------------------------------------------------------------------------------- /io_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- io.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | // The IoPriorityHint constants have been derived from the IO_PRIORITY_HINT enum definition. 7 | type IoPriorityHint uint32 8 | 9 | const ( 10 | IoPriorityVeryLow IoPriorityHint = 0 11 | IoPriorityLow = 1 12 | IoPriorityNormal = 2 13 | IoPriorityHigh = 3 14 | IoPriorityCritical = 4 15 | MaxIoPriorityTypes = 5 16 | ) 17 | -------------------------------------------------------------------------------- /thread.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS NtCreateThreadEx( 9 | _Out_ PHANDLE hThread, 10 | _In_ ACCESS_MASK DesiredAccess, 11 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 12 | _In_ HANDLE ProcessHandle, 13 | _In_ HANDLE lpStartAddress, 14 | _In_ PVOID lpParameter, 15 | _In_ BOOLEAN CreateSuspended, 16 | _In_ DWORD StackZeroBits, 17 | _In_ DWORD SizeOfStackCommit, 18 | _In_ DWORD SizeOfStackReserve, 19 | _Out_ HANDLE ThreadInfo 20 | ); 21 | */ 22 | -------------------------------------------------------------------------------- /io.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | typedef struct _IO_STATUS_BLOCK { 8 | union { 9 | NTSTATUS Status; 10 | PVOID Pointer; 11 | }; 12 | ULONG_PTR Information; 13 | } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; 14 | */ 15 | 16 | type IoStatusBlock struct { 17 | StatusPointer uintptr 18 | Information uintptr 19 | } 20 | 21 | /* 22 | typedef VOID (NTAPI *PIO_APC_ROUTINE)(PVOID ApcContext,PIO_STATUS_BLOCK IoStatusBlock,ULONG Reserved); 23 | */ 24 | 25 | type IoApcRoutine uintptr 26 | 27 | /* 28 | enum: 29 | typedef enum _IO_PRIORITY_HINT { 30 | IoPriorityVeryLow = 0, 31 | IoPriorityLow = 1, 32 | IoPriorityNormal = 2, 33 | IoPriorityHigh = 3, 34 | IoPriorityCritical = 4, 35 | MaxIoPriorityTypes = 5 36 | } IO_PRIORITY_HINT; 37 | */ 38 | -------------------------------------------------------------------------------- /rtl.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | // https://github.com/mirror/processhacker/blob/master/2.x/trunk/phlib/include/ntrtl.hL2994 7 | 8 | /* 9 | func: 10 | BOOLEAN 11 | RtlDosPathNameToNtPathName_U( 12 | _In_ PWSTR DosFileName, 13 | _Out_ PUNICODE_STRING NtFileName, 14 | _Out_opt_ PWSTR *FilePart, 15 | _Out_opt_ PRTL_RELATIVE_NAME_U RelativeName 16 | ); 17 | */ 18 | 19 | // https://github.com/mirror/processhacker/blob/master/2.x/trunk/phlib/include/ntrtl.h#L2896 20 | 21 | /* 22 | type: 23 | typedef struct _RTL_RELATIVE_NAME_U 24 | { 25 | UNICODE_STRING RelativeName; 26 | HANDLE ContainingDirectory; 27 | PRTLP_CURDIR_REF CurDirRef; 28 | } RTL_RELATIVE_NAME_U, *PRTL_RELATIVE_NAME_U; 29 | */ 30 | 31 | // https://github.com/mirror/reactos/blob/master/reactos/include/ndk/rtltypes.h#L1220 32 | 33 | /* 34 | type: 35 | typedef struct _RTLP_CURDIR_REF 36 | { 37 | LONG RefCount; 38 | HANDLE Handle; 39 | } RTLP_CURDIR_REF, *PRTLP_CURDIR_REF; 40 | */ 41 | -------------------------------------------------------------------------------- /thread_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- thread.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | 8 | var ( 9 | procNtCreateThreadEx = modntdll.NewProc("NtCreateThreadEx") 10 | ) 11 | 12 | // OUT-parameter: hThread, ThreadInfo. 13 | func NtCreateThreadEx( 14 | hThread *Handle, 15 | DesiredAccess AccessMask, 16 | ObjectAttributes *ObjectAttributes, 17 | ProcessHandle Handle, 18 | lpStartAddress Handle, 19 | lpParameter *byte, 20 | CreateSuspended bool, 21 | StackZeroBits uint32, 22 | SizeOfStackCommit uint32, 23 | SizeOfStackReserve uint32, 24 | ThreadInfo Handle, 25 | ) NtStatus { 26 | r0, _, _ := procNtCreateThreadEx.Call(uintptr(unsafe.Pointer(hThread)), 27 | uintptr(DesiredAccess), 28 | uintptr(unsafe.Pointer(ObjectAttributes)), 29 | uintptr(ProcessHandle), 30 | uintptr(lpStartAddress), 31 | uintptr(unsafe.Pointer(lpParameter)), 32 | fromBool(CreateSuspended), 33 | uintptr(StackZeroBits), 34 | uintptr(SizeOfStackCommit), 35 | uintptr(SizeOfStackReserve), 36 | uintptr(ThreadInfo)) 37 | return NtStatus(r0) 38 | } 39 | -------------------------------------------------------------------------------- /rtl_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- rtl.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | 8 | var ( 9 | procRtlDosPathNameToNtPathName_U = modntdll.NewProc("RtlDosPathNameToNtPathName_U") 10 | ) 11 | 12 | // RtlRelativeNameU has been derived from the RTL_RELATIVE_NAME_U struct definition. 13 | type RtlRelativeNameU struct { 14 | RelativeName UnicodeString 15 | ContainingDirectory Handle 16 | CurDirRef *RtlpCurdirRef 17 | } 18 | 19 | // RtlpCurdirRef has been derived from the RTLP_CURDIR_REF struct definition. 20 | type RtlpCurdirRef struct { 21 | RefCount int32 22 | Handle Handle 23 | } 24 | 25 | // OUT-parameter: NtFileName, FilePart, RelativeName. 26 | // *OPT-parameter: FilePart, RelativeName. 27 | func RtlDosPathNameToNtPathName_U( 28 | DosFileName *uint16, 29 | NtFileName *UnicodeString, 30 | FilePart *uint16, 31 | RelativeName *RtlRelativeNameU, 32 | ) bool { 33 | r0, _, _ := procRtlDosPathNameToNtPathName_U.Call(uintptr(unsafe.Pointer(DosFileName)), 34 | uintptr(unsafe.Pointer(NtFileName)), 35 | uintptr(unsafe.Pointer(FilePart)), 36 | uintptr(unsafe.Pointer(RelativeName))) 37 | return r0 != 0 38 | } 39 | -------------------------------------------------------------------------------- /examples/lsmod/lsmod.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/hillu/go-ntdll" 5 | 6 | "bytes" 7 | "fmt" 8 | "os" 9 | "unsafe" 10 | ) 11 | 12 | func main() { 13 | buf := make([]byte, 1024) 14 | var rlen uint32 15 | if st := ntdll.CallWithExpandingBuffer(func() ntdll.NtStatus { 16 | return ntdll.NtQuerySystemInformation( 17 | ntdll.SystemModuleInformation, 18 | &buf[0], 19 | uint32(len(buf)), 20 | &rlen, 21 | ) 22 | }, &buf, &rlen); st.IsError() { 23 | fmt.Fprintf(os.Stderr, "NtQuerySystemInformation: %s, len=%d", st.Error(), rlen) 24 | os.Exit(1) 25 | } 26 | mi := (*ntdll.SystemModuleInformationT)(unsafe.Pointer(&buf[0])) 27 | fmt.Println("idx map_base img_base img_size flags load init cnt name") 28 | fmt.Println("--- -------- ---------------- -------- -------- ---- ---- ---- ----") 29 | for i, module := range mi.GetModules() { 30 | nlen := bytes.Index(module.Name[:], []byte{0}) 31 | name := string(module.Name[:nlen]) 32 | fmt.Printf("%3d %08x %016x %08x %08x %04x %04x %04x %s\n", i, 33 | module.MappedBase, module.ImageBase, module.ImageSize, 34 | module.Flags, 35 | module.LoadOrderIndex, module.InitOrderIndex, module.LoadCount, 36 | name) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lsa.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS LsaOpenPolicy( 9 | _In_ PLSA_UNICODE_STRING SystemName, 10 | _In_ PLSA_OBJECT_ATTRIBUTES ObjectAttributes, 11 | _In_ ACCESS_MASK DesiredAccess, 12 | _Inout_ PLSA_HANDLE PolicyHandle 13 | ); 14 | */ 15 | 16 | /* 17 | func: 18 | NTSTATUS LsaAddAccountRights( 19 | _In_ LSA_HANDLE PolicyHandle, 20 | _In_ PSID AccountSid, 21 | _In_ PLSA_UNICODE_STRING UserRights, 22 | _In_ ULONG CountOfRights 23 | ); 24 | */ 25 | 26 | /* 27 | func: 28 | NTSTATUS LsaEnumerateAccountRights( 29 | _In_ LSA_HANDLE PolicyHandle, 30 | _In_ PSID AccountSid, 31 | _Out_ PLSA_UNICODE_STRING *UserRights, 32 | _Out_ PULONG CountOfRights 33 | ); 34 | */ 35 | 36 | /* 37 | func: 38 | NTSTATUS LsaRemoveAccountRights( 39 | _In_ LSA_HANDLE PolicyHandle, 40 | _In_ PSID AccountSid, 41 | _In_ BOOLEAN AllRights, 42 | _In_ PLSA_UNICODE_STRING UserRights, 43 | _In_ ULONG CountOfRights 44 | ); 45 | */ 46 | 47 | /* 48 | func: 49 | NTSTATUS LsaClose( 50 | _In_ LSA_HANDLE ObjectHandle 51 | ); 52 | */ 53 | 54 | type LsaUnicodeString UnicodeString 55 | type LsaHandle Handle 56 | type LsaObjectAttributes ObjectAttributes 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2016-2021 Hilko Bengen 2 | 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /ntstatus.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command statuscrawler go run statuscrawler.go -- 4 | //go:generate statuscrawler 5 | 6 | import ( 7 | "fmt" 8 | ) 9 | 10 | // NTSTATUS is the common return type of all NTDLL functions. 11 | type NtStatus uint32 12 | 13 | // Error() returns a Go error value 14 | func (s NtStatus) Error() error { 15 | if s == 0 { 16 | return nil 17 | } 18 | return fmt.Errorf("NtStatus 0x%08x (%s)", uint32(s), s) 19 | } 20 | 21 | // IsSuccess returns true if the NTSTATUS value indicates that an 22 | // operation was performed successfully 23 | func (s NtStatus) IsSuccess() bool { 24 | return s>>30 == 0 25 | } 26 | 27 | // IsInformational returns true if the NTSTATUS value represents an 28 | // informationel message 29 | func (s NtStatus) IsInofmational() bool { 30 | return s>>30 == 1 31 | } 32 | 33 | // IsWarning returns true if the NTSTATUS value represents a warning 34 | func (s NtStatus) IsWarning() bool { 35 | return s>>30 == 2 36 | } 37 | 38 | // IsErr returns true if the NTSTATUS value represents en error condition 39 | func (s NtStatus) IsError() bool { 40 | return s>>30 == 3 41 | } 42 | 43 | // IsInformational returns the facility encoded into the NTSTATUS value 44 | func (s NtStatus) Facility() uint32 { 45 | return (uint32(s) >> 16) & 0x0fff 46 | } 47 | 48 | // IsInformational returns the error code encoded into the NTSTATUS value 49 | func (s NtStatus) Code() uint32 { 50 | return uint32(s) & 0xffff 51 | } 52 | -------------------------------------------------------------------------------- /security.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS NtQuerySecurityObject( 9 | HANDLE Handle, 10 | SECURITY_INFORMATION SecurityInformation, 11 | PSECURITY_DESCRIPTOR SecurityDescriptor, 12 | ULONG Length, 13 | PULONG LengthNeeded 14 | ); 15 | */ 16 | 17 | /* 18 | func: 19 | NTSTATUS NtSetSecurityObject( 20 | HANDLE Handle, 21 | SECURITY_INFORMATION SecurityInformation, 22 | PSECURITY_DESCRIPTOR SecurityDescriptor 23 | ); 24 | */ 25 | 26 | /* 27 | type: 28 | typedef struct _ACL { 29 | BYTE AclRevision; 30 | BYTE Sbz1; 31 | WORD AclSize; 32 | WORD AceCount; 33 | WORD Sbz2; 34 | } ACL, *PACL; 35 | */ 36 | 37 | /* 38 | type: 39 | typedef struct _SID { 40 | UCHAR Revision; 41 | UCHAR SubAuthorityCount; 42 | SID_IDENTIFIER_AUTHORITY IdentifierAuthority; 43 | ULONG SubAuthority[ANYSIZE_ARRAY]; 44 | } SID, *PISID; 45 | */ 46 | 47 | /* 48 | type: 49 | typedef struct _SID_IDENTIFIER_AUTHORITY { 50 | BYTE Value[6]; 51 | } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 52 | */ 53 | 54 | type SecurityDescriptorControl uint16 55 | 56 | /* 57 | type: 58 | typedef struct _SECURITY_DESCRIPTOR { 59 | UCHAR Revision; 60 | UCHAR Sbz1; 61 | SECURITY_DESCRIPTOR_CONTROL Control; 62 | PSID Owner; 63 | PSID Group; 64 | PACL Sacl; 65 | PACL Dacl; 66 | } SECURITY_DESCRIPTOR, *PISECURITY_DESCRIPTOR; 67 | */ 68 | 69 | type SecurityInformationT uint32 70 | -------------------------------------------------------------------------------- /atom.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | // See http://www.ntinternals.net/: UserMode / NTDLL / Atoms 7 | // 8 | // However, some function definitions (NtAddAtom, NtFindAtom) are 9 | // missing the Length parameter. 10 | 11 | /* 12 | func: 13 | NTSTATUS NtAddAtom( 14 | _In_ PWSTR AtomName, 15 | _In_ ULONG Length, 16 | _Out_ PRTL_ATOM Atom 17 | ); 18 | */ 19 | 20 | /* 21 | func: 22 | NTSTATUS NtDeleteAtom( 23 | _In_ RTL_ATOM Atom 24 | ); 25 | */ 26 | 27 | /* 28 | func: 29 | NTSTATUS NtFindAtom( 30 | _In_ PWCHAR AtomName, 31 | _In_ ULONG Length, 32 | _Out_opt_ PRTL_ATOM Atom); 33 | */ 34 | 35 | /* 36 | func: 37 | NTSTATUS NtQueryInformationAtom( 38 | _In_ RTL_ATOM Atom, 39 | _In_ ATOM_INFORMATION_CLASS AtomInformationClass, 40 | _Out_ PVOID AtomInformation, 41 | _In_ ULONG AtomInformationLength, 42 | _Out_ PULONG ReturnLength 43 | ); 44 | */ 45 | 46 | /* 47 | enum: 48 | typedef enum _ATOM_INFORMATION_CLASS { 49 | AtomBasicInformation, 50 | AtomTableInformation 51 | } ATOM_INFORMATION_CLASS, *PATOM_INFORMATION_CLASS; 52 | */ 53 | 54 | /* 55 | type: 56 | typedef struct _ATOM_BASIC_INFORMATION { 57 | USHORT UsageCount; 58 | USHORT Flags; 59 | USHORT NameLength; 60 | WCHAR Name[1]; 61 | } ATOM_BASIC_INFORMATION, *PATOM_BASIC_INFORMATION; 62 | */ 63 | 64 | /* 65 | type: 66 | typedef struct _ATOM_TABLE_INFORMATION { 67 | ULONG NumberOfAtoms; 68 | RTL_ATOM Atoms[1]; 69 | } ATOM_TABLE_INFORMATION, *PATOM_TABLE_INFORMATION; 70 | */ 71 | 72 | type RtlAtom uint16 73 | -------------------------------------------------------------------------------- /util.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | import ( 4 | "reflect" 5 | "unsafe" 6 | ) 7 | 8 | // CallWithExpandingBuffer is intended to more seamlessly dealing with 9 | // API calls that fill a caller-provided buffer with data. Usually, 10 | // these functions expect the address and current size of the buffer 11 | // and a reference to which the required buffer size will be written. 12 | // 13 | // This function calls fn which encapsulates the actual API call using 14 | // buf and resultLength. If fn returns an NtStatus value that 15 | // indicates an insufficient buffer sizze, the buffer is resized and 16 | // the call is retried. This happens until the call succeeds or fails 17 | // for a non-buffer-related reason. 18 | // 19 | // The size of buf is adjusted according to resultLength. 20 | // 21 | // Example: 22 | /* 23 | var keyName string 24 | var buf []byte 25 | var requiredLength uint32 26 | if st := CallWithExpandingBuffer(func() NtStatus { 27 | return NtQueryKey(h, KeyNameInformation, &buf[0], uint32(len(buf)), &requiredLength) 28 | }, &buf, &requiredLength); st.IsError() { 29 | // handle non buffer-size-related error 30 | } else { 31 | kbi := (*KeyNameInformationT)(unsafe.Pointer(&buf[0])) 32 | keyName = NewUnicodeStringFromBuffer( 33 | (*uint16)(unsafe.Pointer(&kbi.Name)), 34 | int(kbi.NameLength)).String() 35 | } 36 | */ 37 | func CallWithExpandingBuffer(fn func() NtStatus, buf *[]byte, resultLength *uint32) NtStatus { 38 | if len(*buf) == 0 { 39 | *buf = make([]byte, 32, 32) 40 | } 41 | for { 42 | st := fn() 43 | if int(*resultLength) <= cap(*buf) { 44 | (*reflect.SliceHeader)(unsafe.Pointer(buf)).Len = int(*resultLength) 45 | } else { 46 | orig := buf 47 | *buf = make([]byte, int(*resultLength)) 48 | copy(*buf, *orig) 49 | } 50 | if st == STATUS_BUFFER_OVERFLOW || st == STATUS_BUFFER_TOO_SMALL || st == STATUS_INFO_LENGTH_MISMATCH { 51 | continue 52 | } else { 53 | return st 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /unicode_string.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | import ( 4 | "reflect" 5 | "unicode/utf16" 6 | "unsafe" 7 | ) 8 | 9 | //go:generate -command mkcode go run mkcode.go -- 10 | //go:generate mkcode $GOFILE 11 | 12 | /* 13 | type: 14 | typedef struct _UNICODE_STRING { 15 | USHORT Length; 16 | USHORT MaximumLength; 17 | PWSTR Buffer; 18 | } UNICODE_STRING, *PUNICODE_STRING; 19 | */ 20 | 21 | // String converts the UTF-16-encoded string stored in a UnicodeString 22 | // to UTF-8 and returns that as a Go string. 23 | func (u UnicodeString) String() string { 24 | var s []uint16 25 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 26 | hdr.Data = uintptr(unsafe.Pointer(u.Buffer)) 27 | hdr.Len = int(u.Length / 2) 28 | hdr.Cap = int(u.MaximumLength / 2) 29 | return string(utf16.Decode(s)) 30 | } 31 | 32 | // NewUnicodeString converts its argument to UTF-16 and returns a 33 | // pointer to a UnicodeString that can be used with various Windows 34 | // Native API functions. 35 | func NewUnicodeString(s string) *UnicodeString { 36 | buf := utf16.Encode([]rune(s)) 37 | return &UnicodeString{ 38 | Length: uint16(2 * len(buf)), 39 | MaximumLength: uint16(2 * len(buf)), 40 | Buffer: &buf[0], 41 | } 42 | } 43 | 44 | // NewEmptyUnicodeString initializes a UnicodeString for length UTF-16 45 | // characters and returns it. 46 | func NewEmptyUnicodeString(length int) *UnicodeString { 47 | buf := make([]uint16, length, length) 48 | return &UnicodeString{ 49 | Length: 0, 50 | MaximumLength: uint16(2 * length), 51 | Buffer: &buf[0], 52 | } 53 | } 54 | 55 | // NewUnicodeStringFromBuffer initializes a UnicodeString from a 56 | // pointer and a length value as returned by many NTDLL API calls. 57 | func NewUnicodeStringFromBuffer(buffer *uint16, length int) *UnicodeString { 58 | return &UnicodeString{ 59 | Length: uint16(length), 60 | MaximumLength: uint16(length), 61 | Buffer: buffer, 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lsa_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- lsa.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | 8 | var ( 9 | procLsaOpenPolicy = modntdll.NewProc("LsaOpenPolicy") 10 | procLsaAddAccountRights = modntdll.NewProc("LsaAddAccountRights") 11 | procLsaEnumerateAccountRights = modntdll.NewProc("LsaEnumerateAccountRights") 12 | procLsaRemoveAccountRights = modntdll.NewProc("LsaRemoveAccountRights") 13 | procLsaClose = modntdll.NewProc("LsaClose") 14 | ) 15 | 16 | // INOUT-parameter: PolicyHandle. 17 | func LsaOpenPolicy( 18 | SystemName *LsaUnicodeString, 19 | ObjectAttributes *LsaObjectAttributes, 20 | DesiredAccess AccessMask, 21 | PolicyHandle *LsaHandle, 22 | ) NtStatus { 23 | r0, _, _ := procLsaOpenPolicy.Call(uintptr(unsafe.Pointer(SystemName)), 24 | uintptr(unsafe.Pointer(ObjectAttributes)), 25 | uintptr(DesiredAccess), 26 | uintptr(unsafe.Pointer(PolicyHandle))) 27 | return NtStatus(r0) 28 | } 29 | 30 | func LsaAddAccountRights( 31 | PolicyHandle LsaHandle, 32 | AccountSid *Sid, 33 | UserRights *LsaUnicodeString, 34 | CountOfRights uint32, 35 | ) NtStatus { 36 | r0, _, _ := procLsaAddAccountRights.Call(uintptr(PolicyHandle), 37 | uintptr(unsafe.Pointer(AccountSid)), 38 | uintptr(unsafe.Pointer(UserRights)), 39 | uintptr(CountOfRights)) 40 | return NtStatus(r0) 41 | } 42 | 43 | // OUT-parameter: UserRights, CountOfRights. 44 | func LsaEnumerateAccountRights( 45 | PolicyHandle LsaHandle, 46 | AccountSid *Sid, 47 | UserRights *LsaUnicodeString, 48 | CountOfRights *uint32, 49 | ) NtStatus { 50 | r0, _, _ := procLsaEnumerateAccountRights.Call(uintptr(PolicyHandle), 51 | uintptr(unsafe.Pointer(AccountSid)), 52 | uintptr(unsafe.Pointer(UserRights)), 53 | uintptr(unsafe.Pointer(CountOfRights))) 54 | return NtStatus(r0) 55 | } 56 | 57 | func LsaRemoveAccountRights( 58 | PolicyHandle LsaHandle, 59 | AccountSid *Sid, 60 | AllRights bool, 61 | UserRights *LsaUnicodeString, 62 | CountOfRights uint32, 63 | ) NtStatus { 64 | r0, _, _ := procLsaRemoveAccountRights.Call(uintptr(PolicyHandle), 65 | uintptr(unsafe.Pointer(AccountSid)), 66 | fromBool(AllRights), 67 | uintptr(unsafe.Pointer(UserRights)), 68 | uintptr(CountOfRights)) 69 | return NtStatus(r0) 70 | } 71 | 72 | func LsaClose( 73 | ObjectHandle LsaHandle, 74 | ) NtStatus { 75 | r0, _, _ := procLsaClose.Call(uintptr(ObjectHandle)) 76 | return NtStatus(r0) 77 | } 78 | -------------------------------------------------------------------------------- /examples/lsobj/lsobj.go: -------------------------------------------------------------------------------- 1 | // lsobj is a console-based WinObj-like tool 2 | // See https://technet.microsoft.com/en-us/sysinternals/winobj 3 | package main 4 | 5 | import ( 6 | "errors" 7 | "fmt" 8 | "os" 9 | "unsafe" 10 | 11 | "github.com/hillu/go-ntdll" 12 | ) 13 | 14 | var skipDir = errors.New("skip this directory") 15 | 16 | type walkFunc func(string, string) error 17 | 18 | func walk(entry string, fn walkFunc) error { 19 | var h ntdll.Handle 20 | if st := ntdll.NtOpenDirectoryObject(&h, ntdll.STANDARD_RIGHTS_READ|ntdll.DIRECTORY_QUERY, 21 | ntdll.NewObjectAttributes(entry, 0, 0, nil), 22 | ); st != 0 { 23 | return st.Error() 24 | } 25 | defer ntdll.NtClose(h) 26 | var context uint32 27 | for { 28 | var buf [32768]byte 29 | var length uint32 30 | switch st := ntdll.NtQueryDirectoryObject( 31 | h, 32 | &buf[0], 33 | uint32(len(buf)), 34 | true, 35 | context == 0, 36 | &context, 37 | &length, 38 | ); st { 39 | case ntdll.STATUS_SUCCESS: 40 | case ntdll.STATUS_NO_MORE_ENTRIES: 41 | return nil 42 | default: 43 | return st.Error() 44 | } 45 | odi := (*ntdll.ObjectDirectoryInformationT)(unsafe.Pointer(&buf[0])) 46 | var path string 47 | if entry == `\` { 48 | path = `\` + odi.Name.String() 49 | } else { 50 | path = entry + `\` + odi.Name.String() 51 | } 52 | switch typ := odi.TypeName.String(); typ { 53 | case "Directory": 54 | if err := walk(path, fn); err != nil { 55 | return err 56 | } 57 | default: 58 | switch err := fn(path, typ); err { 59 | case skipDir: 60 | return nil 61 | case nil: 62 | continue 63 | default: 64 | return err 65 | } 66 | } 67 | } 68 | } 69 | 70 | func main() { 71 | var arg string 72 | if len(os.Args) > 1 { 73 | arg = os.Args[1] 74 | } else { 75 | arg = "\\" 76 | } 77 | walk(arg, func(path, typ string) error { 78 | switch typ { 79 | case "SymbolicLink": 80 | var h ntdll.Handle 81 | if st := ntdll.NtOpenSymbolicLinkObject( 82 | &h, 83 | ntdll.STANDARD_RIGHTS_READ|ntdll.DIRECTORY_QUERY, 84 | ntdll.NewObjectAttributes(path, 0, 0, nil), 85 | ); st != 0 { 86 | fmt.Printf("%s %s -> \n", path, typ, st) 87 | return nil 88 | } 89 | defer ntdll.NtClose(h) 90 | target := ntdll.NewEmptyUnicodeString(1024) 91 | var length uint32 92 | if st := ntdll.NtQuerySymbolicLinkObject( 93 | h, 94 | target, 95 | &length, 96 | ); st != 0 { 97 | fmt.Printf("%s %s -> \n", path, typ, st) 98 | return nil 99 | } 100 | fmt.Printf("%s %s -> %s\n", path, typ, target) 101 | default: 102 | fmt.Printf("%s %s\n", path, typ) 103 | } 104 | return nil 105 | }) 106 | } 107 | -------------------------------------------------------------------------------- /security_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- security.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | import "reflect" 8 | 9 | var ( 10 | procNtQuerySecurityObject = modntdll.NewProc("NtQuerySecurityObject") 11 | procNtSetSecurityObject = modntdll.NewProc("NtSetSecurityObject") 12 | ) 13 | 14 | // Acl has been derived from the ACL struct definition. 15 | type Acl struct { 16 | AclRevision byte 17 | Sbz1 byte 18 | AclSize uint16 19 | AceCount uint16 20 | Sbz2 uint16 21 | } 22 | 23 | // Sid has been derived from the SID struct definition. 24 | type Sid struct { 25 | Revision byte 26 | SubAuthorityCount byte 27 | IdentifierAuthority SidIdentifierAuthority 28 | SubAuthority [1]uint32 29 | } 30 | 31 | // SubAuthoritySlice returns a slice over the elements of Sid.SubAuthority. 32 | // 33 | // Beware: The data is not copied out of Sid. The size can usually be taken from an other member of the struct (Sid). 34 | func (t *Sid) SubAuthoritySlice(size int) []uint32 { 35 | s := []uint32{} 36 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 37 | hdr.Data = uintptr(unsafe.Pointer(&t.SubAuthority[0])) 38 | hdr.Len = size 39 | hdr.Cap = size 40 | return s 41 | } 42 | 43 | // SetSubAuthoritySlice copies s into the memory at Sid.SubAuthority. 44 | // 45 | // Beware: No bounds check is performed. Another member of the struct (Sid) usually has to be set to the array size. 46 | func (t *Sid) SetSubAuthoritySlice(s []uint32) { 47 | s1 := []uint32{} 48 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 49 | hdr.Data = uintptr(unsafe.Pointer(&t.SubAuthority[0])) 50 | hdr.Len = len(s) 51 | hdr.Cap = len(s) 52 | copy(s1, s) 53 | } 54 | 55 | // SidIdentifierAuthority has been derived from the SID_IDENTIFIER_AUTHORITY struct definition. 56 | type SidIdentifierAuthority struct { 57 | Value [6]byte 58 | } 59 | 60 | // SecurityDescriptor has been derived from the SECURITY_DESCRIPTOR struct definition. 61 | type SecurityDescriptor struct { 62 | Revision byte 63 | Sbz1 byte 64 | Control SecurityDescriptorControl 65 | Owner *Sid 66 | Group *Sid 67 | Sacl *Acl 68 | Dacl *Acl 69 | } 70 | 71 | // unknown-parameter: Handle, SecurityInformation, SecurityDescriptor, Length, LengthNeeded. 72 | func NtQuerySecurityObject( 73 | Handle Handle, 74 | SecurityInformation SecurityInformationT, 75 | SecurityDescriptor *SecurityDescriptor, 76 | Length uint32, 77 | LengthNeeded *uint32, 78 | ) NtStatus { 79 | r0, _, _ := procNtQuerySecurityObject.Call(uintptr(Handle), 80 | uintptr(SecurityInformation), 81 | uintptr(unsafe.Pointer(SecurityDescriptor)), 82 | uintptr(Length), 83 | uintptr(unsafe.Pointer(LengthNeeded))) 84 | return NtStatus(r0) 85 | } 86 | 87 | // unknown-parameter: Handle, SecurityInformation, SecurityDescriptor. 88 | func NtSetSecurityObject( 89 | Handle Handle, 90 | SecurityInformation SecurityInformationT, 91 | SecurityDescriptor *SecurityDescriptor, 92 | ) NtStatus { 93 | r0, _, _ := procNtSetSecurityObject.Call(uintptr(Handle), 94 | uintptr(SecurityInformation), 95 | uintptr(unsafe.Pointer(SecurityDescriptor))) 96 | return NtStatus(r0) 97 | } 98 | -------------------------------------------------------------------------------- /section.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS NtCreateSection ( 9 | _Out_ PHANDLE SectionHandle, 10 | _In_ ACCESS_MASK DesiredAccess, 11 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, 12 | _In_opt_ PLARGE_INTEGER MaximumSize, 13 | _In_ ULONG SectionPageProtection, 14 | _In_ ULONG AllocationAttributes, 15 | _In_opt_ HANDLE FileHandle 16 | ); 17 | */ 18 | 19 | /* 20 | func: 21 | NTSTATUS NtExtendSection ( 22 | _In_ HANDLE SectionHandle, 23 | _Inout_ PLARGE_INTEGER NewSectionSize 24 | ); 25 | */ 26 | 27 | /* 28 | func: 29 | NTSTATUS NtMapViewOfSection( 30 | _In_ HANDLE SectionHandle, 31 | _In_ HANDLE ProcessHandle, 32 | _Inout_ PVOID *BaseAddress, 33 | _In_ ULONG_PTR ZeroBits, 34 | _In_ SIZE_T CommitSize, 35 | _Inout_opt_ PLARGE_INTEGER SectionOffset, 36 | _Inout_ PSIZE_T ViewSize, 37 | _In_ SECTION_INHERIT InheritDisposition, 38 | _In_ ULONG AllocationType, 39 | _In_ ULONG Win32Protect 40 | ); 41 | */ 42 | 43 | /* 44 | func: 45 | NTSTATUS NtOpenSection( 46 | _Out_ PHANDLE SectionHandle, 47 | _In_ ACCESS_MASK DesiredAccess, 48 | _In_ POBJECT_ATTRIBUTES ObjectAttributes 49 | ); 50 | */ 51 | 52 | /* 53 | func: 54 | NTSTATUS NtQuerySection( 55 | _In_ HANDLE SectionHandle, 56 | _In_ SECTION_INFORMATION_CLASS SectionInformationClass, 57 | _Out_ PVOID SectionInformation, 58 | _In_ SIZE_T SectionInformationLength, 59 | _Out_opt_ PSIZE_T ReturnLength 60 | ); 61 | */ 62 | 63 | /* 64 | enum: 65 | typedef enum _SECTION_INFORMATION_CLASS { 66 | SectionBasicInformation, 67 | SectionImageInformation, 68 | SectionRelocationInformation, 69 | SectionOriginalBaseInformation, 70 | SectionInternalImageInformation, 71 | } SECTION_INFORMATION_CLASS; 72 | */ 73 | 74 | /* 75 | type: 76 | typedef struct _SECTION_BASIC_INFORMATION { 77 | PVOID BaseAddress; 78 | ULONG AllocationAttributes; 79 | LARGE_INTEGER MaximumSize; 80 | } SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION; 81 | */ 82 | 83 | /* 84 | type: 85 | typedef struct _SECTION_IMAGE_INFORMATION 86 | { 87 | PVOID TransferAddress; 88 | ULONG ZeroBits; 89 | SIZE_T MaximumStackSize; 90 | SIZE_T CommittedStackSize; 91 | ULONG SubSystemType; 92 | ULONG SubSystemVersion; 93 | ULONG OperatingSystemVersion; 94 | USHORT ImageCharacteristics; 95 | USHORT DllCharacteristics; 96 | USHORT Machine; 97 | BOOLEAN ImageContainsCode; 98 | UCHAR ImageFlags; 99 | ULONG LoaderFlags; 100 | ULONG ImageFileSize; 101 | ULONG CheckSum; 102 | } SECTION_IMAGE_INFORMATION, *PSECTION_IMAGE_INFORMATION; 103 | */ 104 | 105 | func (i SectionImageInformationT) ComPlusNativeReady() bool { 106 | return i.ImageFlags&1 != 0 107 | } 108 | 109 | func (i SectionImageInformationT) ComPlusILOnly() bool { 110 | return i.ImageFlags&2 != 0 111 | } 112 | 113 | func (i SectionImageInformationT) ImageDynamicallyRelocated() bool { 114 | return i.ImageFlags&4 != 0 115 | } 116 | 117 | func (i SectionImageInformationT) ImageMappedFlat() bool { 118 | return i.ImageFlags&8 != 0 119 | } 120 | 121 | func (i SectionImageInformationT) BaseBelow4gb() bool { 122 | return i.ImageFlags&16 != 0 123 | } 124 | 125 | func (i SectionImageInformationT) ComPlusPrefer32bit() bool { 126 | return i.ImageFlags&32 != 0 127 | } 128 | 129 | /* 130 | func: 131 | NTSTATUS NtUnmapViewOfSection ( 132 | _In_ HANDLE ProcessHandle, 133 | _In_opt_ PVOID BaseAddress 134 | ); 135 | */ 136 | 137 | /* 138 | func: 139 | NTSTATUS NtUnmapViewOfSectionEx ( 140 | _In_ HANDLE ProcessHandle, 141 | _In_opt_ PVOID BaseAddress, 142 | _In_ ULONG Flags 143 | ); 144 | */ 145 | 146 | /* 147 | enum: 148 | typedef enum _SECTION_INHERIT { 149 | ViewShare = 1, 150 | ViewUnmap = 2 151 | } SECTION_INHERIT; 152 | */ 153 | -------------------------------------------------------------------------------- /examples/ls-proc-vm/ls-proc-vm.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/hillu/go-ntdll" 5 | 6 | "flag" 7 | "fmt" 8 | "os" 9 | "unsafe" 10 | ) 11 | 12 | func query_vm(ph ntdll.Handle, base uintptr) (*ntdll.MemoryBasicInformationT, ntdll.NtStatus) { 13 | var mbi ntdll.MemoryBasicInformationT 14 | s := ntdll.NtQueryVirtualMemory( 15 | ph, 16 | (*uint8)(unsafe.Pointer(base)), 17 | ntdll.MemoryBasicInformation, 18 | (*uint8)(unsafe.Pointer(&mbi)), 19 | unsafe.Sizeof(mbi), 20 | nil, 21 | ) 22 | if s.IsError() { 23 | return nil, s 24 | } 25 | return &mbi, s 26 | } 27 | 28 | func query_name(ph ntdll.Handle, base uintptr) (string, ntdll.NtStatus) { 29 | buf := [1024]byte{} 30 | s := ntdll.NtQueryVirtualMemory( 31 | ph, 32 | (*uint8)(unsafe.Pointer(base)), 33 | ntdll.MemoryMappedFilenameInformation, 34 | &buf[0], 35 | 1024, 36 | nil, 37 | ) 38 | if s.IsError() { 39 | return "", s 40 | } 41 | return (*ntdll.UnicodeString)(unsafe.Pointer(&buf[0])).String(), s 42 | } 43 | 44 | type memProtect uint32 45 | 46 | func (p memProtect) String() string { 47 | r := []byte("----") 48 | if p&ntdll.PAGE_NOACCESS != 0 { 49 | r[3] = '!' 50 | } 51 | if p&ntdll.PAGE_READONLY != 0 { 52 | r[0] = 'r' 53 | } 54 | if p&ntdll.PAGE_READWRITE != 0 { 55 | r[0] = 'r' 56 | r[1] = 'w' 57 | } 58 | if p&ntdll.PAGE_WRITECOPY != 0 { 59 | r[1] = 'w' 60 | r[3] = 'c' 61 | } 62 | if p&ntdll.PAGE_EXECUTE != 0 { 63 | r[2] = 'x' 64 | } 65 | if p&ntdll.PAGE_EXECUTE_READ != 0 { 66 | r[0] = 'r' 67 | r[2] = 'x' 68 | } 69 | if p&ntdll.PAGE_EXECUTE_READWRITE != 0 { 70 | r[0] = 'r' 71 | r[1] = 'w' 72 | r[2] = 'x' 73 | } 74 | if p&ntdll.PAGE_EXECUTE_WRITECOPY != 0 { 75 | r[1] = 'w' 76 | r[2] = 'x' 77 | r[3] = 'c' 78 | } 79 | if p&ntdll.PAGE_GUARD != 0 { 80 | r[3] = 'G' 81 | } 82 | if p&ntdll.PAGE_NOCACHE != 0 { 83 | r[3] = 'C' 84 | } 85 | return string(r) 86 | } 87 | 88 | type memState uint32 89 | 90 | func (s memState) String() string { 91 | r := []byte("---") 92 | if s&ntdll.MEM_COMMIT != 0 { 93 | r[0] = 'c' 94 | } 95 | if s&ntdll.MEM_RESERVE != 0 { 96 | r[1] = 'r' 97 | } 98 | if s&ntdll.MEM_FREE != 0 { 99 | r[2] = 'f' 100 | } 101 | return string(r) 102 | } 103 | 104 | type memType uint32 105 | 106 | func (s memType) String() string { 107 | r := []byte("---") 108 | if s&ntdll.MEM_MAPPED != 0 { 109 | r[0] = 'm' 110 | } 111 | if s&ntdll.MEM_PRIVATE != 0 { 112 | r[1] = 'p' 113 | } 114 | if s&ntdll.MEM_IMAGE != 0 { 115 | r[2] = 'i' 116 | } 117 | return string(r) 118 | } 119 | 120 | func main() { 121 | var pid uint 122 | flag.UintVar(&pid, "pid", 0, "target process id") 123 | flag.Parse() 124 | if pid == 0 { 125 | fmt.Printf("usage: %s -pid \n", os.Args[0]) 126 | os.Exit(1) 127 | } 128 | 129 | var ph ntdll.Handle 130 | oa := ntdll.NewObjectAttributes("", 0, 0, nil) 131 | client := ntdll.ClientId{ntdll.Handle(pid), 0} 132 | s := ntdll.NtOpenProcess(&ph, ntdll.PROCESS_QUERY_INFORMATION, oa, &client) 133 | if s.IsError() { 134 | fmt.Printf("NtOpenProcess: %s", s) 135 | os.Exit(1) 136 | } 137 | 138 | addr := uintptr(0) 139 | for { 140 | mbi, s := query_vm(ph, addr) 141 | if s.IsError() { 142 | if s != ntdll.STATUS_INVALID_PARAMETER { 143 | fmt.Printf("NtQueryVirtualMemory: %08x: %s", addr, s.Error()) 144 | } 145 | break 146 | } 147 | name, _ := query_name(ph, addr) 148 | if mbi.AllocationBase != nil { 149 | fmt.Printf("%12x %12x + %12x ty:%s st:%s pr:%s %s\n", 150 | uintptr(unsafe.Pointer(mbi.AllocationBase)), 151 | uintptr(unsafe.Pointer(mbi.BaseAddress)), 152 | mbi.RegionSize, 153 | memType(mbi.Type), 154 | memState(mbi.State), 155 | memProtect(mbi.Protect), 156 | name, 157 | ) 158 | } 159 | addr = uintptr(unsafe.Pointer(mbi.BaseAddress)) + mbi.RegionSize 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Go interface to NTDLL functions 2 | =============================== 3 | 4 | [![GoDoc](https://godoc.org/github.com/hillu/go-ntdll?status.svg)](https://godoc.org/github.com/hillu/go-ntdll) 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/hillu/go-ntdll)](https://goreportcard.com/report/github.com/hillu/go-ntdll) 6 | 7 | This package makes selected `NTDLL` functions directly available in Go 8 | programs. At the moment, types and functions for accessing kernel 9 | objects and the Registry are included. The goal is to, eventually, 10 | cover all available functions. 11 | 12 | Note 13 | ---- 14 | 15 | Please do not consider this code, particularly the autogenerated code, 16 | as stable. Identifiers names may still be subject to change. 17 | 18 | Basic functions, types 19 | ---------------------- 20 | 21 | NTDLL functions usually return an `NTSTATUS`, this is mapped into an 22 | `NtStatus` type (underlying kind: `uint32`). Strings are usually 23 | passed around as `UNICODE_STRING`, there is a type `UnicodeStringType` 24 | for that. 25 | 26 | Variable-Sized Arrays 27 | --------------------- 28 | 29 | Structs that contain fields that are arrays with one (or 30 | `ANYSIZE_ARRAY`) elements. For those fields, getters that return a 31 | slice and setters that fill the array from a slice are generated. 32 | 33 | Example: 34 | ``` c 35 | typedef struct _FILE_NAME_INFORMATION { 36 | ULONG FileNameLength; 37 | WCHAR FileName[1]; 38 | } FILE_NAME_INFORMATION, *PFILE_NAME_INFORMATION; 39 | ``` 40 | is turned into 41 | ``` go 42 | type FileNameInformationT struct { 43 | FileNameLength uint32 44 | FileName [1]uint16 45 | } 46 | ``` 47 | and associated methods 48 | ``` go 49 | func (t *FileNameInformationT) FileNameSlice(size int) []uint16 50 | func (t *FileNameInformationT) SetFileNameSlice(s []uint16) 51 | ``` 52 | 53 | Extending 54 | --------- 55 | 56 | Function signatures and structure definitions are generated from 57 | header file snippets as found in the MSDN. The transformation code can 58 | be found in `mkcode.go`, it probably has bugs and does not cover all 59 | cases. 60 | 61 | To add more structures or function stubs or enumeration types, just 62 | find the appropriate definition on MSDN and copy them into block 63 | comments, prefixed by `type:`, `func:`, or `enum:`, respectively. `go 64 | generate` can then be used to regenerate the `*_generated.go` files 65 | containing structure definitions and the glue code around 66 | `golang.org/x/sys/windows`. 67 | 68 | License 69 | ------- 70 | 71 | Copyright (C) 2016-2022 Hilko Bengen 72 | 73 | All rights reserved. 74 | 75 | Redistribution and use in source and binary forms, with or without 76 | modification, are permitted provided that the following conditions are met: 77 | 78 | * Redistributions of source code must retain the above copyright notice, this 79 | list of conditions and the following disclaimer. 80 | 81 | * Redistributions in binary form must reproduce the above copyright notice, 82 | this list of conditions and the following disclaimer in the documentation 83 | and/or other materials provided with the distribution. 84 | 85 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 86 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 87 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 88 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 89 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 90 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 91 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 92 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 93 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 94 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 95 | -------------------------------------------------------------------------------- /atom_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- atom.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | import "reflect" 8 | 9 | // The AtomInformationClass constants have been derived from the ATOM_INFORMATION_CLASS enum definition. 10 | type AtomInformationClass uint32 11 | 12 | const ( 13 | AtomBasicInformation AtomInformationClass = 0 14 | AtomTableInformation = 1 15 | ) 16 | 17 | var ( 18 | procNtAddAtom = modntdll.NewProc("NtAddAtom") 19 | procNtDeleteAtom = modntdll.NewProc("NtDeleteAtom") 20 | procNtFindAtom = modntdll.NewProc("NtFindAtom") 21 | procNtQueryInformationAtom = modntdll.NewProc("NtQueryInformationAtom") 22 | ) 23 | 24 | // AtomBasicInformationT has been derived from the ATOM_BASIC_INFORMATION struct definition. 25 | type AtomBasicInformationT struct { 26 | UsageCount uint16 27 | Flags uint16 28 | NameLength uint16 29 | Name [1]uint16 30 | } 31 | 32 | // NameSlice returns a slice over the elements of AtomBasicInformationT.Name. 33 | // 34 | // Beware: The data is not copied out of AtomBasicInformationT. The size can usually be taken from an other member of the struct (AtomBasicInformationT). 35 | func (t *AtomBasicInformationT) NameSlice(size int) []uint16 { 36 | s := []uint16{} 37 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 38 | hdr.Data = uintptr(unsafe.Pointer(&t.Name[0])) 39 | hdr.Len = size 40 | hdr.Cap = size 41 | return s 42 | } 43 | 44 | // SetNameSlice copies s into the memory at AtomBasicInformationT.Name. 45 | // 46 | // Beware: No bounds check is performed. Another member of the struct (AtomBasicInformationT) usually has to be set to the array size. 47 | func (t *AtomBasicInformationT) SetNameSlice(s []uint16) { 48 | s1 := []uint16{} 49 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 50 | hdr.Data = uintptr(unsafe.Pointer(&t.Name[0])) 51 | hdr.Len = len(s) 52 | hdr.Cap = len(s) 53 | copy(s1, s) 54 | } 55 | 56 | // AtomTableInformationT has been derived from the ATOM_TABLE_INFORMATION struct definition. 57 | type AtomTableInformationT struct { 58 | NumberOfAtoms uint32 59 | Atoms [1]RtlAtom 60 | } 61 | 62 | // AtomsSlice returns a slice over the elements of AtomTableInformationT.Atoms. 63 | // 64 | // Beware: The data is not copied out of AtomTableInformationT. The size can usually be taken from an other member of the struct (AtomTableInformationT). 65 | func (t *AtomTableInformationT) AtomsSlice(size int) []RtlAtom { 66 | s := []RtlAtom{} 67 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 68 | hdr.Data = uintptr(unsafe.Pointer(&t.Atoms[0])) 69 | hdr.Len = size 70 | hdr.Cap = size 71 | return s 72 | } 73 | 74 | // SetAtomsSlice copies s into the memory at AtomTableInformationT.Atoms. 75 | // 76 | // Beware: No bounds check is performed. Another member of the struct (AtomTableInformationT) usually has to be set to the array size. 77 | func (t *AtomTableInformationT) SetAtomsSlice(s []RtlAtom) { 78 | s1 := []RtlAtom{} 79 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 80 | hdr.Data = uintptr(unsafe.Pointer(&t.Atoms[0])) 81 | hdr.Len = len(s) 82 | hdr.Cap = len(s) 83 | copy(s1, s) 84 | } 85 | 86 | // OUT-parameter: Atom. 87 | func NtAddAtom( 88 | AtomName *uint16, 89 | Length uint32, 90 | Atom *RtlAtom, 91 | ) NtStatus { 92 | r0, _, _ := procNtAddAtom.Call(uintptr(unsafe.Pointer(AtomName)), 93 | uintptr(Length), 94 | uintptr(unsafe.Pointer(Atom))) 95 | return NtStatus(r0) 96 | } 97 | 98 | func NtDeleteAtom( 99 | Atom RtlAtom, 100 | ) NtStatus { 101 | r0, _, _ := procNtDeleteAtom.Call(uintptr(Atom)) 102 | return NtStatus(r0) 103 | } 104 | 105 | // OUT-parameter: Atom. 106 | // *OPT-parameter: Atom. 107 | func NtFindAtom( 108 | AtomName *uint16, 109 | Length uint32, 110 | Atom *RtlAtom, 111 | ) NtStatus { 112 | r0, _, _ := procNtFindAtom.Call(uintptr(unsafe.Pointer(AtomName)), 113 | uintptr(Length), 114 | uintptr(unsafe.Pointer(Atom))) 115 | return NtStatus(r0) 116 | } 117 | 118 | // OUT-parameter: AtomInformation, ReturnLength. 119 | func NtQueryInformationAtom( 120 | Atom RtlAtom, 121 | AtomInformationClass AtomInformationClass, 122 | AtomInformation *byte, 123 | AtomInformationLength uint32, 124 | ReturnLength *uint32, 125 | ) NtStatus { 126 | r0, _, _ := procNtQueryInformationAtom.Call(uintptr(Atom), 127 | uintptr(AtomInformationClass), 128 | uintptr(unsafe.Pointer(AtomInformation)), 129 | uintptr(AtomInformationLength), 130 | uintptr(unsafe.Pointer(ReturnLength))) 131 | return NtStatus(r0) 132 | } 133 | -------------------------------------------------------------------------------- /statuscrawler.go: -------------------------------------------------------------------------------- 1 | //+build ignore 2 | 3 | // simple crawler to extract Status Codes from MSDN. 4 | package main 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | "go/format" 10 | "log" 11 | "os" 12 | "regexp" 13 | "sort" 14 | "strings" 15 | "time" 16 | 17 | "github.com/PuerkitoBio/goquery" 18 | "net/http" 19 | ) 20 | 21 | const URL = "https://msdn.microsoft.com/en-us/library/cc704588.aspx" 22 | 23 | type status struct { 24 | val uint64 25 | name string 26 | desc string 27 | } 28 | 29 | type StatusList []status 30 | 31 | func (l StatusList) Len() int { return len(l) } 32 | func (l StatusList) Swap(i, j int) { l[i], l[j] = l[j], l[i] } 33 | func (l StatusList) Less(i, j int) bool { return l[i].val < l[j].val } 34 | 35 | var list StatusList 36 | 37 | func main() { 38 | req, err := http.NewRequest("GET", URL, nil) 39 | if err != nil { 40 | log.Fatalf("Could not construct request: %v", err) 41 | } 42 | req.Header.Add("User-Agent", "Mozilla (compatible; ntstatuscrawler.go; https://github.com/hillu/go-ntdll)") 43 | res, err := http.DefaultClient.Do(req) 44 | if err != nil { 45 | log.Fatalf("Could not retrieve %s: %v", URL, err) 46 | } 47 | if res.StatusCode != 200 { 48 | log.Fatalf("Expected HTTP status 200, got %s", res.Status) 49 | } 50 | 51 | doc, err := goquery.NewDocumentFromResponse(res) 52 | if err != nil { 53 | log.Fatalf("Could not parse document from %s: %v", URL, err) 54 | } 55 | 56 | // This is how the table with the status-codes looks like inside the HTML: 57 | // 58 | // 63 | // 69 | // 77 | 78 | var n2s = map[uint64]string{} 79 | var spaces = regexp.MustCompile(" *") 80 | doc.Find("table tr").Each(func(i int, s *goquery.Selection) { 81 | if i == 0 { 82 | return // skip header 83 | } 84 | st := status{} 85 | 86 | td1 := s.Find("td") 87 | if td1 == nil { 88 | log.Println("entry ", i, "empty td") 89 | return 90 | } 91 | 92 | p := td1.Find("p").First() 93 | v := strings.TrimSpace(p.Text()) 94 | if _, err = fmt.Sscanf(v, "0x%X", &st.val); err != nil { 95 | log.Println("entry ", i, err) 96 | return 97 | } 98 | st.name = p.Next().Text() 99 | n2s[st.val] = st.name // Any duplicate gets overwritten! 100 | desc := strings.Replace(td1.Next().Find("p").Text(), "\n", "", -1) 101 | st.desc = spaces.ReplaceAllLiteralString(desc, " ") 102 | list = append(list, st) 103 | }) 104 | 105 | // Sort the list by status code. 106 | sort.Sort(list) 107 | 108 | // Write the header 109 | code := &bytes.Buffer{} 110 | code.WriteString("package ntdll\n") 111 | code.WriteString("// Generated by github.com/hillu/go-ntdll/statuscrawler; DO NOT EDIT\n") 112 | fmt.Fprintf(code, "// Extracted from %s, ", URL) 113 | 114 | if docid, found := doc.Find(`meta[name="document_id"]`).Attr("content"); found { 115 | fmt.Fprintf(code, "document_id=%s\n\n", docid) 116 | } else if sitever, found := doc.Find(`meta[name="ms.sitever"]`).Attr("content"); found { 117 | fmt.Fprintf(code, "ms.sitever=%s\n\n", sitever) 118 | } else if datetime, found := doc.Find(`time[data-article-date]`).Attr("datetime"); found { 119 | fmt.Fprintf(code, "datetime=%s\n\n", datetime) 120 | } else { 121 | log.Print("Could not find timestamp; using time.Now()") 122 | fmt.Fprintf(code, "on %s\n\n", time.Now().Format(time.RFC822)) 123 | } 124 | 125 | // Write the constants 126 | code.WriteString("const (\n") 127 | for i, s := range list { 128 | fmt.Fprintf(code, "// %s\n", s.desc) 129 | if i == 0 { 130 | fmt.Fprintf(code, "%s NtStatus = 0x%08X\n", s.name, s.val) 131 | } else { 132 | fmt.Fprintf(code, "%s = 0x%08X\n", s.name, s.val) 133 | } 134 | } 135 | code.WriteString(")\n\n") 136 | 137 | n2s[0x00000000] = "STATUS_SUCCESS" // Fix the correspondence 138 | 139 | // Write the reverse-lookup-table. 140 | code.WriteString("var ntStatus2str = map[NtStatus]string{\n") 141 | for _, status := range list { 142 | if short, ok := n2s[status.val]; ok { 143 | fmt.Fprintf(code, "0x%08X : \"%s\",\n", status.val, short) 144 | delete(n2s, status.val) // Avoid duplicates. 145 | } 146 | } 147 | code.WriteString("}\n\n") 148 | 149 | // Write the Stringer method for NtStatus 150 | code.WriteString(` 151 | func (status NtStatus) String() string { 152 | return ntStatus2str[status] 153 | } 154 | `) 155 | 156 | out, err := format.Source(code.Bytes()) 157 | if err != nil { 158 | log.Println(err) 159 | log.Println(code.String()) 160 | } 161 | 162 | if f, err := os.Create("ntstatus_generated.go"); err != nil { 163 | log.Fatal(err) 164 | } else if n, err := f.Write(out); err != nil { 165 | log.Fatal(err) 166 | } else if n != len(out) { 167 | log.Fatal("output size mismatch") 168 | } else { 169 | f.Close() 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /section_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- section.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | 8 | // The SectionInformationClass constants have been derived from the SECTION_INFORMATION_CLASS enum definition. 9 | type SectionInformationClass uint32 10 | 11 | const ( 12 | SectionBasicInformation SectionInformationClass = 0 13 | SectionImageInformation = 1 14 | SectionRelocationInformation = 2 15 | SectionOriginalBaseInformation = 3 16 | SectionInternalImageInformation = 4 17 | ) 18 | 19 | // The SectionInherit constants have been derived from the SECTION_INHERIT enum definition. 20 | type SectionInherit uint32 21 | 22 | const ( 23 | ViewShare SectionInherit = 1 24 | ViewUnmap = 2 25 | ) 26 | 27 | var ( 28 | procNtCreateSection = modntdll.NewProc("NtCreateSection") 29 | procNtExtendSection = modntdll.NewProc("NtExtendSection") 30 | procNtMapViewOfSection = modntdll.NewProc("NtMapViewOfSection") 31 | procNtOpenSection = modntdll.NewProc("NtOpenSection") 32 | procNtQuerySection = modntdll.NewProc("NtQuerySection") 33 | procNtUnmapViewOfSection = modntdll.NewProc("NtUnmapViewOfSection") 34 | procNtUnmapViewOfSectionEx = modntdll.NewProc("NtUnmapViewOfSectionEx") 35 | ) 36 | 37 | // SectionBasicInformationT has been derived from the SECTION_BASIC_INFORMATION struct definition. 38 | type SectionBasicInformationT struct { 39 | BaseAddress *byte 40 | AllocationAttributes uint32 41 | MaximumSize int64 42 | } 43 | 44 | // SectionImageInformationT has been derived from the SECTION_IMAGE_INFORMATION struct definition. 45 | type SectionImageInformationT struct { 46 | TransferAddress *byte 47 | ZeroBits uint32 48 | MaximumStackSize uintptr 49 | CommittedStackSize uintptr 50 | SubSystemType uint32 51 | SubSystemVersion uint32 52 | OperatingSystemVersion uint32 53 | ImageCharacteristics uint16 54 | DllCharacteristics uint16 55 | Machine uint16 56 | ImageContainsCode bool 57 | ImageFlags byte 58 | LoaderFlags uint32 59 | ImageFileSize uint32 60 | CheckSum uint32 61 | } 62 | 63 | // OUT-parameter: SectionHandle. 64 | // *OPT-parameter: ObjectAttributes, MaximumSize, FileHandle. 65 | func NtCreateSection( 66 | SectionHandle *Handle, 67 | DesiredAccess AccessMask, 68 | ObjectAttributes *ObjectAttributes, 69 | MaximumSize *int64, 70 | SectionPageProtection uint32, 71 | AllocationAttributes uint32, 72 | FileHandle Handle, 73 | ) NtStatus { 74 | r0, _, _ := procNtCreateSection.Call(uintptr(unsafe.Pointer(SectionHandle)), 75 | uintptr(DesiredAccess), 76 | uintptr(unsafe.Pointer(ObjectAttributes)), 77 | uintptr(unsafe.Pointer(MaximumSize)), 78 | uintptr(SectionPageProtection), 79 | uintptr(AllocationAttributes), 80 | uintptr(FileHandle)) 81 | return NtStatus(r0) 82 | } 83 | 84 | // INOUT-parameter: NewSectionSize. 85 | func NtExtendSection( 86 | SectionHandle Handle, 87 | NewSectionSize *int64, 88 | ) NtStatus { 89 | r0, _, _ := procNtExtendSection.Call(uintptr(SectionHandle), 90 | uintptr(unsafe.Pointer(NewSectionSize))) 91 | return NtStatus(r0) 92 | } 93 | 94 | // INOUT-parameter: BaseAddress, SectionOffset, ViewSize. 95 | // *OPT-parameter: SectionOffset. 96 | func NtMapViewOfSection( 97 | SectionHandle Handle, 98 | ProcessHandle Handle, 99 | BaseAddress *byte, 100 | ZeroBits *uint32, 101 | CommitSize uintptr, 102 | SectionOffset *int64, 103 | ViewSize *uintptr, 104 | InheritDisposition SectionInherit, 105 | AllocationType uint32, 106 | Win32Protect uint32, 107 | ) NtStatus { 108 | r0, _, _ := procNtMapViewOfSection.Call(uintptr(SectionHandle), 109 | uintptr(ProcessHandle), 110 | uintptr(unsafe.Pointer(BaseAddress)), 111 | uintptr(unsafe.Pointer(ZeroBits)), 112 | uintptr(CommitSize), 113 | uintptr(unsafe.Pointer(SectionOffset)), 114 | uintptr(unsafe.Pointer(ViewSize)), 115 | uintptr(InheritDisposition), 116 | uintptr(AllocationType), 117 | uintptr(Win32Protect)) 118 | return NtStatus(r0) 119 | } 120 | 121 | // OUT-parameter: SectionHandle. 122 | func NtOpenSection( 123 | SectionHandle *Handle, 124 | DesiredAccess AccessMask, 125 | ObjectAttributes *ObjectAttributes, 126 | ) NtStatus { 127 | r0, _, _ := procNtOpenSection.Call(uintptr(unsafe.Pointer(SectionHandle)), 128 | uintptr(DesiredAccess), 129 | uintptr(unsafe.Pointer(ObjectAttributes))) 130 | return NtStatus(r0) 131 | } 132 | 133 | // OUT-parameter: SectionInformation, ReturnLength. 134 | // *OPT-parameter: ReturnLength. 135 | func NtQuerySection( 136 | SectionHandle Handle, 137 | SectionInformationClass SectionInformationClass, 138 | SectionInformation *byte, 139 | SectionInformationLength uintptr, 140 | ReturnLength *uintptr, 141 | ) NtStatus { 142 | r0, _, _ := procNtQuerySection.Call(uintptr(SectionHandle), 143 | uintptr(SectionInformationClass), 144 | uintptr(unsafe.Pointer(SectionInformation)), 145 | uintptr(SectionInformationLength), 146 | uintptr(unsafe.Pointer(ReturnLength))) 147 | return NtStatus(r0) 148 | } 149 | 150 | // *OPT-parameter: BaseAddress. 151 | func NtUnmapViewOfSection( 152 | ProcessHandle Handle, 153 | BaseAddress *byte, 154 | ) NtStatus { 155 | r0, _, _ := procNtUnmapViewOfSection.Call(uintptr(ProcessHandle), 156 | uintptr(unsafe.Pointer(BaseAddress))) 157 | return NtStatus(r0) 158 | } 159 | 160 | // *OPT-parameter: BaseAddress. 161 | func NtUnmapViewOfSectionEx( 162 | ProcessHandle Handle, 163 | BaseAddress *byte, 164 | Flags uint32, 165 | ) NtStatus { 166 | r0, _, _ := procNtUnmapViewOfSectionEx.Call(uintptr(ProcessHandle), 167 | uintptr(unsafe.Pointer(BaseAddress)), 168 | uintptr(Flags)) 169 | return NtStatus(r0) 170 | } 171 | -------------------------------------------------------------------------------- /memory_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- memory.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | import "reflect" 8 | 9 | // The MemoryInformationClass constants have been derived from the MEMORY_INFORMATION_CLASS enum definition. 10 | type MemoryInformationClass uint32 11 | 12 | const ( 13 | MemoryBasicInformation MemoryInformationClass = 0 14 | MemoryWorkingSetInformation = 1 15 | MemoryMappedFilenameInformation = 2 16 | MemoryRegionInformation = 3 17 | MemoryWorkingSetExInformation = 4 18 | MemorySharedCommitInformation = 5 19 | MemoryImageInformation = 6 20 | MemoryRegionInformationEx = 7 21 | MemoryPrivilegedBasicInformation = 8 22 | MemoryEnclaveImageInformation = 9 23 | MemoryBasicInformationCapped = 10 24 | MemoryPhysicalContiguityInformation = 11 25 | ) 26 | 27 | var ( 28 | procNtAllocateVirtualMemory = modntdll.NewProc("NtAllocateVirtualMemory") 29 | procNtFreeVirtualMemory = modntdll.NewProc("NtFreeVirtualMemory") 30 | procNtReadVirtualMemory = modntdll.NewProc("NtReadVirtualMemory") 31 | procNtWriteVirtualMemory = modntdll.NewProc("NtWriteVirtualMemory") 32 | procNtProtectVirtualMemory = modntdll.NewProc("NtProtectVirtualMemory") 33 | procNtQueryVirtualMemory = modntdll.NewProc("NtQueryVirtualMemory") 34 | procNtFlushVirtualMemory = modntdll.NewProc("NtFlushVirtualMemory") 35 | ) 36 | 37 | // MemoryBasicInformationT has been derived from the MEMORY_BASIC_INFORMATION struct definition. 38 | type MemoryBasicInformationT struct { 39 | BaseAddress *byte 40 | AllocationBase *byte 41 | AllocationProtect uint32 42 | PartitionId uint16 43 | RegionSize uintptr 44 | State uint32 45 | Protect uint32 46 | Type uint32 47 | } 48 | 49 | // MemoryBasicInformation32 has been derived from the MEMORY_BASIC_INFORMATION32 struct definition. 50 | type MemoryBasicInformation32 struct { 51 | BaseAddress uint32 52 | AllocationBase uint32 53 | AllocationProtect uint32 54 | RegionSize uint32 55 | State uint32 56 | Protect uint32 57 | Type uint32 58 | } 59 | 60 | // MemoryBasicInformation64 has been derived from the MEMORY_BASIC_INFORMATION64 struct definition. 61 | type MemoryBasicInformation64 struct { 62 | BaseAddress uint64 63 | AllocationBase uint64 64 | AllocationProtect uint32 65 | __alignment1 uint32 66 | RegionSize uint64 67 | State uint32 68 | Protect uint32 69 | Type uint32 70 | __alignment2 uint32 71 | } 72 | 73 | // MemoryWorkingSetInformationT has been derived from the MEMORY_WORKING_SET_INFORMATION struct definition. 74 | type MemoryWorkingSetInformationT struct { 75 | NumberOfEntries *uint32 76 | WorkingSetInfo [1]MemoryWorkingSetBlock 77 | } 78 | 79 | // WorkingSetInfoSlice returns a slice over the elements of MemoryWorkingSetInformationT.WorkingSetInfo. 80 | // 81 | // Beware: The data is not copied out of MemoryWorkingSetInformationT. The size can usually be taken from an other member of the struct (MemoryWorkingSetInformationT). 82 | func (t *MemoryWorkingSetInformationT) WorkingSetInfoSlice(size int) []MemoryWorkingSetBlock { 83 | s := []MemoryWorkingSetBlock{} 84 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 85 | hdr.Data = uintptr(unsafe.Pointer(&t.WorkingSetInfo[0])) 86 | hdr.Len = size 87 | hdr.Cap = size 88 | return s 89 | } 90 | 91 | // SetWorkingSetInfoSlice copies s into the memory at MemoryWorkingSetInformationT.WorkingSetInfo. 92 | // 93 | // Beware: No bounds check is performed. Another member of the struct (MemoryWorkingSetInformationT) usually has to be set to the array size. 94 | func (t *MemoryWorkingSetInformationT) SetWorkingSetInfoSlice(s []MemoryWorkingSetBlock) { 95 | s1 := []MemoryWorkingSetBlock{} 96 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 97 | hdr.Data = uintptr(unsafe.Pointer(&t.WorkingSetInfo[0])) 98 | hdr.Len = len(s) 99 | hdr.Cap = len(s) 100 | copy(s1, s) 101 | } 102 | 103 | // MemoryRegionInformationT has been derived from the MEMORY_REGION_INFORMATION struct definition. 104 | type MemoryRegionInformationT struct { 105 | AllocationBase *byte 106 | AllocationProtect uint32 107 | RegionType uint32 108 | RegionSize uintptr 109 | CommitSize uintptr 110 | PartitionId *uint32 111 | NodePreference *uint32 112 | } 113 | 114 | // MemoryWorkingSetExInformationT has been derived from the MEMORY_WORKING_SET_EX_INFORMATION struct definition. 115 | type MemoryWorkingSetExInformationT struct { 116 | VirtualAddress *byte 117 | VirtualAttributes MemoryWorkingSetExBlock 118 | } 119 | 120 | // MemorySharedCommitInformationT has been derived from the MEMORY_SHARED_COMMIT_INFORMATION struct definition. 121 | type MemorySharedCommitInformationT struct { 122 | CommitSize uintptr 123 | } 124 | 125 | // MemoryImageInformationT has been derived from the MEMORY_IMAGE_INFORMATION struct definition. 126 | type MemoryImageInformationT struct { 127 | ImageBase *byte 128 | SizeOfImage uintptr 129 | ImageFlags uint32 130 | } 131 | 132 | // INOUT-parameter: BaseAddress, RegionSize. 133 | func NtAllocateVirtualMemory( 134 | ProcessHandle Handle, 135 | BaseAddress *byte, 136 | ZeroBits *uint32, 137 | RegionSize *uintptr, 138 | AllocationType uint32, 139 | Protect uint32, 140 | ) NtStatus { 141 | r0, _, _ := procNtAllocateVirtualMemory.Call(uintptr(ProcessHandle), 142 | uintptr(unsafe.Pointer(BaseAddress)), 143 | uintptr(unsafe.Pointer(ZeroBits)), 144 | uintptr(unsafe.Pointer(RegionSize)), 145 | uintptr(AllocationType), 146 | uintptr(Protect)) 147 | return NtStatus(r0) 148 | } 149 | 150 | // INOUT-parameter: BaseAddress, RegionSize. 151 | func NtFreeVirtualMemory( 152 | ProcessHandle Handle, 153 | BaseAddress *byte, 154 | RegionSize *uintptr, 155 | FreeType uint32, 156 | ) NtStatus { 157 | r0, _, _ := procNtFreeVirtualMemory.Call(uintptr(ProcessHandle), 158 | uintptr(unsafe.Pointer(BaseAddress)), 159 | uintptr(unsafe.Pointer(RegionSize)), 160 | uintptr(FreeType)) 161 | return NtStatus(r0) 162 | } 163 | 164 | // OUT-parameter: Buffer, NumberOfBytesRead. 165 | // *OPT-parameter: BaseAddress, NumberOfBytesRead. 166 | func NtReadVirtualMemory( 167 | ProcessHandle Handle, 168 | BaseAddress *byte, 169 | Buffer *byte, 170 | BufferSize uintptr, 171 | NumberOfBytesRead *uintptr, 172 | ) NtStatus { 173 | r0, _, _ := procNtReadVirtualMemory.Call(uintptr(ProcessHandle), 174 | uintptr(unsafe.Pointer(BaseAddress)), 175 | uintptr(unsafe.Pointer(Buffer)), 176 | uintptr(BufferSize), 177 | uintptr(unsafe.Pointer(NumberOfBytesRead))) 178 | return NtStatus(r0) 179 | } 180 | 181 | // OUT-parameter: NumberOfBytesWritten. 182 | // *OPT-parameter: BaseAddress, NumberOfBytesWritten. 183 | func NtWriteVirtualMemory( 184 | ProcessHandle Handle, 185 | BaseAddress *byte, 186 | Buffer *byte, 187 | BufferSize uintptr, 188 | NumberOfBytesWritten *uintptr, 189 | ) NtStatus { 190 | r0, _, _ := procNtWriteVirtualMemory.Call(uintptr(ProcessHandle), 191 | uintptr(unsafe.Pointer(BaseAddress)), 192 | uintptr(unsafe.Pointer(Buffer)), 193 | uintptr(BufferSize), 194 | uintptr(unsafe.Pointer(NumberOfBytesWritten))) 195 | return NtStatus(r0) 196 | } 197 | 198 | // OUT-parameter: OldProtect. 199 | // INOUT-parameter: BaseAddress, RegionSize. 200 | func NtProtectVirtualMemory( 201 | ProcessHandle Handle, 202 | BaseAddress *byte, 203 | RegionSize *uintptr, 204 | NewProtect uint32, 205 | OldProtect *uint32, 206 | ) NtStatus { 207 | r0, _, _ := procNtProtectVirtualMemory.Call(uintptr(ProcessHandle), 208 | uintptr(unsafe.Pointer(BaseAddress)), 209 | uintptr(unsafe.Pointer(RegionSize)), 210 | uintptr(NewProtect), 211 | uintptr(unsafe.Pointer(OldProtect))) 212 | return NtStatus(r0) 213 | } 214 | 215 | // OUT-parameter: MemoryInformation, ReturnLength. 216 | // *OPT-parameter: BaseAddress, ReturnLength. 217 | func NtQueryVirtualMemory( 218 | ProcessHandle Handle, 219 | BaseAddress *byte, 220 | MemoryInformationClass MemoryInformationClass, 221 | MemoryInformation *byte, 222 | MemoryInformationLength uintptr, 223 | ReturnLength *uintptr, 224 | ) NtStatus { 225 | r0, _, _ := procNtQueryVirtualMemory.Call(uintptr(ProcessHandle), 226 | uintptr(unsafe.Pointer(BaseAddress)), 227 | uintptr(MemoryInformationClass), 228 | uintptr(unsafe.Pointer(MemoryInformation)), 229 | uintptr(MemoryInformationLength), 230 | uintptr(unsafe.Pointer(ReturnLength))) 231 | return NtStatus(r0) 232 | } 233 | 234 | // OUT-parameter: IoStatus. 235 | // INOUT-parameter: BaseAddress, RegionSize. 236 | func NtFlushVirtualMemory( 237 | ProcessHandle Handle, 238 | BaseAddress *byte, 239 | RegionSize *uintptr, 240 | IoStatus *IoStatusBlock, 241 | ) NtStatus { 242 | r0, _, _ := procNtFlushVirtualMemory.Call(uintptr(ProcessHandle), 243 | uintptr(unsafe.Pointer(BaseAddress)), 244 | uintptr(unsafe.Pointer(RegionSize)), 245 | uintptr(unsafe.Pointer(IoStatus))) 246 | return NtStatus(r0) 247 | } 248 | -------------------------------------------------------------------------------- /object_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- object.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | import "reflect" 8 | 9 | // The ObjectInformationClass constants have been derived from the OBJECT_INFORMATION_CLASS enum definition. 10 | type ObjectInformationClass uint32 11 | 12 | const ( 13 | ObjectBasicInformation ObjectInformationClass = 0 14 | ObjectNameInformation = 1 15 | ObjectTypeInformation = 2 16 | ObjectAllInformation = 3 17 | ObjectDataInformation = 4 18 | ) 19 | 20 | var ( 21 | procNtOpenDirectoryObject = modntdll.NewProc("NtOpenDirectoryObject") 22 | procNtQueryDirectoryObject = modntdll.NewProc("NtQueryDirectoryObject") 23 | procNtOpenSymbolicLinkObject = modntdll.NewProc("NtOpenSymbolicLinkObject") 24 | procNtQuerySymbolicLinkObject = modntdll.NewProc("NtQuerySymbolicLinkObject") 25 | procNtCreateSymbolicLinkObject = modntdll.NewProc("NtCreateSymbolicLinkObject") 26 | procNtCreateDirectoryObject = modntdll.NewProc("NtCreateDirectoryObject") 27 | procNtCreateDirectoryObjectEx = modntdll.NewProc("NtCreateDirectoryObjectEx") 28 | procNtQueryObject = modntdll.NewProc("NtQueryObject") 29 | procNtDuplicateObject = modntdll.NewProc("NtDuplicateObject") 30 | ) 31 | 32 | // ObjectAttributes has been derived from the OBJECT_ATTRIBUTES struct definition. 33 | type ObjectAttributes struct { 34 | Length uint32 35 | RootDirectory Handle 36 | ObjectName *UnicodeString 37 | Attributes uint32 38 | SecurityDescriptor *byte 39 | SecurityQualityOfService *byte 40 | } 41 | 42 | // ObjectDirectoryInformationT has been derived from the OBJECT_DIRECTORY_INFORMATION struct definition. 43 | type ObjectDirectoryInformationT struct { 44 | Name UnicodeString 45 | TypeName UnicodeString 46 | } 47 | 48 | // ObjectBasicInformationT has been derived from the OBJECT_BASIC_INFORMATION struct definition. 49 | type ObjectBasicInformationT struct { 50 | Attributes uint32 51 | GrantedAccess AccessMask 52 | HandleCount uint32 53 | PointerCount uint32 54 | PagedPoolUsage uint32 55 | NonPagedPoolUsage uint32 56 | Reserved [3]uint32 57 | NameInformationLength uint32 58 | TypeInformationLength uint32 59 | SecurityDescriptorLength uint32 60 | CreateTime int64 61 | } 62 | 63 | // ObjectNameInformationT has been derived from the OBJECT_NAME_INFORMATION struct definition. 64 | type ObjectNameInformationT struct { 65 | Name UnicodeString 66 | } 67 | 68 | // GenericMapping has been derived from the GENERIC_MAPPING struct definition. 69 | type GenericMapping struct { 70 | GenericRead AccessMask 71 | GenericWrite AccessMask 72 | GenericExecute AccessMask 73 | GenericAll AccessMask 74 | } 75 | 76 | // ObjectTypeInformationT has been derived from the OBJECT_TYPE_INFORMATION struct definition. 77 | type ObjectTypeInformationT struct { 78 | TypeName UnicodeString 79 | TotalNumberOfObjects uint32 80 | TotalNumberOfHandles uint32 81 | TotalPagedPoolUsage uint32 82 | TotalNonPagedPoolUsage uint32 83 | TotalNamePoolUsage uint32 84 | TotalHandleTableUsage uint32 85 | HighWaterNumberOfObjects uint32 86 | HighWaterNumberOfHandles uint32 87 | HighWaterPagedPoolUsage uint32 88 | HighWaterNonPagedPoolUsage uint32 89 | HighWaterNamePoolUsage uint32 90 | HighWaterHandleTableUsage uint32 91 | InvalidAttributes uint32 92 | GenericMapping GenericMapping 93 | ValidAccessMask uint32 94 | SecurityRequired bool 95 | MaintainHandleCount bool 96 | TypeIndex byte 97 | ReservedByte byte 98 | PoolType uint32 99 | DefaultPagedPoolCharge uint32 100 | DefaultNonPagedPoolCharge uint32 101 | } 102 | 103 | // ObjectAllInformationT has been derived from the OBJECT_ALL_INFORMATION struct definition. 104 | type ObjectAllInformationT struct { 105 | NumberOfObjects uint32 106 | ObjectTypeInformation [1]ObjectTypeInformationT 107 | } 108 | 109 | // ObjectTypeInformationSlice returns a slice over the elements of ObjectAllInformationT.ObjectTypeInformation. 110 | // 111 | // Beware: The data is not copied out of ObjectAllInformationT. The size can usually be taken from an other member of the struct (ObjectAllInformationT). 112 | func (t *ObjectAllInformationT) ObjectTypeInformationSlice(size int) []ObjectTypeInformationT { 113 | s := []ObjectTypeInformationT{} 114 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 115 | hdr.Data = uintptr(unsafe.Pointer(&t.ObjectTypeInformation[0])) 116 | hdr.Len = size 117 | hdr.Cap = size 118 | return s 119 | } 120 | 121 | // SetObjectTypeInformationSlice copies s into the memory at ObjectAllInformationT.ObjectTypeInformation. 122 | // 123 | // Beware: No bounds check is performed. Another member of the struct (ObjectAllInformationT) usually has to be set to the array size. 124 | func (t *ObjectAllInformationT) SetObjectTypeInformationSlice(s []ObjectTypeInformationT) { 125 | s1 := []ObjectTypeInformationT{} 126 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 127 | hdr.Data = uintptr(unsafe.Pointer(&t.ObjectTypeInformation[0])) 128 | hdr.Len = len(s) 129 | hdr.Cap = len(s) 130 | copy(s1, s) 131 | } 132 | 133 | // ObjectDataInformationT has been derived from the OBJECT_DATA_INFORMATION struct definition. 134 | type ObjectDataInformationT struct { 135 | InheritHandle bool 136 | ProtectFromClose bool 137 | } 138 | 139 | // OUT-parameter: DirectoryHandle. 140 | func NtOpenDirectoryObject( 141 | DirectoryHandle *Handle, 142 | DesiredAccess AccessMask, 143 | ObjectAttributes *ObjectAttributes, 144 | ) NtStatus { 145 | r0, _, _ := procNtOpenDirectoryObject.Call(uintptr(unsafe.Pointer(DirectoryHandle)), 146 | uintptr(DesiredAccess), 147 | uintptr(unsafe.Pointer(ObjectAttributes))) 148 | return NtStatus(r0) 149 | } 150 | 151 | // OUT-parameter: Buffer, ReturnLength. 152 | // INOUT-parameter: Context. 153 | // *OPT-parameter: Buffer, ReturnLength. 154 | func NtQueryDirectoryObject( 155 | DirectoryHandle Handle, 156 | Buffer *byte, 157 | Length uint32, 158 | ReturnSingleEntry bool, 159 | RestartScan bool, 160 | Context *uint32, 161 | ReturnLength *uint32, 162 | ) NtStatus { 163 | r0, _, _ := procNtQueryDirectoryObject.Call(uintptr(DirectoryHandle), 164 | uintptr(unsafe.Pointer(Buffer)), 165 | uintptr(Length), 166 | fromBool(ReturnSingleEntry), 167 | fromBool(RestartScan), 168 | uintptr(unsafe.Pointer(Context)), 169 | uintptr(unsafe.Pointer(ReturnLength))) 170 | return NtStatus(r0) 171 | } 172 | 173 | // OUT-parameter: LinkHandle. 174 | func NtOpenSymbolicLinkObject( 175 | LinkHandle *Handle, 176 | DesiredAccess AccessMask, 177 | ObjectAttributes *ObjectAttributes, 178 | ) NtStatus { 179 | r0, _, _ := procNtOpenSymbolicLinkObject.Call(uintptr(unsafe.Pointer(LinkHandle)), 180 | uintptr(DesiredAccess), 181 | uintptr(unsafe.Pointer(ObjectAttributes))) 182 | return NtStatus(r0) 183 | } 184 | 185 | // OUT-parameter: ReturnedLength. 186 | // INOUT-parameter: LinkTarget. 187 | // *OPT-parameter: ReturnedLength. 188 | func NtQuerySymbolicLinkObject( 189 | LinkHandle Handle, 190 | LinkTarget *UnicodeString, 191 | ReturnedLength *uint32, 192 | ) NtStatus { 193 | r0, _, _ := procNtQuerySymbolicLinkObject.Call(uintptr(LinkHandle), 194 | uintptr(unsafe.Pointer(LinkTarget)), 195 | uintptr(unsafe.Pointer(ReturnedLength))) 196 | return NtStatus(r0) 197 | } 198 | 199 | // OUT-parameter: SymbolicLinkHandle. 200 | func NtCreateSymbolicLinkObject( 201 | SymbolicLinkHandle *Handle, 202 | DesiredAccess AccessMask, 203 | ObjectAttributes *ObjectAttributes, 204 | TargetName *UnicodeString, 205 | ) NtStatus { 206 | r0, _, _ := procNtCreateSymbolicLinkObject.Call(uintptr(unsafe.Pointer(SymbolicLinkHandle)), 207 | uintptr(DesiredAccess), 208 | uintptr(unsafe.Pointer(ObjectAttributes)), 209 | uintptr(unsafe.Pointer(TargetName))) 210 | return NtStatus(r0) 211 | } 212 | 213 | // OUT-parameter: DirectoryHandle. 214 | func NtCreateDirectoryObject( 215 | DirectoryHandle *Handle, 216 | DesiredAccess AccessMask, 217 | ObjectAttributes *ObjectAttributes, 218 | ) NtStatus { 219 | r0, _, _ := procNtCreateDirectoryObject.Call(uintptr(unsafe.Pointer(DirectoryHandle)), 220 | uintptr(DesiredAccess), 221 | uintptr(unsafe.Pointer(ObjectAttributes))) 222 | return NtStatus(r0) 223 | } 224 | 225 | // OUT-parameter: DirectoryHandle. 226 | func NtCreateDirectoryObjectEx( 227 | DirectoryHandle *Handle, 228 | DesiredAccess AccessMask, 229 | ObjectAttributes *ObjectAttributes, 230 | ShadowDirectoryHandle Handle, 231 | Flags uint32, 232 | ) NtStatus { 233 | r0, _, _ := procNtCreateDirectoryObjectEx.Call(uintptr(unsafe.Pointer(DirectoryHandle)), 234 | uintptr(DesiredAccess), 235 | uintptr(unsafe.Pointer(ObjectAttributes)), 236 | uintptr(ShadowDirectoryHandle), 237 | uintptr(Flags)) 238 | return NtStatus(r0) 239 | } 240 | 241 | // OUT-parameter: ObjectInformation, ReturnLength. 242 | // *OPT-parameter: Handle, ReturnLength. 243 | func NtQueryObject( 244 | Handle Handle, 245 | ObjectInformationClass ObjectInformationClass, 246 | ObjectInformation *byte, 247 | ObjectInformationLength uint32, 248 | ReturnLength *uint32, 249 | ) NtStatus { 250 | r0, _, _ := procNtQueryObject.Call(uintptr(Handle), 251 | uintptr(ObjectInformationClass), 252 | uintptr(unsafe.Pointer(ObjectInformation)), 253 | uintptr(ObjectInformationLength), 254 | uintptr(unsafe.Pointer(ReturnLength))) 255 | return NtStatus(r0) 256 | } 257 | 258 | // OUT-parameter: TargetHandle. 259 | // *OPT-parameter: TargetProcessHandle, TargetHandle. 260 | func NtDuplicateObject( 261 | SourceProcessHandle Handle, 262 | SourceHandle Handle, 263 | TargetProcessHandle Handle, 264 | TargetHandle *Handle, 265 | DesiredAccess AccessMask, 266 | HandleAttributes uint32, 267 | Options uint32, 268 | ) NtStatus { 269 | r0, _, _ := procNtDuplicateObject.Call(uintptr(SourceProcessHandle), 270 | uintptr(SourceHandle), 271 | uintptr(TargetProcessHandle), 272 | uintptr(unsafe.Pointer(TargetHandle)), 273 | uintptr(DesiredAccess), 274 | uintptr(HandleAttributes), 275 | uintptr(Options)) 276 | return NtStatus(r0) 277 | } 278 | -------------------------------------------------------------------------------- /process.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS NtQueryInformationProcess( 9 | HANDLE ProcessHandle, 10 | PROCESS_INFORMATION_CLASS ProcessInformationClass, 11 | PVOID ProcessInformation, 12 | ULONG ProcessInformationLength, 13 | PULONG ReturnLength 14 | ); 15 | */ 16 | 17 | /* 18 | func: 19 | NTSTATUS NtOpenProcess( 20 | _Out_ PHANDLE ProcessHandle, 21 | _In_ ACCESS_MASK DesiredAccess, 22 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 23 | _In_opt_ PCLIENT_ID ClientId 24 | ); 25 | */ 26 | 27 | /* 28 | func: 29 | NTSTATUS NtOpenThread( 30 | _Out_ PHANDLE ThreadHandle, 31 | _In_ ACCESS_MASK DesiredAccess, 32 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 33 | _In_opt_ PCLIENT_ID ClientId 34 | ); 35 | */ 36 | 37 | /* 38 | enum: 39 | typedef enum _PROCESS_INFORMATION_CLASS { 40 | ProcessBasicInformation, 41 | ProcessQuotaLimits, 42 | ProcessIoCounters, 43 | ProcessVmCounters, 44 | ProcessTimes, 45 | ProcessBasePriority, 46 | ProcessRaisePriority, 47 | ProcessDebugPort, 48 | ProcessExceptionPort, 49 | ProcessAccessToken, 50 | ProcessLdtInformation, 51 | ProcessLdtSize, 52 | ProcessDefaultHardErrorMode, 53 | ProcessIoPortHandlers, 54 | ProcessPooledUsageAndLimits, 55 | ProcessWorkingSetWatch, 56 | ProcessUserModeIOPL, 57 | ProcessEnableAlignmentFaultFixup, 58 | ProcessPriorityClass, 59 | ProcessWx86Information, 60 | ProcessHandleCount, 61 | ProcessAffinityMask, 62 | ProcessPriorityBoost, 63 | ProcessDeviceMap, 64 | ProcessSessionInformation, 65 | ProcessForegroundInformation, 66 | ProcessWow64Information, 67 | ProcessImageFileName, 68 | ProcessLUIDDeviceMapsEnabled, 69 | ProcessBreakOnTermination, 70 | ProcessDebugObjectHandle, 71 | ProcessDebugFlags, 72 | ProcessHandleTracing, 73 | ProcessIoPriority, 74 | ProcessExecuteFlags, 75 | ProcessTlsInformation, 76 | ProcessCookie, 77 | ProcessImageInformation, 78 | ProcessCycleTime, 79 | ProcessPagePriority, 80 | ProcessInstrumentationCallback, 81 | ProcessThreadStackAllocation, 82 | ProcessWorkingSetWatchEx, 83 | ProcessImageFileNameWin32, 84 | ProcessImageFileMapping, 85 | ProcessAffinityUpdateMode, 86 | ProcessMemoryAllocationMode, 87 | ProcessGroupInformation, 88 | ProcessTokenVirtualizationEnabled, 89 | ProcessConsoleHostProcess, 90 | ProcessWindowInformation, 91 | ProcessHandleInformation, 92 | ProcessMitigationPolicy, 93 | ProcessDynamicFunctionTableInformation, 94 | ProcessHandleCheckingMode, 95 | ProcessKeepAliveCount, 96 | ProcessRevokeFileHandles, 97 | ProcessWorkingSetControl, 98 | ProcessHandleTable, 99 | ProcessCheckStackExtentsMode, 100 | ProcessCommandLineInformation, 101 | ProcessProtectionInformation, 102 | ProcessMemoryExhaustion, 103 | ProcessFaultInformation, 104 | ProcessTelemetryIdInformation, 105 | ProcessCommitReleaseInformation, 106 | ProcessDefaultCpuSetsInformation, 107 | ProcessAllowedCpuSetsInformation, 108 | ProcessSubsystemProcess, 109 | ProcessJobMemoryInformation, 110 | ProcessInPrivate, 111 | ProcessRaiseUMExceptionOnInvalidHandleClose, 112 | ProcessIumChallengeResponse, 113 | ProcessChildProcessInformation, 114 | ProcessHighGraphicsPriorityInformation, 115 | ProcessSubsystemInformation, 116 | ProcessEnergyValues, 117 | ProcessPowerThrottlingState, 118 | ProcessReserved3Information, 119 | ProcessWin32kSyscallFilterInformation, 120 | ProcessDisableSystemAllowedCpuSets, 121 | ProcessWakeInformation, 122 | ProcessEnergyTrackingState, 123 | ProcessManageWritesToExecutableMemory, 124 | ProcessCaptureTrustletLiveDump, 125 | ProcessTelemetryCoverage, 126 | ProcessEnclaveInformation, 127 | ProcessEnableReadWriteVmLogging, 128 | ProcessUptimeInformation, 129 | ProcessImageSection, 130 | ProcessDebugAuthInformation, 131 | ProcessSystemResourceManagement, 132 | ProcessSequenceNumber, 133 | ProcessLoaderDetour, 134 | ProcessSecurityDomainInformation, 135 | ProcessCombineSecurityDomainsInformation, 136 | ProcessEnableLogging, 137 | ProcessLeapSecondInformation, 138 | ProcessFiberShadowStackAllocation, 139 | ProcessFreeFiberShadowStackAllocation, 140 | ProcessAltSystemCallInformation, 141 | ProcessDynamicEHContinuationTargets, 142 | ProcessDynamicEnforcedCetCompatibleRanges, 143 | ProcessCreateStateChange, 144 | ProcessApplyStateChange, 145 | ProcessEnableOptionalXStateFeatures, 146 | ProcessAltPrefetchParam, 147 | ProcessAssignCpuPartitions, 148 | ProcessPriorityClassEx, 149 | ProcessMembershipInformation, 150 | ProcessEffectiveIoPriority, 151 | ProcessEffectivePagePriority, 152 | } PROCESS_INFORMATION_CLASS; 153 | */ 154 | 155 | /* 156 | type: 157 | typedef struct _PEB { 158 | BYTE Reserved1[2]; 159 | BYTE BeingDebugged; 160 | BYTE Reserved2[1]; 161 | PVOID Reserved3[2]; 162 | PPEB_LDR_DATA Ldr; 163 | PRTL_USER_PROCESS_PARAMETERS ProcessParameters; 164 | PVOID Reserved4[3]; 165 | PVOID AtlThunkSListPtr; 166 | PVOID Reserved5; 167 | ULONG Reserved6; 168 | PVOID Reserved7; 169 | ULONG Reserved8; 170 | ULONG AtlThunkSListPtr32; 171 | PVOID Reserved9[45]; 172 | BYTE Reserved10[96]; 173 | PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; 174 | BYTE Reserved11[128]; 175 | PVOID Reserved12[1]; 176 | ULONG SessionId; 177 | } PEB,*PPEB; 178 | */ 179 | 180 | /* 181 | type: 182 | typedef struct _PEB_LDR_DATA { 183 | BYTE Reserved1[8]; 184 | PVOID Reserved2[3]; 185 | LIST_ENTRY InMemoryOrderModuleList; 186 | } PEB_LDR_DATA,*PPEB_LDR_DATA; 187 | */ 188 | 189 | /* 190 | type: 191 | typedef struct _RTL_USER_PROCESS_PARAMETERS { 192 | BYTE Reserved1[16]; 193 | PVOID Reserved2[10]; 194 | UNICODE_STRING ImagePathName; 195 | UNICODE_STRING CommandLine; 196 | } RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS; 197 | */ 198 | 199 | type PsPostProcessInitRoutine struct{} // FIXME 200 | 201 | /* 202 | type: 203 | typedef struct _PROCESS_BASIC_INFORMATION 204 | { 205 | NTSTATUS ExitStatus; 206 | PPEB PebBaseAddress; 207 | ULONG_PTR AffinityMask; 208 | KPRIORITY BasePriority; 209 | HANDLE UniqueProcessId; 210 | HANDLE InheritedFromUniqueProcessId; 211 | } PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; 212 | */ 213 | 214 | /* 215 | func: 216 | NTSTATUS NtQueryInformationThread( 217 | HANDLE ThreadHandle, 218 | THREAD_INFORMATION_CLASS ThreadInformationClass, 219 | PVOID ThreadInformation, 220 | ULONG ThreadInformationLength, 221 | PULONG ReturnLength 222 | ); 223 | */ 224 | 225 | /* 226 | func: 227 | NTSTATUS NtSetInformationThread( 228 | HANDLE ThreadHandle, 229 | THREAD_INFORMATION_CLASS ThreadInformationClass, 230 | PVOID ThreadInformation, 231 | ULONG ThreadInformationLength 232 | ); 233 | */ 234 | 235 | /* 236 | func: 237 | NTSTATUS NtSetInformationProcess ( 238 | HANDLE ProcessHandle, 239 | PROCESS_INFORMATION_CLASS ProcessInformationClass, 240 | PVOID ProcessInformation, 241 | ULONG ProcessInformationLength 242 | ); 243 | */ 244 | 245 | /* 246 | enum: 247 | typedef enum _THREAD_INFORMATION_CLASS { 248 | ThreadBasicInformation, 249 | ThreadTimes, 250 | ThreadPriority, 251 | ThreadBasePriority, 252 | ThreadAffinityMask, 253 | ThreadImpersonationToken, 254 | ThreadDescriptorTableEntry, 255 | ThreadEnableAlignmentFaultFixup, 256 | ThreadEventPair_Reusable, 257 | ThreadQuerySetWin32StartAddress, 258 | ThreadZeroTlsCell, 259 | ThreadPerformanceCount, 260 | ThreadAmILastThread, 261 | ThreadIdealProcessor, 262 | ThreadPriorityBoost, 263 | ThreadSetTlsArrayAddress, 264 | ThreadIsIoPending, 265 | ThreadHideFromDebugger, 266 | ThreadBreakOnTermination, 267 | ThreadSwitchLegacyState, 268 | ThreadIsTerminated, 269 | ThreadLastSystemCall, 270 | ThreadIoPriority, 271 | ThreadCycleTime, 272 | ThreadPagePriority, 273 | ThreadActualBasePriority, 274 | ThreadTebInformation, 275 | ThreadCSwitchMon, 276 | ThreadCSwitchPmu, 277 | ThreadWow64Context, 278 | ThreadGroupInformation, 279 | ThreadUmsInformation, 280 | ThreadCounterProfiling, 281 | ThreadIdealProcessorEx, 282 | MaxThreadInfoClass 283 | } THREAD_INFORMATION_CLASS; 284 | */ 285 | 286 | /* 287 | func: 288 | NTSTATUS 289 | NtCreateProcess( 290 | _Out_ PHANDLE ProcessHandle, 291 | _In_ ACCESS_MASK DesiredAccess, 292 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, 293 | _In_ HANDLE ParentProcess, 294 | _In_ BOOLEAN InheritObjectTable, 295 | _In_opt_ HANDLE SectionHandle, 296 | _In_opt_ HANDLE DebugPort, 297 | _In_opt_ HANDLE TokenHandle 298 | ); 299 | */ 300 | 301 | /* 302 | func: 303 | NTSTATUS NtCreateProcessEx( 304 | _Out_ PHANDLE ProcessHandle, 305 | _In_ ACCESS_MASK DesiredAccess, 306 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, 307 | _In_ HANDLE ParentProcess, 308 | _In_ ULONG Flags, 309 | _In_opt_ HANDLE SectionHandle, 310 | _In_opt_ HANDLE DebugPort, 311 | _In_opt_ HANDLE ExceptionPort, 312 | _In_ BOOLEAN InJob 313 | ); 314 | */ 315 | 316 | const ( 317 | PROCESS_TERMINATE = 0x0001 318 | PROCESS_CREATE_THREAD = 0x0002 319 | PROCESS_SET_SESSIONID = 0x0004 320 | PROCESS_VM_OPERATION = 0x0008 321 | PROCESS_VM_READ = 0x0010 322 | PROCESS_VM_WRITE = 0x0020 323 | PROCESS_DUP_HANDLE = 0x0040 324 | PROCESS_CREATE_PROCESS = 0x0080 325 | PROCESS_SET_QUOTA = 0x0100 326 | PROCESS_SET_INFORMATION = 0x0200 327 | PROCESS_QUERY_INFORMATION = 0x0400 328 | PROCESS_SUSPEND_RESUME = 0x0800 329 | PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 330 | PROCESS_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xffff) 331 | ) 332 | 333 | const ( 334 | THREAD_TERMINATE = 0x0001 335 | THREAD_SUSPEND_RESUME = 0x0002 336 | THREAD_GET_CONTEXT = 0x0008 337 | THREAD_SET_CONTEXT = 0x0010 338 | THREAD_SET_INFORMATION = 0x0020 339 | THREAD_QUERY_INFORMATION = 0x0040 340 | THREAD_SET_THREAD_TOKEN = 0x0080 341 | THREAD_IMPERSONATE = 0x0100 342 | THREAD_DIRECT_IMPERSONATION = 0x0200 343 | THREAD_SET_LIMITED_INFORMATION = 0x0400 344 | THREAD_QUERY_LIMITED_INFORMATION = 0x0800 345 | ) 346 | 347 | const ( 348 | NtCurrentProcess = Handle(^uintptr(0)) 349 | NtCurrentThread = Handle(^uintptr(0) - 1) 350 | ) 351 | -------------------------------------------------------------------------------- /object.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | //go:generate -command mkcode go run mkcode.go -- 8 | //go:generate mkcode $GOFILE 9 | 10 | /* 11 | func: 12 | NTSTATUS WINAPI NtOpenDirectoryObject( 13 | _Out_ PHANDLE DirectoryHandle, 14 | _In_ ACCESS_MASK DesiredAccess, 15 | _In_ POBJECT_ATTRIBUTES ObjectAttributes 16 | ); 17 | */ 18 | 19 | /* 20 | func: 21 | NTSTATUS WINAPI NtQueryDirectoryObject( 22 | _In_ HANDLE DirectoryHandle, 23 | _Out_opt_ PVOID Buffer, 24 | _In_ ULONG Length, 25 | _In_ BOOLEAN ReturnSingleEntry, 26 | _In_ BOOLEAN RestartScan, 27 | _Inout_ PULONG Context, 28 | _Out_opt_ PULONG ReturnLength 29 | ); 30 | */ 31 | 32 | /* 33 | func: 34 | NTSTATUS WINAPI NtOpenSymbolicLinkObject( 35 | _Out_ PHANDLE LinkHandle, 36 | _In_ ACCESS_MASK DesiredAccess, 37 | _In_ POBJECT_ATTRIBUTES ObjectAttributes 38 | ); 39 | */ 40 | 41 | /* 42 | func: 43 | NTSTATUS WINAPI NtQuerySymbolicLinkObject( 44 | _In_ HANDLE LinkHandle, 45 | _Inout_ PUNICODE_STRING LinkTarget, 46 | _Out_opt_ PULONG ReturnedLength 47 | ); 48 | */ 49 | 50 | /* 51 | func: 52 | NTSTATUS WINAPI NtCreateSymbolicLinkObject ( 53 | _Out_ PHANDLE SymbolicLinkHandle, 54 | _In_ ACCESS_MASK DesiredAccess, 55 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 56 | _In_ PUNICODE_STRING TargetName 57 | ); 58 | */ 59 | 60 | /* 61 | func: 62 | NTSTATUS NtCreateDirectoryObject( 63 | _Out_ PHANDLE DirectoryHandle, 64 | _In_ ACCESS_MASK DesiredAccess, 65 | _In_ POBJECT_ATTRIBUTES ObjectAttributes 66 | ); 67 | */ 68 | 69 | /* 70 | func: 71 | NTSTATUS NtCreateDirectoryObjectEx( 72 | _Out_ PHANDLE DirectoryHandle, 73 | _In_ ACCESS_MASK DesiredAccess, 74 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 75 | _In_ HANDLE ShadowDirectoryHandle, 76 | _In_ ULONG Flags 77 | ); 78 | */ 79 | 80 | /* 81 | func: 82 | NTSTATUS NtQueryObject ( 83 | _In_opt_ HANDLE Handle, 84 | _In_ OBJECT_INFORMATION_CLASS ObjectInformationClass, 85 | _Out_ PVOID ObjectInformation, // _Out_writes_bytes_opt_(ObjectInformationLength) 86 | _In_ ULONG ObjectInformationLength, 87 | _Out_opt_ PULONG ReturnLength 88 | ); 89 | */ 90 | 91 | /* 92 | func: 93 | NTSTATUS NtDuplicateObject ( 94 | _In_ HANDLE SourceProcessHandle, 95 | _In_ HANDLE SourceHandle, 96 | _In_opt_ HANDLE TargetProcessHandle, 97 | _Out_opt_ PHANDLE TargetHandle, 98 | _In_ ACCESS_MASK DesiredAccess, 99 | _In_ ULONG HandleAttributes, 100 | _In_ ULONG Options 101 | ); 102 | */ 103 | 104 | /* 105 | type: 106 | typedef struct _OBJECT_ATTRIBUTES { 107 | ULONG Length; 108 | HANDLE RootDirectory; 109 | PUNICODE_STRING ObjectName; 110 | ULONG Attributes; 111 | PVOID SecurityDescriptor; 112 | PVOID SecurityQualityOfService; 113 | } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 114 | */ 115 | 116 | const ( 117 | OBJ_INHERIT = 0x00000002 118 | OBJ_PERMANENT = 0x00000010 119 | OBJ_EXCLUSIVE = 0x00000020 120 | OBJ_CASE_INSENSITIVE = 0x00000040 121 | OBJ_OPENIF = 0x00000080 122 | OBJ_OPENLINK = 0x00000100 123 | OBJ_KERNEL_HANDLE = 0x00000200 124 | OBJ_FORCE_ACCESS_CHECK = 0x00000400 125 | OBJ_VALID_ATTRIBUTES = 0x000007F2 126 | ) 127 | 128 | // FIXME: PVOID -> *byte or PVOID -> uintptr?a 129 | 130 | func NewObjectAttributes(objectName string, attr uint32, rootdir Handle, sd *byte) (oa *ObjectAttributes) { 131 | var s *UnicodeString 132 | if objectName != "" { 133 | s = NewUnicodeString(objectName) 134 | } 135 | oa = &ObjectAttributes{ 136 | Length: uint32(unsafe.Sizeof(*oa)), 137 | RootDirectory: rootdir, 138 | ObjectName: s, 139 | Attributes: attr, 140 | SecurityDescriptor: sd, 141 | } 142 | return 143 | } 144 | 145 | /* 146 | type: 147 | typedef struct _OBJECT_DIRECTORY_INFORMATION { 148 | UNICODE_STRING Name; 149 | UNICODE_STRING TypeName; 150 | } OBJECT_DIRECTORY_INFORMATION, *POBJECT_DIRECTORY_INFORMATION; 151 | */ 152 | 153 | /* 154 | enum: 155 | typedef enum _OBJECT_INFORMATION_CLASS { 156 | ObjectBasicInformation, 157 | ObjectNameInformation, 158 | ObjectTypeInformation, 159 | ObjectAllInformation, 160 | ObjectDataInformation 161 | } OBJECT_INFORMATION_CLASS; 162 | */ 163 | 164 | /* 165 | type: 166 | typedef struct _OBJECT_BASIC_INFORMATION { 167 | ULONG Attributes; 168 | ACCESS_MASK GrantedAccess; 169 | ULONG HandleCount; 170 | ULONG PointerCount; 171 | ULONG PagedPoolUsage; 172 | ULONG NonPagedPoolUsage; 173 | ULONG Reserved[3]; 174 | ULONG NameInformationLength; 175 | ULONG TypeInformationLength; 176 | ULONG SecurityDescriptorLength; 177 | LARGE_INTEGER CreateTime; 178 | } OBJECT_BASIC_INFORMATION, *POBJECT_BASIC_INFORMATION; 179 | */ 180 | 181 | /* 182 | type: 183 | typedef struct _OBJECT_NAME_INFORMATION { 184 | UNICODE_STRING Name; 185 | } OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; 186 | */ 187 | 188 | /* 189 | type: 190 | typedef struct _GENERIC_MAPPING { 191 | ACCESS_MASK GenericRead; 192 | ACCESS_MASK GenericWrite; 193 | ACCESS_MASK GenericExecute; 194 | ACCESS_MASK GenericAll; 195 | } GENERIC_MAPPING; 196 | */ 197 | 198 | /* 199 | type: 200 | typedef struct _OBJECT_TYPE_INFORMATION { 201 | UNICODE_STRING TypeName; 202 | ULONG TotalNumberOfObjects; 203 | ULONG TotalNumberOfHandles; 204 | ULONG TotalPagedPoolUsage; 205 | ULONG TotalNonPagedPoolUsage; 206 | ULONG TotalNamePoolUsage; 207 | ULONG TotalHandleTableUsage; 208 | ULONG HighWaterNumberOfObjects; 209 | ULONG HighWaterNumberOfHandles; 210 | ULONG HighWaterPagedPoolUsage; 211 | ULONG HighWaterNonPagedPoolUsage; 212 | ULONG HighWaterNamePoolUsage; 213 | ULONG HighWaterHandleTableUsage; 214 | ULONG InvalidAttributes; 215 | GENERIC_MAPPING GenericMapping; 216 | ULONG ValidAccessMask; 217 | BOOLEAN SecurityRequired; 218 | BOOLEAN MaintainHandleCount; 219 | UCHAR TypeIndex; 220 | CHAR ReservedByte; 221 | ULONG PoolType; 222 | ULONG DefaultPagedPoolCharge; 223 | ULONG DefaultNonPagedPoolCharge; 224 | } OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; 225 | */ 226 | 227 | /* 228 | type: 229 | typedef struct _OBJECT_ALL_INFORMATION { 230 | ULONG NumberOfObjects; 231 | OBJECT_TYPE_INFORMATION ObjectTypeInformation[1]; 232 | } OBJECT_ALL_INFORMATION, *POBJECT_ALL_INFORMATION; 233 | */ 234 | 235 | func (oi *ObjectAllInformationT) GetObjectTypeInformation() []*ObjectTypeInformationT { 236 | types := make([]*ObjectTypeInformationT, 0, int(oi.NumberOfObjects)) 237 | offset := uintptr(unsafe.Pointer(&oi.ObjectTypeInformation[0])) 238 | for i := uintptr(0); i < uintptr(oi.NumberOfObjects); i++ { 239 | current := (*ObjectTypeInformationT)(unsafe.Pointer(offset)) 240 | types = append(types, current) 241 | offset += unsafe.Sizeof(ObjectTypeInformationT{}) + uintptr(current.TypeName.MaximumLength) 242 | // padding 243 | if rest := offset % unsafe.Sizeof(uintptr(0)); rest != 0 { 244 | offset += unsafe.Sizeof(uintptr(0)) - rest 245 | } 246 | } 247 | return types 248 | } 249 | 250 | /* 251 | type: 252 | typedef struct _OBJECT_DATA_INFORMATION { 253 | BOOLEAN InheritHandle; 254 | BOOLEAN ProtectFromClose; 255 | } OBJECT_DATA_INFORMATION, *POBJECT_DATA_INFORMATION; 256 | */ 257 | 258 | // typedef DWORD ACCESS_MASK 259 | 260 | type AccessMask uint32 261 | 262 | // see winnt.h 263 | const ( 264 | DELETE AccessMask = 0x00010000 265 | READ_CONTROL = 0x00020000 266 | WRITE_DAC = 0x00040000 267 | WRITE_OWNER = 0x00080000 268 | SYNCHRONIZE = 0x00100000 269 | MAXIMUM_ALLOWED = 0x02000000 270 | 271 | STANDARD_RIGHTS_READ = 0x00020000 272 | STANDARD_RIGHTS_WRITE = READ_CONTROL 273 | STANDARD_RIGHTS_EXECUTE = READ_CONTROL 274 | STANDARD_RIGHTS_REQUIRED = 0x000F0000 275 | 276 | STANDARD_RIGHTS_ALL = 0x001F0000 277 | 278 | SPECIFIC_RIGHTS_ALL = 0x0000FFFF 279 | ACCESS_SYSTEM_SECURITY = 0x01000000 280 | 281 | DIRECTORY_QUERY = 0x00000001 282 | DIRECTORY_TRAVERSE = 0x00000002 283 | DIRECTORY_CREATE_OBJECT = 0x00000004 284 | DIRECTORY_CREATE_SUBDIRECTORY = 0x00000008 285 | DIRECTORY_ALL_ACCESS = 0x0000000f 286 | 287 | KEY_QUERY_VALUE = 0x00000001 288 | KEY_SET_VALUE = 0x00000002 289 | KEY_CREATE_SUB_KEY = 0x00000004 290 | KEY_ENUMERATE_SUB_KEYS = 0x00000008 291 | KEY_NOTIFY = 0x00000010 292 | KEY_CREATE_LINK = 0x00000020 293 | KEY_WOW64_64KEY = 0x00000100 294 | KEY_WOW64_32KEY = 0x00000200 295 | KEY_WOW64_RES = 0x00000300 296 | 297 | KEY_READ = ((STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY) &^ SYNCHRONIZE) 298 | KEY_WRITE = ((STANDARD_RIGHTS_WRITE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY) &^ SYNCHRONIZE) 299 | KEY_EXECUTE = ((KEY_READ) &^ SYNCHRONIZE) 300 | KEY_ALL_ACCESS = ((STANDARD_RIGHTS_ALL | KEY_QUERY_VALUE | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_ENUMERATE_SUB_KEYS | KEY_NOTIFY | KEY_CREATE_LINK) &^ SYNCHRONIZE) 301 | 302 | SECTION_QUERY = 0x000001 303 | SECTION_MAP_WRITE = 0x000002 304 | SECTION_MAP_READ = 0x000004 305 | SECTION_MAP_EXECUTE = 0x000008 306 | SECTION_EXTEND_SIZE = 0x000010 307 | SECTION_ALL_ACCESS = 0x0F001F 308 | 309 | PAGE_NOACCESS = 0x0001 310 | PAGE_READONLY = 0x0002 311 | PAGE_READWRITE = 0x0004 312 | PAGE_WRITECOPY = 0x0008 313 | PAGE_EXECUTE = 0x0010 314 | PAGE_EXECUTE_READ = 0x0020 315 | PAGE_EXECUTE_READWRITE = 0x0040 316 | PAGE_EXECUTE_WRITECOPY = 0x0080 317 | PAGE_GUARD = 0x0100 318 | PAGE_NOCACHE = 0x0200 319 | 320 | SEC_BASED = 0x00200000 321 | SEC_NO_CHANGE = 0x00400000 322 | SEC_FILE = 0x00800000 323 | SEC_IMAGE = 0x01000000 324 | SEC_VLM = 0x02000000 325 | SEC_RESERVE = 0x04000000 326 | SEC_COMMIT = 0x08000000 327 | SEC_NOCACHE = 0x10000000 328 | 329 | MEM_IMAGE = SEC_IMAGE 330 | MEM_COMMIT = 0x00001000 331 | MEM_RESERVE = 0x00002000 332 | MEM_DECOMMIT = 0x00004000 333 | MEM_RELEASE = 0x00008000 334 | MEM_FREE = 0x00010000 335 | MEM_PRIVATE = 0x00020000 336 | MEM_MAPPED = 0x00040000 337 | MEM_RESET = 0x00080000 338 | MEM_TOP_DOWN = 0x00100000 339 | MEM_WRITE_WATCH = 0x00200000 340 | MEM_PHYSICAL = 0x00400000 341 | MEM_ROTATE = 0x00800000 342 | MEM_DIFFERENT_IMAGE_BASE_OK = 0x00800000 343 | MEM_RESET_UNDO = 0x01000000 344 | MEM_LARGE_PAGES = 0x20000000 345 | MEM_4MB_PAGES = 0x80000000 346 | MEM_64K_PAGES = (MEM_LARGE_PAGES | MEM_PHYSICAL) 347 | ) 348 | -------------------------------------------------------------------------------- /registry.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | // undocumented NtCompactKeys 7 | // undocumented NtCompressKey 8 | 9 | /* 10 | func: 11 | NTSTATUS NtCreateKey( 12 | _Out_ PHANDLE KeyHandle, 13 | _In_ ACCESS_MASK DesiredAccess, 14 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 15 | _Reserved_ ULONG TitleIndex, 16 | _In_opt_ PUNICODE_STRING Class, 17 | _In_ ULONG CreateOptions, 18 | _Out_opt_ PULONG Disposition 19 | ); 20 | */ 21 | 22 | /* 23 | func: 24 | NTSTATUS NtCreateKeyTransacted( 25 | _Out_ PHANDLE KeyHandle, 26 | _In_ ACCESS_MASK DesiredAccess, 27 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 28 | _Reserved_ ULONG TitleIndex, 29 | _In_opt_ PUNICODE_STRING Class, 30 | _In_ ULONG CreateOptions, 31 | _In_ HANDLE TransactionHandle, 32 | _Out_opt_ PULONG Disposition 33 | ); 34 | */ 35 | 36 | /* 37 | func: 38 | NTSTATUS NtDeleteKey( 39 | _In_ HANDLE KeyHandle 40 | ); 41 | */ 42 | 43 | /* 44 | func: 45 | NTSTATUS NtDeleteValueKey( 46 | _In_ HANDLE KeyHandle, 47 | _In_ PUNICODE_STRING ValueName 48 | ); 49 | */ 50 | 51 | /* 52 | func: 53 | NTSTATUS NtEnumerateKey( 54 | _In_ HANDLE KeyHandle, 55 | _In_ ULONG Index, 56 | _In_ KEY_INFORMATION_CLASS KeyInformationClass, 57 | _Out_opt_ PVOID KeyInformation, 58 | _In_ ULONG Length, 59 | _Out_ PULONG ResultLength 60 | ); 61 | */ 62 | 63 | /* 64 | func: 65 | NTSTATUS NtEnumerateValueKey( 66 | _In_ HANDLE KeyHandle, 67 | _In_ ULONG Index, 68 | _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, 69 | _Out_opt_ PVOID KeyValueInformation, 70 | _In_ ULONG Length, 71 | _Out_ PULONG ResultLength 72 | ); 73 | */ 74 | 75 | /* 76 | func: 77 | NTSTATUS NtFlushKey( 78 | _In_ HANDLE KeyHandle 79 | ); 80 | */ 81 | 82 | // undocumented NtLoadKey 83 | // undocumented NtLoadKey2 84 | 85 | // tbd NtLockProductActivationKeys 86 | // tbd NtLockRegistryKey 87 | 88 | /* 89 | func: 90 | NTSTATUS NtNotifyChangeKey( 91 | _In_ HANDLE KeyHandle, 92 | _In_opt_ HANDLE Event, 93 | _In_opt_ PIO_APC_ROUTINE ApcRoutine, 94 | _In_opt_ PVOID ApcContext, 95 | _Out_ PIO_STATUS_BLOCK IoStatusBlock, 96 | _In_ ULONG CompletionFilter, 97 | _In_ BOOLEAN WatchTree, 98 | _Out_opt_ PVOID Buffer, 99 | _In_ ULONG BufferSize, 100 | _In_ BOOLEAN Asynchronous 101 | ); 102 | */ 103 | 104 | /* 105 | func: 106 | NTSTATUS NtNotifyChangeMultipleKeys( 107 | _In_ HANDLE MasterKeyHandle, 108 | _In_opt_ ULONG Count, 109 | _In_opt_ POBJECT_ATTRIBUTES SubordinateObjects, 110 | _In_opt_ HANDLE Event, 111 | _In_opt_ PIO_APC_ROUTINE ApcRoutine, 112 | _In_opt_ PVOID ApcContext, 113 | _Out_ PIO_STATUS_BLOCK IoStatusBlock, 114 | _In_ ULONG CompletionFilter, 115 | _In_ BOOLEAN WatchTree, 116 | _Out_opt_ PVOID Buffer, 117 | _In_ ULONG BufferSize, 118 | _In_ BOOLEAN Asynchronous 119 | ); 120 | */ 121 | 122 | /* 123 | func: 124 | NTSTATUS NtOpenKey( 125 | _Out_ PHANDLE KeyHandle, 126 | _In_ ACCESS_MASK DesiredAccess, 127 | _In_ POBJECT_ATTRIBUTES ObjectAttributes 128 | ); 129 | */ 130 | 131 | /* 132 | func: 133 | NTSTATUS NtOpenKeyTransacted( 134 | _Out_ PHANDLE KeyHandle, 135 | _In_ ACCESS_MASK DesiredAccess, 136 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 137 | _In_ HANDLE TransactionHandle 138 | ); 139 | */ 140 | 141 | /* 142 | func: 143 | NTSTATUS NtOpenKeyTransactedEx( 144 | _Out_ PHANDLE KeyHandle, 145 | _In_ ACCESS_MASK DesiredAccess, 146 | _In_ POBJECT_ATTRIBUTES ObjectAttributes, 147 | _In_ ULONG OpenOptions, 148 | _In_ HANDLE TransactionHandle 149 | ); 150 | */ 151 | 152 | /* 153 | func: 154 | NTSTATUS NtQueryKey( 155 | _In_ HANDLE KeyHandle, 156 | _In_ KEY_INFORMATION_CLASS KeyInformationClass, 157 | _Out_opt_ PVOID KeyInformation, 158 | _In_ ULONG Length, 159 | _Out_ PULONG ResultLength 160 | ); 161 | */ 162 | 163 | /* 164 | func: 165 | NTSTATUS NtQueryMultipleValueKey( 166 | _In_ HANDLE KeyHandle, 167 | _Inout_ PKEY_VALUE_ENTRY ValueEntries, 168 | _In_ ULONG EntryCount, 169 | _Out_ PVOID ValueBuffer, 170 | _Inout_ PULONG BufferLength, 171 | _Out_opt_ PULONG RequiredBufferLength 172 | ); 173 | */ 174 | 175 | // tbd NtQueryOpenSubKeys 176 | 177 | /* 178 | func: 179 | NTSTATUS NtQueryValueKey( 180 | _In_ HANDLE KeyHandle, 181 | _In_ PUNICODE_STRING ValueName, 182 | _In_ KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass, 183 | _Out_opt_ PVOID KeyValueInformation, 184 | _In_ ULONG Length, 185 | _Out_ PULONG ResultLength 186 | ); 187 | */ 188 | 189 | /* 190 | func: 191 | NTSTATUS NtRenameKey( 192 | _In_ HANDLE KeyHandle, 193 | _In_ PUNICODE_STRING NewName 194 | ); 195 | */ 196 | 197 | // undocumented NtReplaceKey 198 | // undocumented NtRestoreKey 199 | // undocumented NtSaveKey 200 | // undocumented NtSaveKeyEx 201 | 202 | // tbd NtSaveMergedKeys 203 | 204 | /* 205 | func: 206 | NTSTATUS NtSetInformationKey( 207 | _In_ HANDLE KeyHandle, 208 | _In_ KEY_SET_INFORMATION_CLASS KeySetInformationClass, 209 | _In_ PVOID KeySetInformation, 210 | _In_ ULONG KeySetInformationLength 211 | ); 212 | */ 213 | 214 | /* 215 | func: 216 | NTSTATUS NtSetValueKey( 217 | _In_ HANDLE KeyHandle, 218 | _In_ PUNICODE_STRING ValueName, 219 | _In_opt_ ULONG TitleIndex, 220 | _In_ ULONG Type, 221 | _In_opt_ PVOID Data, 222 | _In_ ULONG DataSize 223 | ); 224 | */ 225 | 226 | // undocumented NtUnloadKey2 227 | // undocumented NtUnloadKeyEx 228 | 229 | /* 230 | type: 231 | typedef struct _KEY_VALUE_ENTRY { 232 | PUNICODE_STRING ValueName; 233 | ULONG DataLength; 234 | ULONG DataOffset; 235 | ULONG Type; 236 | } KEY_VALUE_ENTRY, *PKEY_VALUE_ENTRY; 237 | */ 238 | 239 | /* ------------------------------------------------------------ */ 240 | 241 | /* 242 | enum: 243 | typedef enum _KEY_INFORMATION_CLASS { 244 | KeyBasicInformation = 0, 245 | KeyNodeInformation = 1, 246 | KeyFullInformation = 2, 247 | KeyNameInformation = 3, 248 | KeyCachedInformation = 4, 249 | KeyFlagsInformation = 5, 250 | KeyVirtualizationInformation = 6, 251 | KeyHandleTagsInformation = 7, 252 | MaxKeyInfoClass = 8 253 | } KEY_INFORMATION_CLASS; 254 | */ 255 | 256 | /* 257 | type: 258 | typedef struct _KEY_BASIC_INFORMATION { 259 | LARGE_INTEGER LastWriteTime; 260 | ULONG TitleIndex; 261 | ULONG NameLength; 262 | WCHAR Name[1]; 263 | } KEY_BASIC_INFORMATION, *PKEY_BASIC_INFORMATION; 264 | */ 265 | 266 | /* 267 | type: 268 | typedef struct _KEY_NODE_INFORMATION { 269 | LARGE_INTEGER LastWriteTime; 270 | ULONG TitleIndex; 271 | ULONG ClassOffset; 272 | ULONG ClassLength; 273 | ULONG NameLength; 274 | WCHAR Name[1]; 275 | } KEY_NODE_INFORMATION, *PKEY_NODE_INFORMATION; 276 | */ 277 | 278 | /* 279 | type: 280 | typedef struct _KEY_FULL_INFORMATION { 281 | LARGE_INTEGER LastWriteTime; 282 | ULONG TitleIndex; 283 | ULONG ClassOffset; 284 | ULONG ClassLength; 285 | ULONG SubKeys; 286 | ULONG MaxNameLen; 287 | ULONG MaxClassLen; 288 | ULONG Values; 289 | ULONG MaxValueNameLen; 290 | ULONG MaxValueDataLen; 291 | WCHAR Class[1]; 292 | } KEY_FULL_INFORMATION, *PKEY_FULL_INFORMATION; 293 | */ 294 | 295 | /* 296 | type: 297 | typedef struct _KEY_NAME_INFORMATION { 298 | ULONG NameLength; 299 | WCHAR Name[1]; 300 | } KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION; 301 | */ 302 | 303 | /* 304 | type: 305 | typedef struct _KEY_CACHED_INFORMATION { 306 | LARGE_INTEGER LastWriteTime; 307 | ULONG TitleIndex; 308 | ULONG SubKeys; 309 | ULONG MaxNameLen; 310 | ULONG Values; 311 | ULONG MaxValueNameLen; 312 | ULONG MaxValueDataLen; 313 | ULONG NameLength; 314 | } KEY_CACHED_INFORMATION, *PKEY_CACHED_INFORMATION; 315 | */ 316 | 317 | /* 318 | //type: 319 | typedef struct _KEY_VIRTUALIZATION_INFORMATION { 320 | ULONG VirtualizationCandidate :1; 321 | ULONG VirtualizationEnabled :1; 322 | ULONG VirtualTarget :1; 323 | ULONG VirtualStore :1; 324 | ULONG VirtualSource :1; 325 | ULONG Reserved :27; 326 | } KEY_VIRTUALIZATION_INFORMATION, *PKEY_VIRTUALIZATION_INFORMATION; 327 | */ 328 | 329 | /* ------------------------------------------------------------ */ 330 | 331 | /* 332 | enum: 333 | typedef enum _KEY_VALUE_INFORMATION_CLASS { 334 | KeyValueBasicInformation = 0, 335 | KeyValueFullInformation, 336 | KeyValuePartialInformation, 337 | KeyValueFullInformationAlign64, 338 | KeyValuePartialInformationAlign64, 339 | MaxKeyValueInfoClass 340 | } KEY_VALUE_INFORMATION_CLASS; 341 | */ 342 | 343 | /* 344 | type: 345 | typedef struct _KEY_VALUE_BASIC_INFORMATION { 346 | ULONG TitleIndex; 347 | ULONG Type; 348 | ULONG NameLength; 349 | WCHAR Name[1]; 350 | } KEY_VALUE_BASIC_INFORMATION, *PKEY_VALUE_BASIC_INFORMATION; 351 | */ 352 | 353 | /* 354 | type: 355 | typedef struct _KEY_VALUE_FULL_INFORMATION { 356 | ULONG TitleIndex; 357 | ULONG Type; 358 | ULONG DataOffset; 359 | ULONG DataLength; 360 | ULONG NameLength; 361 | WCHAR Name[1]; 362 | } KEY_VALUE_FULL_INFORMATION, *PKEY_VALUE_FULL_INFORMATION; 363 | */ 364 | 365 | /* 366 | type: 367 | typedef struct _KEY_VALUE_PARTIAL_INFORMATION { 368 | ULONG TitleIndex; 369 | ULONG Type; 370 | ULONG DataLength; 371 | UCHAR Data[1]; 372 | } KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION; 373 | */ 374 | 375 | /* ------------------------------------------------------------ */ 376 | 377 | /* 378 | enum: 379 | typedef enum _KEY_SET_INFORMATION_CLASS { 380 | KeyWriteTimeInformation, 381 | KeyWow64FlagsInformation, 382 | KeyControlFlagsInformation, 383 | KeySetVirtualizationInformation, 384 | KeySetDebugInformation, 385 | KeySetHandleTagsInformation, 386 | MaxKeySetInfoClass 387 | } KEY_SET_INFORMATION_CLASS; 388 | */ 389 | -------------------------------------------------------------------------------- /systeminformation.go: -------------------------------------------------------------------------------- 1 | //go:generate -command mkcode go run mkcode.go -- 2 | //go:generate mkcode $GOFILE 3 | 4 | // Information taken from 5 | // - http://www.ntinternals.net/: UserMode / NTDLL / System Information 6 | // - http://www.geoffchappell.com/studies/windows/km/index.htm 7 | // - MinGW headers 8 | 9 | package ntdll 10 | 11 | /* 12 | func: 13 | NTSTATUS NtQuerySystemInformation( 14 | _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 15 | _Out_ PVOID SystemInformation, 16 | _In_ ULONG SystemInformationLength, 17 | _Out_ PULONG ReturnLength 18 | ); 19 | */ 20 | 21 | /* 22 | func: 23 | NTSTATUS NtSetSystemInformation( 24 | _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, 25 | _In_ PVOID SystemInformation, 26 | _In_ ULONG SystemInformationLength 27 | ); 28 | */ 29 | 30 | /* 31 | enum: 32 | typedef enum _SYSTEM_INFORMATION_CLASS { 33 | SystemBasicInformation, 34 | SystemProcessorInformation, 35 | SystemPerformanceInformation, 36 | SystemTimeOfDayInformation, 37 | SystemPathInformation, 38 | SystemProcessInformation, 39 | SystemCallCountInformation, 40 | SystemDeviceInformation, 41 | SystemProcessorPerformanceInformation, 42 | SystemFlagsInformation, 43 | SystemCallTimeInformation, 44 | SystemModuleInformation, 45 | SystemLocksInformation, 46 | SystemStackTraceInformation, 47 | SystemPagedPoolInformation, 48 | SystemNonPagedPoolInformation, 49 | SystemHandleInformation, 50 | SystemObjectInformation, 51 | SystemPageFileInformation, 52 | SystemVdmInstemulInformation, 53 | SystemVdmBopInformation, 54 | SystemFileCacheInformation, 55 | SystemPoolTagInformation, 56 | SystemInterruptInformation, 57 | SystemDpcBehaviorInformation, 58 | SystemFullMemoryInformation, 59 | SystemLoadGdiDriverInformation, 60 | SystemUnloadGdiDriverInformation, 61 | SystemTimeAdjustmentInformation, 62 | SystemSummaryMemoryInformation, 63 | SystemNextEventIdInformation, 64 | SystemEventIdsInformation, 65 | SystemCrashDumpInformation, 66 | SystemExceptionInformation, 67 | SystemCrashDumpStateInformation, 68 | SystemKernelDebuggerInformation, 69 | SystemContextSwitchInformation, 70 | SystemRegistryQuotaInformation, 71 | SystemExtendServiceTableInformation, 72 | SystemPrioritySeperation, 73 | SystemPlugPlayBusInformation, 74 | SystemDockInformation, 75 | SystemPowerInformation, 76 | SystemProcessorSpeedInformation, 77 | SystemCurrentTimeZoneInformation, 78 | SystemLookasideInformation 79 | } SYSTEM_INFORMATION_CLASS, *PSYSTEM_INFORMATION_CLASS; 80 | */ 81 | 82 | /* 83 | type: 84 | typedef struct _SYSTEM_MODULE { 85 | PVOID Section; 86 | PVOID MappedBase; 87 | PVOID ImageBase; 88 | ULONG ImageSize; 89 | ULONG Flags; 90 | WORD LoadOrderIndex; 91 | WORD InitOrderIndex; 92 | WORD LoadCount; 93 | WORD NameOffset; 94 | BYTE Name[256]; 95 | } SYSTEM_MODULE, *PSYSTEM_MODULE; 96 | */ 97 | 98 | /* 99 | type: 100 | typedef struct _SYSTEM_BASIC_INFORMATION { 101 | BYTE Reserved1[4]; 102 | ULONG MaximumIncrement; 103 | ULONG PhysicalPageSize; 104 | ULONG NumberOfPhysicalPages; 105 | ULONG LowestPhysicalPage; 106 | ULONG HighestPhysicalPage; 107 | ULONG AllocationGranularity; 108 | ULONG_PTR LowestUserAddress; 109 | ULONG_PTR HighestUserAddress; 110 | ULONG_PTR ActiveProcessors; 111 | CCHAR NumberOfProcessors; 112 | } SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION; 113 | */ 114 | 115 | /* 116 | type: 117 | typedef struct _SYSTEM_PROCESSOR_INFORMATION { 118 | USHORT ProcessorArchitecture; 119 | USHORT ProcessorLevel; 120 | USHORT ProcessorRevision; 121 | USHORT Unknown; 122 | ULONG FeatureBits; 123 | } SYSTEM_PROCESSOR_INFORMATION, *PSYSTEM_PROCESSOR_INFORMATION; 124 | */ 125 | 126 | /* 127 | type: 128 | typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { 129 | LARGE_INTEGER IdleTime; 130 | LARGE_INTEGER KernelTime; 131 | LARGE_INTEGER UserTime; 132 | LARGE_INTEGER Reserved1[2]; 133 | ULONG Reserved2; 134 | } SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; 135 | */ 136 | 137 | /* 138 | type: 139 | typedef struct _IO_COUNTERS { 140 | ULONGLONG ReadOperationCount; 141 | ULONGLONG WriteOperationCount; 142 | ULONGLONG OtherOperationCount; 143 | ULONGLONG ReadTransferCount; 144 | ULONGLONG WriteTransferCount; 145 | ULONGLONG OtherTransferCount; 146 | } IO_COUNTERS, *PIO_COUNTERS; 147 | */ 148 | 149 | /* 150 | type: 151 | typedef struct _VM_COUNTERS { 152 | SIZE_T PeakVirtualSize; 153 | SIZE_T VirtualSize; 154 | ULONG PageFaultCount; 155 | SIZE_T PeakWorkingSetSize; 156 | SIZE_T WorkingSetSize; 157 | SIZE_T QuotaPeakPagedPoolUsage; 158 | SIZE_T QuotaPagedPoolUsage; 159 | SIZE_T QuotaPeakNonPagedPoolUsage; 160 | SIZE_T QuotaNonPagedPoolUsage; 161 | SIZE_T PagefileUsage; 162 | SIZE_T PeakPagefileUsage; 163 | } VM_COUNTERS, *PVM_COUNTERS; 164 | */ 165 | 166 | /* 167 | type: 168 | typedef struct _SYSTEM_PROCESS_INFORMATION { 169 | ULONG NextEntryOffset; 170 | ULONG NumberOfThreads; 171 | LARGE_INTEGER Reserved[3]; 172 | LARGE_INTEGER CreateTime; 173 | LARGE_INTEGER UserTime; 174 | LARGE_INTEGER KernelTime; 175 | UNICODE_STRING ImageName; 176 | KPRIORITY BasePriority; 177 | HANDLE UniqueProcessId; 178 | HANDLE InheritedFromUniqueProcessId; 179 | ULONG HandleCount; 180 | ULONG SessionId; 181 | ULONG PageDirectoryBase; 182 | VM_COUNTERS VirtualMemoryCounters; 183 | SIZE_T PrivatePageCount; 184 | IO_COUNTERS IoCounters; 185 | } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION; 186 | */ 187 | 188 | type Kpriority uint64 189 | 190 | /* 191 | type: 192 | typedef struct _CLIENT_ID { 193 | HANDLE UniqueProcess; 194 | HANDLE UniqueThread; 195 | } CLIENT_ID, *PCLIENT_ID; 196 | */ 197 | 198 | /* 199 | type: 200 | typedef struct _SYSTEM_THREAD_INFORMATION { 201 | LARGE_INTEGER Reserved1[3]; 202 | ULONG Reserved2; 203 | PVOID StartAddress; 204 | CLIENT_ID ClientId; 205 | KPRIORITY Priority; 206 | LONG BasePriority; 207 | ULONG Reserved3; 208 | ULONG ThreadState; 209 | ULONG WaitReason; 210 | } SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; 211 | */ 212 | 213 | /* 214 | type: 215 | typedef struct _SYSTEM_REGISTRY_QUOTA_INFORMATION { 216 | ULONG RegistryQuotaAllowed; 217 | ULONG RegistryQuotaUsed; 218 | PVOID Reserved1; 219 | } SYSTEM_REGISTRY_QUOTA_INFORMATION, *PSYSTEM_REGISTRY_QUOTA_INFORMATION; 220 | */ 221 | 222 | /* 223 | type: 224 | typedef struct _SYSTEM_TIMEOFDAY_INFORMATION { 225 | LARGE_INTEGER BootTime; 226 | LARGE_INTEGER CurrentTime; 227 | LARGE_INTEGER TimeZoneBias; 228 | ULONG CurrentTimeZoneId; 229 | BYTE Reserved1[20]; 230 | } SYSTEM_TIMEOFDAY_INFORMATION,*PSYSTEM_TIMEOFDAY_INFORMATION; 231 | */ 232 | 233 | /* 234 | type: 235 | typedef struct _SYSTEM_PERFORMANCE_INFORMATION { 236 | LARGE_INTEGER IdleTime; 237 | LARGE_INTEGER ReadTransferCount; 238 | LARGE_INTEGER WriteTransferCount; 239 | LARGE_INTEGER OtherTransferCount; 240 | ULONG ReadOperationCount; 241 | ULONG WriteOperationCount; 242 | ULONG OtherOperationCount; 243 | ULONG AvailablePages; 244 | ULONG TotalCommittedPages; 245 | ULONG TotalCommitLimit; 246 | ULONG PeakCommitment; 247 | ULONG PageFaults; 248 | ULONG WriteCopyFaults; 249 | ULONG TransitionFaults; 250 | ULONG CacheTransitionFaults; 251 | ULONG DemandZeroFaults; 252 | ULONG PagesRead; 253 | ULONG PageReadIos; 254 | ULONG CacheReads; 255 | ULONG CacheIos; 256 | ULONG PagefilePagesWritten; 257 | ULONG PagefilePageWriteIos; 258 | ULONG MappedFilePagesWritten; 259 | ULONG MappedFilePageWriteIos; 260 | ULONG PagedPoolUsage; 261 | ULONG NonPagedPoolUsage; 262 | ULONG PagedPoolAllocs; 263 | ULONG PagedPoolFrees; 264 | ULONG NonPagedPoolAllocs; 265 | ULONG NonPagedPoolFrees; 266 | ULONG TotalFreeSystemPtes; 267 | ULONG SystemCodePage; 268 | ULONG TotalSystemDriverPages; 269 | ULONG TotalSystemCodePages; 270 | ULONG SmallNonPagedLookasideListAllocateHits; 271 | ULONG SmallPagedLookasideListAllocateHits; 272 | ULONG Reserved3; 273 | ULONG MmSystemCachePage; 274 | ULONG PagedPoolPage; 275 | ULONG SystemDriverPage; 276 | ULONG FastReadNoWait; 277 | ULONG FastReadWait; 278 | ULONG FastReadResourceMiss; 279 | ULONG FastReadNotPossible; 280 | ULONG FastMdlReadNoWait; 281 | ULONG FastMdlReadWait; 282 | ULONG FastMdlReadResourceMiss; 283 | ULONG FastMdlReadNotPossible; 284 | ULONG MapDataNoWait; 285 | ULONG MapDataWait; 286 | ULONG MapDataNoWaitMiss; 287 | ULONG MapDataWaitMiss; 288 | ULONG PinMappedDataCount; 289 | ULONG PinReadNoWait; 290 | ULONG PinReadWait; 291 | ULONG PinReadNoWaitMiss; 292 | ULONG PinReadWaitMiss; 293 | ULONG CopyReadNoWait; 294 | ULONG CopyReadWait; 295 | ULONG CopyReadNoWaitMiss; 296 | ULONG CopyReadWaitMiss; 297 | ULONG MdlReadNoWait; 298 | ULONG MdlReadWait; 299 | ULONG MdlReadNoWaitMiss; 300 | ULONG MdlReadWaitMiss; 301 | ULONG ReadAheadIos; 302 | ULONG LazyWriteIos; 303 | ULONG LazyWritePages; 304 | ULONG DataFlushes; 305 | ULONG DataPages; 306 | ULONG ContextSwitches; 307 | ULONG FirstLevelTbFills; 308 | ULONG SecondLevelTbFills; 309 | ULONG SystemCalls; 310 | } SYSTEM_PERFORMANCE_INFORMATION, *PSYSTEM_PERFORMANCE_INFORMATION; 311 | */ 312 | 313 | /* 314 | type: 315 | typedef struct _SYSTEM_EXCEPTION_INFORMATION { 316 | BYTE Reserved1[16]; 317 | } SYSTEM_EXCEPTION_INFORMATION, *PSYSTEM_EXCEPTION_INFORMATION; 318 | */ 319 | 320 | /* 321 | type: 322 | typedef struct _SYSTEM_LOOKASIDE_INFORMATION { 323 | BYTE Reserved1[32]; 324 | } SYSTEM_LOOKASIDE_INFORMATION, *PSYSTEM_LOOKASIDE_INFORMATION; 325 | */ 326 | 327 | /* 328 | type: 329 | typedef struct _SYSTEM_INTERRUPT_INFORMATION { 330 | BYTE Reserved1[24]; 331 | } SYSTEM_INTERRUPT_INFORMATION, *PSYSTEM_INTERRUPT_INFORMATION; 332 | */ 333 | 334 | /* 335 | type: 336 | typedef struct _SYSTEM_POLICY_INFORMATION { 337 | PVOID Reserved1[2]; 338 | ULONG Reserved2[3]; 339 | } SYSTEM_POLICY_INFORMATION, *PSYSTEM_POLICY_INFORMATION; 340 | */ 341 | 342 | /* 343 | type: 344 | typedef struct _SYSTEM_HANDLE_ENTRY { 345 | ULONG OwnerPid; 346 | BYTE ObjectType; 347 | BYTE HandleFlags; 348 | USHORT HandleValue; 349 | PVOID ObjectPointer; 350 | ULONG AccessMask; 351 | } SYSTEM_HANDLE_ENTRY, *PSYSTEM_HANDLE_ENTRY; 352 | */ 353 | 354 | /* 355 | type: 356 | typedef struct _SYSTEM_HANDLE_INFORMATION { 357 | ULONG Count; 358 | SYSTEM_HANDLE_ENTRY Handles[1]; 359 | } SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; 360 | */ 361 | 362 | func (mi *SystemHandleInformationT) GetHandles() []SystemHandleEntry { 363 | return mi.HandlesSlice(int(mi.Count)) 364 | } 365 | 366 | /* 367 | type: 368 | typedef struct _SYSTEM_PAGEFILE_INFORMATION { 369 | ULONG NextEntryOffset; 370 | ULONG CurrentSize; 371 | ULONG TotalUsed; 372 | ULONG PeakUsed; 373 | UNICODE_STRING FileName; 374 | } SYSTEM_PAGEFILE_INFORMATION, *PSYSTEM_PAGEFILE_INFORMATION; 375 | */ 376 | 377 | /* 378 | type: 379 | typedef struct _SYSTEM_MODULE_INFORMATION { 380 | ULONG ModulesCount; 381 | SYSTEM_MODULE Modules[ANYSIZE_ARRAY]; 382 | } SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION; 383 | */ 384 | 385 | func (mi *SystemModuleInformationT) GetModules() []SystemModule { 386 | return mi.ModulesSlice(int(mi.ModulesCount)) 387 | } 388 | -------------------------------------------------------------------------------- /memory.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | //go:generate -command mkcode go run mkcode.go -- 4 | //go:generate mkcode $GOFILE 5 | 6 | /* 7 | func: 8 | NTSTATUS NtAllocateVirtualMemory( 9 | _In_ HANDLE ProcessHandle, 10 | _Inout_ PVOID *BaseAddress, 11 | _In_ ULONG_PTR ZeroBits, 12 | _Inout_ PSIZE_T RegionSize, 13 | _In_ ULONG AllocationType, 14 | _In_ ULONG Protect 15 | ); 16 | */ 17 | 18 | /* 19 | func: 20 | NTSTATUS NtFreeVirtualMemory( 21 | _In_ HANDLE ProcessHandle, 22 | _Inout_ PVOID *BaseAddress, 23 | _Inout_ PSIZE_T RegionSize, 24 | _In_ ULONG FreeType 25 | ); 26 | */ 27 | 28 | /* 29 | func: 30 | NTSTATUS NtReadVirtualMemory( 31 | _In_ HANDLE ProcessHandle, 32 | _In_opt_ PVOID BaseAddress, 33 | _Out_ PVOID Buffer, 34 | _In_ SIZE_T BufferSize, 35 | _Out_opt_ PSIZE_T NumberOfBytesRead 36 | ); 37 | */ 38 | 39 | /* 40 | func: 41 | NTSTATUS NtWriteVirtualMemory( 42 | _In_ HANDLE ProcessHandle, 43 | _In_opt_ PVOID BaseAddress, 44 | _In_ PVOID Buffer, 45 | _In_ SIZE_T BufferSize, 46 | _Out_opt_ PSIZE_T NumberOfBytesWritten 47 | ); 48 | */ 49 | 50 | /* 51 | func: 52 | NTSTATUS NtProtectVirtualMemory( 53 | _In_ HANDLE ProcessHandle, 54 | _Inout_ PVOID *BaseAddress, 55 | _Inout_ PSIZE_T RegionSize, 56 | _In_ ULONG NewProtect, 57 | _Out_ PULONG OldProtect 58 | ); 59 | */ 60 | 61 | /* 62 | func: 63 | NTSTATUS NtQueryVirtualMemory( 64 | _In_ HANDLE ProcessHandle, 65 | _In_opt_ PVOID BaseAddress, 66 | _In_ MEMORY_INFORMATION_CLASS MemoryInformationClass, 67 | _Out_ PVOID MemoryInformation, 68 | _In_ SIZE_T MemoryInformationLength, 69 | _Out_opt_ PSIZE_T ReturnLength 70 | ); 71 | */ 72 | 73 | /* 74 | func: 75 | NTSTATUS NtFlushVirtualMemory( 76 | _In_ HANDLE ProcessHandle, 77 | _Inout_ PVOID *BaseAddress, 78 | _Inout_ PSIZE_T RegionSize, 79 | _Out_ PIO_STATUS_BLOCK IoStatus 80 | ); 81 | */ 82 | 83 | /* 84 | enum: 85 | typedef enum _MEMORY_INFORMATION_CLASS 86 | { 87 | MemoryBasicInformation, 88 | MemoryWorkingSetInformation, 89 | MemoryMappedFilenameInformation, 90 | MemoryRegionInformation, 91 | MemoryWorkingSetExInformation, 92 | MemorySharedCommitInformation, 93 | MemoryImageInformation, 94 | MemoryRegionInformationEx, 95 | MemoryPrivilegedBasicInformation, 96 | MemoryEnclaveImageInformation, 97 | MemoryBasicInformationCapped, 98 | MemoryPhysicalContiguityInformation, 99 | } MEMORY_INFORMATION_CLASS; 100 | */ 101 | 102 | /* 103 | type: 104 | typedef struct _MEMORY_BASIC_INFORMATION { 105 | PVOID BaseAddress; 106 | PVOID AllocationBase; 107 | ULONG AllocationProtect; 108 | USHORT PartitionId; 109 | SIZE_T RegionSize; 110 | ULONG State; 111 | ULONG Protect; 112 | ULONG Type; 113 | } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION; 114 | */ 115 | 116 | /* 117 | type: 118 | typedef struct _MEMORY_BASIC_INFORMATION32 { 119 | DWORD BaseAddress; 120 | DWORD AllocationBase; 121 | DWORD AllocationProtect; 122 | DWORD RegionSize; 123 | DWORD State; 124 | DWORD Protect; 125 | DWORD Type; 126 | } MEMORY_BASIC_INFORMATION32, *PMEMORY_BASIC_INFORMATION32; 127 | */ 128 | 129 | /* 130 | type: 131 | typedef struct _MEMORY_BASIC_INFORMATION64 { 132 | ULONGLONG BaseAddress; 133 | ULONGLONG AllocationBase; 134 | DWORD AllocationProtect; 135 | DWORD __alignment1; 136 | ULONGLONG RegionSize; 137 | DWORD State; 138 | DWORD Protect; 139 | DWORD Type; 140 | DWORD __alignment2; 141 | } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64; 142 | */ 143 | 144 | /* 145 | type: 146 | typedef struct _MEMORY_WORKING_SET_INFORMATION 147 | { 148 | ULONG_PTR NumberOfEntries; 149 | MEMORY_WORKING_SET_BLOCK WorkingSetInfo[1]; 150 | } MEMORY_WORKING_SET_INFORMATION, *PMEMORY_WORKING_SET_INFORMATION; 151 | */ 152 | 153 | /* 154 | NOTE: type contains unions -- define below. 155 | 156 | typedef struct _MEMORY_WORKING_SET_BLOCK 157 | { 158 | ULONG_PTR Protection : 5; 159 | ULONG_PTR ShareCount : 3; 160 | ULONG_PTR Shared : 1; 161 | ULONG_PTR Node : 3; 162 | #ifdef _WIN64 163 | ULONG_PTR VirtualPage : 52; 164 | #else 165 | ULONG VirtualPage : 20; 166 | #endif 167 | } MEMORY_WORKING_SET_BLOCK, *PMEMORY_WORKING_SET_BLOCK; 168 | */ 169 | 170 | type MemoryWorkingSetBlock uintptr 171 | 172 | func (b MemoryWorkingSetBlock) Protection() uintptr { 173 | return uintptr(b) & 31 174 | } 175 | 176 | func (b MemoryWorkingSetBlock) ShareCount() uintptr { 177 | return (uintptr(b) >> 5) & 7 178 | } 179 | 180 | func (b MemoryWorkingSetBlock) Shared() bool { 181 | return (b>>8)&1 != 0 182 | } 183 | 184 | func (b MemoryWorkingSetBlock) Node() uintptr { 185 | return (uintptr(b) >> 9) & 7 186 | } 187 | 188 | func (b MemoryWorkingSetBlock) VirtualPage() uintptr { 189 | return uintptr(b) >> 12 190 | } 191 | 192 | /* 193 | NOTE: type contains unions -- define below. 194 | 195 | typedef struct _MEMORY_REGION_INFORMATION 196 | { 197 | PVOID AllocationBase; 198 | ULONG AllocationProtect; 199 | union 200 | { 201 | ULONG RegionType; 202 | struct 203 | { 204 | ULONG Private : 1; 205 | ULONG MappedDataFile : 1; 206 | ULONG MappedImage : 1; 207 | ULONG MappedPageFile : 1; 208 | ULONG MappedPhysical : 1; 209 | ULONG DirectMapped : 1; 210 | ULONG SoftwareEnclave : 1; // REDSTONE3 211 | ULONG PageSize64K : 1; 212 | ULONG PlaceholderReservation : 1; // REDSTONE4 213 | ULONG MappedAwe : 1; // 21H1 214 | ULONG MappedWriteWatch : 1; 215 | ULONG PageSizeLarge : 1; 216 | ULONG PageSizeHuge : 1; 217 | ULONG Reserved : 19; 218 | }; 219 | }; 220 | SIZE_T RegionSize; 221 | SIZE_T CommitSize; 222 | ULONG_PTR PartitionId; // 19H1 223 | ULONG_PTR NodePreference; // 20H1 224 | } MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; 225 | */ 226 | 227 | /* 228 | type: 229 | typedef struct _MEMORY_REGION_INFORMATION 230 | { 231 | PVOID AllocationBase; 232 | ULONG AllocationProtect; 233 | ULONG RegionType; 234 | SIZE_T RegionSize; 235 | SIZE_T CommitSize; 236 | ULONG_PTR PartitionId; 237 | ULONG_PTR NodePreference; 238 | } MEMORY_REGION_INFORMATION, *PMEMORY_REGION_INFORMATION; 239 | */ 240 | 241 | func (i *MemoryRegionInformationT) Private() bool { 242 | return i.RegionType&1 != 0 243 | } 244 | 245 | func (i *MemoryRegionInformationT) MappedDataFile() bool { 246 | return (i.RegionType>>1)&1 != 0 247 | } 248 | 249 | func (i *MemoryRegionInformationT) MappedImage() bool { 250 | return (i.RegionType>>2)&1 != 0 251 | } 252 | 253 | func (i *MemoryRegionInformationT) MappedPageFile() bool { 254 | return (i.RegionType>>3)&1 != 0 255 | } 256 | 257 | func (i *MemoryRegionInformationT) MappedPhysical() bool { 258 | return (i.RegionType>>4)&1 != 0 259 | } 260 | 261 | func (i *MemoryRegionInformationT) DirectMapped() bool { 262 | return (i.RegionType>>5)&1 != 0 263 | } 264 | 265 | func (i *MemoryRegionInformationT) SoftwareEnclave() bool { 266 | return (i.RegionType>>6)&1 != 0 267 | } 268 | 269 | func (i *MemoryRegionInformationT) PageSize64K() bool { 270 | return (i.RegionType>>7)&1 != 0 271 | } 272 | 273 | func (i *MemoryRegionInformationT) PlaceholderReservation() bool { 274 | return (i.RegionType>>8)&1 != 0 275 | } 276 | 277 | func (i *MemoryRegionInformationT) MappedAwe() bool { 278 | return (i.RegionType>>9)&1 != 0 279 | } 280 | 281 | func (i *MemoryRegionInformationT) MappedWriteWatch() bool { 282 | return (i.RegionType>>10)&1 != 0 283 | } 284 | 285 | func (i *MemoryRegionInformationT) PageSizeLarge() bool { 286 | return (i.RegionType>>11)&1 != 0 287 | } 288 | 289 | func (i *MemoryRegionInformationT) PageSizeHuge() bool { 290 | return (i.RegionType>>12)&1 != 0 291 | } 292 | 293 | /* 294 | type: 295 | typedef struct _MEMORY_WORKING_SET_EX_INFORMATION 296 | { 297 | PVOID VirtualAddress; 298 | MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes; 299 | } MEMORY_WORKING_SET_EX_INFORMATION, *PMEMORY_WORKING_SET_EX_INFORMATION; 300 | */ 301 | 302 | /* 303 | NOTE: type contains unions -- define below. 304 | 305 | typedef struct _MEMORY_WORKING_SET_EX_BLOCK 306 | { 307 | union 308 | { 309 | struct 310 | { 311 | ULONG_PTR Valid : 1; 312 | ULONG_PTR ShareCount : 3; 313 | ULONG_PTR Win32Protection : 11; 314 | ULONG_PTR Shared : 1; 315 | ULONG_PTR Node : 6; 316 | ULONG_PTR Locked : 1; 317 | ULONG_PTR LargePage : 1; 318 | ULONG_PTR Priority : 3; 319 | ULONG_PTR Reserved : 3; 320 | ULONG_PTR SharedOriginal : 1; 321 | ULONG_PTR Bad : 1; 322 | #ifdef _WIN64 323 | ULONG_PTR ReservedUlong : 32; 324 | #endif 325 | }; 326 | struct 327 | { 328 | ULONG_PTR Valid : 1; 329 | ULONG_PTR Reserved0 : 14; 330 | ULONG_PTR Shared : 1; 331 | ULONG_PTR Reserved1 : 5; 332 | ULONG_PTR PageTable : 1; 333 | ULONG_PTR Location : 2; 334 | ULONG_PTR Priority : 3; 335 | ULONG_PTR ModifiedList : 1; 336 | ULONG_PTR Reserved2 : 2; 337 | ULONG_PTR SharedOriginal : 1; 338 | ULONG_PTR Bad : 1; 339 | #ifdef _WIN64 340 | ULONG_PTR ReservedUlong : 32; 341 | #endif 342 | } Invalid; 343 | }; 344 | } MEMORY_WORKING_SET_EX_BLOCK, *PMEMORY_WORKING_SET_EX_BLOCK; 345 | */ 346 | 347 | type MemoryWorkingSetExBlock uintptr 348 | 349 | func (b MemoryWorkingSetExBlock) Valid() bool { 350 | return b&1 != 0 351 | } 352 | 353 | func (b MemoryWorkingSetExBlock) ShareCount() uintptr { 354 | return (uintptr(b) >> 1) & ((1 << 3) - 1) 355 | } 356 | 357 | func (b MemoryWorkingSetExBlock) Win32Protection() uintptr { 358 | return (uintptr(b) >> 4) & ((1 << 11) - 1) 359 | } 360 | 361 | func (b MemoryWorkingSetExBlock) Shared() bool { 362 | return b&(1<<15) != 0 363 | } 364 | 365 | func (b MemoryWorkingSetExBlock) Node() uintptr { 366 | return (uintptr(b) >> 16) & ((1 << 6) - 1) 367 | } 368 | 369 | func (b MemoryWorkingSetExBlock) Locked() bool { 370 | return b&(1<<15) != 0 371 | } 372 | 373 | func (b MemoryWorkingSetExBlock) LargePage() bool { 374 | return b&(1<<16) != 0 375 | } 376 | 377 | func (b MemoryWorkingSetExBlock) Priority() uintptr { 378 | return (uintptr(b) >> 24) & ((1 << 3) - 1) 379 | } 380 | 381 | func (b MemoryWorkingSetExBlock) SharedOriginal() bool { 382 | return b&(1<<30) != 0 383 | } 384 | 385 | func (b MemoryWorkingSetExBlock) Bad() bool { 386 | return b&(1<<31) != 0 387 | } 388 | 389 | /* 390 | type: 391 | typedef struct _MEMORY_SHARED_COMMIT_INFORMATION 392 | { 393 | SIZE_T CommitSize; 394 | } MEMORY_SHARED_COMMIT_INFORMATION, *PMEMORY_SHARED_COMMIT_INFORMATION; 395 | */ 396 | 397 | /* 398 | NOTE: type contains unions -- define below. 399 | 400 | typedef struct _MEMORY_IMAGE_INFORMATION 401 | { 402 | PVOID ImageBase; 403 | SIZE_T SizeOfImage; 404 | union 405 | { 406 | ULONG ImageFlags; 407 | struct 408 | { 409 | ULONG ImagePartialMap : 1; 410 | ULONG ImageNotExecutable : 1; 411 | ULONG ImageSigningLevel : 4; // REDSTONE3 412 | ULONG Reserved : 26; 413 | }; 414 | }; 415 | } MEMORY_IMAGE_INFORMATION, *PMEMORY_IMAGE_INFORMATION; 416 | */ 417 | 418 | /* 419 | type: 420 | typedef struct _MEMORY_IMAGE_INFORMATION 421 | { 422 | PVOID ImageBase; 423 | SIZE_T SizeOfImage; 424 | ULONG ImageFlags; 425 | } MEMORY_IMAGE_INFORMATION, *PMEMORY_IMAGE_INFORMATION; 426 | */ 427 | 428 | func (i MemoryImageInformationT) PartialMap() bool { 429 | return i.ImageFlags&1 != 0 430 | } 431 | 432 | func (i MemoryImageInformationT) NotExecutable() bool { 433 | return (i.ImageFlags>>1)&1 != 0 434 | } 435 | 436 | func (i MemoryImageInformationT) SigningLevel() uintptr { 437 | return (uintptr(i.ImageFlags) >> 2) & 15 438 | } 439 | -------------------------------------------------------------------------------- /token.go: -------------------------------------------------------------------------------- 1 | package ntdll 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | //go:generate -command mkcode go run mkcode.go -- 8 | //go:generate mkcode $GOFILE 9 | 10 | /* 11 | func: 12 | NTSTATUS 13 | NtOpenThreadToken( 14 | _In_ HANDLE ThreadHandle, 15 | _In_ ACCESS_MASK DesiredAccess, 16 | _In_ BOOLEAN OpenAsSelf, 17 | _Out_ PHANDLE TokenHandle 18 | ); 19 | */ 20 | 21 | /* 22 | func: 23 | NTSTATUS 24 | NtOpenThreadTokenEx( 25 | _In_ HANDLE ThreadHandle, 26 | _In_ ACCESS_MASK DesiredAccess, 27 | _In_ BOOLEAN OpenAsSelf, 28 | _In_ ULONG HandleAttributes, 29 | _Out_ PHANDLE TokenHandle 30 | ); 31 | */ 32 | 33 | /* 34 | func: 35 | NTSTATUS 36 | NtOpenProcessToken( 37 | _In_ HANDLE ProcessHandle, 38 | _In_ ACCESS_MASK DesiredAccess, 39 | _Out_ PHANDLE TokenHandle 40 | ); 41 | */ 42 | 43 | /* 44 | func: 45 | NTSTATUS 46 | NtOpenProcessTokenEx( 47 | _In_ HANDLE ProcessHandle, 48 | _In_ ACCESS_MASK DesiredAccess, 49 | _In_ ULONG HandleAttributes, 50 | _Out_ PHANDLE TokenHandle 51 | ); 52 | */ 53 | 54 | /* 55 | func: 56 | NTSTATUS 57 | NtOpenJobObjectToken( 58 | _In_ HANDLE JobHandle, 59 | _In_ ACCESS_MASK DesiredAccess, 60 | _Out_ PHANDLE TokenHandle 61 | ); 62 | */ 63 | 64 | /* 65 | func: 66 | NTSTATUS 67 | NtDuplicateToken( 68 | _In_ HANDLE ExistingTokenHandle, 69 | _In_ ACCESS_MASK DesiredAccess, 70 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, 71 | _In_ BOOLEAN EffectiveOnly, 72 | _In_ TOKEN_TYPE TokenType, 73 | _Out_ PHANDLE NewTokenHandle 74 | ); 75 | */ 76 | 77 | /* 78 | func: 79 | NTSTATUS 80 | NtFilterToken ( 81 | _In_ HANDLE ExistingTokenHandle, 82 | _In_ ULONG Flags, 83 | _In_opt_ PTOKEN_GROUPS SidsToDisable, 84 | _In_opt_ PTOKEN_PRIVILEGES PrivilegesToDelete, 85 | _In_opt_ PTOKEN_GROUPS RestrictedSids, 86 | _Out_ PHANDLE NewTokenHandle 87 | ); 88 | */ 89 | 90 | /* 91 | func: 92 | NTSTATUS 93 | NtImpersonateAnonymousToken( 94 | _In_ HANDLE ThreadHandle 95 | ); 96 | */ 97 | 98 | /* 99 | func: 100 | NTSTATUS 101 | NtQueryInformationToken ( 102 | _In_ HANDLE TokenHandle, 103 | _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, 104 | _Out_ PVOID TokenInformation, // writes_bytes_to_opt_(TokenInformationLength, *ReturnLength) 105 | _In_ ULONG TokenInformationLength, 106 | _Out_ PULONG ReturnLength 107 | ); 108 | */ 109 | 110 | /* 111 | func: 112 | NTSTATUS 113 | NtSetInformationToken ( 114 | _In_ HANDLE TokenHandle, 115 | _In_ TOKEN_INFORMATION_CLASS TokenInformationClass, 116 | _In_ PVOID TokenInformation, // reads_bytes_(TokenInformationLength) 117 | _In_ ULONG TokenInformationLength 118 | ); 119 | */ 120 | 121 | /* 122 | func: 123 | NTSTATUS 124 | NtAdjustPrivilegesToken ( 125 | _In_ HANDLE TokenHandle, 126 | _In_ BOOLEAN DisableAllPrivileges, 127 | _In_opt_ PTOKEN_PRIVILEGES NewState, 128 | _In_ ULONG BufferLength, 129 | _Out_ PTOKEN_PRIVILEGES PreviousState, // writes_bytes_to_opt_(BufferLength, *ReturnLength) 130 | _Out_ PULONG ReturnLength // _When_(PreviousState == NULL, _Out_opt_) 131 | ); 132 | */ 133 | 134 | /* 135 | func: 136 | NTSTATUS 137 | NtAdjustGroupsToken ( 138 | _In_ HANDLE TokenHandle, 139 | _In_ BOOLEAN ResetToDefault, 140 | _In_opt_ PTOKEN_GROUPS NewState, 141 | _In_opt_ ULONG BufferLength, 142 | _Out_ PTOKEN_GROUPS PreviousState, // writes_bytes_to_opt_(BufferLength, *ReturnLength) 143 | _Out_ PULONG ReturnLength 144 | ); 145 | */ 146 | 147 | /* 148 | enum: 149 | typedef enum _TOKEN_TYPE { 150 | TokenPrimary = 1, 151 | TokenImpersonation 152 | } TOKEN_TYPE *PTOKEN_TYPE; 153 | */ 154 | 155 | /* 156 | type: 157 | typedef struct _TOKEN_USER { 158 | SID_AND_ATTRIBUTES User; 159 | } TOKEN_USER, *PTOKEN_USER; 160 | */ 161 | 162 | /* 163 | type: 164 | typedef struct _TOKEN_GROUPS { 165 | ULONG GroupCount; 166 | SID_AND_ATTRIBUTES Groups[ANYSIZE_ARRAY]; 167 | } TOKEN_GROUPS, *PTOKEN_GROUPS; 168 | */ 169 | 170 | func (tg *TokenGroupsT) GetGroups() []SidAndAttributes { 171 | return tg.GroupsSlice(int(tg.GroupCount)) 172 | } 173 | 174 | /* 175 | type: 176 | typedef struct _TOKEN_PRIVILEGES { 177 | ULONG PrivilegeCount; 178 | LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; 179 | } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; 180 | */ 181 | 182 | func (tp *TokenPrivilegesT) GetPrivileges() []LuidAndAttributes { 183 | return tp.PrivilegesSlice(int(tp.PrivilegeCount)) 184 | } 185 | 186 | func (tp *TokenPrivilegesT) SetPrivileges(ps []LuidAndAttributes) { 187 | tp.PrivilegeCount = uint32(len(ps)) 188 | tp.SetPrivilegesSlice(ps) 189 | return 190 | } 191 | 192 | /* 193 | type: 194 | typedef struct _TOKEN_OWNER { 195 | PSID Owner; 196 | } TOKEN_OWNER, *PTOKEN_OWNER; 197 | */ 198 | 199 | /* 200 | type: 201 | typedef struct _TOKEN_PRIMARY_GROUP { 202 | PSID PrimaryGroup; 203 | } TOKEN_PRIMARY_GROUP, *PTOKEN_PRIMARY_GROUP; 204 | */ 205 | 206 | /* 207 | type: 208 | typedef struct _TOKEN_DEFAULT_DACL { 209 | PACL DefaultDacl; 210 | } TOKEN_DEFAULT_DACL, *PTOKEN_DEFAULT_DACL; 211 | */ 212 | 213 | type ClaimsBlob [8]byte 214 | 215 | /* 216 | type: 217 | typedef struct _TOKEN_USER_CLAIMS { 218 | PCLAIMS_BLOB UserClaims; 219 | } TOKEN_USER_CLAIMS, *PTOKEN_USER_CLAIMS; 220 | */ 221 | 222 | /* 223 | type: 224 | typedef struct _TOKEN_DEVICE_CLAIMS { 225 | PCLAIMS_BLOB DeviceClaims; 226 | } TOKEN_DEVICE_CLAIMS, *PTOKEN_DEVICE_CLAIMS; 227 | */ 228 | 229 | /* 230 | type: 231 | typedef struct _TOKEN_GROUPS_AND_PRIVILEGES { 232 | ULONG SidCount; 233 | ULONG SidLength; 234 | PSID_AND_ATTRIBUTES Sids; 235 | ULONG RestrictedSidCount; 236 | ULONG RestrictedSidLength; 237 | PSID_AND_ATTRIBUTES RestrictedSids; 238 | ULONG PrivilegeCount; 239 | ULONG PrivilegeLength; 240 | PLUID_AND_ATTRIBUTES Privileges; 241 | LUID AuthenticationId; 242 | } TOKEN_GROUPS_AND_PRIVILEGES, *PTOKEN_GROUPS_AND_PRIVILEGES; 243 | */ 244 | 245 | /* 246 | type: 247 | typedef struct _TOKEN_LINKED_TOKEN { 248 | HANDLE LinkedToken; 249 | } TOKEN_LINKED_TOKEN, *PTOKEN_LINKED_TOKEN; 250 | */ 251 | 252 | /* 253 | type: 254 | typedef struct _TOKEN_ELEVATION { 255 | ULONG TokenIsElevated; 256 | } TOKEN_ELEVATION, *PTOKEN_ELEVATION; 257 | */ 258 | 259 | /* 260 | type: 261 | typedef struct _TOKEN_MANDATORY_LABEL { 262 | SID_AND_ATTRIBUTES Label; 263 | } TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL; 264 | */ 265 | 266 | /* 267 | type: 268 | typedef struct _TOKEN_MANDATORY_POLICY { 269 | ULONG Policy; 270 | } TOKEN_MANDATORY_POLICY, *PTOKEN_MANDATORY_POLICY; 271 | */ 272 | 273 | /* 274 | type: 275 | typedef struct _TOKEN_ACCESS_INFORMATION { 276 | PSID_AND_ATTRIBUTES_HASH SidHash; 277 | PSID_AND_ATTRIBUTES_HASH RestrictedSidHash; 278 | PTOKEN_PRIVILEGES Privileges; 279 | LUID AuthenticationId; 280 | TOKEN_TYPE TokenType; 281 | SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 282 | TOKEN_MANDATORY_POLICY MandatoryPolicy; 283 | ULONG Flags; 284 | ULONG AppContainerNumber; 285 | PSID PackageSid; 286 | PSID_AND_ATTRIBUTES_HASH CapabilitiesHash; 287 | PSID TrustLevelSid; 288 | PSECURITY_ATTRIBUTES_OPAQUE SecurityAttributes; 289 | } TOKEN_ACCESS_INFORMATION, *PTOKEN_ACCESS_INFORMATION; 290 | */ 291 | 292 | /* 293 | type: 294 | typedef struct _TOKEN_AUDIT_POLICY { 295 | UCHAR PerUserPolicy[30]; // ((POLICY_AUDIT_SUBCATEGORY_COUNT) >> 1) + 1] 296 | } TOKEN_AUDIT_POLICY, *PTOKEN_AUDIT_POLICY; 297 | */ 298 | 299 | /* 300 | type: 301 | typedef struct _TOKEN_SOURCE { 302 | CHAR SourceName[8]; // TOKEN_SOURCE_LENGTH 303 | LUID SourceIdentifier; 304 | } TOKEN_SOURCE, *PTOKEN_SOURCE; 305 | */ 306 | 307 | /* 308 | type: 309 | typedef struct _TOKEN_STATISTICS { 310 | LUID TokenId; 311 | LUID AuthenticationId; 312 | LARGE_INTEGER ExpirationTime; 313 | TOKEN_TYPE TokenType; 314 | SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; 315 | ULONG DynamicCharged; 316 | ULONG DynamicAvailable; 317 | ULONG GroupCount; 318 | ULONG PrivilegeCount; 319 | LUID ModifiedId; 320 | } TOKEN_STATISTICS, *PTOKEN_STATISTICS; 321 | */ 322 | 323 | /* 324 | type: 325 | typedef struct _TOKEN_CONTROL { 326 | LUID TokenId; 327 | LUID AuthenticationId; 328 | LUID ModifiedId; 329 | TOKEN_SOURCE TokenSource; 330 | } TOKEN_CONTROL, *PTOKEN_CONTROL; 331 | */ 332 | 333 | /* 334 | type: 335 | typedef struct _TOKEN_ORIGIN { 336 | LUID OriginatingLogonSession; 337 | } TOKEN_ORIGIN, * PTOKEN_ORIGIN ; 338 | */ 339 | 340 | /* 341 | type: 342 | typedef struct _TOKEN_APPCONTAINER_INFORMATION { 343 | PSID TokenAppContainer; 344 | } TOKEN_APPCONTAINER_INFORMATION, *PTOKEN_APPCONTAINER_INFORMATION; 345 | */ 346 | 347 | /* 348 | type: 349 | typedef struct _TOKEN_SID_INFORMATION { 350 | PSID Sid; 351 | } TOKEN_SID_INFORMATION, *PTOKEN_SID_INFORMATION; 352 | */ 353 | 354 | /* 355 | enum: 356 | typedef enum _TOKEN_INFORMATION_CLASS { 357 | TokenUser = 1, 358 | TokenGroups, 359 | TokenPrivileges, 360 | TokenOwner, 361 | TokenPrimaryGroup, 362 | TokenDefaultDacl, 363 | TokenSource, 364 | TokenType, 365 | TokenImpersonationLevel, 366 | TokenStatistics, 367 | TokenRestrictedSids, 368 | TokenSessionId, 369 | TokenGroupsAndPrivileges, 370 | TokenSessionReference, 371 | TokenSandBoxInert, 372 | TokenAuditPolicy, 373 | TokenOrigin, 374 | TokenElevationType, 375 | TokenLinkedToken, 376 | TokenElevation, 377 | TokenHasRestrictions, 378 | TokenAccessInformation, 379 | TokenVirtualizationAllowed, 380 | TokenVirtualizationEnabled, 381 | TokenIntegrityLevel, 382 | TokenUIAccess, 383 | TokenMandatoryPolicy, 384 | TokenLogonSid, 385 | TokenIsAppContainer, 386 | TokenCapabilities, 387 | TokenAppContainerSid, 388 | TokenAppContainerNumber, 389 | TokenUserClaimAttributes, 390 | TokenDeviceClaimAttributes, 391 | TokenRestrictedUserClaimAttributes, 392 | TokenRestrictedDeviceClaimAttributes, 393 | TokenDeviceGroups, 394 | TokenRestrictedDeviceGroups, 395 | TokenSecurityAttributes, 396 | TokenIsRestricted, 397 | TokenProcessTrustLevel, 398 | TokenPrivateNameSpace, 399 | TokenSingletonAttributes, 400 | MaxTokenInfoClass // MaxTokenInfoClass should always be the last enum 401 | } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS; 402 | */ 403 | 404 | /* 405 | type: 406 | typedef struct _LUID { 407 | DWORD LowPart; 408 | LONG HighPart; 409 | } LUID,*PLUID; 410 | */ 411 | 412 | /* 413 | type: 414 | typedef struct _LUID_AND_ATTRIBUTES { 415 | LUID Luid; 416 | DWORD Attributes; 417 | } LUID_AND_ATTRIBUTES,*PLUID_AND_ATTRIBUTES; 418 | */ 419 | 420 | /* 421 | type: 422 | typedef struct _SID_AND_ATTRIBUTES { 423 | PSID Sid; 424 | DWORD Attributes; 425 | } SID_AND_ATTRIBUTES,*PSID_AND_ATTRIBUTES; 426 | */ 427 | 428 | /* 429 | type: 430 | typedef struct _SID_AND_ATTRIBUTES_HASH { 431 | ULONG SidCount; 432 | PSID_AND_ATTRIBUTES SidAttr; 433 | SID_HASH_ENTRY Hash[32]; // SID_HASH_SIZE 434 | } SID_AND_ATTRIBUTES_HASH, *PSID_AND_ATTRIBUTES_HASH; 435 | */ 436 | 437 | type SidHashEntry *uint64 438 | 439 | type SecurityAttributesOpaque unsafe.Pointer 440 | 441 | /* 442 | enum: 443 | typedef enum _SECURITY_IMPERSONATION_LEVEL { 444 | SecurityAnonymous, 445 | SecurityIdentification, 446 | SecurityImpersonation, 447 | SecurityDelegation 448 | } SECURITY_IMPERSONATION_LEVEL, * PSECURITY_IMPERSONATION_LEVEL; 449 | */ 450 | 451 | const ( 452 | TOKEN_ASSIGN_PRIMARY = 0x0001 453 | TOKEN_DUPLICATE = 0x0002 454 | TOKEN_IMPERSONATE = 0x0004 455 | TOKEN_QUERY = 0x0008 456 | TOKEN_QUERY_SOURCE = 0x0010 457 | TOKEN_ADJUST_PRIVILEGES = 0x0020 458 | TOKEN_ADJUST_GROUPS = 0x0040 459 | TOKEN_ADJUST_DEFAULT = 0x0080 460 | TOKEN_ADJUST_SESSIONID = 0x0100 461 | ) 462 | 463 | const ( 464 | SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x00000001 465 | SE_PRIVILEGE_ENABLED = 0x00000002 466 | SE_PRIVILEGE_REMOVED = 0x00000004 467 | SE_PRIVILEGE_USED_FOR_ACCESS = 0x80000000 468 | ) 469 | -------------------------------------------------------------------------------- /systeminformation_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- systeminformation.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | import "reflect" 8 | 9 | // The SystemInformationClass constants have been derived from the SYSTEM_INFORMATION_CLASS enum definition. 10 | type SystemInformationClass uint32 11 | 12 | const ( 13 | SystemBasicInformation SystemInformationClass = 0 14 | SystemProcessorInformation = 1 15 | SystemPerformanceInformation = 2 16 | SystemTimeOfDayInformation = 3 17 | SystemPathInformation = 4 18 | SystemProcessInformation = 5 19 | SystemCallCountInformation = 6 20 | SystemDeviceInformation = 7 21 | SystemProcessorPerformanceInformation = 8 22 | SystemFlagsInformation = 9 23 | SystemCallTimeInformation = 10 24 | SystemModuleInformation = 11 25 | SystemLocksInformation = 12 26 | SystemStackTraceInformation = 13 27 | SystemPagedPoolInformation = 14 28 | SystemNonPagedPoolInformation = 15 29 | SystemHandleInformation = 16 30 | SystemObjectInformation = 17 31 | SystemPageFileInformation = 18 32 | SystemVdmInstemulInformation = 19 33 | SystemVdmBopInformation = 20 34 | SystemFileCacheInformation = 21 35 | SystemPoolTagInformation = 22 36 | SystemInterruptInformation = 23 37 | SystemDpcBehaviorInformation = 24 38 | SystemFullMemoryInformation = 25 39 | SystemLoadGdiDriverInformation = 26 40 | SystemUnloadGdiDriverInformation = 27 41 | SystemTimeAdjustmentInformation = 28 42 | SystemSummaryMemoryInformation = 29 43 | SystemNextEventIdInformation = 30 44 | SystemEventIdsInformation = 31 45 | SystemCrashDumpInformation = 32 46 | SystemExceptionInformation = 33 47 | SystemCrashDumpStateInformation = 34 48 | SystemKernelDebuggerInformation = 35 49 | SystemContextSwitchInformation = 36 50 | SystemRegistryQuotaInformation = 37 51 | SystemExtendServiceTableInformation = 38 52 | SystemPrioritySeperation = 39 53 | SystemPlugPlayBusInformation = 40 54 | SystemDockInformation = 41 55 | SystemPowerInformation = 42 56 | SystemProcessorSpeedInformation = 43 57 | SystemCurrentTimeZoneInformation = 44 58 | SystemLookasideInformation = 45 59 | ) 60 | 61 | var ( 62 | procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation") 63 | procNtSetSystemInformation = modntdll.NewProc("NtSetSystemInformation") 64 | ) 65 | 66 | // SystemModule has been derived from the SYSTEM_MODULE struct definition. 67 | type SystemModule struct { 68 | Section *byte 69 | MappedBase *byte 70 | ImageBase *byte 71 | ImageSize uint32 72 | Flags uint32 73 | LoadOrderIndex uint16 74 | InitOrderIndex uint16 75 | LoadCount uint16 76 | NameOffset uint16 77 | Name [256]byte 78 | } 79 | 80 | // SystemBasicInformationT has been derived from the SYSTEM_BASIC_INFORMATION struct definition. 81 | type SystemBasicInformationT struct { 82 | Reserved1 [4]byte 83 | MaximumIncrement uint32 84 | PhysicalPageSize uint32 85 | NumberOfPhysicalPages uint32 86 | LowestPhysicalPage uint32 87 | HighestPhysicalPage uint32 88 | AllocationGranularity uint32 89 | LowestUserAddress *uint32 90 | HighestUserAddress *uint32 91 | ActiveProcessors *uint32 92 | NumberOfProcessors byte 93 | } 94 | 95 | // SystemProcessorInformationT has been derived from the SYSTEM_PROCESSOR_INFORMATION struct definition. 96 | type SystemProcessorInformationT struct { 97 | ProcessorArchitecture uint16 98 | ProcessorLevel uint16 99 | ProcessorRevision uint16 100 | Unknown uint16 101 | FeatureBits uint32 102 | } 103 | 104 | // SystemProcessorPerformanceInformationT has been derived from the SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION struct definition. 105 | type SystemProcessorPerformanceInformationT struct { 106 | IdleTime int64 107 | KernelTime int64 108 | UserTime int64 109 | Reserved1 [2]int64 110 | Reserved2 uint32 111 | } 112 | 113 | // IoCounters has been derived from the IO_COUNTERS struct definition. 114 | type IoCounters struct { 115 | ReadOperationCount uint64 116 | WriteOperationCount uint64 117 | OtherOperationCount uint64 118 | ReadTransferCount uint64 119 | WriteTransferCount uint64 120 | OtherTransferCount uint64 121 | } 122 | 123 | // VmCounters has been derived from the VM_COUNTERS struct definition. 124 | type VmCounters struct { 125 | PeakVirtualSize uintptr 126 | VirtualSize uintptr 127 | PageFaultCount uint32 128 | PeakWorkingSetSize uintptr 129 | WorkingSetSize uintptr 130 | QuotaPeakPagedPoolUsage uintptr 131 | QuotaPagedPoolUsage uintptr 132 | QuotaPeakNonPagedPoolUsage uintptr 133 | QuotaNonPagedPoolUsage uintptr 134 | PagefileUsage uintptr 135 | PeakPagefileUsage uintptr 136 | } 137 | 138 | // SystemProcessInformationT has been derived from the SYSTEM_PROCESS_INFORMATION struct definition. 139 | type SystemProcessInformationT struct { 140 | NextEntryOffset uint32 141 | NumberOfThreads uint32 142 | Reserved [3]int64 143 | CreateTime int64 144 | UserTime int64 145 | KernelTime int64 146 | ImageName UnicodeString 147 | BasePriority Kpriority 148 | UniqueProcessId Handle 149 | InheritedFromUniqueProcessId Handle 150 | HandleCount uint32 151 | SessionId uint32 152 | PageDirectoryBase uint32 153 | VirtualMemoryCounters VmCounters 154 | PrivatePageCount uintptr 155 | IoCounters IoCounters 156 | } 157 | 158 | // ClientId has been derived from the CLIENT_ID struct definition. 159 | type ClientId struct { 160 | UniqueProcess Handle 161 | UniqueThread Handle 162 | } 163 | 164 | // SystemThreadInformationT has been derived from the SYSTEM_THREAD_INFORMATION struct definition. 165 | type SystemThreadInformationT struct { 166 | Reserved1 [3]int64 167 | Reserved2 uint32 168 | StartAddress *byte 169 | ClientId ClientId 170 | Priority Kpriority 171 | BasePriority int32 172 | Reserved3 uint32 173 | ThreadState uint32 174 | WaitReason uint32 175 | } 176 | 177 | // SystemRegistryQuotaInformationT has been derived from the SYSTEM_REGISTRY_QUOTA_INFORMATION struct definition. 178 | type SystemRegistryQuotaInformationT struct { 179 | RegistryQuotaAllowed uint32 180 | RegistryQuotaUsed uint32 181 | Reserved1 *byte 182 | } 183 | 184 | // SystemTimeofdayInformationT has been derived from the SYSTEM_TIMEOFDAY_INFORMATION struct definition. 185 | type SystemTimeofdayInformationT struct { 186 | BootTime int64 187 | CurrentTime int64 188 | TimeZoneBias int64 189 | CurrentTimeZoneId uint32 190 | Reserved1 [20]byte 191 | } 192 | 193 | // SystemPerformanceInformationT has been derived from the SYSTEM_PERFORMANCE_INFORMATION struct definition. 194 | type SystemPerformanceInformationT struct { 195 | IdleTime int64 196 | ReadTransferCount int64 197 | WriteTransferCount int64 198 | OtherTransferCount int64 199 | ReadOperationCount uint32 200 | WriteOperationCount uint32 201 | OtherOperationCount uint32 202 | AvailablePages uint32 203 | TotalCommittedPages uint32 204 | TotalCommitLimit uint32 205 | PeakCommitment uint32 206 | PageFaults uint32 207 | WriteCopyFaults uint32 208 | TransitionFaults uint32 209 | CacheTransitionFaults uint32 210 | DemandZeroFaults uint32 211 | PagesRead uint32 212 | PageReadIos uint32 213 | CacheReads uint32 214 | CacheIos uint32 215 | PagefilePagesWritten uint32 216 | PagefilePageWriteIos uint32 217 | MappedFilePagesWritten uint32 218 | MappedFilePageWriteIos uint32 219 | PagedPoolUsage uint32 220 | NonPagedPoolUsage uint32 221 | PagedPoolAllocs uint32 222 | PagedPoolFrees uint32 223 | NonPagedPoolAllocs uint32 224 | NonPagedPoolFrees uint32 225 | TotalFreeSystemPtes uint32 226 | SystemCodePage uint32 227 | TotalSystemDriverPages uint32 228 | TotalSystemCodePages uint32 229 | SmallNonPagedLookasideListAllocateHits uint32 230 | SmallPagedLookasideListAllocateHits uint32 231 | Reserved3 uint32 232 | MmSystemCachePage uint32 233 | PagedPoolPage uint32 234 | SystemDriverPage uint32 235 | FastReadNoWait uint32 236 | FastReadWait uint32 237 | FastReadResourceMiss uint32 238 | FastReadNotPossible uint32 239 | FastMdlReadNoWait uint32 240 | FastMdlReadWait uint32 241 | FastMdlReadResourceMiss uint32 242 | FastMdlReadNotPossible uint32 243 | MapDataNoWait uint32 244 | MapDataWait uint32 245 | MapDataNoWaitMiss uint32 246 | MapDataWaitMiss uint32 247 | PinMappedDataCount uint32 248 | PinReadNoWait uint32 249 | PinReadWait uint32 250 | PinReadNoWaitMiss uint32 251 | PinReadWaitMiss uint32 252 | CopyReadNoWait uint32 253 | CopyReadWait uint32 254 | CopyReadNoWaitMiss uint32 255 | CopyReadWaitMiss uint32 256 | MdlReadNoWait uint32 257 | MdlReadWait uint32 258 | MdlReadNoWaitMiss uint32 259 | MdlReadWaitMiss uint32 260 | ReadAheadIos uint32 261 | LazyWriteIos uint32 262 | LazyWritePages uint32 263 | DataFlushes uint32 264 | DataPages uint32 265 | ContextSwitches uint32 266 | FirstLevelTbFills uint32 267 | SecondLevelTbFills uint32 268 | SystemCalls uint32 269 | } 270 | 271 | // SystemExceptionInformationT has been derived from the SYSTEM_EXCEPTION_INFORMATION struct definition. 272 | type SystemExceptionInformationT struct { 273 | Reserved1 [16]byte 274 | } 275 | 276 | // SystemLookasideInformationT has been derived from the SYSTEM_LOOKASIDE_INFORMATION struct definition. 277 | type SystemLookasideInformationT struct { 278 | Reserved1 [32]byte 279 | } 280 | 281 | // SystemInterruptInformationT has been derived from the SYSTEM_INTERRUPT_INFORMATION struct definition. 282 | type SystemInterruptInformationT struct { 283 | Reserved1 [24]byte 284 | } 285 | 286 | // SystemPolicyInformationT has been derived from the SYSTEM_POLICY_INFORMATION struct definition. 287 | type SystemPolicyInformationT struct { 288 | Reserved1 [2]*byte 289 | Reserved2 [3]uint32 290 | } 291 | 292 | // SystemHandleEntry has been derived from the SYSTEM_HANDLE_ENTRY struct definition. 293 | type SystemHandleEntry struct { 294 | OwnerPid uint32 295 | ObjectType byte 296 | HandleFlags byte 297 | HandleValue uint16 298 | ObjectPointer *byte 299 | AccessMask uint32 300 | } 301 | 302 | // SystemHandleInformationT has been derived from the SYSTEM_HANDLE_INFORMATION struct definition. 303 | type SystemHandleInformationT struct { 304 | Count uint32 305 | Handles [1]SystemHandleEntry 306 | } 307 | 308 | // HandlesSlice returns a slice over the elements of SystemHandleInformationT.Handles. 309 | // 310 | // Beware: The data is not copied out of SystemHandleInformationT. The size can usually be taken from an other member of the struct (SystemHandleInformationT). 311 | func (t *SystemHandleInformationT) HandlesSlice(size int) []SystemHandleEntry { 312 | s := []SystemHandleEntry{} 313 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 314 | hdr.Data = uintptr(unsafe.Pointer(&t.Handles[0])) 315 | hdr.Len = size 316 | hdr.Cap = size 317 | return s 318 | } 319 | 320 | // SetHandlesSlice copies s into the memory at SystemHandleInformationT.Handles. 321 | // 322 | // Beware: No bounds check is performed. Another member of the struct (SystemHandleInformationT) usually has to be set to the array size. 323 | func (t *SystemHandleInformationT) SetHandlesSlice(s []SystemHandleEntry) { 324 | s1 := []SystemHandleEntry{} 325 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 326 | hdr.Data = uintptr(unsafe.Pointer(&t.Handles[0])) 327 | hdr.Len = len(s) 328 | hdr.Cap = len(s) 329 | copy(s1, s) 330 | } 331 | 332 | // SystemPagefileInformationT has been derived from the SYSTEM_PAGEFILE_INFORMATION struct definition. 333 | type SystemPagefileInformationT struct { 334 | NextEntryOffset uint32 335 | CurrentSize uint32 336 | TotalUsed uint32 337 | PeakUsed uint32 338 | FileName UnicodeString 339 | } 340 | 341 | // SystemModuleInformationT has been derived from the SYSTEM_MODULE_INFORMATION struct definition. 342 | type SystemModuleInformationT struct { 343 | ModulesCount uint32 344 | Modules [1]SystemModule 345 | } 346 | 347 | // ModulesSlice returns a slice over the elements of SystemModuleInformationT.Modules. 348 | // 349 | // Beware: The data is not copied out of SystemModuleInformationT. The size can usually be taken from an other member of the struct (SystemModuleInformationT). 350 | func (t *SystemModuleInformationT) ModulesSlice(size int) []SystemModule { 351 | s := []SystemModule{} 352 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 353 | hdr.Data = uintptr(unsafe.Pointer(&t.Modules[0])) 354 | hdr.Len = size 355 | hdr.Cap = size 356 | return s 357 | } 358 | 359 | // SetModulesSlice copies s into the memory at SystemModuleInformationT.Modules. 360 | // 361 | // Beware: No bounds check is performed. Another member of the struct (SystemModuleInformationT) usually has to be set to the array size. 362 | func (t *SystemModuleInformationT) SetModulesSlice(s []SystemModule) { 363 | s1 := []SystemModule{} 364 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 365 | hdr.Data = uintptr(unsafe.Pointer(&t.Modules[0])) 366 | hdr.Len = len(s) 367 | hdr.Cap = len(s) 368 | copy(s1, s) 369 | } 370 | 371 | // OUT-parameter: SystemInformation, ReturnLength. 372 | func NtQuerySystemInformation( 373 | SystemInformationClass SystemInformationClass, 374 | SystemInformation *byte, 375 | SystemInformationLength uint32, 376 | ReturnLength *uint32, 377 | ) NtStatus { 378 | r0, _, _ := procNtQuerySystemInformation.Call(uintptr(SystemInformationClass), 379 | uintptr(unsafe.Pointer(SystemInformation)), 380 | uintptr(SystemInformationLength), 381 | uintptr(unsafe.Pointer(ReturnLength))) 382 | return NtStatus(r0) 383 | } 384 | 385 | func NtSetSystemInformation( 386 | SystemInformationClass SystemInformationClass, 387 | SystemInformation *byte, 388 | SystemInformationLength uint32, 389 | ) NtStatus { 390 | r0, _, _ := procNtSetSystemInformation.Call(uintptr(SystemInformationClass), 391 | uintptr(unsafe.Pointer(SystemInformation)), 392 | uintptr(SystemInformationLength)) 393 | return NtStatus(r0) 394 | } 395 | -------------------------------------------------------------------------------- /token_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- token.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | import "reflect" 8 | 9 | // The TokenTypeT constants have been derived from the TOKEN_TYPE enum definition. 10 | type TokenTypeT uint32 11 | 12 | const ( 13 | TokenPrimary TokenTypeT = 1 14 | TokenImpersonation = 2 15 | ) 16 | 17 | // The TokenInformationClassT constants have been derived from the TOKEN_INFORMATION_CLASS enum definition. 18 | type TokenInformationClassT uint32 19 | 20 | const ( 21 | TokenUser TokenInformationClassT = 1 22 | TokenGroups = 2 23 | TokenPrivileges = 3 24 | TokenOwner = 4 25 | TokenPrimaryGroup = 5 26 | TokenDefaultDacl = 6 27 | TokenSource = 7 28 | TokenType = 8 29 | TokenImpersonationLevel = 9 30 | TokenStatistics = 10 31 | TokenRestrictedSids = 11 32 | TokenSessionId = 12 33 | TokenGroupsAndPrivileges = 13 34 | TokenSessionReference = 14 35 | TokenSandBoxInert = 15 36 | TokenAuditPolicy = 16 37 | TokenOrigin = 17 38 | TokenElevationType = 18 39 | TokenLinkedToken = 19 40 | TokenElevation = 20 41 | TokenHasRestrictions = 21 42 | TokenAccessInformation = 22 43 | TokenVirtualizationAllowed = 23 44 | TokenVirtualizationEnabled = 24 45 | TokenIntegrityLevel = 25 46 | TokenUIAccess = 26 47 | TokenMandatoryPolicy = 27 48 | TokenLogonSid = 28 49 | TokenIsAppContainer = 29 50 | TokenCapabilities = 30 51 | TokenAppContainerSid = 31 52 | TokenAppContainerNumber = 32 53 | TokenUserClaimAttributes = 33 54 | TokenDeviceClaimAttributes = 34 55 | TokenRestrictedUserClaimAttributes = 35 56 | TokenRestrictedDeviceClaimAttributes = 36 57 | TokenDeviceGroups = 37 58 | TokenRestrictedDeviceGroups = 38 59 | TokenSecurityAttributes = 39 60 | TokenIsRestricted = 40 61 | TokenProcessTrustLevel = 41 62 | TokenPrivateNameSpace = 42 63 | TokenSingletonAttributes = 43 64 | MaxTokenInfoClass = 44 65 | ) 66 | 67 | // The SecurityImpersonationLevel constants have been derived from the SECURITY_IMPERSONATION_LEVEL enum definition. 68 | type SecurityImpersonationLevel uint32 69 | 70 | const ( 71 | SecurityAnonymous SecurityImpersonationLevel = 0 72 | SecurityIdentification = 1 73 | SecurityImpersonation = 2 74 | SecurityDelegation = 3 75 | ) 76 | 77 | var ( 78 | procNtOpenThreadToken = modntdll.NewProc("NtOpenThreadToken") 79 | procNtOpenThreadTokenEx = modntdll.NewProc("NtOpenThreadTokenEx") 80 | procNtOpenProcessToken = modntdll.NewProc("NtOpenProcessToken") 81 | procNtOpenProcessTokenEx = modntdll.NewProc("NtOpenProcessTokenEx") 82 | procNtOpenJobObjectToken = modntdll.NewProc("NtOpenJobObjectToken") 83 | procNtDuplicateToken = modntdll.NewProc("NtDuplicateToken") 84 | procNtFilterToken = modntdll.NewProc("NtFilterToken") 85 | procNtImpersonateAnonymousToken = modntdll.NewProc("NtImpersonateAnonymousToken") 86 | procNtQueryInformationToken = modntdll.NewProc("NtQueryInformationToken") 87 | procNtSetInformationToken = modntdll.NewProc("NtSetInformationToken") 88 | procNtAdjustPrivilegesToken = modntdll.NewProc("NtAdjustPrivilegesToken") 89 | procNtAdjustGroupsToken = modntdll.NewProc("NtAdjustGroupsToken") 90 | ) 91 | 92 | // TokenUserT has been derived from the TOKEN_USER struct definition. 93 | type TokenUserT struct { 94 | User SidAndAttributes 95 | } 96 | 97 | // TokenGroupsT has been derived from the TOKEN_GROUPS struct definition. 98 | type TokenGroupsT struct { 99 | GroupCount uint32 100 | Groups [1]SidAndAttributes 101 | } 102 | 103 | // GroupsSlice returns a slice over the elements of TokenGroupsT.Groups. 104 | // 105 | // Beware: The data is not copied out of TokenGroupsT. The size can usually be taken from an other member of the struct (TokenGroupsT). 106 | func (t *TokenGroupsT) GroupsSlice(size int) []SidAndAttributes { 107 | s := []SidAndAttributes{} 108 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 109 | hdr.Data = uintptr(unsafe.Pointer(&t.Groups[0])) 110 | hdr.Len = size 111 | hdr.Cap = size 112 | return s 113 | } 114 | 115 | // SetGroupsSlice copies s into the memory at TokenGroupsT.Groups. 116 | // 117 | // Beware: No bounds check is performed. Another member of the struct (TokenGroupsT) usually has to be set to the array size. 118 | func (t *TokenGroupsT) SetGroupsSlice(s []SidAndAttributes) { 119 | s1 := []SidAndAttributes{} 120 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 121 | hdr.Data = uintptr(unsafe.Pointer(&t.Groups[0])) 122 | hdr.Len = len(s) 123 | hdr.Cap = len(s) 124 | copy(s1, s) 125 | } 126 | 127 | // TokenPrivilegesT has been derived from the TOKEN_PRIVILEGES struct definition. 128 | type TokenPrivilegesT struct { 129 | PrivilegeCount uint32 130 | Privileges [1]LuidAndAttributes 131 | } 132 | 133 | // PrivilegesSlice returns a slice over the elements of TokenPrivilegesT.Privileges. 134 | // 135 | // Beware: The data is not copied out of TokenPrivilegesT. The size can usually be taken from an other member of the struct (TokenPrivilegesT). 136 | func (t *TokenPrivilegesT) PrivilegesSlice(size int) []LuidAndAttributes { 137 | s := []LuidAndAttributes{} 138 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 139 | hdr.Data = uintptr(unsafe.Pointer(&t.Privileges[0])) 140 | hdr.Len = size 141 | hdr.Cap = size 142 | return s 143 | } 144 | 145 | // SetPrivilegesSlice copies s into the memory at TokenPrivilegesT.Privileges. 146 | // 147 | // Beware: No bounds check is performed. Another member of the struct (TokenPrivilegesT) usually has to be set to the array size. 148 | func (t *TokenPrivilegesT) SetPrivilegesSlice(s []LuidAndAttributes) { 149 | s1 := []LuidAndAttributes{} 150 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 151 | hdr.Data = uintptr(unsafe.Pointer(&t.Privileges[0])) 152 | hdr.Len = len(s) 153 | hdr.Cap = len(s) 154 | copy(s1, s) 155 | } 156 | 157 | // TokenOwnerT has been derived from the TOKEN_OWNER struct definition. 158 | type TokenOwnerT struct { 159 | Owner *Sid 160 | } 161 | 162 | // TokenPrimaryGroupT has been derived from the TOKEN_PRIMARY_GROUP struct definition. 163 | type TokenPrimaryGroupT struct { 164 | PrimaryGroup *Sid 165 | } 166 | 167 | // TokenDefaultDaclT has been derived from the TOKEN_DEFAULT_DACL struct definition. 168 | type TokenDefaultDaclT struct { 169 | DefaultDacl *Acl 170 | } 171 | 172 | // TokenUserClaimsT has been derived from the TOKEN_USER_CLAIMS struct definition. 173 | type TokenUserClaimsT struct { 174 | UserClaims *ClaimsBlob 175 | } 176 | 177 | // TokenDeviceClaimsT has been derived from the TOKEN_DEVICE_CLAIMS struct definition. 178 | type TokenDeviceClaimsT struct { 179 | DeviceClaims *ClaimsBlob 180 | } 181 | 182 | // TokenGroupsAndPrivilegesT has been derived from the TOKEN_GROUPS_AND_PRIVILEGES struct definition. 183 | type TokenGroupsAndPrivilegesT struct { 184 | SidCount uint32 185 | SidLength uint32 186 | Sids *SidAndAttributes 187 | RestrictedSidCount uint32 188 | RestrictedSidLength uint32 189 | RestrictedSids *SidAndAttributes 190 | PrivilegeCount uint32 191 | PrivilegeLength uint32 192 | Privileges *LuidAndAttributes 193 | AuthenticationId Luid 194 | } 195 | 196 | // TokenLinkedTokenT has been derived from the TOKEN_LINKED_TOKEN struct definition. 197 | type TokenLinkedTokenT struct { 198 | LinkedToken Handle 199 | } 200 | 201 | // TokenElevationT has been derived from the TOKEN_ELEVATION struct definition. 202 | type TokenElevationT struct { 203 | TokenIsElevated uint32 204 | } 205 | 206 | // TokenMandatoryLabelT has been derived from the TOKEN_MANDATORY_LABEL struct definition. 207 | type TokenMandatoryLabelT struct { 208 | Label SidAndAttributes 209 | } 210 | 211 | // TokenMandatoryPolicyT has been derived from the TOKEN_MANDATORY_POLICY struct definition. 212 | type TokenMandatoryPolicyT struct { 213 | Policy uint32 214 | } 215 | 216 | // TokenAccessInformationT has been derived from the TOKEN_ACCESS_INFORMATION struct definition. 217 | type TokenAccessInformationT struct { 218 | SidHash *SidAndAttributesHash 219 | RestrictedSidHash *SidAndAttributesHash 220 | Privileges *TokenPrivilegesT 221 | AuthenticationId Luid 222 | TokenType TokenTypeT 223 | ImpersonationLevel SecurityImpersonationLevel 224 | MandatoryPolicy TokenMandatoryPolicyT 225 | Flags uint32 226 | AppContainerNumber uint32 227 | PackageSid *Sid 228 | CapabilitiesHash *SidAndAttributesHash 229 | TrustLevelSid *Sid 230 | SecurityAttributes *SecurityAttributesOpaque 231 | } 232 | 233 | // TokenAuditPolicyT has been derived from the TOKEN_AUDIT_POLICY struct definition. 234 | type TokenAuditPolicyT struct { 235 | PerUserPolicy [30]byte 236 | } 237 | 238 | // TokenSourceT has been derived from the TOKEN_SOURCE struct definition. 239 | type TokenSourceT struct { 240 | SourceName [8]byte 241 | SourceIdentifier Luid 242 | } 243 | 244 | // TokenStatisticsT has been derived from the TOKEN_STATISTICS struct definition. 245 | type TokenStatisticsT struct { 246 | TokenId Luid 247 | AuthenticationId Luid 248 | ExpirationTime int64 249 | TokenType TokenTypeT 250 | ImpersonationLevel SecurityImpersonationLevel 251 | DynamicCharged uint32 252 | DynamicAvailable uint32 253 | GroupCount uint32 254 | PrivilegeCount uint32 255 | ModifiedId Luid 256 | } 257 | 258 | // TokenControlT has been derived from the TOKEN_CONTROL struct definition. 259 | type TokenControlT struct { 260 | TokenId Luid 261 | AuthenticationId Luid 262 | ModifiedId Luid 263 | TokenSource TokenSourceT 264 | } 265 | 266 | // TokenOriginT has been derived from the TOKEN_ORIGIN struct definition. 267 | type TokenOriginT struct { 268 | OriginatingLogonSession Luid 269 | } 270 | 271 | // TokenAppcontainerInformationT has been derived from the TOKEN_APPCONTAINER_INFORMATION struct definition. 272 | type TokenAppcontainerInformationT struct { 273 | TokenAppContainer *Sid 274 | } 275 | 276 | // TokenSidInformationT has been derived from the TOKEN_SID_INFORMATION struct definition. 277 | type TokenSidInformationT struct { 278 | Sid *Sid 279 | } 280 | 281 | // Luid has been derived from the LUID struct definition. 282 | type Luid struct { 283 | LowPart uint32 284 | HighPart int32 285 | } 286 | 287 | // LuidAndAttributes has been derived from the LUID_AND_ATTRIBUTES struct definition. 288 | type LuidAndAttributes struct { 289 | Luid Luid 290 | Attributes uint32 291 | } 292 | 293 | // SidAndAttributes has been derived from the SID_AND_ATTRIBUTES struct definition. 294 | type SidAndAttributes struct { 295 | Sid *Sid 296 | Attributes uint32 297 | } 298 | 299 | // SidAndAttributesHash has been derived from the SID_AND_ATTRIBUTES_HASH struct definition. 300 | type SidAndAttributesHash struct { 301 | SidCount uint32 302 | SidAttr *SidAndAttributes 303 | Hash [32]SidHashEntry 304 | } 305 | 306 | // OUT-parameter: TokenHandle. 307 | func NtOpenThreadToken( 308 | ThreadHandle Handle, 309 | DesiredAccess AccessMask, 310 | OpenAsSelf bool, 311 | TokenHandle *Handle, 312 | ) NtStatus { 313 | r0, _, _ := procNtOpenThreadToken.Call(uintptr(ThreadHandle), 314 | uintptr(DesiredAccess), 315 | fromBool(OpenAsSelf), 316 | uintptr(unsafe.Pointer(TokenHandle))) 317 | return NtStatus(r0) 318 | } 319 | 320 | // OUT-parameter: TokenHandle. 321 | func NtOpenThreadTokenEx( 322 | ThreadHandle Handle, 323 | DesiredAccess AccessMask, 324 | OpenAsSelf bool, 325 | HandleAttributes uint32, 326 | TokenHandle *Handle, 327 | ) NtStatus { 328 | r0, _, _ := procNtOpenThreadTokenEx.Call(uintptr(ThreadHandle), 329 | uintptr(DesiredAccess), 330 | fromBool(OpenAsSelf), 331 | uintptr(HandleAttributes), 332 | uintptr(unsafe.Pointer(TokenHandle))) 333 | return NtStatus(r0) 334 | } 335 | 336 | // OUT-parameter: TokenHandle. 337 | func NtOpenProcessToken( 338 | ProcessHandle Handle, 339 | DesiredAccess AccessMask, 340 | TokenHandle *Handle, 341 | ) NtStatus { 342 | r0, _, _ := procNtOpenProcessToken.Call(uintptr(ProcessHandle), 343 | uintptr(DesiredAccess), 344 | uintptr(unsafe.Pointer(TokenHandle))) 345 | return NtStatus(r0) 346 | } 347 | 348 | // OUT-parameter: TokenHandle. 349 | func NtOpenProcessTokenEx( 350 | ProcessHandle Handle, 351 | DesiredAccess AccessMask, 352 | HandleAttributes uint32, 353 | TokenHandle *Handle, 354 | ) NtStatus { 355 | r0, _, _ := procNtOpenProcessTokenEx.Call(uintptr(ProcessHandle), 356 | uintptr(DesiredAccess), 357 | uintptr(HandleAttributes), 358 | uintptr(unsafe.Pointer(TokenHandle))) 359 | return NtStatus(r0) 360 | } 361 | 362 | // OUT-parameter: TokenHandle. 363 | func NtOpenJobObjectToken( 364 | JobHandle Handle, 365 | DesiredAccess AccessMask, 366 | TokenHandle *Handle, 367 | ) NtStatus { 368 | r0, _, _ := procNtOpenJobObjectToken.Call(uintptr(JobHandle), 369 | uintptr(DesiredAccess), 370 | uintptr(unsafe.Pointer(TokenHandle))) 371 | return NtStatus(r0) 372 | } 373 | 374 | // OUT-parameter: NewTokenHandle. 375 | // *OPT-parameter: ObjectAttributes. 376 | func NtDuplicateToken( 377 | ExistingTokenHandle Handle, 378 | DesiredAccess AccessMask, 379 | ObjectAttributes *ObjectAttributes, 380 | EffectiveOnly bool, 381 | TokenType TokenTypeT, 382 | NewTokenHandle *Handle, 383 | ) NtStatus { 384 | r0, _, _ := procNtDuplicateToken.Call(uintptr(ExistingTokenHandle), 385 | uintptr(DesiredAccess), 386 | uintptr(unsafe.Pointer(ObjectAttributes)), 387 | fromBool(EffectiveOnly), 388 | uintptr(TokenType), 389 | uintptr(unsafe.Pointer(NewTokenHandle))) 390 | return NtStatus(r0) 391 | } 392 | 393 | // OUT-parameter: NewTokenHandle. 394 | // *OPT-parameter: SidsToDisable, PrivilegesToDelete, RestrictedSids. 395 | func NtFilterToken( 396 | ExistingTokenHandle Handle, 397 | Flags uint32, 398 | SidsToDisable *TokenGroupsT, 399 | PrivilegesToDelete *TokenPrivilegesT, 400 | RestrictedSids *TokenGroupsT, 401 | NewTokenHandle *Handle, 402 | ) NtStatus { 403 | r0, _, _ := procNtFilterToken.Call(uintptr(ExistingTokenHandle), 404 | uintptr(Flags), 405 | uintptr(unsafe.Pointer(SidsToDisable)), 406 | uintptr(unsafe.Pointer(PrivilegesToDelete)), 407 | uintptr(unsafe.Pointer(RestrictedSids)), 408 | uintptr(unsafe.Pointer(NewTokenHandle))) 409 | return NtStatus(r0) 410 | } 411 | 412 | func NtImpersonateAnonymousToken( 413 | ThreadHandle Handle, 414 | ) NtStatus { 415 | r0, _, _ := procNtImpersonateAnonymousToken.Call(uintptr(ThreadHandle)) 416 | return NtStatus(r0) 417 | } 418 | 419 | // OUT-parameter: TokenInformation, ReturnLength. 420 | func NtQueryInformationToken( 421 | TokenHandle Handle, 422 | TokenInformationClass TokenInformationClassT, 423 | TokenInformation *byte, 424 | TokenInformationLength uint32, 425 | ReturnLength *uint32, 426 | ) NtStatus { 427 | r0, _, _ := procNtQueryInformationToken.Call(uintptr(TokenHandle), 428 | uintptr(TokenInformationClass), 429 | uintptr(unsafe.Pointer(TokenInformation)), 430 | uintptr(TokenInformationLength), 431 | uintptr(unsafe.Pointer(ReturnLength))) 432 | return NtStatus(r0) 433 | } 434 | 435 | func NtSetInformationToken( 436 | TokenHandle Handle, 437 | TokenInformationClass TokenInformationClassT, 438 | TokenInformation *byte, 439 | TokenInformationLength uint32, 440 | ) NtStatus { 441 | r0, _, _ := procNtSetInformationToken.Call(uintptr(TokenHandle), 442 | uintptr(TokenInformationClass), 443 | uintptr(unsafe.Pointer(TokenInformation)), 444 | uintptr(TokenInformationLength)) 445 | return NtStatus(r0) 446 | } 447 | 448 | // OUT-parameter: PreviousState, ReturnLength. 449 | // *OPT-parameter: NewState. 450 | func NtAdjustPrivilegesToken( 451 | TokenHandle Handle, 452 | DisableAllPrivileges bool, 453 | NewState *TokenPrivilegesT, 454 | BufferLength uint32, 455 | PreviousState *TokenPrivilegesT, 456 | ReturnLength *uint32, 457 | ) NtStatus { 458 | r0, _, _ := procNtAdjustPrivilegesToken.Call(uintptr(TokenHandle), 459 | fromBool(DisableAllPrivileges), 460 | uintptr(unsafe.Pointer(NewState)), 461 | uintptr(BufferLength), 462 | uintptr(unsafe.Pointer(PreviousState)), 463 | uintptr(unsafe.Pointer(ReturnLength))) 464 | return NtStatus(r0) 465 | } 466 | 467 | // OUT-parameter: PreviousState, ReturnLength. 468 | // *OPT-parameter: NewState, BufferLength. 469 | func NtAdjustGroupsToken( 470 | TokenHandle Handle, 471 | ResetToDefault bool, 472 | NewState *TokenGroupsT, 473 | BufferLength uint32, 474 | PreviousState *TokenGroupsT, 475 | ReturnLength *uint32, 476 | ) NtStatus { 477 | r0, _, _ := procNtAdjustGroupsToken.Call(uintptr(TokenHandle), 478 | fromBool(ResetToDefault), 479 | uintptr(unsafe.Pointer(NewState)), 480 | uintptr(BufferLength), 481 | uintptr(unsafe.Pointer(PreviousState)), 482 | uintptr(unsafe.Pointer(ReturnLength))) 483 | return NtStatus(r0) 484 | } 485 | -------------------------------------------------------------------------------- /process_generated.go: -------------------------------------------------------------------------------- 1 | // This file was autogenerated using go run mkcode.go -- process.go 2 | // DO NOT EDIT. 3 | 4 | package ntdll 5 | 6 | import "unsafe" 7 | 8 | // The ProcessInformationClass constants have been derived from the PROCESS_INFORMATION_CLASS enum definition. 9 | type ProcessInformationClass uint32 10 | 11 | const ( 12 | ProcessBasicInformation ProcessInformationClass = 0 13 | ProcessQuotaLimits = 1 14 | ProcessIoCounters = 2 15 | ProcessVmCounters = 3 16 | ProcessTimes = 4 17 | ProcessBasePriority = 5 18 | ProcessRaisePriority = 6 19 | ProcessDebugPort = 7 20 | ProcessExceptionPort = 8 21 | ProcessAccessToken = 9 22 | ProcessLdtInformation = 10 23 | ProcessLdtSize = 11 24 | ProcessDefaultHardErrorMode = 12 25 | ProcessIoPortHandlers = 13 26 | ProcessPooledUsageAndLimits = 14 27 | ProcessWorkingSetWatch = 15 28 | ProcessUserModeIOPL = 16 29 | ProcessEnableAlignmentFaultFixup = 17 30 | ProcessPriorityClass = 18 31 | ProcessWx86Information = 19 32 | ProcessHandleCount = 20 33 | ProcessAffinityMask = 21 34 | ProcessPriorityBoost = 22 35 | ProcessDeviceMap = 23 36 | ProcessSessionInformation = 24 37 | ProcessForegroundInformation = 25 38 | ProcessWow64Information = 26 39 | ProcessImageFileName = 27 40 | ProcessLUIDDeviceMapsEnabled = 28 41 | ProcessBreakOnTermination = 29 42 | ProcessDebugObjectHandle = 30 43 | ProcessDebugFlags = 31 44 | ProcessHandleTracing = 32 45 | ProcessIoPriority = 33 46 | ProcessExecuteFlags = 34 47 | ProcessTlsInformation = 35 48 | ProcessCookie = 36 49 | ProcessImageInformation = 37 50 | ProcessCycleTime = 38 51 | ProcessPagePriority = 39 52 | ProcessInstrumentationCallback = 40 53 | ProcessThreadStackAllocation = 41 54 | ProcessWorkingSetWatchEx = 42 55 | ProcessImageFileNameWin32 = 43 56 | ProcessImageFileMapping = 44 57 | ProcessAffinityUpdateMode = 45 58 | ProcessMemoryAllocationMode = 46 59 | ProcessGroupInformation = 47 60 | ProcessTokenVirtualizationEnabled = 48 61 | ProcessConsoleHostProcess = 49 62 | ProcessWindowInformation = 50 63 | ProcessHandleInformation = 51 64 | ProcessMitigationPolicy = 52 65 | ProcessDynamicFunctionTableInformation = 53 66 | ProcessHandleCheckingMode = 54 67 | ProcessKeepAliveCount = 55 68 | ProcessRevokeFileHandles = 56 69 | ProcessWorkingSetControl = 57 70 | ProcessHandleTable = 58 71 | ProcessCheckStackExtentsMode = 59 72 | ProcessCommandLineInformation = 60 73 | ProcessProtectionInformation = 61 74 | ProcessMemoryExhaustion = 62 75 | ProcessFaultInformation = 63 76 | ProcessTelemetryIdInformation = 64 77 | ProcessCommitReleaseInformation = 65 78 | ProcessDefaultCpuSetsInformation = 66 79 | ProcessAllowedCpuSetsInformation = 67 80 | ProcessSubsystemProcess = 68 81 | ProcessJobMemoryInformation = 69 82 | ProcessInPrivate = 70 83 | ProcessRaiseUMExceptionOnInvalidHandleClose = 71 84 | ProcessIumChallengeResponse = 72 85 | ProcessChildProcessInformation = 73 86 | ProcessHighGraphicsPriorityInformation = 74 87 | ProcessSubsystemInformation = 75 88 | ProcessEnergyValues = 76 89 | ProcessPowerThrottlingState = 77 90 | ProcessReserved3Information = 78 91 | ProcessWin32kSyscallFilterInformation = 79 92 | ProcessDisableSystemAllowedCpuSets = 80 93 | ProcessWakeInformation = 81 94 | ProcessEnergyTrackingState = 82 95 | ProcessManageWritesToExecutableMemory = 83 96 | ProcessCaptureTrustletLiveDump = 84 97 | ProcessTelemetryCoverage = 85 98 | ProcessEnclaveInformation = 86 99 | ProcessEnableReadWriteVmLogging = 87 100 | ProcessUptimeInformation = 88 101 | ProcessImageSection = 89 102 | ProcessDebugAuthInformation = 90 103 | ProcessSystemResourceManagement = 91 104 | ProcessSequenceNumber = 92 105 | ProcessLoaderDetour = 93 106 | ProcessSecurityDomainInformation = 94 107 | ProcessCombineSecurityDomainsInformation = 95 108 | ProcessEnableLogging = 96 109 | ProcessLeapSecondInformation = 97 110 | ProcessFiberShadowStackAllocation = 98 111 | ProcessFreeFiberShadowStackAllocation = 99 112 | ProcessAltSystemCallInformation = 100 113 | ProcessDynamicEHContinuationTargets = 101 114 | ProcessDynamicEnforcedCetCompatibleRanges = 102 115 | ProcessCreateStateChange = 103 116 | ProcessApplyStateChange = 104 117 | ProcessEnableOptionalXStateFeatures = 105 118 | ProcessAltPrefetchParam = 106 119 | ProcessAssignCpuPartitions = 107 120 | ProcessPriorityClassEx = 108 121 | ProcessMembershipInformation = 109 122 | ProcessEffectiveIoPriority = 110 123 | ProcessEffectivePagePriority = 111 124 | ) 125 | 126 | // The ThreadInformationClass constants have been derived from the THREAD_INFORMATION_CLASS enum definition. 127 | type ThreadInformationClass uint32 128 | 129 | const ( 130 | ThreadBasicInformation ThreadInformationClass = 0 131 | ThreadTimes = 1 132 | ThreadPriority = 2 133 | ThreadBasePriority = 3 134 | ThreadAffinityMask = 4 135 | ThreadImpersonationToken = 5 136 | ThreadDescriptorTableEntry = 6 137 | ThreadEnableAlignmentFaultFixup = 7 138 | ThreadEventPair_Reusable = 8 139 | ThreadQuerySetWin32StartAddress = 9 140 | ThreadZeroTlsCell = 10 141 | ThreadPerformanceCount = 11 142 | ThreadAmILastThread = 12 143 | ThreadIdealProcessor = 13 144 | ThreadPriorityBoost = 14 145 | ThreadSetTlsArrayAddress = 15 146 | ThreadIsIoPending = 16 147 | ThreadHideFromDebugger = 17 148 | ThreadBreakOnTermination = 18 149 | ThreadSwitchLegacyState = 19 150 | ThreadIsTerminated = 20 151 | ThreadLastSystemCall = 21 152 | ThreadIoPriority = 22 153 | ThreadCycleTime = 23 154 | ThreadPagePriority = 24 155 | ThreadActualBasePriority = 25 156 | ThreadTebInformation = 26 157 | ThreadCSwitchMon = 27 158 | ThreadCSwitchPmu = 28 159 | ThreadWow64Context = 29 160 | ThreadGroupInformation = 30 161 | ThreadUmsInformation = 31 162 | ThreadCounterProfiling = 32 163 | ThreadIdealProcessorEx = 33 164 | MaxThreadInfoClass = 34 165 | ) 166 | 167 | var ( 168 | procNtQueryInformationProcess = modntdll.NewProc("NtQueryInformationProcess") 169 | procNtOpenProcess = modntdll.NewProc("NtOpenProcess") 170 | procNtOpenThread = modntdll.NewProc("NtOpenThread") 171 | procNtQueryInformationThread = modntdll.NewProc("NtQueryInformationThread") 172 | procNtSetInformationThread = modntdll.NewProc("NtSetInformationThread") 173 | procNtSetInformationProcess = modntdll.NewProc("NtSetInformationProcess") 174 | procNtCreateProcess = modntdll.NewProc("NtCreateProcess") 175 | procNtCreateProcessEx = modntdll.NewProc("NtCreateProcessEx") 176 | ) 177 | 178 | // Peb has been derived from the PEB struct definition. 179 | type Peb struct { 180 | Reserved1 [2]byte 181 | BeingDebugged byte 182 | Reserved2 [1]byte 183 | Reserved3 [2]*byte 184 | Ldr *PebLdrData 185 | ProcessParameters *RtlUserProcessParameters 186 | Reserved4 [3]*byte 187 | AtlThunkSListPtr *byte 188 | Reserved5 *byte 189 | Reserved6 uint32 190 | Reserved7 *byte 191 | Reserved8 uint32 192 | AtlThunkSListPtr32 uint32 193 | Reserved9 [45]*byte 194 | Reserved10 [96]byte 195 | PostProcessInitRoutine *PsPostProcessInitRoutine 196 | Reserved11 [128]byte 197 | Reserved12 [1]*byte 198 | SessionId uint32 199 | } 200 | 201 | // PebLdrData has been derived from the PEB_LDR_DATA struct definition. 202 | type PebLdrData struct { 203 | Reserved1 [8]byte 204 | Reserved2 [3]*byte 205 | InMemoryOrderModuleList ListEntry 206 | } 207 | 208 | // RtlUserProcessParameters has been derived from the RTL_USER_PROCESS_PARAMETERS struct definition. 209 | type RtlUserProcessParameters struct { 210 | Reserved1 [16]byte 211 | Reserved2 [10]*byte 212 | ImagePathName UnicodeString 213 | CommandLine UnicodeString 214 | } 215 | 216 | // ProcessBasicInformationT has been derived from the PROCESS_BASIC_INFORMATION struct definition. 217 | type ProcessBasicInformationT struct { 218 | ExitStatus NtStatus 219 | PebBaseAddress *Peb 220 | AffinityMask *uint32 221 | BasePriority Kpriority 222 | UniqueProcessId Handle 223 | InheritedFromUniqueProcessId Handle 224 | } 225 | 226 | // unknown-parameter: ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength, ReturnLength. 227 | func NtQueryInformationProcess( 228 | ProcessHandle Handle, 229 | ProcessInformationClass ProcessInformationClass, 230 | ProcessInformation *byte, 231 | ProcessInformationLength uint32, 232 | ReturnLength *uint32, 233 | ) NtStatus { 234 | r0, _, _ := procNtQueryInformationProcess.Call(uintptr(ProcessHandle), 235 | uintptr(ProcessInformationClass), 236 | uintptr(unsafe.Pointer(ProcessInformation)), 237 | uintptr(ProcessInformationLength), 238 | uintptr(unsafe.Pointer(ReturnLength))) 239 | return NtStatus(r0) 240 | } 241 | 242 | // OUT-parameter: ProcessHandle. 243 | // *OPT-parameter: ClientId. 244 | func NtOpenProcess( 245 | ProcessHandle *Handle, 246 | DesiredAccess AccessMask, 247 | ObjectAttributes *ObjectAttributes, 248 | ClientId *ClientId, 249 | ) NtStatus { 250 | r0, _, _ := procNtOpenProcess.Call(uintptr(unsafe.Pointer(ProcessHandle)), 251 | uintptr(DesiredAccess), 252 | uintptr(unsafe.Pointer(ObjectAttributes)), 253 | uintptr(unsafe.Pointer(ClientId))) 254 | return NtStatus(r0) 255 | } 256 | 257 | // OUT-parameter: ThreadHandle. 258 | // *OPT-parameter: ClientId. 259 | func NtOpenThread( 260 | ThreadHandle *Handle, 261 | DesiredAccess AccessMask, 262 | ObjectAttributes *ObjectAttributes, 263 | ClientId *ClientId, 264 | ) NtStatus { 265 | r0, _, _ := procNtOpenThread.Call(uintptr(unsafe.Pointer(ThreadHandle)), 266 | uintptr(DesiredAccess), 267 | uintptr(unsafe.Pointer(ObjectAttributes)), 268 | uintptr(unsafe.Pointer(ClientId))) 269 | return NtStatus(r0) 270 | } 271 | 272 | // unknown-parameter: ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength, ReturnLength. 273 | func NtQueryInformationThread( 274 | ThreadHandle Handle, 275 | ThreadInformationClass ThreadInformationClass, 276 | ThreadInformation *byte, 277 | ThreadInformationLength uint32, 278 | ReturnLength *uint32, 279 | ) NtStatus { 280 | r0, _, _ := procNtQueryInformationThread.Call(uintptr(ThreadHandle), 281 | uintptr(ThreadInformationClass), 282 | uintptr(unsafe.Pointer(ThreadInformation)), 283 | uintptr(ThreadInformationLength), 284 | uintptr(unsafe.Pointer(ReturnLength))) 285 | return NtStatus(r0) 286 | } 287 | 288 | // unknown-parameter: ThreadHandle, ThreadInformationClass, ThreadInformation, ThreadInformationLength. 289 | func NtSetInformationThread( 290 | ThreadHandle Handle, 291 | ThreadInformationClass ThreadInformationClass, 292 | ThreadInformation *byte, 293 | ThreadInformationLength uint32, 294 | ) NtStatus { 295 | r0, _, _ := procNtSetInformationThread.Call(uintptr(ThreadHandle), 296 | uintptr(ThreadInformationClass), 297 | uintptr(unsafe.Pointer(ThreadInformation)), 298 | uintptr(ThreadInformationLength)) 299 | return NtStatus(r0) 300 | } 301 | 302 | // unknown-parameter: ProcessHandle, ProcessInformationClass, ProcessInformation, ProcessInformationLength. 303 | func NtSetInformationProcess( 304 | ProcessHandle Handle, 305 | ProcessInformationClass ProcessInformationClass, 306 | ProcessInformation *byte, 307 | ProcessInformationLength uint32, 308 | ) NtStatus { 309 | r0, _, _ := procNtSetInformationProcess.Call(uintptr(ProcessHandle), 310 | uintptr(ProcessInformationClass), 311 | uintptr(unsafe.Pointer(ProcessInformation)), 312 | uintptr(ProcessInformationLength)) 313 | return NtStatus(r0) 314 | } 315 | 316 | // OUT-parameter: ProcessHandle. 317 | // *OPT-parameter: ObjectAttributes, SectionHandle, DebugPort, TokenHandle. 318 | func NtCreateProcess( 319 | ProcessHandle *Handle, 320 | DesiredAccess AccessMask, 321 | ObjectAttributes *ObjectAttributes, 322 | ParentProcess Handle, 323 | InheritObjectTable bool, 324 | SectionHandle Handle, 325 | DebugPort Handle, 326 | TokenHandle Handle, 327 | ) NtStatus { 328 | r0, _, _ := procNtCreateProcess.Call(uintptr(unsafe.Pointer(ProcessHandle)), 329 | uintptr(DesiredAccess), 330 | uintptr(unsafe.Pointer(ObjectAttributes)), 331 | uintptr(ParentProcess), 332 | fromBool(InheritObjectTable), 333 | uintptr(SectionHandle), 334 | uintptr(DebugPort), 335 | uintptr(TokenHandle)) 336 | return NtStatus(r0) 337 | } 338 | 339 | // OUT-parameter: ProcessHandle. 340 | // *OPT-parameter: ObjectAttributes, SectionHandle, DebugPort, ExceptionPort. 341 | func NtCreateProcessEx( 342 | ProcessHandle *Handle, 343 | DesiredAccess AccessMask, 344 | ObjectAttributes *ObjectAttributes, 345 | ParentProcess Handle, 346 | Flags uint32, 347 | SectionHandle Handle, 348 | DebugPort Handle, 349 | ExceptionPort Handle, 350 | InJob bool, 351 | ) NtStatus { 352 | r0, _, _ := procNtCreateProcessEx.Call(uintptr(unsafe.Pointer(ProcessHandle)), 353 | uintptr(DesiredAccess), 354 | uintptr(unsafe.Pointer(ObjectAttributes)), 355 | uintptr(ParentProcess), 356 | uintptr(Flags), 357 | uintptr(SectionHandle), 358 | uintptr(DebugPort), 359 | uintptr(ExceptionPort), 360 | fromBool(InJob)) 361 | return NtStatus(r0) 362 | } 363 | -------------------------------------------------------------------------------- /mkcode.go: -------------------------------------------------------------------------------- 1 | //go:build ignore 2 | // +build ignore 3 | 4 | // Simple tool that tries to understand simple function definitions as 5 | // used in describing the Windwos Native API. 6 | // 7 | // Comments in Go files that begin with "func:" are parsed as a C 8 | // function prototype. 9 | // 10 | // Comments in Go files that begin with "type:" are parsed as a C 11 | // type definitions. 12 | // 13 | // Comments in Go files that begin with "enum:" are parsed as a C 14 | // enum definitions. 15 | package main 16 | 17 | import ( 18 | "bytes" 19 | "flag" 20 | "fmt" 21 | "go/format" 22 | "go/parser" 23 | "go/token" 24 | "io" 25 | "log" 26 | "os" 27 | "path/filepath" 28 | "strconv" 29 | "strings" 30 | "text/scanner" 31 | ) 32 | 33 | type State int 34 | 35 | const ( 36 | StateInit State = iota 37 | StateParam 38 | StateMember 39 | StateExit 40 | ) 41 | 42 | type Direction int 43 | 44 | const ( 45 | DirectionUnspecified Direction = iota 46 | DirectionIn 47 | DirectionInOpt 48 | DirectionOut 49 | DirectionOutOpt 50 | DirectionInOut 51 | DirectionInOutOpt 52 | DirectionReserved 53 | ) 54 | 55 | type FunctionParameterDefinition struct { 56 | Direction 57 | Type string 58 | Name string 59 | } 60 | 61 | type FunctionDefinition struct { 62 | Type string 63 | Name string 64 | Params []FunctionParameterDefinition 65 | } 66 | 67 | type StructMemberDefinition struct { 68 | Name string 69 | Type string 70 | Array int 71 | } 72 | 73 | type StructDefinition struct { 74 | Name, OriginalName string 75 | Members []StructMemberDefinition 76 | } 77 | 78 | var translation = map[string]string{ 79 | "NTSTATUS": "NtStatus", 80 | "HANDLE": "Handle", 81 | "VOID": "byte", 82 | "SIZE_T": "uintptr", 83 | "LONGLONG": "int64", 84 | "ULONGLONG": "uint64", 85 | "ULONG": "uint32", 86 | "LONG": "int32", 87 | "DWORD": "uint32", 88 | "USHORT": "uint16", 89 | "SHORT": "int16", 90 | "WSTR": "uint16", 91 | "WCHAR": "uint16", 92 | "UWORD": "uint16", 93 | "WORD": "uint16", 94 | "UCHAR": "byte", 95 | "CCHAR": "byte", 96 | "CHAR": "byte", 97 | "BYTE": "byte", 98 | "BOOLEAN": "bool", 99 | "LARGE_INTEGER": "int64", 100 | "ULARGE_INTEGER": "uint64", 101 | } 102 | 103 | func translate(from string) (to string) { 104 | var ok bool 105 | if to, ok = translation[from]; ok { 106 | return 107 | } 108 | // recognize pointer types 109 | if from[0] == 'P' && 110 | !strings.HasPrefix(from, "PUBLIC_") && 111 | !strings.HasPrefix(from, "PEB") && 112 | !strings.HasPrefix(from, "PS_POST_PROCESS") && 113 | !strings.HasPrefix(from, "PROCESS") { 114 | if rest := translate(from[1:]); rest != "" { 115 | return "*" + rest 116 | } 117 | } 118 | if strings.HasSuffix(from, "_PTR") { 119 | if rest := translate(from[:len(from)-4]); rest != "" { 120 | return "*" + rest 121 | } 122 | } 123 | if strings.Contains(from, "_") || strings.HasSuffix(from, "ID") { 124 | words := strings.Split(from, "_") 125 | for _, w := range words { 126 | to = to + strings.Title(strings.ToLower(w)) 127 | } 128 | // This avoids collisions between constants and type definitions, e.g. 129 | // KeyBasicInformation (constant) vs. KEY_BASIC_INFORMATION (struct) 130 | if strings.HasSuffix(from, "_INFORMATION") || 131 | strings.HasSuffix(from, "_TYPE") || 132 | strings.HasPrefix(from, "TOKEN_") { 133 | to += "T" 134 | } 135 | } else { 136 | return strings.Title(strings.ToLower(from)) 137 | } 138 | return 139 | } 140 | 141 | // ParseFunctionDefinition is a half-arsed parser for C function 142 | // definitions as found in MSDN documentation for NTDLL member 143 | // function. 144 | // 145 | // Example (adapted from 146 | // https://msdn.microsoft.com/en-us/library/windows/hardware/ff567029(v=vs.85).aspx): 147 | // 148 | // NTSTATUS NtOpenSection( 149 | // 150 | // _Out_ PHANDLE SectionHandle, 151 | // _In_ ACCESS_MASK DesiredAccess, 152 | // _In_ POBJECT_ATTRIBUTES ObjectAttributes 153 | // 154 | // ); 155 | func ParseFunctionDefinition(rd io.Reader) (*FunctionDefinition, error) { 156 | s := &scanner.Scanner{Mode: scanner.GoTokens} 157 | s.Init(rd) 158 | state := StateInit 159 | var f FunctionDefinition 160 | tokens := make([]string, 0) 161 | for { 162 | r := s.Scan() 163 | if r == scanner.EOF { 164 | break 165 | } 166 | switch state { 167 | case StateInit: 168 | switch r { 169 | case '(': 170 | if len(tokens) < 2 { 171 | return nil, fmt.Errorf("function definition needs at least a name and a type") 172 | } 173 | f.Name = tokens[0] 174 | var typ string 175 | for _, t := range tokens[1:] { 176 | switch t { 177 | // ignore WINAPI calling convention 178 | case "WINAPI": 179 | default: 180 | typ = t 181 | } 182 | } 183 | f.Type = translate(typ) 184 | if f.Type == "" { 185 | return nil, fmt.Errorf("did not find translation type for %s", typ) 186 | } 187 | tokens = tokens[0:0] 188 | state = StateParam 189 | case scanner.Ident: 190 | tokens = append([]string{s.TokenText()}, tokens...) 191 | default: 192 | return nil, fmt.Errorf("parse error: got %s", scanner.TokenString(r)) 193 | } 194 | case StateParam: 195 | switch r { 196 | case scanner.Ident: 197 | tokens = append([]string{s.TokenText()}, tokens...) 198 | case ',', ')': 199 | if len(tokens) < 2 { 200 | return nil, fmt.Errorf("function parameter needs at least a name and a type") 201 | } 202 | 203 | p := FunctionParameterDefinition{Name: tokens[0]} 204 | 205 | var typ string 206 | for _, t := range tokens[1:] { 207 | switch t { 208 | case "_In_": 209 | p.Direction = DirectionIn 210 | case "_In_opt_": 211 | p.Direction = DirectionInOpt 212 | case "_Out_": 213 | p.Direction = DirectionOut 214 | case "_Out_opt_": 215 | p.Direction = DirectionOutOpt 216 | case "_Inout_": 217 | p.Direction = DirectionInOut 218 | case "_Inout_opt_": 219 | p.Direction = DirectionInOutOpt 220 | case "_Reserved_": 221 | p.Direction = DirectionReserved 222 | default: 223 | typ = t 224 | } 225 | } 226 | p.Type = translate(typ) 227 | if p.Type == "" { 228 | return nil, fmt.Errorf("did not find translation type for %s", typ) 229 | } 230 | f.Params = append(f.Params, p) 231 | tokens = tokens[0:0] 232 | if r == ')' { 233 | state = StateExit 234 | } 235 | } 236 | case StateExit: 237 | switch r { 238 | case ';': 239 | state = StateInit 240 | break 241 | } 242 | } 243 | } 244 | if state != StateInit { 245 | return nil, fmt.Errorf("parse error: wrong state %d", state) 246 | } 247 | return &f, nil 248 | } 249 | 250 | // ParseStructDefinition is a half-arsed parser for C struct 251 | // definitions as found in MSDN documentation for NTDLL / Windows 252 | // Driver types. 253 | // 254 | // Example: 255 | // 256 | // typedef struct _OBJECT_ATTRIBUTES { 257 | // ULONG Length; 258 | // HANDLE RootDirectory; 259 | // PUNICODE_STRING ObjectName; 260 | // ULONG Attributes; 261 | // PVOID SecurityDescriptor; 262 | // PVOID SecurityQualityOfService; 263 | // } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; 264 | func ParseStructDefinition(rd io.Reader) (*StructDefinition, error) { 265 | s := &scanner.Scanner{Mode: scanner.GoTokens} 266 | s.Init(rd) 267 | state := StateInit 268 | var sd StructDefinition 269 | for { 270 | r := s.Scan() 271 | if r == scanner.EOF { 272 | break 273 | } 274 | switch state { 275 | case StateInit: 276 | e := fmt.Errorf("expecting typedef struct _X {") 277 | if r != scanner.Ident || s.TokenText() != "typedef" { 278 | return nil, e 279 | } 280 | if r = s.Scan(); r != scanner.Ident || s.TokenText() != "struct" { 281 | return nil, e 282 | } 283 | if r = s.Scan(); r != scanner.Ident || !strings.HasPrefix(s.TokenText(), "_") { 284 | return nil, e 285 | } 286 | sd.OriginalName = s.TokenText()[1:] 287 | sd.Name = translate(sd.OriginalName) 288 | if sd.Name == "" { 289 | return nil, fmt.Errorf("did not find translation type for %s", sd.OriginalName) 290 | } 291 | if r = s.Scan(); r != '{' { 292 | return nil, e 293 | } 294 | state = StateMember 295 | case StateMember: 296 | if r == '}' { 297 | state = StateExit 298 | continue 299 | } 300 | if r != scanner.Ident { 301 | return nil, fmt.Errorf("%s: expecting type, got '%s'", sd.OriginalName, s.TokenText()) 302 | } 303 | typ := translate(s.TokenText()) 304 | if typ == "" { 305 | return nil, fmt.Errorf("did not find translation type for %s", s.TokenText()) 306 | } 307 | m := StructMemberDefinition{Type: typ} 308 | if r = s.Scan(); r != scanner.Ident { 309 | return nil, fmt.Errorf("%s: expecting type / name pair, got '%s'", sd.OriginalName, s.TokenText()) 310 | } 311 | m.Name = s.TokenText() 312 | if r = s.Scan(); r == '[' { 313 | if r = s.Scan(); r == scanner.Int { 314 | if n, err := strconv.Atoi(s.TokenText()); err != nil { 315 | return nil, err 316 | } else { 317 | m.Array = n 318 | } 319 | } else if r == scanner.Ident && s.TokenText() == "ANYSIZE_ARRAY" { 320 | m.Type = m.Type 321 | m.Array = 1 322 | } else { 323 | return nil, fmt.Errorf("%s: expecting number after '[', got '%s'", sd.OriginalName, s.TokenText()) 324 | } 325 | if r = s.Scan(); r != ']' { 326 | return nil, fmt.Errorf("%s: expecting ']', got '%s'", sd.OriginalName, s.TokenText()) 327 | } 328 | r = s.Scan() 329 | } else if r != ';' { 330 | return nil, fmt.Errorf("%s: expecting semicolon after type / name pair, got '%s'", sd.OriginalName, s.TokenText()) 331 | } 332 | sd.Members = append(sd.Members, m) 333 | case StateExit: 334 | if r == ';' { 335 | state = StateInit 336 | break 337 | } 338 | var typ string 339 | if r == '*' { 340 | typ = "*" 341 | r = s.Scan() 342 | } 343 | if r != scanner.Ident { 344 | return nil, fmt.Errorf("expecting type def, got '%s'", r) 345 | } 346 | typ += s.TokenText() 347 | if strings.HasPrefix(typ, "*P") { 348 | typ = typ[2:] 349 | } 350 | if typ != sd.OriginalName && typ[0] == 'I' { 351 | typ = typ[1:] 352 | } 353 | if typ != sd.OriginalName { 354 | return nil, fmt.Errorf("expecting type %s, got %s", sd.OriginalName, typ) 355 | } 356 | if s.Peek() == ',' { 357 | s.Scan() 358 | } 359 | } 360 | } 361 | if state != StateInit { 362 | return nil, fmt.Errorf("parse error: wrong state %d", state) 363 | } 364 | return &sd, nil 365 | } 366 | 367 | type EnumMemberDefinition struct { 368 | Name string 369 | Value int 370 | } 371 | 372 | type EnumDefinition struct { 373 | Name, OriginalName string 374 | Members []EnumMemberDefinition 375 | } 376 | 377 | // ParseEnumDefinition is a half-arsed parser for C enum definitions 378 | // as found in MSDN documentation for NTDLL / Windows Driver types. 379 | // 380 | // Example: 381 | // 382 | // typedef enum _KEY_VALUE_INFORMATION_CLASS { 383 | // KeyValueBasicInformation = 0, 384 | // KeyValueFullInformation, 385 | // KeyValuePartialInformation, 386 | // KeyValueFullInformationAlign64, 387 | // KeyValuePartialInformationAlign64, 388 | // MaxKeyValueInfoClass 389 | // } KEY_VALUE_INFORMATION_CLASS; 390 | func ParseEnumDefinition(rd io.Reader) (*EnumDefinition, error) { 391 | s := &scanner.Scanner{Mode: scanner.GoTokens} 392 | s.Init(rd) 393 | state := StateInit 394 | var ed EnumDefinition 395 | lastval := -1 396 | for { 397 | r := s.Scan() 398 | if r == scanner.EOF { 399 | break 400 | } 401 | switch state { 402 | case StateInit: 403 | e := fmt.Errorf("expecting typedef enum _X {") 404 | if r != scanner.Ident || s.TokenText() != "typedef" { 405 | return nil, e 406 | } 407 | if r = s.Scan(); r != scanner.Ident || s.TokenText() != "enum" { 408 | return nil, e 409 | } 410 | if r = s.Scan(); r != scanner.Ident || !strings.HasPrefix(s.TokenText(), "_") { 411 | return nil, e 412 | } 413 | ed.OriginalName = s.TokenText()[1:] 414 | ed.Name = translate(ed.OriginalName) 415 | if r = s.Scan(); r != '{' { 416 | return nil, e 417 | } 418 | state = StateMember 419 | case StateMember: 420 | if r == '}' { 421 | state = StateExit 422 | continue 423 | } 424 | if r != scanner.Ident { 425 | return nil, fmt.Errorf("%s: expecting name, got '%s'", ed.OriginalName, s.TokenText()) 426 | } 427 | m := EnumMemberDefinition{Name: s.TokenText()} 428 | if r = s.Scan(); r == '=' { 429 | if r = s.Scan(); r != scanner.Int { 430 | return nil, fmt.Errorf("%s: expecting int, got '%s'", ed.OriginalName, s.TokenText()) 431 | } 432 | v, err := strconv.Atoi(s.TokenText()) 433 | if err != nil { 434 | return nil, err 435 | } 436 | lastval = v 437 | m.Value = v 438 | r = s.Scan() 439 | } else if r == ',' || r == '}' { 440 | lastval++ 441 | m.Value = lastval 442 | } else { 443 | return nil, fmt.Errorf("%s: expecting enum value or ellipsis, got '%s'", ed.OriginalName, s.TokenText()) 444 | } 445 | if r == ',' || r == '}' { 446 | ed.Members = append(ed.Members, m) 447 | } else { 448 | return nil, fmt.Errorf("%s: Expecting ',' or '}', got '%s'", ed.OriginalName, s.TokenText()) 449 | } 450 | if r == '}' { 451 | state = StateExit 452 | } 453 | case StateExit: 454 | if r == ';' { 455 | state = StateInit 456 | break 457 | } 458 | var typ string 459 | if r == '*' { 460 | typ = "*" 461 | r = s.Scan() 462 | } 463 | if r != scanner.Ident { 464 | return nil, fmt.Errorf("expecting type def, got '%s'", r) 465 | } 466 | typ += s.TokenText() 467 | if strings.HasPrefix(typ, "*P") { 468 | typ = typ[2:] 469 | } 470 | if typ != ed.OriginalName && typ[1:] == ed.OriginalName { 471 | typ = typ[1:] 472 | } 473 | if typ != ed.OriginalName { 474 | return nil, fmt.Errorf("expecting type %s, got %s", ed.OriginalName, typ) 475 | } 476 | if s.Peek() == ',' { 477 | s.Scan() 478 | } 479 | } 480 | } 481 | return &ed, nil 482 | } 483 | 484 | func main() { 485 | var outfile string 486 | var functions []FunctionDefinition 487 | var structs []StructDefinition 488 | var enums []EnumDefinition 489 | flag.StringVar(&outfile, "output", "", "output file") 490 | flag.Parse() 491 | if flag.NArg() != 1 { 492 | log.Fatal("pass exactly one file") 493 | } 494 | infile := filepath.Clean(flag.Arg(0)) 495 | fset := token.NewFileSet() 496 | if outfile == "" { 497 | ext := filepath.Ext(infile) 498 | outfile = infile[:len(infile)-len(ext)] + "_generated" + ext 499 | } 500 | f, err := os.Open(infile) 501 | if err != nil { 502 | log.Fatal(err) 503 | } 504 | file, err := parser.ParseFile(fset, "", f, parser.ParseComments) 505 | if err != nil { 506 | log.Fatal(err) 507 | } 508 | for _, cgroup := range file.Comments { 509 | comment := strings.TrimSpace(cgroup.Text()) 510 | if strings.HasPrefix(comment, "func:") { 511 | comment = comment[5:] 512 | f, err := ParseFunctionDefinition(strings.NewReader(comment)) 513 | if err != nil { 514 | log.Fatal(err) 515 | } 516 | functions = append(functions, *f) 517 | } else if strings.HasPrefix(comment, "type:") { 518 | comment = comment[5:] 519 | s, err := ParseStructDefinition(strings.NewReader(comment)) 520 | if err != nil { 521 | log.Fatal(err) 522 | } 523 | structs = append(structs, *s) 524 | } else if strings.HasPrefix(comment, "enum:") { 525 | comment = comment[5:] 526 | e, err := ParseEnumDefinition(strings.NewReader(comment)) 527 | if err != nil { 528 | log.Fatal(err) 529 | } 530 | enums = append(enums, *e) 531 | } 532 | } 533 | f.Close() 534 | buf := &bytes.Buffer{} 535 | fmt.Fprintf(buf, ` 536 | // This file was autogenerated using go run mkcode.go %s 537 | // DO NOT EDIT. 538 | 539 | package %s 540 | 541 | `, strings.Join(os.Args[1:], " "), file.Name) 542 | 543 | funcs: 544 | for _, function := range functions { 545 | for _, param := range function.Params { 546 | if param.Type[0] == '*' { 547 | fmt.Fprintln(buf, `import "unsafe"`) 548 | break funcs 549 | } 550 | } 551 | } 552 | structs: 553 | for _, st := range structs { 554 | for _, m := range st.Members { 555 | if m.Array == 1 && !strings.HasPrefix(m.Name, "Reserved") { 556 | fmt.Fprintln(buf, `import "reflect"`) 557 | break structs 558 | } 559 | } 560 | } 561 | 562 | for _, enum := range enums { 563 | fmt.Fprintf(buf, ` 564 | // The %[1]s constants have been derived from the %[2]s enum definition. 565 | type %[1]s uint32; const ( 566 | `, 567 | enum.Name, enum.OriginalName) 568 | for i, member := range enum.Members { 569 | if i == 0 { 570 | fmt.Fprintf(buf, "%s %s = %d\n", member.Name, enum.Name, member.Value) 571 | } else { 572 | fmt.Fprintf(buf, "%s = %d\n", member.Name, member.Value) 573 | } 574 | } 575 | fmt.Fprint(buf, ")\n") 576 | } 577 | 578 | if len(functions) != 0 { 579 | fmt.Fprintln(buf, "var (") 580 | for _, function := range functions { 581 | fmt.Fprintf(buf, `proc%[1]s = modntdll.NewProc("%[1]s")`, function.Name) 582 | fmt.Fprintln(buf) 583 | } 584 | fmt.Fprintln(buf, ")") 585 | } 586 | 587 | for _, st := range structs { 588 | fmt.Fprintf(buf, ` 589 | // %[1]s has been derived from the %[2]s struct definition. 590 | type %[1]s struct { 591 | `, 592 | st.Name, st.OriginalName) 593 | for _, m := range st.Members { 594 | if m.Array > 0 { 595 | fmt.Fprintf(buf, "%s [%d]%s\n", m.Name, m.Array, m.Type) 596 | } else { 597 | fmt.Fprintf(buf, "%s %s\n", m.Name, m.Type) 598 | } 599 | } 600 | fmt.Fprint(buf, "}\n\n") 601 | for _, m := range st.Members { 602 | if m.Array == 1 && !strings.HasPrefix(m.Name, "Reserved") { 603 | fmt.Fprintf(buf, ` 604 | // %[2]sSlice returns a slice over the elements of %[1]s.%[2]s. 605 | // 606 | // Beware: The data is not copied out of %[1]s. The size can usually be taken from an other member of the struct (%[1]s). 607 | func (t *%[1]s) %[2]sSlice(size int) []%[3]s { 608 | s := []%[3]s{} 609 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s)) 610 | hdr.Data = uintptr(unsafe.Pointer(&t.%[2]s[0])) 611 | hdr.Len = size 612 | hdr.Cap = size 613 | return s 614 | } 615 | 616 | // Set%[2]sSlice copies s into the memory at %[1]s.%[2]s. 617 | // 618 | // Beware: No bounds check is performed. Another member of the struct (%[1]s) usually has to be set to the array size. 619 | func (t *%[1]s) Set%[2]sSlice(s []%[3]s) { 620 | s1 := []%[3]s{} 621 | hdr := (*reflect.SliceHeader)(unsafe.Pointer(&s1)) 622 | hdr.Data = uintptr(unsafe.Pointer(&t.%[2]s[0])) 623 | hdr.Len = len(s) 624 | hdr.Cap = len(s) 625 | copy(s1, s) 626 | } 627 | `, st.Name, m.Name, m.Type) 628 | } 629 | } 630 | } 631 | 632 | for _, function := range functions { 633 | var plist, alist []string 634 | var out, inout, opt, reserved, unknown []string 635 | var comment string 636 | for _, param := range function.Params { 637 | switch param.Direction { 638 | case DirectionIn: // default, don't mention 639 | case DirectionInOpt: 640 | opt = append(opt, param.Name) 641 | case DirectionOut: 642 | out = append(out, param.Name) 643 | case DirectionOutOpt: 644 | out = append(out, param.Name) 645 | opt = append(opt, param.Name) 646 | case DirectionInOut: 647 | inout = append(inout, param.Name) 648 | case DirectionInOutOpt: 649 | inout = append(inout, param.Name) 650 | opt = append(opt, param.Name) 651 | case DirectionReserved: 652 | reserved = append(reserved, param.Name) 653 | default: 654 | unknown = append(unknown, param.Name) 655 | } 656 | alist = append(alist, fmt.Sprintf("%s %s", param.Name, param.Type)) 657 | if param.Type == "bool" { 658 | plist = append(plist, fmt.Sprintf("fromBool(%s)", param.Name)) 659 | } else if param.Type[0] == '*' { 660 | plist = append(plist, fmt.Sprintf("uintptr(unsafe.Pointer(%s))", param.Name)) 661 | } else { 662 | plist = append(plist, fmt.Sprintf("uintptr(%s)", param.Name)) 663 | } 664 | // alist = append(alist, fmt.Sprintf("p%d %s", n, param.Type)) 665 | // plist = append(plist, "p"+strconv.Itoa(n)) 666 | } 667 | if len(out) > 0 { 668 | comment = fmt.Sprintf("// OUT-parameter: %s.\n", strings.Join(out, ", ")) 669 | } 670 | if len(inout) > 0 { 671 | comment += fmt.Sprintf("// INOUT-parameter: %s.\n", strings.Join(inout, ", ")) 672 | } 673 | if len(reserved) > 0 { 674 | comment += fmt.Sprintf("// RESERVED-parameter: %s.\n", strings.Join(reserved, ", ")) 675 | } 676 | if len(opt) > 0 { 677 | comment += fmt.Sprintf("// *OPT-parameter: %s.\n", strings.Join(opt, ", ")) 678 | } 679 | if len(unknown) > 0 { 680 | comment += fmt.Sprintf("// unknown-parameter: %s.\n", strings.Join(unknown, ", ")) 681 | } 682 | 683 | returnExpression := function.Type + "(r0)" 684 | if function.Type == "bool" { 685 | returnExpression = "r0 != 0" 686 | } 687 | fmt.Fprintf(buf, ` 688 | %[6]sfunc %[1]s(%[2]s) %[3]s { 689 | r0, _, _ := proc%[1]s.Call(%[4]s) 690 | return %[5]s 691 | } 692 | 693 | `, function.Name, "\n"+strings.Join(alist, ",\n")+",\n", function.Type, strings.Join(plist, ",\n"), returnExpression, comment) 694 | } 695 | 696 | f, err = os.Create(outfile) 697 | if err != nil { 698 | log.Fatal(err) 699 | } 700 | data, err := format.Source(buf.Bytes()) 701 | if err != nil { 702 | log.Fatal(string(buf.Bytes()), err) 703 | } 704 | f.Write(data) 705 | f.Close() 706 | } 707 | --------------------------------------------------------------------------------
59 | //

Return value/code

60 | //
61 | //

Description

62 | //
64 | //

0x00000000

65 | //

STATUS_SUCCESS

66 | //
67 | //

The operation completed successfully.

68 | //
70 | //

0x00000000

71 | //

STATUS_WAIT_0

72 | //
73 | //

The caller specified WaitAny for WaitType and one of 74 | // the dispatcher objects in the Object array has been set to the signaled 75 | // state.

76 | //