I was reading a tutorial on PE and it says
Go to the section table either by adding ImageBase to SizeOfHeaders
but SizeOfHeaders is
The size of all headers+section table
so if we add SizeOfHeaders to ImageBase won't we jump at the sections rather than the table?
SizeOfHeaders is not used to find out the position of the section table, even if they might match in some files (but I don't expect so).
Here's how it's done in the Windows headers (and thus the system loader):
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \
((ULONG_PTR)(ntheader) + \
FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \
((ntheader))->FileHeader.SizeOfOptionalHeader \
))
Note that the actual value of SizeOfOptionalHeader is not checked; it can be very big or even negative - some malware uses it trick to fool analyzing tools.
See here for more details and even nastier tricks.
SizeOfHeaders indeed is the size of the entire header, including the DOS stub.
To get the address of the section table, first get the address of the optional header, and add FileHeader.SizeOfOptionalHeader.
Related
When I compile my Delphi project and instruct the compiler to create a memory mapping file (*.map) it contains a description of the used memory segments at the top of the file.
Example:
Start Length Name Class
0001:00401000 00475600H .text CODE
0002:00877000 00004998H .itext ICODE
0003:0087C000 00030410H .data DATA
0004:008AD000 00009170H .bss BSS
0005:00000000 00000278H .tls TLS
When looking at the PE section table docs only ".text" and the other sections except for ".itext" is listed there.
What is the purpose of that ".itext" segment and how does it differ from ".text"? Is it some Delphi/Borland/Embarcadero-specific extension?
The itext segments (with Class = ICODE) resemble the initialization sections of the linked units.
How is SizeOfImage in the PE optional header computed?
Trying to learn the PE format, I've come across the SizeOfImage field in the optional header.
To quote the documentation:
The size (in bytes) of the image, including all headers, as the image
is loaded in memory. It must be a multiple of SectionAlignment.
However, I've experienced that if I set this field wrongly, then the executable won't run and an error 193 (badly formatted excutable) is displayed:
How do I compute the SizeOfImage field, and why won't an executable run if its set wrong (e.g. the executable runs if it's set to 0x00003000 but not 0x00004000 or 0x00002000)?
The safest way that I know of is to loop through each section and find the section to be loaded last in memory (i.e. the highest address). You can almost always assume this is the last section and just skip directly to that section if you trust your PE file (such as if you are using a standard linker, etc). You begin with calculating the end-of-data pointer of that section as follows:
pEndOfLastSection = pLastSection->VirtualAddress + pLastSection->Misc.VirtualSize + pOptionalHeader->ImageBase
pEndOfLastSection now represents the end of the actual section's data (as it exists in the file, padded to file alignment, but not padded to memory alignment) and doesn't include any padding the loader must add to ensure the section fits exactly within the granularity of the memory section alignment.
Despite the other fields that might seem to store the end of the section rounded up to the next nearest "memory" alignment, you must you must perform this calculation yourself on the pEndOfLastSection pointer. I wrote the following function which so far has worked for my purposes:
//
// peRoundUpToAlignment() - rounds dwValue up to nearest dwAlign
//
DWORD peRoundUpToAlignment(DWORD dwAlign, DWORD dwVal)
{
if (dwAlign)
{
//do the rounding with bitwise operations...
//create bit mask of bits to keep
// e.g. if section alignment is 0x1000 1000000000000
// we want the following bitmask 11111111111111111111000000000000
DWORD dwMask = ~(dwAlign-1);
//round up by adding full alignment (dwAlign-1 since if already aligned we don't want anything to change),
// then mask off any lower bits
dwVal = (dwVal + dwAlign-1) & dwMask;
}
return(dwVal);
} //peRoundUpToAlignment()
Now take your pEndOfLastSecion and pass it to the rounding function as follows:
//NOTE: we are rounding to memory section alignment, not file
pEndOfLastSectionMem = peRoundUpToAlignment(pOptionalHeader->SectionAlignment,pEndOfLastSection)
Now you have a "simulated" pointer to the end of the PE file as it would be loaded in memory. NOTE: the end pointers calculated above actually point 1 byte past the last byte of the last section; this allows you to subtract them from their base to get the size. Once you have the end pointer of the last section as it would be loaded in memory, you can subtract this from the loader base and get the size of the PE file as it should be loaded in memory, and this size is obviously the same regardless of where the loader might relocate the PE file:
uCalcSizeOfFile = pEndOfLastSectionMem - pOptionalHeader->ImageBase
Unless the image has been tampered with, the calculation of uCalcSizeOfFile above should be equal to the pOptionalHeader->SizeOfImage field.
In
http://en.redinskala.com/finding-the-ep/
there is information about how to find the file offset of the entry point in a exe-file.
Here I can read that
EP (File) = AddressOfEntryPoint – BaseOfCode + .text[PointerToRawData]
+ FileAlignment
However, when I have been calculating this myself (I used a couple of different exe files) I have came to the conclusion that
Offset of entry point in EXE file = AddressOfEntryPoint + .text[PointerToRawData] -
.text[VirtualAddress]
Where AddressOfEntryPoint is fetched from IMAGE_OPTIONAL_HEADER and the other two values from the IMAGE_SECTION_HEADER.
Is the information on that web page false? Adding FileAlignment like they do just seems wrong, it does not make sense. Or does it? A file alignment suggests that I should use modulo or something to compute a value. If BaseOfCode and FileAlignment is the same value (mostly they are), it would not disturb adding them to the calculation, but how would it make sense?
Correct, you don't need to use the FileAlignment value at all.
The algorithm should be something like as follow (very similar to yours):
Get AddressOfEntryPoint from IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint (this is a VA)
Search in which section header this VA resides (usually the 1st one, but you should really search in all section headers).
Once you have the right section header, get its VirtualAddress and PointerToRawData fields.
Subtract VirtualAddress from AddressOfEntryPoint: you now have a "delta"
As the exactly same delta applies to offsets, then: add "delta" to PointerToRawData.
You simply don't need FileAlignment because the section in which the entry point lies is already aligned on that value.
On Linux, when linking I can specify any virtual address for a section:
ld -Ttext 0x10000000 -Tdata 0x20000000 foo.o -o foo
But I don't see such option for Windows' link.exe.
Is it possible to specify PE section start addresses somehow?
MinGW ld can put the sections at arbitrary addresses. Dumpbin and disassemblers can handle it without problem.
But it seems Windows does not accept anything but the default address: if you try to set it to a different value Windows will say "not a valid Win32 application".
The base address must be 0x400000 or 0x1000000.
And the .text section must be at 0x401000 or 0x1001000.
Also it seems no gaps allowed between the sections. If I try to place the .data section to 0x403000 instead of 0x402000, then Windows is unable to load it...
(I maybe wrong, or mingw ld is buggy...)
When using GCC, this page explains how to define variables at absolute addresses (including mentioning the section in which they should reside) : https://mcuoneclipse.com/2012/11/01/defining-variables-at-absolute-addresses-with-gcc/
The idea I use here is to put the variable with a special section
name, and then place it in the linker file at an absolute address.
unsigned char __attribute__((section (".myBufSection"))) buf[128]
__attribute__ ((aligned (512)));
With this, my variable will be put into a section named
‘.myBufSection’, and it will be aligned on a 512 address boundary.
The next step is to place that section at an address in the linker file.
SECTIONS
{
/* placing my named section at given address: */
.myBufBlock 0x20000000 :
{
KEEP(*(.myBufSection)) /* keep my variable even if not referenced */
} > m_data
/* other placements follow here... */
}
PS: Another method is mentioned in How can I declare a variable at an absolute address with GCC?
PS 2: Another related (alas unanswered) question is this : How to place a variable at a given absolute address in memory (with Visual C++)
I am trying to write a multi stage boot loader using NASM and gcc.
For this purpose I am referring grub boot loader source.
I have written a stage1 loader, but stuck at over writing partition
tables of MBR.
In grub stage1.S, they are using code like this to skip partition tables:
. = _start + STAGE1_PARTEND
.word STAGE1_SIGNATURE
How can I do that in NASM?.
using times it will over write the partition tables.
So please help me.
Assigning a value to . is treated the same as a .org directive (see this page).
Thus, the code you pasted is changing the current origin to _start + STAGE1_PARTEND and placing a word with the value STAGE1_SIGNATURE there.
So in NASM code you should be able to do something like:
fill: times _start+STAGE1_PARTEND-$ db 0
dw STAGE1_SIGNATURE
; .word is 16 bits on x86 (regardless of .code16 / .code64)
Also see this example in the NASM manual showing how to pad a BIOS boot sector this way, as a replacement for MASM-style org or GAS-style . = new_position actually seeking and filling with padding in a flat binary output file.
times STAGE1_PARTEND-($-_start) db 0
dw STAGE1_SIGNATURE
Right, Nasm will accept only one "org" directive. The Nasm equivalent of "." is "$", but I don't think that'll help you either. I don't have the GRUB code on hand, or I'd look. Where does the partition table "come from"? If it's read from disk, there may be a signature already in place(?). Perhaps you can simply "stop" the Nasm code before overwriting the partition table and leave the existing sig in place? Nasm will do almost "anything you want", but this may be an exception. It won't "move" (skip) and assemble more at a new place as (G)as is apparently doing here - at least not readily. I may need to download the GRUB code to figure out a workaround. Possibly something like...
; stage1 code
; possible padding here?
%incbin "partition_table.bin"
dw (SIG) ; if not part of the .bin code?
... or something.