通过未初始化的全局指针访问。

#include <stdio.h>

char * str = "Hello World";
int main(void){
    puts(str);
    return 0;
}

反汇编代码:

   0x000011e0 <+19>:	call   0x120d <__x86.get_pc_thunk.ax>
   0x000011e5 <+24>:	add    eax,0x2df3
   0x000011ea <+29>:	mov    edx,DWORD PTR [eax+0x30]
   0x000011f0 <+35>:	sub    esp,0xc
   0x000011f3 <+38>:	push   edx
   0x000011f4 <+39>:	mov    ebx,eax
   0x000011f6 <+41>:	call   0x1070 <puts@plt>

再看重定位表。

p@ubuntu:~/Templates$ readelf -r Hello

Relocation section '.rel.dyn' at offset 0x3a4 contains 9 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00003ed8  00000008 R_386_RELATIVE   # init_array
00003edc  00000008 R_386_RELATIVE   # fini_array
00003ff8  00000008 R_386_RELATIVE   
00004004  00000008 R_386_RELATIVE   
00004008  00000008 R_386_RELATIVE   # 这里就是我们str全局变量。该地址在data段
00003fec  00000106 R_386_GLOB_DAT    00000000   _ITM_deregisterTMClone
00003ff0  00000206 R_386_GLOB_DAT    00000000   __cxa_finalize@GLIBC_2.1.3
00003ff4  00000406 R_386_GLOB_DAT    00000000   __gmon_start__
00003ffc  00000606 R_386_GLOB_DAT    00000000   _ITM_registerTMCloneTa

Relocation section '.rel.plt' at offset 0x3ec contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00003fe4  00000307 R_386_JUMP_SLOT   00000000   puts@GLIBC_2.0
00003fe8  00000507 R_386_JUMP_SLOT   00000000   __libc_start_main@GLIBC_2.0

确实通过ip relative 来定位的全局变量,并不应该需要重定位,但只能定位到指向”helloWorld”字符串全局指针。但是这个全局指针需要重定位,将指向相对文件偏移的地址转化为指向内存偏移的地

通过未初始化的全局指针访问。

#include <stdio.h>
char * str2;
int main(void){
    str2 = "Hello World" ;
    puts(str2);
    return 0;
}

反汇编代码

   0x000011e0 <+19>:	call   0x1219 <__x86.get_pc_thunk.ax>
   0x000011e5 <+24>:	add    eax,0x2df3
   0x000011ea <+29>:	lea    edx,[eax-0x1fd0]
   0x000011f0 <+35>:	mov    DWORD PTR [eax+0x34],edx
   0x000011f6 <+41>:	mov    edx,DWORD PTR [eax+0x34]
   0x000011fc <+47>:	sub    esp,0xc
   0x000011ff <+50>:	push   edx
   0x00001200 <+51>:	mov    ebx,eax
   0x00001202 <+53>:	call   0x1070 <puts@plt>

没有重定位,懂得都懂。

局部变量使用访问模块内部全局变量指针。

char * str = "Hello World";
int main(void){
    char * str2 = str ;
    puts(str2);
    return 0;
}

反汇编代码

 0x000011e0 <+19>:	sub    esp,0x10
   0x000011e3 <+22>:	call   0x1215 <__x86.get_pc_thunk.ax>
   0x000011e8 <+27>:	add    eax,0x2df0
   0x000011ed <+32>:	mov    edx,DWORD PTR [eax+0x30]
   0x000011f3 <+38>:	mov    DWORD PTR [ebp-0xc],edx
   0x000011f6 <+41>:	sub    esp,0xc
   0x000011f9 <+44>:	push   DWORD PTR [ebp-0xc]
   0x000011fc <+47>:	mov    ebx,eax
   0x000011fe <+49>:	call   0x1070 <puts@plt>

通过ip relative 指令定位到0x4008,该地址的值指向”Hello World”字符串,

查看重定位表

p@ubuntu:~/Templates$ readelf -r Hello

Relocation section '.rel.dyn' at offset 0x3a4 contains 9 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00003ed8  00000008 R_386_RELATIVE   
00003edc  00000008 R_386_RELATIVE   
00003ff8  00000008 R_386_RELATIVE   
00004004  00000008 R_386_RELATIVE   
00004008  00000008 R_386_RELATIVE   # 这次将存储字符串的指针存放在该处
00003fec  00000106 R_386_GLOB_DAT    00000000   _ITM_deregisterTMClone
00003ff0  00000206 R_386_GLOB_DAT    00000000   __cxa_finalize@GLIBC_2.1.3
00003ff4  00000406 R_386_GLOB_DAT    00000000   __gmon_start__
00003ffc  00000606 R_386_GLOB_DAT    00000000   _ITM_registerTMCloneTa

Relocation section '.rel.plt' at offset 0x3ec contains 2 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00003fe4  00000307 R_386_JUMP_SLOT   00000000   puts@GLIBC_2.0
00003fe8  00000507 R_386_JUMP_SLOT   00000000   __libc_start_main@GLIBC_2.0

该处为data段。

且该地址的值为0x2008 , 刚好为“hello world” 字符串的文件偏移。

直接访问

#include <stdio.h>
int main(void){
    puts("Hello World");
    return 0;
}

同未初始化的全局指针访问。那必然不需要重定位。

结论

模块内部变量指针类型重定位地址
直接访问
全局函数指针调用R_386_RELATIVEdata段
未初始化全局指针访问
局部指针访问R_386_RELATIVEdata段

到这里,有个体会,重定位的对象都是指针。

分类: ELF安卓

pareto

未来什么方向不管,先做自己喜欢做的事情。

0 条评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注