栈踩踏实验

news2025/1/4 19:13:14

程序的存储结构

分布

在磁盘和内存中的分布如下:
在这里插入图片描述
节视图
.data:已经初始化的全局变量/局部静态变量
.bss:未初始化的全局变量/局部静态变量
.got.plt:全局偏移量表,保存全局变量引用的地址
.rodata:只读数据
text:代码节,保存了程序执行的代码
.init:程序初始化和终止的代码
段视图
stack:栈,向低地址生长
heap:堆,向高地址生长
data:读写权限的数据段
code:具有执行权限的数据段

以hello world为例

// gcc -m32 -no-pie -g -o main main.c
#include <stdio.h>

int main()
{
	printf("hello world\n");
	return 0;
}

objdump -h main #可查看各个节的位置

alientek@ubuntu16:~/Desktop/exc$ objdump -h main

main:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  08048154  08048154  00000154  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  08048168  08048168  00000168  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.gnu.build-id 00000024  08048188  08048188  00000188  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     00000020  080481ac  080481ac  000001ac  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000050  080481cc  080481cc  000001cc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       0000004a  0804821c  0804821c  0000021c  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  0000000a  08048266  08048266  00000266  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  08048270  08048270  00000270  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rel.dyn      00000008  08048290  08048290  00000290  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rel.plt      00000010  08048298  08048298  00000298  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         00000023  080482a8  080482a8  000002a8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000030  080482d0  080482d0  000002d0  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .plt.got      00000008  08048300  08048300  00000300  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .text         00000192  08048310  08048310  00000310  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .fini         00000014  080484a4  080484a4  000004a4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 15 .rodata       00000014  080484b8  080484b8  000004b8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .eh_frame_hdr 0000002c  080484cc  080484cc  000004cc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 17 .eh_frame     000000cc  080484f8  080484f8  000004f8  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 18 .init_array   00000004  08049f08  08049f08  00000f08  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .fini_array   00000004  08049f0c  08049f0c  00000f0c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .jcr          00000004  08049f10  08049f10  00000f10  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .dynamic      000000e8  08049f14  08049f14  00000f14  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .got          00000004  08049ffc  08049ffc  00000ffc  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .got.plt      00000014  0804a000  0804a000  00001000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 24 .data         00000008  0804a014  0804a014  00001014  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 25 .bss          00000004  0804a01c  0804a01c  0000101c  2**0
                  ALLOC
 26 .comment      00000035  00000000  00000000  0000101c  2**0
                  CONTENTS, READONLY
 27 .debug_aranges 00000020  00000000  00000000  00001051  2**0
                  CONTENTS, READONLY, DEBUGGING
 28 .debug_info   0000008f  00000000  00000000  00001071  2**0
                  CONTENTS, READONLY, DEBUGGING
 29 .debug_abbrev 00000042  00000000  00000000  00001100  2**0
                  CONTENTS, READONLY, DEBUGGING
 30 .debug_line   00000038  00000000  00000000  00001142  2**0
                  CONTENTS, READONLY, DEBUGGING
 31 .debug_str    000000d3  00000000  00000000  0000117a  2**0
                  CONTENTS, READONLY, DEBUGGING

ldd 命令用于打印程序或者共享库文件所依赖的共享库列表。注意,ldd 本身不是一个二进制程序,而是一个 Shell 脚本,使用文本编辑器 vim 可以查看其内容.

alientek@ubuntu16:~/Desktop/exc$ ldd main
        linux-gate.so.1 =>  (0xf7f4d000)
        libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0xf7d75000)
        /lib/ld-linux.so.2 (0xf7f4f000)

gdb-peda 插件

跑起来以后

gdb-peda$ vmmap
Start      End        Perm      Name
0x08048000 0x08049000 r-xp      /home/alientek/Desktop/exc/main
0x08049000 0x0804a000 r--p      /home/alientek/Desktop/exc/main
0x0804a000 0x0804b000 rw-p      /home/alientek/Desktop/exc/main
0xf7dfe000 0xf7dff000 rw-p      mapped
0xf7dff000 0xf7faf000 r-xp      /lib/i386-linux-gnu/libc-2.23.so
0xf7faf000 0xf7fb0000 ---p      /lib/i386-linux-gnu/libc-2.23.so
0xf7fb0000 0xf7fb2000 r--p      /lib/i386-linux-gnu/libc-2.23.so
0xf7fb2000 0xf7fb3000 rw-p      /lib/i386-linux-gnu/libc-2.23.so
0xf7fb3000 0xf7fb6000 rw-p      mapped
0xf7fd3000 0xf7fd4000 rw-p      mapped
0xf7fd4000 0xf7fd7000 r--p      [vvar]
0xf7fd7000 0xf7fd9000 r-xp      [vdso]
0xf7fd9000 0xf7ffc000 r-xp      /lib/i386-linux-gnu/ld-2.23.so
0xf7ffc000 0xf7ffd000 r--p      /lib/i386-linux-gnu/ld-2.23.so
0xf7ffd000 0xf7ffe000 rw-p      /lib/i386-linux-gnu/ld-2.23.so
0xfffdd000 0xffffe000 rw-p      [stack]

