可重定位的目标文件phase1.o,在生成执行程序的过程中重定位的方法( 随机段地址版)

可重定位的目标文件phase1.o,在生成执行程序的过程中重定位的方法

随机段地址版

gcc main.o phase1.o -o linkbomb1
连接时,在各个.o合并生成了执行程序linkbomb1后,要对linkbomb1进行重定位。

1.查看phase1.o的重定位条目

$readelf -r phase1.o
Relocation section ‘.rela.text’ at offset 0x2b8 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000007 000300000002 R_X86_64_PC32 0000000000000000 .data + 10
00000000000f 000c00000004 R_X86_64_PLT32 0000000000000000 puts - 4
Relocation section ‘.rela.data.rel.local’ at offset 0x2e8 contains 1 entry:
Offset Info Type Sym. Value Sym. Name + Addend
000000000000 000a00000001 R_X86_64_64 0000000000000000 do_phase + 0

$objdump -d -r phase1.o
Disassembly of section .text:
0000000000000000 <do_phase>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # b <do_phase+0xb>
7: R_X86_64_PC32 .data+0x10
b: 48 89 c7 mov %rax,%rdi
e: e8 00 00 00 00 callq 13 <do_phase+0x13>
f: R_X86_64_PLT32 puts-0x4
13: 90 nop
14: 5d pop %rbp
15: c3 retq

2.phase1.o中数据节.data的重定位
2.1 查看数据节需要重定位的条目

$readelf -x.rel.data phase1.o
.rel.data
r1=00000000 00000000 01000000 0A000000 00000000 00000000
{
offset=0;
type=1; R_X86_64_64
sybmol=0a; do_phase
addend=0x0;
}
这个就是void (*phase)()=do_phase; 全局变量phase被初始化为do_phase子程序的起始地址。
而do_phase的地址,只有连接生成执行程序linkbomb1后,各个text合并后,才能确定do_phase的地址,重新对这个变量phase赋初值。

2.2 确定需要重定位的数据位置和长度: 0, 8

$readelf -x.data.rel.local phase1.o
Hex dump of section ‘.data.rel.local’:
NOTE: This section has relocations against it, but these have NOT been applied to this dump.
0x00000000 00000000 00000000

2.3 生成执行程序linkbomb1时,可重定位项目的重定位方法:

phase1.o中.data节的重定位如下:
refptr=s+r1.offset=.data.rel.local节在linkbomb中的.data段的地址+r1.offset=0x201088+0=0x201088
0x201088=linkbomb的.data段地址+phase1.o的.data.rel.local节在此段的偏移 =0x0x201000+0x88
0x88=main.o+init.o+phase1.o等的数据.data占的空间
*refptr=(unsigned long)(ADDR(r1.symbol)+r1.addend)==(0x0698 + 0x0)=0x0000000000000698

2.4 查看已重定位的.data节

$readelf -x.data linkbomb1
Hex dump of section ‘.data’: .data段地址0x201000
0x00201000 00000000 00000000 08102000 00000000 … …
0x00201010 00000000 00000000 00000000 00000000 …
0x00201020 5a354a48 526a6970 47713774 70674263 Z5JHRjipGq7tpgBc
0x00201030 62474454 50755061 49514b4d 48517465 bGDTPuPaIQKMHQte
0x00201040 62724b09 33795178 774c4d74 6c346b78 brK.3yQxwLMtl4kx
0x00201050 65477766 73354255 345a6762 49334572 eGwfs5BU4ZgbI3Er
0x00201060 5461516a 63444634 4c596462 73425430 TaQjcDF4LYdbsBT0
0x00201070 57553447 4b6c7654 36737053 315a4b76 WU4GKlvT6spS1ZKv
0x00201080 20780000 00000000 98060000 00000000 x…

3.phase1.o代码节.text的重定位

init.o+main.o+phase1.o===>linkbomb1 各代码节需要合并成代码段

3.1 查看.text代码节的重定位条目

$readelf -x.rel.text phase1.o
.rel.text
r1=07000000 00000000 02000000 03000000 10000000 00000000
{
offset=7;
type=0x02; R_X86_64_PC32
sybmol=3; .data 是本phase1.o的.data,与最后执行程序的.data不是一个,应加上偏移。
addend=0x10;
}
r2=0f000000 00000000 04000000 0c000000 fcffffff ffffffff
{
offset=0x0f;
type=4; R_X86_64_PLT32
sybmol=0x0c; puts
addend=-4;
}

3.2 反汇编.text代码节,进一步验证重定位条目。

$objdump -d -r phase1.o
Disassembly of section .text:
0000000000000000 <do_phase>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8d 05 00 00 00 00 lea 0x0(%rip),%rax # b <do_phase+0xb>
7: R_X86_64_PC32 .data+0x10
b: 48 89 c7 mov %rax,%rdi
e: e8 00 00 00 00 callq 13 <do_phase+0x13>
f: R_X86_64_PLT32 puts-0x4
13: 90 nop
14: 5d pop %rbp
15: c3 retq

3.3 确定phase1.o的代码节.text在linkbomb1中的起始地址

$ objdump -d linkbomb1
0000000000000698 <do_phase>:
698: 55 push %rbp
699: 48 89 e5 mov %rsp,%rbp
69c: 48 8d 05 91 09 20 00 lea 0x200991(%rip),%rax # 201034 <MBMlYcfY+0x14>
6a3: 48 89 c7 mov %rax,%rdi
6a6: e8 85 fe ff ff callq 530 puts@plt
6ab: 90 nop
6ac: 5d pop %rbp
6ad: c3 retq
6ae: 66 90 xchg %ax,%ax
do_phase是phase1.o中.text节的第一个函数,此地址就是.text地址

3.4 R_X86_64_PC32的重定位(R1):

refptr=s+r1.offset=<do_phase>地址+r1.offset=0x0698+0x07=0x069f
refaddr=ADDR(s)+r1.offset= 0x0698+0x07 == refptr
*refptr=(unsigned)(ADDR(r1.symbol)+r1.addend-refaddr)==0x201020+ 0x10 -0x069f = 0x200991
0x201020=是phase1.o中.data节,在linkbomb1的.data段的实际地址。

3.5 R_X86_64_PLT32的重定位(R2):

先计算要修改的地址refptr,再确定要写入的内容*refptr:
refptr=s+r2.offset=0x0698+0x0f=0x06a7
s=在执行程序linkbomb1的text段(合并了各text节)中原来phase1.o的.text节需重定位地址=<do_phase>地址=0x0698
*refptr=(unsigned)(ADDR(r2.symbol)+r2.addend-refptr)==(0x0530-0x04 - 0x06a7 = 0xfe85

通过 objdump -d linkbomb1 或者 objdump -d -j .plt linkbomb1 查看puts的地址
Disassembly of section .plt:
0000000000000520 <.plt>:
520: ff 35 9a 0a 20 00 pushq 0x200a9a(%rip) # 200fc0 <GLOBAL_OFFSET_TABLE+0x8>
526: ff 25 9c 0a 20 00 jmpq *0x200a9c(%rip) # 200fc8 <GLOBAL_OFFSET_TABLE+0x10>
52c: 0f 1f 40 00 nopl 0x0(%rax)
0000000000000530 puts@plt:
530: ff 25 9a 0a 20 00 jmpq *0x200a9a(%rip) # 200fd0 <puts@GLIBC_2.2.5>
536: 68 00 00 00 00 pushq $0x0
53b: e9 e0 ff ff ff jmpq 520 <.plt>

猜你喜欢

转载自blog.csdn.net/aurora0_0/article/details/84558442
今日推荐