Is there any way to run 32-bit .ELF files that call for .bin Files? - elf

The Lexibook TV Games/Yeno 200-in-1 Console has a large set of 32-bit games. On the MicroSD Card, the 32-bit games are a set of folders with one .elf file, and a folder of many many .bin files. My question is, is there any type of way to run these properly? Opening the .elf files in online viewers show the files called upon, and the beginning is as follows:
ELF header
==========
Name Offset NumValue Value
EI_MAG: 0x00000000 0x7F454C46 ELF
EI_CLASS 0x00000004 0x01 32 BIT
EI_DATA 0x00000005 0x01 DATA2LSB (Little-Endian)
EI_VERSION 0x00000006 0x01 EV_CURRENT
EI_OSABI 0x00000007 0x00 UNIX System V ABI
EI_OSABIVER 0x00000008 0x00
E_TYPE 0x00000010 0x0002 ET_EXEC (Executable file)
E_MACHINE 0x00000012 0x0087 Unknown
E_VERSION 0x00000014 0x00000001 EV_CURRENT
E_ENTRY 0x00000018 0xA0081000
E_PHOFF 0x0000001C 0x00000034
E_SHOFF 0x00000020 0x00266A18
E_FLAGS 0x00000024 0x00070000
E_EHSIZE 0x00000028 0x0034
E_PHENTSIZE 0x0000002A 0x0020
E_PHNUM 0x0000002C 0x0001
E_SHENTSIZE 0x0000002E 0x0028
E_SHNUM 0x00000030 0x001D
E_SHSTRNDX 0x00000032 0x001A
Program header tables
=====================
Type Offset VAddr PAddr FileSz MemSz Align Flags
PT_LOAD 0x00000000 0xA0080000 0xA0080000 0x001DE034 0x0025EB20 0x00008000 Execute|Write|Read
"UNIX System V ABI" Is written, which may be info that's important.
P.S. - Sorry if my question isn't very clear, I don't know much about this kind of stuff. Thank you!

Related

Make all pages readable/writable/executable

I would like to grant full permissions (read, write, and execute) to all memory pages in an ELF binary. Ideally, I'd like to be able to do this as a transformation on a binary or object file, in the same way that symbols can be changed with objcopy. I have not yet found a good way to do this. I would also be okay with a solution that involves running code at startup that calls mprotect on every page with the flags PROT_READ | PROT_WRITE | PROT_EXEC. I've tried this briefly, but I haven't found a good way to know which pages are mapped, and therefore which pages need to be mprotected.
It isn't required that dynamically allocated pages have all permissions, only the pages mapped at program startup.
The following script implements Employed Russian's answer in code:
sets the p_type of the RELRO segment to PT_NULL
sets Flags on LOAD segments to PF_X|PF_W|PF_R.
It depends on pyelftools for python3, which can be installed with pip3 install pyelftools.
#!/usr/bin/env python3
import sys
from elftools.elf.elffile import ELFFile
from elftools.elf.descriptions import describe_p_type
if len(sys.argv) != 2:
print("Usage: elf_rwe <elf>")
name = sys.argv[1]
with open(name, "rb") as f:
elf = ELFFile(f)
rwe_offsets = []
relro_offsets = []
for i in range(elf['e_phnum']):
program_offset = elf['e_phoff'] + i * elf['e_phentsize']
f.seek(program_offset)
program_header = elf.structs.Elf_Phdr.parse_stream(f)
if program_header['p_type'] == "PT_LOAD":
rwe_offsets.append(program_offset)
if program_header['p_type'] == "PT_GNU_RELRO":
relro_offsets.append(program_offset)
f.seek(0)
b = list(f.read())
# Zap RELRO
pt_null = 0
for off in relro_offsets:
b[off] = pt_null
# Fix permissions
p_flags_offset = 4
for off in rwe_offsets:
b[off + p_flags_offset] = 0x7 # PF_X|PF_W|PF_R
with open(name, "wb") as f:
f.write(bytes(b))
I would like to grant full permissions (read, write, and execute) to all memory pages in an ELF binary.
Note that some security policies, such as W^X in selinux will prevent your binary from running.
Ideally, I'd like to be able to do this as a transformation on a binary or object file
Run readelf -Wl on your binary. You'll see something similar to:
$ readelf -Wl /bin/date
Elf file type is EXEC (Executable file)
Entry point 0x4021cf
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x0001f8 0x0001f8 R E 0x8
INTERP 0x000238 0x0000000000400238 0x0000000000400238 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x00dde4 0x00dde4 R E 0x200000
LOAD 0x00de10 0x000000000060de10 0x000000000060de10 0x0004e4 0x0006b0 RW 0x200000
DYNAMIC 0x00de28 0x000000000060de28 0x000000000060de28 0x0001d0 0x0001d0 RW 0x8
NOTE 0x000254 0x0000000000400254 0x0000000000400254 0x000044 0x000044 R 0x4
GNU_EH_FRAME 0x00cb8c 0x000000000040cb8c 0x000000000040cb8c 0x0002f4 0x0002f4 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x00de10 0x000000000060de10 0x000000000060de10 0x0001f0 0x0001f0 R 0x1
What you want to do then is to change Flags on LOAD segments to have PF_X|PF_W|PF_R. The flags are part of Elf{32,64}_Phdr table, and the offset to the table is in stored in e_phoff of the Elf{32,64}_Ehdr (which is stored at the start of every ELF file).
Look in /usr/include/elf.h. Parsing fixed-sized ELF structures involved here isn't complicated.
You are unlikely to find any standard tool that would do this for you (given that this is such an unusual and unsecure thing to do), but a program to change flags is trivial to write in C, Python or Perl.
P.S. You may also need to "zap" the RELRO segment, which could be done by changing its p_type to PT_NULL.
I haven't found a good way to know which pages are mapped, and therefore which pages need to be mprotected.
On Linux, you could parse /proc/self/maps to get that info. Other OSes may offer a different way to achieve the same.