elf文件

C语言函数栈帧与传参

函数执行过程

:函数在调用过程中,会在内存中开辟一块名为栈帧的空间,用于存放局部变量等数据,由编译器管理。
:由程序员管理。

ESP(Extended stack pointer)存放的都是栈顶地址。
EBP(Extended base pointer)该指针总是指向当前栈帧的底部(高地址)。

push和pop命令,会自动来更改 esp寄存器。
每个栈帧对应着一个未运行完的函数,包括主函数。栈帧中保存了该函数的返回地址、和局部变量。

别人的: https://blog.csdn.net/iluo12/article/details/122557685
https://blog.csdn.net/chihiro1122/article/details/127671496

以add程序为例

参数较少,编译成32位可执行程序,才会采用栈传参。

//main2.c
int  add(int a,int b)
{
    int c = 0;
    c = a + b;
    return c;
}
int main()
{
    int a=0;
    int b=1;
    int sum=0;
    sum=add(a,b);
    return 0;
}

gdb-peda 看汇编代码

0x80483f8 <main>:    push   ebp 
0x80483f9 <main+1>:  mov    ebp,esp #从栈顶开始跑了
0x80483fb <main+3>:  sub    esp,0x10#可能是流出
0x80483fe <main+6>:  mov    DWORD PTR [ebp-0xc],0x0 #a
0x8048405 <main+13>: mov    DWORD PTR [ebp-0x8],0x1 #b
0x804840c <main+20>: mov    DWORD PTR [ebp-0x4],0x0 #sum
0x8048413 <main+27>: push   DWORD PTR [ebp-0x8] #b入栈
0x8048416 <main+30>: push   DWORD PTR [ebp-0xc] #a入栈
0x8048419 <main+33>: call   0x80483db <add> #调用子函数
0x804841e <main+38>: add    esp,0x8
0x8048421 <main+41>: mov    DWORD PTR [ebp-0x4],eax
0x8048424 <main+44>: mov    eax,0x0
0x8048429 <main+49>: leave  
0x804842a <main+50>: ret  

在执行main时候,EBP=0xffffd128,栈从ESP=0xffffd118开始生长。

0x80483dc <add+1>:   mov    ebp,esp
0x80483de <add+3>:   sub    esp,0x10
0x80483e1 <add+6>:   mov    DWORD PTR [ebp-0x4],0x0 #c
0x80483e8 <add+13>:  mov    edx,DWORD PTR [ebp+0x8] #取函数参数
0x80483eb <add+16>:  mov    eax,DWORD PTR [ebp+0xc] #取函数参数
0x80483ee <add+19>:  add    eax,edx
0x80483f0 <add+21>:  mov    DWORD PTR [ebp-0x4],eax #结果存在c
0x80483f3 <add+24>:  mov    eax,DWORD PTR [ebp-0x4] #返回值放在ax里面
0x80483f6 <add+27>:  leave  
0x80483f7 <add+28>:  ret 

进入 add子函数后,EBP=0xffffd108,ESP从0xffffd0f8开始生长。

栈的分布

0000| 0xffffd0f8 --> 0xf7e2da60 (add    ebx,0x1845a0)#add的栈帧
0004| 0xffffd0fc --> 0x804847b (<__libc_csu_init+75>:   add    edi,0x1)
0008| 0xffffd100 --> 0x1 
0012| 0xffffd104 --> 0xffffd1c4 --> 0xffffd342 ("/home/alientek/Desktop/exc/main2")
0016| 0xffffd108 --> 0xffffd128 --> 0x0 #add的栈帧
0020| 0xffffd10c --> 0x804841e (<main+38>:      add    esp,0x8)
0024| 0xffffd110 --> 0x0 
0028| 0xffffd114 --> 0x1 
0000| 0xffffd118 --> 0x8048439 (<__libc_csu_init+9>:    add    ebx,0x1bc7)#main的栈帧
0004| 0xffffd11c --> 0x0 
0008| 0xffffd120 --> 0x1 
0012| 0xffffd124 --> 0x0 
0016| 0xffffd128 --> 0x0 #main的栈帧
0020| 0xffffd12c --> 0xf7e17647 (<__libc_start_main+247>:       add    esp,0x10)
0024| 0xffffd130 --> 0x1 
0028| 0xffffd134 --> 0xffffd1c4 --> 0xffffd342 ("/home/alientek/Desktop/exc/main2")

