下面这段代码在WindowsVista x64上导致了一个异常,我不明白为什么。

size_t pBaseAddr;
char *lpszFuncName;
IMAGE_EXPORT_DIRECTORY *pExportDir;
const char **lpszNames;
unsigned int dwIndex;

lpszNames  = ((const char **)(pBaseAddr + pExportDir->AddressOfNames));
if(lpszNames == NULL)
  return NULL;

for(dwIndex = 0; dwIndex < pExportDir->NumberOfFunctions; dwIndex++)
{
   if(strcmp((char *)(pBaseAddr + lpszNames[dwIndex]), lpszFuncName) == 0)
       return Something;
}

我认为问题出在strcmp()行,特别是lpszNames[dwIndex]上。它在32位上工作,但在64位上由于访问冲突而崩溃。
如果你想看到整个代码check my previous question
编辑:由于人们没有看到我在问题上发布的链接,我将发布原始问题的全部代码。
// Retrieve NT header from base address.
IMAGE_NT_HEADERS *GetNtHeaderFromBase( void *pBaseAddr )
{
 IMAGE_DOS_HEADER       *pDosHeader;
 IMAGE_NT_HEADERS       *pNtHeaders;

 pDosHeader = ((IMAGE_DOS_HEADER *)pBaseAddr);
 if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
  return NULL;

 pNtHeaders = ((IMAGE_NT_HEADERS *)((DWORD)pBaseAddr + pDosHeader->e_lfanew));
 if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
  return NULL;

 return ((pNtHeaders == NULL) ? NULL : pNtHeaders);
}


// This emulates GetProcAddress.
void *GetFuncAddr( size_t pBaseAddr, char *lpszFuncName )
{
 IMAGE_NT_HEADERS       *pNtHeaders;
 IMAGE_DATA_DIRECTORY   *pDataDir;
 IMAGE_EXPORT_DIRECTORY *pExportDir;
 const char      **lpszNames;
 size_t       *lpdwFuncs, dwIndex;

 pNtHeaders = GetNtHeaderFromBase((void *)pBaseAddr);
 if(pNtHeaders == NULL)
  return NULL;

 pDataDir = ((IMAGE_DATA_DIRECTORY *)(pNtHeaders->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_EXPORT));
 if(pDataDir == NULL)
  return NULL;

 pExportDir = ((IMAGE_EXPORT_DIRECTORY *)(pBaseAddr + pDataDir->VirtualAddress));
 if(pExportDir == NULL)
  return NULL;

 lpdwFuncs  = ((size_t *)(pBaseAddr + pExportDir->AddressOfFunctions));
 lpszNames  = ((const char **)(pBaseAddr + pExportDir->AddressOfNames));
 if(lpdwFuncs == NULL || lpszNames == NULL)
  return NULL;

 for(dwIndex = 0; dwIndex < pExportDir->NumberOfFunctions; dwIndex++)
 {
  // decrypt funcname and get the address
  if(strcmp((char *)(pBaseAddr + lpszNames[dwIndex]), lpszFuncName) == 0)
   return (void*)(pBaseAddr + lpdwFuncs[dwIndex]);
 }

 return NULL;
}

编辑2:不,我没有用德沃德。

最佳答案

访问冲突意味着您可能试图取消引用lpszNames数组中的空指针。
lpszNames[dwIndex]正在返回一个可能没有指向有效数据的char *
能否验证lpszNames[dwIndex]不返回空值?
实际上,它甚至可能不必为空,它可能只是在“受保护”内存中定义的地址。

10-08 00:44