pwn.college 在 SSH 获取 Desktop 的剪贴板内容

pwn_college

pwn.college 上使用 GUI Desktop 有个痛点,获取 VNC 的剪贴板内容十分费劲。得先在卡地不行的 VNC 窗口中用光标选中 flag 文本,右键复制,回到 VNC 控制台才能看到复制的文本。再次复制转移到系统剪贴板。

都远程连接了,当然还是通过 SSH 终端更方便,直接框选然后右击就复制了。不过 GUI 的 xfce4 环境和 SSH 不在一起,系统也不提供 xclip 程序,那就另辟蹊径。

Python 的 tkinter 模块,有个剪贴板功能。可大部分 challenge 的 python 不带这个模块。好在发现所有程序都在 /nix/store 里,下一步是找到带这个模块的 python,用 find /nix/store -wholename "*/_tkinter*" 很快就找到几个。

然后就是简单 封装

function clipboard() {
    local python=/nix/store/6gvxs9gj8baa4rpn1kxbibjwg8xkjn7g-python3-3.13.11-env/bin/python
	DISPLAY=:0 "$python" -c "
import tkinter, sys
tk = tkinter.Tk()
tk.withdraw()
try:
    print(tk.clipboard_get())
except tkinter.TclError:
    try:
        print(tk.selection_get(selection='PRIMARY'))
    except tkinter.TclError:
        print('Clipboard is empty or not accessible', file=sys.stderr)
"
}

但设置剪贴板有些麻烦,调用 clipboard_append() 不能稳定地成功。不过能复制也足够了。

使用 cURL 的语法但是用 netcat 发送请求

pwn_college

有一关是 Talking Web | Playing With Programs. 是需要用 nc 发送请求的,但手写 HTTP 有些麻烦,不如让 cURL 替我们生成

# Send request with nc but using curl syntax.
# designed for 'Playing With Programs / Taking Web' section.
function curlnc() {
    curl -sv -o /dev/null -m 0.001 "http://challenge.localhost$@" 2>&1 | sed -n 's/^> //p' | tee /dev/tty | nc challenge.localhost 80
}

这里需要注意的是不能用 tee >(nc localhost 80),因为重定向输出是异步的,会让 shell 认为命令已经结束,提前输出 PS1,打乱程序的输出内容。

这里用了很小的超时设置,间接实现 dry-run 效果,虽然实际上还会发送到服务器,但不会一直等待响应。

另外环境上还提供很多好用的程序,比如 jq, eza, bat, httpx,都位于 /run/dojo/bin


后面进入到 POST 阶段,发现上面那套简单的 --verbose 不够用了,不会打印请求体。这就得用 --trace-ascii 配合正则提取来做了。

function curlnc() {
    curl -s -o /dev/null -m 0.001 "http://challenge.localhost$@" --trace-ascii - | sed -nE 's/^[0-9a-f]+://p' | tee /dev/tty | nc challenge.localhost 80
}

再后面 POST 的 body 超过 64Byte 后,trace 输出的内容会换行,那处理起来就不稳定了。换条思路,本地起个服务器,接受 cURL 的请求体,用 nc 把请求发出去。

function curlnc() {
    target_host="challenge.localhost"
    target_port="80"
    socket_path="/tmp/curlnc.sock"
    pid_file="/tmp/curlnc.pid"
    (socat UNIX-LISTEN:"$socket_path",fork EXEC:"nc $target_host $target_port" &
     echo $! > "$pid_file")
    curl -v --unix-socket "$socket_path" "http://$target_host${1:-/}" "${@:2}"
    kill "$(cat "$pid_file")"
    rm -f "$pid_file" "$socket_path"
}

相当于个代理了,这里 fork + kill 为了支持重定向。
根据 socat 版本,新的可能会输出进程退出的信息,这时候可以加上 -d0 参数只打印 error 日志。

tshark 抓包常用命令

pwn_college
记录有用的 Wireshark 命令行抓包指令组合

# 输出 TCP 包中的原文
tshark -q -Y http -T fields -e tcp.payload -l | awk '{print $0"0a2d2d2d2d2d2d0a"; fflush()}' | xxd -r -p
 
# 只输出 HTTP 的细节
tshark -Y http -O http -S ======