如何从共享库的文本部分获取偏移量和数据?

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中的地址(就像您使用函数指针一样)。此外,反汇编程序将填充加载地址和符号/指令的绝对地址(相对于某些任意基数),因此您可以减去这些地址。

以上是关于如何从共享库的文本部分获取偏移量和数据?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mongodb 中使用偏移量和限制?

Luxon:获取偏移量和直到的数组(就像我们可以在时刻时区中一样)

获取节点中特定时区的 UTC 偏移量和 DST 信息? [复制]

Mysql 主从复制之半同步复制(基于gtid)

给定元素数组、子列表的偏移量和长度的有效部分缩减

如何从设置中获取数据并发送到此片段