« 大放血,一种新的加载驱动方法非完整爆光Microsoft DirectShow MPEG2TuneRequest Stack Overflow Exploit »

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

在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;
}

 

 完整代码:GetModuleListByHashTable.rar

测试程序:GetModuleListByHashTableEXE.rar 大约支持Win2K XP Vista

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

日历

最新评论及回复

最近发表

Powered By Z-Blog 2.0 bate Build Theme by toboku

Copyright langouster. Some Rights Reserved.   苏ICP备06046736号