summaryrefslogtreecommitdiff
path: root/packages/w32/alpc_typedef.go
blob: 52b35c97d53435637da7a2cca2a65ed69a233b85 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
package w32

import (
	"errors"
)

// nt!_ALPC_MESSAGE_ATTRIBUTES
//  +0x000 AllocatedAttributes : Uint4B
//  +0x004 ValidAttributes  : Uint4B
type ALPC_MESSAGE_ATTRIBUTES struct {
	AllocatedAttributes uint32
	ValidAttributes     uint32
}

type ALPC_CONTEXT_ATTR struct {
	PortContext    *AlpcPortContext
	MessageContext uintptr
	Sequence       uint32
	MessageId      uint32
	CallbackId     uint32
}

type ALPC_HANDLE_ATTR struct {
	Flags         uint32
	Handle        HANDLE
	ObjectType    uint32
	DesiredAccess uint32
}

// nt!_CLIENT_ID
//  +0x000 UniqueProcess    : Ptr64 Void
//  +0x008 UniqueThread     : Ptr64 Void
type CLIENT_ID struct {
	UniqueProcess uintptr
	UniqueThread  uintptr
}

// nt!_UNICODE_STRING
//  +0x000 Length           : Uint2B
//  +0x002 MaximumLength    : Uint2B
//  +0x008 Buffer           : Ptr64 Uint2B
type UNICODE_STRING struct {
	Length        uint16
	MaximumLength uint16
	_             [4]byte // align to 0x08
	Buffer        *uint16
}

// nt!_OBJECT_ATTRIBUTES
//  +0x000 Length           : Uint4B
//  +0x008 RootDirectory    : Ptr64 Void
//  +0x010 ObjectName       : Ptr64 _UNICODE_STRING
//  +0x018 Attributes       : Uint4B
//  +0x020 SecurityDescriptor : Ptr64 Void
//  +0x028 SecurityQualityOfService : Ptr64 Void
type OBJECT_ATTRIBUTES struct {
	Length                   uint32
	_                        [4]byte // align to 0x08
	RootDirectory            HANDLE
	ObjectName               *UNICODE_STRING
	Attributes               uint32
	_                        [4]byte // align to 0x20
	SecurityDescriptor       *SECURITY_DESCRIPTOR
	SecurityQualityOfService *SECURITY_QUALITY_OF_SERVICE
}

// cf: http://j00ru.vexillium.org/?p=502 for legacy RPC
// nt!_PORT_MESSAGE
//    +0x000 u1               : <unnamed-tag>
//    +0x004 u2               : <unnamed-tag>
//    +0x008 ClientId         : _CLIENT_ID
//    +0x008 DoNotUseThisField : Float
//    +0x018 MessageId        : Uint4B
//    +0x020 ClientViewSize   : Uint8B
//    +0x020 CallbackId       : Uint4B
type PORT_MESSAGE struct {
	DataLength     uint16 // These are the two unnamed unions
	TotalLength    uint16 // without Length and ZeroInit
	Type           uint16
	DataInfoOffset uint16
	ClientId       CLIENT_ID
	MessageId      uint32
	_              [4]byte // align up to 0x20
	ClientViewSize uint64
}

func (pm PORT_MESSAGE) CallbackId() uint32 {
	return uint32(pm.ClientViewSize >> 32)
}

func (pm PORT_MESSAGE) DoNotUseThisField() float64 {
	panic("WE TOLD YOU NOT TO USE THIS FIELD")
}

const PORT_MESSAGE_SIZE = 0x28

// http://www.nirsoft.net/kernel_struct/vista/SECURITY_QUALITY_OF_SERVICE.html
type SECURITY_QUALITY_OF_SERVICE struct {
	Length              uint32
	ImpersonationLevel  uint32
	ContextTrackingMode byte
	EffectiveOnly       byte
	_                   [2]byte // align to 12 bytes
}

const SECURITY_QOS_SIZE = 12

// nt!_ALPC_PORT_ATTRIBUTES
//  +0x000 Flags            : Uint4B
//  +0x004 SecurityQos      : _SECURITY_QUALITY_OF_SERVICE
//  +0x010 MaxMessageLength : Uint8B
//  +0x018 MemoryBandwidth  : Uint8B
//  +0x020 MaxPoolUsage     : Uint8B
//  +0x028 MaxSectionSize   : Uint8B
//  +0x030 MaxViewSize      : Uint8B
//  +0x038 MaxTotalSectionSize : Uint8B
//  +0x040 DupObjectTypes   : Uint4B
//  +0x044 Reserved         : Uint4B
type ALPC_PORT_ATTRIBUTES struct {
	Flags               uint32
	SecurityQos         SECURITY_QUALITY_OF_SERVICE
	MaxMessageLength    uint64 // must be filled out
	MemoryBandwidth     uint64
	MaxPoolUsage        uint64
	MaxSectionSize      uint64
	MaxViewSize         uint64
	MaxTotalSectionSize uint64
	DupObjectTypes      uint32
	Reserved            uint32
}

const SHORT_MESSAGE_MAX_SIZE uint16 = 65535 // MAX_USHORT
const SHORT_MESSAGE_MAX_PAYLOAD uint16 = SHORT_MESSAGE_MAX_SIZE - PORT_MESSAGE_SIZE

// LPC uses the first 4 bytes of the payload as an LPC Command, but this is
// NOT represented here, to allow the use of raw ALPC. For legacy LPC, callers
// must include the command as part of their payload.
type AlpcShortMessage struct {
	PORT_MESSAGE
	Data [SHORT_MESSAGE_MAX_PAYLOAD]byte
}

func NewAlpcShortMessage() AlpcShortMessage {
	sm := AlpcShortMessage{}
	sm.TotalLength = SHORT_MESSAGE_MAX_SIZE
	return sm
}

func (sm *AlpcShortMessage) SetData(d []byte) (e error) {

	copy(sm.Data[:], d)
	if len(d) > int(SHORT_MESSAGE_MAX_PAYLOAD) {
		e = errors.New("data too big - truncated")
		sm.DataLength = SHORT_MESSAGE_MAX_PAYLOAD
		sm.TotalLength = SHORT_MESSAGE_MAX_SIZE
		return
	}
	sm.TotalLength = uint16(PORT_MESSAGE_SIZE + len(d))
	sm.DataLength = uint16(len(d))
	return

}

// TODO - is this still useful?
func (sm *AlpcShortMessage) GetData() []byte {
	if int(sm.DataLength) > int(SHORT_MESSAGE_MAX_PAYLOAD) {
		return sm.Data[:] // truncate
	}
	return sm.Data[:sm.DataLength]
}

func (sm *AlpcShortMessage) Reset() {
	// zero the PORT_MESSAGE header
	sm.PORT_MESSAGE = PORT_MESSAGE{}
	sm.TotalLength = SHORT_MESSAGE_MAX_SIZE
	sm.DataLength = 0
}

type AlpcPortContext struct {
	Handle HANDLE
}