首页
社区
课程
招聘
[原创]GOT,PLT和动态链接
发表于: 2025-7-7 19:15 4067

[原创]GOT,PLT和动态链接

2025-7-7 19:15
4067

第一次写文章,大佬们轻喷,如有错误,恭请指正

本文通过实验理清.plt & .plt.got & .got & .got.plt的内存布局与执行流程。

1、gcc、gdb、readelf、010editor(添加elf解析模板请自行解决)
2、gdb需要了解下x命令
图片描述
如:

symbol.c定义了一个全局变量与全局函数,编译为动态链接库

main.c调用动态链接库symbol.so

生成文件如下
图片描述
运行
图片描述
第一次失败是因为动态链接器找不到动态链接库libsymbol.so,将该库加入/usr/lib32就行。执行成功返回结果52

先看看可执行文件main里面的节区。可以看到各节区的Addr,是一个相对地址,如.data节区Addr为0x00004008,这就是位置无关代码技术。意味着可以把main可执行文件加载到进程的虚拟内存空间的任意位置。和offset文件偏移相似,可以把它当成相对于虚拟内存空间的偏移。

图片描述
gdb调试main,然后查看plt

.plt & .plt.got
图片描述
红线上方为.plt,下方为.plt.got
前两项为公共表项,作用是跳转到.got.plt中进行"函数真实地址解析"的函数
0x102c开始那4个字节都为0x00,可以不用管什么意思
.plt保存函数跳转桩,如my_func的跳转jmp *0x10(%ebx)
.got.plt

图片描述
.got.plt保存动态链接的函数在内存中实际地址,如0x4004处my_func的地址0x00001046。供.plt使用,实现延迟绑定。i386架构下,.got.plt保留了3个公共表项,从0x3ff4开始4字节为一项,前3项分别为:

.got

图片描述
.got保存全局符号的地址,如0x3fec处的0x0000118d,为main函数的地址
总体看来:
图片描述

①静态调试
上一步静态调试中查看了4个节区在程序中的虚拟内存布局,接下来模拟程序运行进行讲解。会用到上面大局观中的4个图,可以用pixpin贴在屏幕上
反汇编main函数

图片描述
①处调用函数,__x86.get_pc_thunk.ax功能是,将函数的返回地址保存到eax寄存器,即将下一行语句地址0x11a4保存到eax,然后下一行add 0x2e50,最后寄存器eax(PIC寄存器)值为0x3ff4,即为.got.plt的起始地址!此处涉及到位置无关代码技术,实际上就是通过运行时PC指针的值来找到代码所引用的 其他符号的位置, 不管二进制文件被加载到哪个位置, 都可以正确执行。可以看看链接位置无关代码。
②处将eax赋值给ebx,现在ebx为PIC寄存器(PIC寄存器保存.got.plt的地址)。然后调用了my_func函数,地址为0x1040。该地址在.plt中,对应三条语句如下(大局观图①)
图片描述
第一行,jmp到其他地址。ebx寄存器保存的是.got.plt的虚拟地址,即0x3ff4,0x10为偏移,表示从.got.plt偏移0x10的地方取值,0x3ff4+0x10=0x4004,所以第一行语句作用是从0x4004地址取出值,作为jmp的地址进行跳转。
查看.got.plt,0x4004处的值是0x1046(大局观图②)
图片描述
这里0x1046似曾相识,居然是上面.plt中的第二行语句的地址。所以又回到了.plt的第二行语句,接着往下走,第二行push参数8入栈,这个参数用于寻找解析my_func,是_dl_runtime_resolve函数的参数,按下不表。第三行语句jmp 0x1020,又回到了.plt开头地址(大局观图①)
图片描述
往下走,push参数ebx偏移4位置的值入栈,是_dl_runtime_resolve函数的参数,按下不表,jmp *0x8(%ebx),说过ebx存储.got.plt的地址,所以是从.got.plt偏移0x8的地方取值,0x3ff4+0x8=0x3ffc,查看.got.plt,0x3ffc处的值是0x00000000(大局观图②)
图片描述
实际上这是函数_dl_runtime_resolve的地址,之前有提到过两个按下不表的_dl_runtime_resolve函数的参数,分别是.plt中my_func函数桩push $0x8,和公共表项push 0x4(%ebx)。所以这里jmp *0x8(%ebx)实际就是调用了_dl_runtime_resolve((link_map *)m, 8)!参数8表示my_func对应的重定位条目在.rel.plt中的偏移为8个字节,查看.rel.plt表
图片描述
.rel.plt偏移8个字节为0x00004004,0x00000307,表示需要重定位的地址在0x4004,在.got.plt表中可以看到是my_func(大局观图②)。0x00000307后8位为重定位类型,07表示R_386_JUMP_SLOT,前24位为符号表索引,000003表示在.dynsym中索引为3的符号。参数0x4(%ebx)为.got.plt的第二项即got[1],上面说过got[1]存储的是link_map数据结构描述符地址,提供了运行时的必要信息。
_dl_runtime_resolve函数接下来会解析出my_func的地址并将值填入.got.plt中,然后跳转执行真正的my_func函数。该函数定义在glibc/sysdeps/i386/dl-trampoline.S中, 关键代码如下:

