您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 国内外标准规范 > LinuxAPIHook
一步一步走进LinuxHOOKAPI(一)最近我查阅很多参考资料.发现对于讲述LinuxHOOKAPI的资料是很少,让我们这些新人难以去走进LinuxHOOK大门.在这里我将全面的讲述LinuxHOOKAPI的全部实现过程,这个过程中我也遇到很多坎坷,所以在这么写下这份教程.让大家都来进入HOOK的神秘世界.不要认为HOOKAPI是windows的专利(PS.其实我以前就是这么认为的.哈哈....),其实在Linux中也有HOOKAPI这样的技术,只是实现起来相对比较麻烦,首先今天主要带大家认识的是ELF文件,在Linux中,ELF文件主要是应用在可执行文件,重定位文件,可执行文件动态连接库。首先来看一下ELFHead的定义:PS.我们这里主要针对的是32位平台.有关64位平台相关定义请参阅/usr/include/elf.h#defineEI_NIDENT(16)typedefstruct{unsignedchare_ident[EI_NIDENT];/*Magicnumberandotherinfo*/Elf32_Halfe_type;/*Objectfiletype*/Elf32_Halfe_machine;/*Architecture*/Elf32_Worde_version;/*Objectfileversion*/Elf32_Addre_entry;/*Entrypointvirtualaddress*/Elf32_Offe_phoff;/*Programheadertablefileoffset*/Elf32_Offe_shoff;/*Sectionheadertablefileoffset*/Elf32_Worde_flags;/*Processor-specificflags*/Elf32_Halfe_ehsize;/*ELFheadersizeinbytes*/Elf32_Halfe_phentsize;/*Programheadertableentrysize*/Elf32_Halfe_phnum;/*Programheadertableentrycount*/Elf32_Halfe_shentsize;/*Sectionheadertableentrysize*/Elf32_Halfe_shnum;/*Sectionheadertableentrycount*/Elf32_Halfe_shstrndx;/*Sectionheaderstringtableindex*/}Elf32_Ehdr;e_ident:这个成员,是ELF文件的第一个成员,该成员是个数字,根据上面的宏可以看出,这个程序是个16字节的数据.该成员的前4个字节依次是0x7F,0x45,0x4c,0x46,也就是\177ELF。这是ELF文件的标志,任何一个ELF文件这四个字节都完全相同。为了让我们更方便的使用ELF数据在elf.h中对上述数据进行了宏定义.如下:#defineEI_MAG00/*Fileidentificationbyte0index*/#defineELFMAG00x7f/*Magicnumberbyte0*#defineEI_MAG11/*Fileidentificationbyte1index*/#defineELFMAG1'E'/*Magicnumberbyte1*/#defineEI_MAG22/*Fileidentificationbyte2index*/#defineELFMAG2'L'/*Magicnumberbyte2*/#defineEI_MAG33/*Fileidentificationbyte3index*/#defineELFMAG3'F'/*Magicnumberbyte3*//*Conglomerationoftheidentificationbytes,foreasytestingasaword.*/#defineELFMAG\177ELF#defineSELFMAG4第四个字节表示ELF格式,1:32位2:64位#defineEI_CLASS4/*Fileclassbyteindex*/#defineELFCLASSNONE0/*Invalidclass*/#defineELFCLASS321/*32-bitobjects*/#defineELFCLASS642/*64-bitobjects*/#defineELFCLASSNUM3第五个字节表示数据编码格式,1:小端模式2:大端模式#defineEI_DATA5/*Dataencodingbyteindex*/#defineELFDATANONE0/*Invaliddataencoding*/#defineELFDATA2LSB1/*2'scomplement,littleendian*/#defineELFDATA2MSB2/*2'scomplement,bigendian*/#defineELFDATANUM3第六个字节表示文件版本,该值目前必须为1#defineEV_CURRENT1/*Currentversion*/第七个字节表示操作系统标识:#defineEI_OSABI7/*OSABIidentification*/#defineELFOSABI_NONE0/*UNIXSystemVABI*/#defineELFOSABI_SYSV0/*Alias.*/#defineELFOSABI_HPUX1/*HP-UX*/#defineELFOSABI_NETBSD2/*NetBSD.*/#defineELFOSABI_LINUX3/*Linux.*/#defineELFOSABI_SOLARIS6/*SunSolaris.*/#defineELFOSABI_AIX7/*IBMAIX.*/#defineELFOSABI_IRIX8/*SGIIrix.*/#defineELFOSABI_FREEBSD9/*FreeBSD.*/#defineELFOSABI_TRU6410/*CompaqTRU64UNIX.*/#defineELFOSABI_MODESTO11/*NovellModesto.*/#defineELFOSABI_OPENBSD12/*OpenBSD.*/#defineELFOSABI_ARM97/*ARM*/#defineELFOSABI_STANDALONE255/*Standalone(embedded)application*/第八个字节表示ABI版本#defineEI_ABIVERSION8/*ABIversion*/第九个字节表示e_ident中从哪开始之后未使用.#defineEI_PAD9/*Byteindexofpaddingbytes*/e_type:这个成员是ELF文件的类型:1:表示此文件是重定位文件.2:表示可执行文件.3:表示此文件是一个动态连接库。e_machine:这个成员表示机器版本.具体定义参与elf.h(篇幅问题,太长了)e_version:这个成员表示ELF文件版本,为1e_entry:这个成员表示可执行文件的入口虚拟地址。此字段指出了该文件中第一条可执行机器指令在进程被正确加载后的内存地址!ELF可执行文件只能被加载到固定位置.e_phoff:这个成员表示程序头(ProgramHeaders)在ELF文件中的偏移量。如果程序头不存在此值为0。e_shoff:这个成员表示节头(SectionHeaders:)在ELF文件中的偏移量。如果节头不存在此值为0。e_flags:这个成员表示处理器标志.e_ehsize:这个成员描述了“ELF头”自身占用的字节数。e_phentsize:该成员表示程序头中的每一个结构占用的字节数。程序头也叫程序头表,可以被看做一个在文件中连续存储的结构数组,数组中每一项是一个结构,此字段给出了这个结构占用的字节大小。e_phoff:指出程序头在ELF文件中的起始偏移。e_phnum:此字段给出了程序头中保存了多少个结构。如果程序头中有3个结构则程序头在文件中占用了3×e_phentsize个字节的大小。e_shentsize:节头中每个结构占用的字节大小。节头与程序头类似也是一个结构数组,关于这两个结构的定义将分别在讲述程序头和节头的时候给出。e_shnum:节头中保存了多少个结构。e_shstrndx:这是一个整数索引值。节头可以看作是一个结构数组,用这个索引值做为此数组的下标,它在节头中指定的一个结构进一步给出了一个“字符串表”的信息,而这个字符串表保存着节头中描述的每一个节的名称,包括字符串表自己也是其中的一个节。示例代码:#includeunistd.h#includeelf.h#includefcntl.h#includestdio.h#includestring.h#includestdlib.h#includesys/mman.h#includesys/types.h#includesys/stat.hintg_File=0;void*g_pData=NULL;void*Map(char*szFileName){g_File=open(szFileName,O_RDWR);if(g_File0){g_File=0;returnNULL;}structstatstatus;fstat(g_File,&status);g_pData=mmap(0,status.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,g_File,0);if(MAP_FAILED!=g_pData){returng_pData;}close(g_File);g_pData=NULL;g_File=0;returnNULL;}voiddisplayEhdr(Elf32_Ehdr*ehdr){printf(Magic:);inti=0;for(i=0;iEI_NIDENT;i++){printf(%02x,ehdr-e_ident[i]);}printf(\n);printf(Version:0x%x\n,ehdr-e_version);printf(Entrypointaddress:0x%x\n,ehdr-e_entry);printf(Startofprogramheaders:%d(bytesintofile)\n,ehdr-e_phoff);printf(Startofsectionheaders:%d(bytesintofile)\n,ehdr-e_shoff);printf(Flags:%d\n,ehdr-e_flags);printf(Sizeofthisheader:%d(bytes)\n,ehdr-e_ehsize);printf(Sizeofprogramheaders:%d(bytes)\n,ehdr-e_phentsize);printf(Numberofprogramheaders:%d\n,ehdr-e_phnum);printf(Sizeofsectionheaders:%d(bytes)\n,ehdr-e_shentsize);printf(Numberofsectionheaders:%d\n,ehdr-e_shnum);printf(Sectionheaderstringtableindex:%d\n,ehdr-e_shstrndx);}intmain(intargc,char*argv[]){if(argc!=2){printf(parametererror\n);exit(0);}Elf32_Ehdr*ehdr=(Elf32_Ehdr*)Map(argv[1]);if(ehdr==NULL){perror(MapError\n);exit(0);}displayEhdr(ehdr);}一步一步走进LinuxHOOKAPI(二)从
本文标题:LinuxAPIHook
链接地址:https://www.777doc.com/doc-1085023 .html