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_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
|
||||
test:
|
||||
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 another set of binaries that are as small as possible, but may not work
|
||||
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
|
||||
docker run -it \
|
||||
@@ -47,8 +50,8 @@ build:
|
||||
-w "/go/src/github.com/dominicbreuker" \
|
||||
--env CGO_ENABLED=0 \
|
||||
--env GOOS=linux \
|
||||
--env GOARCH=386 \
|
||||
$(BUILD_IMAGE) /bin/sh -c "go build -a -ldflags '-extldflags \"-static\"' -o pspy/bin/pspy32 pspy/main.go"
|
||||
--env GOARCH=386 \
|
||||
$(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 \
|
||||
--rm \
|
||||
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
||||
@@ -56,18 +59,18 @@ build:
|
||||
--env CGO_ENABLED=0 \
|
||||
--env GOOS=linux \
|
||||
--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 \
|
||||
--rm \
|
||||
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
||||
-w "/go/src/github.com/dominicbreuker" \
|
||||
--env GOOS=linux \
|
||||
--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 \
|
||||
--rm \
|
||||
-v $(PROJECT_DIR):/go/src/github.com/dominicbreuker/pspy \
|
||||
-w "/go/src/github.com/dominicbreuker" \
|
||||
--env GOOS=linux \
|
||||
--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" />
|
||||
|
||||
# pspy - unprivileged linux process snooping
|
||||
# pspy - unprivileged Linux process snooping
|
||||
|
||||
[](https://goreportcard.com/report/github.com/DominicBreuker/pspy)
|
||||
[](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.
|
||||
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.
|
||||
|
||||
## 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.
|
||||
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)
|
||||
- 64 bit big, static version: `pspy64` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy64)
|
||||
- 32 bit small version: `pspy32s` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy32s)
|
||||
- 64 bit small version: `pspy64s` [download](https://github.com/DominicBreuker/pspy/releases/download/v1.0.0/pspy64s)
|
||||
- 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.2.0/pspy64)
|
||||
- 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.2.0/pspy64s)
|
||||
|
||||
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
|
||||
|
||||
@@ -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).
|
||||
- -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.
|
||||
- -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.
|
||||
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"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -17,15 +16,20 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var bannerLines = []string{
|
||||
" _____ _____ _______ __",
|
||||
" | __ \\ / ____| __ \\ \\ / /",
|
||||
" | |__) | (___ | |__) \\ \\_/ / ",
|
||||
" | ___/ \\___ \\| ___/ \\ / ",
|
||||
" | | ____) | | | | ",
|
||||
" |_| |_____/|_| |_| ",
|
||||
helpText,
|
||||
}
|
||||
var banner = `
|
||||
|
||||
██▓███ ██████ ██▓███ ▓██ ██▓
|
||||
▓██░ ██▒▒██ ▒ ▓██░ ██▒▒██ ██▒
|
||||
▓██░ ██▓▒░ ▓██▄ ▓██░ ██▓▒ ▒██ ██░
|
||||
▒██▄█▓▒ ▒ ▒ ██▒▒██▄█▓▒ ▒ ░ ▐██▓░
|
||||
▒██▒ ░ ░▒██████▒▒▒██▒ ░ ░ ░ ██▒▓░
|
||||
▒▓▒░ ░ ░▒ ▒▓▒ ▒ ░▒▓▒░ ░ ░ ██▒▒▒
|
||||
░▒ ░ ░ ░▒ ░ ░░▒ ░ ▓██ ░▒░
|
||||
░░ ░ ░ ░ ░░ ▒ ▒ ░░
|
||||
░ ░ ░
|
||||
░ ░
|
||||
|
||||
`
|
||||
|
||||
var helpText = `
|
||||
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.
|
||||
Processes are monitored by scanning /proc, using file system events as triggers.
|
||||
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{
|
||||
Use: "pspy",
|
||||
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) {
|
||||
logger := logging.NewLogger(debug)
|
||||
|
||||
logger.Infof("%s", banner)
|
||||
|
||||
cfg := &config.Config{
|
||||
RDirs: rDirs,
|
||||
Dirs: dirs,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
@@ -70,9 +71,20 @@ func (i *Inotify) Watch(dir string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var errno22Counter = 0
|
||||
|
||||
func (i *Inotify) Read(buf []byte) (int, error) {
|
||||
n, errno := unix.Read(i.FD, buf)
|
||||
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, nil
|
||||
|
||||
Reference in New Issue
Block a user