栈踩踏

写一个子函数里面数组越界的例子

//main3.c
void test(void)
{
    char tmp[4];
    tmp[20]=1;
    return;
}
int main()
{
    test();
    return 0;
}

test函数的汇编指令如下,给tmp[20]赋值实际上写到了0xffffd10c这个地址上了,这里记录了test子函数返回时,应该执行的main函数的地址,把地址破坏了,该程序无法继续运行了。

   0x8048447 <test+12>: mov    DWORD PTR [ebp-0xc],eax
   0x804844a <test+15>: xor    eax,eax
   0x804844c <test+17>: mov    BYTE PTR [ebp+0x4],0x1

这段代码的栈如下

0000| 0xffffd0f0 --> 0x1 
0004| 0xffffd0f4 --> 0x400000 ('')
0008| 0xffffd0f8 --> 0xf7e2da60 (add    ebx,0x1845a0)
0012| 0xffffd0fc --> 0x80484db (<__libc_csu_init+75>:   add    edi,0x1)
0016| 0xffffd100 --> 0x1 
0020| 0xffffd104 --> 0xffffd1c4 --> 0xffffd342 ("/home/alientek/Desktop/exc/main3")
0024| 0xffffd108 --> 0xffffd118 --> 0x0 
0028| 0xffffd10c --> 0x804847a (<main+22>:      mov    eax,0x0)
0000| 0xffffd110 --> 0xf7fb23dc --> 0xf7fb31e0 --> 0x0 #main的栈帧
0004| 0xffffd114 --> 0xffffd130 --> 0x1 
0008| 0xffffd118 --> 0x0 #main的BSP
0012| 0xffffd11c --> 0xf7e17647 (<__libc_start_main+247>:       add    esp,0x10)
0016| 0xffffd120 --> 0xf7fb2000 --> 0x1b2db0 
0020| 0xffffd124 --> 0xf7fb2000 --> 0x1b2db0 
0024| 0xffffd128 --> 0x0 
0028| 0xffffd12c --> 0xf7e17647 (<__libc_start_main+247>:       add    esp,0x10)

运行结果

alientek@ubuntu16:~/Desktop/exc$ ./main3
Illegal instruction

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/581383.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023 Idea 热部署 JRebel 插件激活方法

2023 Idea 热部署 JRebel 插件激活方法 1. 下载源代码 进入下面 github 地址 clone 代码到本地 https://github.com/Byron4j/JrebelLicenseServerforJava 2. 编译和打包 cd /Users/daixiaohu/Desktop/JrebelLicenseServerforJavamvn clean package3. 运行项目 cd target/jav…

前端项目搭建以及项目配置

前端项目搭建 - vitevue3.0ant vite比起webpack速度更快 vite搭建项目 https://cn.vitejs.dev/ 步骤&#xff1a; 1.打开cmd 2.找到项目应该建的文件夹 比如直接建到桌面上 cd desktop3.创建项目 使用创建项目命令&#xff0c;然后根据提示填写项目名称&#xff0c;以及要…

计算机视觉基础:锚框

锚框 目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;ground-truth bounding box&#xff09;。 不同的模型使用的区域采样方法可能不同。 这里…

KVM网络桥接模式底层网络原理解说

文章目录 前言一、tap设备在kvm中的应用1. tap虚拟网络设备2. Tap/Tun工作原理3. 结论 二、KVM网络桥接模式细节解说1.查看虚拟网卡2.vnet虚拟网卡说明 总结 前言 在以下两篇文章中我们介绍了虚拟网卡技术以及虚拟交换机技术&#xff0c;今天我们再来详细说说在在kvm网络模式下…

chatgpt赋能python:为什么Python在SEO中不见了?

为什么Python在SEO中不见了&#xff1f; Python是众所周知的一种流行的编程语言&#xff0c;它被广泛地用于各种应用程序&#xff0c;从人工智能和机器学习到数据科学和Web应用程序。然而&#xff0c;在最近的一次更新中&#xff0c;有些人注意到Python似乎在搜索引擎优化&…

【LAMP平台建构】

一.LAMP介绍 LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词&#xff0c;具体包括Linux操作系统、Apache网站服务器、MySQL数据库服务器、PHP&#xff08;…

使用JS来实现tab栏切换

这是我今天从学习的知识点&#xff0c;今天试着做了一个tab栏切换&#xff0c;学到很多的知识点&#xff0c;讲师也比学校的老师讲的更加详细明白 个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大一在校生&#xff0c;web前端开发专业 &#x1f921; 个人主页…

c#快速入门

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析2 目录 &#x1f449;&#x1f3fb; c#和c不同之处&#x1f449;&#x1f3fb;程序文件的…

