2014-10-28 88 views
1

我試圖在kernel32.dll中找到loadlibrary的RVA。我已經閱讀了一些解析PE頭文件的文檔,但我似乎無法找出爲什麼我的指向導出目錄的指針看起來無效。PIMAGE_EXPORT_DIRECTORY - 內存訪問錯誤

hFile = CreateFile(fileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); 
    if (hFile == INVALID_HANDLE_VALUE) 
    { 
     err = GetLastError(); 
     return err; 
    } 

    hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); 
    if (hFileMapping == 0) 
    { 
     err = GetLastError(); 
     CloseHandle(fileName); 
     return err; 
    } 

    lpFileBase = MapViewOfFile(hFileMapping, FILE_MAP_READ, 0, 0, 0); 
    if (lpFileBase == 0) 
    { 
     err = GetLastError(); 
     CloseHandle(fileName); 
     CloseHandle(hFileMapping); 
     return err; 
    } 

    dosHeader = (PIMAGE_DOS_HEADER)lpFileBase; 
    pNTHeader = (PIMAGE_NT_HEADERS)((BYTE*)dosHeader + dosHeader->e_lfanew); 
    base = (DWORD64)dosHeader; 

在這裏我打開文件,一切似乎都很好,當我在這裏用調試器運行。

exportsStartRVA = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; 
    exportsEndRVA = exportsStartRVA + pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; 

在這裏,我成功訪問DataDirectory以獲取VirtualAddress和導出目錄的大小。

PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader); 
unsigned i; 
for (i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++) 
{ 
    // Is the RVA within this section? 
    if ((exportsStartRVA >= section->VirtualAddress) && 
     (exportsStartRVA < (section->VirtualAddress + section->Misc.VirtualSize))) 
     break; 
} 

我會遍歷所有部分,直到我得到一個包含exportsStartRVA的節標題。現在是「section」指向導出目錄的Section Header的指針。

exportDir = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)base + exportsStartRVA + section->PointerToRawData - section->VirtualAddress); 

這裏我得到一個指向導出目錄的指針。

PDWORD pfunctions = (PDWORD)((PBYTE)base + (DWORD64)exportDir->AddressOfFunctions + header->PointerToRawData - header->VirtualAddress); 
PDWORD ordinals = (PDWORD)((PBYTE)base + (DWORD64)exportDir->AddressOfNameOrdinals + header->PointerToRawData - header->VirtualAddress); 
PSTR* name = (PSTR*)((PBYTE)base + (DWORD64)exportDir->AddressOfNames + header->PointerToRawData - header->VirtualAddress); 
PSTR funcName; 

for (unsigned i = 0; i < (DWORD64)exportDir->NumberOfNames; i++) 
{ 
    funcName = name[i]; 
} 

編輯:問題在於我解引用我覺得內,同樣,funcname實際上並沒有給我比一個內存訪問錯誤的任何其他。

+0

對於什麼是值得的,乍一看你的邏輯對我來說看起來沒問題。你有沒有嘗試解引用導出目錄中的任何指針,看看是否讓你到任何看起來有效的地方? – 2014-10-29 19:56:13

+0

我在上面添加了一段代碼。 funcName始終是「地址處的內存讀取錯誤」。我想我的解引用可能有問題。我只是認爲exportDir是錯誤的,因爲WinDBG給我「內存訪問錯誤」 – Informat 2014-10-29 20:56:46

+0

是的,指向ExportDir的指針工作,它只是不從內存訪問錯誤更新,直到我真的從它讀取我的壞。所以問題在於我的解除引用。我會更新這個。 – Informat 2014-10-29 21:11:32

回答

1

AddressOfNames是一個RVA列表的RVA,用於將不是RVA的字符串名稱串到字符串列表中。