日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何修改动态库符号表

發(fā)布時間:2025/3/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何修改动态库符号表 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

如何修改動態(tài)庫符號表


??? 一、ELF 文件和有關術語

Unix 系統(tǒng)的可執(zhí)行文件和動態(tài)庫文件是以 ELF 格式存放的。為使下面的敘述
清晰而沒有伎義,先簡要介紹一下 ELF 文件格式,并約定一些術語。關于ELF
文件格式的詳細情況請參看有關文獻。

ELF 文件中代碼、連接信息和注釋是以節(jié)(section)為單位存放的,并存有一
個節(jié)頭表(section header)。對每一節(jié),在節(jié)頭表中都有一個表項(節(jié)頭表項)
與之對應,表項記錄了該節(jié)的一些信息,例如該節(jié)在文件中的位置信息和該節(jié)
的字節(jié)長度信息。

程序運行讀入內(nèi)存時,是以程序段(program segment)為單位讀入的。在 ELF
文件中有一個程序頭表(program header table),每個程序段在程序頭表中有
一個表項(程序頭表項)與之對應,表項記錄了該程序段的有關信息,例如該程
序段在文件中的位置信息和該程序段的字節(jié)長度信息。程序段的內(nèi)容由若干節(jié)
組成,節(jié)的內(nèi)容組合在一起連成一片構成程序段的內(nèi)容。

在所有這些節(jié)中,有一節(jié)的內(nèi)容由字符串構成,這些字符串是各節(jié)的名稱,叫
節(jié)名。下面稱這一節(jié)為節(jié)名表。另有一節(jié),節(jié)名為".dynsym",它的內(nèi)容為符
號表,符號表的每一表項記錄了一個符號的有關信息,例如該符號對應的代碼
的地址值。還有一節(jié),節(jié)名為".dynstr",它的內(nèi)容由字符串構成。大多數(shù)符
號在該節(jié)中有一個字符串與之對應,這個字符串是該符號的符號名。而每一函
數(shù)對應一個符號,函數(shù)名即為符號名。下面稱被某一函數(shù)對應的符號為函數(shù)符
號。

ELF 文件開始處的一段叫 ELF 文件頭。它記錄了程序頭表在文件中的偏移、
程序頭表的表項數(shù)目、程序頭表每一表項的字節(jié)長度、節(jié)頭表在文件中的偏移、
節(jié)頭表的表項數(shù)目、節(jié)頭表每個表項的字節(jié)長度。它還記錄了節(jié)名表所在的節(jié)
的索引序號。

二、動態(tài)庫符號表修改方法

修改動態(tài)庫符號表的方法和步驟如下:

第一步:

讀取 ELF 文件頭,取出

??? (1) 程序頭表在文件中的偏移,獲取程序頭表在文件中的位置;
??? (2) 程序頭表的表項數(shù)目和程序頭表每一表項的字節(jié)長度;
??? (3) 節(jié)頭表在文件中的偏移,獲取節(jié)頭表在文件中的位置;
??? (4) 節(jié)頭表的表項數(shù)目和節(jié)頭表每個表項的字節(jié)長度;
??? (3) 節(jié)名表所在的節(jié)的索引序號。

ELF 文件頭在文件中的偏移為零,即起始于 ELF 文件開頭的第一字節(jié),它的
數(shù)據(jù)結構為:

#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;???????????? /* 節(jié)頭表在文件中的偏移 */
?? Elf32_Word??? e_flags;???????????? /* 處理器標志 */
?? Elf32_Half??? e_ehsize;??????????? /* ELF 文件頭長度 */
?? Elf32_Half??? e_phentsize;???????? /* 程序頭表每個表項長度 */
?? Elf32_Half??? e_phnum;???????????? /* 程序頭表的表項總數(shù) */
?? Elf32_Half??? e_shentsize;???????? /* 節(jié)頭表每個表項長度 */
?? Elf32_Half??? e_shnum;???????????? /* 節(jié)頭表的表項總數(shù) */
?? Elf32_Half??? e_shstrndx;????????? /* 節(jié)名表所在的節(jié)的表項索引號 */
} Elf32_Ehdr;

