Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

show strings in compiled binary

Tags:

c

string

gcc

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 ?

like image 750
Martin Vegter Avatar asked Feb 19 '15 11:02

Martin Vegter


People also ask

How do I find a string in binary?

Its name is quite self-explanatory, it retrieves any printable string from a given file. strings [ - ] [ -a ] [ -o ] [ -t format ] [ -number ] [ -n number ] [--] [file ...]

How to search strings in an executable?

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.

What is a compiled binary?

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.


2 Answers

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:

  • they are of type char[6] and have the same content (C11 §6.2.5/p20),
  • they have static storage duration, meaning that they must be initialized conceptually before program's execution (C11 §5.1.2/p1).

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.

C11 §6.2.5/p20 Types:

An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.

C11 §5.1.2/p1 Execution environments:

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.

like image 100
Grzegorz Szpetkowski Avatar answered Sep 30 '22 18:09

Grzegorz Szpetkowski


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.

like image 45
alk Avatar answered Sep 30 '22 18:09

alk