Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 months ago.
Improve this question
I just read one section in PE file. I have output like this:
Section Info (1 of 6)
---------------------
Section Header name : .text
ActualSize of code or data : 0x49937
Virtual Address(RVA) : 0x1000
Size of raw data (rounded to FA) : 0x49a00
Pointer to Raw Data : 0x400
Pointer to Relocations : 0
Pointer to Line numbers : 0
Number of relocations : 0
Number of line numbers : 0
Characteristics : Contains executable code, Readable,
Section Info (2 of 6)
---------------------
Section Header name : .rdata
ActualSize of code or data : 0x1ed60
Virtual Address(RVA) : 0x4b000
Size of raw data (rounded to FA) : 0x1ee00
Pointer to Raw Data : 0x49e00
Pointer to Relocations : 0
Pointer to Line numbers : 0
Number of relocations : 0
Number of line numbers : 0
Characteristics : Contains initialized data, Readable,
I just want to read executable sections. For example, how can read .text section?
Caveat: Don't know for sure, but the following is based on some [obvious] deductions ...
In .text, the Pointer to Raw Data value is 0x400.
This [probably] isn't a valid memory address. So, it's [probably] a file offset (as this is what makes sense).
This is further supported by the fact that the .text section Size of raw data is 0x49a00.
Now, 0x400 + 0x49a00 --> 0x49e00 which is the Pointer to Raw Data value of the next section .rdata
So, if you seek the PE file to 0x400 and read 0x49a00 bytes, you'll be getting the contents of the .text section [as you desire]. That length is the rounded up length [to align to the next section's data], so a better length to read might be the ActualSize of code or data value of 0x49937
Side note: Although it's not a guarantee, the 0x400 offset of the .text section (the first section) data implies that the PE file header and all the [basic] section header structs fit in the first 0x400 (1024 decimal) bytes of the file. This is a reasonable assumption, given that PE is a simple format with a fixed number of section types (vs ELF that can have arbitrary/extensible sections).
Related
I want to learn about ARM stack unwinding and for this reason, I took a closer look into the .ARM.exidx section of my binary. The binary was build using gcc for arm, little endian, for an Cortex M0 32bit.
As expected, I got the exidx table, here is an example I dumped with objdump:
8012d34 c09bff7f ab07b180 909cff7f a907b180 ................
8012d44 c09cff7f b0ab0e80 509eff7f b0ab0c80 ........P.......
8012d54 249fff7f b0aa0580 b49fff7f b0ab0880 $...............
8012d64 aca0ff7f b0ab1080 74a1ff7f b0ab0880 ........t.......
8012d74 dca1ff7f b0b0b080 e4a1ff7f aa03b180 ................
8012d84 34a2ff7f b0ab0880 20a3ff7f b0ab1280 4....... .......
8012d94 20a4ff7f b0b0b080 28a4ff7f b0b0a880 .......(.......
8012da4 44a4ff7f 01000000 10a6ff7f b0b0b080 D...............
As far as I understand is the first entry the call address of a function inside my programm (The ones that end in 0x7f) and are in the prel31 format to indicate the general model.
Now, my question is, how can I convert these addresses into the actual function addresses?
I found the conversion inside the unwind.h inside the linux for ARM kernel
/* Convert a prel31 symbol to an absolute address */
#define prel31_to_addr(ptr) \
({ \
/* sign-extend to 32 bits */ \
long offset = (((long)*(ptr)) << 1) >> 1; \
(unsigned long)(ptr) + offset; \
})
but I can not get the addresses from the exidx section to match up with the addresses I can look up inside the map file.
Should the addresses from the exidx match up with the from the map file or is there a misunderstanding on my side? If the should match up, how can I convert them?
See: Structure of ARM extab.
The exidx section is linked with the executable. The distance between the exidx and the code is important. You can get the linker to dump the table address. It is actually the 'binary offset'. For example,
10000: 8012d34 c09bff7f
Then you take 0x7fff9bc0, the 2nd little endian entry and run it through the macro.
Offset is 0xffff9bc0 -> 6440
So the binary offset is 10000-6440 -> 9bc0.
Unfortunately, your 'exidx' offset is probably not so nice as 0x10000. If you have a linker file, you can add padding to make it nice and easy to translate for an experiment.
The offset matters and this is what make a pointer relative of length 31 to an address (prel31addr).
What exactly does ". = 0x7c00" in a linker script do?
More specifically, when I place . = 0x7c00 at the beginning of a linker script, why doesn't the resulting output file begin with 0x7c00 = 31,744 zeros?
I understand that when a PC boots, the BIOS places the 512 byte MBR at memory address 0x7c00. However, I am confused as to how exactly the linker's location counter affects how the output file is laid out.
(For context, I'm trying to thoroughly understand the sample code from the "x86 bare metal" project. https://github.com/cirosantilli/x86-bare-metal-examples. I've included the entire linker script below for context.)
SECTIONS
{
/*
We could also pass the -Ttext 0x7C00 to as instead of doing this.
If your program does not have any memory accesses, you can omit this.
*/
. = 0x7c00;
.text :
{
__start = .;
/*
We are going to stuff everything
into a text segment for now, including data.
Who cares? Other segments only exist to appease C compilers.
*/
*(.text)
/*
Magic bytes. 0x1FE == 510.
We could add this on each Gas file separately with `.word`,
but this is the perfect place to DRY that out.
*/
. = 0x1FE;
SHORT(0xAA55)
*(.stage2)
__stage2_nsectors = ABSOLUTE((. - __start) / 512);
. = ALIGN(512);
__end = .;
__end_align_4k = ALIGN(4k);
}
}
It looks like the ". = 0x7c00" is not meaning a length but an absolute address. It reads to me as 'set the current value of the special variable "." to be the hex value 0x7c00 and then it plans to use that address as an offset later in the script like with the . = ALIGN(512) it is also why it saves that address off as __start so it can then do math on the resulting image. If you manipulate . during the script so it points to the last chunk of memory added to the image then you can use it to determine the total size:
__stage2_nsectors = ABSOLUTE((. - __start) / 512);
in English would be
The difference between the starting place and wherever I ended divided by sector size.
I'm working on an embedded project on an ARM mcu that has a custom linker file with several different memory spaces:
/* Memory Spaces Definitions */
MEMORY
{
rom (rx) : ORIGIN = 0x00400000, LENGTH = 0x00200000
data_tcm (rw) : ORIGIN = 0x20000000, LENGTH = 0x00008000
prog_tcm (rwx) : ORIGIN = 0x00000000, LENGTH = 0x00008000
ram (rwx) : ORIGIN = 0x20400000, LENGTH = 0x00050000
sdram (rw) : ORIGIN = 0x70000000, LENGTH = 0x00200000
}
Specifically, I have a number of different memory devices with different characteristics (TCM, plain RAM (with a D-Cache in the way), and an external SDRAM), all mapped as part of the same address space.
I'm specifically placing different variables in the different memory spaces, depending on the requirements (am I DMA'ing into it, do I have cache-coherence issues, do I expect to overflow the D-cache, etc...).
If I exceed any one of the sections, I get a linker error. However, unless I do so, the linker only prints the memory usage as bulk percentage:
Program Memory Usage : 33608 bytes 1.6 % Full
Data Memory Usage : 2267792 bytes 91.1 % Full
Given that I have 3 actively used memory spaces, and I know for a fact that I'm using 100% of one of them (the SDRAM), it's kind of a useless output.
Is there any way to make the linker output the percentage of use for each memory space individually? Right now, I have to manually open the .map file, search for the section header, and then manually subtract the size from the total available memory specified in the .ld file.
While this is kind of a minor thing, it'd sure be nice to just have the linker do:
Program Memory Usage : 33608 bytes 1.6 % Full
Data Memory Usage : 2267792 bytes 91.1 % Full
data_dtcm : xxx bytes xx % Full
ram : xxx bytes xx % Full
sdram : xxx bytes xx % Full
This is with GCC-ARM, and therefore GCC-LD.
Arrrgh, so of course, I find the answer right after asking the question:
--print-memory-usage
Used as -Wl,--print-memory-usage, you get the following:
Memory region Used Size Region Size %age Used
rom: 31284 B 2 MB 1.49%
data_tcm: 26224 B 32 KB 80.03%
prog_tcm: 0 GB 32 KB 0.00%
ram: 146744 B 320 KB 44.78%
sdram: 2 MB 2 MB 100.00%
I would like to place a 2kB chunk of memory, aligned 16 bytes before a 1024 bytes alignment.
Platform : arm, bare metal, GNU toolchain. No need for portability
Can I do that with either GCC/attributes pragmas, ld custom linker script or any other solution ?
I would like to avoid wasting 1kB for that (basically placing a 3kB chunk of memory aligned at 1kB & adding 1024-16 bytes of padding).
Forcing a particular address to place the data is possible, but will ld be able to place variables before and after it (or is it just a way to put padding ? )
Context : buffer needs to be at 1k boundary by hardware design , but I'd like to add a bit of room before / after to be able to copy to this buffer with no bounds checking if my source is at most 16B wide.
edit: added example.
Let's say I have RAM starting at 0x2000000. I need a char buf[2048] be placed in it, at 1024*N-16 offset - ie (&buf[16])%1024==0 , hopefully without losing 1008 padding bytes.
(edit2)
So I'd like to have :
0x2000000 - some vars
0x2000010 - some other vars ...
0x2000100 - some other vars ...
0x20003F0 - char buf[2048] : here (int)&buf[16]%1024=0x2000400%1024==0
0x2000BF0 - some other vars ...
ALIGN(exp) is equivalent to (. + exp - 1) & ~(exp - 1). Of course, that expression only works if exp is a power of two. So you can't use ALIGN(), but you can write your own expression that does produce the result you want. Something like ((. + 1024 + 16 - 1) & ~(1024 - 1)) - 16 should do the trick. Plug in various values for . and you see it rounds up like you want.
The problem you'll have is that the linker will place every section you specified to be before your special section before it, and every section specified to be after it after it. It won't cleverly order the .data sections of different files to be before or after so as to produce the minimum amount of padding. It also won't re-order individual variables within an object file and section at all. If you are trying to pack as tightly as possible, I think you'll need to do something like:
.data : {
*(.about1008bytes)
. = ((. + 1024 + 16 - 1) & ~(1024 - 1)) - 16
*(.DMAbuf)
*(.data)
}
Use a section attribute to place your buffer in .DMAbuf and try to find close to but not more than 1008 bytes of other data variables and stick them in section .about1008bytes.
If you want to go crazy, use gcc -fdata-sections to place every data object in its own section, extract the section sizes with readelf, give that to a program you write to sort them for optimal packing that then spits out a chunk of linker script listing them in the optimal order.
You should define a specific section into your linker script, with the required alignment.
Looking at the man
ALIGN(exp)
Return the result of the current location counter (.) aligned to the next exp boundary. exp must be an expression whose value is a power of two. This is equivalent to
(. + exp - 1) & ~(exp - 1)
ALIGN doesn't change the value of the location counter--it just does arithmetic on it. As an example, to align the output .data section to the next 0x2000 byte boundary after the preceding section and to set a variable within the section to the next 0x8000 boundary after the input sections:
SECTIONS{ ...
.data ALIGN(0x2000): {
*(.data)
variable = ALIGN(0x8000);
}
... }
The first use of ALIGN in this example specifies the location of a section because it is used as the optional start attribute of a section definition (see section Optional Section Attributes). The second use simply defines the value of a variable. The built-in NEXT is closely related to ALIGN.
As an example you can define your section
SECTIONS
{
.myBufBlock ALIGN(16) :
{
KEEP(*(.myBufSection))
} > m_data
}
and into your code you can
unsigned char __attribute__((section (".myBufSection"))) buf[2048];
EDIT
SECTIONS
{
.myBufBlock 0x0x7FBF0 :
{
KEEP(*(.myBufSection))
} > m_data
}
and into your code you can
unsigned char __attribute__((section (".myBufSection"))) buf[16+2048+16];
To your DMA you can set the address &buf[16] that will be 1k aligned.
I am working on an executable Packer & I have done compression & Encryption part so far. Now I have to store decompression/decryption stub/routine in the compressed file. My question is that will this stub be written in HEX code or I can place the assembly instruction directly ? If later is possible, then how ?
Creating a working packed binary requires:
modify the PE geometry
insert your code
Depending on your code size, you might want to use section padding, or to add your own section.
Then, to insert your code - as you seem to prefer direct ASM insertion - my suggestion would be to make the decryption code EIP-independent, then assemble it with something like YASM as pure code (-o), and include the code as assembled binary directly.
I wrote several mini-packers that might help as a starting reference, as they also 'insert' assembled code.
You have to have section with characteristic as "readable" & "writable" & "contains code" & "Is executable"
Address of Entry Point: 0x00019860
Section Header #1
Name: UPX0
Virtual Size: 0x00010000 (65536)
Virtual Address: 0x00001000
Size of Raw Data: 0x00000000 (0)
File Pointer to Raw Data: 0x00000400
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xE0000080
Section contains uninitialized data.
Section is executable.
Section is readable.
Section is writeable.
Section Header #2
Name: UPX1
Virtual Size: 0x00009000 (36864)
Virtual Address: 0x00011000
Size of Raw Data: 0x00008A00 (35328)
File Pointer to Raw Data: 0x00000400
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xE0000040
Section contains initialized data.
Section is executable.
Section is readable.
Section is writeable.
Section Header #3
Name: .rsrc
Virtual Size: 0x00001000 (4096)
Virtual Address: 0x0001A000
Size of Raw Data: 0x00000800 (2048)
File Pointer to Raw Data: 0x00008E00
File Pointer to Relocation Table: 0x00000000
File Pointer to Line Numbers: 0x00000000
Number of Relocations: 0
Number of Line Numbers: 0
Characteristics: 0xC0000040
Section contains initialized data.
Section is readable.
Section is writeable.
Just in short, UPX generates one section which contains compressed code and decompressor routine and second section which is uninitialized but is allowed to have writable and executable characteristic. The decompressor routine decompresses the code to the uninitialized section and continues with execution of the original entrypoint...