ELF unmapped region in a segment

Below is the output for my readelf -l test
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00008000 0x00008000 0x00148 0x00148 R E 0x8000
LOAD 0x000148 0x00010148 0x00010148 0x00000 0x00004 RW 0x8000
NOTE 0x0000b4 0x000080b4 0x000080b4 0x00024 0x00024 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
Section to Segment mapping:
Segment Sections...
00 .note.gnu.build-id .text
01 .bss
02 .note.gnu.build-id
03
My question is about the first LOAD segment. It encompasses [8000 - 8148], and is mapped to sections .note and .text. My readelf -S output shows that .note section starts from 80b4, and .text starts from 80d8. That means Loadable segment contains a region [8000-80b3] which is unmapped to any section, but still will be loaded to memory by loader.
My question is, if there is any harm if I create a new segment which ranges from[80b4-8148] deleting this segment?
That means Loadable segment contains a region [8000-80b3] which is unmapped to any section, but still will be loaded to memory by loader.
Correct. You will find the Elf32_Ehdr, and likely a set of Elf32_Phdrs in that segment.
Note: for the main binary, it's actually the kernel that does the loading, and not the dynamic linker. You are not wrong in calling it "loader", but usually people use "loader" for the dynamic linker, and not the "part of the kernel that maps in the main binary".
My question is, if there is any harm if I create a new segment which ranges from[80b4-8148] deleting this segment?
The segment has to be page-aligned. A segment with .p_vaddr that is not page-aligned (as I believe you are proposing) will be rejected by the kernel.

Binary, produced by MSP430GCC, has strange start address for text segment

After compiling an exemplary C program with msp430-gcc (LTS 20120406 unpatched) for the MSPG2211 I got the following output using the readelf command:
section header
program header
The address space of the MSPG2211 microcontroller is structured as follows:
0x0000 - 0x01FF - Peripherals
0x0200 - 0x027F - RAM
0x1000 - 0x10FF - Flash (information memory)
0x1100 - 0xF7FF - ???
0xF800 - 0xFFFF - Flash (code memory + interrupt vectors)
The text section shown in the section header starts at 0xF800 which is the first address of the code memory.
The text segment, including only the text section, is bigger than the text section and starts already at 0xF76C.
As I understood, the loadable segments gets loaded to the shown physical addresses for program execution.
So why the start address of the text segment lies within an undefined memory region?
Some of the names sections (such as .text) contain data that is actually loaded into the MCU.
The ELF program headers, however, contain only metadata; their address does not matter.

saveenv fails after U-Boot update - Writing to NAND... FAILED

