1
#include <stdio.h>

void interrupt();

int main() {
 int n = 8;
 char c = 'Z';
 interrupt();
 printf("%d%c\n", n, c);
}

void interrupt() {
 printf("Run normally\n");
 //ADD CODE...
}

As it stands, this function will output "8Z" regardless of what the interrupt() method does. I am attempting to modify it such that it prints "3Y" without changing anything in the original main function, and only using the interrupt() function (not allowed to pass arguments!). I am allowed to use variables in the interrupt() function, but I am confused to as how you obtain the addresses of 'n' and 'c' without making a global variable, which would defeat the purpose of this question. Since the address of the stack changes every time this runs, there doesn't seem to be a way to do pointer arithmetic (which is what I need to do), and therefore I'm a bit confused and stuck.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Senescence
  • 63
  • 1
  • 7
  • Is that a real programming question? where did you find it? – Mehrdad Feb 04 '16 at 04:01
  • Yes, it's a programming question. I suppose the point of the assignment was to have you modify what main() prints out using pointer arithmetic in another function, but my question is how can you access that information without using a global variable or passing parameters. Unless it's not possible. – Senescence Feb 04 '16 at 04:05
  • 2
    There's no solid cross-platform solution for that. But knowing the compiler specifics and system ABI you can calculate stack offsets and thus modify the stack of the calling function (given that its local variables are actually allocated on stack and not in registers). – Alex Skalozub Feb 04 '16 at 04:11
  • 1
    It's not possible if you stay within the rules of the language. The question is asking you to break the rules, with stuff along the lines of `int n; *(&n + 4) = 3;`, and try and get some *particular* weirdness to happen (rather than crashing, seeming to work, or getting random weirdness). (Also, that code snippet was made up to show the general idea) – user253751 Feb 04 '16 at 04:17
  • Agreed @Alex Skalozub. It's the only way to do it. – Holsety Feb 04 '16 at 04:24
  • Looks like an XY-problem or another stupid homework constraint give by someone without true software-development experience. (Or too little to use a real-world example for whatever he wants to teach here). – too honest for this site Feb 04 '16 at 12:16

2 Answers2

2

Disclaimer: Don't attempt to use this in production code

I took this as a puzzle and proceeded to solve it. You said you are not allowed to modify main. I took the liberty of modifying main slightly -- to print the addresses of n and c.

int main()
{
   int n = 8;
   char c = 'Z';

   printf("%p %p\n", &n, &c);

   interrupt();
   printf("%d%c\n", n, c);
}

I also modified interrupt a little bit, also to print the values of an address.

void interrupt() {
   int i = 10;
   char* np = (char*)&i;
   char* cp = (char*)&i;

   printf("%p %p\n", np, cp);
   printf("%p\n", &i);
}

When I ran the program, I got the following output:

0x22cb0c 0x22cb0b
0x22cabc 0x22cabc
0x22cabc
8Z

From the output, I am able to compute the offset between &n in main and &i in interrupt, and the offset between &c in main and &i in interrupt. Now I can manipulate the offset to make np and cp in interrupt to point to n and c in main.

void interrupt() {
   int i = 10;
   char* np = (char*)&i;
   char* cp = (char*)&i;

   np += (0x22cb0c - 0x22cabc);
   cp += (0x22cb0b - 0x22cabc);

   *(int*)np = 3;
   *cp = 'Y';

   printf("%p %p\n", np, cp);
   printf("%p\n", &i);
}

With the changes to interrupt, I get the following output:

0x22cb0c 0x22cb0b
0x22cb0c 0x22cb0b
0x22cabc
3Y

Mission accomplished by changing main a little bit. If you are not allowed to change it at all, you'll have to use a different program to compute the offsets.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
1

By what @Alex Skalozub said, you can get the stack offset and modify the local variables in the calling function.

You can: 1. Study the compiler and OS manual to calculate the stack offset.

Or 2. Write a little function to get it at run-time. Like below.

int get_stack_offset(void)
{
    long dummy1;
    return dummy_call(&dummy1) + sizeof(dummy1);
}

int dummy_call(int address)
{
    long dummy2;
    return &dummy2 - address;
}

Then you can just

void interrupt() {
    printf("Run normally\n");
    int stack_offset = get_stack_offset();
    char* c_address = (char*) (&stack_offset - stack_offset);
    int* n_address = (int*) (c_address - sizeof(char));

    // Then, modify them
    *c_address = 'Y';
    *n_address = 3;

    // Other
    // ...
}

*Assuming the stack is increasing. When it is decreasing you need reverse the +/- operator.

*I don't consider about alignment, which maybe you need to.

*And here is a great explanation you can reference. Does stack grow upward or downward?

Community
  • 1
  • 1
Holsety
  • 103
  • 7
  • The helper function may be not quite correct, because different compiler features (like stack protector etc.) may render different stack layout in `main` and `interrupt`, so there will be additional offset. – Alex Skalozub Feb 04 '16 at 06:17
  • @Alex Skalozub Sure. This is just a sample. If want to apply to real code, we need consider much more. – Holsety Feb 04 '16 at 06:48