PWN

ELF 更换 glibc

Posted by Elli0t on 2020-10-09

ldd 命令查看当前正在使用的链接库

1
2
3
4
5
6
7
8
9
10
11
root@pwn:/ctf/work# ldd program
linux-vdso.so.1 (0x00007ffe3fb86000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa1ff6e3000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa1ff8df000)

root@pwn:/ctf/work# ldd /lib64/ld-linux-x86-64.so.2
statically linked

root@pwn:/ctf/work# ldd /lib/x86_64-linux-gnu/libc.so.6
/lib64/ld-linux-x86-64.so.2 (0x00007f854e770000)
linux-vdso.so.1 (0x00007ffe957b9000)

ldd 输出第一行 linux-vdso.so.1 (0x00007ffe3fb86000) 不是实际的库文件,你是找不到的,它是一个虚拟库文件用于和 kernel 交互。

libc.so.6 动态链接库

ld-linux-x86-64.so.2 负责动态加载。它们通过读取可执行文件的头部信息来确定哪些库文件是必须的,以及哪些需要加载。加载完成后,它会通过修正执行文件里的相关的地址指针来和加载的库文件完成动态链接,此时程序就可以运行了。

ld-linux.so 是专门负责寻找库文件的库。以 cat 为例,cat 首先告诉 ld-linux.so 它需要 libc.so.6 这个库文件,ld-linux.so 将按一定顺序找到 libc.so.6 库再给 cat 调用。ld-linux.so 的位置是写死在程序中的,gcc 在编译程序时就写死在里面了。

patchelf

https://github.com/NixOS/patchelf

如果题目给了 libc.so.6 用 IDA 或者啥打开看看 glibc 版本,然后更换相应版本的 ld 和 libc

tesafdsasfaew

图中 libc 版本为 2.23

修改 ELF 中硬编码的 ld 和 libc 的路径。

1
2
3
4
5
6
7
8
9
10
root@pwn:/ctf/work# ldd mmutag 
linux-vdso.so.1 (0x00007fff3734e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f002c5b7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f002c7b3000)
root@pwn:/ctf/work# patchelf --set-interpreter /glibc/2.23/64/lib/ld-2.23.so ./mmutag
root@pwn:/ctf/work# patchelf --replace-needed libc.so.6 /glibc/2.23/64/lib/libc-2.23.so ./mmutag
root@pwn:/ctf/work# ldd mmutag
linux-vdso.so.1 (0x00007ffd833d9000)
/glibc/2.23/64/lib/libc-2.23.so (0x00007f9077b82000)
/glibc/2.23/64/lib/ld-2.23.so => /lib64/ld-linux-x86-64.so.2 (0x00007f9077f25000)

LIEF(没用过,不熟)

https://www.ayrx.me/using-a-non-system-libc

pwn_debug(不太好用)

https://github.com/ray-cp/pwn_debug

pwn_debug-基于pwntools的ctf pwns的辅助调试工具

使用 pwn_debug 共有四个步骤:

  1. 导入工具from pwn_debug*
  2. 声明一个pwn_debug对象:pdbg=pwn_debug("binary")
  3. 将模式参数,共有三个模式:debuglocalremote
  4. 运行模式。
  5. 使用pwntools做过去的事情。

一个典型的例子如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from pwn_debug import *

## step 1
pdbg=pwn_debug("binary")

pdbg.context.terminal=['tmux', 'splitw', '-h']

## step 2
pdbg.local("libc.so.6")
pdbg.debug("2.23")
pdbg.remote('34.92.96.238',10000)
## step 3
#p=pdbg.run("local")
#p=pdbg.run("debug")
p=pdbg.run("remote")

pdbg.bp(0x80489aa)

elf=pdbg.elf
print hex(elf.got['printf'])
print hex(elf.plt['printf'])

libc=pdbg.libc
print libc.symbols['system']
p.interactive()

LD_PRELOAD(如果 libc 的版本差太多的话就没办法使用)

LD_PRELOAD=/lib/x86_64-linux-gnu/libc-2.19.so ./program

LD_PRELOAD 只是告诉 ld.so 该去哪儿加载 libc, 可是 ld.so 也没有办法去加载不同版本的 libc

Link
https://bbs.pediy.com/thread-254868.htm
https://www.jianshu.com/p/ee1ad4044ef7
https://blog.csdn.net/feixiaoxing/article/details/79888886
https://www.cnblogs.com/sun-frederick/p/4763460.html