Phishing & BotNets
Re: PE Headers Oct 20 2005 01:59PM
Harlan Carvey (keydet89 yahoo com) (1 replies)
Re: PE Headers Oct 20 2005 02:53PM
Jonathon Giffin (giffin cs wisc edu)
Harlan Carvey wrote:
> Based on what you've said, given the information from
> the .data section above, the calculation of
> "sh.PointerToRawData - sh.VirtualAddress" is a
> negative number.

Negative corrections are expected. The layout of the sections in the PE
file and the layout of the sections in memory need not coincide. For
example, the .data section could appear before the .text section in the
file, but when loaded, the ordering would be reversed. This is all
handled by the loader as it reads values in the section headers. As a
result, the correction value added to an RVA could be either positive or

However, the layout of an individual section is fixed. This is why you
can legitimately use values from section headers to find the file offset
of an RVA.

In practice, I would expect the ordering of sections in a PE file to
match the ordering of sections in memory. However, a PE file will be
smaller than the image size in memory. For example, sections must be
page aligned in memory but can begin at any offset in a file. The extra,
unused space used by the last page of a section in memory to maintain
alignment need not appear in the PE file. As a result, all later
sections are shifted backwards in the file. They have file offsets less
then the virtual address at which they will be loaded in memory. Hence,
the correction value added to RVAs will likely be negative.

If using negative values in file pointer calculations makes you
uncomfortable, reorder the computation to be

file_offset = sh.PointerToRawData + (RVA - sh.VirtualAddress)

Assuming you do some minor sanity checks beforehand, then the RVA will
always be larger than the section's VirtualAddress, the file_offset will
be legitimate, and this computation will never overflow.

> From the headers of netstat.exe, I can pull the
> the first descriptor is 0x5354. Using the calculation
> above for the .text section, the offset within the
> file for the DLL name is 0x4754. This works out
> perfectly.

Good to hear.

> I guess what I'm not getting from this point, from any
> source, is this...when dealing with the RVAs in the
> IMAGE_IMPORT_DESCRIPTOR, how does one determine the
> particular section to be used? I'm assuming that the
> RVAs for the import lookup table and the import
> address table would be in the .data section, and the
> RVA for the DLL name would be within the .text
> section, but how do you calculate the offsets for
> sections with non-standard names? Should I instead be
> looking at the characteristics of the section?

I do a linear search through all section headers until I find the
section containing the virtual address of the import section directory.

Here is example C code that I have written on a Win2k machine using the
header file windows.h with WIN32_LEAN_AND_MEAN undefined. I left out
most of the error-handling code for conciseness:

/* I assume that you read this structure successfully. */

/* Get the import section directory. */

/* Get the section containing the import directory. */
int i;
for (i = 0; i < nth.FileHeader.NumberOfSections; ++i)
fread((void*)&ish, sizeof(IMAGE_SECTION_HEADER), 1, PE_file);
if (idd->VirtualAddress >= ish.VirtualAddress &&
idd->VirtualAddress < ish.VirtualAddress + ish.SizeOfRawData)
if (i == nth.FileHeader.NumberOfSections)

/* Success! ish is the section containing the import table. Use
* the values ish.VirtualAddress and ish.PointerToRawData in
* computing file_offsets for RVAs.


[ reply ]


Privacy Statement
Copyright 2010, SecurityFocus