最近想学HOOK方面的知识、看了一些代码、发现PE的知识忘了好多、尤其是导入表导出表那块

(其实之前学PE 这块也是主学、其他大概了解、)

看了以前的笔记发现还是挺详细的、好多东西还是可以帮我速度的回忆起来、、

好像有一大阵不写C++程序了、、学了一阵汇编为了脱壳逆向嘎嘎、、不过壳脱的还行、逆向这个不怎么样接着努力、、

说实话偶还是比较喜欢编程的哦、、尤其是底层、、嘎嘎、、底层是神马、、貌似木有接触过、哎这知识学的、神马跟神马啊、、听学长讲过、学学各种HOOK将来找个工作木有问题啦、、所以嘛 我得谨遵教诲好好HOOK 呼呼呼咳咳咳、、神马IAT INLINE SSDT、、一个么有写过、、不过写过一个也就可以写俩三、、N个咯、、

好了赶紧总结一下IMPORT EXPORT吧不然一会就忘了(啥都不行就忘性超强啊哎、)

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 先不结合代码了说一下感受吧、、


PE的完整名字叫这个  Portable  Execute

常见的EXE、DLL、OCX、SYS、COM都是PE文件,PE文件是微软Windows操作系统上的程序文件(可能是间接被执行,如DLL)(摘自百科、)


反正PE很牛X啦、学底层不学这个是万万不可以的、、

PE的结构: DOS NT(NT标志 FileHeader OptionHeader)节表。。各个节、、

首先想要读取PE的文件信息需要将PE映射到内存、、并获取其首地址、函数有一下几个、、

CreateFile打开一个PE文件

CreateFileMapping将打开的文件映射到内存

MapViewOfFile创建文件映射的视图,并通过视图返回的内存地址(即基地址)

记得关闭句柄、、CloseHandle


得到基地址了用基地址去初始化PE的各个结构一获取导入表导出表的地址、、

PE的地址是个线性的即可以用y=Ax+B;去访问、、首地址这里是pFiAddr、

DOS = (PIMAGE_DOS_HEADER)pFiAddr;

NT = (PIMAGE_NT_HEADERS)(DOS->e_lfanew+pFiAddr); PE的偏移量: e_lfanew

NT有了其成员(NT标志 FileHeader OptionHeader)唾手可得、(多大点事、、嘎嘎)

FileHeader = (PIMAGE_FILE_HEADER)&(NT->FileHeader);注意是取地址、、

OptionHeader = (PIMAGE_OPTIONAL_HEADER)&(NT->OptionalHeader);


导入表导出表的RVA和SIZE在一个叫IMAGE_DATA_DIRECTORY结构中

typedef struct _IMAGE_DATA_DIRECTORY {

  DWORD  VirtualAddress;

  DWORD  Size;

} IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY;

而OptionHeader结构的最后一个成员包含16个这个结构、、部分OptionHeader结构如下、、

  、、、

DWORD  SizeOfHeapCommit;

DWORD  LoaderFlags;

DWORD  NumberOfRvaAndSizes;

IMAGE_DATA_DIRECTORYDataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];

} IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;


所以要找输入、出表先找OptionHeader的最后一成员、、

DATA = (PIMAGE_DATA_DIRECTORY)&(OPTION->DataDirectory[0]);

DataDirectory这个东西包含16个IMAGE_DATA_DIRECTORY、、在这就知道

第一个是导出表DataDirectory[0]、第二个是导入表DataDirectory[1]就OK了、、

现在就知道了导入、出表的RVA 要读其中信息需要知道其在文件中得地址

这里涉及一个地址的转换RVA到RAW

PE加载到内存中是分区段的而区段是一个这样的结构、、PIMAGE_SECTION_HEADER这些表都在这些结构中、、在哪一个节中需要计算一下、、

这个节表结构的信息中有本区段的RVA和RAW故可以利用此得到任何一个RVA对应的RAW

类似小时候 求一座很高很高的塔的高度、使用影子那种方法差不多(你懂的、、)

所以RVA到RAW是这样的、、

先看RVA是不是空的是空的就不用比了、、不是的话、、

for (DWORD i=0; i<节表数量; i++)

{

if (  RVA>=SECTION[i].VirtualAddress&&RVA <=SECTION[i].VirtualAddress+SECTION[i].Misc.VirtualSize)

{

RVA=RVA-SECTION[i].VirtualAddress+SECTION[i].PointerToRawData+ (DWORD)pFileAddr;

return RVA;

}

}

很容易理解 就是跟每一个节的首地址还有末地址比较在其中说明在这个节中

计算即可不在的话继续遍历 节表的数量在FileHeader中可以直接拿到、、


好现在输入、出表的文件地址找到了、、可以初始化其结构了、、

IMPORT = (PIMAGE_IMPORT_DESCRIPTOR)(RAWIMPORT) ;

EXPORT = (PIMAGE_IMPORT_DESCRIPTOR)(RAWEXPORT) ;

现在输入表输出表的信息就可以输出了、、

未完待续、、