一步一步走进Linux HOOK API(六)

上一节,我们讲了如何手动通过GDB来拦截printf的参数,其实ELF远远不止我们介绍的那点东西,在经过一轮实战之后,我们得继续回到ELF文件格式的探索之旅了.今天我们这里就要讲什么的,好了,今天我们轻松一点,看一下动态节,

动态节的类型是SHT_DYNAMIC,

先看一下动态节的定义:

[cpp]  view plain copy
  1. typedef struct  
  2. {  
  3.   Elf32_Sword   d_tag;   /* Dynamic entry type */  
  4.   union  
  5.     {  
  6.       Elf32_Word d_val;  /* Integer value */  
  7.       Elf32_Addr d_ptr;  /* Address value */  
  8.     } d_un;  
  9. } 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类型的动态结构出现在动态表中.

下面给出示例代码,跟打印符号表几乎一样:

[cpp]  view plain copy
  1. #include "readDyn.h"  
  2. DynType dynName[] = {  
  3. "DT_NULL",0,"DT_NEEDED",    1,"DT_PLTRELSZ","DT_PLTGOT",  
  4. 3,"DT_HASH",4,"DT_STRTAB",  5"DT_SYMTAB",   6,"DT_RELA",    7,  
  5. "DT_RELASZ",    8,"DT_RELAENT",9,"DT_STRSZ",10,"DT_SYMENT",  
  6. 11,"DT_INIT",12,"DT_FINI",13,"DT_SONAME",14,"DT_RPATH",15,  
  7. "DT_SYMBOLIC",16,"DT_REL",17,"DT_RELSZ",18,"DT_RELENT",19,  
  8. "DT_PLTREL",    20,"DT_DEBUG",21,"DT_TEXTREL",  22,"DT_JMPREL",  
  9. 23,"DT_BIND_NOW",24,"DT_INIT_ARRAY",25,"DT_FINI_ARRAY",26,  
  10. "DT_INIT_ARRAYSZ",27,"DT_FINI_ARRAYSZ",28,"DT_RUNPATH",29,  
  11. "DT_FLAGS",30,"DT_ENCODING",32,"DT_PREINIT_ARRAY",32,  
  12. "DT_PREINIT_ARRAYSZ", 33,"DT_NUM",34,"DT_LOOS",0x6000000d,  
  13. "DT_HIOS",0x6ffff000,"DT_LOPROC",0x70000000,"DT_HIPROC",  
  14. 0x7fffffff,  
  15. };  
  16. char* findDynTypeName(unsigned int type)  
  17. {  
  18. int i = 0;  
  19. for(i = 0;i < sizeof(dynName) / sizeof(DynType);i++){  
  20. if(dynName[i].type == type){  
  21. return dynName[i].typeName;  
  22. break;  
  23. }  
  24. }  
  25. return dynName[0].typeName;  
  26. }  
  27. void display_dyn(Elf32_Ehdr *ehdr,Elf32_Shdr *shdr)  
  28. {  
  29. Elf32_Dyn *dyn = (Elf32_Dyn *)((char*)ehdr + shdr->sh_offset);  
  30. char    *symName = (char*)(((Elf32_Shdr *)((char*)ehdr + ehdr->e_shoff + shdr->sh_link * sizeof(Elf32_Shdr)))->sh_offset   
  31. + (char*)ehdr);  
  32. printf("symb = 0x%x\n",(char*)dyn);  
  33. printf("symName = 0x%x\n",(char*)symName);  
  34. printf("Dynamic section at offset 0x%x contains entries:\n",dyn);  
  35. int i = 0;  
  36. printf("%-10s%-10s%s\n","Tag","Type","Name/Value");  
  37. do{  
  38. printf("%-10x",dyn->d_tag);  
  39. printf("%-10s",findDynTypeName(dyn->d_tag));  
  40. if(dyn->d_tag == DT_NEEDED){  
  41. printf("%s",symName + dyn->d_un.d_ptr);  
  42. }else{  
  43. printf("%x",dyn->d_un.d_val);  
  44. }  
  45. printf("\n");  
  46. }while(dyn->d_tag != DT_NULL && dyn++);  
  47. }  
  48. void displayDyn(Elf32_Ehdr *ehdr,Elf32_Shdr *shdr)  
  49. {  
  50. int py = ehdr->e_shstrndx * sizeof(Elf32_Shdr);  
  51. Elf32_Shdr *symtab = (Elf32_Shdr *)((char*)shdr + py);  
  52. char *szShdrName = (char*)(symtab->sh_offset + (char*)ehdr);  
  53. int i = 0;  
  54. for(i = 0; i < ehdr->e_shnum; i++){  
  55. if(shdr->sh_type == SHT_DYNAMIC){  
  56. display_dyn(ehdr,shdr);  
  57. }  
  58. shdr++;  
  59. }  
  60. }  

你可能感兴趣的:(一步一步走进Linux HOOK API(六))