能力值:
( LV4,RANK:45 )
|
-
-
2 楼
查了下资料有点傻眼了。。
解析pdb文件得到未导出变量地址
对应驱动应该如何写 傻眼中
http://hi.baidu.com/sumcogito/blog/item/03e5685525114b58574e0052.html
程序要用到dbghelp.dll中的一些函数
http://msdn.microsoft.com/en-us/library/ms679291%28VS.85%29.aspx
要自己下载系统对应的符号文件
首先是一些初始化的东西:
设置符号选项,调用下面两个函数
DWORD Options = SymGetOptions();
Options = Options|SYMOPT_DEBUG;
SymSetOptions(Options);
调用SymInitialize函数进行初始化(这是必须的)
hProcess = GetCurrentProcess();
BOOL bRet = SymInitialize(hProcess,0,FALSE);
if(!bRet)
{
printf("SymInitialize error ...\n");
}
可以用函数SymSetSearchPath(hProcess,SymbolPath);设置符号搜索路径
然后用SymLoadModule64加载模块,这里是ntoskrnl.exe
char FileName[256] ;
GetSystemDirectory(FileName,sizeof(FileName));
strcat(FileName,"\\ntoskrnl.exe");
BaseOfDll = SymLoadModule64(hProcess,NULL,FileName,NULL,0,0);
BaseOfDll返回加载的基址
然后就可以调用SymEnumSymbols查询符号了
SymEnumSymbols(hProcess,BaseOfDll,0,EnumSymCallBack,0);
参数EnumSymCallBack是一个回调函数,在里面得到未导出函数的VA,
BOOL CALLBACK EnumSymCallBack(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext)
/*
参数pSymInfo结构Name成员是符号名,Address是符号地址(The virtual address of the start of the symbol)
*/
{
if(strcmp((pSymInfo->Name), "PspCreateProcessNotifyRoutine")==0)
{
printf("Oh,yeah! %s :%0x\n",pSymInfo->Name,pSymInfo->Address);
}
return TRUE;
}
完整代码:
[code]
#include <stdio.h>
#include <windows.h>
#include "dbghelp.h"
#pragma comment(lib,"dbghelp.lib")
BOOL CALLBACK EnumSymCallBack(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext);
int main(int argc, char* argv[])
{
HANDLE hProcess;
DWORD64 BaseOfDll;
PIMAGEHLP_SYMBOL pSymbol = NULL;
DWORD Options = SymGetOptions();
Options = Options|SYMOPT_DEBUG;
SymSetOptions(Options);
hProcess = GetCurrentProcess();
BOOL bRet = SymInitialize(hProcess,0,FALSE);
if(!bRet)
{
printf("SymInitialize error ...\n");
}
char SymbolPath[256];
GetCurrentDirectory(sizeof(SymbolPath),SymbolPath);
strcat(SymbolPath,"\\symbols");
SymSetSearchPath(hProcess,SymbolPath);
char FileName[256] ;
GetSystemDirectory(FileName,sizeof(FileName));
strcat(FileName,"\\ntoskrnl.exe");
BaseOfDll = SymLoadModule64(hProcess,NULL,FileName,NULL,0,0);
if(BaseOfDll == 0)
{
DWORD nErr = GetLastError();
}
SymEnumSymbols(hProcess,BaseOfDll,0,EnumSymCallBack,0);
SymUnloadModule64(hProcess,BaseOfDll);
SymCleanup(hProcess);
for(;;);
return 0;
}
BOOL CALLBACK EnumSymCallBack(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext)
{
if(strcmp((pSymInfo->Name), "PspCreateProcessNotifyRoutine")==0)
{
printf("Oh,yeah! %s :%0x\n",pSymInfo->Name,pSymInfo->Address);
}
if(strcmp((pSymInfo->Name), "PspLoadImageNotifyRoutine")==0)
{
printf("Oh,yeah! %s :%0x\n",pSymInfo->Name,pSymInfo->Address);
}
if(strcmp((pSymInfo->Name), "PspCreateThreadNotifyRoutine")==0)
{
printf("Oh,yeah! %s :%0x\n",pSymInfo->Name,pSymInfo->Address);
}
if(strcmp((pSymInfo->Name), "CmpCallBackVector")==0)
{
printf("Oh,yeah! %s :%0x\n",pSymInfo->Name,pSymInfo->Address);
}
if(strcmp((pSymInfo->Name), "KeBugCheckCallBackListHead")==0)
{
printf("Oh,yeah! %s :%0x\n",pSymInfo->Name,pSymInfo->Address);
}
return TRUE;
}
|
能力值:
( LV4,RANK:45 )
|
-
-
3 楼
*******
|
能力值:
( LV4,RANK:45 )
|
-
-
4 楼
做个记录 找到一个方法
http://bbs.pediy.com/showthread.php?t=74411
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
虽然ntoskrnl.exe没有导出NtWriteVirtualMemory函数,但ntdll.dll导出了这个函数,我们可以通过ntdll.dll来获取NtWriteVirtualMemory的地址,继而获取SSDT表中NtWriteVirtualMemory的序号, 具体看代码吧,不是原创,在原创的基础上小改了一下,希望对LZ有用。
//加载DLL文件镜像,返回DLL的基地址
NTSTATUS CreateDllSection(IN IN PUNICODE_STRING pDllName, OUT PHANDLE pSection, OUT PPVOID pBaseAddress)
{
HANDLE hFile;
OBJECT_ATTRIBUTES oa = {sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE};
IO_STATUS_BLOCK iosb;
SIZE_T size=0;
NTSTATUS status;
ASSERT(pSection&&pBaseAddress);
*pBaseAddress = NULL;
status = ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
if (NT_SUCCESS(status)) {
oa.ObjectName = 0;
status = ZwCreateSection(pSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, SEC_IMAGE, hFile);
if (NT_SUCCESS(status)) {
status = ZwMapViewOfSection(*pSection, ZwCurrentProcess(), pBaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE);
if (!NT_SUCCESS(status)) {
ZwClose(*pSection);
}
}
ZwClose(hFile);
}
return status;
}
//通过函数名和DLL的基地址查找函数地址
PVOID GetSectionDllFuncAddr(IN PCHAR lpFunctionName, IN PVOID BaseAddress)
{
PVOID functionAddress = NULL;
PIMAGE_DOS_HEADER dosheader;
PIMAGE_OPTIONAL_HEADER opthdr;
PIMAGE_EXPORT_DIRECTORY pExportTable;
PDWORD arrayOfFunctionAddresses;
PDWORD arrayOfFunctionNames;
PWORD arrayOfFunctionOrdinals;
DWORD Base;
STRING ntFunctionName, ntFunctionNameSearch;
PCHAR functionName;
DWORD functionOrdinal;
ULONG x;
ASSERT(lpFunctionName&&BaseAddress);
dosheader = (PIMAGE_DOS_HEADER)BaseAddress;
opthdr =(PIMAGE_OPTIONAL_HEADER) ((PBYTE)BaseAddress+dosheader->e_lfanew+24);
pExportTable =(PIMAGE_EXPORT_DIRECTORY)((PBYTE)BaseAddress + opthdr->DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT]. VirtualAddress);
// now we can get the exported functions, but note we convert from RVA to address
arrayOfFunctionAddresses = (PDWORD)( (PBYTE)BaseAddress + pExportTable->AddressOfFunctions);
arrayOfFunctionNames = (PDWORD)( (PBYTE)BaseAddress + pExportTable->AddressOfNames);
arrayOfFunctionOrdinals = (PWORD)( (PBYTE)BaseAddress + pExportTable->AddressOfNameOrdinals);
Base = pExportTable->Base;
RtlInitString(&ntFunctionNameSearch, lpFunctionName);
for (x = 0; x < pExportTable->NumberOfFunctions; x++) {
functionName = (PCHAR)( (PBYTE)BaseAddress + arrayOfFunctionNames[x]);
RtlInitString(&ntFunctionName, functionName);
functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1; // always need to add base, -1 as array counts from 0
// this is the funny bit. you would expect the function pointer to simply be arrayOfFunctionAddresses[x]...
// oh no... thats too simple. it is actually arrayOfFunctionAddresses[functionOrdinal]!!
if (RtlCompareString(&ntFunctionName, &ntFunctionNameSearch, TRUE) == 0) {
functionAddress = (PBYTE)BaseAddress + arrayOfFunctionAddresses[functionOrdinal];
break;
}
}
return functionAddress;
}
具体的函数用法为:
#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
#define HOOK_SSDTCALL_BY_ID(_Funcid, _Hook, _Orig ) (LONG)_Orig = InterlockedExchange((PLONG)&KeServiceDescriptorTable.ServiceTableBase[_Funcid], (LONG)_Hook)
NTSTATUS status;
UNICODE_STRING tmpStr;
HANDLE hSection;
PVOID ntdllBaseAddress;
//对于未导出函数,使用GetSectionDllFuncAddr函数获取其服务索引号(地址在用户态)
RtlInitUnicodeString(&tmpStr, L"[URL="file://\\SystemRoot\\System32\\ntdll.dll"]\\SystemRoot\\System32\\ntdll.dll[/URL]");
//加载DLL文件
status = CreateDllSection(&tmpStr, &hSection, &ntdllBaseAddress);
ASSERT(NT_SUCCESS(status));
//获取ZwWriteVirtualMemory函数地址
ZwWriteVirtualMemory = (ZWWRITEVIRTUALMEMORY)GetSectionDllFuncAddr("ZwWriteVirtualMemory", ntdllBaseAddress);
//获取ZwWriteVirtualMemory在SSDT中的序号
ZwWriteVirtualMemoryId = SYSCALL_INDEX(ZwWriteVirtualMemory);
KdPrint(("SYS:ZwWriteVirtualMemory's Id:%d\n", ZwWriteVirtualMemoryId));
//关闭DLL文件
ZwClose(hSection);
//HOOK ZwWriteVirtualMemoryId函数
HOOK_SSDTCALL_BY_ID(ZwWriteVirtualMemoryId, HookZwWriteVirtualMemory, RealZwWriteVirtualMemory);//HOOK ZwWriteVirtualMemory函数
这种方法在XP及更高版本的Windows系统都有效
|
能力值:
( LV4,RANK:45 )
|
-
-
6 楼
太感谢了
你既给了方法 又给了代码
虽然不知道能否使用
但是还是先给你kx奖励吧
难得有人这么热心
|