Senescence
Senescence

Reputation: 63

Use pointer arithmetic to change the value of a variable in another function.

#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.

Upvotes: 1

Views: 549

Answers (2)

Holsety
Holsety

Reputation: 103

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?

Upvotes: 1

R Sahu
R Sahu

Reputation: 206647

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.

Upvotes: 2

Related Questions