Ghidra: memory blocks, image base, and the entry point
The memory map is Ghidra’s picture of the file after the loader laid it out. Blocks, permissions, and the entry point are the facts every later address has to sit on.
Blocks are the loader’s layout
Window > Memory Map is the table of blocks. Each row has a start address, an end address, a length, a name, and flags for read, write, and execute. An ELF that still has section headers usually yields familiar names: .text for instructions, .rodata for constants, .data for initialized globals, .bss for zeroed globals. A PE uses names such as .text and .rdata. A file whose section headers were removed may show only LOAD segments. The flags still tell you which range the loader marked executable.
Program Trees, under the Window menu, is the same layout drawn as a tree you can click. Clicking a block moves the listing there. Use it when you know the kind of byte you want, a string or an instruction, and you do not yet know the address.
Three facts to copy into the notebook Image base: Entry address: Block that contains the entry (name, start, execute flag):
Image base is a database choice
Absolute addresses in the listing are addresses at the image base Ghidra assigned. A non-position-independent ELF often keeps the base written in its header. A position-independent ELF is commonly laid out at a default such as 00100000, because the file itself says the base is chosen at load. Either way, the number in the listing is how this database names a byte. It is the right number to type into Go To. It is the wrong number to paste into a debugger command unless you have rebased the debugger to the same base.
Pointers inside the file are interpreted relative to this layout. If you imported a raw image at the wrong base, a pointer that should land on a string lands outside every block, and the reference list stays empty. That symptom belongs to the import settings. Open Memory Map, compare the base with the lab notes, and re-import if they disagree.
The entry point is a marked address
The container records one address as the start. Ghidra labels it entry and lists it among the entry points in the Symbol Tree. On the harbor-check ELF that address is inside .text, the function is short, and its body is the C runtime’s startup, which a later lesson follows until it reaches main. The label entry is already the fact you need from this lesson: you can always return to the first instruction by going to that symbol.
A shared library often has an entry that only runs constructors, while the functions other programs call are exports. A raw firmware image may use a reset vector at a fixed offset in the block you named. The memory map still answers the same question. Which address is marked as the start, and which permissions does that block have?
Lab: name the blocks in harbor-check
Open the program you imported. In Memory Map, find the block that contains entry and confirm it is executable. Find the block you expect to hold read-only constants and confirm it is readable and not executable. Write the image base, the entry address, and those two block names in the notebook. Then use Program Trees to click each block and notice where the listing moves.
Search the listing for the text check.conf, or use Search > For Strings and sort by the text. The address you land on should fall inside the read-only block you just named. If it falls inside the executable block, look again before you decide the compiler embedded the bytes in an instruction stream. Most of the time the string is data, and the executable block only holds the instruction that takes its address.
Notebook, filled from your database (addresses will differ): Image base: 00100000 Entry: 00101080 block .text R-X Constants: 00102000 block .rodata R-- check.conf hit: 00102048 inside .rodata
Diagram
Three blocks you should be able to point at
- Loader
The importer lays the file out at an image base and creates one block per section or segment it kept.
- Map
Window > Memory Map lists each block’s start, end, and read, write, and execute flags.
- Entry
The entry point is a symbol, often named entry. It is the first instruction the loader would transfer to.
- Addresses
Every address you quote is an address in this database. A position-independent binary is rebased again when it actually runs.
What each kind of block is for
- Executable
Instructions live here. On a typical ELF this block is named .text, and its permissions include execute.
- Read-only data
Constants and most strings live here. On ELF that is often .rodata. On PE the usual name is .rdata. The block is readable and not executable.
- Writable data
Globals the program can store into live in .data or .bss. A string you expected to be constant, sitting in a writable block, is a fact worth writing down.
Image base: Entry address: Block that contains the entry (name, start, execute flag):
Check yourself
1. In a normal ELF layout, where do you expect the literal "/etc/harbor/check.conf" to sit?
2. Your listing shows addresses near 00101240, and the same program on a running Linux box is mapped somewhere else entirely. What is the listing address?
3. The Symbol Tree shows a function named entry at the start of the executable block. What is that function?