• Home
  • About
    • Rhy7hm photo

      Rhy7hm

      天天被计算机教做人

    • Learn More
    • Email
  • Posts
    • All Posts
    • All Tags
  • Projects

哇,是PT_DYNAMIC!

06 Sep 2018

Reading time ~2 minutes

0x01 动态段

类型:PT_DYNAMIC

包括但不限于:

1) 运行时需要链接的共享库列表

2) 全局偏移表GOT地址

3) 重定位条目的相关信息

ELF 动态数组标记 可以参考: https://docs.oracle.com/cd/E24847_01/html/E22196/chapter6-14428.html#scrolltoc

一些入口可以参考:

https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/dynamicsection.html

32位ELF文件动态段的结构体如下:

typedef struct {
    Elf32_Sword d_tag;
    union {
        Elf32_Word d_val;
        Elf32_Addr d_ptr;
    } d_un;
} Elf32_Dyn;
extern Elf32_Dyn _DYNAMIC[]

其中d_tag决定了d_un的含义,d_val成员保存了一个整型值,d_ptr成员保存了一个内存虚址。

一些和re2diresolve相关的 类型/入口/地址

DT_SYMTAB –> 动态符号表的地址,对应的节名.dynsym

其中

struct Elf32_Sym
{
  Elf32_Word    st_name;   /* Symbol name (string tbl index) */
  Elf32_Addr    st_value;  /* Symbol value */
  Elf32_Word    st_size;   /* Symbol size */
  unsigned char st_info;   /* Symbol type and binding */
  unsigned char st_other;  /* Symbol visibility */
  Elf32_Section st_shndx;  /* Section index */
};
struct Elf64_Sym
{
  Elf64_Word    st_name;   /* Symbol name (string tbl index) */
  unsigned char st_info;   /* Symbol type and binding */
  unsigned char st_other;  /* Symbol visibility */
  Elf64_Section st_shndx;  /* Section index */
  Elf64_Addr    st_value;  /* Symbol value */
  Elf64_Xword   st_size;   /* Symbol size */
};

如: Elf32_Sym <offset aRead - offset byte_804822C, 0, 0, 12h, 0, 0> ; "read"

其中的offset aRead - offset byte_804822C,即该符号的名字,是下面提到的DT_STRTAB中的一个字符串,

DT_STRTAB –> 符号字符串表的地址,对应的节名.dynstr

DT_JMPREL –>Address of PLT relocs,与过程链接表单独关联的重定位项的地址。

typedef struct elf32_rel {
  Elf32_Addr    r_offset;
  Elf32_Word    r_info;
} Elf32_Rel;

其中r_offset为应用重定位操作的位置,r_info可以认为是ELF32_R_SYM||ELF32_R_TYPE (#define ELF32_R_INFO(s, t) (((s)«8)+(unsigned char)(t)))

可参考:

https://docs.oracle.com/cd/E19957-01/806-0641/chapter6-54839/index.html

DT_VERSYM –>Address of the table provided by the .gnu.version section.This section contains the Symbol Version Table. 如: Alt text

再用我手上的程序对着四个类型举个例子

Alt text

参考:

还是《Linux二进制分析》

还是angelboy的slide

http://pwn4.fun/2016/11/09/Return-to-dl-resolve/

https://ctf-wiki.github.io/ctf-wiki/pwn/stackoverflow/advanced_rop/

《程序员的自我修养》


彩蛋:

32位linux的内存地址分布:

64位


继续彩蛋

free 命令显示系统使用和空闲的内存情况,包括物理内存、交互区内存(swap)和内核缓冲区内存。


还是彩蛋:

如果ELF文件是以PIC模式编译的(动态链接的可执行文件一般是PIC的),调用的外部函数会出现在.rel.plt中,不使用的话会出现在.rel.dyn中。

.rel.dyn实际上是对数据引用的修正,所修正的位置位于.got及其数据段;

.rel.plt是对数据引用的修正,修正的位置位于.got.plt


彩蛋+1:

进程的内存布局。

随手举个例子。

gdb-peda$ vmmap
Start      End        Perm	Name
0x08048000 0x08049000 r-xp	/root/Desktop/king/12lev/level12
0x08049000 0x0804a000 r--p	/root/Desktop/king/12lev/level12
0x0804a000 0x0804b000 rw-p	/root/Desktop/king/12lev/level12

0xf7dc6000 0xf7ddf000 r--p	/lib32/libc-2.27.so
0xf7ddf000 0xf7f2b000 r-xp	/lib32/libc-2.27.so
0xf7f2b000 0xf7f99000 r--p	/lib32/libc-2.27.so
0xf7f99000 0xf7f9a000 ---p	/lib32/libc-2.27.so
0xf7f9a000 0xf7f9c000 r--p	/lib32/libc-2.27.so
0xf7f9c000 0xf7f9d000 rw-p	/lib32/libc-2.27.so


0xf7f9d000 0xf7fa0000 rw-p	mapped
0xf7fce000 0xf7fd0000 rw-p	mapped
0xf7fd0000 0xf7fd3000 r--p	[vvar]
0xf7fd3000 0xf7fd5000 r-xp	[vdso]
0xf7fd5000 0xf7fd6000 r--p	/lib32/ld-2.27.so
0xf7fd6000 0xf7ff1000 r-xp	/lib32/ld-2.27.so
0xf7ff1000 0xf7ffb000 r--p	/lib32/ld-2.27.so
0xf7ffc000 0xf7ffd000 r--p	/lib32/ld-2.27.so
0xf7ffd000 0xf7ffe000 rw-p	/lib32/ld-2.27.so
0xfffdd000 0xffffe000 rw-p	[stack]

↓

text段	可读可执行
data段 part one -->开了只读重定位RELRO		// -->.got
data段剩余部分							//.got.plt -->

然后是libc的内存映射,如下图

其中0xf7f99000 0xf7f9a000 ---p /lib32/libc-2.27.so的存在是为了占用text段和data段之间的内存空间,从而无法创建任意的内存映射。

PS:堆通常位于data段之后(maps文件中)(这里没有),而当调用malloc()请求的内存块大小超过MMAP_THRESHOLD时,会创建匿名内存段,这种类型的匿名内存段不会被标上[heap]标签。

0xf7f9d000 0xf7fa0000 rw-p	mapped
0xf7fce000 0xf7fd0000 rw-p	mapped

可参考:

What is an anonymous mapping?

Glibc 内存管理

然后是用于内核数据交互的vvar。内核通过映射到用户空间的一段只读区域来返回内核数据,这就是内存中的[vvar]区域。 + 虚拟动态共享目标文件(Virtual Dynamic Shared Object),被glibc用于调用一些常用的系统调用。

0xf7fd0000 0xf7fd3000 r--p	[vvar]
0xf7fd3000 0xf7fd5000 r-xp	[vdso]

然后是一大段动态连接器的内存映射。从技术上来讲,动态连接器也是一个共享库。 最后是栈。



pwndlresolve Share Tweet +1