Skip to main content
12 of 12
added 37 characters in body
julian
  • 7.2k
  • 3
  • 23
  • 56

It is assumed here that Linux ELF32 binaries are being analyzed.

Code and data such as strings are stored in separate parts of ELF binaries.

  • To disassemble the parts containing code, use objdump -dj .text <binary_name>.
  • To examine hard-coded string data, use readelf -x .rodata <binary_name>

Instructions and Data are located in separate areas within ELF binaries

Currently I can get the offsets and assembly code, but not text strings alongside.

Code and hardcoded strings are not intermingled in x86 or x86-64 ELF binaries. When the compiler toolchain generates a binary, hardcoded strings are placed in a separate area of the binary from the executable code and are referenced/accessed by their virtual memory address. Here is a diagram by Ange Albertini of the how different sections are laid out in ELF binaries: Ange Albertini ELF

To make this more clear, below are visualizations of the Linux utilities ls, cat, mkdir and mv (accomplished via binvis.io). The solid blue areas consist of ASCII string data (the .rodata section, for example), and the large blocks of blue, white, red and black mixed together are regions that consist of executable code (the .text section, for example).

* ls cat mkdir mv

ls cat mkdir mv

As we can see from these visualizations, these binaries are organized in a similar fashion. Each binary has discrete areas, or sections, which contain different information. We can also see here that there are multiple areas (i.e. sections) containing ASCII string data, not just one.

Sections with executable instructions will not contain meaningful strings, only code. This can be observed directly by using the -s option with objdump when examining the .text section of the Linux date utility:

$ objdump -sj .text /bin/date
/bin/date:     file format elf64-x86-64

Contents of section .text:
 401af0 41574531 ff415645 31f64155 41544531  AWE1.AVE1.AUATE1
 401b00 e45589fd 534889f3 4881ecd8 00000048  .U..SH..H......H
 401b10 8b3ee8f9 530000be a1c84000 bf060000  .>..S.....@.....
 401b20 00e8bafe ffffbe87 944000bf 61944000  [email protected].@.
 401b30 e83bfcff ffbf6194 4000e811 fcffffbf  .;....a.@.......
 401b40 102c4000 e8877800 00c64424 0f0048c7  .,@...x...D$..H.
 < snip >

In ELF binaries, the .text section holds the executable instructions of the program. The bytes the instructions are composed of are being treated as ASCII in this hexdump, so there are meaningless sequences of characters being printed.

Objdump will treat data as instructions and disassemble accordingly

objdump relies on an ELF binary's section headers to determine which sections of the binary contain code and which sections contain data. Only sections with instructions (.text, for example) should be disassembled using objdump.The -D argument to objdump will result in all sections of an ELF binary being disassembled, even non-code sections like .data and .rodata.

From the manual page:

-D

--disassemble-all

Like -d, but disassemble the contents of all sections, not just those expected to contain instructions.

This means that even if a section contained hardcoded strings (.dynstr, .shstrtab, .rodata, etc.) objdump would treat this data as instructions and dissasemble them accordingly.

Here is an example using /bin/date:

/bin/date:     file format elf64-x86-64


Disassembly of section .rodata:

0000000000409400 <.rodata>:
  409400:       01 00                   add    %eax,(%rax)
  409402:       02 00                   add    (%rax),%al
  409404:       74 69                   je     40946f <__sprintf_chk@plt+0x798f>
  409406:       6d                      insl   (%dx),%es:(%rdi)
  409407:       65 20 25 73 20 69 73    and    %ah,%gs:0x73692073(%rip)        # 73a9b481 <stderr+0x7348d131>
  40940e:       20 6f 75                and    %ch,0x75(%rdi)
  409411:       74 20                   je     409433 <__sprintf_chk@plt+0x7953>
  409413:       6f                      outsl  %ds:(%rsi),(%dx)
  409414:       66                      data16
  409415:       20 72 61                and    %dh,0x61(%rdx)
  409418:       6e                      outsb  %ds:(%rsi),(%dx)
  409419:       67 65 00 0a             add    %cl,%gs:(%edx)
  40941d:       52                      push   %rdx
  40941e:       65                      gs
  40941f:       70 6f                   jo     409490 <__sprintf_chk@plt+0x79b0>
  < snip >

It looks like there are instructions being disassembled, when in reality is data being treated as code:

$ readelf -x .rodata /bin/date
Hex dump of section '.rodata':
  0x00409400 01000200 74696d65 20257320 6973206f ....time %s is o
  0x00409410 7574206f 66207261 6e676500 0a526570 ut of range..Rep

Furthermore, the arguments -b binary result in objdump treating the binary as a blob with a single section, obliterating any distinction between code and data within the binary, resulting in the entire contents of the binary being treated as code.

Reference: the System V ABI section 4: "Object Files"

julian
  • 7.2k
  • 3
  • 23
  • 56