Compare commits

..

No commits in common. "master" and "20250525-0b5eb5a9" have entirely different histories.

19 changed files with 83 additions and 204 deletions

View File

@ -33,7 +33,7 @@ if __name__ == "__main__":
parser.add_argument('--small', action='store_true', help='Build small version of linpeas.') parser.add_argument('--small', action='store_true', help='Build small version of linpeas.')
parser.add_argument('--include', type=str, help='Build linpeas only with the modules indicated you can indicate section names or module IDs).') parser.add_argument('--include', type=str, help='Build linpeas only with the modules indicated you can indicate section names or module IDs).')
parser.add_argument('--exclude', type=str, help='Exclude the given modules (you can indicate section names or module IDs).') parser.add_argument('--exclude', type=str, help='Exclude the given modules (you can indicate section names or module IDs).')
parser.add_argument('--output', required=True, type=str, help='Path to write the final linpeas file to.') parser.add_argument('--output', required=True, type=str, help='Parth to write the final linpeas file to.')
args = parser.parse_args() args = parser.parse_args()
all_modules = args.all all_modules = args.all

View File

@ -26,7 +26,7 @@
# License: GNU GPL # License: GNU GPL
# Version: 1.0 # Version: 1.0
# Functions Used: echo_not_found, print_2title, print_info # Functions Used: echo_not_found, print_2title, print_info
# Global Variables: $NoEnvVars, $EnvVarsRed # Global Variables:
# Initial Functions: # Initial Functions:
# Generated Global Variables: # Generated Global Variables:
# Fat linpeas: 0 # Fat linpeas: 0
@ -35,5 +35,5 @@
print_2title "Environment" print_2title "Environment"
print_info "Any private information inside environment variables?" print_info "Any private information inside environment variables?"
(env || printenv || set) 2>/dev/null | grep -Eiv "$NoEnvVars" | sed -${E} "s,$EnvVarsRed,${SED_RED},g" || echo_not_found "env || set" (env || printenv || set) 2>/dev/null | grep -v "RELEVANT*|FIND*|^VERSION=|dbuslistG|mygroups|ldsoconfdG|pwd_inside_history|kernelDCW_Ubuntu_Precise|kernelDCW_Ubuntu_Trusty|kernelDCW_Ubuntu_Xenial|kernelDCW_Rhel|^sudovB=|^rootcommon=|^mounted=|^mountG=|^notmounted=|^mountpermsB=|^mountpermsG=|^kernelB=|^C=|^RED=|^GREEN=|^Y=|^B=|^NC=|TIMEOUT=|groupsB=|groupsVB=|knw_grps=|sidG|sidB=|sidVB=|sidVB2=|sudoB=|sudoG=|sudoVB=|timersG=|capsB=|notExtensions=|Wfolders=|writeB=|writeVB=|_usrs=|compiler=|LS_COLORS=|pathshG=|notBackup=|processesDump|processesB|commonrootdirs|USEFUL_SOFTWARE|PSTORAGE_" | sed -${E} "s,[pP][aA][sS][sS][wW]|[aA][pP][iI][kK][eE][yY]|[aA][pP][iI][_][kK][eE][yY]|KRB5CCNAME,${SED_RED},g" || echo_not_found "env || set"
echo "" echo ""

View File

@ -19,20 +19,20 @@ print_2title "Internet Access?"
TIMEOUT_INTERNET_SECONDS=5 TIMEOUT_INTERNET_SECONDS=5
if [ "$SUPERFAST" ]; then if [ "$SUPERFAST" ]; then
TIMEOUT_INTERNET_SECONDS=2.5 TIMEOUT_INTERNET_SECONDS=2
fi fi
# Run all checks in background # Run all checks in background
check_tcp_80 "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid1=$! check_tcp_80 2>/dev/null & pid1=$!
check_tcp_443 "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid2=$! check_tcp_443 2>/dev/null & pid2=$!
check_icmp "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid3=$! check_icmp 2>/dev/null & pid3=$!
check_dns "$TIMEOUT_INTERNET_SECONDS" 2>/dev/null & pid4=$! check_dns 2>/dev/null & pid4=$!
# Kill all after 10 seconds # Kill all after 10 seconds
(sleep $(( $TIMEOUT_INTERNET_SECONDS + 1 )) && kill -9 $pid1 $pid2 $pid3 $pid4 2>/dev/null) & (sleep $TIMEOUT_INTERNET_SECONDS && kill -9 $pid1 $pid2 $pid3 $pid4 2>/dev/null) &
check_tcp_443_bin $TIMEOUT_INTERNET_SECONDS 2>/dev/null check_tcp_443_bin 2>/dev/null
tcp443_bin_status=$? tcp443_bin_status=$?
wait $pid1 $pid2 $pid3 $pid4 2>/dev/null wait $pid1 $pid2 $pid3 $pid4 2>/dev/null

