动态加载器

点击此处获得更好的阅读体验


WP来源

来自Jazz原创投稿

题目考点

  • ELF文件

  • Linux ELF Dynaamic Loader 技术吧

  • 动态库链接器/加载器ld-linux.so

解题思路

开局一个Webshell,且提示无需提权

注释的命令大概就是先开始给elf文件755权限 可读可写可运行,后面再给644权限就不行了

目标为执行根目录下的elf文件readflag

什么是elf文件

ELF (文件格式):在计算机科学中,是一种用于二进制文件可执行文件目标代码、共享库和核心转储格式文件

通俗理解成在linux下的可执行文件

再回到题目提示 使用Linux ELF Dynaamic Loader 技术

这就要介绍Linux ELF Dynaamic Loader 技术了 翻译一下==Linux ELF动态加载器

结合题目给出无需提权,且咱们在webshell里直接/readflag 权限不够。

等于说咱们直接执行是不行的,那么显而易见,需要用到动态加载器来做到间接执行

需要用到:动态库链接器/加载器ld-linux.so.2

ld-linux.so.2是什么文件?

这是glibc的库文件,一般链接到相应版本的ld-xxx.so上,是和动态库载入有关的函数

很多现代应用都是通过动态编译链接的,当一个 需要动态链接 的应用被操作系统加载时,系统必须要 定位 然后 加载它所需要的所有动态库文件。 在Linux环境下,这项工作是由ld-linux.so.2来负责完成的,我们可以通过 ldd 命令来查看一个 应用需要哪些依赖的动态库:

1
2
3
4
5
6
7
8
9
10
11
$ ldd `which ls`
linux-gate.so.1 => (0xb7fff000)
librt.so.1 => /lib/librt.so.1 (0x00b98000)
libacl.so.1 => /lib/libacl.so.1 (0x00769000)
libselinux.so.1 => /lib/libselinux.so.1 (0x00642000)
libc.so.6 => /lib/libc.so.6 (0x007b2000)
libpthread.so.0 => /lib/libpthread.so.0 (0x00920000)
/lib/ld-linux.so.2 (0x00795000)
libattr.so.1 => /lib/libattr.so.1 (0x00762000)
libdl.so.2 => /lib/libdl.so.2 (0x0091a000)
libsepol.so.1 => /lib/libsepol.so.1 (0x0065b000)

当最常见的ls小程序加载时,操作系统会将 控制权 交给 ld-linux.so 而不是 交给程序正常的进入地址。 ld-linux.so.2 会寻找然后加载所有需要的库文件,然后再将控制权交给应用的起始入口。

上面的ls在启动时,就需要ld-linux.so加载器将所有的动态库加载后然后再将控制权移交给ls程序的入口。

ld-linux.so.2 man page给我们更高一层的全局介绍, 它是在 链接器(通常是ld)在运行状态下的部件,用来定位和加载动态库到应用的运行地址(或者是运行内存)当中去。通常,动态链接是 在连接阶段当中 隐式指定的。 gcc -W1 options -L/path/included -lxxx 会将 options 传递到ld 然后指定相应的动态库加载。 ELF 文件提供了相应的加载信息, GCC包含了一个特殊的 ELF 头: INTERP, 这个 INTERP指定了 加载器的路径,我们可以用readelf 来查看相应的程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ readelf -l a.out

Elf file type is EXEC (Executable file)
Entry point 0x8048310
There are 9 program headers, starting at offset 52

Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x004cc 0x004cc R E 0x1000
LOAD 0x000f0c 0x08049f0c 0x08049f0c 0x0010c 0x00110 RW 0x1000
. . .

ELF 规格要求,假如 PT_INTERP 存在的话,操作系统必须创建这个 interpreter文件的运行映射,而不是这个程序本身, 控制权会交给这个interpreter,用来定位和加载所有的动态库.

综上所述,使用动态加载器加载动态链接的elf文件

即命令:/lib64/ld-linux-x86-64.so.2 /readflag 即可获取flag

拓展知识(静态和动态链接)

Linux系统里有两种类型的可执行程序: 静态链接的可执行程序。这种程序文件本身包含了运行所需要的所有库函数的代码。程序自身就可以运行,而不依赖于额外的库文件。静态链接的程序的一个优点就是安装时不需要额外安装依赖库。 动态链接的可执行程序。动态链接程序只为调用的库函数设置了占位符,并没有真正把函数代码链接到程序本身中,所以这种程序体积小。而且往往多个程序依赖于同一个共享库文件,这样多个程序运行时,通过虚拟内存的机制,物理内存中之需要保留一份共享库代码,大大节约了内存空间。其缺点是自身运行需要依赖外部库文件,安装时如果所依赖的库文件不存在,需要额外安装库文件。总的来说,其优点大于缺点,所以目前系统上大多数程序都是动态链接的。

参考链接:

https://zhuanlan.zhihu.com/p/235551437

https://blog.csdn.net/lgfun/article/details/100138996

FLAG

1
动态flag