问题描述
我对c语言还比较陌生,并且一直在研究过程的虚拟内存以学习一些基本概念。我遵循Holberton学校的教程。
(参考:https://blog.holbertonschool.com/hack-virtual-memory-stack-registers-assembly-code/)
基于此博客的最后一部分,我编写了一个c程序,该程序将堆栈中某个函数的返回地址更改为我自己的名为“ bye”的函数的地址,然后退出该程序。
但是,我想超越,以便“再见”将返回到调用原始函数(func1)的main,而不是退出。
我似乎能够做到这一点,但是与func1刚返回main相比,栈指针(rsp和rbp)奇怪地偏移了8个字节。
为什么会这样?以及我该如何解决?
这是源代码:
#include <stdlib.h>
#include <stdio.h>
void bye(void) __attribute__((noinline));
void func1(void) __attribute__((noinline));
void func2(void);
void * ret_jump; /*a pointer to a label so that the label can be global*/
void bye(){
register long rsp asm("rsp");
register long rbp asm("rbp");
printf("bye,rsp: %lx\n",rsp);
printf("bye,rbp : %lx\n",rbp);
printf("[*] You have been tricked!!\n");
/*goto instead of return to not mess with the stack*/
goto *ret_jump;
}
/*Original function that should return to main but returns to bye*/
void func1(void){
register long rsp asm("rsp");
register long rbp asm("rbp");
printf("func1,rsp);
printf("func1,rbp);
int a;
int b;
int c;
a = 64;
b = 32;
c = a * b;
printf("a = %d,b = %d,c = %d\n",a,b,c);
printf("Value of 'a' using rbp: %d\n",*((int*)((char*)rbp - 0xc)));
printf("Value of 'b' using rbp: %d\n",*((int*)((char*)rbp - 0x8)));
printf("Value of 'c' using rbp: %d\n",*((int*)((char*)rbp - 0x4)));
printf("PrevIoUs value of rbp: %lx\n",*(unsigned long int*)rbp);
printf("Return address of func1 = %lx\n",*((unsigned long int*)((char*)rbp + 0x8)));
/*Change the return address of func1 (in main) to the address of the bye function*/
printf("func1,rbp);
*((unsigned long int*)(((char*)rbp) + 0x8)) = (unsigned long int)bye;
printf("PrevIoUs value of rbp: %lx\n",*((unsigned long int*)((char*)rbp + 0x8)));
printf("func1,rbp);
/*The stack pointers change after this return call.*/
return;
}
/*This function shows how the stack pointers are offset by 8 bytes from what they would have been if func1 returned to main*/
void func2(void){
register long rsp asm("rsp");
register long rbp asm("rbp");
printf("func2,rsp);
printf("func2,rbp);
int a;
int b;
int c;
printf("a = %d,c);
printf("rsp: %lx\n",rsp);
printf("rbp : %lx\n",rbp);
}
int main(void){
ret_jump = &&ret_jmp;
register long rsp asm ("rsp");
register long rbp asm ("rbp");
printf("main,rbp = %lx\n",rbp);
printf("main,rsp = %lx\n",rsp);
func1();
ret_jmp:
printf("func1,rbp);
func2();
return EXIT_SUCCESS;
}
这是运行时的输出:
main,rbp = 7ffe96b075f0
main,rsp = 7ffe96b075f0
func1,rsp: 7ffe96b075d0
func1,rbp : 7ffe96b075e0
a = 64,b = 32,c = 2048
Value of 'a' using rbp: 64
Value of 'b' using rbp: 32
Value of 'c' using rbp: 2048
PrevIoUs value of rbp: 7ffe96b075f0
Return address of func1 = 55c0a7a0c93a
func1,rbp : 7ffe96b075e0
PrevIoUs value of rbp: 7ffe96b075f0
Return address of func1 = 55c0a7a0c68a
func1,rbp : 7ffe96b075e0
bye,rsp: 7ffe96b075e8
bye,rbp : 7ffe96b075e8
[*] You have been tricked!!
func1,rsp: 7ffe96b075e8
func1,rbp : 7ffe96b075e8
func2,rsp: 7ffe96b075c8
func2,rbp : 7ffe96b075d8
a = 32766,b = -1482635904,c = 21952
rsp: 7ffe96b075c8
rbp : 7ffe96b075d8
我的机器运行的Ubuntu 16.04内核为5.4.0-48-generic。它使用的是glibc 2.27
在此先感谢任何可以提供帮助的人!
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)