7

I would like to make a checksum of the current stack in the main, in order to check if it has been altered between two points.

For example:

int main(void) {
    ...
    stack_checksum();

    ... process ...

    if(stack_checksum() != ...)
        altered.
}

How can I grab the base stack address and the current address of the stack's top ?

EDIT: With @Miroslav Bajtoš help, step for approach:

  • Put local variable in a structure
  • Check backtrace return array
Maxux
  • 199
  • 1
  • 1
  • 11
  • 2
    Despite the fact it's only main, I dare say it will be platform dependent. You may benefit from studying the way variable argument lists are handled. Check out `stdarg.h` on your platform. – StoryTeller - Unslander Monica Jan 13 '13 at 17:41
  • @StoryTeller The variable argument list is probably implemented with `__builtin_va_list`, `__builtin_va_arg()`, etc... – qwertz Jan 13 '13 at 18:03

2 Answers2

6

It depends on which compiler/implementation of standard library you are using.

For gcc (or any other compiler that uses glibc), you can use backtrace() functions in execinfo.h - see these answers for more details: How to generate a stacktrace when my gcc C++ app crashes and How to get more detailed backtrace

For Microsoft compiler, you can use StackWalk64() function, see this article for more details: Walking-the-callstack. There was also a similar quesion asked here on StackOverflow: StackWalk64 on Windows - Get symbol name

Computing checksum should be easy once you can walk the stack.

Community
  • 1
  • 1
Miroslav Bajtoš
  • 10,667
  • 1
  • 41
  • 99
  • The array returned by backtrace contains stack and code segments address, no ? I get the main addres (0x8048...), etc. but not the stack address, no ? – Maxux Jan 13 '13 at 18:25
  • Yes, you have a complete stack of called functions (including the code segment address, as you pointed out). Did you want to read something else instead? – Miroslav Bajtoš Jan 13 '13 at 18:36
  • If it's possible to get the address of the base pointer and the stack length, it will be easy to checksum it. I guess that called functions address will not help. The answer of @Cooday seems good but need asm inline. – Maxux Jan 13 '13 at 20:29
  • @Maxux OK, why do you want to checksum the stack in the first place? What are you trying to achieve? Verifying that local variables has same values? – Miroslav Bajtoš Jan 14 '13 at 09:34
  • Overall, yes. In fact it's to check if the process (cf code on original post) don't alter the stack (overflow, ...). – Maxux Jan 14 '13 at 13:56
  • 1
    Well, if you want to check variable values, then maybe you can put them in a custom structure and then you can compute hash of this structure. BTW, comparing variables on the stack won't be very reliable. Think about **argv parameter of main: argv value stays still the same even if value of argv[0] was modified. – Miroslav Bajtoš Jan 14 '13 at 14:44
3

I think you will have to use inline assembly for this. The following code stores the current values of the base pointer and the current pointer in base and current. It's for gcc on a 64-bit machine:

// make these variables global (if not, the stack registers would change)
void *base, *current;
__asm__("movq %%rbp, %0;"
        "movq %%rsp, %1;"
        : "=r"(base), "=r"(current)
        :
        :
);

If you are on a 32-bit machine you have to use ebp and esp instead of rbp and rsp and movl instead of movq.
I recommend you to check out this inline assembly tutorial for gcc if you have any questions with the syntax.

qwertz
  • 14,614
  • 10
  • 34
  • 46