以上即是main第一次调用my_func的流程。总结一下,main函数中调用my_func,会跳转到.plt对应的函数桩代码,然后第一行直接到.got.plt取出存储的my_func的真实地址进行跳转,只不过第一次调用时,.got.plt中存储的并不是“真实地址”,而是.plt函数桩代码的下一行,跳回.plt函数桩后,将_dl_runtime_resolve的参数my_func对应的重定位条目偏移压入栈中,接着又跳转到.plt的首地址,将_dl_runtime_resolve的参数got[1] link_map压入栈中,然后跳转到got[2],调用_dl_runtime_resolve解析真正的地址填入.got.plt后,由动态链接器跳转到my_func的真实地址,而不返回.plt。
之后调用my_func,则会从.plt函数桩跳转到.got.plt中存储的真实的函数地址。
②动态调试
接下来就去看看实际运行过程中,内存中真实的值。

图片描述
查看4个表的真实地址

图片描述
图片描述
再次查看我们关心的4个表的内容
.plt & .plt.got

图片描述
.got.plt

图片描述
此时my_func的真实地址还没解析填充,因为程序断在了main函数开始,还没有执行调用my_func。__libc_start_main函数的地址已经解析填充,为0xf7d81d00。
可以看到got[1]、got[2]也有值了,got[1]为link_map的地址,got[2]为_dl_runtime_resolve函数的地址
.got

图片描述
0xf7f9f004存储的是my_var
图片描述
0xf7d9b260存储的是__cxa_finalize函数
图片描述
0x5655618d存储的是main函数、
前面说过因为还没有调用my_func,所以.got.plt没有my_func的真实地址,接下来继续下一步,运行完程序。

图片描述
再次查看.got.plt
图片描述
my_func地址解析并填充了,这个地址0xf7f9c13d在libsymbol.c的.text节中
图片描述






