Skip to content

Commit

Permalink
Added a few more artifacts.
Browse files Browse the repository at this point in the history
  • Loading branch information
scudette committed Aug 16, 2018
1 parent d775bf9 commit bc37c0d
Show file tree
Hide file tree
Showing 16 changed files with 309 additions and 47 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,9 @@ release:
-o output/velociraptor ./bin/
strip output/velociraptor

install: release
install -D output/velociraptor \
$(DESTDIR)$(prefix)/usr/bin/velociraptor

clean:
rm -f gui/assets/ab0x.go
18 changes: 12 additions & 6 deletions artifacts/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ type Repository struct {
loaded_dirs []string
}

func (self *Repository) LoadDirectory(dirname string) error {
func (self *Repository) LoadDirectory(dirname string) (*int, error) {
count := 0
if utils.InString(&self.loaded_dirs, dirname) {
return nil
return &count, nil
}
self.loaded_dirs = append(self.loaded_dirs, dirname)
return filepath.Walk(dirname,
return &count, filepath.Walk(dirname,
func(file_path string, info os.FileInfo, err error) error {
if err != nil {
return errors.WithStack(err)
Expand All @@ -49,6 +50,7 @@ func (self *Repository) LoadDirectory(dirname string) error {
}

self.data[artifact.Name] = artifact
count += 1
}
return nil
})
Expand Down Expand Up @@ -225,10 +227,12 @@ func GetGlobalRepository(config_obj *config.Config) (*Repository, error) {

logger := logging.NewLogger(config_obj)
if config_obj.Frontend.ArtifactsPath != "" {
logger.Info("Loading artifacts from %s", config_obj.Frontend.ArtifactsPath)
err := global_repository.LoadDirectory(config_obj.Frontend.ArtifactsPath)
count, err := global_repository.LoadDirectory(
config_obj.Frontend.ArtifactsPath)
switch errors.Cause(err).(type) {
// PathError is not fatal - it means we just cant load the directory.

// PathError is not fatal - it means we just
// cant load the directory.
case *os.PathError:
logger.Info("Unable to load artifacts from directory "+
"%s (skipping): %v", config_obj.Frontend.ArtifactsPath, err)
Expand All @@ -239,6 +243,8 @@ func GetGlobalRepository(config_obj *config.Config) (*Repository, error) {
// parse the artifacts themselves.
return nil, err
}
logger.Info("Loaded %d artifacts from %s",
*count, config_obj.Frontend.ArtifactsPath)
}
return global_repository, nil
}
46 changes: 46 additions & 0 deletions artifacts/definitions/docker/docker_info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Linux.Applications.Docker.Info
description: Get Dockers info by connecting to its socket.
parameters:
- name: dockerSocket
description: |
Docker server socket. You will normally need to be root to connect.
default: /var/run/docker.sock
sources:
- precondition: |
SELECT OS From info() where OS = 'linux'
queries:
- LET data = SELECT parse_json(data=Content) as JSON
FROM http_client(url=dockerSocket + ":unix/info")
- SELECT JSON.ID as ID,
JSON.Containers as Containers,
JSON.ContainersRunning as ContainersRunning,
JSON.ContainersPaused as ContainersPaused,
JSON.ContainersStopped as ContainersStopped,
JSON.Images as Images,
JSON.Driver as Driver,
JSON.MemoryLimit as MemoryLimit,
JSON.SwapLimit as SwapLimit,
JSON.KernelMemory as KernelMemory,
JSON.CpuCfsPeriod as CpuCfsPeriod,
JSON.CpuCfsQuota as CpuCfsQuota,
JSON.CPUShares as CPUShares,
JSON.CPUSet as CPUSet,
JSON.IPv4Forwarding as IPv4Forwarding,
JSON.BridgeNfIptables as BridgeNfIptables,
JSON.BridgeNfIp6tables as BridgeNfIp6tables,
JSON.OomKillDisable as OomKillDisable,
JSON.LoggingDriver as LoggingDriver,
JSON.CgroupDriver as CgroupDriver,
JSON.KernelVersion as KernelVersion,
JSON.OperatingSystem as OperatingSystem,
JSON.OSType as OSType,
JSON.Architecture as Architecture,
JSON.NCPU as NCPU,
JSON.MemTotal as MemTotal,
JSON.HttpProxy as HttpProxy,
JSON.HttpsProxy as HttpsProxy,
JSON.NoProxy as NoProxy,
JSON.Name as Name,
JSON.ServerVersion as ServerVersion,
JSON.DockerRootDir as DockerRootDir
FROM data
23 changes: 23 additions & 0 deletions artifacts/definitions/docker/docker_version.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Linux.Applications.Docker.Version
description: Get Dockers version by connecting to its socket.
parameters:
- name: dockerSocket
description: |
Docker server socket. You will normally need to be root to connect.
default: /var/run/docker.sock
sources:
- precondition: |
SELECT OS From info() where OS = 'linux'
queries:
- LET data = SELECT parse_json(data=Content) as JSON
FROM http_client(url=dockerSocket + ":unix/version")
- SELECT JSON.Version as Version,
JSON.ApiVersion as ApiVersion,
JSON.MinAPIVersion as MinAPIVersion,
JSON.GitCommit as GitCommit,
JSON.GoVersion as GoVersion,
JSON.Os as Os,
JSON.Arch as Arch,
JSON.KernelVersion as KernelVersion,
JSON.BuildTime as BuildTime
FROM data
29 changes: 29 additions & 0 deletions artifacts/definitions/linux/cpu_time.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Linux.Sys.CPUTime
description: |
Displays information from /proc/stat file about the time the cpu
cores spent in different parts of the system.
parameters:
- name: procStat
default: /proc/stat
sources:
- precondition: |
SELECT OS From info() where OS = 'linux'
queries:
- LET raw = SELECT * FROM split_records(
filenames=procStat,
regex=' +',
columns=['core', 'user', 'nice', 'system',
'idle', 'iowait', 'irq', 'softirq',
'steal', 'guest', 'guest_nice'])
WHERE core =~ 'cpu.+'
- SELECT core AS Core,
atoi(string=user) as User,
atoi(string=nice) as Nice,
atoi(string=system) as System,
atoi(string=idle) as Idle,
atoi(string=iowait) as IOWait,
atoi(string=irq) as IRQ,
atoi(string=softirq) as SoftIRQ,
atoi(string=steal) as Steal,
atoi(string=guest) as Guest,
atoi(string=guest_nice) as GuestNice FROM raw
46 changes: 46 additions & 0 deletions artifacts/definitions/linux/crontab.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Linux.Sys.Crontab
description: |
Displays parsed information from crontab.
parameters:
- name: cronTabGlob
default: /etc/crontab,/etc/cron.d/**,/var/at/tabs/**,/var/spool/cron/**,/var/spool/cron/crontabs/**
sources:
- precondition: |
SELECT OS From info() where OS = 'linux'
queries:
- |
LET raw = SELECT * FROM foreach(
row={
SELECT FullPath from glob(globs=split(string=cronTabGlob, sep=","))
},
query={
SELECT FullPath, data, parse_string_with_regex(
string=data,
regex=[
/* Regex for event (Starts with @) */
"^(?P<Event>@[a-zA-Z]+)\\s+(?P<Command>.+)",
/* Regex for regular command. */
"^(?P<Minute>[^\\s]+)\\s+"+
"(?P<Hour>[^\\s]+)\\s+"+
"(?P<DayOfMonth>[^\\s]+)\\s+"+
"(?P<Month>[^\\s]+)\\s+"+
"(?P<DayOfWeek>[^\\s]+)\\s+"+
"(?P<Command>.+)$"]) as Record
/* Read lines from the file and filter ones that start with "#" */
FROM split_records(
filenames=FullPath,
regex="\n", columns=["data"]) WHERE not data =~ "^\\s*#"
}) WHERE Record.Command
- |
SELECT Record.Event AS Event,
Record.Minute AS Minute,
Record.Hour AS Hour,
Record.DayOfMonth AS DayOfMonth,
Record.Month AS Month,
Record.DayOfWeek AS DayOfWeek,
Record.Command AS Command,
FullPath AS Path
FROM raw
42 changes: 38 additions & 4 deletions bin/artifacts.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/ghodss/yaml"
"gopkg.in/alecthomas/kingpin.v2"
"regexp"
"strings"
actions_proto "www.velocidex.com/golang/velociraptor/actions/proto"
artifacts "www.velocidex.com/golang/velociraptor/artifacts"
config "www.velocidex.com/golang/velociraptor/config"
Expand All @@ -21,7 +22,12 @@ var (
"list", "Print all artifacts")

