问题
I'm trying to build a PE viewer in C++ and it seems to crash if i try to output the names of the libraries in the Import Directory Table. It seems that I am not getting the correct pointers for the DLLs that are used by the program.
HANDLE handle = CreateFile("messagebox.exe",GENERIC_READ,0,0,OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,0);
DWORD size = GetFileSize(handle,NULL);
PVOID virtualpointer = VirtualAlloc(NULL,size,MEM_COMMIT,PAGE_READWRITE);
state = ReadFile(handle,virtualpointer,size,&byteread,NULL);
CloseHandle(handle);
PIMAGE_NT_HEADERS ntheaders = PIMAGE_NT_HEADERS(PCHAR(vpointer) +
PIMAGE_DOS_HEADER(vpointer)->e_lfanew);
handle = GetCurrentProcess();
DWORD EntryAddr = ntheaders->OptionalHeader.ImageBase +
ntheaders->OptionalHeader.AddressOfEntryPoint;
DWORD importdir =
(DWORD) &(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]);
DWORD va = (DWORD)(ntheaders->OptionalHeader.ImageBase) +
((PIMAGE_DATA_DIRECTORY)dwValueB)->VirtualAddress;
LPSTR libname[128];
int i =0;
while(((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name)
{
// get DLL name
libname[i] = (LPSTR)(nt->OptionalHeader.ImageBase +
((PIMAGE_IMPORT_DESCRIPTOR)dwValueC)->Name);
i++;
}
回答1:
To read the names of the libraries in the Import Directory Table, you can do the following:
- Get the file's memory-mapped base address.
- Get pointer to IMAGE_NT_HEADERS structure.
Get pointer to IMAGE_SECTION_HEADER structure.
DataDirectory
is the final 128 bytes of OptionalHeader, which in turn is the final member of the PE header IMAGE_NT_HEADERS. The structure has 2 members which contain the location and size of the data structure.
If you want to look up information about the dll names, you first find the RVA (Relative Virtual Address) of theImport Directory
from theData Directory
, find that address in the raw section data and now you have an array ofIMAGE_IMPORT_DESCRIPTOR
. Get the member of this array that relates to mapped image by inspecting the strings pointed to by the Name fields.
I will not describe structure of Portable Executable File Format, but you can look at the following links:
Peering Inside the PE
Microsoft Systems Journal
Some variables in your code are not declared and this is confusing, but sticking to your skeleton code I wrote it so that it meets to your question.
DWORD Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh,PIMAGE_NT_HEADERS pnt);
int _tmain(int argc, _TCHAR* argv[])
{
LPCWSTR fNmae=L"C:\\Windows\\system32\\notepad.exe";
HANDLE handle=CreateFile(fNmae/*"messagebox.exe"*/, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
DWORD byteread,size=GetFileSize(handle, NULL);
PVOID virtualpointer=VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
ReadFile(handle, virtualpointer, size, &byteread, NULL);
CloseHandle(handle);
// Get pointer to NT header
PIMAGE_NT_HEADERS ntheaders=(PIMAGE_NT_HEADERS)(PCHAR(virtualpointer) + PIMAGE_DOS_HEADER(virtualpointer)-> e_lfanew);
PIMAGE_SECTION_HEADER pSech=IMAGE_FIRST_SECTION(ntheaders);//Pointer to first section header
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor; //Pointer to import descriptor
__try
{
if(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0)/*if size of the table is 0 - Import Table does not exist */
{
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD_PTR)virtualpointer +\
Rva2Offset(ntheaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress,pSech,ntheaders));
LPSTR libname[256];
size_t i=0;
// Walk until you reached an empty IMAGE_IMPORT_DESCRIPTOR
while(pImportDescriptor->Name != NULL)
{
printf("Library Name :");
//Get the name of each DLL
libname[i]=(PCHAR)((DWORD_PTR)virtualpointer + Rva2Offset(pImportDescriptor->Name,pSech,ntheaders));
printf("%s\n", libname[i]);
pImportDescriptor++; //advance to next IMAGE_IMPORT_DESCRIPTOR
i++;
}
}
else
{
printf("No Import Table!\n");
return 1;
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
if(EXCEPTION_ACCESS_VIOLATION == GetExceptionCode())
{
printf("Exception: EXCEPTION_ACCESS_VIOLATION\n");
return 1;
}
}
if(virtualpointer)
VirtualFree(virtualpointer, size, MEM_DECOMMIT);
return 0;
}
/*Convert Virtual Address to File Offset */
DWORD Rva2Offset(DWORD rva,PIMAGE_SECTION_HEADER psh,PIMAGE_NT_HEADERS pnt)
{
size_t i = 0;
PIMAGE_SECTION_HEADER pSeh;
if(rva == 0)
{
return (rva);
}
pSeh = psh;
for(i = 0; i < pnt->FileHeader.NumberOfSections; i++)
{
if(rva >= pSeh->VirtualAddress && rva < pSeh->VirtualAddress +
pSeh->Misc.VirtualSize)
{
break;
}
pSeh++;
}
return (rva - pSeh->VirtualAddress + pSeh->PointerToRawData);
}
来源:https://stackoverflow.com/questions/15960437/how-to-read-import-directory-table-in-c