Lets suppose I have simple C program and I compile it with gcc -o hello hello.c
:
#include<stdio.h>
main()
{
printf("hello");
}
Now I want to display "strings" with the strings
utility:
$ strings hello
/lib64/ld-linux-x86-64.so.2
__gmon_start__
libc.so.6
printf
__libc_start_main
GLIBC_2.2.5
fffff.
l$ L
t$(L
|$0H
hello
;*3$"
and, as expected, I can see the string "hello" in the binary.
However, when I modify my C
program and put "hello" as a constant:
#include<stdio.h>
char s[6] = {'h','e','l','l','o','\0' } ;
main()
{
printf("%s\n", s);
}
I don't see the string "hello" in the binary anymore.
Can somebody please explain why ?
Its name is quite self-explanatory, it retrieves any printable string from a given file. strings [ - ] [ -a ] [ -o ] [ -t format ] [ -number ] [ -n number ] [--] [file ...]
If you are using process hacker, just select the process with the strings you want to find->Properties->Memory. Then, in the top right corner, you should see a strings... button. That will search for all strings in the process.
When referring to a download or program, binaries are compiled code that allow a program to be installed without having to compile the source code. Many open source programs offer downloads in source format. This format allows users to view the code, but also requires the code to be compiled or in binaries format.
From man 1 strings
(emphasis mine):
For each file given, GNU strings prints the printable character sequences that are at least 4 characters long (or the number given with the options below) and are followed by an unprintable character. By default, it only prints the strings from the initialized and loaded sections of object files; for other types of files, it prints the strings from the whole file.
The C language does not define strings as first-class citizens. They are expressed as either string arrays or strings literals. For instance, in such basic program:
#include <stdio.h>
int main(void)
{
char s[] = "my string";
printf("%s\n", s);
return 0;
}
we can reasonably say that s
array holds a string. Notice that this one is allocated on stack. It has automatic storage duration, as opposite to example in your question, where s
is clearly defined outside of main
(and any) function.
Now, backing to your question, both underlying objects in your two programs share the same characteristics:
char[6]
and have the same content (C11 §6.2.5/p20),The only difference is that modyfing a string literal invokes undefined behaviur, thus compiler may choose to place them into seperate (e.g. read-only) memory location.
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.
All objects with static storage duration shall be initialized (set to their initial values) before program startup.
Looking from more practical viewpoint, beside that strings
command you might also analyze your programs with gdb
debugger, more specifically using x/s
command. Here is basic illustration:
$ gcc -g hello.c -o hello
$ gdb -q hello
Reading symbols from /home/grzegorz/hello...done.
(gdb) disas /m main
Dump of assembler code for function main:
6 {
0x00000000004004c4 <+0>: push %rbp
0x00000000004004c5 <+1>: mov %rsp,%rbp
7 printf("%s\n", s);
0x00000000004004c8 <+4>: mov $0x60086c,%edi
0x00000000004004cd <+9>: callq 0x4003b8 <puts@plt>
8 }
0x00000000004004d2 <+14>: leaveq
0x00000000004004d3 <+15>: retq
End of assembler dump.
(gdb) x/s 0x60086c
0x60086c <s>: "hello"
You might want to compare results of disas
command for your programs and see if there is some discrepancy between them.
I don't see the string "hello" in the binary anymore.
I'd consider this expected valid behaviour, as you aren't providing the literal "hello"
anymore, but 6 seperate char
literals instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With