# ELF access analysis — one page

## With the kit

```bash
tools/elf-static.sh   ./bin                 # capabilities, no execution
tools/elf-trace.sh    -- ./bin args         # full syscall trace -> REPORT.md + CSVs
tools/elf-trace.sh    -T 30 -p 1234         # attach to a running process for 30 s
tools/elf-preload.sh  -- ./bin              # libc interposer, no ptrace
tools/elf-snapshot.sh -p 1234 -n 10 -i 2    # what a daemon holds open, sampled
tools/elf-snapshot.sh -N mydaemon           # same, by name
tools/elf-fanotify.sh -- ./bin              # system-wide file access (root)
tools/elf-audit.sh start ./bin key          # kernel audit rules (root)
tools/elf-audit.sh report key ; tools/elf-audit.sh stop key
tools/elf-report.sh   -- ./bin              # everything + ANALYSIS.md
tools/parse_strace.py old.log -o R.md --cwd /srv/app   # re-parse a trace from elsewhere
```

## Raw commands

### Static
```bash
file ./bin ; sha256sum ./bin ; rpm -qf ./bin && rpm -V $(rpm -qf ./bin)
readelf -h ./bin                      # type: EXEC=no-PIE, DYN=PIE or .so
readelf -d ./bin | grep -E 'NEEDED|RUNPATH|RPATH'
ldd ./bin                             # misses dlopen()
readelf -W --dyn-syms ./bin | awk '$7=="UND"{print $8}' | sort -u
strings -a ./bin | grep -E '^/'       # candidate paths
objdump -d ./bin | grep -c syscall    # raw syscalls (Go/asm)
nm -D --defined-only ./bin            # what a .so exports
```

### Files and processes at runtime
```bash
strace -f -y -yy -s256 -e trace=%file,%desc,%process,%network -o t.log -- ./bin
strace -f -e trace=%file -o t.log -- ./bin       # files only, quieter
strace -f -c -- ./bin                            # syscall counts
strace -f -e trace=openat -e status=failed -- ./bin   # only failures
ltrace -f -S ./bin                               # library calls + syscalls

grep -oP 'openat\(.*?"\K[^"]+' t.log | sort -u                  # every path opened
grep -E 'execve|clone|fork' t.log                               # process events
grep -E 'O_WRONLY|O_RDWR|O_CREAT' t.log | grep -oP '"\K[^"]+'   # opened for write
grep ENOENT t.log | grep -oP '"\K[^"]+' | sort -u               # probed, absent
```

### A running process
```bash
ls -l /proc/PID/fd                       # open files right now
lsof -n -P -p PID                        # same, with modes: r/w/u
cat /proc/PID/maps | awk '$6~"^/"{print $6}' | sort -u   # mapped libs (incl. dlopen)
readlink /proc/PID/{exe,cwd,root}
tr '\0' '\n' < /proc/PID/environ
ps -o pid,ppid,user,args --ppid PID      # children
pstree -paA PID
fuser -v /path/to/file                   # who has this file open
lsof /path/to/file                       # same, more detail
lsof -i -n -P                            # every socket on the box
ss -tanp | grep PID                      # this process's sockets
```

### System-wide
```bash
fatrace -t                                                  # all file access (root)
fatrace -c                                                  # current directory only
extrace                                                     # every exec, with argv
bpftrace -e 'tracepoint:syscalls:sys_enter_openat /comm=="bin"/ {printf("%s\n", str(args->filename));}'
bpftrace -e 'tracepoint:sched:sched_process_exec {printf("%d %s\n", pid, str(args->filename));}'
auditctl -a always,exit -F arch=b64 -S openat -F exe=/path/bin -k k
ausearch -k k -i ; aureport --file
```

### Containers
```bash
podman run --rm -it --network=none --cap-add=SYS_PTRACE -v "$PWD:/w:Z" almalinux:9 \
  strace -f -y -o /w/t.log /w/bin
nsenter -t PID -m -p ls -l /proc/1/fd        # look inside another mount/pid namespace
```

## Flag reference

| strace | |
|---|---|
| `-f` | follow children — almost always required |
| `-y` / `-yy` | print the path / socket behind each fd |
| `-s N` | string length (default 32 truncates paths) |
| `-e trace=%file,%desc,%process,%network` | the four classes that matter here |
| `-e status=failed` | only calls that returned an error |
| `-p PID` | attach; `-T` duration; `-o` output file |
| `-c` | summary instead of a log |
| `-k` | stack trace per syscall (needs symbols) |

| lsof FD column | meaning |
|---|---|
| `3r` `3w` `3u` | fd 3 open read / write / read-write |
| `cwd` `rtd` `txt` `mem` | working dir, root, the executable, a mapped file |

| fatrace flags | `R` read, `W` write, `O` open, `C` close, `+` create, `D` delete |
|---|---|