View File

@ -8,7 +8,7 @@
# Functions Used: print_2title # Functions Used: print_2title
# Global Variables: $DEBUG, $knw_usrs, $nosh_usrs, $sh_usrs, $DEBUG, $USER, $STRINGS # Global Variables: $DEBUG, $knw_usrs, $nosh_usrs, $sh_usrs, $DEBUG, $USER, $STRINGS
# Initial Functions: # Initial Functions:
# Generated Global Variables: $mysqluser, $mysqlexec, $mysqlconnect, $mysqlconnectnopass, $mysqluser, $version_output, $major_version, $version, $process_info # Generated Global Variables: $mysqluser, $mysqlexec, $mysqlconnect, $mysqlconnectnopass
# Fat linpeas: 0 # Fat linpeas: 0
# Small linpeas: 1 # Small linpeas: 1
@ -103,41 +103,3 @@ if [ "$(command -v mysql || echo -n '')" ] || [ "$(command -v mysqladmin || echo
fi fi
echo "" echo ""
fi fi
### This section checks if MySQL (mysqld) is running as root and if its version is 4.x or 5.x to refer a known local privilege escalation exploit! ###
# Find the mysqld process
process_info=$(ps aux | grep '[m]ysqld' | head -n1)
if [ -z "$process_info" ]; then
echo "MySQL process not found." | sed -${E} "s,.*,${SED_GREEN},"
else
# Extract the process user
mysqluser=$(echo "$process_info" | awk '{print $1}')
# Get the MySQL version string
version_output=$(mysqld --version 2>&1)
# Extract the version number (expects format like X.Y.Z)
version=$(echo "$version_output" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
if [ -z "$version" ]; then
echo "Unable to determine MySQL version." | sed -${E} "s,.*,${SED_GREEN},"
else
# Extract the major version number (X from X.Y.Z)
major_version=$(echo "$version" | cut -d. -f1)
# Check if MySQL is running as root and if the version is either 4.x or 5.x
if [ "$mysqluser" = "root" ] && { [ "$major_version" -eq 4 ] || [ "$major_version" -eq 5 ]; }; then
echo "MySQL is running as root with version $version. This is a potential local privilege escalation vulnerability!" | sed -${E} "s,.*,${SED_RED},"
echo "\tRefer to: https://www.exploit-db.com/exploits/1518" | sed -${E} "s,.*,${SED_YELLOW},"
echo "\tRefer to: https://medium.com/r3d-buck3t/privilege-escalation-with-mysql-user-defined-functions-996ef7d5ceaf" | sed -${E} "s,.*,${SED_YELLOW},"
else
echo "MySQL is running as user '$mysqluser' with version $version." | sed -${E} "s,.*,${SED_GREEN},"
fi
### ------------------------------------------------------------------------------------------------------------------------------------------------ ###
fi
fi

View File

@ -1,22 +0,0 @@
# Title: Interesting Files - Interesting Environment Variables
# ID: IF_Interesting_environment_variables
# Author: Jack Vaughn
# Last Update: 25-05-2025
# Description: Searching possible sensitive environment variables inside of /proc/*/environ
# License: GNU GPL
# Version: 1.0
# Functions Used: print_2title
# Global Variables: $MACPEAS, $NoEnvVars, $EnvVarsRed
# Initial Functions:
# Generated Global Variables:
# Fat linpeas: 0
# Small linpeas: 1
if [ -z "$MACPEAS" ]; then
print_2title "Checking all env variables in /proc/*/environ removing duplicates and filtering out useless env vars"
cat /proc/[0-9]*/environ 2>/dev/null | \
tr '\0' '\n' | \
grep -Eiv "$NoEnvVars" | \
sort -u | \
sed -${E} "s,$EnvVarsRed,${SED_RED},g"
fi

View File

@ -8,19 +8,25 @@
# Functions Used: # Functions Used:
# Global Variables: # Global Variables:
# Initial Functions: # Initial Functions:
# Generated Global Variables: $TIMEOUT_INTERNET_SECONDS_DNS, $local_pid # Generated Global Variables: $pid, $pids
# Fat linpeas: 0 # Fat linpeas: 0
# Small linpeas: 1 # Small linpeas: 1
check_dns(){ check_dns(){
local TIMEOUT_INTERNET_SECONDS_DNS=$1
if ! [ -f "/bin/bash" ]; then if ! [ -f "/bin/bash" ]; then
echo " /bin/bash not found" echo " /bin/bash not found"
return return
fi fi
# example.com /bin/bash -c '
(bash -c '((( echo cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001 | xxd -p -r >&3; dd bs=9000 count=1 <&3 2>/dev/null | xxd ) 3>/dev/udp/1.1.1.1/53 && echo "DNS accessible") | grep "accessible" && exit 0 ) 2>/dev/null || echo "DNS is not accessible"') & local_pid=$! for ip in 1.1.1.1 8.8.8.8 ; do
(( echo cfc9 0100 0001 0000 0000 0000 0a64 7563 6b64 7563 6b67 6f03 636f 6d00 0001 0001 | xxd -p -r >&3; dd bs=9000 count=1 <&3 2>/dev/null | xxd ) 3>/dev/udp/$ip/53 && echo "DNS available" && exit 0) &
sleep $TIMEOUT_INTERNET_SECONDS_DNS && kill -9 $local_pid 2>/dev/null && echo "DNS is not accessible" pids+=($!)
done
for pid in ${pids[@]}; do
wait $pid && exit 0
done
echo "DNS not available"
' 2>/dev/null | grep "available" || echo "DNS not available"
} }

View File

@ -8,20 +8,11 @@
# Functions Used: # Functions Used:
# Global Variables: # Global Variables:
# Initial Functions: # Initial Functions:
# Generated Global Variables: $TIMEOUT_INTERNET_SECONDS_ICMP, $local_pid # Generated Global Variables:
# Fat linpeas: 0 # Fat linpeas: 0
# Small linpeas: 1 # Small linpeas: 1
check_icmp(){ check_icmp(){
local TIMEOUT_INTERNET_SECONDS_ICMP=$1 (ping -c 1 1.1.1.1 | grep -E "1 received|1 packets received" && echo "Ping is available" || echo "Ping is not available" 2>/dev/null) | grep -i "available"
if ! [ "$(command -v ping 2>/dev/null || echo -n '')" ]; then
echo " ping not found"
return
fi
# example.com
((ping -c 1 1.1.1.1 2>/dev/null | grep -Ei "1 received|1 packets received" && echo "ICMP is accessible" || echo "ICMP is not accessible" 2>/dev/null) | grep "accessible" && exit 0 ) 2>/dev/null || echo "ICMP is not accessible" & local_pid=$!
sleep $TIMEOUT_INTERNET_SECONDS_ICMP && kill -9 $local_pid 2>/dev/null && echo "ICMP is not accessible"
} }

View File

@ -8,21 +8,30 @@
# Functions Used: # Functions Used:
# Global Variables: # Global Variables:
# Initial Functions: # Initial Functions:
# Generated Global Variables: $local_pid, $TIMEOUT_INTERNET_SECONDS_443 # Generated Global Variables: $pid, $pids
# Fat linpeas: 0 # Fat linpeas: 0
# Small linpeas: 1 # Small linpeas: 1
check_tcp_443(){ check_tcp_443(){
local TIMEOUT_INTERNET_SECONDS_443=$1
if ! [ -f "/bin/bash" ]; then if ! [ -f "/bin/bash" ]; then
echo " /bin/bash not found" echo " /bin/bash not found"
return return
fi fi
# example.com /bin/bash -c '
(bash -c '(echo >/dev/tcp/104.18.74.230/443 2>/dev/null && echo "Port 443 is accessible" && exit 0) 2>/dev/null || echo "Port 443 is not accessible"') & local_pid=$! for ip in 1.1.1.1; do
(echo >/dev/tcp/$ip/443 && echo "Port 443 is accessible" && exit 0) &
sleep $TIMEOUT_INTERNET_SECONDS_443 && kill -9 $local_pid 2>/dev/null && echo "Port 443 is not accessible" pids+=($!)
done
for pid in ${pids[@]}; do
wait $pid && exit 0
done
echo "Port 443 is not accessible"
' 2>/dev/null | grep "accessible" || echo "Port 443 is not accessible"
} }

View File

@ -8,17 +8,16 @@
# Functions Used: # Functions Used:
# Global Variables: # Global Variables:
# Initial Functions: # Initial Functions:
# Generated Global Variables: $url_lambda, $TIMEOUT_INTERNET_SECONDS_443_BIN # Generated Global Variables: $url_lambda
# Fat linpeas: 0 # Fat linpeas: 0
# Small linpeas: 1 # Small linpeas: 1
check_tcp_443_bin () { check_tcp_443_bin () {
local TIMEOUT_INTERNET_SECONDS_443_BIN=$1
local url_lambda="https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/" local url_lambda="https://2e6ppt7izvuv66qmx2r3et2ufi0mxwqs.lambda-url.us-east-1.on.aws/"
if command -v curl >/dev/null 2>&1; then if command -v curl >/dev/null 2>&1; then
if curl -s --connect-timeout $TIMEOUT_INTERNET_SECONDS_443_BIN "$url_lambda" \ if curl -s --connect-timeout 5 "$url_lambda" \
-H "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1 -H "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1
then then
echo "Port 443 is accessible with curl" echo "Port 443 is accessible with curl"
@ -29,7 +28,7 @@ check_tcp_443_bin () {
fi fi
elif command -v wget >/dev/null 2>&1; then elif command -v wget >/dev/null 2>&1; then
if wget -q --timeout=$TIMEOUT_INTERNET_SECONDS_443_BIN -O - "$url_lambda" \ if wget -q --timeout=5 -O - "$url_lambda" \
--header "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1 --header "User-Agent: linpeas" -H "Content-Type: application/json" >/dev/null 2>&1
then then
echo "Port 443 is accessible with wget" echo "Port 443 is accessible with wget"

View File

@ -8,21 +8,25 @@
# Functions Used: # Functions Used:
# Global Variables: # Global Variables:
# Initial Functions: # Initial Functions:
# Generated Global Variables: $local_pid, $TIMEOUT_INTERNET_SECONDS_80 # Generated Global Variables: $pid, $pids
# Fat linpeas: 0 # Fat linpeas: 0
# Small linpeas: 1 # Small linpeas: 1
check_tcp_80(){ check_tcp_80(){
local TIMEOUT_INTERNET_SECONDS_80=$1
if ! [ -f "/bin/bash" ]; then if ! [ -f "/bin/bash" ]; then
echo " /bin/bash not found" echo " /bin/bash not found"
return return
fi fi
# example.com /bin/bash -c '
(bash -c '(echo >/dev/tcp/104.18.74.230/80 2>/dev/null && echo "Port 80 is accessible" && exit 0) 2>/dev/null || echo "Port 80 is not accessible"') & local_pid=$! for ip in 1.1.1.1; do
(echo >/dev/tcp/$ip/80 && echo "Port 80 is accessible" && exit 0) &
sleep $TIMEOUT_INTERNET_SECONDS_80 && kill -9 $local_pid 2>/dev/null && echo "Port 80 is not accessible" pids+=($!)
done
for pid in ${pids[@]}; do
wait $pid && exit 0
done
echo "Port 80 is not accessible"
' 2>/dev/null | grep "accessible"
} }

View File

@ -1,18 +0,0 @@
# Title: Variables - EnvVarsRed
# ID: EnvVarsRed
# Author: Carlos Polop
# Last Update: 26-05-2025
# Description: Useless env vars
# License: GNU GPL
# Version: 1.0
# Functions Used:
# Global Variables:
# Initial Functions:
# Generated Global Variables: $EnvVarsRed
# Fat linpeas: 0
# Small linpeas: 1
EnvVarsRed="[pP][aA][sS][sS][wW]|[aA][pP][iI][kK][eE][yY]|[aA][pP][iI][_][kK][eE][yY]|KRB5CCNAME|[aA][pP][iI][_][kK][eE][yY]|[aA][wW][sS]|[aA][zZ][uU][rR][eE]|[gG][cC][pP]|[aA][pP][iI]|[sS][eE][cC][rR][eE][tT]|[sS][qQ][lL]|[dD][aA][tT][aA][bB][aA][sS][eE]|[tT][oO][kK][eE][nN]"

View File

@ -1,16 +0,0 @@
# Title: Variables - NoEnvVars
# ID: NoEnvVars
# Author: Carlos Polop
# Last Update: 26-05-2025
# Description: Useless env vars
# License: GNU GPL
# Version: 1.0
# Functions Used:
# Global Variables:
# Initial Functions:
# Generated Global Variables: $NoEnvVars
# Fat linpeas: 0
# Small linpeas: 1
NoEnvVars="LESS_TERMCAP|JOURNAL_STREAM|XDG_SESSION|DBUS_SESSION|systemd\/sessions|systemd_exec|MEMORY_PRESSURE_WATCH|RELEVANT*|FIND*|^VERSION=|dbuslistG|mygroups|ldsoconfdG|pwd_inside_history|kernelDCW_Ubuntu_Precise|kernelDCW_Ubuntu_Trusty|kernelDCW_Ubuntu_Xenial|kernelDCW_Rhel|^sudovB=|^rootcommon=|^mounted=|^mountG=|^notmounted=|^mountpermsB=|^mountpermsG=|^kernelB=|^C=|^RED=|^GREEN=|^Y=|^B=|^NC=|TIMEOUT=|groupsB=|groupsVB=|knw_grps=|sidG|sidB=|sidVB=|sidVB2=|sudoB=|sudoG=|sudoVB=|timersG=|capsB=|notExtensions=|Wfolders=|writeB=|writeVB=|_usrs=|compiler=|LS_COLORS=|pathshG=|notBackup=|processesDump|processesB|commonrootdirs|USEFUL_SOFTWARE|PSTORAGE_|^PATH=|^INVOCATION_ID=|^WATCHDOG_PID=|^LISTEN_PID="

View File

@ -292,12 +292,9 @@ class LinpeasBaseBuilder:
all_module_paths += self.enumerate_directory(LINPEAS_PARTS["variables"]) all_module_paths += self.enumerate_directory(LINPEAS_PARTS["variables"])
for module in LINPEAS_PARTS["modules"]: for module in LINPEAS_PARTS["modules"]:
exclude = False
for ex_module in exclude_modules: for ex_module in exclude_modules:
if ex_module in module["folder_path"] or ex_module in [module["name"], module["name_check"]]: if ex_module in module["folder_path"] or ex_module in [module["name"], module["name_check"]]:
exclude = True continue
break
if exclude: continue
all_module_paths += self.enumerate_directory(module["folder_path"]) all_module_paths += self.enumerate_directory(module["folder_path"])
for module in all_module_paths: for module in all_module_paths:

View File

@ -97,7 +97,7 @@ class LinpeasBuilder:
for orig_url in urls: for orig_url in urls:
tar_gz_bin_name = "" tar_gz_bin_name = ""
if ",,," in orig_url: if ",,," in orig_url:
tar_gz_bin_name = orig_url.split(",,,")[1] tar_gz_bin_name = url.split(",,,")[1]
url = orig_url.split(",,,")[0] url = orig_url.split(",,,")[0]
else: else:
url = orig_url url = orig_url
@ -402,9 +402,9 @@ class LinpeasBuilder:
def __replace_mark(self, mark: str, find_calls: list, join_char: str): def __replace_mark(self, mark: str, find_calls: list, join_char: str):
"""Substitute the markup with the actual code""" """Substitude the markup with the actual code"""
self.linpeas_sh = self.linpeas_sh.replace(mark, join_char.join(find_calls)) #New line char isn't needed self.linpeas_sh = self.linpeas_sh.replace(mark, join_char.join(find_calls)) #New line char is't needed
def write_linpeas(self, path): def write_linpeas(self, path):
"""Write on disk the final linpeas""" """Write on disk the final linpeas"""

View File

@ -106,6 +106,8 @@ def parse_line(line: str):
global FINAL_JSON, C_SECTION, C_MAIN_SECTION, C_2_SECTION, C_3_SECTION global FINAL_JSON, C_SECTION, C_MAIN_SECTION, C_2_SECTION, C_3_SECTION
if "Cron jobs" in line:
a=1
if is_section(line, TITLE1_PATTERN): if is_section(line, TITLE1_PATTERN):
title = parse_title(line) title = parse_title(line)
@ -143,23 +145,14 @@ def parse_line(line: str):
def parse_peass(outputpath: str, jsonpath: str = ""): def parse_peass(outputpath: str, jsonpath: str = ""):
global OUTPUT_PATH, JSON_PATH, FINAL_JSON, C_SECTION, C_MAIN_SECTION, C_2_SECTION, C_3_SECTION global OUTPUT_PATH, JSON_PATH
OUTPUT_PATH = outputpath OUTPUT_PATH = outputpath
JSON_PATH = jsonpath JSON_PATH = jsonpath
# Reset globals to avoid data leaking between executions for line in open(OUTPUT_PATH, 'r', encoding="utf8").readlines():
FINAL_JSON = {}
C_SECTION = FINAL_JSON
C_MAIN_SECTION = FINAL_JSON
C_2_SECTION = FINAL_JSON
C_3_SECTION = FINAL_JSON
with open(OUTPUT_PATH, 'r', encoding="utf8") as f:
for line in f.readlines():
line = line.strip() line = line.strip()
# Remove empty lines or lines containing only color codes if not line or not clean_colors(line): #Remove empty lines or lines just with colors hex
if not line or not clean_colors(line):
continue continue
parse_line(line) parse_line(line)

View File

@ -102,16 +102,18 @@ namespace winPEAS.Checks
{ {
vulnHandlers = ProcessesInfo.GetVulnHandlers(progress); vulnHandlers = ProcessesInfo.GetVulnHandlers(progress);
} }
Dictionary<string, string> colors = new Dictionary<string, string>();
colors[Checks.CurrentUserName] = Beaprint.ansi_color_bad;
colors[HandlesHelper.elevatedProcess] = Beaprint.ansi_color_bad;
foreach (Dictionary<string, string> handler in vulnHandlers) foreach (Dictionary<string, string> handler in vulnHandlers)
{ {
colors[handler["Reason"]] = Beaprint.ansi_color_bad; Dictionary<string, string> colors = new Dictionary<string, string>()
} {
{ Checks.CurrentUserName, Beaprint.ansi_color_bad },
{ handler["Reason"], Beaprint.ansi_color_bad },
};
Beaprint.DictPrint(vulnHandlers, colors, true); Beaprint.DictPrint(vulnHandlers, colors, true);
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Beaprint.PrintException(ex.Message); Beaprint.PrintException(ex.Message);

View File

@ -31,7 +31,7 @@ namespace winPEAS.Helpers
public static string ansi_current_user = MAGENTA; public static string ansi_current_user = MAGENTA;
private static string Advisory = private static string Advisory =
"winpeas should be used for authorized penetration testing and/or educational purposes only. " + "winpeas should be used for authorized penetration testing and/or educational purposes only." +
"Any misuse of this software will not be the responsibility of the author or of any other collaborator. " + "Any misuse of this software will not be the responsibility of the author or of any other collaborator. " +
"Use it at your own devices and/or with the device owner's permission."; "Use it at your own devices and/or with the device owner's permission.";

View File

@ -12,7 +12,6 @@ namespace winPEAS.Helpers
private const int CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64; private const int CNST_SYSTEM_EXTENDED_HANDLE_INFORMATION = 64;
public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; public const uint STATUS_INFO_LENGTH_MISMATCH = 0xC0000004;
public const int DUPLICATE_SAME_ACCESS = 0x2; public const int DUPLICATE_SAME_ACCESS = 0x2;
public const string elevatedProcess = "Access denied, process is probably elevated";
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct FILE_NAME_INFO public struct FILE_NAME_INFO
@ -172,7 +171,7 @@ namespace winPEAS.Helpers
// Hex perms from https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights and https://github.com/buffer/maltracer/blob/master/defines.py // Hex perms from https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights and https://github.com/buffer/maltracer/blob/master/defines.py
//PROCESS_ALL_ACCESS //PROCESS_ALL_ACCESS
if ((h.GrantedAccess & 0x001F0FFF) == h.GrantedAccess || (h.GrantedAccess & 0x1FFFFF) == h.GrantedAccess) if ((h.GrantedAccess & 0x001F0FFF) == h.GrantedAccess)
{ {
vulnHandler.isVuln = true; vulnHandler.isVuln = true;
vulnHandler.reason = "PROCESS_ALL_ACCESS"; vulnHandler.reason = "PROCESS_ALL_ACCESS";
@ -455,8 +454,6 @@ namespace winPEAS.Helpers
} }
catch catch
{ {
data["name"] = elevatedProcess;
data["sid"] = elevatedProcess;
return data; return data;
} }
finally finally
@ -472,32 +469,12 @@ namespace winPEAS.Helpers
public static PT_RELEVANT_INFO getProcInfoById(int pid) public static PT_RELEVANT_INFO getProcInfoById(int pid)
{ {
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO(); PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
Process proc;
try Process proc = Process.GetProcessById(pid);
{
proc = Process.GetProcessById(pid);
}
catch
{
pri.pid = pid;
pri.name = "Error, process may not exist";
pri.userName = "Error, process may not exist";
pri.userSid = "Error, process may not exist";
pri.imagePath = "Error, process may not exist";
return pri;
}
Dictionary<string, string> user = GetProcU(proc); Dictionary<string, string> user = GetProcU(proc);
StringBuilder fileName = new StringBuilder(2000);
try StringBuilder fileName = new StringBuilder(2000);
{
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000); Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
}
catch
{
fileName = new StringBuilder(elevatedProcess);
}
pri.pid = pid; pri.pid = pid;
pri.name = proc.ProcessName; pri.name = proc.ProcessName;

View File

@ -195,11 +195,11 @@ namespace winPEAS.Info.ProcessInfo
continue; continue;
List<string> permsFile = PermissionsHelper.GetPermissionsFile(sFilePath, Checks.Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT); List<string> permsFile = PermissionsHelper.GetPermissionsFile(sFilePath, Checks.Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT);
IdentityReference sid = null;
try try
{ {
System.Security.AccessControl.FileSecurity fs = System.IO.File.GetAccessControl(sFilePath); System.Security.AccessControl.FileSecurity fs = System.IO.File.GetAccessControl(sFilePath);
sid = fs.GetOwner(typeof(SecurityIdentifier)); IdentityReference sid = fs.GetOwner(typeof(SecurityIdentifier));
string ownerName = sid.Translate(typeof(NTAccount)).ToString();
// If current user already have permissions over that file or the proc belongs to the owner of the file, // If current user already have permissions over that file or the proc belongs to the owner of the file,
// handler not interesting to elevate privs // handler not interesting to elevate privs
@ -207,8 +207,6 @@ namespace winPEAS.Info.ProcessInfo
continue; continue;
to_add["File Path"] = sFilePath; to_add["File Path"] = sFilePath;
string ownerName = sid.Translate(typeof(NTAccount)).ToString();
to_add["File Owner"] = ownerName; to_add["File Owner"] = ownerName;
} }
catch (System.IO.FileNotFoundException) catch (System.IO.FileNotFoundException)
@ -220,10 +218,7 @@ namespace winPEAS.Info.ProcessInfo
{ {
continue; continue;
} }
catch (System.Security.Principal.IdentityNotMappedException)
{
to_add["File Owner"] = sid.ToString();
}
} }
else if (typeName == "key") else if (typeName == "key")