Reputation: 63
#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
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
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