一步一步走进Linux HOOK API(六)
上一节,我们讲了如何手动通过GDB来拦截printf的参数,其实ELF远远不止我们介绍的那点东西,在经过一轮实战之后,我们得继续回到ELF文件格式的探索之旅了.今天我们这里就要讲什么的,好了,今天我们轻松一点,看一下动态节,
动态节的类型是SHT_DYNAMIC,
先看一下动态节的定义:
typedef struct
{
Elf32_Sword d_tag; /* Dynamic entry type */
union
{
Elf32_Word d_val; /* Integer value */
Elf32_Addr d_ptr; /* Address value */
} d_un;
} Elf32_Dyn;
乍看之下,这个结构貌似挺简单的嘛,就2成员,一个岁居然是联合体.这就郁闷了,什么时候用d_val.什么时候用d_prt呢?
在动态节中有很多不同的类型.成员d_tag给出了结构的类型值,而d_un成员是由d_val.还是d_prt就要看这个结构体的类型了,庆幸的是,我们主要知道DT_NEEDED,DT_NEEDED被定义为常量1,对于DT_NEEDED类型的动态结构他的d_val成员其实是一个字符串表中的索引,它给出的字符串就是这个ELF文件所依赖的外部动态库的名称.你的ELF文件需要依赖多少个动态库就有多少个DT_NEEDED类型的动态结构出现在动态表中.
下面给出示例代码,跟打印符号表几乎一样:
#include "readDyn.h"
DynType dynName[] = {
"DT_NULL",0,"DT_NEEDED", 1,"DT_PLTRELSZ","DT_PLTGOT",
3,"DT_HASH",4,"DT_STRTAB", 5"DT_SYMTAB", 6,"DT_RELA", 7,
"DT_RELASZ", 8,"DT_RELAENT",9,"DT_STRSZ",10,"DT_SYMENT",
11,"DT_INIT",12,"DT_FINI",13,"DT_SONAME",14,"DT_RPATH",15,
"DT_SYMBOLIC",16,"DT_REL",17,"DT_RELSZ",18,"DT_RELENT",19,
"DT_PLTREL", 20,"DT_DEBUG",21,"DT_TEXTREL", 22,"DT_JMPREL",
23,"DT_BIND_NOW",24,"DT_INIT_ARRAY",25,"DT_FINI_ARRAY",26,
"DT_INIT_ARRAYSZ",27,"DT_FINI_ARRAYSZ",28,"DT_RUNPATH",29,
"DT_FLAGS",30,"DT_ENCODING",32,"DT_PREINIT_ARRAY",32,
"DT_PREINIT_ARRAYSZ", 33,"DT_NUM",34,"DT_LOOS",0x6000000d,
"DT_HIOS",0x6ffff000,"DT_LOPROC",0x70000000,"DT_HIPROC",
0x7fffffff,
};
char* findDynTypeName(unsigned int type)
{
int i = 0;
for(i = 0;i < sizeof(dynName) / sizeof(DynType);i++){
if(dynName[i].type == type){
return dynName[i].typeName;
break;
}
}
return dynName[0].typeName;
}
void display_dyn(Elf32_Ehdr *ehdr,Elf32_Shdr *shdr)
{
Elf32_Dyn *dyn = (Elf32_Dyn *)((char*)ehdr + shdr->sh_offset);
char *symName = (char*)(((Elf32_Shdr *)((char*)ehdr + ehdr->e_shoff + shdr->sh_link * sizeof(Elf32_Shdr)))->sh_offset
+ (char*)ehdr);
printf("symb = 0x%x\n",(char*)dyn);
printf("symName = 0x%x\n",(char*)symName);
printf("Dynamic section at offset 0x%x contains entries:\n",dyn);
int i = 0;
printf("%-10s%-10s%s\n","Tag","Type","Name/Value");
do{
printf("%-10x",dyn->d_tag);
printf("%-10s",findDynTypeName(dyn->d_tag));
if(dyn->d_tag == DT_NEEDED){
printf("%s",symName + dyn->d_un.d_ptr);
}else{
printf("%x",dyn->d_un.d_val);
}
printf("\n");
}while(dyn->d_tag != DT_NULL && dyn++);
}
void displayDyn(Elf32_Ehdr *ehdr,Elf32_Shdr *shdr)
{
int py = ehdr->e_shstrndx * sizeof(Elf32_Shdr);
Elf32_Shdr *symtab = (Elf32_Shdr *)((char*)shdr + py);
char *szShdrName = (char*)(symtab->sh_offset + (char*)ehdr);
int i = 0;
for(i = 0; i < ehdr->e_shnum; i++){
if(shdr->sh_type == SHT_DYNAMIC){
display_dyn(ehdr,shdr);
}
shdr++;
}
}