第二步:

依據(jù)節(jié)頭表在文件中的偏移和節(jié)名表所在的節(jié)的索引序號,定出節(jié)名表在節(jié)頭
表中對應的表項的文件偏移,即定出該表項在文件中的位置。讀取該表項,取
出節(jié)名表在文件中的偏移和該節(jié)在文件中的字節(jié)長度。節(jié)頭表由若干表項組成,
每個表項的內(nèi)容按下面的數(shù)據(jù)結構來組織:

typedef struct
{
?? Elf32_Word??? sh_name;???????????? /* 節(jié)名索引號 */
?? Elf32_Word??? sh_type;???????????? /* 節(jié)類型 */
?? Elf32_Word??? sh_flags;??????????? /* 節(jié)標志 */
?? Elf32_Addr??? sh_addr;???????????? /* 執(zhí)行時該節(jié)虛地址 */
?? Elf32_Off???? sh_offset;?????????? /* 在文件中的偏移 */
?? Elf32_Word??? sh_size;???????????? /* 節(jié)長度 */
?? Elf32_Word??? sh_link;???????????? /* 到其他節(jié)的連接 */
?? Elf32_Word??? sh_info;???????????? /* 其他信息 */
?? Elf32_Word??? sh_addralign;??????? /* alignment */
?? Elf32_Word??? sh_entsize;????????? /* 如內(nèi)容為表,每個表項的長度 */
} Elf32_Shdr;

第三步:

按節(jié)名表在文件中的偏移和該節(jié)的長度讀取節(jié)名表,并緩存在一個緩沖區(qū)中。

第四步:

依據(jù)節(jié)頭表在文件中的偏移、節(jié)頭表的表項總數(shù)、以及節(jié)頭表每個表項長度搜
索節(jié)頭表。對每個節(jié)頭表項,讀出節(jié)名索引號,由節(jié)名索引號從上面緩存在緩
沖區(qū)中節(jié)名表得出該節(jié)頭表項對應的節(jié)的名字。如果名字為".dynsym",記錄
該節(jié)的在文件中的偏移和字節(jié)長度。名字為 ".dynsym" 的節(jié)的內(nèi)容是符號表,
除了記錄它在文件中的偏移和字節(jié)長度外,還要記下它的每個表項的長度。每
個表項即是對一個符號所記錄的信息,表項的數(shù)據(jù)結構為:

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;????? /* 所在節(jié)的節(jié)索引號 */
} Elf32_Sym;

在搜索節(jié)頭表時,除了找 ".dynsym" 節(jié)外,還要找到名字為 ".dynstr" 的節(jié),
記下它的在文件中的偏移和字節(jié)長度。由該結在文件中的偏移和字節(jié)長度讀取
它的內(nèi)容,并緩存在一個緩沖區(qū)中。

第五步:

按第四步中得到的 ..dynsym節(jié)的字節(jié)長度和符號表的表項的長度算出符號表表
項數(shù)目,也即符號的數(shù)目。然后依據(jù)第四步中得到的符號表(即.dynsym節(jié))在
文件中的偏移把文件指針打到符號表所在的位置,檢索符號表找到要修改的符
號。方法是從符號表表項中讀出符號名索引號(st_name)的值,這個值即是該
表項記錄其信息的符號的符號名字符串在 .dynstr 節(jié)中的偏移,由這個值在
第四步中緩存 .dynstr 節(jié)的緩沖區(qū)中取出符號名,把符號名和要找的符號的
符號名進行比較。

第六步:

第五步中找到了要修改的符號,現(xiàn)在可以進行修改了。所謂修改符號就是修改
該符號在符號表(.dynsym 節(jié))中表項,因為表項的內(nèi)容是對該符號的有關信
息的記錄。hook 時需要關注的是符號地址值(st_value)和符號對應的代碼長
度(st_size)。可以把符號地址值(st_value)和符號對應的代碼長度(st_size)
修改為動態(tài)庫中另一符號的相應的 st_value 和 st_size 值。通常修改的是
函數(shù)符號。如果是函數(shù)符號,那么修改后當調(diào)用該函數(shù)時,實際調(diào)用的是上面
修改時取其 st_value 和 st_size 值的另一符號所對應的函數(shù)。也可以向ELF
文件中加入的一段幾十字節(jié)的 shellcode 或其他代碼,修改符號表時把所修
改的符號在符號表中的表項的 st_value 值指向這段 shellcode 或其他代碼,
st_size 的值置為這段代碼的字節(jié)長度。那么,程序調(diào)用被修改的符號所對應
的函數(shù)時,實際調(diào)用的是這段 shellcode 或其他代碼。

