读书笔记_windows下的混合钩子(HOOK)_part 2
来源:互联网 发布:大专网络教育 编辑:程序博客网 时间:2024/06/11 16:55
读书笔记_windows下的混合钩子(HOOK)_part 2
1. 分析PE文件
下面接着看如果分析PE文件,从而找到其要导入的DLL。
首先看PE文件的导入数据.idata段。.idata段是导入数据,包括导入库和导入地址名称表。在WINNT.H中所定义的数据目录为:
// 目录入口
// 导出目录
#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
// 导入目录
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
// 资源目录
#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
// 异常目录
#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
// 安全目录
#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
// 重定位基本表
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
// 调试目录
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
// 描述字串
#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
// 机器值(MIPS GP)
#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8
// TLS目录
#define IMAGE_DIRECTORY_ENTRY_TLS 9
// 载入配置目录
#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
在分析PE时,首先要得到导入段(即DataDirectory的IMAGE_DIRECTROY_ENTRY_IMPORT)的RVA。将RVA与模块在内存中的起始地址相加(基地址),就会得到虚拟地址,这个地址也就是指向IMAGE_IMPORT_DESCRIPTOR的指针。
关于IMAGE_IMPORT_DESCRIPTOR的描述如下:
IMAGE_IMPORT_DESCRIPTOR是在导入段中(Imports Section)中,DataDirectory 入口的导入点都是指向IMAGE_IMPORT_DESCRIPTOR结构的,具体的结构如下表所示:
Size
Member
Description
DWORD
OriginalFirstThunk
This field is badly named. It contains the RVA of the Import Name Table (INT). This is an array of IMAGE_THUNK_DATA structures. This field is set to 0 to indicate the end of the array of IMAGE_IMPORT_DESCRIPTORs.
DWORD
TimeDateStamp
This is 0 if this executable is not bound against the imported DLL. When binding in the old style (see the section on Binding), this field contains the time/date stamp (number of seconds since 1/1/1970 GMT) when the binding occurred. When binding in the new style, this field is set to -1.
DWORD
ForwarderChain
This is the Index of the first forwarded API. Set to -1 if no forwarders. Only used for old-style binding, which could not handle forwarded APIs efficiently.
DWORD
Name
The RVA of the ASCII string with the name of the imported DLL.
DWORD
FirstThunk
Contains the RVA of the Import Address Table (IAT). This is array of IMAGE_THUNK_DATA structures.
每个导入执行块都有一个IMAGE_IMPORT_DESCRIPTOR结构。
通过得到第一个IMAGE_IMPORT_DESCRIPTOR结构后,由于所有的DLL都具有相应的IMAGE_IMPORT_DESCRIPTOR结构,当发现Characteristics域为0的结构时,就已经达到该模块所导入的最后一个DLL。
每个IMAGE_IMPORT_DESCRIPTOR结构中包含指向两个独立数组的指针。其中一个是该模块从给定的DLL中导入的所有函数的地址数据指针,通过IMAGE_IMPORT_DESCRIPTOR的FirstThunk成员到达该地址表,IMAGE_IMPORT_DESCRIPTOR中的OriginalFirstThunk用于寻找指向IMAGE_IMPORT_BY_NAME结构的指针数组,这些结构包含了被导入函数的名称,除非函数是根据序号导入的。
2. HookImportsOfImage函数
来看HookImportsOfImage函数,它的功能是扫描所有模块,确定它们是否从Kernel32.dll导入了GetProcAddress函数,如果发现了这个IAT,可以首先修改IAT的内存保护机制,改变权限后就使用钩子重写IAT中的地址。来具体看HookImportsOfImage函数,
NTSTATUS HookImportsOfImage ( PIMAGE_DOS_HEADER image_addr, HANDLE h_proc)
{
PIMAGE_DOS_HEADER dosHeader;
PIMAGE_NT_HEADERS pNTHeader;
PIMAGE_IMPORT_DESCRIPTOR importDesc;
PIMAGE_IMPORT_BY_NAME p_ibn;
DWORD importsStartRVA;
PWORD pd_IAT, pd_INTO;
int count, index;
char *dll_name = NULL;
char *pc_dlltar = "kernel32.dll";
char *pc_fnctar = "GetProcAddress";
PMDL p_mdl;
PDWORD MappedImTable;
dosHeader = (PIMAGE_DOS_HEADER) image_addr;
pNTHeader = MakePtr ( PIMAGE_NT_HEADERS, dosHeader, dosHeader->e_lfanew );
// First, verify that the e_lfanew field gave us a reasonable
// pointer, then verify the PE signature.
if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE)
return STATUS_INVALID_IMAGE_FORMAT;
importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if ( !importsStartRVA )
return STATUS_INVALID_IMAGE_FORMAT;
importDesc = ( PIMAGE_IMPORT_DESCRIPTOR ) (importsStartRVA + (DWORD)dosHeader);
for(count = 0; importDesc[count].Characteristics != 0; count++)
{
dll_name = (char*)(importDesc[count].Name + (DWORD)dosHeader);
pd_IAT = (PDWORD)(((DWORD)dosHeader) + (DWORD)importDesc[count].FirstThunk);
pd_INTO = (PDWORD)(((DWORD)dosHeader) + (DWORD)importDesc[count].OriginalFirstThunk);
for ( index = 0; pd_IAT[index] != 0; index++)
{
// if this is an import by ordinal
// the high bit is set
if((pd_INT[index] & IMAGE_ORDINAL_FLAG) != IMAGE_ORDINAL_FLAG)
{
p_ibn = (PIMAGE_IMPORT_BY_NAME)(pd_INTO[index] + ((DWORD)dosHeader));
if((_stricmp(dll_name, pc_dlltar) == 0) && (strcmp(p_ibn->Name, pc_fnctar) ==0))
{
// Use the trick you already learned to map a different
// virtual address to the same physical page so no permission problems
//
// Map the memory into our domain so we can change the
// permissions on the MDL
p_mdl = MmCreateMdl(NULL, &pd_IAT[index], 4);
if(!p_mdl)
return STATUS_UNSUCCESSFUL;
MmBuildMdlForNonPagedPool(p_mdl);
// Change the flags of MDL
p_mdl->MdlFlags = p_mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedImTable = MmMapLocakedPages(p_mdl, KernelMode);
// Address of the "new function"
*MappedImTable = d_shareM;
// Free MDL
MmUnmapLoackedPages(MappedImTable, p_mdl);
IoFreeMdl(p_mdl);
}
}
}
return STATUS_SUCCESS;
}
HookImportsOfImage是一个回调函数,每当将一个映像(进程,设备驱动程序,DLL等)加载到内存中是,都会调用它。代码已经搜索了每个映像,检查它是否导入了钩子的目标函数,如果找到该目标函数,则替换它在IAT中的地址。
- 读书笔记_windows下的混合钩子(HOOK)_part 2
- 读书笔记_windows下的混合钩子(HOOK)_part 1
- 读书笔记_windows下的混合钩子(HOOK)_part 5_钩子的内存空间
- 读书笔记_windows下的混合钩子(HOOK)_part 3_HookImportsOfImage函数解析
- 读书笔记_windows下的混合钩子(HOOK)_part 4_使用MDL修改内存保护机制
- 读书笔记_windows的APIHook技术_part 2
- 读书笔记_windows内核编程基础_part 2
- 读书笔记_windows内核调试_part 2_内核对话过程
- 读书笔记_windows内核编程基础_part 1
- 读书笔记_windows内核调试_part 1
- 读书笔记_windows下的验证机制
- Wordpress的钩子(hook)
- 读书笔记_Windows的启动过程
- 读书笔记_windows的APIHook技术
- TP框架----hook(钩子)的使用
- java的关闭钩子(Shutdown Hook)
- hook钩子的使用
- 钩子(hook)
- 放弃理想,未必能成就现实
- java中hashcode()和equals()的详解[转]
- 好的程序员做不出好的软件设计
- uboot Makefile 分析
- JCTVC 会议输出文档
- 读书笔记_windows下的混合钩子(HOOK)_part 2
- SQL中JOIN和UNION区别、用法及示例
- NDK开发中利用Logcat调试JNI
- cvs add: added independently by second party 问题解决
- 在VPS上安装cPanel主机控制面板
- function object研究之四
- Facebook是如何开发软件的
- Windows下Apache与Tomcat的整合
- 解决了/usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.9' not found的问题