c/cpp暗改调用栈的一些玩法(0x01)

调用栈浅说

调用栈的图参考了这篇博客https://blog.csdn.net/VarusK/...
通过这个图可以形象看出函数调用的过程中,每个函数调用的栈帧如何,栈区的排布等信息。

当一个函数被调用的时候,进栈的顺序为:

  1. 主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址。
  2. 函数的各个参数,由右往左入栈的,然后是函数中的局部变量。
    image.png

修改调用栈中的返回地址

如上面一小节提到的那样,我们的传参和主调函数的下一个指令地址在栈的结构中是相邻的,于是我们可以通过参数地址定位到主调函数的下一指令地址,并对其进行修改。

代码如下:

#include <stdio.h>

#define dp(msg)\
{\
    printf(msg);\
    printf(" > in func: < %s >", __FUNCTION__);\
    printf("\n");\
}

void leaper( int a )
{
    int* p    = &a;
    if ( a ){
        for( int i = 0; i < 64; i ++ ){
            if ( ( *(p+i) > (long)leaper ) && ( ( *(p+i) - (long)leaper ) < 0x1000 ) ){
                *(p+i) += 5;
                break;
            }
            if ( ( *(p+i) < (long)leaper ) && ( ( (long)leaper - *(p+i) ) < 0x1000 ) ){
                *(p+i) += 5;
                break;
            }
        }
    }
    return;
}

void func_a()
{
    dp("here!");
}

int main( int argc, char* argv[] )
{
    leaper(1);
    func_a();
    dp("end");
    return 0;
}

代码说明:main中调了leaper函数,首先会把执行func_a的指令地址(也就是执行完leaper之后的指令地址)先压栈,然后将传参压栈,在leaper中参数地址取出来&a,然后在其周围寻找类似于leaper指针值的值,找到第一个就ok,然后将其+5,这就算给下一条指令地址加上偏移了,这里面我担心不同编译器的栈帧结构不太一样,所以采取这种写法容错高一些,+5是为了正确跳过指令的长度,(不同的芯片这个值不一样,这样看具体的指令长度,比如arm应该是4,86的芯片的call指令写5应该是ok,具体应该怎么样可以使用objdump看汇编代码,然后进行修改)。

最终的效果,因为调用栈中的下一条指令的地址被修改了,所以func_a会被跳过。直接打印"end"了。

因为c/cpp有了指针,会导致有很多玩内存的玩法,通常会造成一些让人错愕的效果,“不安全”和“玩法”成为了c/cpp这枚硬币的两面。

1 声望
0 粉丝
0 条评论
推荐阅读
Redis 发布订阅模式:原理拆解并实现一个消息队列
“65 哥,如果你交了个漂亮小姐姐做女朋友,你会通过什么方式将这个消息广而告之给你的微信好友?““那不得拍点女朋友的美照 + 亲密照弄一个九宫格图文消息在朋友圈发布大肆宣传,暴击单身狗。”像这种 65 哥通过朋...

码哥字节6阅读 1.2k

封面图
C 程序眼中的 Unicode
去年写了一篇文章「在 C 程序中处理 UTF-8 字符串」,介绍了如何使用 GLib 提供的 UTF-8 字符串处理函数来实现基本的 UTF-8 文本处理。不过,GLib 是一个功能比较全面的 C 程序库,C 字符串处理仅仅是它的一个很...

garfileo3阅读 5.6k评论 5

万字避坑指南!C++的缺陷与思考(上)
导语 | 本文主要总结了本人在C++开发过程中对一些奇怪、复杂的语法的理解和思考,同时作为C++开发的避坑指南。前言C++是一门古老的语言,但仍然在不间断更新中,不断引用新特性。但与此同时C++又甩不掉巨大的历史...

腾讯云开发者5阅读 506

计算机如何表示整数
在计算机中,任何的数据都是用二进制: 0 和 1 来表示。整数也不例外。生活中的 10,在 8 个字节的整数中表示为 00001010。但是这样子只能表示正数和零。怎么表示负数呢?于是有了符号位的概念。在 8 个字节的整...

kang2阅读 3k评论 7

麒麟操作系统 (kylinos) 从入门到精通 - 研发环境 - 第二十一篇 C++/C语言开发环境搭建
类别:笔记本型号:中国长城 NF14C硬件平台:飞腾处理器(ArmV8 指令集)系统:银河麒麟操作系统 V10 SP1(2203) 关键词:信创,麒麟系统,linux,c++,c,内核飞腾,arm

码上世界1阅读 2.3k评论 1

封面图
ctf(pwn&reverse)总结
F5/tab 查看伪代码空格 查看汇编代码视图-&gt;打开子视图-&gt;字符串 :查看所有字符串编辑-&gt;修补程序 :修改程序 修改完后点击修补程序应用到输入文件即可保存修改

白风之下阅读 2.7k

浙大版《C语言程序设计》第四版(何钦铭颜晖) 第5章 函数 课后习题答案
你也可以上程序咖([链接]),打开大学幕题板块,不但有答案,讲解,还可以在线答题。一、选择题1.在 C 语言程序中,若对函数类型未加显式说明,则函数的隐含类型为( )。A. voidB. double C. charD. int答:D解析...

茹茹1阅读 1k

1 声望
0 粉丝
宣传栏