三、示例程序

為對上面所說的進行解釋,下面的給出一個示例程序。它打印出 ELF 文件的
有關信息,然后通過修改符號表把動態(tài)庫的函數(shù)1 hook 到函數(shù)2。這樣做以后,
如果某程序編譯時與該動態(tài)庫連接了,它調(diào)用函數(shù)1時,程序運行時實際調(diào)用
的是函數(shù)2。函數(shù)2可以是動態(tài)庫本身就有的函數(shù),也可以是你向 ELF 文件中
偷偷加入的一段幾十字節(jié)的 shellcode。這是向系統(tǒng)置入后門的一個方法,特
別是 hook 經(jīng)常被調(diào)用的動態(tài)庫。

測試時做了一個小動態(tài)庫,它僅有兩個函數(shù) haha() 和 huhu():
________________________________________________________
/* haha.c */

#include <stdio.h>

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

#include <stdio.h>

void huhu(void)
{
?? printf(" --- huhu/n");
?? 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 調(diào)用 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 <lib***.so> <dst_sym> <src_sym>
*???????? (Note: when dst_sym == src_sym, ELF file is not changed.)
*
* Author: wangdb (wangdb@nsfocus.com)
*/

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>

#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;

/* 下面的數(shù)據(jù)結構定義取自 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 <object_file> <dst_sym> <src_sym>/n",

argv[0]);
????? exit(1);
?? }

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

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

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

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

?? e_hdr_ptr = (myElf32_Ehdr *)buf;

?? fprintf(stdout, "(Magic number and other info)e_ident: %s/n",
??????????????????? e_hdr_ptr->e_ident);
?? fprintf(stdout, "(Object file type)e_type: 0x%04X/n",
??????????????????? e_hdr_ptr->e_type);
?? fprintf(stdout, "(Architecture)e_machine: 0x%04X/n",
??????????????????? e_hdr_ptr->e_machine);
?? fprintf(stdout, "(Object file version)e_version: 0x%08X/n",
??????????????????? e_hdr_ptr->e_version);
?? fprintf(stdout, "(Entry point virtual address)e_entry: 0x%08X/n",
??????????????????? e_hdr_ptr->e_entry);
?? fprintf(stdout, "(Program header table file offset)e_phoff: 0x%

08X/n",
??????????????????? e_hdr_ptr->e_phoff);
?? fprintf(stdout, "(Section header table file offset)e_shoff: 0x%

08X/n",
??????????????????? e_hdr_ptr->e_shoff);
?? fprintf(stdout, "(Processor-specific flags)e_flags: 0x%08X/n",
??????????????????? e_hdr_ptr->e_flags);
?? fprintf(stdout, "(ELF header size in bytes)e_ehsize: 0x%04X/n",
??????????????????? e_hdr_ptr->e_ehsize);
?? fprintf(stdout, "(Program header table entry size)e_phentsize: 0x%

04X/n",
??????????????????? e_hdr_ptr->e_phentsize);
?? fprintf(stdout, "(Program header table entry count)e_phnum: 0x%

04X/n",
??????????????????? e_hdr_ptr->e_phnum);
?? fprintf(stdout, "(Section header table entry size)e_shentsize: 0x%

04X/n",
??????????????????? e_hdr_ptr->e_shentsize);
?? fprintf(stdout, "(Section header table entry count)e_shnum: 0x%

04X/n",
??????????????????? e_hdr_ptr->e_shnum);
?? fprintf(stdout, "(Section header string table index)e_shstrndx: 0x%

04X/n",
??????????????????? e_hdr_ptr->e_shstrndx);

?? /* 記下程序頭表在文件中的偏移、節(jié)頭表在文件中的偏移、
????? 節(jié)名表所在的節(jié)的索引序號、程序頭表表項字節(jié)長度、程序頭表表項數(shù)目


????? 節(jié)頭表表項字節(jié)長度、節(jié)頭表表項數(shù)目。*/
?? 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.../n");

?? if ( lseek(fd, (off_t)ProHdrFileOffset, SEEK_SET) !=

ProHdrFileOffset ) {
????? fprintf(stderr, "lseek to program header error./n");
????? 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/n");
???????? close(fd); exit(1);
????? }
????? fprintf(stdout, "Program Header Entry for Segment %d:/n", i + 1);
????? p_hdr_ptr = (myElf32_Phdr *)buf;
????? fprintf(stdout, "(Segment type)p_type: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_type);
????? fprintf(stdout, "(Segment flags)p_flags: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_flags);
????? fprintf(stdout, "(Segment file offset)p_offset: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_offset);
????? fprintf(stdout, "(Segment virtual address)p_vaddr: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_vaddr);
????? fprintf(stdout, "(Segment physical address)p_paddr: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_paddr);
????? fprintf(stdout, "(Segment size in file)p_filesz: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_filesz);
????? fprintf(stdout, "(Segment size in memory)p_memsz: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_memsz);
????? fprintf(stdout, "(Segment alignment)p_align: 0x%08X/n",
?????????????????????? p_hdr_ptr->p_align);
?? }

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

?? /* 定出節(jié)名表所在的節(jié)在節(jié)頭表中對應的表項的文件偏移。*/
?? 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./n");
????? close(fd); exit(1);
?? }
?? if ( read(fd, buf, (size_t)SecHdrTblEntrSize) != (ssize_t)

SecHdrTblEntrSize ) {
????? fprintf(stderr, "read error/n");
????? close(fd); exit(1);
?? }
?? s_hdr_ptr = (myElf32_Shdr *)buf;
?? SecNamStrTblFileOffset = (unsigned int)s_hdr_ptr->sh_offset;

?? /* 讀取節(jié)名表,并緩存在一個緩沖區(qū)中。*/
?? if ( lseek(fd, (off_t)SecNamStrTblFileOffset, SEEK_SET) !=
??????? SecNamStrTblFileOffset || SecNamStrTblFileOffset == 0 ) {
????? fprintf(stderr, "lseek to Section Name String Table error./n");
????? 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/n");
????? close(fd); exit(1);
?? }

?? if ( lseek(fd, (off_t)SecHdrFileOffset, SEEK_SET) !=

SecHdrFileOffset ||
??????? SecHdrFileOffset == 0 ) {
????? fprintf(stderr, "lseek to section header error./n");
????? close(fd); exit(1);
?? }

?? /* 記錄符號表(即.dynsym節(jié))在文件中的偏移,由它的字節(jié)長度和每個表項


????? 長度算出符號表的表項數(shù)目。同時記下.dynstr節(jié)在文件中的偏移和字節(jié)長

度。*/
?? for (i = 0; i < (int)SecHdrTblEntrNum; i++) {
????? if ( read(fd, buf, (size_t)SecHdrTblEntrSize) !=
?????????? (ssize_t)SecHdrTblEntrSize ) {
???????? fprintf(stderr, "read error/n");
???????? 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./n");
????? 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/n");
???????? close(fd); exit(1);
????? }
????? s_hdr_ptr = (myElf32_Shdr *)buf;
????? fprintf(stdout, "Section %d:/n", i);
????? SecNameIndex = (unsigned int)s_hdr_ptr->sh_name;
????? fprintf(stdout, "(Section name (string tbl index))sh_name: 0x%08X

-> %s/n",
?????????????????????? s_hdr_ptr->sh_name, SecNameStrTable +

SecNameIndex);
????? fprintf(stdout, "(Section type)sh_type: 0x%08X/n",
?????????????????????? s_hdr_ptr->sh_type);
????? fprintf(stdout, "(Section flags)sh_flags: 0x%08X/n",
?????????????????????? s_hdr_ptr->sh_flags);
????? fprintf(stdout, "(Section virtual addr at execution)sh_addr: 0x%

08X/n",
?????????????????????? s_hdr_ptr->sh_addr);
????? fprintf(stdout, "(Section file offset)sh_offset: 0x%08X/n",
?????????????????????? s_hdr_ptr->sh_offset);
????? fprintf(stdout, "(Section size in bytes)sh_size: 0x%08X/n",
?????????????????????? s_hdr_ptr->sh_size);
????? fprintf(stdout, "(Link to another section)sh_link: 0x%08X/n",
?????????????????????? s_hdr_ptr->sh_link);
????? fprintf(stdout, "(Additional section information)sh_info: 0x%

08X/n",
?????????????????????? s_hdr_ptr->sh_info);
????? fprintf(stdout, "(Section alignment)sh_addralign: 0x%08X/n",
?????????????????????? s_hdr_ptr->sh_addralign);
????? fprintf(stdout, "(Entry size if section holds table)sh_entsize:

0x%08X/n",
?????????????????????? s_hdr_ptr->sh_entsize);
?? }

?? fprintf(stdout,
"**********************************************************************

**/n");

?? if ( lseek(fd, (off_t)DebugInfoStrTblFileOffset, SEEK_SET) !=
??????? DebugInfoStrTblFileOffset || DebugInfoStrTblFileOffset == 0 ) {
????? fprintf(stderr, "lseek to Debug Info String Table error./n");
????? 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./n");
????? 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/n", i);
????? fprintf(stdout, "Symbol_index_and_name: 0x%08X -> %s/n",
??????????????????? symptr->st_name, DebugInfoStrTable + symptr-

>st_name);
????? fprintf(stdout, "Symbol_value: 0x%08X/n", symptr->st_value);
????? fprintf(stdout, "Symbol_size: 0x%08X/n", symptr->st_size);
????? fprintf(stdout, "Symbol_type_and_binding: 0x%02X/n", symptr-

>st_info);
????? fprintf(stdout, "Section_index: 0x%04X/n", symptr->st_shndx);
????? fprintf(stdout,
???????? "--------------------------------------------------------/n");
?? }

?? fprintf(stdout,
"**********************************************************************

**/n");

next:

?? /* 讀取 .dynstr 節(jié)的內(nèi)容,并緩存在一個緩沖區(qū)中。*/
?? if ( lseek(fd, (off_t)SymNamStrTblFileOffset, SEEK_SET) !=
??????? SymNamStrTblFileOffset || SymNamStrTblFileOffset == 0 ) {
????? fprintf(stderr, "lseek to Dynamical symbol name string

error./n");
????? 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./n");
????? 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/n", i);
????? fprintf(stdout, "Symbol_index_and_name: 0x%08X -> %s/n",
?????????????????????? symptr->st_name, SymNamStrTable + symptr-

>st_name);
????? fprintf(stdout, "Symbol_value: 0x%08X/n", symptr->st_value);
????? fprintf(stdout, "Symbol_size: 0x%08X/n", symptr->st_size);
????? fprintf(stdout, "Symbol_type_and_binding: 0x%02X/n", symptr-

>st_info);
????? fprintf(stdout, "Section_index: 0x%04X/n", symptr->st_shndx);
????? fprintf(stdout,
???????? "--------------------------------------------------------/n");
?? }

?? fprintf(stdout,
"**********************************************************************

**/n");

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

>si_flags);
????? fprintf(stdout,
???????? "--------------------------------------------------------/n");
?? }

?? 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'./n", argv[1]);
????? exit(-1);
?? }

?? /* 檢索符號表搜索要修改的符號。*/
?? if ( lseek(fd, (off_t)SymTblFileOffset, SEEK_SET) !=

SymTblFileOffset ) {
????? fprintf(stderr, "lseek error./n");
????? 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./n");
????? close(fd); exit(-1);
?? }
?? if ( write(fd, dst_sym, (size_t)16) != (ssize_t)16 ) {
????? fprintf(stderr, "write error/n");
????? close(fd); exit(-1);
?? }

?? close(fd);
?? return 0;
}

/* EOF */

總結

以上是生活随笔為你收集整理的如何修改动态库符号表的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。