登录后台

页面导航

本文编写于 258 天前,最后修改于 91 天前,其中某些信息可能已经过时。

前言

补充(这个简单方便,一系列操作集成):https://freedom.dsyzy.xyz/2020/03/12/gfree-libc%E4%BD%BF%E7%94%A8%EF%BC%8C%E4%BB%BB%E6%84%8F%E5%88%87%E6%8D%A2%E5%92%8C%E8%B0%83%E8%AF%95%E6%BA%90%E7%A0%81%E7%BA%A7libc/#%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95%EF%BC%9A

pwn选手做题时会遇见各种libc版本,常见的是2.23和2.27,但是遇见其他版本的libc咋办?

我傻乎乎的配了两个pwn虚拟机,2.23的题用ubuntu16做,2.27的题用ubuntu18做,但是这样很麻烦,而且遇见其他版本libc就无从下手了

网上看到强制加载libc的方法,但是不管用,或者无法使用gdb调试,原因在于没有本地编译glibc

https://bbs.pediy.com/thread-254868.htm

安装各版本glibc

提示:

及时快照,不然哪一步崩了就不好还原了
记得换源

参照:https://bbs.pediy.com/thread-225849.htm

glibc-all-in-one已经集成了几个版本的glibc,直接拿这个安装比较方便点

仓库:https://github.com/matrix1001/glibc-all-in-one

步骤:

  1. git clone https://github.com/matrix1001/glibc-all-in-one
  2. cd glibc-all-in-one
  3. chmod 777 build download extract
  4. ./build 2.29 amd64 #编译glibc

gcc版本有可能出问题,ubuntu16默认是4或5,ubuntu18是7,这里需要gcc共存及切换

ubuntu16升级gcc比较麻烦,记得挂梯子!

提醒一下,glibc-all-in-one下载的文件有三个文件,带符号,可以用于gdb调试,自己下载的时候可以对照下载

修改elf文件的默认加载路径

我尝试了patchelf,16能成功,18没成功,,太菜了

参照:https://www.jianshu.com/p/ee1ad4044ef7

把ld-2.29.so从/glibc/2.29/amd64/libc目录里提取出来,同道理提取其它版本

运行下面代码

#coding:utf-8
from pwn import *
import os
def change_ld(binary, ld):
    if not os.access(ld, os.R_OK): 
      log.failure("Invalid path {} to ld".format(ld))
      return None
    if not os.access(binary, os.R_OK): 
      log.failure("Invalid path {} to binary".format(binary))
      return None
    binary = ELF(binary)
    path = './{}_{}'.format(os.path.basename(binary.path), ld.split('.')[-2])
    if os.access(path, os.F_OK):
      os.remove(path)
      print("remove exist file.....")
      return ELF(path)
    for segment in binary.segments:
      if segment.header['p_type'] == 'PT_INTERP':
        size = segment.header['p_memsz']
        addr = segment.header['p_paddr']
        data = segment.data()
        if size <= len(ld):
          log.failure("Failed to change PT_INTERP from {} to {}".
            format(data, ld))
          return None
        binary.write(addr, ld.ljust(size, '\x00'))
        break
    binary.save(path)    
    os.chmod(path, 0b111000000) #rwx------
    success("PT_INTERP has changed from {} to {}. Using temp file {}".format(data, ld, path)) 
    return ELF(path)
change_ld('./pwn', 'ld-2.29-64.so')

就会生成一个elf文件的副本,这个副本会通过ld-2.29-64.so链接到libc.2.29,这样就实现了强制程序加载其他版本libc

ld-2.29-64.so文件必须和elf文件在同一个目录

gcc和g++各版本共存

https://blog.csdn.net/gaishi_hero/article/details/81213830

查看版本:

gcc -v
g++ -v

安装低版本g++和gcc:

sudo apt-get install gcc-4.9 gcc-4.9-multilib g++-4.9 g++-4.9-multilib

gcc版本共存的配置:(后面的数字是优先级,没什么影响)

sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 60 
sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 60

g++版本共存的配置

sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-4.8 60
sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-7 60

切换版本;

sudo update-alternatives --config gcc
sudo update-alternatives --config g++

已经完成了,可以查看版本,随意切换

可以通过如下命令对配置列表中的选项进行删除:

sudo update-alternatives --remove gcc /usr/bin/gcc-4.9
sudo update-alternatives --remove g++ /usr/bin/g++-4.9