2010-06-04 7 views
10

Actualmente estoy escribiendo un analizador/cargador PE. He cargado correctamente el archivo PE en la memoria utilizando el archivo c estándar io, he recuperado los encabezados válidos de DOS y PE (el encabezado opcional) y obtengo acceso a las secciones PE. Mi próximo objetivo es obtener acceso a la tabla Exportar para recuperar los símbolos exportados. Para hacer esto, he utilizado el RVA almacenado en el conjunto de diccionario de datos de encabezados opcionales en el índice 0 (que creo que apunta a la tabla de exportación) y agregué esta dirección a la dirección del archivo PE cargado en la memoria del programa. en un encabezado válido de tabla de exportación. Estoy convirtiendo direcciones NULL y datos cuando hago esto. aquí hay un pequeño fragmento de código;Resolver RVA para importar y exportar tablas dentro de un archivo PE

// RVA from optional headers data dictionaries array cast to Export directory type 
    IMAGE_EXPORT_DIRECTORY* ied(
    (IMAGE_EXPORT_DIRECTORY*)((void*) 
    ((unsigned char*)buffer + ioh->DataDirectory[0].VirtualAddress))); 

¿Tengo que usar memoria IO asignada para hacer esto correctamente? ¿Estoy calculando la dirección incorrecta? La información sobre PE RVA parece escasa. gracias de antemano.

+0

El conjunto de artículos señaló en este SO respuesta podría ser de ayuda: http://stackoverflow.com/questions/2307754/within-a-dll-how-is-the-function-table-structured/2307850#2307850 –

Respuesta

0

No todas las imágenes PE tendrán una tabla de directorio de exportación. Debe verificar el campo "NumberOfRvaAndSizes" específico del Windows del encabezado opcional. Si es menor o igual a IMAGE_DIRECTORY_ENTRY_EXPORT (0), entonces no hay una tabla de directorio de exportación (es decir, no hay nada válido ubicado en ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]). Para obtener un ejemplo, consulte la respuesta a this question.

13

Abrí una mi viejo proyecto desde el momento en que me gusta que examinó la estructura de directorios de importación y exportación (IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_DIRECTORY_ENTRY_IMPORT, IMAGE_DIRECTORY_ENTRY_IAT y IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT). En resumen, puedo explicar la parte en la que tienes un problema. Me refiero a la parte de cómo encontrar el puntero a, por ejemplo, IMAGE_EXPORT_DIRECTORY dentro de PE.

primer lugar de la causa, es posible utilizar las operaciones de lectura de archivos/escritura para analizar un archivo PE, pero es mucho más fácil de utilizar la asignación de archivos como siguiente:

hSrcFile = CreateFile (pszSrcFilename, GENERIC_READ, FILE_SHARE_READ, 
         NULL, OPEN_EXISTING, 0, NULL); 
hMapSrcFile = CreateFileMapping (hSrcFile, NULL, PAGE_READONLY, 0, 0, NULL); 
pSrcFile = (PBYTE) MapViewOfFile (hMapSrcFile, FILE_MAP_READ, 0, 0, 0); 

después de que tengamos el puntero pSrcFile que apuntan al archivo PE contienen podemos encontrar otros lugares importantes dentro del PE:

pDosHeader = (IMAGE_DOS_HEADER *)pSrcFile; 
IMAGE_NT_HEADERS32 *pNtHdr = (IMAGE_NT_HEADERS32 *) 
    ((PBYTE)pDosHeader + pDosHeader->e_lfanew); 
IMAGE_SECTION_HEADER *pFirstSectionHeader = (IMAGE_SECTION_HEADER *) 
    ((PBYTE)&pNtHdr->OptionalHeader + 
    pNtHdr->FileHeader.SizeOfOptionalHeader); 

dirección virtual Ahora todos hemos necesitado de cualquier directorio. Por ejemplo,

pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 

es una dirección virtual del directorio de exportación. Después de eso, para convertir la dirección virtual al puntero de memoria, , debemos encontrar la sección de PE que tiene esta dirección virtual dentro de.Para ello podemos enumerar las secciones del PE y encontrar un rallador i o igual a 0 y menos de pNtHdr->FileHeader.NumberOfSection s donde

pFirstSectionHeader[i].VirtualAddress <= 
pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 

y al mismo tiempo

pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress 
< pFirstSectionHeader[i].VirtualAddress + pFirstSectionHeader[i].Misc.VirtualSize 

entonces usted debe buscar los datos de exportación en la sección pFirstSectionHeader[i]:

IMAGE_SECTION_HEADER *pSectionHeader = &pFirstSectionHeader[i]; 
IMAGE_EXPORT_DIRECTORY *pExportDirectory = 
    (IMAGE_EXPORT_DIRECTORY *)((PBYTE)pbyFile + pSectionHeader->PointerToRawData + 
    pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress - 
    pSectionHeader->VirtualAddress); 

el mismo procedimiento se debe repetir para encontrar (IMAGE_IMPORT_DESCRIPTOR *) WH ich corresponde a IMAGE_DIRECTORY_ENTRY_IMPORT y (IMAGE_BOUND_IMPORT_DESCRIPTOR *) que corresponde a IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT para volcar la información de importación, incluida una información vinculante (si existe).

para volcar la información de IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT (corresponde a (ImgDelayDescr *) definido en delayimp.h) se debe utilizar también la información de la IMAGE_DIRECTORY_ENTRY_IAT (corresponde a (IMAGE_THUNK_DATA32 *)).

Para obtener más información acerca de PE recomiendo que http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

+0

Solo para aclarar, ¿puedes decir de dónde viene 'pbyFile'? –

+0

@DebugErr: Es lo mismo que 'pSrcFile' utilizado anteriormente. No es necesario leer todo el archivo EXE/DLL en la memoria. Uno puede usar métodos de mapeo de memoria para acceder a él. – Oleg

+0

Veo, estoy escribiendo esto en C#, así que ahora soy un poco flojo y solo necesitaba la dirección en el archivo (pSrcFile sería simplemente 0 para el cálculo). Implementé tu función, pero a excepción del campo TimeDateStamp, todos mis otros campos ExportDataDirectory se ven horriblemente mal :( –

0

se define macro para obtener primera sección

PIMAGE_SECTION_HEADER FisrtSection = IMAGE_FIRST_SECTION(NtHeaders)

Cuestiones relacionadas