- 论坛徽章:
- 0
|
本帖最后由 kdx_test 于 2020-05-15 08:32 编辑
我baidu了一下,在 linux 32位系统里面,有关动态链接里 GOT表的访问,说大致为以下样式:
- fun@plt:
- jmp *(fun@got.plt)
- push index
- jmp _init
复制代码
至于 linux 64位系统,我也baidu了一下,似乎样式跟 上面 32位系统的是一样的,只是地址不一样(变成 0x400XXX)。
但实际上,对于 Linux 64 位系统(ubuntu17.04 64位),我自己写了一个例子测试后发现却不是这样,我的测试样式如下:
- fun@plt
- jmpq *0x20089a(%rip) // 200fb8 <a1>, ff 25 9a 08 20 00
- xchg %ax,%ax // 66 90
复制代码
问题:
我的测试有问题?
附上测试过程如下(测试环境:ubuntu 17.04 64位):
- //代码 a1.c
- #include <stdio.h>
- static char arr[] = {
- 'w','x','y','z','4','4','4','4'
- };
- void a1()
- {
- printf("a1.c\n");
- printf("a1:%s\n",arr);
- }
- //代码 a2.c
- #include <stdio.h>
- static char arr[] = "abcd12345";
- void a2()
- {
- printf("a2.c\n");
- printf("a2:%s\n",arr);
- }
- //代码 b1.c
- #include <stdio.h>
- void b1()
- {
- char arr[] = "ghij56789";
- printf("b1.c\n");
- printf("b1:%s\n", arr);
- }
- //代码 b2.c
- #include <stdio.h>
- void b2()
- {
- char arr[] = {
- 'k','l','m','n','2','2','2','2'
- };
- printf("b2.c\n");
- printf("b2:%s\n",arr);
- }
- //代码 main.c
- #include <stdio.h>
- void a1();
- void a2();
- void b1();
- void b2();
- int main()
- {
- a1();
- a2();
- b1();
- b2();
- printf("main.c\n");
- return 0;
- }
- //编译
- gcc -g -fPIC -shared a1.c -o a1.so
- gcc -g -fPIC -shared a2.c -o a2.so
- gcc -g -fPIC -shared b1.c -o b1.so
- gcc -g -fPIC -shared b2.c -o b2.so
- gcc main.c a1.so a2.so b1.so b2.so -o main -g -Xlinker -rpath ./
- 使用 gdb 调试
- > gdb main
- > b main
- > r
- > disass main
- Dump of assembler code for function main:
- 0x0000555555554870 <+0>: push %rbp
- 0x0000555555554871 <+1>: mov %rsp,%rbp
- => 0x0000555555554874 <+4>: mov $0x0,%eax
- 0x0000555555554879 <+9>: callq 0x555555554718 //实际是 call a1
- 0x000055555555487e <+14>: mov $0x0,%eax
- 0x0000555555554883 <+19>: callq 0x555555554728
- 0x0000555555554888 <+24>: mov $0x0,%eax
- 0x000055555555488d <+29>: callq 0x555555554738
- 0x0000555555554892 <+34>: mov $0x0,%eax
- 0x0000555555554897 <+39>: callq 0x555555554720
- 0x000055555555489c <+44>: lea 0x91(%rip),%rdi # 0x555555554934
- 0x00005555555548a3 <+51>: callq 0x555555554710
- 0x00005555555548a8 <+56>: mov $0x0,%eax
- 0x00005555555548ad <+61>: pop %rbp
- 0x00005555555548ae <+62>: retq
- End of assembler dump.
- 以 call 0x555555554718 为例
- > x/16x 0x555555554718
- 0x555555554718: 0x089a25ff 0x90660020 0x08aa25ff 0x90660020
- .......................
- 转换前8个字节(小端转大端)
-
- ff 25 9a 08 20 00 66 90
- 这个就是我之前提到样式
- GOT条目地址 = 当前EIP + 偏移 + sizeof(调用指令)
- = 0x555555554718 + 0x20089a + sizeof(调用指令)
- = 0x555555554718 + 0x20089a + 6
- = 0x555555754FB8
- > x/16x 0x555555754FB8(GOT条目地址)
- 0x555555754fb8: 0xf7bd56c0 0x00007fff 0xf7228300 0x00007fff
- 转换前8个字节(小端转大端)
- c0 56 bd f7 ff 7f 00 00
- 目标函数地址 = 0x7ffff7bd56c0
- > x/16x 0x7ffff7bd56c0(目标函数)
- 0x7ffff7bd56c0 <a1>: 0xe5894855 0x2a3d8d48 0xe8000000 0xfffffec0
- 0x7ffff7bd56d0 <a1+16>: 0x59358d48 0x48002009 0x001c3d8d 0x00b80000
- 0x7ffff7bd56e0 <a1+32>: 0xe8000000 0xfffffeb8 0x00c35d90 0x08ec8348
- ........
- 可见,call 0x555555554718 即 call a1 (函数a1()是在 共享库 a1.so中)
复制代码
因为上面的调试是可以“找到”共享库 a1.so 里面的 a1()函数的,所以上面的分析应该是没问题的。但这个与baidu到的资料有较大不同,主要是baidu的资料里面是涉及到了GOT条目的(例如:会有 push操作,将函数对应GOT索引压栈,然后又使用 GOT[2]里面的 _dl_runtime_resolve()函数等),这些似乎在我上面的例子里面没有碰到,但又能得到相应的结果,这是为何?是巧合还是baidu到的资料有问题(我说的是 linux 64位的资料)?
|
|