9

I'm following the example in the Art of Exploitation book to try and disassemble a program in C, while the book comes with its own Linux LiveCD, I prefer using BT5 (32 bit).

The code example is very simple - (I've used it the same)

#include <stdio.h>

int main()
{
  int i;
  for(i=0; i < 10; i++)       // Loop 10 times.
  {
    puts("Hello, world!\n");  // put the string to the output.
  }
  return 0;                   // Tell OS the program exited without errors.
}

The author is using

gcc file_name.c

to compile the code, and I use the almost the same syntax but with -o in order to save the compiled path to where I want.

Then he uses the command -

objdump -D loop | grep -A20 main.:

to examine the compiled binary.

This is his output -

reader@hacking:~/booksrc $ objdump -D a.out | grep -A20 main.:
08048374 <main>:
 8048374:       55                      push   %ebp
 8048375:       89 e5                   mov    %esp,%ebp
 8048377:       83 ec 08                sub    $0x8,%esp
 804837a:       83 e4 f0                and    $0xfffffff0,%esp
 804837d:       b8 00 00 00 00          mov    $0x0,%eax
 8048382:       29 c4                   sub    %eax,%esp
 8048384:       c7 45 fc 00 00 00 00    movl   $0x0,0xfffffffc(%ebp)
 804838b:       83 7d fc 09             cmpl   $0x9,0xfffffffc(%ebp)
 804838f:       7e 02                   jle    8048393 <main+0x1f>
 8048391:       eb 13                   jmp    80483a6 <main+0x32>
 8048393:       c7 04 24 84 84 04 08    movl   $0x8048484,(%esp)
 804839a:       e8 01 ff ff ff          call   80482a0 <printf@plt>
 804839f:       8d 45 fc                lea    0xfffffffc(%ebp),%eax
 80483a2:       ff 00                   incl   (%eax)
 80483a4:       eb e5                   jmp    804838b <main+0x17>
 80483a6:       c9                      leave
 80483a7:       c3                      ret
 80483a8:       90                      nop
 80483a9:       90                      nop
 80483aa:       90                      nop
reader@hacking:~/booksrc $

and this is my output for the same program -

root@bt:~# objdump -D loop | grep -A20 main.:

080483e4 <main>:
 80483e4:   55                      push   %ebp
 80483e5:   89 e5                   mov    %esp,%ebp
 80483e7:   83 e4 f0                and    $0xfffffff0,%esp
 80483ea:   83 ec 20                sub    $0x20,%esp
 80483ed:   c7 44 24 1c 00 00 00    movl   $0x0,0x1c(%esp)
 80483f4:   00 
 80483f5:   eb 11                   jmp    8048408 <main+0x24>
 80483f7:   c7 04 24 e0 84 04 08    movl   $0x80484e0,(%esp)
 80483fe:   e8 15 ff ff ff          call   8048318 <puts@plt>
 8048403:   83 44 24 1c 01          addl   $0x1,0x1c(%esp)
 8048408:   83 7c 24 1c 09          cmpl   $0x9,0x1c(%esp)
 804840d:   7e e8                   jle    80483f7 <main+0x13>
 804840f:   b8 00 00 00 00          mov    $0x0,%eax
 8048414:   c9                      leave  
 8048415:   c3                      ret    
 8048416:   90                      nop
 8048417:   90                      nop
 8048418:   90                      nop
 8048419:   90                      nop
 804841a:   90                      nop
root@bt:~# 

Do you think there's a difference because I'm not using the same Linux Distribution? It also looks like his code is calling the printf() function while mine is calling the puts() function (like he used in his example).

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
YSY
  • 1,226
  • 3
  • 13
  • 19
  • There's no way `puts("...")` can compile to `call printf@plt`. The other way around, yes for sure, that's a minor optimization. [gdb disassembly doesn't match book](https://stackoverflow.com/q/24239401) shows an image of the code from the same book but with `printf` in the source; perhaps this is first edition and is a typo or mismatch between the book's example C and asm. Also, `puts("...\n")` will print a blank line because `puts` implicitly appends a newline, so that's unusual. – Peter Cordes Feb 07 '21 at 21:00

3 Answers3

6

It doesn't have to be the OS difference, it's enough if you use different version of GCC to produce different machine code / assembly code.

Regarding puts / printf - the compiler uses whatever it decides better (in terms of efficiency, security etc.) when you call printf with no format, there is no need for it, so he uses puts which is faster.

MByD
  • 135,866
  • 28
  • 264
  • 277
  • I'm reading that book too. It explains also how to exploit printf's format-string "issue". From what I've understood from your answer, it seems gcc might prefer using puts in this kind of programs. Is there a way to tell it we want to use printf instead of puts? – BlackBear Aug 07 '11 at 20:50
  • 2
    @MByD - The compiler **does** parse the format string and warns about any discrepancies... – Bo Persson Aug 07 '11 at 22:06
  • Thanks, I hope I'll succeed with undetstanding the differences, @BlackBear, do you happend to have the book source files? Thanks! – YSY Aug 08 '11 at 05:27
  • 1
    @YSY: I have the book with the cd. Here's the iso for it: http://www.mininova.org/tor/2533556 – BlackBear Aug 08 '11 at 11:33
1

Even if you use the same compiler (gcc) there is no expectation that compiling on different machines on the same day or the same machine on different days will give the same result.

Different versions of gcc, 32 bit vs 64 bit, etc. if you didnt install gcc yourself to exactly match a gcc installed by the author then you likely have a different version and the expectation is the code will be different.

Once you add optimizations and other command line options (related to code generation, -o is not one of those) the differences on the same machine the same day vary dramatically.

I would hope that is not the point of the book, I would expect it teaches you these differences but how to take advantage of some things when you do happen to see them produced. Basically go with what the book came up with as it is probably related to what the book is trying to teach.

bottom line expect the same code to never build the same, some compilers go so far as to put a time stamp in the file insuring that no two builds will never exactly match. gcc in particular is constantly evolving and no two people build it the same way so even with the same source version you can see differences in the output.

old_timer
  • 69,149
  • 8
  • 89
  • 168
0

Different version of the compiler probably. Yours is optimizing the call to printf - since there is really not format string, calling puts could be slightly faster.

Mat
  • 202,337
  • 40
  • 393
  • 406