首页
社区
课程
招聘
[原创]符号表获取内核未导出函数地址
发表于: 2014-6-9 22:15 16441

[原创]符号表获取内核未导出函数地址

2014-6-9 22:15
16441
  在看v校分享的代码的时候,看到他的NtQueueApcThread没有从r3传,而是从ssdt获取,代码里面另外的两个函数是查符号表得到的。我就在想能不能从r3获取也一起传。查了好久的api,就是弄不懂到底说的啥意思,后来发现SymLoadModuleEx是比较关键的。
  大体的思路是通过NtQuerySystemInformation获得内核基地址ModuleBase。SymInitializeW设置一下符号表地址。然后把内核模块当做dll加载一次,不过使用DONT_RESOLVE_DLL_REFERENCES标记,别让内核执行。然后调用SymLoadModuleEx再加载一次得到了第一次的基地址DllBase,估计这个函数内部调用LoadLiabrary,不过发现已经加载就只是增加计数值了。然后用SymFromNameW得到查找函数的地址。不过得加上ModuleBase-DllBase,就是相应函数的地址了。之后就是SymCleanup和FreeLibrary。
  不过有个问题是,我用的符号表是从windbg下载的里面找的,符号表是ntkrpamp.pdb,但是内核确实ntkrnlpa.exe。不知道为何,反正windbg能用ntkrpamp.pdb解析ntkrnlpa.exe
  代码只是测试一下,用v校代码改的,和我一样的菜鸟可以改一改用用,高手请飘过。
  
PVOID SymGetProcAddressKernel(LPCWSTR szApiName)
{
	PSYSTEM_MODULE_INFORMATION SystemInfo;
	BOOL bFind =FALSE;
	DWORD dwBufferSize;
	WCHAR *wszKernels[]={
		L"ntoskrnl",// - 单处理器,不支持PAE
		L"ntkrnlpa",// - 单处理器,支持PAE
		L"ntkrnlmp",// - 多处理器,不支持PAE
		L"ntkrpamp"// - 多处理器,支持PAE
	};
	DWORD i;
	BYTE memory[0x2000];
	ZeroMemory(memory, sizeof(memory));
	SYMBOL_INFOW * info = (SYMBOL_INFOW *)memory;
	HMODULE hDll;
	WCHAR wcsPdb[MAX_PATH]={0};
	WCHAR wcsExe[MAX_PATH]={0};
	PCHAR Ptr,Last;
	PWCHAR PathPtr;
	WCHAR path[MAX_PATH] = { 0 };
	WCHAR wcsImageName[MAX_PATH] = {0};

	NtQuerySystemInformation((SYSTEMINFOCLASS)11,0,0,&dwBufferSize);
	SystemInfo = (PSYSTEM_MODULE_INFORMATION)malloc(dwBufferSize);
	NtQuerySystemInformation((SYSTEMINFOCLASS)11,SystemInfo,dwBufferSize,0);
	Ptr = (PCHAR)SystemInfo->aSM[0].ImageName + strlen(SystemInfo->aSM[0].ImageName)-1;
	Last = Ptr;
	while(*Ptr){
		if(*Ptr == '\\'){
			Last = Ptr+1;
			break;
		}
		Ptr --;
	}
	MultiByteToWideChar(CP_ACP,
		0,
		Last,
		-1,
		wcsImageName,
		sizeof(wcsImageName)); 
	for(i=0;i<4;i++){
		if(!wcsnicmp(wszKernels[i],wcsImageName,wcslen(wszKernels[i]))){
			bFind =TRUE;
			break;
		}
	}
	DWORD ret=0;
	if(bFind){
		wcscpy(wcsPdb,L"ntkrpamp.pdb");
		wcscpy(wcsExe,wszKernels[i]);
		wcscat(wcsExe,L".exe");
		GetModuleFileNameW(0, path, _countof(path));
		PathPtr= path+wcslen(path);
		while(*PathPtr!='\\')
			PathPtr--;
		*PathPtr =L'\0';


		if (!SymInitializeW(GetCurrentProcess(),path, TRUE)){
			return NULL;
		}

		hDll = LoadLibraryExW(wcsImageName,NULL,DONT_RESOLVE_DLL_REFERENCES);
		printf("%s:基地址%x\n",(DWORD)SystemInfo->aSM[0].ImageName,(PCHAR)SystemInfo->aSM[0].Base);
		SymLoadModuleExW(GetCurrentProcess(),NULL,wszKernels[i],0,(DWORD)hDll,0,0,0);
		info->SizeOfStruct = sizeof(SYMBOL_INFOW);
		info->MaxNameLen = MAX_SYM_NAME;
		SymFromNameW(GetCurrentProcess(),szApiName,info);
		ret =(DWORD)info->Address - (DWORD)hDll+(DWORD)SystemInfo->aSM[0].Base;
		FreeLibrary(hDll);
		SymCleanup(GetCurrentProcess());	
	}
	return (PVOID)ret;
}


  记得印象最深的就是别用Release版调试,各种错误,比如内部变量会显示不出来。还是要用Debug版本调试。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
  • 1.jpg (62.50kb,17次下载)
收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 18
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
楼主也在研究dbghelp?我们一起研究吧看了你代码,觉得没啥问题啊
2014-6-9 23:43
0
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
3
LZ 看下你内核文件 ntkrnlpa.exe 属性中的原始文件名是啥
2014-6-10 06:43
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
原始文件名是ntkrpamp.exe,原来是改了名字。
2014-6-10 09:58
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
没有研究,只是在学习别人的代码。
2014-6-10 09:59
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
还是有问题。NtQueueApcThread还是找不出来,每次都是先找ntdll里面的,而且又不能根据ntoskrnl.exe导出表找,因为不导出。还没有解决问题。只是试了一下其他函数。
2014-6-10 11:32
0
雪    币: 14
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
楼主能不能把源码分享下,我这怎么试都有问题
2014-10-24 22:20
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
代码有问题,有的函数是查不到的的。查pdb吧。我记得别的帖子放了查pdb的代码,你把vs2010自带的代码改抄几句就能查了,我住的位置没电脑,很久没搞这个了。
2014-10-24 22:30
0
雪    币: 230
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
没事啊。我按照你那个自己用DELPHI 写了个能获取啊!!

上传的附件:
2014-10-25 21:28
0
雪    币: 135
活跃值: (63)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
10
[QUOTE=honffx;1326144]没事啊。我按照你那个自己用DELPHI 写了个能获取啊!!
[/QUOTE]会有错误的,我记得queueapc那个就出错,原因忘了。查pdb吧。
2014-10-25 21:56
0
雪    币: 230
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
if (!SymInitializeW(GetCurrentProcess(),path, false))  <<就可以了
2014-10-25 22:07
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
fatecaster 没有研究,只是在学习别人的代码。
确实是这个问题,获取的函数地址是错误的,是ntdll里面的了
2022-6-25 05:57
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
问题我解决了 你这个SymLoadModuleEx的参数没传对
2022-6-25 22:21
0
游客
登录 | 注册 方可回帖
返回
//