-3

my doubt is the following: assuming Ubuntu 14.04 32bit and x_86 intel atom cpu how many bytes does the format %x read from stack? I know that I can read what's in the stack by using:

formatstring="%x";
printf(formatstring);

As I put more %x in the formatstring, more data are read from the stack. Since %x takes 4 bytes, every %x should read 4 bytes from the stack, so for example if the 1st %x read what's written at the address 0x0 the 2nd will read what's at address 0x4 and so on.. (obviously the numbers are just for me to make the explanation easier). Is this assumption correct? It seems not since when I tried in an exercise to calculate the address of a var doing known_address + (numberof %x untill_the_var_value_is_printed )* 4 I found a wrong address.

mik1904
  • 1,335
  • 9
  • 18
  • 1
    Probably none, it would typically use a register – M.M Dec 21 '16 at 22:36
  • What do you mean? – mik1904 Dec 21 '16 at 22:42
  • 5
    C knows nothing about stacks. (Indeed, `register` keyword notwithstanding, it knows nothing about registers, either.) Your code exhibits undefined behavior because there are insufficient arguments for the format. Anything could happen. You can study the behavior of a particular version of a particular implementation, but you cannot generalize that. And as for me, I don't find studying manifestations of undefined behavior very intersting. – John Bollinger Dec 21 '16 at 22:43
  • @JohnBollinger I'm doing an system security course on my 2nd of my MSc and we are looking at format string vulnerability and in this case using %x it actually prints 4 bytes from the stack – mik1904 Dec 21 '16 at 22:48
  • 5
    Typically the first few arguments are passed in [registers](https://en.wikipedia.org/wiki/Processor_register), not the stack – M.M Dec 21 '16 at 22:49
  • From the manual:: `o, u, x, X The unsigned int argument is converted to unsigned octal (o), unsigned decimal (u), or unsigned hexadecimal (x and X) ` --- so %x expects an unsigned int. – wildplasser Dec 21 '16 at 22:50
  • @mik1904, maybe in your case it does print 4 bytes from the stack, and in that case I guess you have then answered your own question. Anyway, if you want to pose a question about a particular C implementation then it is incumbent on you to *specify the implementation*. I'll not help you with such a question, but perhaps someone else will. – John Bollinger Dec 21 '16 at 22:54
  • 1
    @M.M Does it typically use registers for variadic functions like `printf`? – Barmar Dec 21 '16 at 22:55
  • @Barmar Yes, [see here for example](http://stackoverflow.com/questions/20301201/calling-printf-from-inline-asm-x64) – M.M Dec 21 '16 at 22:59
  • 1
    The OP specifies 32-bit Linux. It doesn't specify a processor architecture, but doesn't Linux on ia32 typically use cdecl, in which all parameters are passed on the stack? – user3553031 Dec 21 '16 at 23:36
  • 3
    @JohnBollinger: For one who is studying software security, the manifestations of undefined behaviour are *very* interesting. If one wants to abuse a software bug to get RCE, or if one wants to implement a migitation that makes it more difficult to do so, then one needs to understand what actually happens on various platforms when undefined behaviour is invoked. However, you are correct that the OP should have been more precise about what platform it is using. Since it it outside of the semantics of C, this sort of question might be more appropriate on https://security.stackexchange.com. – user3553031 Dec 21 '16 at 23:48
  • @user3553031: "32 bit Linux" covers many very different architectures already. Including: x86, multiple ARM-versions, PPC, MIPS, SuperH to state the most common. All have very different ABIs, the RISC often use registers for the first arguments. The question is far too broad. – too honest for this site Dec 22 '16 at 00:28

1 Answers1

2

As far as the C standard is concerned, the question is not meaningful.

A %x format specifier requires a corresponding argument of type unsigned int. (unsigned int and int are more or less interchangeable as arguments, as long as the value is within the representable range of both types.) The standard doesn't explicitly say so, but it doesn't define the behavior.

If a particular compiler generates code that passes unsigned int arguments to variadic functions on the stack (a term the C standard doesn't use), then printf might read sizeof (unsigned int) bytes from the stack for each %x specifier. On other implementations, it might attempt to read arguments from registers, or from somewhere else. Also, sizeof (unsigned int) can vary from one implementation to another. In principle, it could even vary with compile-time optimization levels.

If you want to know about how something like printf("%x") will actually behave, you'll need to specify the particular implementation you're using, both the target OS and hardware and the compiler you're using. "32-bit Linux" is not nearly specific enough. Since C implementations are not required to document this, it might be difficult to get the details.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631