Tmux for CTF: customize the work environment without losing progress

Depov

Moderator
Staff member
MODERATOR
ULTIMATE
SUPREME
PREMIUM
MEMBER
Joined
Feb 18, 2025
Messages
392
Reaction score
635
Deposit
0$
Why CTF player multiplexer terminal

A typical CTF session is simultaneous operation in four or six terminals. In one, the port scanner spins, in the second, the listing of directories, the third listens to the incoming shell, in the fourth, notes are written or the exploit is launched. Without a multiplexer, each process is tied to a separate SSH connection. Breaking the connection is the loss of everything.

The terminal multiplexer solves three problems critical for CTF.

Persistency. Tmux works as a server process on a remote machine. The SSH connection can fall at least ten times in a row – the processes inside the tmux continue to live. Reconnected, gained tmux attach - nmap scanned, listener caught the shell, gobuster found /admin. Nothing's missing. From the NCSA documentation: "tmux sequences protected on the login node, you can simply log back in attach, to your existing session, and work your work exactly where you are left off."

Organization of the workspace. Instead of switching between PuTTY windows or terminal tabs, one window broken down on the panel (panes). On the left, the exploit is launched, on the right is the listener output, at the bottom is the shell on the target machine. You can see it at the same time, without Alt+Tab. Tmux organizes information into a three-level hierarchy: session (session) → windows (windows, browser tabs) → panels (panes, separation of one window into parts).

Reproducibility. The tmux session launch script with the desired layout – and three seconds after the SSH connection to the VPS is ready for a full-fledged working environment for the CTF. It is not necessary to create windows and tools with your hands every time. At CTF-competitions with limited time it is especially noticeable: every minute to recreate the environment after a cliff is a minute that could go to the decision of the taska.
Tmux vs screen: which terminal multiplexer to choose for CTF

Both instruments solve the task of maintaining the session of the terminal. For CTF tasks, the difference is significant.
Setup tmux: basic commands and hotkeys

Basic cycle of work: creating a named session tmux new -s htb, working inside, disconnecting through Ctrl+b d (detach), later returning through tmux attach -t htb. The session is all this time alive - the processes work, the conclusion is preserved in the buffer.

