Skip to content
Courses

Executable Mapping Lab

How Programs WorkLab 1 of 2 · Investigative60–90 minutesLabBuilds on: Virtual Memory and Process Maps

Finish From Executable to Process, Reading an ELF File, and Virtual Memory and Process Maps first. You’ll want the Ubuntu x86-64 course VM, with file, readelf, sha256sum, and the ordinary /proc tools all available. The only thing needing internet access here is the download itself.

Download executable-mapping-v1.0.0.tar and save it in ~/underdunn-course/downloads.

Expected archive SHA-256:

b34e1eab25c8d7bff3544c84c7fd86f5b9f1968889068f47dc8a7b7e2b8b82da
Terminal window
cd ~/underdunn-course/downloads
sha256sum executable-mapping-v1.0.0.tar
mkdir -p ~/underdunn-course/labs/executable-mapping
tar -xf executable-mapping-v1.0.0.tar -C ~/underdunn-course/labs/executable-mapping
cd ~/underdunn-course/labs/executable-mapping/executable-mapping-v1.0.0
find . -maxdepth 2 -type f -printf '%P\n' | sort

Stop right there unless the digest matches and mapping-target shows up in that listing. Check both the digest and the inventory before you run the target at all, since that’s your baseline for everything afterward.

Use file, readelf -h, and readelf -lW to establish:

  1. ELF class, machine, type, and entry point.
  2. Every LOAD segment’s offset, virtual address, file size, memory size, flags, and alignment.
  3. Which segment contains executable code.
  4. Which segment requires more memory than it has file-backed bytes.

Before running the target, compare each LOAD segment’s permissions with what you expect in its live mapping. Keep file offsets, ELF virtual addresses and runtime addresses distinct; a scratch table is optional.

Run the target in the background, where it’ll stay alive for two minutes:

Terminal window
./mapping-target &
mapping_pid=$!
printf 'PID: %s\n' "$mapping_pid"
ps -p "$mapping_pid" -o pid,stat,comm,args

Confirm that PID really does belong to mapping-target, and then compare the live executable mappings with the program headers:

Terminal window
target_path="$(readlink "/proc/$mapping_pid/exe")"
grep -F "$target_path" "/proc/$mapping_pid/maps"

Calculate one load bias from matching file offsets and page-aligned addresses. Use it to predict a second mapping start, and then compare that prediction with /proc. Explain any page-sized expansion you find, rather than expecting one program-header row to match one mapping row character for character (they usually won’t).

When you’re done, stop only the process you recorded, and then confirm it’s gone:

Terminal window
kill -TERM "$mapping_pid"
wait "$mapping_pid"
ps -p "$mapping_pid" -o pid,stat,comm,args

That final ps output should contain nothing but the headings.

Milestone 4: check the count and entry point

Section titled “Milestone 4: check the count and entry point”

Count the entries whose program-header type is exactly LOAD. Enter that decimal count and the entry point as readelf -h prints it, including the 0x prefix. Use the supplied executable.

Check your answers

Enter the values you found. Your answers are checked in this browser without being sent anywhere.

Hint 1: choose the loader’s viewUse the program header table rather than the section table, because Linux maps segments.
Hint 2: match offsets before addressesFind a LOAD entry and a live mapping backed by the same file offset, and page-align both sides before you calculate any load bias.
Hint 3: count exact type labelsRun readelf -lW ./mapping-target and count only the rows whose first field is LOAD. Take the entry point from readelf -h, and not from a disassembly address.
  • The checksum doesn’t match: delete only the downloaded archive, fetch the pinned link again, and verify it before you extract anything.
  • The target exits before you can inspect it: confirm you launched ./mapping-target, save $! immediately, and use ps before you read /proc.
  • Your calculated load bias fails on a second row: recheck the file offsets and the page alignment. Don’t match rows by permission alone.
  • grep finds nothing at all: confirm the PID still exists, and use the exact path from /proc/PID/exe. Don’t assume the extracted relative path is how /proc prints it.

The checker should accept the LOAD count and entry point. Use your calculated load bias to check a second executable-backed mapping. If it differs, compare file offsets and page alignment. Stop the background process and confirm it is gone.

Confirm the recorded PID isn’t running any more before you reset anything. Then restore a fresh working copy:

Terminal window
cd ~/underdunn-course/labs/executable-mapping
rm -rf -- executable-mapping-v1.0.0
tar -xf ~/underdunn-course/downloads/executable-mapping-v1.0.0.tar -C .

For final cleanup, run only the first two lines, and keep the verified archive and any working files you want.