[Vol-users] Some Help Please! ELF Segments in Memory

Bridgey theGeek bridgeythegeek at gmail.com
Mon Jul 17 08:29:33 EDT 2017

Hi all,

Hoping somebody can provide some comments re ELF files in memory.

My ultimate question is: How can I find the .bss section of an ELF
file in memory?

But I have a more specific one. Consider the following output from a
Volatility plugin I wrote which aims to parse the segments:

Volatility Foundation Volatility Framework 2.6

# First we grab the proc_maps which are mapped to the process of
interest (in this case, Xorg)...
# This mimics the linux_proc_maps plugin

Parsing proc maps...
/usr/lib/xorg/Xorg r-x start=0x55d4ddda4000 end=0x55d4ddfe0000 length=0x23c000
/usr/lib/xorg/Xorg r-- start=0x55d4de1e0000 end=0x55d4de1e2000 length=0x2000
/usr/lib/xorg/Xorg rw- start=0x55d4de1e2000 end=0x55d4de1ef000 length=0xd000

# Not listing anonymous maps for now.

# The we parse the ELF header which is at the start of the first
proc_map shown above

Parsing elf_ehdr...
Container({'e_flags': 0, 'e_shoff': 2401000, 'e_phoff': 64, 'e_shnum':
30, 'e_entry': 270368, 'e_version': 'EV_CURRENT', 'e_machine':
'EM_X86_64', 'e_phnum': 9, 'e_shentsize': 64, 'e_ident':
0, 'EI_MAG': [127, 69, 76, 70]}), 'e_type': 'ET_DYN', 'e_phentsize':
56, 'e_shstrndx': 29, 'e_ehsize': 64})

# This looks sane, so let's go to e_phoff (64) and read the program header

Parsing segments...

0x55d4ddda4040 Segment<p_memsz=0x1f8, p_flags=0x5, p_offset=0x40,
p_type=PT_PHDR, p_align=0x8, p_paddr=0x40, p_filesz=0x1f8,

0x55d4ddda4078 Segment<p_memsz=0x1c, p_flags=0x4, p_offset=0x238,
p_type=PT_INTERP, p_align=0x1, p_paddr=0x238, p_filesz=0x1c,

0x55d4ddda40b0 Segment<p_memsz=0x23bdd4, p_flags=0x5, p_offset=0x0,
p_type=PT_LOAD, p_align=0x200000, p_paddr=0x0, p_filesz=0x23bdd4,

0x55d4ddda40e8 Segment<p_memsz=0x1f8f0, p_flags=0x6,
p_offset=0x23c408, p_type=PT_LOAD, p_align=0x200000, p_paddr=0x43c408,
p_filesz=0xdd98, p_vaddr=0x43c408>

0x55d4ddda4120 Segment<p_memsz=0x2e0, p_flags=0x6, p_offset=0x23dc78,
p_type=PT_DYNAMIC, p_align=0x8, p_paddr=0x43dc78, p_filesz=0x2e0,

0x55d4ddda4158 Segment<p_memsz=0x44, p_flags=0x4, p_offset=0x254,
p_type=PT_NOTE, p_align=0x4, p_paddr=0x254, p_filesz=0x44,

0x55d4ddda4190 Segment<p_memsz=0x9904, p_flags=0x4, p_offset=0x1f2b50,
p_type=PT_GNU_EH_FRAME, p_align=0x4, p_paddr=0x1f2b50,
p_filesz=0x9904, p_vaddr=0x1f2b50>

0x55d4ddda41c8 Segment<p_memsz=0x0, p_flags=0x6, p_offset=0x0,
p_type=PT_GNU_STACK, p_align=0x10, p_paddr=0x0, p_filesz=0x0,

0x55d4ddda4200 Segment<p_memsz=0x1bf8, p_flags=0x4, p_offset=0x23c408,
p_type=PT_GNU_RELRO, p_align=0x1, p_paddr=0x43c408, p_filesz=0x1bf8,

# These segments look sane, and in fact the values match what I see
from `readelf --segments` against the Xorg binary on disk.

# I ignore the first PT_LOAD segment because the p_flags and p_vaddr
tell me the .bss isn't going to be in there. (As does the output from
`readelf --segments`)
# And I try to read the data pointed to by the p_vaddr of the second PT_LOAD

Testing PT_LOAD at 0x55d4ddda40e8.

# Let's re-print the segment to remind ourselves:
0x55d4ddda40e8 Segment<p_memsz=0x1f8f0, p_flags=0x6,
p_offset=0x23c408, p_type=PT_LOAD, p_align=0x200000, p_paddr=0x43c408,
p_filesz=0xdd98, p_vaddr=0x43c408>

# So starting at the base address (0x55d4ddda4000) + p_vaddr
(0x43c408) =0x55d4de1e0408, I should be able to read p_memsz (0x1f8f0)
bytes, right?
# Wrong... I can only read 0xebf7 (60,407) bytes before volatility
reports an error
Failed to read offset 0xebf8==60408

Notably, the starting offset, 0x55d4de1e0408, is in:
/usr/lib/xorg/Xorg r-- start=0x55d4de1e0000 end=0x55d4de1e2000 length=0x2000
but of course is bigger than the size of the proc_map.

I really do appreciate any comments you might have as to where my
understanding is lacking!


More information about the Vol-users mailing list