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

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

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

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

$readelf -r phase1.o

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

$readelf -x.rel.data phase1.o
.rel.data
r1=00000000 00000000 01000000 09000000 00000000 00000000
{
offset=0;
type=1; R_X86_64_64
sybmol=9; 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 phase1.o
Hex dump of section ‘.data’:
NOTE: This section has relocations against it, but these have NOT been applied to this dump.
0x00000000 00000000 00000000 00000000 00000000 …
0x00000010 00000000 00000000 00000000 00000000 …
0x00000020 5a354a48 526a6970 47713774 70674263 Z5JHRjipGq7tpgBc
0x00000030 62474454 50755061 49514b4d 48517465 bGDTPuPaIQKMHQte
0x00000040 62724b09 33795178 774c4d74 6c346b78 brK.3yQxwLMtl4kx
0x00000050 65477766 73354255 345a6762 49334572 eGwfs5BU4ZgbI3Er
0x00000060 5461516a 63444634 4c596462 73425430 TaQjcDF4LYdbsBT0
0x00000070 57553447 4b6c7654 36737053 315a4b76 WU4GKlvT6spS1ZKv
0x00000080 207800 x.

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

phase1.o中.data节的重定位如下:
refptr=s+r1.offset=.data节在linkbomb中的.data段的地址+r1.offset=0x601040+0=0x00601040
0x601040=linkbomb的.data段地址+phase1.o的.data节在此段的偏移=0x601020+0x20
0x20=main.o+init.o等的数据占的空间
*refptr=(unsigned long)(ADDR(r1.symbol)+r1.addend)==(0x400514 + 0x0)=0x0000000000400514

2.4 查看已重定位的.data节

$readelf -x.data linkbomb1
Hex dump of section ‘.data’: .data段地址0x601020
0x00601020 00000000 00000000 00000000 00000000 …
0x00601030 00000000 00000000 00000000 00000000 …
0x00601040 14054000 00000000 00000000 00000000 …@…
0x00601050 00000000 00000000 00000000 00000000 …
0x00601060 5a354a48 526a6970 47713774 70674263 Z5JHRjipGq7tpgBc
0x00601070 62474454 50755061 49514b4d 48517465 bGDTPuPaIQKMHQte
0x00601080 62724b09 33795178 774c4d74 6c346b78 brK.3yQxwLMtl4kx
0x00601090 65477766 73354255 345a6762 49334572 eGwfs5BU4ZgbI3Er
0x006010a0 5461516a 63444634 4c596462 73425430 TaQjcDF4LYdbsBT0
0x006010b0 57553447 4b6c7654 36737053 315a4b76 WU4GKlvT6spS1ZKv
0x006010c0 207800 x.

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

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

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

$readelf -x.rel.text phase1.o
.rel.text
r1=05000000 00000000 0a000000 03000000 34000000 00000000
{
offset=5;
type=0x0a; R_X86_64_32
sybmol=3; .data 是本phase1.o的.data,与最后执行程序的.data不是一个,应加上偏移。
addend=0x34;
}
r2=0a000000 00000000 02000000 0a000000 fcffffff ffffffff
{
offset=0x0a;
type=2; R_X86_64_PC32
sybmol=0x0a; puts
addend=-4;
}

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

$objdump -d -r phase1.o
0000000000000000 <do_phase>:
0: 48 83 ec 08 sub $0x8,%rsp
4: bf 00 00 00 00 mov $0x0,%edi
5: R_X86_64_32 .data+0x34
9: e8 00 00 00 00 callq e <do_phase+0xe>
a: R_X86_64_PC32 puts-0x4
e: 48 83 c4 08 add $0x8,%rsp
12: c3 retq

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

$ objdump -d linkbomb1
0000000000400514 <do_phase>:
400514: 48 83 ec 08 sub $0x8,%rsp
400518: bf 74 10 60 00 mov $0x601074,%edi
40051d: e8 ce fe ff ff callq 4003f0 puts@plt
400522: 48 83 c4 08 add $0x8,%rsp
400526: c3 retq
400527: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
40052e: 00 00
do_phase是phase1.o中.text节的第一个函数,此地址就是.text地址

3.4 R_X86_64_32的重定位(R1):

先计算要修改的地址refptr,再确定要写入的内容*refptr:
refptr=s+r1.offset=0x400514+5=0x400519
s=在执行程序linkbomb1的text段(合并了各text节)中原来phase1.o的.text节需重定位地址=<do_phase>地址=0x400514
*refptr=(unsigned)(ADDR(r1.symbol)+r1.addend)==(0x601020+0x20)+ 0x34=0x601074
ADDR(r1.symbol)=0x601020+0x20
0x601020 是linkbomb的数据段.data的地址
0x20 是phase1.o的.data节在linkbomb1的.data段的偏移,包括init.o等+main.o占用空间,长度0x20。连接合并data节时确定的。
通过如下方法查看
readelf -S -W linkbomb1 .data 是0xA3长度
readelf -S -W phase1.o .data 是0x83长度

3.5 R_X86_64_PC32的重定位(R2):

refptr=s+r2.offset=<do_phase>地址+r2.offset=0x400514+0x0a=0x40051e
refaddr=ADDR(s)+r2.offset= 0x400514+0x0A=0x40051E == refptr
*refptr=目标地址-下一指令地址=(unsigned)(ADDR(r2.symbol)+r2.addend-refaddr)==0x4003f0 + -0x4 -0x40051e = 0xfffffece
下一指令地址 = r2.addend - refaddr
通过 objdump -d linkbmb1 或者 objdump -d -j .plt linkbomb1 查看puts的地址

00000000004003e0 <.plt>:
4003e0: ff 35 22 0c 20 00 pushq 0x200c22(%rip) # 601008 <GLOBAL_OFFSET_TABLE+0x8>
4003e6: ff 25 24 0c 20 00 jmpq *0x200c24(%rip) # 601010 <GLOBAL_OFFSET_TABLE+0x10>
4003ec: 0f 1f 40 00 nopl 0x0(%rax)
00000000004003f0 puts@plt:
4003f0: ff 25 22 0c 20 00 jmpq *0x200c22(%rip) # 601018 <puts@GLIBC_2.2.5>
4003f6: 68 00 00 00 00 pushq $0x0
4003fb: e9 e0 ff ff ff jmpq 4003e0 <.plt>

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值