artifact_command_list_name = artifact_command_list.Arg(
"regex", "Regex of names to match.").String()
"regex", "Regex of names to match.").
HintAction(listArtifacts).String()

artifact_command_list_verbose_count = artifact_command_list.Flag(
"verbose", "Show more details (Use -v -vv for even more)").
Short('v').Counter()

artifact_command_collect = artifact_command.Command(
"collect", "Collect all artifacts")
Expand All @@ -37,6 +43,25 @@ var (
Required().String()
)

func listArtifacts() []string {
result := []string{}
config_obj := get_config_or_default()
repository, err := artifacts.GetGlobalRepository(config_obj)
if err != nil {
return result
}
for _, name := range repository.List() {
result = append(result, name)
}
return result
}

func getFilterRegEx(pattern string) (*regexp.Regexp, error) {
pattern = strings.Replace(pattern, "*", ".*", -1)
pattern = "^" + pattern + "$"
return regexp.Compile(pattern)
}

func collectArtifact(
config_obj *config.Config,
repository *artifacts.Repository,
Expand Down Expand Up @@ -74,7 +99,7 @@ func getRepository(config_obj *config.Config) *artifacts.Repository {
repository, err := artifacts.GetGlobalRepository(config_obj)
kingpin.FatalIfError(err, "Artifact GetGlobalRepository ")
if *artifact_definitions_dir != "" {
err := repository.LoadDirectory(*artifact_definitions_dir)
_, err := repository.LoadDirectory(*artifact_definitions_dir)
if err != nil {
logging.NewLogger(config_obj).Error("Artifact LoadDirectory", err)
}
Expand All @@ -88,7 +113,7 @@ func doArtifactCollect() {
repository := getRepository(config_obj)
var name_regex *regexp.Regexp
if *artifact_command_collect_name != "" {
re, err := regexp.Compile(*artifact_command_collect_name)
re, err := getFilterRegEx(*artifact_command_collect_name)
kingpin.FatalIfError(err, "Artifact name regex not valid")

name_regex = re
Expand Down Expand Up @@ -120,7 +145,7 @@ func doArtifactList() {

var name_regex *regexp.Regexp
if *artifact_command_list_name != "" {
re, err := regexp.Compile(*artifact_command_list_name)
re, err := getFilterRegEx(*artifact_command_list_name)
kingpin.FatalIfError(err, "Artifact name regex not valid")

name_regex = re
Expand All @@ -132,6 +157,11 @@ func doArtifactList() {
continue
}

if *artifact_command_list_verbose_count == 0 {
fmt.Println(name)
continue
}

artifact, pres := repository.Get(name)
if !pres {
kingpin.Fatalf("Artifact %s not found", name)
Expand All @@ -143,6 +173,10 @@ func doArtifactList() {
fmt.Printf("Definition %s:\n***********\n%v\n",
artifact.Name, string(res))

if *artifact_command_list_verbose_count <= 1 {
continue
}

request := &actions_proto.VQLCollectorArgs{}
err = artifacts.Compile(artifact, request)
kingpin.FatalIfError(err, "Unable to compile artifact.")
Expand Down
3 changes: 3 additions & 0 deletions bin/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ var (
)

func doShowConfig() {
if *config_path == "" {
kingpin.Fatalf("Config file must be specified.")
}
config_obj, err := config.LoadClientConfig(*config_path)
kingpin.FatalIfError(err, "Unable to load config.")

Expand Down
8 changes: 6 additions & 2 deletions bin/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import (
)

var (
app = kingpin.New("velociraptor", "An advanced incident response agent.")
config_path = app.Flag("config", "The configuration file.").String()
app = kingpin.New("velociraptor",
"An advanced incident response and monitoring agent.")
config_path = app.Flag("config", "The configuration file.").Short('c').
Envar("VELOCIRAPTOR_CONFIG").String()

artifact_definitions_dir = app.Flag(
"definitions", "A directory containing artifact definitions").String()
Expand Down Expand Up @@ -50,6 +52,8 @@ func get_config_or_default() *config.Config {
}

func main() {
app.HelpFlag.Short('h')
app.UsageTemplate(kingpin.CompactUsageTemplate)
command := kingpin.MustParse(app.Parse(os.Args[1:]))

for _, command_handler := range command_handlers {
Expand Down
5 changes: 4 additions & 1 deletion debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
# This special exception was added by Craig Small in version 0.37 of dh-make.

# Uncomment this to turn on verbose mode.
# export DH_VERBOSE=1
export DH_VERBOSE=1

%:
dh $@

override_dh_auto_test:

override_dh_auto_build:
make release
3 changes: 0 additions & 3 deletions debian/velociraptor.substvars

This file was deleted.

37 changes: 37 additions & 0 deletions vql/functions/functions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package functions

import (
"context"
"strconv"
vql_subsystem "www.velocidex.com/golang/velociraptor/vql"
vfilter "www.velocidex.com/golang/vfilter"
)

type _ToIntArgs struct {
String string `vfilter:"required,field=string"`
}

type _ToInt struct{}

func (self _ToInt) Call(
ctx context.Context,
scope *vfilter.Scope,
args *vfilter.Dict) vfilter.Any {
arg := &_ToIntArgs{}
err := vfilter.ExtractArgs(scope, args, arg)
if err != nil {
scope.Log("%s: %s", self.Name(), err.Error())
return vfilter.Null{}
}

result, _ := strconv.Atoi(arg.String)
return result
}

func (self _ToInt) Name() string {
return "atoi"
}

func init() {
vql_subsystem.RegisterFunction(&_ToInt{})
}
Loading

0 comments on commit bc37c0d

Please sign in to comment.