三门问题的实验验证:贝叶斯概率公式实战

引言 数理统计与概率论经常出现在我们的日常生活中&#xff0c;如果能灵活掌握&#xff0c;可以起到很大的帮助。下面通过几个经典问题的探讨&#xff0c;浅入深出&#xff0c;更加深刻的理解贝叶斯全概率公式和贝叶斯公式的作用。 我的最深的体会就是&#xff0c;当某些已发生…

基于Go开发PaaS平台3

Go开发PaaS平台核心功能 代码仓库地址GitHub - yunixiangfeng/gopaas 10-18 中间件前端页面以及核心API开发&#xff08;中&#xff09; C:\Users\Administrator\Desktop\gopaas\middlewareapi\handler\middlewareApiHandler.go package handlerimport ("context"…

【技术解决方案】企业如何从SpringBoot应用平滑迁移到云原生K8s平台

文章目录 在K8S上部署Spring Cloud Alibaba在Kubernetes上部署Spring Cloud Kubernetes在Kubernetes上部署Spring Boot应用方案对比分析拥抱Service Mesh关于DevopsServerless最佳实践 好久不见了&#xff0c;小伙伴们&#xff0c;你们最近还好吗&#xff1f;有没有想我&#x…

常量池介绍

什么是“字面量”和“符号引用”和"直接引用" 最近看jvm时遇到了“字面量”和“符号引用”这两个概念&#xff0c;它们被存放在运行时常量池&#xff0c;看了一些博客以后对这两个概念有了初步认识。 字面量可以理解为实际值&#xff0c;int a 8中的8和String a …

linux互斥锁(pthread_mutex)知识点总结

对于多线程程序来说&#xff0c;我们往往需要对这些多线程进行同步。同步&#xff08;synchronization&#xff09;是指在一定的时间内只允许某一个线程访问某个资源。而在此时间内&#xff0c;不允许其它的线程访问该资源。我们可以通过互斥锁&#xff08;mutex&#xff09;&a…

1、Vue.js---Vue核心

目录 Vue是什么 什么是渐进式&#xff1a; Vue 的特点 与其它 JS 框架的关联 Vue 周边库 搭建Vue开发环境&#xff08;2种方式&#xff09; 1、直接用 2、NPM Hello小案例 小结&#xff1a; 模板语法 代码 小结&#xff1a; 数据绑定 代码&#xff1a; 小结&…

11、渗透性测试及验收测试

目录 什么是安全测试 安全测试与常规测试的区别 SQL注入漏洞 SQL注入漏洞会带来以下几种常见的后果&#xff1a; SQL注入漏洞攻击流程 注入点类型 SQL注入的防范措施 XSS跨站脚本漏洞 XSS原理解析 XSS类型 1、反射型XSS 2、存储型XSS 3、存储型XSS 查找XSS漏洞的…

1.4. 运算符与表达式

在 Java 中&#xff0c;运算符是用于执行特定操作的符号&#xff0c;而表达式是由变量、常量和运算符组成的一段代码&#xff0c;用于计算值。本节将介绍 Java 中的常用运算符和表达式的使用。 1.4.1. 算术运算符 Java 支持以下算术运算符&#xff1a; 加法&#xff08;&…

C语言基础习题讲解

C语言基础习题讲解 运算符判断简单循环 运算符 1. 设计一个程序, 输入三位数a, 分别输出个,十,百位. (0<a<1000) 样例输入: 251 样例输出: 2 5 1 #include <stdio.h> int main() {int input 0;int x 0;int y 0;int z 0;scanf("%d", &input);x …

chatgpt赋能python:Python三次方函数介绍

Python三次方函数介绍 Python是一种流行的编程语言&#xff0c;用于各种应用程序&#xff0c;包括数据分析和机器学习。Python三次方函数是Python语言中的一个内置函数&#xff0c;可用于计算一个数字的三次方。本文将介绍Python三次方函数的相关内容并提供一些示例。 Python…

chatgpt赋能python:Python三个数相加的方法与应用

Python三个数相加的方法与应用 在现代编程语言中&#xff0c;Python是一个非常流行的语言。Python语言的的特点是易学易用、功能强大、语法简洁等。在Python中&#xff0c;运算也是非常方便的&#xff0c;特别是对于数值计算。本文将讨论如何在Python中实现三个数的加法运算&a…

LeetCode高频算法刷题记录11

文章目录 1. 最大正方形【中等】1.1 题目描述1.2 解题思路1.3 代码实现 2. 在排序数组中查找元素的第一个和最后一个位置【中等】2.1 题目描述2.2 解题思路2.3 代码实现 3. 搜索二维矩阵 II【中等】3.1 题目描述3.2 解题思路3.3 代码实现 4. 翻转二叉树【简单】4.1 题目描述4.2…