引用与参考:
73eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6W2N6X3W2D9M7r3q4F1i4K6u0W2j5$3!0E0i4K6u0r3x3U0l9I4z5q4)9J5c8U0l9@1i4K6u0r3x3o6W2Q4x3V1k6S2j5X3!0#2N6q4)9J5k6r3N6G2N6q4)9J5k6s2m8D9N6q4)9J5c8W2)9J5x3#2)9J5y4f1f1#2i4K6t1#2z5p5q4Q4x3U0g2m8z5q4)9J5y4f1f1$3i4K6t1#2z5o6m8Q4x3U0f1^5x3g2)9J5y4f1f1#2i4K6t1#2z5o6S2Q4x3U0f1^5y4W2)9J5y4f1f1$3i4K6t1#2z5f1g2Q4x3U0f1&6x3l9`.`.
Tool Interface Standard (TIS) Executable and Linking Format (ELF) Specification Version 1.2
ELF文件格式分析-北大操作系统实验室.pdf
程序员的自我修养第2、3、4、7章
279K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6M7r3q4U0k6g2)9J5k6h3u0A6L8r3W2T1K9h3I4A6i4K6u0W2j5$3!0E0i4K6u0r3x3K6M7^5y4K6M7$3y4e0c8Q4x3V1k6D9K9i4y4@1M7#2)9J5c8U0p5@1y4U0M7J5z5o6u0Q4x3@1k6@1P5i4m8W2i4K6y4p5M7$3g2J5K9h3g2K6
感兴趣可以看:
cc5K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6W2N6X3W2D9M7r3q4F1i4K6u0W2j5$3!0E0i4K6u0r3x3U0l9J5x3q4)9J5c8U0l9&6i4K6u0r3x3e0y4Q4x3V1k6Y4k6r3u0Q4x3X3c8@1K9i4m8K6i4K6u0r3
125K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6G2j5h3y4A6j5g2)9J5k6h3c8W2N6W2)9J5c8X3q4F1k6s2u0G2K9h3c8Q4x3X3c8D9L8$3q4V1i4K6u0V1M7$3!0Q4x3V1j5`.
40eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6*7K9s2g2S2L8X3I4S2L8W2)9J5k6i4A6Z5K9h3S2#2i4K6u0W2j5$3!0E0i4K6u0r3M7q4)9J5c8U0M7H3z5e0R3J5y4K6t1H3z5b7`.`.

x/5wx 0x3ff4,w表示word,4个字节,x表示hex16进制格式,所以就是从0x3ff4打印516进制的4字节数据
x/5wx 0x3ff4,w表示word,4个字节,x表示hex16进制格式,所以就是从0x3ff4打印516进制的4字节数据
x/12i 0x1020,表示从0x1020处打印12个instruction
x/12i 0x1020,表示从0x1020处打印12个instruction
// symbol.c
int my_var = 42;
int my_func(int a, int b) {
    return a + b;
}
// symbol.c
int my_var = 42;
int my_func(int a, int b) {
    return a + b;
}
gcc -g -m32 -masm=intel -shared -fPIC symbol.c -o libsymbol.so
gcc -g -m32 -masm=intel -shared -fPIC symbol.c -o libsymbol.so
// main.c
int var = 10;
extern int my_var;
extern int my_func(int, int);
 
int main() {
    int a, b;
    a = var;
    b = my_var;
    return my_func(a, b);
}
// main.c
int var = 10;
extern int my_var;
extern int my_func(int, int);
 
int main() {
    int a, b;
    a = var;
    b = my_var;
    return my_func(a, b);
}
# 位置无关
gcc -g -m32 -masm=intel -L. -lsymbol main.c libsymbol.so -o main
# 位置无关
gcc -g -m32 -masm=intel -L. -lsymbol main.c libsymbol.so -o main
readelf -S main
readelf -S main
gdb main
x/12i 0x1020
gdb main
x/12i 0x1020
x/5wx 0x3ff4
x/5wx 0x3ff4
got[0]: 本ELF的.dynamic节区的装载地址(此处为0x00003ee4)
got[1]: 本ELF的link_map数据结构描述符地址(此处为0x00000000,还未填充真实地址)
got[2]: _dl_runtime_resolve函数的地址(此处为0x00000000,还未填充真实地址)
got[0]: 本ELF的.dynamic节区的装载地址(此处为0x00003ee4)

[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!

最后于 2025-7-15 17:32 被whohh编辑 ,原因:
收藏
免费 7
支持
分享
最新回复 (4)
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
2
能私聊吗
2025-7-24 22:50
0
雪    币: 678
活跃值: (670)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
mb_yqsvfqmf 能私聊吗
可以
2025-7-25 10:46
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
whohh 可以
留个联系方式
2025-7-29 07:39
0
雪    币: 678
活跃值: (670)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
mb_yqsvfqmf 留个联系方式
v550580
2025-7-29 15:12
0
游客
登录 | 注册 方可回帖
返回