2

I'm trying to understand the connection between the stack content at

call   0x555555554580 <printf@plt>

if you execute printf("%lx%lx%lx%lx%lx%lx"). Assume my stack looks like

0x00007fffffffd850│+0x0000: 0x0000000000000001 
0x00007fffffffd858│+0x0008: 0x0000000000000002
0x00007fffffffd860│+0x0010: 0x0000000000000003
0x00007fffffffd868│+0x0018: 0x0000000000000004

before the call <printf@plt>, which value would i normally expect to get back? If i test it in gdb i normally get:

a b c d e 1 2 3 4 ...

where a,b,c,d,e where not on my stack before the call to printf. I assume they where values which where pushed on the stack during the execution of printf. But what is buffling me is that if i do one step into the call of printf@plt. The instruction pointer is pushed onto the stack, so that it will look like this:

0x00007fffffffd848│+0x0000: value of $rip
0x00007fffffffd850│+0x0008: 0x0000000000000001 
0x00007fffffffd858│+0x0010: 0x0000000000000002
0x00007fffffffd860│+0x0018: 0x0000000000000003
0x00007fffffffd868│+0x0020: 0x0000000000000004

Now i would expect my output to contain this value of $rip at output e. But this is not the case. I would be grateful if you could tell my why i don't find this stack value on my output or some content that does go deeper how exactly printf("%x") access the stack.

ASP
  • 33
  • 2
  • 2
    dont try to reason about UB – pm100 Feb 20 '22 at 22:23
  • Can you show your program's source - that is, the entire C function code that has that `printf` statement? – selbie Feb 20 '22 at 22:25
  • Looks like 64-bit code, it uses a calling convention that passes the first 4 or 5 arguments in registers instead of the stack. So you see the register values first. https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions – Hans Passant Feb 20 '22 at 22:40
  • Generally questions tagged [tag:c] are assumed to refer to ISO standard C and nothing else, so from that standpoint there is nothing to say except "undefined behavior". Questions about compiler-generated assembly and exploitation are on topic, but you should tag (and mention in the question) the CPU architecture (x86-64?), operating system/ABI, and compiler if you know it. The [tag:assembly] tag may be appropriate too. – Nate Eldredge Feb 21 '22 at 03:09

1 Answers1

1

which value would i normally expect to get back?

You don't even know that your arguments are passed on any stack or registers, or if your program actually has a stack. Such constructs are not specified by the C language.

From

printf("%lx%lx%lx%lx%lx%lx")

You can not expect any value:

If there are insufficient arguments for the format, the behavior is undefined.

When you invoke undefined behavior, any result is possible - including the compiler refusing to compile your program, your program refusing to run, or your program failing at any point that may appear completely unrelated to the code that invokes undefined behavior.

In practice, the values you get will depend on a number of factors, if your program runs at all. The values printed will depend on the platform, your compilation options, and likely the phase of the moon and the migration patterns of Norwegian storks and other birds. Simply recompiling your code may cause the output to change.

You may be able to exploit particulars in your compiler and environment to produce somewhat predictable output, but that in no way can ever be guaranteed to remain predicatable.

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56