From 25e8e39d4ade7a2f33b363c4310984fed65fa1b5 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Thu, 10 Oct 2024 01:39:06 +1000 Subject: [PATCH] Bugfixes: Force timeline message to be a string. (#3811) If the timeline message column was not a string, it would not be emitted at all. This PR forces it to be a string. Also handle floats in table output. Update vfilter to fix LIMIT bug in GROUP BY clauses. --- docs/references/vql.yaml | 34 +++++++++++++++++++ go.mod | 4 +-- go.sum | 4 +++ .../src/components/core/table.jsx | 5 +-- timelines/transformer.go | 13 ++++++- 5 files changed, 55 insertions(+), 5 deletions(-) diff --git a/docs/references/vql.yaml b/docs/references/vql.yaml index ee765a7a64..3e2291cc83 100644 --- a/docs/references/vql.yaml +++ b/docs/references/vql.yaml @@ -3668,6 +3668,28 @@ - linux_amd64_cgo - windows_386_cgo - windows_amd64_cgo +- name: hunt_info + description: | + Retrieve the hunt information. + + This function is a convenience function to the full hunts() + plugin, and can retrieve the hunt information for a specific hunt + id. As a convenience, the function will also accept a flow id for + flows which were launched by the hunt. These flow IDs have a + specific format indicating they were launched from a hunt. + + type: Function + args: + - name: hunt_id + type: string + description: | + Hunt Id to look up or a flow id created by that hunt + (e.g. F.CRUU3KIE5D73G.H). + + metadata: + permissions: READ_RESULTS + platforms: + - linux_amd64_cgo - name: hunt_results description: | Retrieve the results of a hunt. @@ -5784,6 +5806,12 @@ - name: raw type: bool description: Emit raw events (no parsed). + - name: start_time + type: time.Time + description: Only parse events newer than this time (default all times). + - name: end_time + type: time.Time + description: Only parse events older than this time (default all times). metadata: permissions: FILESYSTEM_READ platforms: @@ -10254,6 +10282,12 @@ - name: raw type: bool description: Emit raw events (no parsed). + - name: start_time + type: time.Time + description: Only parse events newer than this time (default all times). + - name: end_time + type: time.Time + description: Only parse events older than this time (default all times). metadata: permissions: FILESYSTEM_READ platforms: diff --git a/go.mod b/go.mod index c58a9802ca..fd86fb0058 100644 --- a/go.mod +++ b/go.mod @@ -78,7 +78,7 @@ require ( golang.org/x/mod v0.17.0 golang.org/x/net v0.27.0 golang.org/x/sys v0.25.0 - golang.org/x/text v0.17.0 + golang.org/x/text v0.19.0 golang.org/x/time v0.3.0 google.golang.org/api v0.146.0 google.golang.org/genproto v0.0.0-20231009173412-8bfb1ae86b6c // indirect @@ -96,7 +96,7 @@ require ( www.velocidex.com/golang/go-prefetch v0.0.0-20240910051453-2385582c1c22 www.velocidex.com/golang/oleparse v0.0.0-20230217092320-383a0121aafe www.velocidex.com/golang/regparser v0.0.0-20240404115756-2169ac0e3c09 - www.velocidex.com/golang/vfilter v0.0.0-20240812032614-1f95429e06af + www.velocidex.com/golang/vfilter v0.0.0-20241009150353-76c3a28b1767 ) require ( diff --git a/go.sum b/go.sum index 3222d42bc1..fbfbe12388 100644 --- a/go.sum +++ b/go.sum @@ -767,6 +767,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -896,5 +898,7 @@ www.velocidex.com/golang/regparser v0.0.0-20240404115756-2169ac0e3c09 h1:G1RWYBX www.velocidex.com/golang/regparser v0.0.0-20240404115756-2169ac0e3c09/go.mod h1:pxSECT5mWM3goJ4sxB4HCJNKnKqiAlpyT8XnvBwkLGU= www.velocidex.com/golang/vfilter v0.0.0-20240812032614-1f95429e06af h1:klCJBImYvYAAfCy8STae7xju1o5pu2AUerBqPyymryM= www.velocidex.com/golang/vfilter v0.0.0-20240812032614-1f95429e06af/go.mod h1:P50KPQr2LpWVAu7ilGH8CBLBASGtOJ2971yA9YhR8rY= +www.velocidex.com/golang/vfilter v0.0.0-20241009150353-76c3a28b1767 h1:XUBc9OV6JZuLjIuGSyRS5sZmkWWdfav8SazJBy3MNeI= +www.velocidex.com/golang/vfilter v0.0.0-20241009150353-76c3a28b1767/go.mod h1:P50KPQr2LpWVAu7ilGH8CBLBASGtOJ2971yA9YhR8rY= www.velocidex.com/golang/vtypes v0.0.0-20240123105603-069d4a7f435c h1:rL/It+Ig+mvIhmy9vl5gg5b6CX2J12x0v2SXIT2RoWE= www.velocidex.com/golang/vtypes v0.0.0-20240123105603-069d4a7f435c/go.mod h1:tjaJNlBWbvH4cEMrEu678CFR2hrtcdyPINIpRxrOh4U= diff --git a/gui/velociraptor/src/components/core/table.jsx b/gui/velociraptor/src/components/core/table.jsx index 623f398502..11bc7bd263 100644 --- a/gui/velociraptor/src/components/core/table.jsx +++ b/gui/velociraptor/src/components/core/table.jsx @@ -400,7 +400,7 @@ class VeloTable extends Component { export default VeloTable; -const int_regex = /^-?[0-9]+$/; +const int_regex = /^-?[0-9.]+$/; // The JSON response from the server is encoded as a strict protobuf // with string cell values. Here we expand it into arbitrary JSON objects. @@ -423,7 +423,8 @@ export function PrepareData(value) { } else if (cell[0] === "{" || cell[0] === "[") { cell = JSONparse(cell); } else if(cell.match(int_regex)) { - cell = parseInt(cell); + // This works on int or floats the same. + cell = parseFloat(cell); } else if(cell[0] === " ") { cell = cell.substr(1); } diff --git a/timelines/transformer.go b/timelines/transformer.go index 9064a37a0f..f223588d86 100644 --- a/timelines/transformer.go +++ b/timelines/transformer.go @@ -1,6 +1,7 @@ package timelines import ( + "fmt" "time" "github.com/Velocidex/ordereddict" @@ -45,7 +46,8 @@ func (self timelineTransformer) Transform( if message_column == "" { message_column = "Message" } - message, _ := event.GetString(message_column) + message_any, _ := event.Get(message_column) + message := toStr(message_any) timestamp_description_column := self.TimestampDescriptionColumn if timestamp_description_column == "" { @@ -64,3 +66,12 @@ func (self timelineTransformer) Transform( Source: source, } } + +func toStr(in interface{}) string { + s, ok := in.(string) + if ok { + return s + } + + return fmt.Sprintf("%v", in) +}