#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...
}
目前,此功能将输出&#34; 8Z&#34;无论interrupt()方法做什么。我试图修改它,以便打印&#34; 3Y&#34;不改变原始main函数中的任何内容,只使用interrupt()函数(不允许传递参数!)。我被允许在interrupt()函数中使用变量,但我很困惑,因为你如何获得&#39; n&#39;和&#39; c&#39;没有制作全局变量,这会破坏这个问题的目的。由于堆栈的地址每次运行都会改变,因此似乎不是一种做指针运算的方法(这是我需要做的事情),因此我有点困惑和卡住。 / p>
答案 0 :(得分:2)
免责声明:请勿在生产代码中尝试使用此功能
我把它作为一个谜题并继续解决它。您说您不能修改main
。我冒昧地稍微修改main
- 打印n
和c
的地址。
int main()
{
int n = 8;
char c = 'Z';
printf("%p %p\n", &n, &c);
interrupt();
printf("%d%c\n", n, c);
}
我还修改了interrupt
一点,也打印了一个地址的值。
void interrupt() {
int i = 10;
char* np = (char*)&i;
char* cp = (char*)&i;
printf("%p %p\n", np, cp);
printf("%p\n", &i);
}
当我运行程序时,我得到以下输出:
0x22cb0c 0x22cb0b
0x22cabc 0x22cabc
0x22cabc
8Z
从输出中,我能够计算&n
中main
与&i
中interrupt
之间的偏移量,以及&c
中main
之间的偏移量{1}}和&i
中的interrupt
。现在,我可以操纵偏移量,使np
中的cp
和interrupt
指向n
中的c
和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);
}
对interrupt
进行更改后,我得到以下输出:
0x22cb0c 0x22cb0b
0x22cb0c 0x22cb0b
0x22cabc
3Y
通过稍微改变main
来完成任务。如果您根本不允许更改它,则必须使用其他程序来计算偏移量。
答案 1 :(得分:1)
通过@Alex Skalozub所说的,您可以获得堆栈偏移并修改调用函数中的局部变量。
您可以: 1.研究编译器和OS手册以计算堆栈偏移量。
或者 2.编写一个小函数来在运行时获取它。如下所示。
int get_stack_offset(void)
{
long dummy1;
return dummy_call(&dummy1) + sizeof(dummy1);
}
int dummy_call(int address)
{
long dummy2;
return &dummy2 - address;
}
然后你可以
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
// ...
}
*假设堆栈正在增加。当它减少时,你需要反转+/-运算符。
*我不考虑对齐,也许你需要。
*这是一个很好的解释,你可以参考。 Does stack grow upward or downward?