快捷搜索:   nginx

Linux系统下解析Elf文件DT_RPATH后门

  一。前言

    前一段时间回顾elf文件方面的知识时,翻了以前很多优秀的文章,在xfocus的帮助文件unix版中看到了alert7大侠<> 这篇文章,看了一下时间9月/14号,那段时间忙着重修,没到网吧去。alert7没有贴代码,我想还是有人不了解,就把这篇文章写出来给大家整理性的介绍一下,这里指的是linux下。

这篇文章不是介绍elf基础的文章,所以一些概念性的东西请参考elf鉴别,然后拿起你的gdb实际去了解一下啥叫got,plt,重定向的概念,了解一下动态连接和静态连接,用readelf或者objdump实际看一下,后面的参考中可以找到你需要的。文中错误再所难免,欢迎指正;)

  二。分析

    后门存在的原因:

引自<>

*动态数组标记DT_RPATH保存着目录列表的字符串(用冒号(:)分隔)。

例如,字符串/home/dir/lib:/home/dir2/lib:告诉动态连接器先搜索/home/dir/lib,再搜索/home/dir2/lib,再是当前目录。

    LD_LIBRARY_PATH环境变量设置的目录在DT_RPATH指向的目录之后被搜索。而且出于安全考虑,动态连接器忽略set-user和set-group的程序的LD_LIBRARY_PATH所指定的搜索目录。但它会搜索DT_RPATH指明的目录和/usr/lib。所以这个DT_RPATH还是比较感兴趣的。

    有了以上的基本知识,我们可以在一个set-user的程序上安装一个DT_RPATH入口(一般程序都没有)。让其搜索路径首先为当前目录。把我们自己编写的库以其名字放到当前目录下,更让其加栽我们自己的动态库。这样我们就可以得到set-user的权限了。

    截获了__libc_start_main,肯定能确保ping 程序放弃特权之前执行。(假如截获malloc之类的就不能确保了)。因为我们用到了一些libc。so。6中的函数,所以我们需要把我们自己的LIB以libresolv。so。2的名字存放在当前目录下。

由此实现这个后门的关键在于:

    a:修改或添加(通常是不存在的)在。dynamic节中(数组)d_tag为DT_RPATH的入口结构(entry)d_un。d_val指向为到。dynstr节的的一个以**NULL结尾字符串的偏移量(如果存在DT_RATH的话)。此字符串是路径的集合,其中路径以:分开。

    最后一个:后面表示当前目录,如果前面的字符串改成这样的"_wujianqiang:\0"(这样用来表示一个NULL;))表明现在当前目录下的_wujianqiang子目录中寻找,然后再在当前目录下寻找,显然这里采用的相对目录,我们主要是构造这个字符串,同时我们要想到,我们是添加一个这样的字符串还是修改某个字符串成为我们需要的形式,显然前者就比较复杂,就要使program header ,section 的某些成员都要改变,所以我们采用修改的方法,找一个动态符号修改,这里我选用了__gmon_start__这个字符串。当然其它的也可以,不过发现__gmon_start__有点特殊,并且几乎所有的程序里都有这个符号,所以我就选了这个。

    通常d_tag为DT_RPATH的入口结构不存在,所以我们要添加这个DT_RPATH,实际上。dynamic数组中应该有几个空的没用的这样的NULL入口,(一般都可以找到)所以我在程序中找的是第一个NULL入口,没有采用修改某些入口的方法。同样的这里我们不需要修改任何section,program header 的某些结构成员,因为这里有并且存在entry结构,我们不用添加只要修改。至此我们的elf文件修改任务结束。

    b。现在我们只需要做的就是截获那个函数的问题,alert7提出了截获__libc_start_main这个函数,我们就来截获这个函数但是为啥“能够“截获这个函数的原因我们在后面讲述。

我们先解决问题a:

下面是相关知识

通常来说每一个动态连接的object它的程序头表将有一个类型为PT_DYNAMIC的元素。该“段”包含了。dynamic section。

每个入口(entry)的结构如下:

+ 图一。 Dynamic Structure

typedef struct

{

Elf32_Sword d_tag; /* Dynamic entry type */

union

{

Elf32_Word d_val; /* Integer value */

Elf32_Addr d_ptr; /* Address value */

} d_un;

} Elf32_Dyn;

下面用readelf解释一下

+图二

[wujian@redhat72 elf_door]$ readelf -l 。/pinG

Program Headers:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align [。。。。]

DYNAMIC 0x005618 0x0804e618 0x0804e618 0x000d0 0x000d0 RW 0x4

Section to Segment mapping:

Segment Sections。。。

[。。。。]

04 dynamic

[wujian@redhat72 elf_door]$ readelf -S 。/pinG

There are 24 section headers, starting at offset 0x57cc:

Section Headers: 其中省略部分

[Nr] Name Type Addr Off Size ES Flg Lk Inf Al

[ 4] 。dynsym DYNSYM 080482a0 0002a0 000370 10 A 5 1 4

[ 5] 。dynstr STRTAB 08048610 000610 000233 00 A 0 0 1

[ 8] 。rel。dyn REL 080488e4 0008e4 000030 08 A 4 0 4

[ 9] 。rel。plt REL 08048914 000914 000168 08 A 4 b 4

[11] 。plt PROGBITS 08048a94 000a94 0002e0 04 AX 0 0 4

[12] 。text PROGBITS 08048d80 000d80 003230 00 AX 0 0 16

[19] 。got PROGBITS 0804e554 005554 0000c4 04 WA 0 0 4

[20] 。dynamic DYNAMIC 0804e618 005618 0000d0 08 WA 5 0 4

 [2] [3] [4] [5] [6] [7] 下一页

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论