给定一个像这样的简单程序,
void main (int argc, char * argv[] ) {
char * arr[] = {"foo", "bar", "baz"};
*(arr[0]) = 'F';
printf( "%s", arr[0] );
}
如何找出部分字符串foo
,bar
以及baz
在界定?例如,它们是否在.text
或 部分.rodata
,并检查以确保这些部分是ro
, 或rw
?
给定一个像这样的简单程序,
void main (int argc, char * argv[] ) {
char * arr[] = {"foo", "bar", "baz"};
*(arr[0]) = 'F';
printf( "%s", arr[0] );
}
如何找出部分字符串foo
,bar
以及baz
在界定?例如,它们是否在.text
或 部分.rodata
,并检查以确保这些部分是ro
, 或rw
?
在下面的答案中,我将向您展示实现您想要的几种方法。我将使用不同的方法来使用 radre2 来做到这一点。
首先,让我们用更长的字符串创建一个程序:
$ 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
并在radare2中打开它:
$ r2 helloworld
现在我们有了一个很小的二进制文件,我们可以开始了。
使用该iz
命令可以列出数据部分中的字符串。对于每个字符串,您可以看到它所属的部分:
[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
当然,您始终可以使用radare 的内部grep ( ~
) 仅获取相关列:
[0x000005b0]> iz~[5,7]
(.rodata) Hello
(.rodata) World
(.rodata) Byebye
与 不同iz
,该命令izz
将在整个二进制文件中搜索字符串。此命令将向您显示更多的字符串,iz
但它也会在其他部分中搜索字符串。
[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
...
同样,您可以看到radare2 向您显示每个字符串的部分名称。如果您正在搜索特定的字符串,grep 是您的朋友:
[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
在这种方法中,您已经知道字符串的地址,并且您想知道它属于哪个部分。让我们以“你好”为例。我们看到“你好”地址是0x000007b4
。让我们使用验证ps
(p RINT小号特林):
[0x000005b0]> ps @ 0x000007b4
Hello
如您所见,我们打印了一个以零结尾的字符串0x07b4
(“@”是radare 的临时搜索)。现在我们确定这是“Hello”的地址,我们可以使用iS.
来显示当前的Section名称:
[0x000005b0]> iS. @ 0x07b4
Current section
00 0x000007b0 25 0x000007b0 25 -r-- .rodata
正如预期的那样,该地址属于该.rodata
部分。就像我们之前看到的那样。
最后,您想检查节的属性是只读还是读写。使用iS
您可以列出所有部分,包括它们的属性:
[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
或者,用于iSq
显示更简洁的输出(q表示quiet),您还可以 grep 用于读写部分:
[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
如果您想查看只读部分,请像这样使用 grep iS~r--
。