精华内容
下载资源
问答
  • Linux动态库符号表

    2019-07-14 12:54:53
    https://blog.csdn.net/wuzoujing/article/details/56674000#2为什么要strip
    展开全文
  • Mac系统动态库符号表分析

    千次阅读 2019-04-29 09:07:23
    查看符号表 # 查看 nm *.dylib nm -C *.dylib nm -P *.dylib nm -nm *.dylib -n,按照数字而不是默认的字符排序。 -r,符号按照反序显示 -C,以原代码显示 -P,以简单格式显示每一个符号 符号表分析 符号类型 ...

    查看符号表

    # 系统下的环境变量加载顺序
    /etc/profile 
    /etc/paths 
    ~/.bash_profile 
    ~/.bash_login 
    ~/.profile 
    ~/.bashrc 
    # 生效
    source ~/.bash_profile 
    
    # 查看
    nm  *.dylib
    nm  -C  *.dylib
    nm  -P  *.dylib
    nm  -nm  *.dylib
    nm  *.dylib | grep " T "
    

    -n,按照数字而不是默认的字符排序。
    -r,符号按照反序显示
    -C,以原代码显示
    -P,以简单格式显示每一个符号

    符号表分析

    符号类型 大写代码全局范围,小写代表局部范围

    符号类型代号说明
    AGlobal absolute 符号
    aLocal absolute 符号
    BGlobal bss 符号
    bLocal bss 符号
    DGlobal data 符号
    dLocal data 符号
    f源文件名称符号
    TGlobal text 符号,代码区的符号
    tLocal text 符号
    U未定义符号
    未知符号
    展开全文
  • 如何修改动态库符号表

    千次阅读 2013-10-08 10:30:42
    ELF 文件中代码、连接信息和注释是以节(section)为单位存放的,并存有一个节头(section header)。对每一节,在节头...Unix 系统的可执行文件和动态库文件是以 ELF 格式存放的。为使下面的叙述清晰而没有伎义,先

    ELF 文件中代码、连接信息和注释是以节(section)为单位存放的,并存有一个节头表(section header)。对每一节,在节头表中都有一个表项(节头表项)与之对应,表项记录了该节的一些信息,例如该节在文件中的位置信息和该节的字节长度信息。

    一、ELF 文件和有关术语

    Unix 系统的可执行文件和动态库文件是以 ELF 格式存放的。为使下面的叙述清晰而没有伎义,先简要介绍一下 ELF 文件格式,并约定一些术语。关于ELF文件格式的详细情况请参看有关文献。ELF 文件中代码、连接信息和注释是以节(section)为单位存放的,并存有一个节头表(section header)。对每一节,在节头表中都有一个表项(节头表项)与之对应,表项记录了该节的一些信息,例如该节在文件中的位置信息和该节的字节长度信息。程序运行读入内存时,是以程序段(program segment)为单位读入的。在 ELF文件中有一个程序头表(program header table),每个程序段在程序头表中有一个表项(程序头表项)与之对应,表项记录了该程序段的有关信息,例如该程序段在文件中的位置信息和该程序段的字节长度信息。程序段的内容由若干节组成,节的内容组合在一起连成一片构成程序段的内容。在所有这些节中,有一节的内容由字符串构成,这些字符串是各节的名称,叫节名。下面称这一节为节名表。另有一节,节名为".dynsym",它的内容为符号表,符号表的每一表项记录了一个符号的有关信息,例如该符号对应的代码的地址值。还有一节,节名为".dynstr",它的内容由字符串构成。大多数符号在该节中有一个字符串与之对应,这个字符串是该符号的符号名。而每一函数对应一个符号,函数名即为符号名。下面称被某一函数对应的符号为函数符号。

    ELF 文件开始处的一段叫 ELF 文件头。它记录了程序头表在文件中的偏移、程序头表的表项数目、程序头表每一表项的字节长度、节头表在文件中的偏移、节头表的表项数目、节头表每个表项的字节长度。它还记录了节名表所在的节的索引序号。

    二、动态库符号表修改方法

    修改动态库符号表的方法和步骤如下:

    第一步:

    读取 ELF 文件头,取出

    (1) 程序头表在文件中的偏移,获取程序头表在文件中的位置;
    (2) 程序头表的表项数目和程序头表每一表项的字节长度;
    (3) 节头表在文件中的偏移,获取节头表在文件中的位置;
    (4) 节头表的表项数目和节头表每个表项的字节长度;
    (3) 节名表所在的节的索引序号。

    ELF 文件头在文件中的偏移为零,即起始于 ELF 文件开头的第一字节,它的
    数据结构为:

    #define EI_NIDENT (16)

    typedef uint16_t Elf32_Half;
    typedef uint32_t Elf32_Word;
    typedef uint32_t Elf32_Addr;
    typedef uint32_t Elf32_Off;
    typedef uint16_t Elf32_Section;

    typedef struct
    {
    unsigned char e_ident[EI_NIDENT]; /* Magic number及其他信息 */
    Elf32_Half e_type; /* ELF 文件类型 */
    Elf32_Half e_machine; /* 机器型号 */
    Elf32_Word e_version; /* 版本 */
    Elf32_Addr e_entry; /* 程序入口虚地址 */
    Elf32_Off e_phoff; /* 程序头表在文件中的偏移 */
    Elf32_Off e_shoff; /* 节头表在文件中的偏移 */
    Elf32_Word e_flags; /* 处理器标志 */
    Elf32_Half e_ehsize; /* ELF 文件头长度 */
    Elf32_Half e_phentsize; /* 程序头表每个表项长度 */
    Elf32_Half e_phnum; /* 程序头表的表项总数 */
    Elf32_Half e_shentsize; /* 节头表每个表项长度 */
    Elf32_Half e_shnum; /* 节头表的表项总数 */
    Elf32_Half e_shstrndx; /* 节名表所在的节的表项索引号 */
    } Elf32_Ehdr;

    第二步:

    依据节头表在文件中的偏移和节名表所在的节的索引序号,定出节名表在节头表中对应的表项的文件偏移,即定出该表项在文件中的位置。读取该表项,取出节名表在文件中的偏移和该节在文件中的字节长度。节头表由若干表项组成,每个表项的内容按下面的数据结构来组织:

    typedef struct

    {
    Elf32_Word sh_name; /* 节名索引号 */
    Elf32_Word sh_type; /* 节类型 */
    Elf32_Word sh_flags; /* 节标志 */
    Elf32_Addr sh_addr; /* 执行时该节虚地址 */
    Elf32_Off sh_offset; /* 在文件中的偏移 */
    Elf32_Word sh_size; /* 节长度 */
    Elf32_Word sh_link; /* 到其他节的连接 */
    Elf32_Word sh_info; /* 其他信息 */
    Elf32_Word sh_addralign; /* alignment */
    Elf32_Word sh_entsize; /* 如内容为表,每个表项的长度 */
    } Elf32_Shdr;

    第三步:

    按节名表在文件中的偏移和该节的长度读取节名表,并缓存在一个缓冲区中。

    第四步:

    依据节头表在文件中的偏移、节头表的表项总数、以及节头表每个表项长度搜索节头表。对每个节头表项,读出节名索引号,由节名索引号从上面缓存在缓冲区中节名表得出该节头表项对应的节的名字。如果名字为".dynsym",记录该节的在文件中的偏移和字节长度。名字为 ".dynsym" 的节的内容是符号表,除了记录它在文件中的偏移和字节长度外,还要记下它的每个表项的长度。每个表项即是对一个符号所记录的信息,表项的数据结构为:

    typedef struct

    {
    Elf32_Word st_name; /* 符号名索引号 */
    Elf32_Addr st_value; /* 符号地址值 */
    Elf32_Word st_size; /* 符号对应的代码长度 */
    unsigned char st_info; /* 符号类型和梆定信息 */
    unsigned char st_other; /* 未用,值为 0 */
    Elf32_Section st_shndx; /* 所在节的节索引号 */
    } Elf32_Sym;

    在搜索节头表时,除了找 ".dynsym" 节外,还要找到名字为 ".dynstr" 的节,记下它的在文件中的偏移和字节长度。由该结在文件中的偏移和字节长度读取它的内容,并缓存在一个缓冲区中。

    第五步:

    按第四步中得到的 ..dynsym节的字节长度和符号表的表项的长度算出符号表表项数目,也即符号的数目。然后依据第四步中得到的符号表(即.dynsym节)在文件中的偏移把文件指针打到符号表所在的位置,检索符号表找到要修改的符号。方法是从符号表表项中读出符号名索引号(st_name)的值,这个值即是该表项记录其信息的符号的符号名字符串在 .dynstr 节中的偏移,由这个值在第四步中缓存 .dynstr 节的缓冲区中取出符号名,把符号名和要找的符号的符号名进行比较。

    第六步:

    第五步中找到了要修改的符号,现在可以进行修改了。所谓修改符号就是修改该符号在符号表(.dynsym 节)中表项,因为表项的内容是对该符号的有关信息的记录。hook 时需要关注的是符号地址值(st_value)和符号对应的代码长度(st_size)。可以把符号地址值(st_value)和符号对应的代码长度(st_size)修改为动态库中另一符号的相应的st_value 和 st_size 值。通常修改的是函数符号。如果是函数符号,那么修改后当调用该函数时,实际调用的是上面修改时取其 st_value 和 st_size 值的另一符号所对应的函数。也可以向ELF文件中加入的一段几十字节的 shellcode 或其他代码,修改符号表时把所修改的符号在符号表中的表项的 st_value 值指向这段 shellcode 或其他代码,st_size 的值置为这段代码的字节长度。那么,程序调用被修改的符号所对应的函数时,实际调用的是这段 shellcode 或其他代码。

    三、示例程序

    为对上面所说的进行解释,下面的给出一个示例程序。它打印出 ELF 文件的有关信息,然后通过修改符号表把动态库的函数1 hook 到函数2。这样做以后,如果某程序编译时与该动态库连接了,它调用函数1时,程序运行时实际调用的是函数2。函数2可以是动态库本身就有的函数,也可以是你向 ELF 文件中偷偷加入的一段几十字节的 shellcode。这是向系统置入后门的一个方法,特别是 hook 经常被调用的动态库。测试时做了一个小动态库,它仅有两个函数 haha() 和 huhu():

    ________________________________________________________
    /* haha.c */

    #include

    void haha(void)
    {
    printf(" --- haha ");
    return;
    }
    ________________________________________________________
    /* huhu.c */

    #include

    void huhu(void)
    {
    printf(" --- huhu ");
    return;
    }
    ________________________________________________________

    [wangdb@redhat62 exploit]$ gcc -c -fPIC -O3 haha.c huhu.c
    [wangdb@redhat62 exploit]$ gcc -shared haha.o huhu.o -o libtst.so.1.0
    [wangdb@redhat62 exploit]$ ln -s libtst.so.1.0 libtst.so

    程序 m.c 调用 huhu() 和 haha():
    ________________________________________________________
    /* m.c */
    int main()
    {
    haha();
    huhu();
    return 0;
    }
    ________________________________________________________

    [wangdb@redhat62 exploit]$ gcc m.c -L. -ltst -o ttt
    [wangdb@redhat62 exploit]$ gcc -O3 hook_elf.c -o elf_hook
    [wangdb@redhat62 exploit]$ ./ttt
    --- haha
    --- huhu
    [wangdb@redhat62 exploit]$ ./elf_hook libtst.so huhu haha
    .
    .
    .
    [wangdb@redhat62 exploit]$ ./ttt
    --- haha
    --- haha
    [wangdb@redhat62 exploit]$

    下面是 hook_elf.c 程序:
    ________________________________________________________________________________
    /*
    * C Program File: hook_elf.c ---
    *
    * Description: This program read and print relevant information of ELF
    * File, then hook function fun1 to fun2. After hooking, when
    * some program call function fun1, actually it is fun2 being
    * called.
    * Usage:
    * hook_elf 
    * (Note: when dst_sym == src_sym, ELF file is not changed.)
    *
    * Author: wangdb (wangdb@nsfocus.com)
    */

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include

    #define EI_NIDENT (16)

    typedef uint16_t Elf32_Half;
    typedef uint32_t Elf32_Word;
    typedef uint32_t Elf32_Addr;
    typedef uint32_t Elf32_Off;
    typedef uint16_t Elf32_Section;

    /* 下面的数据结构定义取自 elf.h 头文件 */

    /* The ELF file header. This appears at the start of every ELF file. */

    typedef struct
    {
    unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
    Elf32_Half e_type; /* Object file type */
    Elf32_Half e_machine; /* Architecture */
    Elf32_Word e_version; /* Object file version */
    Elf32_Addr e_entry; /* Entry point virtual address */
    Elf32_Off e_phoff; /* Program header table file offset */
    Elf32_Off e_shoff; /* Section header table file offset */
    Elf32_Word e_flags; /* Processor-specific flags */
    Elf32_Half e_ehsize; /* ELF header size in bytes */
    Elf32_Half e_phentsize; /* Program header table entry size */
    Elf32_Half e_phnum; /* Program header table entry count */
    Elf32_Half e_shentsize; /* Section header table entry size */
    Elf32_Half e_shnum; /* Section header table entry count */
    Elf32_Half e_shstrndx; /* Section header string table index */
    } myElf32_Ehdr;

    /* Program segment header. */

    typedef struct
    {
    Elf32_Word p_type; /* Segment type */
    Elf32_Off p_offset; /* Segment file offset */
    Elf32_Addr p_vaddr; /* Segment virtual address */
    Elf32_Addr p_paddr; /* Segment physical address */
    Elf32_Word p_filesz; /* Segment size in file */
    Elf32_Word p_memsz; /* Segment size in memory */
    Elf32_Word p_flags; /* Segment flags */
    Elf32_Word p_align; /* Segment alignment */
    } myElf32_Phdr;

    /* Section header. */

    typedef struct
    {
    Elf32_Word sh_name; /* Section name (string tbl index) */
    Elf32_Word sh_type; /* Section type */
    Elf32_Word sh_flags; /* Section flags */
    Elf32_Addr sh_addr; /* Section virtual addr at execution */
    Elf32_Off sh_offset; /* Section file offset */
    Elf32_Word sh_size; /* Section size in bytes */
    Elf32_Word sh_link; /* Link to another section */
    Elf32_Word sh_info; /* Additional section information */
    Elf32_Word sh_addralign; /* Section alignment */
    Elf32_Word sh_entsize; /* Entry size if section holds table */
    } myElf32_Shdr;

    /* Symbol table entry. */

    typedef struct
    {
    Elf32_Word st_name; /* Symbol name (string tbl index) */
    Elf32_Addr st_value; /* Symbol value */
    Elf32_Word st_size; /* Symbol size */
    unsigned char st_info; /* Symbol type and binding */
    unsigned char st_other; /* No defined meaning, 0 */
    Elf32_Section st_shndx; /* Section index */
    } myElf32_Sym;

    /* The syminfo section if available contains additional information about
    every dynamic symbol. */

    typedef struct
    {
    Elf32_Half si_boundto; /* Direct bindings, symbol bound to */
    Elf32_Half si_flags; /* Per symbol flags */
    } myElf32_Syminfo;


    /* Main routine */

    int main(int argc, char *argv[])
    {
    myElf32_Ehdr *e_hdr_ptr;
    myElf32_Phdr *p_hdr_ptr;
    myElf32_Shdr *s_hdr_ptr;

    myElf32_Sym *symptr;
    myElf32_Syminfo *HashSymPtr;

    int fd, i;
    unsigned char buf[256];

    unsigned int ProHdrFileOffset;
    unsigned int SecHdrFileOffset;
    unsigned int NamStrSecTblIndex;
    unsigned int ProHdrTblEntrNum;
    unsigned int SecHdrTblEntrNum;
    unsigned int ProHdrTblEntrSize;
    unsigned int SecHdrTblEntrSize;

    unsigned int SecNamStrTblFileOffset = 0;
    char SecNameStrTable[1024];
    unsigned int SecNameIndex = 0;

    unsigned char SymTblEntry[16];

    unsigned int DebugInfoFileOffset = 0;
    int DebugInfoSymTblNum = 0;
    unsigned int DebugInfoStrTblFileOffset = 0;
    char DebugInfoStrTable[4096];
    unsigned int DebugInfoStrTblSize = 0;

    unsigned int SymTblFileOffset = 0;
    int SymTblNum = 0;
    unsigned int SymNamStrTblFileOffset = 0;
    char SymNamStrTable[2048];
    unsigned int SymNamStrTblSize = 0;

    unsigned int HashOffset = 0;
    int HashTblNum = 0;

    unsigned char src_sym[16], dst_sym[16];
    unsigned char tmp_sym_addr[4];
    unsigned char tmp_sym_size[4];
    unsigned int src_sym_tbl = 0, dst_sym_tbl = 0;

    if (argc < 4) {
    fprintf(stderr, "Usage: %s ", argv[0]);
    exit(1);
    }

    if ( (fd = open(argv[1], O_RDONLY)) == -1 ) {
    fprintf(stderr, "Can't open file "%s". ", argv[1]);
    exit(1);
    }

    fprintf(stdout, "Dump content of the ELF file '%s' ", argv[1]);

    fprintf(stdout, "Part I: ELF File Header... ");

    /* 读取 ELF 文件头 */
    if ( read(fd, buf, 52) != 52 ) {
    fprintf(stderr, "read error ");
    close(fd); exit(1);
    }

    e_hdr_ptr = (myElf32_Ehdr *)buf;

    fprintf(stdout, "(Magic number and other info)e_ident: %s ",
    e_hdr_ptr->e_ident);
    fprintf(stdout, "(Object file type)e_type: 0x%04X ",
    e_hdr_ptr->e_type);
    fprintf(stdout, "(Architecture)e_machine: 0x%04X ",
    e_hdr_ptr->e_machine);
    fprintf(stdout, "(Object file version)e_version: 0x%08X ",
    e_hdr_ptr->e_version);
    fprintf(stdout, "(Entry point virtual address)e_entry: 0x%08X ",
    e_hdr_ptr->e_entry);
    fprintf(stdout, "(Program header table file offset)e_phoff: 0x%08X ",
    e_hdr_ptr->e_phoff);
    fprintf(stdout, "(Section header table file offset)e_shoff: 0x%08X ",
    e_hdr_ptr->e_shoff);
    fprintf(stdout, "(Processor-specific flags)e_flags: 0x%08X ",
    e_hdr_ptr->e_flags);
    fprintf(stdout, "(ELF header size in bytes)e_ehsize: 0x%04X ",
    e_hdr_ptr->e_ehsize);
    fprintf(stdout, "(Program header table entry size)e_phentsize: 0x%04X ",
    e_hdr_ptr->e_phentsize);
    fprintf(stdout, "(Program header table entry count)e_phnum: 0x%04X ",
    e_hdr_ptr->e_phnum);
    fprintf(stdout, "(Section header table entry size)e_shentsize: 0x%04X ",
    e_hdr_ptr->e_shentsize);
    fprintf(stdout, "(Section header table entry count)e_shnum: 0x%04X ",
    e_hdr_ptr->e_shnum);
    fprintf(stdout, "(Section header string table index)e_shstrndx: 0x%04X ",
    e_hdr_ptr->e_shstrndx);

    /* 记下程序头表在文件中的偏移、节头表在文件中的偏移、
    节名表所在的节的索引序号、程序头表表项字节长度、程序头表表项数目、
    节头表表项字节长度、节头表表项数目。*/
    ProHdrFileOffset = (unsigned int)e_hdr_ptr->e_phoff;
    SecHdrFileOffset = (unsigned int)e_hdr_ptr->e_shoff;
    NamStrSecTblIndex = (unsigned int)e_hdr_ptr->e_shstrndx;
    ProHdrTblEntrNum = (unsigned int)e_hdr_ptr->e_phnum;
    SecHdrTblEntrNum = (unsigned int)e_hdr_ptr->e_shnum;
    ProHdrTblEntrSize = (unsigned int)e_hdr_ptr->e_phentsize;
    SecHdrTblEntrSize = (unsigned int)e_hdr_ptr->e_shentsize;

    fprintf(stdout, "Part II: Program Header Table... ");

    if ( lseek(fd, (off_t)ProHdrFileOffset, SEEK_SET) != ProHdrFileOffset ) {
    fprintf(stderr, "lseek to program header error. ");
    close(fd); exit(1);
    }

    for (i = 0; i < (int)ProHdrTblEntrNum; i++) {
    if ( read(fd, buf, (size_t)ProHdrTblEntrSize) !=
    (ssize_t)ProHdrTblEntrSize ) {
    fprintf(stderr, "read error ");
    close(fd); exit(1);
    }
    fprintf(stdout, "Program Header Entry for Segment %d: ", i + 1);
    p_hdr_ptr = (myElf32_Phdr *)buf;
    fprintf(stdout, "(Segment type)p_type: 0x%08X ",
    p_hdr_ptr->p_type);
    fprintf(stdout, "(Segment flags)p_flags: 0x%08X ",
    p_hdr_ptr->p_flags);
    fprintf(stdout, "(Segment file offset)p_offset: 0x%08X ",
    p_hdr_ptr->p_offset);
    fprintf(stdout, "(Segment virtual address)p_vaddr: 0x%08X ",
    p_hdr_ptr->p_vaddr);
    fprintf(stdout, "(Segment physical address)p_paddr: 0x%08X ",
    p_hdr_ptr->p_paddr);
    fprintf(stdout, "(Segment size in file)p_filesz: 0x%08X ",
    p_hdr_ptr->p_filesz);
    fprintf(stdout, "(Segment size in memory)p_memsz: 0x%08X ",
    p_hdr_ptr->p_memsz);
    fprintf(stdout, "(Segment alignment)p_align: 0x%08X ",
    p_hdr_ptr->p_align);
    }

    fprintf(stdout, "Part III: Section Header Table... ");

    /* 定出节名表所在的节在节头表中对应的表项的文件偏移。*/
    SecNamStrTblFileOffset = SecHdrFileOffset + NamStrSecTblIndex * 40;
    if ( lseek(fd, (off_t)SecNamStrTblFileOffset, SEEK_SET) !=
    SecNamStrTblFileOffset || SecNamStrTblFileOffset == 0 ) {
    fprintf(stderr,
    "lseek to Section Table Entry for Section Name String Table error. ");
    close(fd); exit(1);
    }
    if ( read(fd, buf, (size_t)SecHdrTblEntrSize) != (ssize_t)SecHdrTblEntrSize ) {
    fprintf(stderr, "read error ");
    close(fd); exit(1);
    }
    s_hdr_ptr = (myElf32_Shdr *)buf;
    SecNamStrTblFileOffset = (unsigned int)s_hdr_ptr->sh_offset;

    /* 读取节名表,并缓存在一个缓冲区中。*/
    if ( lseek(fd, (off_t)SecNamStrTblFileOffset, SEEK_SET) !=
    SecNamStrTblFileOffset || SecNamStrTblFileOffset == 0 ) {
    fprintf(stderr, "lseek to Section Name String Table error. ");
    close(fd); exit(1);
    }
    if ( read(fd, SecNameStrTable, (size_t)s_hdr_ptr->sh_size) !=
    (ssize_t)s_hdr_ptr->sh_size ) {
    fprintf(stderr, "read error ");
    close(fd); exit(1);
    }

    if ( lseek(fd, (off_t)SecHdrFileOffset, SEEK_SET) != SecHdrFileOffset ||
    SecHdrFileOffset == 0 ) {
    fprintf(stderr, "lseek to section header error. ");
    close(fd); exit(1);
    }

    /* 记录符号表(即.dynsym节)在文件中的偏移,由它的字节长度和每个表项的
    长度算出符号表的表项数目。同时记下.dynstr节在文件中的偏移和字节长度。*/
    for (i = 0; i < (int)SecHdrTblEntrNum; i++) {
    if ( read(fd, buf, (size_t)SecHdrTblEntrSize) !=
    (ssize_t)SecHdrTblEntrSize ) {
    fprintf(stderr, "read error ");
    close(fd); exit(1);
    }
    s_hdr_ptr = (myElf32_Shdr *)buf;
    /*if ( s_hdr_ptr->sh_type == 0x3 && s_hdr_ptr->sh_name == 0x11 ) {
    SecNamStrTblFileOffset = (unsigned int)s_hdr_ptr->sh_offset;
    }*/
    if ( strcmp(SecNameStrTable + s_hdr_ptr->sh_name, ".symtab") == 0 ) {
    DebugInfoFileOffset = (unsigned int)s_hdr_ptr->sh_offset;
    DebugInfoSymTblNum = (int)((s_hdr_ptr->sh_size)/(s_hdr_ptr->sh_entsize));
    }
    if ( strcmp(SecNameStrTable + s_hdr_ptr->sh_name, ".strtab") == 0 ) {
    DebugInfoStrTblFileOffset = (unsigned int)s_hdr_ptr->sh_offset;
    DebugInfoStrTblSize = (unsigned int)s_hdr_ptr->sh_size;
    }
    if ( strcmp(SecNameStrTable + s_hdr_ptr->sh_name, ".dynsym") == 0 ) {
    SymTblFileOffset = (unsigned int)s_hdr_ptr->sh_offset;
    SymTblNum = (int)((s_hdr_ptr->sh_size)/(s_hdr_ptr->sh_entsize));
    }
    if ( strcmp(SecNameStrTable + s_hdr_ptr->sh_name, ".dynstr") == 0 ) {
    SymNamStrTblFileOffset = (unsigned int)s_hdr_ptr->sh_offset;
    SymNamStrTblSize = (unsigned int)s_hdr_ptr->sh_size;
    }
    if ( strcmp(SecNameStrTable + s_hdr_ptr->sh_name, ".hash") == 0 ) {
    HashOffset = (unsigned int)s_hdr_ptr->sh_offset;
    HashTblNum = (int)((s_hdr_ptr->sh_size)/(s_hdr_ptr->sh_entsize));
    }
    }

    if ( lseek(fd, (off_t)SecHdrFileOffset, SEEK_SET) != SecHdrFileOffset ) {
    fprintf(stderr, "lseek to section header error. ");
    close(fd); exit(1);
    }

    for (i = 0; i < (int)SecHdrTblEntrNum; i++) {
    if ( read(fd, buf, (size_t)SecHdrTblEntrSize) !=
    (ssize_t)SecHdrTblEntrSize ) {
    fprintf(stderr, "read error ");
    close(fd); exit(1);
    }
    s_hdr_ptr = (myElf32_Shdr *)buf;
    fprintf(stdout, "Section %d: ", i);
    SecNameIndex = (unsigned int)s_hdr_ptr->sh_name;
    fprintf(stdout, "(Section name (string tbl index))sh_name: 0x%08X -> %s ",
    s_hdr_ptr->sh_name, SecNameStrTable + SecNameIndex);
    fprintf(stdout, "(Section type)sh_type: 0x%08X ",
    s_hdr_ptr->sh_type);
    fprintf(stdout, "(Section flags)sh_flags: 0x%08X ",
    s_hdr_ptr->sh_flags);
    fprintf(stdout, "(Section virtual addr at execution)sh_addr: 0x%08X ",
    s_hdr_ptr->sh_addr);
    fprintf(stdout, "(Section file offset)sh_offset: 0x%08X ",
    s_hdr_ptr->sh_offset);
    fprintf(stdout, "(Section size in bytes)sh_size: 0x%08X ",
    s_hdr_ptr->sh_size);
    fprintf(stdout, "(Link to another section)sh_link: 0x%08X ",
    s_hdr_ptr->sh_link);
    fprintf(stdout, "(Additional section information)sh_info: 0x%08X ",
    s_hdr_ptr->sh_info);
    fprintf(stdout, "(Section alignment)sh_addralign: 0x%08X ",
    s_hdr_ptr->sh_addralign);
    fprintf(stdout, "(Entry size if section holds table)sh_entsize: 0x%08X ",
    s_hdr_ptr->sh_entsize);
    }

    fprintf(stdout,
    "************************************************************************ ");

    if ( lseek(fd, (off_t)DebugInfoStrTblFileOffset, SEEK_SET) !=
    DebugInfoStrTblFileOffset || DebugInfoStrTblFileOffset == 0 ) {
    fprintf(stderr, "lseek to Debug Info String Table error. ");
    goto next;
    }
    read(fd, DebugInfoStrTable, (size_t)(DebugInfoStrTblSize + 1));

    if ( lseek(fd, (off_t)DebugInfoFileOffset, SEEK_SET) !=
    DebugInfoFileOffset || DebugInfoFileOffset == 0 ) {
    fprintf(stderr, "lseek to Debug Info Symbol Table error. ");
    goto next;
    }
    for (i = 0; i < DebugInfoSymTblNum; i++) {
    read(fd, SymTblEntry, (size_t)16);
    symptr = (myElf32_Sym *)SymTblEntry;
    fprintf(stdout, "Debug Infomation -> Symbol ID: %d ", i);
    fprintf(stdout, "Symbol_index_and_name: 0x%08X -> %s ",
    symptr->st_name, DebugInfoStrTable + symptr->st_name);
    fprintf(stdout, "Symbol_value: 0x%08X ", symptr->st_value);
    fprintf(stdout, "Symbol_size: 0x%08X ", symptr->st_size);
    fprintf(stdout, "Symbol_type_and_binding: 0x%02X ", symptr->st_info);
    fprintf(stdout, "Section_index: 0x%04X ", symptr->st_shndx);
    fprintf(stdout,
    "-------------------------------------------------------- ");
    }

    fprintf(stdout,
    "************************************************************************ ");

    next:

    /* 读取 .dynstr 节的内容,并缓存在一个缓冲区中。*/
    if ( lseek(fd, (off_t)SymNamStrTblFileOffset, SEEK_SET) !=
    SymNamStrTblFileOffset || SymNamStrTblFileOffset == 0 ) {
    fprintf(stderr, "lseek to Dynamical symbol name string error. ");
    close(fd); exit(1);
    }
    read(fd, SymNamStrTable, (size_t)(SymNamStrTblSize + 1));
    if ( lseek(fd, (off_t)SymTblFileOffset, SEEK_SET) != SymTblFileOffset ||
    SymTblFileOffset == 0 ) {
    fprintf(stderr, "lseek to Dynamical symbol Table error. ");
    close(fd); exit(1);
    }
    for (i = 0; i < SymTblNum; i++) {
    read(fd, SymTblEntry, (size_t)16);
    symptr = (myElf32_Sym *)SymTblEntry;
    fprintf(stdout, "Symbol ID: %d ", i);
    fprintf(stdout, "Symbol_index_and_name: 0x%08X -> %s ",
    symptr->st_name, SymNamStrTable + symptr->st_name);
    fprintf(stdout, "Symbol_value: 0x%08X ", symptr->st_value);
    fprintf(stdout, "Symbol_size: 0x%08X ", symptr->st_size);
    fprintf(stdout, "Symbol_type_and_binding: 0x%02X ", symptr->st_info);
    fprintf(stdout, "Section_index: 0x%04X ", symptr->st_shndx);
    fprintf(stdout,
    "-------------------------------------------------------- ");
    }

    fprintf(stdout,
    "************************************************************************ ");

    if ( lseek(fd, (off_t)HashOffset, SEEK_SET) != HashOffset ||
    HashOffset == 0 ) {
    fprintf(stderr, "lseek to hash table error. ");
    close(fd); exit(-1);
    }
    for (i = 0; i < HashTblNum; i++) {
    fprintf(stdout, "Hash Table ID: %d ", i);
    read(fd, SymTblEntry, (size_t)4);
    HashSymPtr = (myElf32_Syminfo *)SymTblEntry;
    fprintf(stdout, "Direct_bindings, symbol_bound_to: 0x%04X ",
    HashSymPtr->si_boundto);
    fprintf(stdout, "Per_symbol_flags: 0x%04X ", HashSymPtr->si_flags);
    fprintf(stdout,
    "-------------------------------------------------------- ");
    }

    close(fd); /* End of Printing */

    /* Change symbol value, hook it */

    if ( (fd = open(argv[1], O_RDWR)) < 0 ) {
    fprintf(stderr, "Can't open object file '%s'. ", argv[1]);
    exit(-1);
    }

    /* 检索符号表搜索要修改的符号。*/
    if ( lseek(fd, (off_t)SymTblFileOffset, SEEK_SET) != SymTblFileOffset ) {
    fprintf(stderr, "lseek error. ");
    close(fd); exit(-1);
    }

    for (i = 0; i < SymTblNum; i++) {
    read(fd, SymTblEntry, (size_t)16);
    symptr = (myElf32_Sym *)SymTblEntry;
    if ( strcmp(argv[2], SymNamStrTable + symptr->st_name) == 0 ) {
    memcpy(dst_sym, SymTblEntry, 16);
    dst_sym_tbl = (unsigned int)lseek(fd, (off_t)0, SEEK_CUR) - 16;
    }
    if ( strcmp(argv[3], SymNamStrTable + symptr->st_name) == 0 ) {
    memcpy(src_sym, SymTblEntry, 16);
    src_sym_tbl = (unsigned int)lseek(fd, (off_t)0, SEEK_CUR) - 16;
    }
    }

    /* 修改符号表中要修改的符号所对应的表项的 st_value 和 st_size 值。*/
    symptr = (myElf32_Sym *)src_sym;
    memcpy(tmp_sym_addr, &symptr->st_value, 4);
    memcpy(tmp_sym_size, &symptr->st_size, 4);
    symptr = (myElf32_Sym *)dst_sym;
    memcpy(&symptr->st_value, tmp_sym_addr, 4);
    memcpy(&symptr->st_size, tmp_sym_size, 4);

    if ( dst_sym_tbl == 0 || src_sym_tbl == 0 ||
    lseek(fd, (off_t)dst_sym_tbl, SEEK_SET) != dst_sym_tbl ) {
    fprintf(stderr, "lseek error. ");
    close(fd); exit(-1);
    }
    if ( write(fd, dst_sym, (size_t)16) != (ssize_t)16 ) {
    fprintf(stderr, "write error ");
    close(fd); exit(-1);
    }

    close(fd);
    return 0;
    }

    /* EOF */

    展开全文
  • android编译动态链接时,缺省的编译选项下默认所有的符号表都会导出, 这导致别人很容易通过符号表获取动态库里的相关信息。 通过增加-fvisibility=hidden选项有时候能影藏部分符号表,如何根本上解决这个问题呢,...

    android编译动态链接库时,缺省的编译选项下默认所有的符号表都会导出, 这导致别人很容易通过符号表获取动态库里的相关信息。

    通过增加-fvisibility=hidden选项有时候能影藏部分符号表,如何根本上解决这个问题呢,本文介绍的“jni加密器”就能解决此功能。

    1.安装jni加密器:sec.apk

    下载链接:http://apk.91.com/Soft/Android/com.sn.sec-2.html

    2. 把so拷贝到手机上, 用jni加密器打开它,如下图:

    点击打开链接

    3. 设置过滤条件

    点击设置按钮, 对过滤条件进行设置

    例如要对所有包含x264的符号进行加密,在”包含“里输入x264,如果需要保留所有包含java或者com的符号表, 则在”不包含“项填java  com。


    4.加密

    加密后符号表如下图:



    现在所有包含x264的符号全部影藏起来了


    展开全文
  • GCC制作动态库导出符号表

    千次阅读 2017-08-09 13:48:57
    GCC制作动态链接库时默认会将所有的函数及变量都导出到符号表,正常情况下...为了避免这种情况,就需要定制符号表,即仅仅将需要提供给其他模块使用的接口或变量导出到符号表,本文就是介绍制作这样的动态库的方法。
  • 动态库、可执行文件符号表分析

    千次阅读 2020-04-20 12:21:19
    分析最后的可执行文件和动态库文件的符号表; 1.1 第一个C文件:basic.c 这个C文件只定义并实现了四个不同形参的函数、五个静态变量、一个全局变量。由于只关心符号表或者其他二进制内容,因此不具体实现特定功能....
  • 动态链接库符号表问题

    千次阅读 2020-02-25 17:37:21
    当链接动态库时出现下面这样的错误时,一般是动态库生成的编译选项问题 found local symbol '__bss_start' in global part of symbol table found local symbol '_edata' in global part of symbol table found ...
  • Linux动态库(.so)符号表

    万次阅读 2017-02-24 10:22:59
    动态库(.so)符号表 最近编译libbinder.so发现system/lib/libbinder.so只有358K,但单独编译生成的obj/SHARED_LIBRARIES/libbinder_intermediates/LINKED/libbinder.so有5M多,原因是前者做了strip命令操作。 1...
  • 本文分析了linux环境下动态库和静态库导出相同符号所导致的符号冲突问题,通过构建问题模型并进行情景分析,提出解决方案,最后验证解决方案。
  • Android NDK隐藏jni动态库的内部符号表

    千次阅读 2018-06-26 10:14:14
    写过win32程序的朋友对dll导出函数名都很熟悉,大家都可以通过.def...当编译动态链接库时,缺省的编译选项下默认所有的符号表都会导出。以android-ndk下的san-angeles例子为例,用ndk编译之后生成的jni动态库导出的...
  • Linux动态库 同名符号,可以参考一下。
  • linux静态库 动态库符号 符号恢复

    千次阅读 2018-04-17 00:45:08
    前言 最近遇到了一题去除符号的题目,需要进行符号修复。为此学习了一波,顺便补了补其它的一下知识。 准备知识 ...生成动态库 gcc -shared -o libxxx.so.1.0 hello.o 生成静态库 ar cqs l...
  • 浅谈动态库符号的私有化与全局化

    千次阅读 2013-05-12 01:13:57
    描述了这样一个问题:动态库若想使用自己的符号,不受可执行程序(或其他动态库的影响),可以使用-Wl,-Bsymbolic链接参数或version_script来让动态库的符号自我解决,而不必通过全局符号表来动态解决。 之前的文章...
  • linux命令之查看动态库符号-nm

    千次阅读 2017-11-22 16:46:36
    在调用动态库的时候,由于动态库接口修改或者版本不匹配出现调用动态库找不到函数接口符号的情况。 原因可能有如下几种: 1.由于c++动态库编译没有加extern c导致函数编译时加了c++的前缀的; 2.系统中有多个库,...
  • Linux动态链接(5)动态库符号搜索顺序

    千次阅读 2016-08-03 21:25:32
    这里的动态搜索是指通过dlopen+dlsym来搜索动态库符号的过程,而静态搜索则是指程序在运行的过程中的惰性链接实现。这里其实又是一个比较边界的问题,但是也是可能存在的,另外这些问题可以促使感兴趣的同学看一下...
  • 符号表分离程序或动态库, 如何用GDB调试 五竹 1 Debugging Information in Separate Files GDB支持用户将程序调试信息放在一个独立的文件里,而不是和可执行程序在一个文件

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 162,421
精华内容 64,968
关键字:

动态库符号表