J...S
J...S

Reputation: 5207

Tim Newsham format string exploit

I was reading Tim Newsham's white paper on format string exploits and found some parts in the beginning difficult to understand.

The following program was being discussed.

/*
 * fmtme.c
 *       Format a value into a fixed-size buffer
 */

#include <stdio.h>

int
main(int argc, char **argv)
{
    char buf[100];
    int x;
    if(argc != 2)
        exit(1);
    x = 1;
    snprintf(buf, sizeof buf, argv[1]);
    buf[sizeof buf - 1] = 0;
    printf("buffer (%d): %s\n", strlen(buf), buf);
    printf("x is %d/%#x (@ %p)\n", x, x, &x);
    return 0;
}

Author says "All examples in this document were actually performed on an x86 BSD/OS 4.1", a little-endian machine.

The program is executed like

% ./fmtme "%x %x %x %x"
buffer (15): 1 f31 1031 3133
x is 1/0x1 (@ 0x804745c)

The paper says:

"A quick analysis of the program will reveal that the stack layout of the
program when the snprintf function is called is:

    Address  Contents       Description
    fp+8     Buffer         pointer 4-byte address
    fp+12    Buffer         length 4-byte integer
    fp+16    Format         string 4-byte address
    fp+20    Variable x     4-byte integer
    fp+24    Variable buf   100 characters

The four values output in the previous test were the next four arguments on
the stack after the format string: the variable x, then three 4-byte
integers
taken from the uninitialized buf variable."

What is fp here? File pointer?

And why does it start from fp+8 and not fp+4 when the increments are by 4 everwhere else (4-byte address)?

Here, does larger address mean the value is higher up or lower down the stack?

What does the names given under 'Contents' mean?


And when I run the above program, the value of x, ie, 1, is not being printed. Maybe because of different architecture?

I get like this

./fmtme "%x %x %x %x"
buffer (34): cd512860 b3356d80 b3356d80 8247ee8
x is 1/0x1 (@ 0x7ffc08247d8c)

Can anyone help?

Upvotes: 0

Views: 130

Answers (1)

caf
caf

Reputation: 239021

  • fp stands for "frame pointer".

  • The arguments start at fp+8because fp+4 is the return address and fp+0 is the saved frame pointer.

  • In a conventional grows-down stack as x86 uses, higher addresses are deeper in the stack (items that were pushed earlier).

The Contents is a little bit unclear - it's trying to describe what's in that stack slot but some of them don't have names. This might be clearer:

Address  Contents                  Description
fp+8     First snprintf argument   pointer 4-byte address
fp+12    Second snprintf argument  length 4-byte integer
fp+16    Third snprintf argument   string 4-byte address
fp+20    Variable x in main        4-byte integer
fp+24    Variable buf in main      100 characters

You don't see the same result because these kinds of things - formally undefined behaviour - are highly sensitive to the architecture, compiler and compiler version you're using. It appears from the pointer value printed with %p that you're using a 64 bit architecture - if you're using x86-64, then then first 6 integral arguments to a function are passed in registers, not on the stack, so that's where your bogus %x formats are going to start looking. You could try compiling for x86 with the -m32 compiler option, but there's no guarantees.

Upvotes: 2

Related Questions