黑基网 首页 学院 网络安全 查看内容

另一种枚举进程模块的方法

2009-7-6 09:01| 投稿: security

摘要:   在ntdll里有一张表,叫作LdrpHashTable,这张hash表中保存了进程已经的模块列表,函数GetModuleHandle就是通过查找这张句返回模块句柄的。  这张hash表也指向LDR...
  在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;  }
小编推荐:欲学习电脑技术、系统维护、网络管理、编程开发和安全攻防等高端IT技术,请 点击这里 注册黑基账号,公开课频道价值万元IT培训教程免费学,让您少走弯路、事半功倍,好工作升职加薪!



免责声明:本文由投稿者转载自互联网,版权归原作者所有,文中所述不代表本站观点,若有侵权或转载等不当之处请联系我们处理,让我们一起为维护良好的互联网秩序而努力!联系方式见网站首页右下角。


鲜花

握手

雷人

路过

鸡蛋

相关阅读

最新评论


新出炉

返回顶部