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
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