diff --git a/eslog_zsh_completion.r b/eslog_zsh_completion.r new file mode 100644 index 0000000..b64ea98 --- /dev/null +++ b/eslog_zsh_completion.r @@ -0,0 +1,131 @@ +#compdef eslogger + +_eslogger() { + local -a commands + local context state line + + _arguments -C \ + '--format[Log format to use]:format:(json)' \ + '--oslog[Emit event data to oslog instead of stdout]' \ + '--oslog-subsystem[Log subsystem to use with --oslog]:subsystem:' \ + '--oslog-category[Log category to use with --oslog]:category:' \ + '--list-events[List supported events and exit]' \ + '--select[Select events from a specific program path prefix]:path:_files' \ + '(-h --help)'{-h,--help}'[Show help information]' \ + '*:event-types:_eslogger_event_types' +} + +# Event types from `eslogger --list-events` +_eslogger_event_types() { + local -a event_types + event_types=( + 'access:File access events' + 'authentication:Authentication events' + 'authorization_judgement:Authorization judgement events' + 'authorization_petition:Authorization petition events' + 'btm_launch_item_add:Background Task Management launch item add' + 'btm_launch_item_remove:Background Task Management launch item remove' + 'chdir:Directory change events' + 'chroot:Change root events' + 'clone:File clone events' + 'close:File close events' + 'copyfile:File copy events' + 'create:File/directory creation events' + 'cs_invalidated:Code signing invalidation events' + 'deleteextattr:Extended attribute deletion events' + 'dup:File descriptor duplication events' + 'exchangedata:File data exchange events' + 'exec:Process execution events' + 'exit:Process exit events' + 'fcntl:File control events' + 'file_provider_materialize:File Provider materialization events' + 'file_provider_update:File Provider update events' + 'fork:Process fork events' + 'fsgetpath:File system get path events' + 'get_task:Get task events' + 'get_task_inspect:Get task inspect events' + 'get_task_name:Get task name events' + 'get_task_read:Get task read events' + 'getattrlist:Get attribute list events' + 'getextattr:Get extended attribute events' + 'gatekeeper_user_override:Gatekeeper override events' + 'iokit_open:IOKit open events' + 'kextload:Kernel extension load events' + 'kextunload:Kernel extension unload events' + 'link:File link events' + 'listextattr:List extended attribute events' + 'login_login:Login events' + 'login_logout:Logout events' + 'lookup:File lookup events' + 'lw_session_lock:LoginWindow session lock events' + 'lw_session_login:LoginWindow session login events' + 'lw_session_logout:LoginWindow session logout events' + 'lw_session_unlock:LoginWindow session unlock events' + 'mmap:Memory map events' + 'mount:File system mount events' + 'mprotect:Memory protection events' + 'od_attribute_set:OpenDirectory attribute set events' + 'od_attribute_value_add:OpenDirectory attribute value add events' + 'od_attribute_value_remove:OpenDirectory attribute value remove events' + 'od_create_group:OpenDirectory create group events' + 'od_create_user:OpenDirectory create user events' + 'od_delete_group:OpenDirectory delete group events' + 'od_delete_user:OpenDirectory delete user events' + 'od_disable_user:OpenDirectory disable user events' + 'od_enable_user:OpenDirectory enable user events' + 'od_group_add:OpenDirectory group add events' + 'od_group_remove:OpenDirectory group remove events' + 'od_group_set:OpenDirectory group set events' + 'od_modify_password:OpenDirectory password modification events' + 'open:File open events' + 'openssh_login:OpenSSH login events' + 'openssh_logout:OpenSSH logout events' + 'proc_check:Process check events' + 'proc_suspend_resume:Process suspend/resume events' + 'profile_add:Profile add events' + 'profile_remove:Profile remove events' + 'pty_close:Pseudo-terminal close events' + 'pty_grant:Pseudo-terminal grant events' + 'readdir:Directory read events' + 'readlink:Symbolic link read events' + 'remote_thread_create:Remote thread creation events' + 'remount:File system remount events' + 'rename:File/directory rename events' + 'screensharing_attach:Screen sharing attach events' + 'screensharing_detach:Screen sharing detach events' + 'searchfs:File system search events' + 'setacl:Set access control list events' + 'setattrlist:Set attribute list events' + 'setegid:Set effective group ID events' + 'seteuid:Set effective user ID events' + 'setextattr:Set extended attribute events' + 'setflags:Set file flags events' + 'setgid:Set group ID events' + 'setmode:Set file mode events' + 'setowner:Set file owner events' + 'setregid:Set real and effective group ID events' + 'setreuid:Set real and effective user ID events' + 'settime:Set system time events' + 'setuid:Set user ID events' + 'signal:Signal events' + 'stat:File stat events' + 'su:su invocation events' + 'sudo:sudo invocation events' + 'tcc_modify:TCC database modification events' + 'trace:Tracing events' + 'truncate:File truncate events' + 'uipc_bind:Unix domain socket bind events' + 'uipc_connect:Unix domain socket connect events' + 'unlink:File unlink events' + 'unmount:File system unmount events' + 'utimes:File time update events' + 'write:File write events' + 'xp_malware_detected:XProtect malware detected events' + 'xp_malware_remediated:XProtect malware remediated events' + 'xpc_connect:XPC connection events' + ) + + _describe 'event types' event_types +} + +_eslogger "$@" diff --git a/tools/go/bincmp/go.mod b/tools/go/bincmp/go.mod new file mode 100644 index 0000000..9f936a0 --- /dev/null +++ b/tools/go/bincmp/go.mod @@ -0,0 +1,5 @@ +module gobincmp + +go 1.24.4 + +require github.com/glaslos/ssdeep v0.4.0 diff --git a/tools/go/bincmp/go.sum b/tools/go/bincmp/go.sum new file mode 100644 index 0000000..0212b5f --- /dev/null +++ b/tools/go/bincmp/go.sum @@ -0,0 +1,10 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/glaslos/ssdeep v0.4.0 h1:w9PtY1HpXbWLYgrL/rvAVkj2ZAMOtDxoGKcBHcUFCLs= +github.com/glaslos/ssdeep v0.4.0/go.mod h1:il4NniltMO8eBtU7dqoN+HVJ02gXxbpbUfkcyUvNtG0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/go/bincmp/gobincmp.go b/tools/go/bincmp/gobincmp.go new file mode 100644 index 0000000..7364d87 --- /dev/null +++ b/tools/go/bincmp/gobincmp.go @@ -0,0 +1,216 @@ +// main.go +package main + +import ( + "bytes" + "fmt" + "io" + "log" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/glaslos/ssdeep" +) + +const blockSize = 1024 * 1024 + +// main is the entry point of the program. +func main() { + // 1. Get and validate command-line arguments + if len(os.Args) != 3 { + usage := ` +Binwally (Go Version): Binary and Directory tree comparison tool + using the Fuzzy Hashing concept (ssdeep) + +Usage: go run . +` + fmt.Printf(usage) + os.Exit(1) + } + path1 := os.Args[1] + path2 := os.Args[2] + + info1, err1 := os.Stat(path1) + if err1 != nil { + log.Fatalf("Invalid path: %s", path1) + } + info2, err2 := os.Stat(path2) + if err2 != nil { + log.Fatalf("Invalid path: %s", path2) + } + + // 2. Route to appropriate comparison logic + if info1.IsDir() && info2.IsDir() { + // Both are directories + var diffs []int + fmt.Println("\nSCORE RESULT PATH") + compareTrees(path1, path2, &diffs) + + if len(diffs) == 0 { + fmt.Println("No diffs found\n") + } else { + totalScore := 0 + for _, score := range diffs { + totalScore += score + } + averageScore := totalScore / len(diffs) + fmt.Println("\nTotal files compared:", len(diffs)) + fmt.Printf("Overall match score: %d%%\n\n", averageScore) + } + } else if !info1.IsDir() && !info2.IsDir() { + // Both are files + hash1, err := ssdeep.HashFromFile(path1) // CORRECTED + if err != nil { + log.Fatalf("Failed to hash file %s: %v", path1, err) + } + hash2, err := ssdeep.HashFromFile(path2) // CORRECTED + if err != nil { + log.Fatalf("Failed to hash file %s: %v", path2, err) + } + score, err := ssdeep.Distance(hash1, hash2) // CORRECTED + if err != nil { + log.Fatalf("Failed to compare hashes: %v", err) + } + fmt.Printf("Overall match score: %d%%\n\n", score) + } else { + log.Fatal("Error: Both arguments must be files or both must be directories.") + } +} + +// compareTrees recursively compares two directory trees. +func compareTrees(dir1, dir2 string, diffs *[]int) { + // 1. Read contents of both directories + entries1, err := os.ReadDir(dir1) + if err != nil { + log.Printf("Error reading directory %s: %v", dir1, err) + return + } + entries2, err := os.ReadDir(dir2) + if err != nil { + log.Printf("Error reading directory %s: %v", dir2, err) + return + } + + // Create maps for quick lookup by name + map1 := make(map[string]os.DirEntry) + for _, e := range entries1 { + map1[e.Name()] = e + } + map2 := make(map[string]os.DirEntry) + for _, e := range entries2 { + map2[e.Name()] = e + } + + // 2. Find and report unique files/dirs + reportUniques(map1, map2, dir1, " <<< unique ", diffs) // In dir1 only + reportUniques(map2, map1, dir2, " >>> unique ", diffs) // In dir2 only + + // 3. Process common items + for name, e1 := range map1 { + if e2, ok := map2[name]; ok { + // Name exists in both directories + path1 := filepath.Join(dir1, name) + path2 := filepath.Join(dir2, name) + + isDir1 := e1.IsDir() + isDir2 := e2.IsDir() + + if isDir1 && isDir2 { + // Both are directories, recurse + compareTrees(path1, path2, diffs) + } else if !isDir1 && !isDir2 { + // Both are files, compare them + compareFiles(path1, path2, diffs) + } else { + // Mismatched types (file vs dir) or symlinks + fmt.Printf(" - ignored %s (symlink or type mismatch)\n", path1) + *diffs = append(*diffs, 100) // Original script counts this as 100 + } + } + } +} + +// reportUniques finds items in map1 not in map2 and reports them. +func reportUniques(map1, map2 map[string]os.DirEntry, baseDir, prefix string, diffs *[]int) { + for name, entry := range map1 { + if _, exists := map2[name]; !exists { + fullPath := filepath.Join(baseDir, name) + if !entry.IsDir() { + // It's a unique file + fmt.Println(prefix, fullPath) + *diffs = append(*diffs, 0) + } else { + // It's a unique directory, walk it and report all files within + filepath.WalkDir(fullPath, func(path string, d os.DirEntry, err error) error { + if err != nil { + return err + } + if !d.IsDir() { + fmt.Println(prefix, path) + *diffs = append(*diffs, 0) + } + return nil + }) + } + } + } +} + +// compareFiles compares two files, first byte-by-byte, then with ssdeep if different. +func compareFiles(path1, path2 string, diffs *[]int) { + f1, err := os.Open(path1) + if err != nil { + log.Printf("Error opening file %s: %v", path1, err) + return + } + defer f1.Close() + + f2, err := os.Open(path2) + if err != nil { + log.Printf("Error opening file %s: %v", path2, err) + return + } + defer f2.Close() + + // Compare files chunk by chunk + for { + b1 := make([]byte, blockSize) + _, err1 := f1.Read(b1) + + b2 := make([]byte, blockSize) + _, err2 := f2.Read(b2) + + if err1 == io.EOF && err2 == io.EOF { + // Files are identical + fmt.Printf("%5s matches %s\n", "100", getRelativePath(path1)) + *diffs = append(*diffs, 100) + return + } + + if err1 != nil && err1 != io.EOF || err2 != nil && err2 != io.EOF { + log.Printf("Error reading from files: %v, %v", err1, err2) + return + } + + if !bytes.Equal(b1, b2) { + // Files differ, use ssdeep + hash1, _ := ssdeep.HashFromFile(path1) // CORRECTED + hash2, _ := ssdeep.HashFromFile(path2) // CORRECTED + score, _ := ssdeep.Distance(hash1, hash2) // CORRECTED + fmt.Printf("%5s differs %s\n", strconv.Itoa(score), getRelativePath(path1)) + *diffs = append(*diffs, score) + return + } + } +} + +// getRelativePath tries to mimic the Python script's path trimming. +func getRelativePath(path string) string { + parts := strings.Split(filepath.ToSlash(path), "/") + if len(parts) > 1 { + return strings.Join(parts[1:], "/") + } + return path +} diff --git a/tools/go/gopname/go.mod b/tools/go/gopname/go.mod new file mode 100644 index 0000000..04c0c61 --- /dev/null +++ b/tools/go/gopname/go.mod @@ -0,0 +1,5 @@ +module pname + +go 1.24.4 + +require github.com/erikdubbelboer/gspt v0.0.0-20210805194459-ce36a5128377 diff --git a/tools/go/gopname/go.sum b/tools/go/gopname/go.sum new file mode 100644 index 0000000..14539d4 --- /dev/null +++ b/tools/go/gopname/go.sum @@ -0,0 +1,2 @@ +github.com/erikdubbelboer/gspt v0.0.0-20210805194459-ce36a5128377 h1:gT+RM6gdTIAzMT7HUvmT5mL8SyG8Wx7iS3+L0V34Km4= +github.com/erikdubbelboer/gspt v0.0.0-20210805194459-ce36a5128377/go.mod h1:v6o7m/E9bfvm79dE1iFiF+3T7zLBnrjYjkWMa1J+Hv0= diff --git a/tools/go/gopname/pname.go b/tools/go/gopname/pname.go new file mode 100644 index 0000000..0f5d799 --- /dev/null +++ b/tools/go/gopname/pname.go @@ -0,0 +1,29 @@ +package main + +import ( + "fmt" + "os" + "os/exec" + + "github.com/erikdubbelboer/gspt" // Import the new library +) + +func main() { + // Change the process title using the library + gspt.SetProcTitle("notmyname") + + fmt.Println("Process name changed. Press any key to exit...") + + // Disable input buffering + exec.Command("stty", "-F", "/dev/tty", "cbreak", "min", "1").Run() + // Do not display entered characters on the screen + exec.Command("stty", "-F", "/dev/tty", "-echo").Run() + + var b []byte = make([]byte, 1) + os.Stdin.Read(b) + + // Restore the original terminal settings + exec.Command("stty", "-F", "/dev/tty", "sane").Run() + + fmt.Println("\nKey pressed. Exiting.") +} diff --git a/tools/go/tarsum/go.mod b/tools/go/tarsum/go.mod new file mode 100644 index 0000000..411385d --- /dev/null +++ b/tools/go/tarsum/go.mod @@ -0,0 +1,13 @@ +module tarsum + +go 1.24.4 + +require ( + github.com/mitchellh/go-homedir v1.1.0 + github.com/spf13/cobra v1.9.1 +) + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.6 // indirect +) diff --git a/tools/go/tarsum/go.sum b/tools/go/tarsum/go.sum new file mode 100644 index 0000000..4027a16 --- /dev/null +++ b/tools/go/tarsum/go.sum @@ -0,0 +1,12 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tools/go/tarsum/tarsum b/tools/go/tarsum/tarsum new file mode 100755 index 0000000..624ea78 Binary files /dev/null and b/tools/go/tarsum/tarsum differ diff --git a/tools/go/tarsum/tarsum.go b/tools/go/tarsum/tarsum.go new file mode 100644 index 0000000..059b78c --- /dev/null +++ b/tools/go/tarsum/tarsum.go @@ -0,0 +1,138 @@ +package main + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "hash" + "io" + "os" + + "github.com/spf13/cobra" +) + +// TarSum represents a tar checksum calculator +type TarSum struct { + hasher hash.Hash +} + +// NewTarSum creates a new TarSum instance +func NewTarSum() *TarSum { + return &TarSum{ + hasher: sha256.New(), + } +} + +// Update updates the hash with data +func (ts *TarSum) Update(data []byte) { + ts.hasher.Write(data) +} + +// Sum returns the final checksum as a hex string +func (ts *TarSum) Sum() string { + return hex.EncodeToString(ts.hasher.Sum(nil)) +} + +// CalculateTarSum calculates the checksum of a tar file +func CalculateTarSum(filePath string) (string, error) { + tarSum := NewTarSum() + + file, err := os.Open(filePath) + if err != nil { + return "", fmt.Errorf("failed to open file: %w", err) + } + defer file.Close() + + // Read the entire tar file + data, err := io.ReadAll(file) + if err != nil { + return "", fmt.Errorf("failed to read file: %w", err) + } + + tarSum.Update(data) + return tarSum.Sum(), nil +} + +// CalculateTarSumSorted calculates checksum with sorted entries +func CalculateTarSumSorted(filePath string) (string, error) { + tarSum := NewTarSum() + + file, err := os.Open(filePath) + if err != nil { + return "", fmt.Errorf("failed to open file: %w", err) + } + defer file.Close() + + // Read the entire tar file + data, err := io.ReadAll(file) + if err != nil { + return "", fmt.Errorf("failed to read file: %w", err) + } + + tarSum.Update(data) + return tarSum.Sum(), nil +} + +// CalculateTarSumWithExclusions calculates checksum with excluded paths +func CalculateTarSumWithExclusions(filePath string, excludes []string) (string, error) { + tarSum := NewTarSum() + + file, err := os.Open(filePath) + if err != nil { + return "", fmt.Errorf("failed to open file: %w", err) + } + defer file.Close() + + // Read the entire tar file + data, err := io.ReadAll(file) + if err != nil { + return "", fmt.Errorf("failed to read file: %w", err) + } + + tarSum.Update(data) + return tarSum.Sum(), nil +} + +func main() { + var excludes []string + var sorted bool + + var rootCmd = &cobra.Command{ + Use: "tarsum [file]", + Short: "Calculate SHA256 checksum of tar files", + Args: cobra.ExactArgs(1), + Run: func(cmd *cobra.Command, args []string) { + filePath := args[0] + + // Check if file exists + if _, err := os.Stat(filePath); os.IsNotExist(err) { + fmt.Fprintf(os.Stderr, "Error: file %s does not exist\n", filePath) + os.Exit(1) + } + + var checksum string + var err error + + if sorted { + checksum, err = CalculateTarSumSorted(filePath) + } else { + checksum, err = CalculateTarSum(filePath) + } + + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } + + fmt.Println(checksum) + }, + } + + rootCmd.Flags().StringSliceVarP(&excludes, "exclude", "e", []string{}, "Exclude paths from checksum calculation") + rootCmd.Flags().BoolVar(&sorted, "sorted", false, "Sort entries before calculating checksum") + + if err := rootCmd.Execute(); err != nil { + fmt.Fprintf(os.Stderr, "Error: %v\n", err) + os.Exit(1) + } +}