to be able to run my eSata Sheevaplug with Debian Wheezy I had to upgrade U-Boot to the DENX version.
As step-by-step guide I used this read from Martin Michlmayr. I did the upgrade using screen and a USB stick at the plug.
The upgrade went good and after resetting I got the plug started with the new version.
Marvell>> version
U-Boot 2013.10 (Oct 21 2013 - 21:06:56)
Marvell-Sheevaplug - eSATA - SD/MMC
gcc (Debian 4.8.1-9) 4.8.1
GNU ld (GNU Binutils for Debian) 2.23.52.20130727
Marvell>>
In the guide is written to set machid environment variable and MAC address.
But unfortunatly saveenv fails due to bad blocks in the NAND. I tried different versions of U-Boot also the one provided by NewIT. All behave the same way.
Marvell>> setenv machid a76
Marvell>> saveenv
Saving Environment to NAND...
Erasing NAND...
Skipping bad block at 0x00060000
Writing to NAND... FAILED!
There are some blocks marked as bad, which might be normal - by NewIT.
Marvell>> nand info
Device 0: nand0, sector size 128 KiB
Page size 2048 b
OOB size 64 b
Erase size 131072 b
Marvell>> nand bad
Device 0 bad blocks:
00060000
00120000
00360000
039c0000
0c300000
10dc0000
1ac40000
1f1c0000
Has someone a clue what the problem is and what I need to change to be able saving environment variables in u-boot?
Thanks,
schibbl
Due to configuration of environment variable storage at NAND, the sector size of 128k and a bad block mapping the environment variable storage adress it is not possible to write env to NAND.
Marvell>> nand bad
Device 0 bad blocks:
00060000
...
include/configs/sheevaplug.h which points perfectly to the bad block.
/*
* max 4k env size is enough, but in case of nand
* it has to be rounded to sector size
*/
#define CONFIG_ENV_SIZE 0x20000 /* 128k */
#define CONFIG_ENV_ADDR 0x60000
#define CONFIG_ENV_OFFSET 0x60000 /* env starts here */
Because of unused sector 0x80000 to 0x9FFFF I moved env storage there.
/*
* max 4k env size is enough, but in case of nand
* it has to be rounded to sector size
*/
#define CONFIG_ENV_SIZE 0x20000 /* 128k */
#define CONFIG_ENV_ADDR 0x80000
#define CONFIG_ENV_OFFSET 0x80000 /* env starts here due to bad block */
Beware! We have to ensure our compiled u-boot.kwb is less then 384k. Otherwise we will write u-boot to bad block marked memory and will brick the device.
Best way to recompile with custom env address, is to use Michlmayrs sources, which includes patches for mmc and e-sata support.

Size of ELF file vs size in RAM

I have an STM32 onto which I load ELF files in RAM (using OpenOCD and JTAG). So far, I haven't really been paying attention to the size of the ELF files that I load.
Normally, when I compile an ELF file that is too large for my board (my board has 128KB of RAM onto which the executable can be loaded) the linker complains (in the linker script I specify the size of the RAM).
Now that I notice the size of the outputted ELF file, I see that it is 261KB, and yet the linker has not complained!
Why is my ELF file so large, but my linker is fine with it? Is the ELF file on the host loaded exactly on the board?
No -- ELF contains things like relocation records that don't get loaded. It can also contain debug information (typically in DWARF format) that only gets loaded by a debugger.
You might want to use readelf to give you an idea of what one of your ELF files actually contains. You probably don't want to do it all the time, but doing it at least a few times to get some idea of what's there can give a much better idea of what you're dealing with.
readelf is part of the binutils package; chances are pretty decent you already have a copy that came with your other development tools.
If you want to get into even more detail, Googling for something like "ELF Format" should turn up lots of articles. Be aware, however, that ELF is a decidedly non-trivial format. If you decide you want to understand all the details, it'll take quite a bit of time and effort.
using the utility arm-none-eabi-size you can get a better picture of what actually gets used on the chip. The -A option will breakdown the size by section.
The relevant sections to look at when it comes to RAM are .data, .bss (static ram usage) and .heap (the heap: dynamic memory allocation by your program).
Roughly speaking, as long as the static ram size is below the RAM number from the datasheet, you should be able to run something on the chip and the linker shouldn't complain - your heap usage will then depends on your program.
Note: .text would be what needs to fit in the flash (the code).
example:
arm-none-eabi-size -A your-elf-file.elf
Sample output:
section size addr
.mstack 2048 536870912
.pstack 2304 536872960
.nocache 32 805322752
.eth 0 805322784
.vectors 672 134217728
.xtors 68 134610944
.text 162416 134611072
.rodata 23140 134773488
.ARM.exidx 8 134796628
.data 8380 603979776
.bss 101780 603988160
.ram0_init 0 604089940
.ram0 0 604089940
.ram1_init 0 805306368
.ram1 0 805306368
.ram2_init 0 805322784
.ram2 0 805322784
.ram3_init 0 805339136
.ram3 0 805339136
.ram4_init 0 939524096
.ram4 0 939524096
.ram5_init 0 536875264
.ram5 0 536875264
.ram6_init 0 0
.ram6 0 0
.ram7_init 0 947912704
.ram7 0 947912704
.heap 319916 604089940
.ARM.attributes 51 0
.comment 77 0
.debug_line 407954 0
.debug_info 3121944 0
.debug_abbrev 160701 0
.debug_aranges 14272 0
.debug_str 928595 0
.debug_loc 493671 0
.debug_ranges 146776 0
.debug_frame 51896 0
Total 5946701