Skip to content

Commit 7cf8d38

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 20f4386 commit 7cf8d38

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
@@ -256,3 +256,20 @@ var DNSOptsFlags = []ParamFlag{
256256
{"DISABLE_IDN_ENCODING", 0x00200000},
257257
{"APPEND_MULTILABEL", 0x00800000},
258258
}
259+
260+
// AccessMaskFlags describes the generic and specific access rights
261+
var AccessMaskFlags = []ParamFlag{
262+
{"DELETE", windows.DELETE},
263+
{"READ_CONTROL", windows.READ_CONTROL},
264+
{"WRITE_DAC", windows.WRITE_DAC},
265+
{"WRITE_OWNER", windows.WRITE_OWNER},
266+
{"SYNCHRONIZE", windows.SYNCHRONIZE},
267+
{"STANDARD_RIGHTS_REQUIRED", windows.STANDARD_RIGHTS_REQUIRED},
268+
{"STANDARD_RIGHTS_ALL", windows.STANDARD_RIGHTS_ALL},
269+
{"ACCESS_SYSTEM_SECURITY", windows.ACCESS_SYSTEM_SECURITY},
270+
{"MAXIMUM_ALLOWED", windows.MAXIMUM_ALLOWED},
271+
{"GENERIC_READ", windows.GENERIC_READ},
272+
{"GENERIC_WRITE", windows.GENERIC_WRITE},
273+
{"GENERIC_EXECUTE", windows.GENERIC_EXECUTE},
274+
{"GENERIC_ALL", windows.GENERIC_ALL},
275+
}

pkg/kevent/kparam_windows.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,18 @@ func (e *Kevent) produceParams(evt *etw.EventRecord) {
735735
n++
736736
}
737737
e.AppendParam(kparams.Callstack, kparams.Slice, callstack)
738+
case ktypes.CreateSymbolicLinkObject:
739+
source, offset := evt.ReadUTF16String(0)
740+
target, offset := evt.ReadUTF16String(offset)
741+
desiredAccess := evt.ReadUint32(offset)
742+
status := evt.ReadUint32(offset + 4)
743+
e.AppendParam(kparams.LinkSource, kparams.UnicodeString, source)
744+
e.AppendParam(kparams.LinkTarget, kparams.UnicodeString, target)
745+
e.AppendParam(kparams.DesiredAccess, kparams.Flags, desiredAccess, WithFlags(AccessMaskFlags))
746+
e.AppendParam(kparams.NTStatus, kparams.Status, status)
747+
if evt.HasStackTrace() {
748+
e.AppendParam(kparams.Callstack, kparams.Slice, evt.Callstack())
749+
}
738750
}
739751
}
740752

pkg/kevent/kparams/fields_windows.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,9 @@ const (
241241
MemProtectMask = "protection_mask"
242242
// MemPageType identifies the parameter that represents the allocated region type.
243243
MemPageType = "page_type"
244+
245+
// LinkSource identifies the parameter that represents the source symbolic link object or other kernel object
246+
LinkSource = "source"
247+
// LinkTarget identifies the parameter that represents the target symbolic link object or other kernel object
248+
LinkTarget = "target"
244249
)

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
}
@@ -540,7 +549,7 @@ func (k *Ktype) HookID() uint16 {
540549
// Source designates the provenance of this event type.
541550
func (k Ktype) Source() EventSource {
542551
switch k {
543-
case OpenProcess, OpenThread, SetThreadContext:
552+
case OpenProcess, OpenThread, SetThreadContext, CreateSymbolicLinkObject:
544553
return AuditAPICallsLogger
545554
case QueryDNS, ReplyDNS:
546555
return DNSLogger
@@ -555,7 +564,7 @@ func (k Ktype) Source() EventSource {
555564
// events, but it appears first on the consumer callback
556565
// before other events published before it.
557566
func (k Ktype) CanArriveOutOfOrder() bool {
558-
return k.Category() == Registry || k.Subcategory() == DNS || k == OpenProcess || k == OpenThread || k == SetThreadContext
567+
return k.Category() == Registry || k.Subcategory() == DNS || k == OpenProcess || k == OpenThread || k == SetThreadContext || k == CreateSymbolicLinkObject
559568
}
560569

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

0 commit comments

Comments
 (0)