I am trying to carry out a simple format string attack on this program:

#include <stdio.h>

int main(int argc, char *argv[])

I face no problem leaking the stack in the usual way by passing a format string like this:

./test "%x %x %x %x"

or with direct parameter access like this:

./test "%4\$x"

Next, I am trying to find out the location (nth parameter) of the format string itself in the stack this way:

 for ((i = 1; i < 200; i++)); do echo -n "$i " && ./test "AAAAAAAA%$i\$x" 0; done | grep 4141

Once I know the value of $i (let's say 134) where the "AAAA..." string appears, I should be able to read off arbitrary addresses like this:

./test $'\xaa\xbb\xcc\xdd%134\$s' 

I guess it's the traditional way of leaking information through a format string bug (as described in The Shellcoder's Handbook).

However, the format string I am passing is not nicely packed in a discrete $ith parameter (I don't have a better way to phrase it). Interestingly, half of it is present in 133 (upper word) and half of it in 134 (lower word). How am I supposed to pass arbitrary addresses as mentioned above in this situation? I am assuming I have to use a different sort of formatting to catch the exact address, but I am not sure how to proceed.

Also, ./test $'\xaa\xbb\xcc\xdd%134$s', simply prints off the ascii equivalent of those hex values. The argument doesn't exactly work as it is supposed to (I hope I am clear in what I am trying to achieve here). What is the proper way to pass these addresses?

If it helps, I am on Ubuntu12 i386 and using Bash.

1 Answer 1


It was rather trivial. Modifying the previous example a bit,

for ((i = 1; i < 200; i++)); do echo -n "$i " && ./test "BBAAAACC%$i\$x" 0; done | grep 4141

the upper word of location 129 is filled with the B's, and the lower word of location 131 is filled with the C's - with the A's nicely sandwiched in the middle at location 130. So I simply had to pass the address padded with two extra bytes both at the beginning and at the end. I also figured out how to pass the hex values with printf in bash.

To verify it's working, I picked up the address (0xbffffe2c) of a known string "HOME=/home/arman" and passed it as an argument like this:

./test AA$(printf "\x2c\xfe\xff\xbf")AA%130\$s

Bingo! The string is printed like this:


EDIT: The padding at the beginning is not really required. This works perfectly as well:

./test $(printf "\x2c\xfe\xff\xbf")AA%130\$s

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .