[C++][PEB][ASM]硬幹取得指定函數的內存地址、透過PEB枚舉獲取指定內存地址之函數名稱

這篇是個人筆記啦XD
基本上就是因為網路上要找到寫這種奇怪的東西,實在找不到
所以就去網路上東抓西抓然後改一改弄出來的東西了

首先是
透過指定模組取得函數名稱的地址(其實就是GetProcAddress API的功能啦)

DWORD GetFuncAddr(HMODULE hModule,char* FuncName)
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
PIMAGE_EXPORT_DIRECTORY pExportDirectory;
HMODULE hModuleBase = hModule;
pDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)hModuleBase + pDosHeader->e_lfanew);
pExportDirectory = PIMAGE_EXPORT_DIRECTORY(pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress + (PBYTE)hModuleBase);
PDWORD pAddressName = PDWORD((PBYTE)hModuleBase+pExportDirectory->AddressOfNames); //函数名称表指针
PWORD pAddressOfNameOrdinals = (PWORD)((PBYTE)hModuleBase+pExportDirectory->AddressOfNameOrdinals); //函数名称序号表指针
PDWORD pAddresOfFunction = (PDWORD)((PBYTE)hModuleBase+pExportDirectory->AddressOfFunctions); //函数地址表指针
 for (int index = 0; index < (pExportDirectory->NumberOfNames); index++)
 {
  PCHAR pFunc = (PCHAR)((long)hModuleBase + *pAddressName);
  pAddressName ++ ;
  if (!strcmp(pFunc, FuncName)) return (DWORD)( (PBYTE)hModuleBase + pAddresOfFunction[*pAddressOfNameOrdinals]);
  pAddressOfNameOrdinals++;//ENT和函数名序号数组两个并行数组同时滑动指针(序号数组中的序号就对应函数名对应的函数地址的数组索引)
 }
 return (NULL);
}
再來就是
網路上找不太到該怎麼實做的
"從指定函數地址取得函數名稱"(應該說是GetProcAddress的反函數吧?)
實際做法其實就是把上面的暴力枚舉模組的API反過來檢測而已
AnsiString GetFuncName(HMODULE hModule,DWORD FuncAddr)
{
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNtHeader;
PIMAGE_EXPORT_DIRECTORY pExportDirectory;
HMODULE hModuleBase = hModule;
pDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)hModuleBase + pDosHeader->e_lfanew);
pExportDirectory = PIMAGE_EXPORT_DIRECTORY(pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress + (PBYTE)hModuleBase);
PDWORD pAddressName = PDWORD((PBYTE)hModuleBase+pExportDirectory->AddressOfNames); //函数名称表指针
PWORD pAddressOfNameOrdinals = (PWORD)((PBYTE)hModuleBase+pExportDirectory->AddressOfNameOrdinals); //函数名称序号表指针
PDWORD pAddresOfFunction = (PDWORD)((PBYTE)hModuleBase+pExportDirectory->AddressOfFunctions); //函数地址表指针
 for (int index = 0; index < (pExportDirectory->NumberOfNames); index++)
 {
  PCHAR pFunc = (PCHAR)((long)hModuleBase + *pAddressName);
  pAddressName ++ ;
  DWORD CurrentFuncAddr = ( (DWORD)hModuleBase + pAddresOfFunction[*pAddressOfNameOrdinals]) ;
  if ( !(CurrentFuncAddr - FuncAddr) )
  {
   return pFunc;
  }
  pAddressOfNameOrdinals++;
 }
 return ("");
}
最後就是
萬一如果知道內存地址但是不知道它在哪個模組上的時候
 要馬可以透過VirtualQueryEx取得模組基址
但要是VirtualQueryEx沒辦法取得的時候就得透過PEB表暴力列舉所有模組然後去搜索
AnsiString EnumGetFuncName(DWORD FuncAddr)
{
 MEMORY_BASIC_INFORMATION mbi;
 VirtualQueryEx((void*)-1,(void *)FuncAddr,&mbi,sizeof(MEMORY_BASIC_INFORMATION));
 if (mbi.BaseAddress && mbi.AllocationBase) return (GetFuncName((HMODULE)mbi.AllocationBase ,FuncAddr));
 void *PEB = NULL,
 *Ldr = NULL,
 *Flink = NULL,
 *p = NULL,
 *BaseAddress = NULL,
 *FullDllName = NULL;
 asm
 {
  mov eax,fs:[0x30]
  mov PEB,eax
 }
 Ldr = *( ( void ** )( ( unsigned char * )PEB+0x0c ) );
 Flink = *( ( void ** )( ( unsigned char * )Ldr+ 0x1c ) );
 p = Flink;
 do
 {
  BaseAddress = *( ( void ** )( ( unsigned char * )p+ 0x08 ) );
  FullDllName = *( ( void ** )( ( unsigned char * )p+ 0x18) );
  AnsiString CurrentFoundName = GetFuncName((HMODULE)BaseAddress,FuncAddr);
  if (CurrentFoundName != "") return CurrentFoundName ;
  p = *( ( void ** )p);
 }
 while ( Flink != p );
 return "";
}

留言

  1. And as it's an additive manufacturing process , is not a|there is not any} want to fret about any wastage. One of the many types of 3D printing that's used in the medical system area Shower Caps is bioprinting. Rather than printing utilizing plastic or steel, bioprinters use a computer-guided pipette to layer living cells, known as bio-ink, on high of each other} to create artificial living tissue in a laboratory.

    回覆刪除

張貼留言

這個網誌中的熱門文章

[Black Asia Arsenal] puzzCode: 專注開發後門的編譯器, 自帶反逆向、對抗病毒特徵碼定位技術

重建天堂之門:從 32 位元地獄一路打回天堂聖地(下)攻擊篇:x96 Shellcode、天堂聖杯 & 天堂注入器

[ASM][IDA][C++]爆破也能很優雅!純靜態爆破文件關鍵點+純靜態打Patch(IDA反組譯﹢打Patch)