将堆栈上的函数返回地址更改为另一个函数,并在之后返回到main

问题描述

我对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 (将#修改为@)