| 关键词: nbsp ENTRY LdrpHashTable dwMinorVersion dwMajorVersion hProcess pDllFullPath pTemp LIST LdrDataEntry |
在ntdll里有一张表,叫作LdrpHashTable,这张hash表中保存了进程已经的模块列表,函数GetModuleHandle就是通过查找这张句返回模块句柄的。 这张hash表也指向LDR_DATA_TABLE_ENTRY,作为HashLinks字段: typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; LIST_ENTRY InInitializationOrderLinks; PVOID DllBase; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; USHORT LoadCount; USHORT TlsIndex; union { LIST_ENTRY HashLinks; struct { PVOID SectionPointer; ULONG CheckSum; }; }; union { ULONG TimeDateStamp; PVOID LoadedImports; }; PVOID EntryPointActivationContext; PVOID PatchInformation; } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; 当然这张表的内容也可以被抹掉,但是那个模块就不能使用函数GetModuleHandle了。此方法对直接Map Dll dump文件的方法无效。另外使用此方法在定位表时可能需要一些特征搜索,硬编码啊。。。。 关键代码: //LdrpHashTable LIST_ENTRY *GetHashTableAddress() { HANDLE hModule=GetModuleHandle("ntdll.dll"); BYTE *p=NULL; LIST_ENTRY *retval; CONST BYTE *pSign=NULL; DWORD SignLen; DWORD dwVersion,dwMajorVersion,dwMinorVersion; dwVersion=GetVersion(); dwMajorVersion= LOBYTE(LOWORD(dwVersion)); dwMinorVersion= HIBYTE(LOWORD(dwVersion)); if(dwMajorVersion==5 && dwMinorVersion==0)//2k { pSign=(CONST BYTE *)"\x89\x01\x89\x56\x40\x89\x0a\x89\x48\x04\x8b\x4f\x10\x8d\x47\x0c"; SignLen=16; } else if(dwMajorVersion==5 && dwMinorVersion==1)//xp { pSign=(CONST BYTE *)"\x8B\x48\x04\x89\x07\x89\x4F\x04\x89\x39\x89"; SignLen=11; } else if(dwMajorVersion==6 && dwMinorVersion==0)//vista { pSign=(CONST BYTE *)"\x89\x45\x88\x8b\x18\x3b\xd8"; SignLen=7; } else { printf("不支持的系统"); return NULL; } //__asm{int 3} __try { for(DWORD i=0;i<0x70000;i++) { if(memcmp((BYTE *)hModule+i,pSign,SignLen)==0) { p=(BYTE *)hModule+i-4; retval=(LIST_ENTRY *)(*(DWORD *)p); if((ULONG)retval>(ULONG)hModule && (ULONG)retval<0x80000000) break; else retval=NULL; } } } __except(EXCEPTION_EXECUTE_HANDLER) {} return retval; } void PrintDll(HANDLE hProcess,LIST_ENTRY *LdrpHashTable) { LIST_ENTRY *LdrpHashTableTemp=NULL,*pListEntry,*pListHead; UNICODE_STRING *pDllFullPath; void *pTemp; DWORD size; LDR_DATA_TABLE_ENTRY LdrDataEntry; size=sizeof(LIST_ENTRY)*32; pTemp=malloc(size); //读Hash表 if(!ReadProcessMemory(hProcess,LdrpHashTable,pTemp,size,&size)) goto END; LdrpHashTableTemp=(LIST_ENTRY *)pTemp; for(DWORD i=0;i<32;i++) { pListEntry=LdrpHashTableTemp+i; pListEntry=pListEntry->Flink; pListHead=LdrpHashTable+i; while(pListEntry!=pListHead) { size=sizeof(LIST_ENTRY); pTemp=malloc(size); if(!ReadProcessMemory(hProcess,(BYTE *)pListEntry -0x3c,&LdrDataEntry,sizeof(LdrDataEntry),&size)) goto END; //读模块路径保存在pTemp中 pDllFullPath=&LdrDataEntry.FullDllName; pTemp=malloc(pDllFullPath->MaximumLength); memset(pTemp,0,pDllFullPath->MaximumLength); if(!ReadProcessMemory(hProcess,pDllFullPath->Buffer,pTemp,pDllFullPath->Length,&size)) goto END; wprintf(L"%ws \n",pTemp); free(pTemp); pListEntry=LdrDataEntry.HashLinks.Flink; } } END: if(!LdrpHashTableTemp) free(LdrpHashTableTemp); } int _tmain(int argc, _TCHAR* argv[]) { LIST_ENTRY *LdrpHashTable; HANDLE hProcess; DWORD Pid; LdrpHashTable=GetHashTableAddress(); if(!LdrpHashTable) { printf("找不到Hash表"); getchar(); return 0; } printf("输入进程ID:"); scanf("%d",&Pid); hProcess=OpenProcess(PROCESS_VM_READ,FALSE,Pid); if(hProcess==NULL) { printf("打开进程出错"); getchar(); return 0; } PrintDll(hProcess,LdrpHashTable); return 0; } |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|