CTF-PWN: 虚表(vtable)
vtable
vtable(虚表,virtual table)是面向对象编程中的一个关键概念,主要用于实现多态性(polymorphism)。它是一种数据结构,通常是一个指针数组,包含了类的虚函数(virtual functions)的地址。每个类都有自己的 vtable,并且每个对象实例都有一个指向该 vtable 的指针,称为 vptr(虚表指针)。
主要功能和工作原理
-
虚函数调用机制:
- 当一个类定义了虚函数时,编译器会为这个类生成一个
vtable。虚函数表中记录了当前类及其基类的虚函数地址。 - 每个对象实例在内存中都有一个
vptr,指向这个对象所属类的vtable。 - 当通过基类指针或引用调用虚函数时,程序会通过
vptr查找vtable中对应函数的地址,从而实现动态绑定(dynamic binding)和多态性。
- 当一个类定义了虚函数时,编译器会为这个类生成一个
-
继承与覆盖:
- 子类可以覆盖基类的虚函数。编译器会在子类的
vtable中用子类的函数地址替换基类的函数地址。 - 这样,当通过基类指针或引用调用虚函数时,程序会使用子类的实现,而不是基类的实现。
- 子类可以覆盖基类的虚函数。编译器会在子类的
示例
以下是一个简单的例子,说明 vtable 的工作原理:
#include <iostream>class Base {
public:virtual void foo() {std::cout << "Base::foo()" << std::endl;}virtual void bar() {std::cout << "Base::bar()" << std::endl;}
};class Derived : public Base {
public:void foo() override {std::cout << "Derived::foo()" << std::endl;}void bar() override {std::cout << "Derived::bar()" << std::endl;}
};int main() {Base* b = new Derived();b->foo(); // 输出 "Derived::foo()"b->bar(); // 输出 "Derived::bar()"delete b;return 0;
}
在这个例子中:
Base类有两个虚函数foo和bar。Derived类继承自Base并覆盖了这两个虚函数。- 在
main函数中,通过基类指针b调用了虚函数foo和bar,由于动态绑定的机制,实际调用的是Derived类中的实现。
vtable 和 vptr 的示意图
假设 Base 类和 Derived 类的 vtable 如下:
Base::vtable
+------------+
| &Base::foo |
| &Base::bar |
+------------+Derived::vtable
+---------------+
| &Derived::foo |
| &Derived::bar |
+---------------+
当创建一个 Derived 类对象时,内存布局可能如下:
Derived object
+--------+
| vptr | ----> Derived::vtable
+--------+
小结
vtable 是实现 C++ 等面向对象编程语言中多态性的重要机制。它通过维护一个虚函数指针数组和对象实例中的虚表指针,实现了动态绑定和函数调用的多态性。在编译器的支持下,vtable 机制在运行时动态选择合适的函数实现,从而使得面向对象编程中的继承和多态特性能够顺利工作。
__IO_FILE与vtable
__IO_FILE 结构体的虚表(vtable)指向了各种文件操作函数,例如 open、read、write、close 等。这些函数指针赋予了不同类型的文件流(如普通文件、内存流、网络流等)特定的行为,从而实现了多态性。
具体来说,__IO_FILE 结构体中的虚表指向了一个包含这些函数指针的结构体(通常称为 jump table 或 vtable),这些函数指针对应于文件操作函数。这些函数指针在运行时会被调用,以执行具体的文件操作。
示例代码解释
以下是一个简化的示例,展示了 __IO_FILE 结构体及其虚表的概念:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>// 定义虚表结构体,包含文件操作函数指针
struct _IO_jump_t {ssize_t (*read)(void *cookie, char *buf, size_t nbytes);ssize_t (*write)(void *cookie, const char *buf, size_t nbytes);int (*close)(void *cookie);
};// 定义文件结构体,包含一个指向虚表的指针
typedef struct {struct _IO_jump_t *vtable;void *cookie; // 自定义数据,可以用来存储文件句柄或其他状态信息
} _IO_FILE;// 虚表的具体实现
ssize_t my_read(void *cookie, char *buf, size_t nbytes) {// 自定义读函数的实现// 这里假设cookie是一个文件指针FILE *fp = (FILE *)cookie;return fread(buf, 1, nbytes, fp);
}ssize_t my_write(void *cookie, const char *buf, size_t nbytes) {// 自定义写函数的实现// 这里假设cookie是一个文件指针FILE *fp = (FILE *)cookie;return fwrite(buf, 1, nbytes, fp);
}int my_close(void *cookie) {// 自定义关闭函数的实现// 这里假设cookie是一个文件指针FILE *fp = (FILE *)cookie;return fclose(fp);
}// 定义虚表实例并赋值
struct _IO_jump_t my_vtable = {.read = my_read,.write = my_write,.close = my_close,
};// 打开文件并初始化自定义文件结构体
_IO_FILE *my_fopen(const char *filename, const char *mode) {FILE *fp = fopen(filename, mode);if (!fp) return NULL;_IO_FILE *file = (_IO_FILE *)malloc(sizeof(_IO_FILE));file->vtable = &my_vtable;file->cookie = fp;return file;
}// 关闭文件并释放自定义文件结构体
int my_fclose(_IO_FILE *file) {int result = file->vtable->close(file->cookie);free(file);return result;
}// 读取文件
ssize_t my_fread(_IO_FILE *file, char *buf, size_t nbytes) {return file->vtable->read(file->cookie, buf, nbytes);
}// 写入文件
ssize_t my_fwrite(_IO_FILE *file, const char *buf, size_t nbytes) {return file->vtable->write(file->cookie, buf, nbytes);
}int main() {_IO_FILE *file = my_fopen("example.txt", "w+");if (!file) {perror("Failed to open file");return 1;}const char *text = "Hello, world!";my_fwrite(file, text, strlen(text));char buf[512];fseek((FILE *)file->cookie, 0, SEEK_SET); // 重置文件指针位置my_fread(file, buf, sizeof(buf));printf("Read from file: %s\n", buf);my_fclose(file);return 0;
}
解释
-
虚表结构体
_IO_jump_t:- 这个结构体包含了各种文件操作函数的指针,例如
read、write和close。
- 这个结构体包含了各种文件操作函数的指针,例如
-
文件结构体
_IO_FILE:- 这个结构体包含一个指向虚表的指针
vtable和一个自定义数据指针cookie,用于存储具体的文件信息(例如文件指针)。
- 这个结构体包含一个指向虚表的指针
-
自定义文件操作函数:
- 这些函数实现了特定的文件操作,例如
my_read、my_write和my_close,并通过虚表中的函数指针调用。
- 这些函数实现了特定的文件操作,例如
-
文件操作函数的调用:
my_fopen函数打开文件并初始化_IO_FILE结构体。my_fread和my_fwrite函数通过虚表指针调用具体的读写函数。my_fclose函数通过虚表指针调用关闭函数并释放结构体内存。
通过这种方式,你可以看到 __IO_FILE 结构体的虚表指向了各种文件操作函数,从而实现了不同类型文件流的多态行为。
寻找不同libc版本的定义
要查找特定版本的 GNU libc(glibc)中 _IO_jump_t 的定义和其他相关实现细节,你可以采取以下几种方法:
1. 查看源码仓库
glibc 的源码是公开的,你可以在其源码仓库中查找特定版本的实现:
- GNU libc 官方网站:你可以从 GNU libc 网站上获取源码。
- GNU libc Git Repository:glibc 的代码仓库托管在 sourceware.org。你可以使用以下命令克隆仓库:
然后你可以切换到特定的版本标签或提交记录来查看源代码。例如:git clone git://sourceware.org/git/glibc.gitcd glibc git checkout tags/glibc-2.31
2. 在线代码浏览器
你也可以使用在线代码浏览器查看特定版本的 glibc 源代码。这些浏览器通常提供了方便的搜索和导航功能。例如:
- Sourceware Git Web:这是 sourceware.org 提供的在线代码浏览器,直接访问 glibc Git web.
3. 下载和解压发行版源码
特定版本的 glibc 源代码可以通过下载对应的源码压缩包来获取:
- 从 GNU FTP 站点 下载特定版本的源码压缩包。
- 解压下载的源码包:
tar -xvf glibc-2.31.tar.gz cd glibc-2.31
4. 查看系统安装的源码包
如果你使用的是基于 Debian 或 Fedora 的 Linux 发行版,通常可以安装特定版本的 glibc 源代码包:
- Debian/Ubuntu:
sudo apt-get source libc6 - Fedora:
sudo dnf download --source glibc
查找 _IO_jump_t 的定义
在源码树中,你可以使用 grep 或其他文本搜索工具查找 _IO_jump_t 的定义。通常,相关定义会出现在 libio 目录下的头文件中,例如 libio.h。
grep -r "_IO_jump_t" .
以上命令会在当前目录及其子目录中递归搜索包含 _IO_jump_t 的文件。
示例
让我们以 glibc 2.31 版本为例:
-
克隆并检出特定版本:
git clone git://sourceware.org/git/glibc.git cd glibc git checkout tags/glibc-2.31 -
查找
_IO_jump_t的定义:grep -r "_IO_jump_t" .
这样,你应该能够找到 _IO_jump_t 以及其他相关数据结构和函数的定义。通常,这些定义会出现在 libio/libio.h 或类似的头文件中。
通过这些步骤,你可以查找到特定版本的 glibc 中 _IO_jump_t 的定义以及其他相关实现细节。
相关文章:
CTF-PWN: 虚表(vtable)
vtable vtable(虚表,virtual table)是面向对象编程中的一个关键概念,主要用于实现多态性(polymorphism)。它是一种数据结构,通常是一个指针数组,包含了类的虚函数(virtu…...
Redis 集群 总结
前言 相关系列 《Redis & 目录》(持续更新)《Redis & 集群 & 源码》(学习过程/多有漏误/仅作参考/不再更新)《Redis & 集群 & 总结》(学习总结/最新最准/持续更新)《Redis & 集群…...
2024校园交友系统构建指南/保姆版教程与技巧uniapp+php支持二开
一、建构技巧 1.前后端分离:采用前后端分离的开发模式,有助于提升开发效率,降低维护成本。前端专注于用户界面和交互体验,后端专注于业务逻辑和数据处理。 2.数据安全与隐私保护:实现细粒度的用户权限控制,确保用户数…...
NVR设备ONVIF接入平台EasyCVR视频分析设备平台视频质量诊断技术与能力
视频诊断技术是一种智能化的视频故障分析与预警系统,NVR设备ONVIF接入平台EasyCVR通过对前端设备传回的码流进行解码以及图像质量评估,对视频图像中存在的质量问题进行智能分析、判断和预警。这项技术在安防监控领域尤为重要,因为它能够确保监…...
系统思考—啤酒游戏经营决策沙盘
《第五项修炼:学习型组织建立》——系统思考的深层实践 越来越多的客户发现,系统思考不仅仅是一门课程,而是一种长期的实践。感谢合作伙伴对《第五项修炼》的支持,将其作为一个整体项目推荐。广东嘉荣超市在8月结束两天系统思考的…...
组件封装思路
组件封装的核心思路是:把可复用的结构只写一次,把可能发生变化的部分抽象成组件参数(props/插槽)。 如果是像纯文本,像是一些主标题和副标题,可以抽象成prop传入 如果主体内容是复杂的模版,有图片有列表等,…...
akshare股票涨跌停获取统计分析
参看: https://akshare.akfamily.xyz/data/stock/stock.html#id375 数据源来自东方财富网:https://quote.eastmoney.com/ztb/detail#typeztgc 参数说明 涨停统计: n/m代表m天中有n次涨停板 安装: pip install akshare -i http…...
前端对一个增删改查的思考
1、来源:dify dify/web/app/components/workflow/nodes/question-classifier/components/class-list.tsx at main langgenius/dify GitHub 2、代码流程: 3、思索问题: 1、为啥要用return形式,而不是value直接当函数࿱…...
【Clickhouse】客户端连接工具配置
ClickHouse 是什么 ClickHouse 是一个分布式实时分析型列式存储数据库。具备高性能,支撑PB级数据,提供实时分析,稳定可扩展等特性。适用于数据仓库、BI报表、监控系统、互联网用户行为分析、广告投放业务以及工业、物联网等分析和时序应用场…...
【测试平台】打包 jenkins配置和jenkinsfile文件
背景: 当打包机环境配置完成后,需要挂到master的jenkins中,完成调度。 jenkins启动 命令行直接启动即可。 nohup java -jar /usr/local/opt/jenkins/libexec/jenkins.war --httpListenAddress0.0.0.0 --httpPort80 appending output to n…...
Leetcode224 -- 基本计算器及其拓展
题目分析: 其实这个计算器的实现并不难,因为除了括号就剩下加减法嘛,括号肯定比加减法先执行,但是加减法是同级的,只是会改变数字的正负号而已,所以实现的逻辑并不是很难,我们只需要一个栈&…...
python的lambda实用技巧
lambda表达式 lambda表达式是一种简化的函数表现形式,也叫匿名函数,可以存在函数名也可以不存在。 使用一行代码就可以表示一个函数: # 格式 lambda arg[参数] : exp[表现形式] # 无参写法 lambda : "hello" # 一般写法 lambda …...
VB中的资源文件(Resource File)及其用途
在Visual Basic(VB)中,资源文件(Resource File)是一种特殊的文件,用于存储应用程序中使用的非代码资源。这些资源可以是字符串、图像、图标、音频文件、视频文件等。资源文件的主要用途是使应用程序的管理和…...
【vue】11.Vue 3生命周期钩子在实践中的具体应用
Vue 3的生命周期钩子为开发者提供了在不同阶段操作组件的强大能力。本文将带您了解每个生命周期钩子的使用场景,并通过简单的案例来展示它们在实际开发中的应用。 1. 创建阶段(Creation Hooks) beforeCreate 进行一些初始化操作,…...
1.5 新特性 C++面试常见问题
1.5.1 说说C11的新特性有哪些? C11 引入了许多重要的新特性和增强,目的是提升语言的性能、可读性和简洁性。以下是 C11 的一些主要新特性: 1. 自动类型推导 使用 auto 关键字,可以让编译器自动推导变量的类型。auto x 42; …...
[mysql]子查询的概述和分类及单行子查询
子查询引入 查询的基本结构已经给大家了,子查询里面也是有一些新的内容,子查询其实就是在查询中嵌套另一个查询,叫嵌套查询可能大家更容易理解一点..,类似与FOR循环和FOR循环的嵌套,这一章是我们查询的最难的部分,大家 难度是查询的顶峰,多表查询和子查询是非常重要,SQL优化里…...
SpringMVC执行流程(视图阶段JSP、前后端分离阶段)、面试题
目录 1.SpringMVC执行流程分为以下两种 2.非前后端分离的SpringMVC的执行流程 3.前后端分离的项目SpringMVC执行流程 4. 面试题 1.SpringMVC执行流程分为以下两种 2.非前后端分离的SpringMVC的执行流程 流程图: 更加生动的描述: DisPatcherServlet…...
宠物空气净化器有用吗?有哪几款吸毛效果好且低噪的推荐
伴随着天气越来越凉,照常来说,猫咪掉毛的频率应该会变少,但是为什么我家的猫咪还在掉很多毛。 现在就连南方地区都要加外套了,但是猫咪掉毛太多,都不敢穿纯棉面料的衣服,还有本来想着顺应天气的变化&#…...
linux -磁盘管理命令
学会用fidsk -l blkid lskid 就够用 格式化文件系统:mkfs -t <文件系统格式> /dev/vdb1 1..df -Th 查看磁盘挂载情况。 2.fdisk 磁盘分区命令 示例一:fdisk -l 查看磁盘分区,箭头指出分区信息 示例二:创建分区eg…...
[Chrome插件开发]关于报错Service worker registration failed. Status code: 15
manifest.json中不能使用ts: "background": {"service_worker": "background.ts"}只能使用js "background": {"service_worker": "background.js"}在vite.config.js中增加以下配置,可以将…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
ZYNQ学习记录FPGA(一)ZYNQ简介
一、知识准备 1.一些术语,缩写和概念: 1)ZYNQ全称:ZYNQ7000 All Pgrammable SoC 2)SoC:system on chips(片上系统),对比集成电路的SoB(system on board) 3)ARM:处理器…...
