mirror of
https://github.com/DominicBreuker/pspy.git
synced 2025-12-21 19:54:53 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9c63e5d6c5 | ||
|
|
c136be2f46 | ||
|
|
831cac3196 | ||
|
|
3bd4885e22 | ||
|
|
6f434e1d5b |
15
Makefile
15
Makefile
@@ -9,6 +9,9 @@ DEV_DOCKERFILE = $(PROJECT_DIR)/docker/Dockerfile.development
|
|||||||
TEST_IMAGE = local/pspy-testing:latest
|
TEST_IMAGE = local/pspy-testing:latest
|
||||||
TEST_DOCKERFILE = $(PROJECT_DIR)/docker/Dockerfile.testing
|
TEST_DOCKERFILE = $(PROJECT_DIR)/docker/Dockerfile.testing
|
||||||
|
|
||||||
|
VERSION = `git describe --tags --always || echo "unknown"`
|
||||||
|
BUILD_SHA = `git rev-parse HEAD || echo "unknown"`
|
||||||
|
|
||||||
# Run unit test and integration test inside container
|
# Run unit test and integration test inside container
|
||||||
test:
|
test:
|
||||||
docker build -f $(TEST_DOCKERFILE) -t $(TEST_IMAGE) .
|
docker build -f $(TEST_DOCKERFILE) -t $(TEST_IMAGE) .
|
||||||
@@ -38,7 +41,7 @@ example:
|
|||||||
# builds one set of static binaries that should work on any system without dependencies, but are huge
|
# builds one set of static binaries that should work on any system without dependencies, but are huge
|
||||||
# builds another set of binaries that are as small as possible, but may not work
|
# builds another set of binaries that are as small as possible, but may not work
|
||||||
build:
|
build:
|
||||||
sh -c "if ! docker image ls | grep '$(BUILD_IMAGE)' | cut -d ':' -f1; then echo 'building build image'; docker build -f $(BUILD_DOCKERFILE) -t $(BUILD_IMAGE) .; fi"
|
# sh -c "if ! docker image ls | grep '$(BUILD_IMAGE)' | cut -d ':' -f1; then echo 'building build image'; docker build -f $(BUILD_DOCKERFILE) -t $(BUILD_IMAGE) .; fi"
|
||||||
|
|
||||||
mkdir -p $(PROJECT_DIR)/bin
|
mkdir -p $(PROJECT_DIR)/bin
|
||||||
docker run -it \
|
docker run -it \
|
||||||
@@ -47,8 +50,8 @@ build:
|
|||||||
-w "/go/src/github.com/dominicbreuker" \
|
-w "/go/src/github.com/dominicbreuker" \
|
||||||
--env CGO_ENABLED=0 \
|
--env CGO_ENABLED=0 \
|
||||||
--env GOOS=linux \
|
--env GOOS=linux \
|
||||||
--env GOARCH=386 \
|
--env GOARCH=386 \
|
||||||
$(BUILD_IMAGE) /bin/sh -c "go build -a -ldflags '-extldflags \"-static\"' -o pspy/bin/pspy32 pspy/main.go"
|
$(BUILD_IMAGE) /bin/sh -c "go build -a -ldflags '-s -w -X main.version=${VERSION} -X main.commit=${BUILD_SHA} -extldflags \"-static\"' -o pspy/bin/pspy32 pspy/main.go"
|
||||||
docker run -it \
|
docker run -it \
|
||||||
--rm \
|
--rm \
|
||||||
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
||||||
@@ -56,18 +59,18 @@ build:
|
|||||||
--env CGO_ENABLED=0 \
|
--env CGO_ENABLED=0 \
|
||||||
--env GOOS=linux \
|
--env GOOS=linux \
|
||||||
--env GOARCH=amd64 \
|
--env GOARCH=amd64 \
|
||||||
$(BUILD_IMAGE) /bin/sh -c "go build -a -ldflags '-extldflags \"-static\"' -o pspy/bin/pspy64 pspy/main.go"
|
$(BUILD_IMAGE) /bin/sh -c "go build -a -ldflags '-s -w -X main.version=${VERSION} -X main.commit=${BUILD_SHA} -extldflags \"-static\"' -o pspy/bin/pspy64 pspy/main.go"
|
||||||
docker run -it \
|
docker run -it \
|
||||||
--rm \
|
--rm \
|
||||||
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
||||||
-w "/go/src/github.com/dominicbreuker" \
|
-w "/go/src/github.com/dominicbreuker" \
|
||||||
--env GOOS=linux \
|
--env GOOS=linux \
|
||||||
--env GOARCH=386 \
|
--env GOARCH=386 \
|
||||||
$(BUILD_IMAGE) /bin/sh -c "go build -ldflags '-w -s' -o pspy/bin/pspy32s pspy/main.go && upx pspy/bin/pspy32s"
|
$(BUILD_IMAGE) /bin/sh -c "go build -ldflags '-w -s -X main.version=${VERSION} -X main.commit=${BUILD_SHA}' -o pspy/bin/pspy32s pspy/main.go && upx pspy/bin/pspy32s"
|
||||||
docker run -it \
|
docker run -it \
|
||||||
--rm \
|
--rm \
|
||||||
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
||||||
-w "/go/src/github.com/dominicbreuker" \
|
-w "/go/src/github.com/dominicbreuker" \
|
||||||
--env GOOS=linux \
|
--env GOOS=linux \
|
||||||
--env GOARCH=amd64 \
|
--env GOARCH=amd64 \
|
||||||
$(BUILD_IMAGE) /bin/sh -c "go build -ldflags '-w -s' -o pspy/bin/pspy64s pspy/main.go && upx pspy/bin/pspy64s"
|
$(BUILD_IMAGE) /bin/sh -c "go build -ldflags '-w -s -X main.version=${VERSION} -X main.commit=${BUILD_SHA}' -o pspy/bin/pspy64s pspy/main.go && upx pspy/bin/pspy64s"
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -1,6 +1,6 @@
|
|||||||
<img src="images/logo.svg" align="left" />
|
<img src="images/logo.svg" align="left" />
|
||||||
|
|
||||||
# pspy - unprivileged linux process snooping
|
# pspy - unprivileged Linux process snooping
|
||||||
|
|
||||||
[](https://goreportcard.com/report/github.com/DominicBreuker/pspy)
|
[](https://goreportcard.com/report/github.com/DominicBreuker/pspy)
|
||||||
[](https://codeclimate.com/github/DominicBreuker/pspy/maintainability)
|
[](https://codeclimate.com/github/DominicBreuker/pspy/maintainability)
|
||||||
@@ -12,7 +12,7 @@ It allows you to see commands run by other users, cron jobs, etc. as they execut
|
|||||||
Great for enumeration of Linux systems in CTFs.
|
Great for enumeration of Linux systems in CTFs.
|
||||||
Also great to demonstrate your colleagues why passing secrets as arguments on the command line is a bad idea.
|
Also great to demonstrate your colleagues why passing secrets as arguments on the command line is a bad idea.
|
||||||
|
|
||||||
The tool gathers it's info from procfs scans.
|
The tool gathers the info from procfs scans.
|
||||||
Inotify watchers placed on selected parts of the file system trigger these scans to catch short-lived processes.
|
Inotify watchers placed on selected parts of the file system trigger these scans to catch short-lived processes.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
@@ -21,13 +21,13 @@ Inotify watchers placed on selected parts of the file system trigger these scans
|
|||||||
|
|
||||||
Get the tool onto the Linux machine you want to inspect.
|
Get the tool onto the Linux machine you want to inspect.
|
||||||
First get the binaries. Download the released binaries here:
|
First get the binaries. Download the released binaries here:
|
||||||
- 32 bit big, static version: `pspy32` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy32)
|
- 32 bit big, static version: `pspy32` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy32)
|
||||||
- 64 bit big, static version: `pspy64` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy64)
|
- 64 bit big, static version: `pspy64` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64)
|
||||||
- 32 bit small version: `pspy32s` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy32s)
|
- 32 bit small version: `pspy32s` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy32s)
|
||||||
- 64 bit small version: `pspy64s` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy64s)
|
- 64 bit small version: `pspy64s` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.2.0/pspy64s)
|
||||||
|
|
||||||
The statically compiled files should work on any Linux system but are quite huge (~4MB).
|
The statically compiled files should work on any Linux system but are quite huge (~4MB).
|
||||||
If size is an issue, try the smaller versions which depend on libc and are compressed with UPX (<1MB).
|
If size is an issue, try the smaller versions which depend on libc and are compressed with UPX (~1MB).
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
@@ -41,7 +41,8 @@ The summary is as follows:
|
|||||||
- -r: list of directories to watch with Inotify. pspy will watch all subdirectories recursively (by default, watches /usr, /tmp, /etc, /home, /var, and /opt).
|
- -r: list of directories to watch with Inotify. pspy will watch all subdirectories recursively (by default, watches /usr, /tmp, /etc, /home, /var, and /opt).
|
||||||
- -d: list of directories to watch with Inotify. pspy will watch these directories only, not the subdirectories (empty by default).
|
- -d: list of directories to watch with Inotify. pspy will watch these directories only, not the subdirectories (empty by default).
|
||||||
- -i: interval in milliseconds between procfs scans. pspy scans regularly for new processes regardless of Inotify events, just in case some events are not received.
|
- -i: interval in milliseconds between procfs scans. pspy scans regularly for new processes regardless of Inotify events, just in case some events are not received.
|
||||||
- -c: print events in different colors. Red for new processes, green for new Inotify events.
|
- -c: print commands in different colors. File system events are not colored anymore, commands have different colors based on process UID.
|
||||||
|
- --debug: prints verbose error messages which are otherwise hidden.
|
||||||
|
|
||||||
The default settings should be fine for most applications.
|
The default settings should be fine for most applications.
|
||||||
Watching files inside `/usr` is most important since many tools will access libraries inside it.
|
Watching files inside `/usr` is most important since many tools will access libraries inside it.
|
||||||
|
|||||||
30
cmd/root.go
30
cmd/root.go
@@ -5,7 +5,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -17,15 +16,20 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var bannerLines = []string{
|
var banner = `
|
||||||
" _____ _____ _______ __",
|
|
||||||
" | __ \\ / ____| __ \\ \\ / /",
|
██▓███ ██████ ██▓███ ▓██ ██▓
|
||||||
" | |__) | (___ | |__) \\ \\_/ / ",
|
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
|
||||||
" | ___/ \\___ \\| ___/ \\ / ",
|
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
|
||||||
" | | ____) | | | | ",
|
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
|
||||||
" |_| |_____/|_| |_| ",
|
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
|
||||||
helpText,
|
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
|
||||||
}
|
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
|
||||||
|
░░ ░ ░ ░ ░░ ▒ ▒ ░░
|
||||||
|
░ ░ ░
|
||||||
|
░ ░
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
var helpText = `
|
var helpText = `
|
||||||
pspy monitors the system for file system events and new processes.
|
pspy monitors the system for file system events and new processes.
|
||||||
@@ -33,11 +37,9 @@ It prints these envents to the console.
|
|||||||
File system events are monitored with inotify.
|
File system events are monitored with inotify.
|
||||||
Processes are monitored by scanning /proc, using file system events as triggers.
|
Processes are monitored by scanning /proc, using file system events as triggers.
|
||||||
pspy does not require root permissions do operate.
|
pspy does not require root permissions do operate.
|
||||||
Check our https://github.com/dominicbreuker/pspy for more information.
|
Check out https://github.com/dominicbreuker/pspy for more information.
|
||||||
`
|
`
|
||||||
|
|
||||||
var banner = strings.Join(bannerLines, "\n")
|
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "pspy",
|
Use: "pspy",
|
||||||
Short: "pspy can watch your system for new processes and file system events",
|
Short: "pspy can watch your system for new processes and file system events",
|
||||||
@@ -75,6 +77,8 @@ func init() {
|
|||||||
func root(cmd *cobra.Command, args []string) {
|
func root(cmd *cobra.Command, args []string) {
|
||||||
logger := logging.NewLogger(debug)
|
logger := logging.NewLogger(debug)
|
||||||
|
|
||||||
|
logger.Infof("%s", banner)
|
||||||
|
|
||||||
cfg := &config.Config{
|
cfg := &config.Config{
|
||||||
RDirs: rDirs,
|
RDirs: rDirs,
|
||||||
Dirs: dirs,
|
Dirs: dirs,
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -70,9 +71,20 @@ func (i *Inotify) Watch(dir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errno22Counter = 0
|
||||||
|
|
||||||
func (i *Inotify) Read(buf []byte) (int, error) {
|
func (i *Inotify) Read(buf []byte) (int, error) {
|
||||||
n, errno := unix.Read(i.FD, buf)
|
n, errno := unix.Read(i.FD, buf)
|
||||||
if n < 1 {
|
if n < 1 {
|
||||||
|
if errno.Error() == "invalid argument" {
|
||||||
|
errno22Counter += 1
|
||||||
|
if errno22Counter > 20 {
|
||||||
|
fmt.Printf("Unrecoverable inotify error (%s, errno %d). Exiting program...\n", errno, errno)
|
||||||
|
os.Exit(22)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
errno22Counter = 0
|
||||||
|
}
|
||||||
return n, fmt.Errorf("reading from inotify fd %d: errno: %d", i.FD, errno)
|
return n, fmt.Errorf("reading from inotify fd %d: errno: %d", i.FD, errno)
|
||||||
}
|
}
|
||||||
return n, nil
|
return n, nil
|
||||||
|
|||||||
10
main.go
10
main.go
@@ -1,7 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/dominicbreuker/pspy/cmd"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/dominicbreuker/pspy/cmd"
|
||||||
|
)
|
||||||
|
|
||||||
|
var version string
|
||||||
|
var commit string
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
fmt.Printf("pspy - version: %s - Commit SHA: %s\n", version, commit)
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user