Linux C/C++内存越界定位: 利用mprotect使程序在crash在第一现场

Linux中mprotect()函数详解 测试源码 //mmp.c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/mman.h> int *g_ps32Result; void add(int a, int b) { *g_ps32Result = a + b; } void s... 阅读详情

原文链接:https://blog.youkuaiyun.com/thisinnocence/article/details/80025064

对于大型Linux C/C++程序,内存越界和野指针类问题往往比较难定位。有的由于内存被非法改写造成了业务功能问题,有的则直接导致了程序crash,而且还经常不是第一现场。针对这种问题,可以采取的解决方法有:

  1. 利用valgrind工具来排查,会影响程序性能;
  2. 使用Address Sanitizer工具排查;
  3. 如果是固定的内存被破坏,可以利用gdb watch来抓取第一现场的调用栈;
  4. 可以利用Git二分回退代码库的commit点,缩减代码范围进行code review;
  5. 利用mprotect来进行保护对应内存,被非法改写时crash掉程序,分析coredump;

这里用一个小例子介绍下mprotect用法。根据mprotect的官方文档说明,使用mprotect这里最重要的一点是被保护的内存是按页对齐的,范围也是按页来的。这是因为Linux管理进程地址空间是一VMA(Virtual Memory Area)为单位来管理进程虚拟地址空间的,而VMA必须是page size大小的整数倍,可以看这篇文章 How The Kernel Manages Your Memory.
对于按页对齐申请内存,可以看这篇适配malloc申请按页对齐的内存。
也可以使用 posix_memalign来申请,如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>

int *result = 0;

void add(int a, int b)
{
    *result = a + b;
}

void subtract(int a, int b)
{
    *result = a - b;
}

int main()
{
    int ret;
    int pagesize;

    // 获取操作系统一个页的大小, 一般是 4KB == 4096
    pagesize = sysconf(_SC_PAGE_SIZE);
    printf("pagesize is: %d Byte\n", pagesize);
    if (pagesize == -1) {
        perror("sysconf");
        return -1;
    }

    // 按页对齐来申请一页内存, result会是一个可以被页(0x1000 == 4096)整除的地址
    ret = posix_memalign((void**)&result, pagesize, pagesize);
    printf("posix_memalign mem %p\n", result);
    if (ret != 0) {
        // posix_memalign 返回失败不会设置系统的errno, 不能用perror输出错误
        printf("posix_memalign fail, ret %u\n", ret);
        return -1;
    }

    add(1, 1); // 结果写入 *result
    printf("the result is %d\n", *result);

    // 保护result指向的内存, 权限设为只读
    ret = mprotect(result, pagesize, PROT_READ);
    if (ret == -1) {
        perror("mprotect");
        return -1;
    }

    subtract(1, 1); // 结果写入 *result, 但是 *result 只读, 引发segment fault
    printf("the result is %d\n", *result);

    free(result);
    return 0;
}

运行定位如下, 执行ulimit -c unlimited打开生成coredump,执行过程如下:

root@ubuntu:/media/psf/Home/iLearn/learn_mprotect# ulimit -c unlimited
root@ubuntu:/media/psf/Home/iLearn/learn_mprotect# gcc -g main.c
root@ubuntu:/media/psf/Home/iLearn/learn_mprotect# ./a.out
pagesize is: 4096 Byte
posix_memalign mem 0x1b2f000
the result is 2
Segmentation fault (core dumped)
root@ubuntu:/media/psf/Home/iLearn/learn_mprotect# ls
a.out  core  main.c
root@ubuntu:/media/psf/Home/iLearn/learn_mprotect# gdb a.out core
GNU gdb (Ubuntu 7.7-0ubuntu3.1) 7.7
Reading symbols from a.out...done.
[New LWP 20389]
Core was generated by `./a.out'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00000000004006e5 in subtract (a=1, b=1) at main.c:15
15	    *result = a - b;
(gdb) bt
#0  0x00000000004006e5 in subtract (a=1, b=1) at main.c:15
#1  0x00000000004007f2 in main () at main.c:50

这样由于野指针或越界导致的内存被非法改写就可以crash到第一现场了,通过coredump就可以很容易找到问题点 ?

 

C语言_mprotect 函数深度解析与应用实践 Linux mprotect 函数深度解析与应用实践 阅读详情

相关推荐

Linux下用qBreakpad定位Qt程序崩溃位置

Linux下用qBreakpad定位Qt程序崩溃位置

weixin_45001971的博客 3173

Linux下查看内存使用状况的命令:free -h

total:指一共有多少内存; used:正在被使用的内存; free:完全空闲中的内存; shared:共享内存(无实际用处?) buffer/cache:缓存缓冲内存; available:真实可用的内存; cache(内存中的高速缓存)的作用:提高cpu读取数据的速度;(访内存比访问外存花费时间少,划分部分内存作为缓存区,提高性能---高效率的读) buffer(内存中的缓冲区):为了提高写硬盘的速度;(高效率的写) 参考书籍:运维手册 ...

JoggingPig的博客 2377

软件安全防护实战:对抗Ghidra逆向分析与MCP自动化攻击的五大策略

在软件安全领域,逆向工程是分析程序内部逻辑、挖掘漏洞的核心技术,而静态分析与动态调试是其两大支柱。通过反汇编、反编译和控制流分析,攻击者能够深入理解软件实现原理,进而窃取知识产权或发现安全缺陷。随着自动化工具链和集成协议的发展,逆向工程的效率与协作性大幅提升,对软件资产的威胁日益严峻。因此,构建多层次、深度的防护体系具有重要的技术价值,能有效提升攻击成本,保护核心算法与业务逻辑。在实际应用场景中,针对使用Ghidra等强大静态分析工具并结合MCP协议进行自动化攻击的威胁,需从代码混淆、二进制加壳、构建链安全

weixin_30955617的博客 377

mprotect

mprotect是一个在Linux操作系统中使用的函数,它允许用户修改一段指定内存区域的访问权限。

qq_42805085的博客 1080

Node.js Hook 机制深度解析:从 run-with-flags 到 require 拦截

Hook 是现代 JavaScript 运行时的核心扩展机制,本质是在关键执行节点(如模块加载、函数调用、进程启动)注入可控逻辑。其底层依赖 Node.js 的 CommonJS 模块系统与 V8 启动流程,通过 --require、Module._load 重写、run-with-flags.js 代理启动等技术实现无侵入式干预。这类机制不仅支撑调试(--inspect)、监控(Sentry 自动注入)、安全审计(Frida 配合)等工程实践,也是 Git pre-receive、Webpack 插件、V

weixin_34197488的博客 558

SAP SD核心流程解析:从销售订单到财务结算的实战指南

本文深入解析SAP SD模块从销售订单到财务结算的核心流程,重点剖析了销售订单中的行项目类别如何作为流程的“总开关”,决定了后续交货、开票及财务集成的走向。文章结合实战案例,详细拆解了正常销售、退货、第三方销售、寄售等典型流程的配置要点与国内化适配方案,并阐述了SD与财务模块集成的关键连接点,为顾问和用户提供了一份全面的实战指南。

weixin_29250403的博客 426

【Linux C/C++开发】深入解析 Linux C/C++ 中的 Deferred Crash (延迟崩溃)

Linux C/C++ 中的 Deferred Crash(延迟崩溃)是程序发生内存破坏后延迟触发的异常现象,表现为崩溃点与错误发生点分离。主要成因包括堆元数据破坏、栈溢出和释放后使用等问题。调试这类问题极具挑战性,因为常规方法难以定位错误源头。推荐使用 AddressSanitizer 等工具在编译时检测内存错误,或通过 Valgrind 分析运行时问题。预防措施包括使用智能指针、容器类替代裸指针,以及严格的代码审查。这种崩溃的典型特征是错误发生与程序崩溃之间存在"潜伏期",使得问题难

love131452098的博客 1114

夜间灯光遥感数据介绍及下载汇总

夜间灯光遥感数据介绍及下载汇总

qq_43874102的博客 1万+

GDB汇编调试实战:从黑盒崩溃到指令级精准定位

在软件开发和系统调试中,理解程序在CPU层面的实际执行过程是深入排查复杂问题的关键。通过反汇编技术,开发者可以将高级语言代码映射到底层机器指令,直观观察寄存器、内存和指令指针的实时状态,从而掌握程序运行的底层原理。这项技术的核心价值在于能够穿透编译器优化和符号表缺失的障碍,精准定位那些高级调试器难以触及的深层缺陷,例如栈溢出、内存越界和多线程竞态条件。在Linux开发环境中,GDB调试器内置了强大的反汇编引擎和指令级控制能力,为分析系统调用、库函数实现以及无符号表程序提供了不可替代的手段。通过结合热门的GD

weixin_33866037的博客 312

Linux系统安全学习手册

Linux反弹shell Linux系统应急响应 Linux服务器安全加固 Linux下的用户、组和权限 Linux中的gcc Linux中su和sudo的用法和区别 Linux系统python2与python3共存 Linux中grep工具的使用 Linux中环境变量的设置 Linux中常见的150个命令(干货) Linux中编写Shell脚本 LNMP环境搭建Wordpress博客 LAMP环境搭建一个Discuz论坛 Linux运维比较常用的一些脚本 Linux系统中安装软

谢公子的博客 7532

【温室气体数据集】CAMS 发布的温室气体(GHG)数据集总结

【温室气体数据集】CAMS 发布的温室气体(GHG)数据集总结

WW、forever的博客 555

Rust实现高级反调试与反分析技术:构建安全软件保护层

在软件安全领域,反调试与反分析技术是保护核心代码逻辑、防止逆向工程的关键手段。其基本原理是通过检测程序运行环境、干扰分析工具、混淆代码逻辑等方式,增加攻击者理解和篡改软件的难度。这些技术的核心价值在于提升软件的安全性,保护知识产权,并延长产品的安全生命周期。在应用场景上,广泛用于恶意软件分析对抗、游戏安全保护、软件许可验证以及商业软件的核心算法防护。本文将探讨如何利用Rust语言的内存安全特性和高性能优势,结合RedOps(红队操作)中的隐匿技术思想,系统性地实现环境感知、行为干扰和核心保护等多层防御机制,

weixin_34214500的博客 321

全志V3S嵌入式驱动开发(uboot移植)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 安装了ubuntu操作系统,有了开发板,下面就可以进行我们的开发工作了。第一步,我们要面临的问题就是uboot移植。一般来说,嵌入式的基础环境就是uboot、linux和rootfs。uboot完成一些基本硬件的初始化,比如cpu频率设置、ddr初始化、加载linux等等。早前,uboot的烧入比较麻烦,需要jtag工具才能完成。现在来说,很多soc支持系统直接从sd卡启动,这对开发

嵌入式-老费,一个分享专业嵌入式知识的blog 2818

mprotect函数测试

mprotect函数测试

1399

【阿里AgentScope框架】多框架组合:AgentScope加LangChain,让你的开发效率直线上升

本文以一个例子来看下AgentScope框架和LangChain如何实现融合使用,真的超级简单,一看就懂。这是一种思路,为多种框架的融合使用提供借鉴。

同学小张的博客 3471

SAP Gateway OData V4 大数据集合分页机制详解,$skiptoken、Next Link 与服务端分页

更关键的是确定稳定排序方式,选择可靠的分页游标,限制单次 Response Size,正确生成 Next Link,让 Consumer 把 Next Link 当成不可解释的协议结果,并明确区分 Pagination、Delta Synchronization 和 Snapshot Consistency。从协议表达来看,请求没有问题。假设系统内部配置为每次最多返回 100 条,而数据库里一共存在 12580 条符合条件的销售订单,那么第一次响应只包含前 100 条,同时附带一个 Next Link。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 52

浅谈mprotect函数和mmap函数

在Linux中,mprotect()函数可以用来修改一段指定内存区域的权限。 细说参数一句话mprotect()函数把自start开始的、长度为len的内存区的保护属性修改为prot指定的值。注意几点: mmap函数 首先了解内存映射:内存映射:(可以类别数学中函数的映射关系,抽象类比的理解这种关系或者说是过程)将用户空间的一段内存区域映射到内核空间,映射成功后,用户对这段内存区域的修改可以直接反映到内核空间,同样,内核空间对这段区域的修改也直接反映用户空间通俗点理解嘛:就是你和镜子中的你,你发

Rt1Text的博客 1505

【DRAM存储器六十四】DDR5介绍--preamble、postamble、interamble、刷新、power down、MPSM

简述DDR5 reamble、postamble、interamble、刷新、power down、MPSM的功能定义

highman110的博客 337

Linux中mprotect()函数的用法

mprotect()函数修改在内存映像上的保护模式。 函数原型: #include    #include    int mprotect(const void *start, size_t len, int prot); mprotect把自start开始的内存区的保护模式修改为prot指定的值,如果执行成功返回0,如果执行失败,mprotect返回-1,并且设置errno变量。

Roland_Sun的专栏 5万+

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

【CTF | pwn篇】mprotect()函数

本文介绍了Linux中mprotect()函数的使用方法,该函数用于修改指定内存区域的保护属性。文章详细说明了函数原型、参数选项(PROT_READ、PROT_WRITE等)及其组合使用方式,并强调了内存区间必须对齐页边界的要求。同时列出了函数可能返回的错误码及其具体原因(如EACCES、ENOMEM等),帮助开发者理解调用失败时的处理方式。最后提供了官方文档参考链接。

序章的博客 838

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

静态编译:Mprotect、自动化rop链;Ret2csu

开启NX,64位,IDA分析:看左半边不难看出这是一道静态编译题(简单解释,左边函数很多,静态编译占内存一般比动态多的多右半边可以看到,只有一个gets函数可以利用(存在栈溢出由于这题是静态编译题,因此我们可以有多种写法,这里我们分别使用Mprotect与自动化rop链解题。

2301_79880752的博客 1644

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

mprotect()函数 Unix/Linux

mprotect - 控制允许访问的内存区域 内容简介 #include int mprotect(const void *addr, size_t len, int prot); 描述 The function mprotect() specifies the desired protection for the memory page(s) containing

hellochenlu的博客 3120

mprotect设置内存访问权限

一、源代码以及编译 vi protect.ci

程序改变生活 5665
上一篇: [bashdb]SHELL脚本的事脚本解决
下一篇: Linux下杂乱无章的Bash脚本传入参数--如何解析?
RyanLeiWang
博客等级 码龄20年 184粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值