Executing function_a
Executing function_b
Finished!
和main()
函数已给出,仅允许在标记的部分中更改function_a()
。 。我们必须对堆栈进行操作,以使从function_b()
返回时,我们不会返回其实际父级function_b()
,而是返回其祖父function_a()
。然后将main()
的返回地址和保存的帧指针复制到function_a()
的帧。我的程序执行以下操作:#include <stdio.h>
#include <stdint.h>
void function_b(void) {
char buffer[4];
// edit between here...
uint32_t * x = &buffer;
while (*(x++) != 0xa0b1c2d3); // Find the beacon
*(uint32_t*)(&buffer + 6) = *(x + 2); // Copy return address from caller
*(uint32_t*)(&buffer + 5) = *(x + 1); // Copy frame pointer from caller
// ... and here
fprintf(stdout, "Executing function_b\n");
}
void function_a(void) {
int beacon = 0xa0b1c2d3;
fprintf(stdout, "Executing function_a\n");
function_b();
fprintf(stdout, "Executed function_b\n");
}
int main(void) {
function_a();
fprintf(stdout, "Finished!\n");
return 0;
}
所以它执行正确的操作,但segfault除外。从
function_a()
函数返回时失败。我用gdb来获得此信息:无法理解function_b()
崩溃。我可以看到发生这种情况的唯一方法是,我弄错了main()
的堆栈框架,但我没有弄错,或者我应该在那里更改一些东西,但是我不知道是什么。 注意:该程序使用GCC和标志
function_b()
进行编译。我在64位计算机上。#1 楼
我在64位计算机上。
function_b()
中的代码将指针视为32位值而不是64位值。您应该使用uint64_t*
而不是uint32_t*
。#2 楼
正如Jason所写,我应该使用64位指针。除此之外,事实证明,我必须从堆栈帧中复制四个数字。这是有效的代码:uint64_t * my_ptr = &buf;
int * x = my_ptr;
while (*(++x) != 0xa0b1c2d3); // Find the beacon. We could of course simply have a look
uint64_t * y = x + 1; // with gdb where it's stored, but this works generically.
*(my_ptr+7) = *(y+3); // Copy frame information
*(my_ptr+6) = *(y+2);
*(my_ptr+5) = *(y+1);
*(my_ptr+4) = *y;
通常,您需要弄些必须复制的地址。您可以像使用gdb一样大致了解。确切的数字取决于函数及其变量。
评论
“如果我仅获得提示而不是完整的答案,我将不胜感激。”但是,您接受了非提示的完整答案作为接受的答案:
–詹森·格夫纳(Jason Geffner)
15年3月18日在16:43
我以为我们同意我将在注释中编辑我的工作代码。但是您回滚了我的编辑而没有解释。
–user187
15年3月19日在7:44