以下代码在Windows Vista 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;
}
EDIT2:不,我不是在使用DWORD。
答案 0 :(得分:1)
访问冲突意味着您可能尝试取消引用lpszNames
数组中的空指针。
lpszNames[dwIndex]
正在返回char *
,可能并未指向有效数据。
您能否验证lpszNames[dwIndex]
不返回null?
实际上,它甚至可能不必为空,它可能只是一个在“受保护”内存中定义的地址。
答案 1 :(得分:0)
pNtHeaders = ((IMAGE_NT_HEADERS *)((DWORD)pBaseAddr + pDosHeader->e_lfanew));
if(pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
return NULL;
您正在投射指向DWORD
的指针。这在64位系统上是不安全的,其中DWORD
是指针大小的一半。我不确定这是否是你问题的根源,但它绝对不安全。
答案 2 :(得分:0)
void GetFuncAddr(HMODULE hBaseAddr, char *pFuncName)
{
unsigned int count = 1;
IMAGE_DOS_HEADER *pDosHeader;
IMAGE_NT_HEADERS *pNtHeaders;
IMAGE_OPTIONAL_HEADER *pOptionalHeader;
IMAGE_DATA_DIRECTORY *pDataDirectory;
IMAGE_pExpORT_DIRECTORY *pExp;
ULONG * addrofnames;
char *funcname;
ULONG *funcaddr;
pDosHeader = (IMAGE_DOS_HEADER *)hBaseAddr;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return NULL;
}
pNtHeaders = (IMAGE_NT_HEADERS *)(((BYTE *)pDosHeader) + pDosHeader->e_lfanew);
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
return NULL;
}
pOptionalHeader = &pNtHeaders->pOptionalHeader;
pDataDirectory = &pOptionalHeader->pDataDirectory[IMAGE_DIRECTORY_ENTRY_pExpORT];
pExp = (IMAGE_pExpORT_DIRECTORY *)((size_t)pDosHeader + pDataDirectory->VirtualAddress);
addrofnames = (ULONG *)((BYTE*) hBaseAddr + pExp->addrofnames);
funcaddr = (ULONG*) ((BYTE*) hBaseAddr + pExp->AddressOfFunctions);
for(count = 0; count < pExp->NumberOfNames; count++)
{
funcname = (char*)((BYTE*) hBaseAddr + addrofnames[count]);
if(strcmp(funcname, pFuncName) == 0)
{
return (void*)((BYTE*) hBaseAddr + funcaddr[count]);
}
}
return NULL;
}