如何从共享库的文本部分获取偏移量和数据?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何从共享库的文本部分获取偏移量和数据?相关的知识,希望对你有一定的参考价值。
我使用-g 386共享选项(使用基本程序集版本)构建OpenSSL-1.0.2n以生成共享库libcrypto.so.1.0.0。
在crypto / aes文件夹中,生成了aes-x86_64.s,它具有不同的全局函数/标签。 aes-x86_64.s中的总行数为2535,不同的地方(或.s文件中的行号)存在各种标签。
328 .globl AES_encrypt
.type AES_encrypt,@function
.align 16
.globl asm_AES_encrypt
.hidden asm_AES_encrypt
asm_AES_encrypt:
334 AES_encrypt:
775 .globl AES_decrypt
.type AES_decrypt,@function
.align 16
.globl asm_AES_decrypt
.hidden asm_AES_decrypt
asm_AES_decrypt:
781 AES_decrypt:
844 .globl private_AES_set_encrypt_key
.type private_AES_set_encrypt_key,@function
.align 16
847 private_AES_set_encrypt_key:
1105 .globl private_AES_set_decrypt_key
.type private_AES_set_decrypt_key,@function
.align 16
1108 private_AES_set_decrypt_key:
1292 .globl AES_cbc_encrypt
.type AES_cbc_encrypt,@function
.align 16
.globl asm_AES_cbc_encrypt
.hidden asm_AES_cbc_encrypt
asm_AES_cbc_encrypt:
1299 AES_cbc_encrypt:
1750 .LAES_Te:
.long 0xa56363c6,0xa56363c6
.long 0x847c7cf8,0x847c7cf8
.long 0x997777ee,0x997777ee
.long 0x8d7b7bf6,0x8d7b7bf6
.long 0x0df2f2ff,0x0df2f2ff
.long 0xbd6b6bd6,0xbd6b6bd6
....
....
2140 .LAES_Td:
.long 0x50a7f451,0x50a7f451
.long 0x5365417e,0x5365417e
.long 0xc3a4171a,0xc3a4171a
.long 0x965e273a,0x965e273a
.long 0xcb6bab3b,0xcb6bab3b
AES_cbc_encrypt是在行号776处声明的全局函数,标签AES_cbc_encrypt在行号781处。
本地标签.LAES_Te和.LAES_Td分别位于第1750和2140行,其中存储了长数据。
我可以通过链接共享库从另一个C程序访问程序集文件的全局标签AES_cbc_encrypt。
//test_glob.c
#include <stdlib.h>
extern void* AES_cbc_encrypt() ;
int main()
{
long *p;
int i;
p=(long *)(&AES_cbc_encrypt);
for(i=0;i<768;i++)
{
printf("p+%d %p %x
",i, p+i,*(p+i));
}
}
gcc test_glob.c -lcryto
./a.out
This gives some random output and later segmentation fault.
必须有一种方法可以从全局标签AES_cbc_encrypt中找到此数据部分(本地标签.LAES_Te和.LAES_Td)的偏移量,以便可以在加密/解密中使用这些数据。
我有以下问题。
1.如何找到从全局标签AES_cbc_encrypt到本地标签.LAES_Te和.LAES_Td的偏移量,以便根据该偏移量我可以从另一个C程序访问数据?
2.还有其他方法可以从C程序访问汇编文件的那些数据吗?
3.有没有办法在内存中找到加载这些数据的位置并访问这些内存位置来访问数据?
我使用的是gcc-5.4 Linux Ubuntu 16.04。任何帮助或链接将受到高度赞赏。提前致谢。
编辑1:
readelf -a aes-x86_64.o产生以下输出。
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 14672 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 16
Section header string table index: 13
Section Headers:
[Nr] Name Type Address Offset Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040 0000000000002e40 0000000000000000 AX 0 0 64
[ 2] .rela.text RELA 0000000000000000 00003808 0000000000000018 0000000000000018 I 14 1 8
[ 3] .data PROGBITS 0000000000000000 00002e80 0000000000000000 0000000000000000 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 00002e80 0000000000000000 0000000000000000 WA 0 0 1
[ 5] .note.GNU-stack PROGBITS 0000000000000000 00002e80 0000000000000000 0000000000000000 0 0 1
[ 6] .debug_line PROGBITS 0000000000000000 00002e80 00000000000005a4 0000000000000000 0 0 1
[ 7] .rela.debug_line RELA 0000000000000000 00003820 0000000000000018 0000000000000018 I 14 6 8
[ 8] .debug_info PROGBITS 0000000000000000 00003424 0000000000000071 0000000000000000 0 0 1
[ 9] .rela.debug_info RELA 0000000000000000 00003838 0000000000000060 0000000000000018 I 14 8 8
[10] .debug_abbrev PROGBITS 0000000000000000 00003495 0000000000000014 0000000000000000 0 0 1
[11] .debug_aranges PROGBITS 0000000000000000 000034b0 0000000000000030 0000000000000000 0 0 16
[12] .rela.debug_arang RELA 0000000000000000 00003898 0000000000000030 0000000000000018 I 14 11 8
[13] .shstrtab STRTAB 0000000000000000 000038c8 0000000000000085 0000000000000000 0 0 1
[14] .symtab SYMTAB 0000000000000000 000034e0 0000000000000228 0000000000000018 15 14 8
[15] .strtab STRTAB 0000000000000000 00003708 00000000000000fb 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
Relocation section '.rela.text' at offset 0x3808 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000fc0 001600000002 R_X86_64_PC32 0000000000000000 OPENSSL_ia32cap_P - 4
Relocation section '.rela.debug_line' at offset 0x3820 contains 1 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000030 000100000001 R_X86_64_64 0000000000000000 .text + 0
Relocation section '.rela.debug_info' at offset 0x3838 contains 4 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000006 000a0000000a R_X86_64_32 0000000000000000 .debug_abbrev + 0
00000000000c 000b0000000a R_X86_64_32 0000000000000000 .debug_line + 0
000000000010 000100000001 R_X86_64_64 0000000000000000 .text + 0
000000000018 000100000001 R_X86_64_64 0000000000000000 .text + 2e40
Relocation section '.rela.debug_aranges' at offset 0x3898 contains 2 entries:
Offset Info Type Sym. Value Sym. Name + Addend
000000000006 00090000000a R_X86_64_32 0000000000000000 .debug_info + 0
000000000010 000100000001 R_X86_64_64 0000000000000000 .text + 0
The decoding of unwind sections for machine type Advanced Micro Devices X86-64 is not currently supported.
Symbol table '.symtab' contains 23 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 SECTION LOCAL DEFAULT 1
2: 0000000000000000 0 SECTION LOCAL DEFAULT 3
3: 0000000000000000 0 SECTION LOCAL DEFAULT 4
4: 0000000000000000 483 FUNC LOCAL DEFAULT 1 _x86_64_AES_encrypt
5: 00000000000001f0 609 FUNC LOCAL DEFAULT 1 _x86_64_AES_encrypt_compa
6: 0000000000000520 465 FUNC LOCAL DEFAULT 1 _x86_64_AES_decrypt
7: 0000000000000700 737 FUNC LOCAL DEFAULT 1 _x86_64_AES_decrypt_compa
8: 0000000000000ae0 649 FUNC LOCAL DEFAULT 1 _x86_64_AES_set_encrypt_k
9: 0000000000000000 0 SECTION LOCAL DEFAULT 8
10: 0000000000000000 0 SECTION LOCAL DEFAULT 10
11: 0000000000000000 0 SECTION LOCAL DEFAULT 6
12: 0000000000000000 0 SECTION LOCAL DEFAULT 11
13: 0000000000000000 0 SECTION LOCAL DEFAULT 5
14: 0000000000000460 177 FUNC GLOBAL DEFAULT 1 AES_encrypt
15: 0000000000000460 0 NOTYPE GLOBAL HIDDEN 1 asm_AES_encrypt
16: 00000000000009f0 184 FUNC GLOBAL DEFAULT 1 AES_decrypt
17: 00000000000009f0 0 NOTYPE GLOBAL HIDDEN 1 asm_AES_decrypt
18: 0000000000000ab0 35 FUNC GLOBAL DEFAULT 1 private_AES_set_encrypt_k
19: 0000000000000d70 541 FUNC GLOBAL DEFAULT 1 private_AES_set_decrypt_k
20: 0000000000000f90 1411 FUNC GLOBAL DEFAULT 1 AES_cbc_encrypt
21: 0000000000000f90 0 NOTYPE GLOBAL HIDDEN 1 asm_AES_cbc_encrypt
22: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND OPENSSL_ia32cap_P
No version information found in this file.
编辑2:
nm aes-x86_64.o产生以下输出。
0000000000000f90 T AES_cbc_encrypt
00000000000009f0 T AES_decrypt
0000000000000460 T AES_encrypt
0000000000000f90 T asm_AES_cbc_encrypt
00000000000009f0 T asm_AES_decrypt
0000000000000460 T asm_AES_encrypt
U OPENSSL_ia32cap_P
0000000000000d70 T private_AES_set_decrypt_key
0000000000000ab0 T private_AES_set_encrypt_key
0000000000000520 t _x86_64_AES_decrypt
0000000000000700 t _x86_64_AES_decrypt_compact
0000000000000000 t _x86_64_AES_encrypt
00000000000001f0 t _x86_64_AES_encrypt_compact
0000000000000ae0 t _x86_64_AES_set_encrypt_key
编辑3:
nm -a给出以下输出
0000000000000f90 T AES_cbc_encrypt
00000000000009f0 T AES_decrypt
0000000000000460 T AES_encrypt
0000000000000f90 T asm_AES_cbc_encrypt
00000000000009f0 T asm_AES_decrypt
0000000000000460 T asm_AES_encrypt
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 N .debug_abbrev
0000000000000000 N .debug_aranges
0000000000000000 N .debug_info
0000000000000000 N .debug_line
0000000000000000 n .note.GNU-stack
U OPENSSL_ia32cap_P
0000000000000d70 T private_AES_set_decrypt_key
0000000000000ab0 T private_AES_set_encrypt_key
0000000000000000 t .text
0000000000000520 t _x86_64_AES_decrypt
0000000000000700 t _x86_64_AES_decrypt_compact
0000000000000000 t _x86_64_AES_encrypt
00000000000001f0 t _x86_64_AES_encrypt_compact
0000000000000ae0 t _x86_64_AES_set_encrypt_key
如果您基于此版本的库对偏移量进行硬编码,则可能会破坏aes-x86_64.s
中具有任何更改的其他版本。
因此,您应该在要访问的数据位置向.globl foo
添加foo:
和.s
标签,并在C中将其声明为extern uint32_t foo[]
。
然后,用于从共享库访问静态数据的正常代码机制将启动。(即,如果需要,从GOT加载地址)。
另外,除非使用-fno-plt
进行编译,否则&AES_cbc_encrypt
将是PLT存根/包装器的地址,而不是库中的实际函数。
如果您只需要它来使用库的特定版本:
然后是的,我认为使用-fno-plt
,获取库中函数的地址将编译/汇编为来自GOT的加载,因此您在动态链接后获得实际地址。 -fno-plt
对于这项工作至关重要。
如果它在另一个部分(可能是.rodata
而不是.text
)可能相当遥远,所以你对768 * 4字节的简单扫描可能找不到该表。
从符号中找到偏移的更好方法是可以在C中使用&
:
使用调试器:单步执行使用数据的函数,并找到它所加载的地址(gdb
的内置反汇编应该有效)。
或者反汇编二进制文件并查看RIP相对负载或表地址的LEA中的little-endian rel32偏移量。 (该偏移量不会在运行时修复)。查看asm源以查找引用所需隐藏符号的指令,然后在反汇编中找到该指令。
这将为您提供从该指令结束到表的字节距离。您可以看到该指令到符号的距离,您可以使用C中的地址(就像您使用函数指针一样)。此外,反汇编程序将填充加载地址和符号/指令的绝对地址(相对于某些任意基数),因此您可以减去这些地址。
以上是关于如何从共享库的文本部分获取偏移量和数据?的主要内容,如果未能解决你的问题,请参考以下文章
Luxon:获取偏移量和直到的数组(就像我们可以在时刻时区中一样)