【Win内核】从TEB到模块遍历

最近逐步接触内核结构,有些感觉就是其实大体的都知道,但一到细节就gg。仔细想想,其实之前学的系统结构都是基于最早的,而当代的计算机结构是经历过n年优化了的结果,所以不能以管窥豹,对于内核的学习更是需要手动去实操。个人觉得可以自己去推导计算机的组件和发展流程,有益于你更深入的理解内核结构的设计,提高思维记忆

通过TEB遍历模块

主要的流程是全局变量-》TEB-》PEB-》LDR-》遍历LDR_ENTRY

  • 我是怎么知道TEB的地址呢?
    其实是3环的时候,FS:[0x18]默认就是存储TEB的指针;而0环的时候存储的数据有区别
#include "stdafx.h"
#include <windows.h>
#include <Ntsecapi.h>    //for unicode_string
typedef struct _PEB_LDR_DATA  
{
	ULONG Length;
	BOOLEAN Initialized;
	PVOID SsHandle; 
	LIST_ENTRY InLoadOrderModuleList;
	LIST_ENTRY InMemoryOrderModuleList;
	LIST_ENTRY InInitializationOrderModuleList; 
	PVOID EntryInProgress;
} PEB_LDR_DATA,*PPEB_LDR_DATA; 





int TebAddress;
int PebAddress;
int Ldr;

void GetAddress(){
	//获取Teb\Peb\Ldr的地址
	__asm{
		mov eax,fs:[0x18]
		mov TebAddress,eax
		mov eax,[eax+0x30]
		mov PebAddress,eax
		mov eax,[eax+0xc]
		mov Ldr,eax
	}
	printf("TebAddress:\t%08X\n",TebAddress);
	printf("PebAddress:\t%08X\n",PebAddress);
	printf("Ldr:\t\t%08X\n",Ldr);
}

void ShowModuleInfo(PLIST_ENTRY pEntry){
    BYTE * pBase = (BYTE *)pEntry;
    PUNICODE_STRING pUnicode = (PUNICODE_STRING)(pBase + sizeof(_LIST_ENTRY) + 
    sizeof(DWORD)* 3 + sizeof(UNICODE_STRING));
    
    printf("DllBase=%p EntryPoint=%p BaseDllName = %ws\n",    
            *(DWORD *)(pBase + sizeof(_LIST_ENTRY)),                        //DllBase
            *(DWORD *)(pBase + sizeof(_LIST_ENTRY) + sizeof(DWORD)),        //EntryPoint
            pUnicode->Buffer);                                                //BaseDllName

	printf("%08x-%08x\n",((PLIST_ENTRY)(pBase-0x10))->Flink,((PLIST_ENTRY)(pBase-0x10))->Blink);
	printf("%08x-%08x\n",((PLIST_ENTRY)(pBase-0x8))->Flink,((PLIST_ENTRY)(pBase-0x8))->Blink);
}

void GetInLoadOrderModuleList(){
	PPEB_LDR_DATA LdrF = (PPEB_LDR_DATA)Ldr;

	PLIST_ENTRY pFirst = LdrF->InInitializationOrderModuleList.Flink;
	PLIST_ENTRY pLast = LdrF->InInitializationOrderModuleList.Blink;

	while(pFirst!=pLast){		
		ShowModuleInfo(pFirst);
		Sleep(2000);
		pFirst = pFirst->Flink;
	}
	
}


int main(int argc, char* argv[])
{
GetAddress();

GetInLoadOrderModuleList();

getchar();
return 0;
}

相关的内核结构你们就自己查吧,正好提高你们的能力。

陷入的坑

最近其实搞这个搞了好久。最开始是想构造一个简单的shellcode,所以一开始就需要能遍历模块。但碍于刚接触,很多内核结构都不熟悉,所以一直没能成功。

主要还是对结构中的双向链表有误解。习惯性以为链表中的指针指向的就是节点的头部,但后面发现都只是指向List_ENTRY结构首部,也就是节点的中间部分。
但我还是有个疑问,这样的话,相当于三个圈,第三个,算了画个图描述下
【Win内核】从TEB到模块遍历

叫我灵魂画师

大概就是这个意思,也就是相当于三个环扣在LDR_DATA上。但我有个疑问,既然是一个链,为什么每个节点都有三个链孔,按道理一个不就已经足够了

M猜想

  • 猜想1:其他两个仅是结构需求,不用
    本来以为其他两个孔都是0,仅是因为结构设计,但好像又没那么简单。其他的两个链孔有值
    【Win内核】从TEB到模块遍历
  • 猜想2:难不成这是个套娃?下一个节点其实也有三个环???
    想想就头大,以后再搞。

如果有师傅会的,欢迎交流。

上一篇:Entry 组件


下一篇:2021-10-21