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:
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
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"