Why no corresponding subroutine call in machine code dump when calling strcpy()?

2

I am working through the book 'Hacking: The Art of Exploitation' by Jon Erickson.

In one part of the book he gives C code and then walks through the corresponding assembly using gdb, explaining the instructions and memory activity.

I am working along in Mac OS X, so things are a bit different than he presents in the book (he is using Linux).

Anyway, I have this C program:

1 #include <stdio.h>
2 #include <string.h>
3 
4 int main()
5 {
6         char str_a[20];
7 
8         strcpy(str_a, "Hello, world!\n");
9         printf(str_a);
10 }

Here is the corresponding otool object dump (I have just included main):

_main:
0000000100000ea0    pushq   %rbp
0000000100000ea1    movq    %rsp,%rbp
0000000100000ea4    subq    $0x30,%rsp
0000000100000ea8    movq    0x00000189(%rip),%rax
0000000100000eaf    movq    (%rax),%rax
0000000100000eb2    movq    %rax,0xf8(%rbp)
0000000100000eb6    leaq    0xd4(%rbp),%rax
0000000100000eba    movq    %rax,%rcx
0000000100000ebd    movq    $0x77202c6f6c6c6548,%rdx
0000000100000ec7    movq    %rdx,(%rcx)
0000000100000eca    movb    $0x00,0x0e(%rcx)
0000000100000ece    movw    $0x0a21,0x0c(%rcx)
0000000100000ed4    movl    $0x646c726f,0x08(%rcx)
0000000100000edb    movq    %rcx,0xe8(%rbp)
0000000100000edf    xorb    %cl,%cl
0000000100000ee1    movq    %rax,%rdi
0000000100000ee4    movb    %cl,%al
0000000100000ee6    callq   0x100000f1e ; symbol stub for: _printf
0000000100000eeb    movl    0xf4(%rbp),%eax
0000000100000eee    movq    0x00000143(%rip),%rcx
0000000100000ef5    movq    (%rcx),%rcx
0000000100000ef8    movq    0xf8(%rbp),%rdx
0000000100000efc    cmpq    %rdx,%rcx
0000000100000eff    movl    %eax,0xd0(%rbp)
0000000100000f02    jne 0x100000f0d
0000000100000f04    movl    0xd0(%rbp),%eax
0000000100000f07    addq    $0x30,%rsp
0000000100000f0b    popq    %rbp
0000000100000f0c    ret
0000000100000f0d    callq   0x100000f12 ; symbol stub for: ___stack_chk_fail

OK. You will notice the subroutine call to printf():

0000000100000ee6    callq   0x100000f1e ; symbol stub for: _printf

But where is the call to strcpy()?

There are two further anomalies. First of all, if I set a breakpoint in gdp for strcpy():

break strcpy

The program zips through its execution without stopping. It seems as if strcpy() isn't actually getting called.

Second, when I compiled the code:

gcc -g -o char_array2 char_array2.c

I got a warning:

char_array2.c: In function ‘main’:
char_array2.c:9: warning: format not a string literal and no format arguments
char_array2.c:9: warning: format not a string literal and no format arguments

I'm not sure if that is related to the missing subroutine call, but I thought I would include it as a data point anyway.

It almost seems to me as if the compiler has decided strcpy() is not necessary and has optimised the code to work without it. The program does work as expected, printing 'Hello, world!' to the standard output, but this missing call to strcpy() has me wondering exactly what is happening.

In Erickson's example in the book there is a call to strcpy() so perhaps there is a difference in how his compiler and my compiler are working. I am on LLVM:

i686-apple-darwin11-llvm-gcc-4.2

Any ideas would be gratefully received!

Thanks in advance, and I hope you find this one interesting.

Tom

c
macos
assembly
gdb
asked on Stack Overflow Jan 22, 2012 by Tom Scrace

1 Answer

9

It's right here:

0000000100000ebd    movq    $0x77202c6f6c6c6548,%rdx
0000000100000ec7    movq    %rdx,(%rcx)
0000000100000eca    movb    $0x00,0x0e(%rcx)
0000000100000ece    movw    $0x0a21,0x0c(%rcx)
0000000100000ed4    movl    $0x646c726f,0x08(%rcx)

User contributions licensed under CC BY-SA 3.0