Younth_ID 2022-04-12 18:36 采纳率: 0%
浏览 11
已结题

栈帧的栈溢出结构问题

在msvc环境下,x86 cdecl 函数调用约定下,看别人的视频讲了栈溢出控制跳转的一个例子,但是没看明白,他改写了EIP的返回地址,按照网上栈帧的介绍
在函数调用时,生成新栈帧的时候,地址从高到低依次是:

  1. 函数参数
  2. 返回地址(EIP)
  3. 前栈帧的栈底EBP
  4. 当前栈帧的局部变量空间

他通过局部变量的地址进行越界,找到了栈帧的返回地址(函数调用结束后的下一条指令地址),改它,改成了另一个函数地址,从而改变了程序流程。但是仅仅这个操作不行,函数退出的时候会平栈,程序会崩。
到这里都没有问题,根据网上的介绍,都能理解。
然后就是他修复平栈问题的处理方案,他继续越界,改变了紧接着返回地址的下一个4字节存储空间,按照我的理解,这里应该是函数参数的栈空间啊。
按照他的搞法,然后还真的平了,这个是什么道理?

#pragma optimize("",off)

void test_no_param() {
    char* str = "stack over flow.";
    MessageBoxA(NULL,str, "stop", MB_OK | MB_ICONINFORMATION);
}

void test() {
    //PUSH EBP
    //MOV EBP,ESP


    //0.
    //SUB ESP,08
    //int tmp[2] = { 0 };
    //tmp[sizeof(tmp)/sizeof(int)+1] = (int)test_no_param;
    
    //1.
    //SUB ESP,04
    int tmp = 0;
    //EBP=(&tmp)+1
    //EIP=(&tmp)+2
    *((&tmp) + 2) = (int)test_no_param;
    
    //POP EBP
    //RET; cdecl
    //RET 4; stdcall
}

int add_param(int a, int b)
{
    int c = 0;
    c = a + b;
    printf("%d+%d=%d\n",a,b,c);
    return c;
}

int add(int a, int b)
{
    int tmp[2] = { 0 };
    tmp[3] = (int)add_param;
    //tmp[4]放的是什么呢?网上说是下一条的指令指针地址
    //???为什么呢?
    tmp[4] = (int)test;
    tmp[5] = a;
    tmp[6] = b;
    tmp[4] = a;

    return 0;
}

int main() {
    //test();
    add(3, 2);
    printf("wow.\n");
}
#pragma optimize("",on)
  • 写回答

0条回答 默认 最新

    报告相同问题?

    问题事件

    • 系统已结题 4月20日
    • 创建了问题 4月12日

    悬赏问题

    • ¥15 无源定位系统的时差估计误差标准差
    • ¥15 请问这个代码哪里有问题啊
    • ¥20 python--version在命令端输入结果Python is not defined怎么办?还有pip不是exe格式是不是没安装成功?
    • ¥15 通过GaussianView进行结构微调消除虚频
    • ¥15 调用transformers库
    • ¥15 由于导出的数据名字中带有/,导致Matlab打不开,怎么办?
    • ¥15 新硬盘安装的程序总是崩溃,提示遇到错误
    • ¥15 openpcdet自制数据集评估bev精度和3d精度相同
    • ¥15 excel 上下按钮 显示行
    • ¥20 云卓h12pro 数传问题