最近想学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) ;
现在输入表输出表的信息就可以输出了、、
未完待续、、