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

很多的时候,我们需要使用到无模块获取到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函数)

逆向总结(3)-- 无模块遍历API(找到Kernel32.dll)_第1张图片


代码





#include "stdafx.h"
#include 




//#define CONTAINING_RECORD(address, type, field) ((type *)( (PCHAR)(address)-(ULONG_PTR)(&((type *)0)->field)))


typedef struct _UNICODE_STRING {
	USHORT  Length;
	USHORT  MaximumLength;
	PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;


typedef struct _PEB_LDR_DATA
{
	DWORD Length;
	UCHAR Initialized;
	PVOID SsHandle;
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList;
	PVOID EntryInProgress;
}PEB_LDR_DATA, *PPEB_LDR_DATA;


typedef struct _LDR_DATA_TABLE_ENTRY
{
	LIST_ENTRY InLoadOrderLinks;
	LIST_ENTRY InMemoryOrderLinks;
	LIST_ENTRY InInitializationOrderLinks;
	PVOID DllBase;
	PVOID EntryPoint;
	DWORD SizeOfImage;
	UNICODE_STRING FullDllName;
	UNICODE_STRING BaseDllName;
	DWORD Flags;
	WORD LoadCount;
	WORD TlsIndex;
	LIST_ENTRY HashLinks;
	PVOID SectionPointer;
	DWORD CheckSum;
	DWORD TimeDateStamp;
	PVOID LoadedImports;
	PVOID EntryPointActivationContext;
	PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;


typedef struct _PEB
{
	UCHAR InheritedAddressSpace;
	UCHAR ReadImageFileExecOptions;
	UCHAR BeingDebugged;
	UCHAR SpareBool;
	PVOID Mutant;
	PVOID ImageBaseAddress;
	PPEB_LDR_DATA Ldr;
}PEB, *PPEB;


int main(void)
{
	PLDR_DATA_TABLE_ENTRY pLdrDataEntry = NULL;
	PLIST_ENTRY pListEntryStart = NULL, pListEntryEnd = NULL;
	PPEB_LDR_DATA pPebLdrData = NULL;
	PPEB pPeb = NULL;


	__asm
	{
		//1、通过fs:[30h]获取当前进程的_PEB结构  
		mov eax, dword ptr fs : [30h];
		mov pPeb, eax
	}


	//2、通过_PEB的Ldr成员获取_PEB_LDR_DATA结构  
	pPebLdrData = pPeb->Ldr;


	//3、通过_PEB_LDR_DATA的InMemoryOrderModuleList成员获取_LIST_ENTRY结构  
	pListEntryStart = pListEntryEnd = pPebLdrData->InMemoryOrderModuleList.Flink;


	//查找所有已载入到内存中的模块  
	do
	{
		//4、通过_LIST_ENTRY的Flink成员获取_LDR_DATA_TABLE_ENTRY结构  
		// CONTAINING_RECORD宏 根据结构体中的某成员的地址来推算出该结构体整体的地址!
		pLdrDataEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(pListEntryStart, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);


		//5、输出_LDR_DATA_TABLE_ENTRY的BaseDllName或FullDllName成员信息  
		printf("%S\n", pLdrDataEntry->FullDllName.Buffer);


		pListEntryStart = pListEntryStart->Flink;


	} while (pListEntryStart != pListEntryEnd);


	getchar();
}


效果如下图:

逆向总结(3)-- 无模块遍历API(找到Kernel32.dll)_第2张图片



参考文档:

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

你可能感兴趣的:(逆向,破解,病毒)