逆向总结(3)-- 无模块遍历API(找到Kernel32.dll)

来源:互联网 发布:mysql router 读写分离 编辑:程序博客网 时间:2024/05/16 15:01

很多的时候,我们需要使用到无模块获取到Kernel32.dll的基址,这时候,我们就需要借助FS还完成:

      1)通过FS得到TEB的地址

         2)TEB偏移0x30处指向的是PEB指针

         3)PEB偏移0x0C处指向PEB_LDR_DATA结构指针

         4)PEB_LDR_DATA偏移0x1C处是InInitializationOrderModuleLis(模块初始化链表的头指针)

         5)InInitializationOrderModuleLis中按顺序存在着此进程的初始化模块信息,在NT5.x内核中,第一个节点为ntdll.dll的基址,第二个节点为Kernel32.dll的基址; 在NT6.1内核中,第二个节点为KernelBase.dll的基址(包含着Kernel32.dll的大部分实现,其中就有GetProcAddress函数)



代码

#include "stdafx.h"#include <windows.h>//#define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address)-(ULONG_PTR)(&((type *)0)->field)))typedef struct _UNICODE_STRING {<span style="white-space:pre"></span>USHORT  Length;<span style="white-space:pre"></span>USHORT  MaximumLength;<span style="white-space:pre"></span>PWSTR  Buffer;} UNICODE_STRING, *PUNICODE_STRING;typedef struct _PEB_LDR_DATA{<span style="white-space:pre"></span>DWORD Length;<span style="white-space:pre"></span>UCHAR Initialized;<span style="white-space:pre"></span>PVOID SsHandle;<span style="white-space:pre"></span>LIST_ENTRY InLoadOrderModuleList;<span style="white-space:pre"></span>LIST_ENTRY InMemoryOrderModuleList;<span style="white-space:pre"></span>LIST_ENTRY InInitializationOrderModuleList;<span style="white-space:pre"></span>PVOID EntryInProgress;}PEB_LDR_DATA, *PPEB_LDR_DATA;typedef struct _LDR_DATA_TABLE_ENTRY{<span style="white-space:pre"></span>LIST_ENTRY InLoadOrderLinks;<span style="white-space:pre"></span>LIST_ENTRY InMemoryOrderLinks;<span style="white-space:pre"></span>LIST_ENTRY InInitializationOrderLinks;<span style="white-space:pre"></span>PVOID DllBase;<span style="white-space:pre"></span>PVOID EntryPoint;<span style="white-space:pre"></span>DWORD SizeOfImage;<span style="white-space:pre"></span>UNICODE_STRING FullDllName;<span style="white-space:pre"></span>UNICODE_STRING BaseDllName;<span style="white-space:pre"></span>DWORD Flags;<span style="white-space:pre"></span>WORD LoadCount;<span style="white-space:pre"></span>WORD TlsIndex;<span style="white-space:pre"></span>LIST_ENTRY HashLinks;<span style="white-space:pre"></span>PVOID SectionPointer;<span style="white-space:pre"></span>DWORD CheckSum;<span style="white-space:pre"></span>DWORD TimeDateStamp;<span style="white-space:pre"></span>PVOID LoadedImports;<span style="white-space:pre"></span>PVOID EntryPointActivationContext;<span style="white-space:pre"></span>PVOID PatchInformation;}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;typedef struct _PEB{<span style="white-space:pre"></span>UCHAR InheritedAddressSpace;<span style="white-space:pre"></span>UCHAR ReadImageFileExecOptions;<span style="white-space:pre"></span>UCHAR BeingDebugged;<span style="white-space:pre"></span>UCHAR SpareBool;<span style="white-space:pre"></span>PVOID Mutant;<span style="white-space:pre"></span>PVOID ImageBaseAddress;<span style="white-space:pre"></span>PPEB_LDR_DATA Ldr;}PEB, *PPEB;int main(void){<span style="white-space:pre"></span>PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;<span style="white-space:pre"></span>PLIST_ENTRY pListEntryStart = NULL, pListEntryEnd = NULL;<span style="white-space:pre"></span>PPEB_LDR_DATA pPebLdrData = NULL;<span style="white-space:pre"></span>PPEB pPeb = NULL;<span style="white-space:pre"></span>__asm<span style="white-space:pre"></span>{<span style="white-space:pre"></span>//1、通过fs:[30h]获取当前进程的_PEB结构  <span style="white-space:pre"></span>mov eax, dword ptr fs : [30h];<span style="white-space:pre"></span>mov pPeb, eax<span style="white-space:pre"></span>}<span style="white-space:pre"></span>//2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构  <span style="white-space:pre"></span>pPebLdrData = pPeb->Ldr;<span style="white-space:pre"></span>//3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构  <span style="white-space:pre"></span>pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;<span style="white-space:pre"></span>//查找所有已载入到内存中的模块  <span style="white-space:pre"></span>do<span style="white-space:pre"></span>{<span style="white-space:pre"></span>//4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构  <span style="white-space:pre"></span>// CONTAINING_RECORD宏 根据结构体中的某成员的地址来推算出该结构体整体的地址!<span style="white-space:pre"></span>pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);<span style="white-space:pre"></span>//5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息  <span style="white-space:pre"></span>printf("%S\n", pLdrDataEntry->FullDllName.Buffer);<span style="white-space:pre"></span>pListEntryStart = pListEntryStart->Flink;<span style="white-space:pre"></span>} while (pListEntryStart != pListEntryEnd);<span style="white-space:pre"></span>getchar();}

效果如下图:




参考文档:

LDR链调试手记
http://bbs.pediy.com/showthread.php?t=149527
关于LDR的疑问与探索
http://bbs.pediy.com/showthread.php?p=1374563

0 0