Hotcakes that are really needed for CTFs (everyone starts with a prefix Ctrl+b:

c – create a new window (tab inside the session)
, – rename the current window (called “recon”, “exploit”, “privesc”)
n / p – move on to the next / previous window
0–9 – go to the window by number
w – interactive list of all windows with preview of content
" – divide the current panel horizontally (top and bottom)
% – divide the panel vertically (left and right)
стрелки – switching the focus between the panels
z – deploy the current panel to the entire screen and back (zoom/unzoom)
[ – scroll mode and buffer search (exit – q)
x – close the current panel (with confirmation)
d – detach, disconnect from the session

Separately pro Ctrl+b z - a thing that is underestimated. When the nmap output takes 300 lines, and the panel is a quarter of the screen, you deploy it to the full screen, calmly study the result, press Ctrl+b z Again, you go back to the layout. No need to drag the boundaries of the panels.

List of live sessions: tmux ls. The output will show the session name, the number of windows and the creation time. It is useful when in the morning I forgot whether the session was created for the current car. Complete the whole session without going inside: tmux kill-session -t htb. Destroy all sessions at once: tmux kill-server.
Configuration tmux.conf for CTF tasks

File ~/.tmux.conf transforms tmux from tolerable into irreplaceable. Here's a config that stands on my attacking VPS:

set -g mouse on
set -g history-limit 50000
set -g base-index 1
setw -g pane-base-index 1
set -g renumber-windows on
set -s escape-time 0
bind | split-window -h -c "#{pane_current_path}"
bind - split-window -v -c "#{pane_current_path}"
bind r source-file ~/.tmux.conf \; display "Reloaded"
setw -g mode-keys vi

Parsing in the context of CTF work.

history-limit 50000 – the size of the scrolling buffer. By default, tmux stores 2000 lines. Conclusion nmap -sV -sC on the entire range of ports easily crosses this boundary. With 50000 lines, no line is lost - you can scroll back and find the desired service banner. Values 10000–50000 are standard practice for working machines.

base-index 1 and pane-base-index 1 – numbering windows and panels from one instead of zero. By default, the first window has the number 0, and for switching you have to reach for Ctrl+b 0. with unit — Ctrl+b 1 for the first window. Small, but for the four-hour CTF, these little things add up.

escape-time 0 – removes delay after pressing Escape. Without this setting, the vim inside the tmux reacts with a noticeable lag when switching modes. When you rule the exploit in vim and immediately launch it, the lag is annoying.

bind | split-window -h -c "#{pane_current_path}" – binding Ctrl+b | for vertical split. Flag -c "#{pane_current_path}" here is critical: without it, each new panel opens in the home directory, and you have to do again cd /tmp/ctf/exploit/. With the flag, the new panel starts in the same directory where you work. Similarly bind - for horizontal separation.

mode-keys vi – navigation in scrolling mode through vi-keys: hjkl for movement, / to search by text. Find port 8443 in nmap output: Ctrl+b [ → /8443 → Enter. A second instead of manual scrolling with arrows.

Apply config without restart: Ctrl+b r (through config binary above) or Ctrl+b : → enter source-file ~/.tmux.conf.
Working environment for CTF: layout panels in tmux
Reconnaissance and scanning layout

At the reconnaissance stage, three or four panels are needed at the same time. The upper left is the main scan (nmap or rustscan). The upper right is a list of directories (gobuster, feroxbuster, dresearch). Lower left is a working terminal for manual commands and quick checks (curl, whatweb, manual HTTP requests). Bottom right – notes in vim or nano, where you write found ports, credentials, potential vectors.

Created in ten seconds. Launching tmux new -s recon. Doing Ctrl+b | Two vertical panels. You move to the left, Ctrl+b - The left half is divided horizontally. Arrow to the right, again Ctrl+b - The right half is also divided. Four panels are ready. Rename the window: Ctrl+b , → enter "recon".

According to MITRE ATT&CK, this stage is System Information Discovery (T1082) and File and Directory Discovery (T1083): listing ports, services, available directories and files on the target machine. Each tmux panel closes its intelligence vector, and the entire context is visible at the same time.

When the operation begins, you create a new window Ctrl+b c, you call "exploit." Switching between Attack Phases: Ctrl+b 1 (recon) and Ctrl+b 2 (exploit). Intelligence data remain in the first window, it is possible to return and reconsider the conclusion at any time.
Layout for operation and interception of shells

At the stage of operation, the layout changes. One panel is constantly busy with the listener: rlwrap nc -lvnp 4444 or pwncat-cs :4444. A neighboring panel is for running an exploit or sending a payload. The bottom large panel is for work in the resulting shell after successful operation.

Why the listener and exploit in the neighboring panels - you see at the same time sending payload, and the moment of arrival of the reverse connection. You don’t have to switch between windows to understand whether the exploit worked or not. When the shell comes, switch to the listener panel with an arrow (Ctrl+b стрелка-вниз) and start working on the target car.

For command CTFs, there is a cool thing – panel synchronization: Ctrl+b : → set-window-option synchronize-panes on. After that, each entered symbol is duplicated in all the panels of the current window. Received shells on three machines and need to be performed whoami on everyone? You type once, the result appears in three panels at the same time. Switch off: same command with off.
Maintaining terminal session: detach, attach and recovery after cliff

The central value of a multiplexer is the ability to disconnect from a session without killing processes. Ctrl+b d - detach. You went back to the regular Shell SSH, but the tmux session is alive. Nmap scans, listener listens, panels saved.

View live sessions: tmux ls. Connect to specific: tmux attach -t htb or abbreviated tmux a -t htb. If the session is one, enough tmux a.

A practical scenario for working in the terminal without loss of progress: in the morning created tmux new -s htb-machine, worked two hours, did a detach, left. In the evening, he connected to a VPS from another device - a laptop, a tablet, even a phone through Termux. Team tmux a -t htb-machine – the workplace is restored exactly. Output nmap scrolls up, shell is waiting for input, vim with notes in place. From the RunPod documentation: "TMUX runs your commands in persistent terminal sessions that continue even if you disconnect."

If the SSH is broken without an obvious detach, the tmux session is still alive. Here is a key difference from the work without a multiplexer: without tmux, the breakage of the SSH sends SIGHUP to all child processes - they are completed. With tmux, processes live in the tmux server process, which is independent of the SSH connection.

When reconnecting tmux ls will show the existing session. If the old SSH client did not have time to send an outage signal and the session is marked as "attached" - use tmux attach -dt htb. Flag -d forcibly disconnects the previous client and connects the current one. For screen analogue: screen -DR ctf.

Useful team to start each job: tmux attach || tmux new -s ctf. First, tries to connect to an existing session, and only if there are no sessions – creates a new one. So do not fruit the oak when you forget whether tmux started in the morning.
CTF Workflow Automation by Scripts

Creating a layout with your hands at each connection is routine. The script unfolds the finished working environment in seconds.

#!/bin/bash
TARGET=${1:-"10.10.10.1"}
SESSION="ctf-$TARGET"
tmux has-session -t $SESSION 2>/dev/null && tmux a -t $SESSION && exit
tmux new-session -d -s $SESSION -n recon
tmux send-keys -t $SESSION:recon "echo Target: $TARGET" Enter
tmux split-window -h -t $SESSION:recon
tmux new-window -t $SESSION -n exploit
tmux split-window -v -t $SESSION:exploit
tmux send-keys -t $SESSION:exploit.1 "rlwrap nc -lvnp 4444" Enter
tmux select-window -t $SESSION:recon
tmux attach -t $SESSION

Use: chmod +x ctf-start.sh && ./ctf-start.sh 10.10.10.45. Two windows are created in a second: "recon" with two panels for scanning and "exploit" with a panel for the exploit and already launched listener on the port 4444.

tmux has-session checks whether there is a session with that name. If yes, the script simply connects to it without creating a duplicate. The name of the session includes IP objectives (ctf-10.10.10.45), so for each machine is a separate environment. Through tmux ls You can see what purposes you work for in parallel.

For different platforms, you can create options: a script for HackTheBox – with a VPN check through ip a | grep tun0 before launch, the script for TryHackMe is with openvpn autostart. Principle One: The script unfolds the tmux session with the desired layout for a specific task type.

Additional windows are easily added. Privesc window to increase privileges: tmux new-window -t $SESSION -n privesc. Or a “notes” window with a running vim: tmux new-window -t $SESSION -n notes → tmux send-keys -t $SESSION:notes "vim /tmp/ctf/notes.md" Enter.
Screen linux terminal: a backup option for CTF

GNU Screen appeared in 1987 and is pre-installed on almost any Linux server. For CTF screen is relevant in one particular scenario: you got a shell on the target machine, you want to organize the work right on it, and the tmux is not installed. Screen is highly likely to be in place.

Basic Screen Commands with Prefix Ctrl+a (Unlike Ctrl+b at tmux):

Create a session: screen -S ctf
Disconnect: Ctrl+a d
List of sessions: screen -ls
Connect: screen -r ctf
Forced connection: screen -DR ctf
New window: Ctrl+a c
Next / previous window: Ctrl+a n / Ctrl+a p
List of windows: Ctrl+a "
Separation horizontally: Ctrl+a S
Division vertically: Ctrl+a |
Switching between regions: Ctrl+a Tab
Scroll (copy mode): Ctrl+a
End the session from outside: screen -X -S ctf quit

In practice, screen is annoying with one thing: after the separation of the window, the new region is empty. You need to switch there (Ctrl+a Tab) and create a shell in it (Ctrl+a c). In tmux, the new panel immediately receives a working terminal. When working quickly on the CTF, this additional operation is significantly inhibited.

Minimum config ~/.screenrc for normal operation: defscrollback 10000 (scroll buffer), startup_message off (remove greetings), term screen-256color (Rectified colors). Three lines are enough for the eyes.

Working approach: on the attacking VPS - tmux with a full config. On the target machine after receiving the shell - screen, if available. Don’t waste time choosing to use what’s at hand.
Productivity techniques in the terminal for CTF players

Several techniques that speed up work in tmux and rarely fall into standard cheat sheets.

Name of windows for the attack phases. Ctrl+b , → enter "recon", "privesc", "loot". With five open windows Ctrl+b w will show a list with clear names instead of five identical “bash”. In a four-hour CTF, minutes are running – each switch is seconds faster.

Search by scroll buffer. Ctrl+b [ → / → search bar → Enter. Found a reference to port 8443 in 500 lines of output nmap per second. n to the next coincidence, N - to the previous one. Without a search, you would have to leaf through the arrows - the pleasure is doubtful.

Save the output panel to the file. Ctrl+b : → enter capture-pane -S - → then Ctrl+b : → save-buffer /tmp/scan.txt. The contents of the panel are in the text file. It is indispensable for writeups and reports.

Send the command to the panel from the outside. tmux send-keys -t ctf:exploit.1 "id" Enter sends id to a specific panel without switching to it. You can build into automation scripts: one script sends the desired commands on the panels.

Zoom for withdrawal. Already mentioned Ctrl+b z, but it is worth stressing: it retains the position of scrolling. Turned the panel, scrolled up, found the right, swerved - the position remained. The panel is not dropped.

Security: the history of teams. All teams in tmux sessions fall into [Shell History (T1552.003, Credential Access). On shared VPS, passwords and APIs typed directly in the terminal are stored in ~/.bash_history. For training CTFs, this is not critical, but the habit is to form immediately: environment variables (export TOKEN=...) or files instead of open input. On real projects it is already a matter of security of the client.
 
Top Bottom