Skip to content

Commit bdf9844

Browse files
committed
feat(event): New CreateSymbolicLinkObject event
The CreateSymbolicLinkObject event is fired when the new symbolic link is created within the object manager directory.
1 parent 97e5764 commit bdf9844

File tree

8 files changed

+158
-108
lines changed

8 files changed

+158
-108
lines changed

pkg/config/schema_windows.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ var schema = `
197197
"blacklist": {
198198
"type": "object",
199199
"properties": {
200-
"events": {"type": "array", "items": {"type": "string", "enum": ["CreateThread", "TerminateThread", "OpenProcess", "OpenThread", "SetThreadContext", "LoadImage", "UnloadImage", "CreateFile", "CloseFile", "ReadFile", "WriteFile", "DeleteFile", "RenameFile", "SetFileInformation", "EnumDirectory", "MapViewFile", "UnmapViewFile", "RegCreateKey", "RegOpenKey", "RegSetValue", "RegQueryValue", "RegQueryKey", "RegDeleteKey", "RegDeleteValue", "RegCloseKey", "Accept", "Send", "Recv", "Connect", "Disconnect", "Reconnect", "Retransmit", "CreateHandle", "CloseHandle", "DuplicateHandle", "QueryDns", "ReplyDns", "VirtualAlloc", "VirtualFree"]}},
200+
"events": {"type": "array", "items": {"type": "string", "enum": ["CreateThread", "TerminateThread", "OpenProcess", "OpenThread", "SetThreadContext", "LoadImage", "UnloadImage", "CreateFile", "CloseFile", "ReadFile", "WriteFile", "DeleteFile", "RenameFile", "SetFileInformation", "EnumDirectory", "MapViewFile", "UnmapViewFile", "RegCreateKey", "RegOpenKey", "RegSetValue", "RegQueryValue", "RegQueryKey", "RegDeleteKey", "RegDeleteValue", "RegCloseKey", "Accept", "Send", "Recv", "Connect", "Disconnect", "Reconnect", "Retransmit", "CreateHandle", "CloseHandle", "DuplicateHandle", "QueryDns", "ReplyDns", "VirtualAlloc", "VirtualFree", "CreateSymbolicLinkObject"]}},
201201
"images": {"type": "array", "items": {"type": "string", "minLength": 1}}
202202
},
203203
"additionalProperties": false

pkg/filter/rules.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -651,7 +651,8 @@ func (r *Rules) buildCompileResult() *config.RulesCompileResult {
651651
if typ == ktypes.MapViewFile || typ == ktypes.UnmapViewFile {
652652
rs.HasVAMapEvents = true
653653
}
654-
if typ == ktypes.OpenProcess || typ == ktypes.OpenThread || typ == ktypes.SetThreadContext {
654+
if typ == ktypes.OpenProcess || typ == ktypes.OpenThread || typ == ktypes.SetThreadContext ||
655+
typ == ktypes.CreateSymbolicLinkObject {
655656
rs.HasAuditAPIEvents = true
656657
}
657658
if typ.Subcategory() == ktypes.DNS {

pkg/kevent/flags.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,20 @@ var DNSOptsFlags = []ParamFlag{
259259
{"DISABLE_IDN_ENCODING", 0x00200000},
260260
{"APPEND_MULTILABEL", 0x00800000},
261261
}
262+
263+
// AccessMaskFlags describes the generic and specific access rights
264+
var AccessMaskFlags = []ParamFlag{
265+
{"DELETE", windows.DELETE},
266+
{"READ_CONTROL", windows.READ_CONTROL},
267+
{"WRITE_DAC", windows.WRITE_DAC},
268+
{"WRITE_OWNER", windows.WRITE_OWNER},
269+
{"SYNCHRONIZE", windows.SYNCHRONIZE},
270+
{"STANDARD_RIGHTS_REQUIRED", windows.STANDARD_RIGHTS_REQUIRED},
271+
{"STANDARD_RIGHTS_ALL", windows.STANDARD_RIGHTS_ALL},
272+
{"ACCESS_SYSTEM_SECURITY", windows.ACCESS_SYSTEM_SECURITY},
273+
{"MAXIMUM_ALLOWED", windows.MAXIMUM_ALLOWED},
274+
{"GENERIC_READ", windows.GENERIC_READ},
275+
{"GENERIC_WRITE", windows.GENERIC_WRITE},
276+
{"GENERIC_EXECUTE", windows.GENERIC_EXECUTE},
277+
{"GENERIC_ALL", windows.GENERIC_ALL},
278+
}

pkg/kevent/kparam_windows.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,18 @@ func (e *Kevent) produceParams(evt *etw.EventRecord) {
751751
n++
752752
}
753753
e.AppendParam(kparams.Callstack, kparams.Slice, callstack)
754+
case ktypes.CreateSymbolicLinkObject:
755+
source, offset := evt.ReadUTF16String(0)
756+
target, offset := evt.ReadUTF16String(offset)
757+
desiredAccess := evt.ReadUint32(offset)
758+
status := evt.ReadUint32(offset + 4)
759+
e.AppendParam(kparams.LinkSource, kparams.UnicodeString, source)
760+
e.AppendParam(kparams.LinkTarget, kparams.UnicodeString, target)
761+
e.AppendParam(kparams.DesiredAccess, kparams.Flags, desiredAccess, WithFlags(AccessMaskFlags))
762+
e.AppendParam(kparams.NTStatus, kparams.Status, status)
763+
if evt.HasStackTrace() {
764+
e.AppendParam(kparams.Callstack, kparams.Slice, evt.Callstack())
765+
}
754766
}
755767
}
756768

pkg/kevent/kparams/fields_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,9 @@ const (
245245
MemProtectMask = "protection_mask"
246246
// MemPageType identifies the parameter that represents the allocated region type.
247247
MemPageType = "page_type"
248+
249+
// LinkSource identifies the parameter that represents the source symbolic link object or other kernel object
250+
LinkSource = "source"
251+
// LinkTarget identifies the parameter that represents the target symbolic link object or other kernel object
252+
LinkTarget = "target"
248253
)

pkg/kevent/ktypes/category.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ const (
4747
Driver Category = "driver"
4848
// Mem is the category for memory events
4949
Mem Category = "mem"
50+
// Object the category for object manager events
51+
Object Category = "object"
5052
// Other is the category for uncategorized events
5153
Other Category = "other"
5254
// Unknown is the category for events that couldn't match any of the previous categories
@@ -79,5 +81,6 @@ func Categories() []string {
7981
string(Driver),
8082
string(Other),
8183
string(Unknown),
84+
string(Object),
8285
}
8386
}

pkg/kevent/ktypes/ktypes_windows.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ var (
207207
// StackWalk represents stack walk event with the collection of return addresses
208208
StackWalk = pack(windows.GUID{Data1: 0xdef2fe46, Data2: 0x7bd6, Data3: 0x4b80, Data4: [8]byte{0xbd, 0x94, 0xf5, 0x7f, 0xe2, 0x0d, 0x0c, 0xe3}}, 32)
209209

210+
// CreateSymbolicLinkObject represents the event emitted by the object manager when the new symbolic link is created within the object manager directory
211+
CreateSymbolicLinkObject = pack(AuditAPIEventGUID, 3)
212+
210213
// UnknownKtype designates unknown kernel event type
211214
UnknownKtype = pack(windows.GUID{}, 0)
212215
)
@@ -322,6 +325,8 @@ func (k Ktype) String() string {
322325
return "ReplyDns"
323326
case StackWalk:
324327
return "StackWalk"
328+
case CreateSymbolicLinkObject:
329+
return "CreateSymbolicLinkObject"
325330
default:
326331
return ""
327332
}
@@ -355,6 +360,8 @@ func (k Ktype) Category() Category {
355360
return Handle
356361
case VirtualAlloc, VirtualFree:
357362
return Mem
363+
case CreateSymbolicLinkObject:
364+
return Object
358365
default:
359366
return Unknown
360367
}
@@ -455,6 +462,8 @@ func (k Ktype) Description() string {
455462
return "Sends a DNS query to the name server"
456463
case ReplyDNS:
457464
return "Receives the response from the DNS server"
465+
case CreateSymbolicLinkObject:
466+
return "Creates the symbolic link within the object manager directory"
458467
default:
459468
return ""
460469
}
@@ -541,7 +550,7 @@ func (k *Ktype) HookID() uint16 {
541550
// Source designates the provenance of this event type.
542551
func (k Ktype) Source() EventSource {
543552
switch k {
544-
case OpenProcess, OpenThread, SetThreadContext:
553+
case OpenProcess, OpenThread, SetThreadContext, CreateSymbolicLinkObject:
545554
return AuditAPICallsLogger
546555
case QueryDNS, ReplyDNS:
547556
return DNSLogger
@@ -556,7 +565,7 @@ func (k Ktype) Source() EventSource {
556565
// events, but it appears first on the consumer callback
557566
// before other events published before it.
558567
func (k Ktype) CanArriveOutOfOrder() bool {
559-
return k.Category() == Registry || k.Subcategory() == DNS || k == OpenProcess || k == OpenThread || k == SetThreadContext
568+
return k.Category() == Registry || k.Subcategory() == DNS || k == OpenProcess || k == OpenThread || k == SetThreadContext || k == CreateSymbolicLinkObject
560569
}
561570

562571
// FromParts builds ktype from provider GUID and hook ID.

0 commit comments

Comments
 (0)