8

I was trying to replicate the experiment in Gray Hat Hacking - Third Edition, Chapter 12, about Format String Exploits, but their architecture is IA32, while mine is AMD 64bits. Therefore when I check for values in stack with commands like:

$ ./fmtstr "AAAAAAAA %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x %08x"   

Nothing showing up, that resembles its representation in memory (41414141 41414141). Why is the exploit buffer not returning actual and sequential memory data?? For more info please see his console image Help!.

Fernando Pérez
  • 133
  • 2
  • 7
  • Even though you found this in a security book, the core question here is about assembly language, no the actual security. I'm voting to close this question as "off-topic". – Mike Ounsworth Apr 10 '17 at 02:00
  • Not at all. This question is on the classic Format String Vulnerability and its exploitation, no assembly syntax is discussed Mike. – Fernando Pérez Apr 10 '17 at 13:46
  • I love that you're trying to argue with me, that's hilarious. The only question mark is "Is it the x64 bit architecture messing with me?" That is clearly an ASM question, not a question about security concepts. Oh well, I've cast my vote, we'll see what the rest of the community thinks. – Mike Ounsworth Apr 10 '17 at 13:54
  • No need to get defensive Mike! Arguing (in a respectful manner) is the essence of progress, don't feel offended. And please refrain of using sarcasm as it is not helpful at all, which is the main purpose of the site. – Fernando Pérez Apr 10 '17 at 15:29
  • Upvoted. Happy that although some people voted to close this it is still possible to find it. – robert Feb 27 '18 at 17:50

1 Answers1

6

If you're using the example code from the book (below), at some point you should reach the "AAAAAAAA" pattern (0x41). Note that, since you're running it on a 64-bit machine that stores elements in the stack with 8 bytes each, you should run it with $ ./fmtstr "AAAAAAAA %016x %016x %016x %016x %016x %016x %016x %016x %016x %016x %016x %016x %016x" instead, or you will miss part of each element on the stack.

#include <stdlib.h>
int main(int argc, char *argv[]){
        static int canary=0;   // stores the canary value in .data section
        char temp[2048];       // string to hold large temp string
      strcpy(temp, argv[1]);   // take argv1 input and jam into temp
      printf(temp);            // print value of temp
      printf("\n");            // print carriage return
      printf("Canary at 0x%08x = 0x%08x\n", &canary, canary); //print canary
}

You should pay attention to the quote in the book that states:

The fact that the fourth item shown (from the stack) was our format string depends on the nature of the format function used and the location of the vulnerable call in the vulnerable program. To find this value, simply use brute force and keep increasing the number of %08x tokens until the beginning of the format string is found. For our simple example (fmtstr), the distance, called the offset, is defined as 4.

Remember that the parameter being parsed to printf isn't the string itself, but the address of the string. So it's position on the memory layout of the program in relation to the printf stack is what will define how further you'll have to search to find it.

  • I had a similar observation, but when I run with x016 instead of x08 I get printed out, values that don't correspond to the stack frame, I created a breakpoint right after the print, and values printed don't match those from: `gdb$x/120x $rsp.` With x08 they match, but only showing 8bytes and skipping 8, and so on... With x016, it prints out values like 0000000008405109 and that value is nowhere to be found in the Stack Frame. – Fernando Pérez Apr 07 '17 at 18:48
  • Making some quick tests here the values when using `%08x` and `%016x` match, except on some of the elements on the stack, which is expected. There are values that change on each execution on the stack, like canary values, or some addresses stored there that might be randomized because of ASLR. Truth is, the stack isn't as simple now as it used to be on the old days. I'm not sure I'm getting you problem though, you're failing to find the parsed string on the stack? – murphsghost Apr 07 '17 at 19:32
  • I got the address of SHELL from ./getEnvAddr SHELL and then ran in GDB the program. But as I said, can't find where my printed hex values are in the stack, see this [image of the process](https://image.ibb.co/h2xP1Q/pic1.jpg). – Fernando Pérez Apr 07 '17 at 20:01
  • On 64bit, I've used %#016lx. Without the "l", the parameter is treated as "int" instead of "long". – Les Apr 28 '18 at 11:25
  • Why if I enter a memory address instead of `AAAA`, only four bytes are printed? – Eye Patch Apr 16 '20 at 20:03
  • @Fernando Since this question is still around, note that on amd64, arguments are not initially passed on the stack, but rather registers. The format string is in RDI, the next arguments are pulled from RSI, RDX, RCX. _Then_, arguments are taken from the stack. This explains why you are seeing values not on the stack. – multithr3at3d May 15 '20 at 15:08