4

Given a simple program like this,

void main (int argc, char * argv[] ) {
    char * arr[] = {"foo", "bar", "baz"};
    *(arr[0]) = 'F';
    printf( "%s", arr[0] );
}

How do I find out what section the strings foo, bar, and baz are defined in? As in, are they in the .text section or .rodata, and also check to make sure those section are ro, or rw?

4

In the following answer, I'll show you several ways to achieve what you want. I'll use different approaches to do this with radre2.

First, let's create a program with a bit longer strings:

$ cat helloworld.c 

#include <stdio.h>

void main (int argc, char * argv[] ) {
    char * arr[] = {"Hello", "World", "Byebye"};
    arr[0] = "F";
    printf( "%s\n", arr[0] );
}

$ gcc helloworld.c -o helloworld

And open it in radare2:

$ r2 helloworld

Now that we have a tiny binary, we can start.


Method 1: Strings in data sections

Using the iz command you can list the strings in the data sections. For each string, you can see the section it belongs to:

[0x000005b0]> iz
000 0x000007b4 0x000007b4   5   6 (.rodata) ascii Hello
001 0x000007ba 0x000007ba   5   6 (.rodata) ascii World
002 0x000007c0 0x000007c0   6   7 (.rodata) ascii Byeby

And of course, you can always use radare's internal grep (~) to take only the relevant columns:

[0x000005b0]> iz~[5,7]
(.rodata) Hello
(.rodata) World
(.rodata) Byebye

Method 2: Strings in the whole binary

Unlike iz, the command izz will search for strings in the whole binary. This command will show you more strings than iz but it'll search for strings in other sections as well.

[0x000005b0]> izz
000 0x00000034 0x00000034   4  10 (LOAD0) utf16le @8\t@
001 0x00000238 0x00000238  27  28 (.interp) ascii /lib64/ld-linux-x86-64.so.2
002 0x00000379 0x00000379   9  10 (.dynstr) ascii libc.so.6
003 0x00000383 0x00000383   4   5 (.dynstr) ascii puts
004 0x00000388 0x00000388  16  17 (.dynstr) ascii __stack_chk_fail
005 0x00000399 0x00000399  14  15 (.dynstr) ascii __cxa_finalize
006 0x000003a8 0x000003a8  17  18 (.dynstr) ascii __libc_start_main
007 0x000003ba 0x000003ba   9  10 (.dynstr) ascii GLIBC_2.4
008 0x000003c4 0x000003c4  11  12 (.dynstr) ascii GLIBC_2.2.5
009 0x000003d0 0x000003d0  27  28 (.dynstr) ascii _ITM_deregisterTMCloneTable
010 0x000003ec 0x000003ec  14  15 (.dynstr) ascii __gmon_start__
011 0x000003fb 0x000003fb  25  26 (.dynstr) ascii _ITM_registerTMCloneTable
...
019 0x000007b4 0x000007b4   5   6 (.rodata) ascii Hello
020 0x000007ba 0x000007ba   5   6 (.rodata) ascii World
021 0x000007c0 0x000007c0   6   7 (.rodata) ascii Byebye
022 0x00000810 0x00000810   4   5 (.eh_frame) ascii \e\f\a\b
023 0x00000840 0x00000840   4   5 (.eh_frame) ascii \e\f\a\b
024 0x00000867 0x00000867   5   6 (.eh_frame) ascii ;*3$"
025 0x0000088a 0x0000088a   4   5 (.eh_frame) ascii h\f\a\b
026 0x00001038 0x00000000  16  17 (.comment) ascii GCC: (GNU) 7.2.0
027 0x00001669 0x00000001   6   7 (.strtab) ascii init.c
028 0x00001670 0x00000008  10  11 (.strtab) ascii crtstuff.c
...

Again, you can see that radare2 shows you the section name for each string. If you are searching for specific strings, grep is your friend:

[0x000005b0]> izz~Hello, World, Byebye
019 0x000007b4 0x000007b4   5   6 (.rodata) ascii Hello
020 0x000007ba 0x000007ba   5   6 (.rodata) ascii World
021 0x000007c0 0x000007c0   6   7 (.rodata) ascii Byebye

[0x000005b0]> izz~Hello, World, Byebye[5,7]
(.rodata) Hello
(.rodata) World
(.rodata) Byebye

Method 3: Section of a specific address

In this method, you already know the address of the string and you want to know to which section it belongs. Let's take "Hello" for example. We saw that "Hello" address is 0x000007b4. Let's verify it using ps (print string):

[0x000005b0]> ps @ 0x000007b4
Hello

As you can see, we printed a zero-terminated string from 0x07b4 ("@" is radare's temporary seek). Now that we are sure that this is the address of "Hello", we can use iS. to show the current Section name:

[0x000005b0]> iS. @ 0x07b4
Current section
00 0x000007b0    25 0x000007b0    25 -r-- .rodata

As expected, this address belongs to the .rodata section. Just as we saw before.


Show Sections' attributes

Finally, you wanted to check whether the sections' attributes are read-only or read-write. Using iS you can list all the sections, including their attributes:

[0x000005b0]> iS
[Sections]
00 0x00000000     0 0x00000000     0 ---- 
01 0x00000238    28 0x00000238    28 -r-- .interp
02 0x00000254    32 0x00000254    32 -r-- .note.ABI_tag
03 0x00000274    36 0x00000274    36 -r-- .note.gnu.build_id
04 0x00000298    28 0x00000298    28 -r-- .gnu.hash
05 0x000002b8   192 0x000002b8   192 -r-- .dynsym
06 0x00000378   157 0x00000378   157 -r-- .dynstr
07 0x00000416    16 0x00000416    16 -r-- .gnu.version
08 0x00000428    48 0x00000428    48 -r-- .gnu.version_r
09 0x00000458   216 0x00000458   216 -r-- .rela.dyn
10 0x00000530    48 0x00000530    48 -r-- .rela.plt
11 0x00000560    23 0x00000560    23 -r-x .init
12 0x00000580    48 0x00000580    48 -r-x .plt
13 0x000005b0   498 0x000005b0   498 -r-x .text
14 0x000007a4     9 0x000007a4     9 -r-x .fini
15 0x000007b0    25 0x000007b0    25 -r-- .rodata
16 0x000007cc    52 0x000007cc    52 -r-- .eh_frame_hdr
17 0x00000800   240 0x00000800   240 -r-- .eh_frame
18 0x00000de0     8 0x00200de0     8 -rw- .init_array
19 0x00000de8     8 0x00200de8     8 -rw- .fini_array
20 0x00000df0   480 0x00200df0   480 -rw- .dynamic
21 0x00000fd0    48 0x00200fd0    48 -rw- .got
22 0x00001000    40 0x00201000    40 -rw- .got.plt
23 0x00001028    16 0x00201028    16 -rw- .data
24 0x00001038     0 0x00201038     8 -rw- .bss
25 0x00001038    17 0x00000000    17 ---- .comment
26 0x00001050  1560 0x00000000  1560 ---- .symtab
27 0x00001668   555 0x00000000   555 ---- .strtab
28 0x00001893   259 0x00000000   259 ---- .shstrtab
29 0x00000040   504 0x00000040   504 -r-x PHDR
30 0x00000238    28 0x00000238    28 -r-- INTERP
31 0x00000000  2288 0x00000000  2288 -r-x LOAD0
32 0x00000de0   600 0x00200de0   608 -rw- LOAD1
33 0x00000df0   480 0x00200df0   480 -rw- DYNAMIC
34 0x00000254    68 0x00000254    68 -r-- NOTE
35 0x000007cc    52 0x000007cc    52 -r-- GNU_EH_FRAME
36 0x00000000     0 0x00000000     0 -rw- GNU_STACK
37 0x00000de0   544 0x00200de0   544 -r-- GNU_RELRO
38 0x00000000    64 0x00000000    64 -rw- ehdr

Alternatively, use iSq to show a less-verbose output (q is for quiet), and you also can grep for read-write sections:

[0x000005b0]> iS~rw
18 0x00000de0     8 0x00200de0     8 -rw- .init_array
19 0x00000de8     8 0x00200de8     8 -rw- .fini_array
20 0x00000df0   480 0x00200df0   480 -rw- .dynamic
21 0x00000fd0    48 0x00200fd0    48 -rw- .got
22 0x00001000    40 0x00201000    40 -rw- .got.plt
23 0x00001028    16 0x00201028    16 -rw- .data
24 0x00001038     0 0x00201038     8 -rw- .bss
32 0x00000de0   600 0x00200de0   608 -rw- LOAD1
33 0x00000df0   480 0x00200df0   480 -rw- DYNAMIC
36 0x00000000     0 0x00000000     0 -rw- GNU_STACK
38 0x00000000    64 0x00000000    64 -rw- ehdr

If you want to see read-only sections, use grep like this iS~r--.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.