Repository restructuring

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

View File

@@ -1,12 +0,0 @@
import os
import sys
__doc__ = __doc__ or ""
__all__ = [
"util", "fileserver", "xss_handler", "rev_shell",
"xp_cmdshell", "dnsserver", "sqli", "smtpserver",
"upload_file", "pcap_file_extract"
]
inc_dir = os.path.dirname(os.path.realpath(__file__))
sys.path.append(inc_dir)

View File

View File

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -125,6 +125,7 @@ TIP_DOCKER_ROOTLESS="In rootless mode privilege escalation to root will not be p
TIP_CVE_2019_5021="Alpine linux version 3.3.x-3.5.x accidentally allow users to login as root with a blank password, if we have command execution in the container we can become root using su root"
TIP_CVE_2019_13139="Docker versions before 18.09.4 are vulnerable to a command execution vulnerability when parsing URLs"
TIP_CVE_2019_5736="Docker versions before 18.09.2 are vulnerable to a container escape by overwriting the runC binary"
TIP_CVE_2025_9074="Docker Desktop versions between 4.25 to 4.44.2 on Windows and MacOS are vulnerable to a container escape via a malicious image. See https://github.com/PtechAmanja/CVE-2025-9074-Docker-Desktop-Container-Escape"
TIP_SYS_MODULE="Giving the container the SYS_MODULE privilege allows for kernel modules to be mounted. Using this, a malicious module can be used to execute code as root on the host."
@@ -378,7 +379,7 @@ userCheck() {
groups=$(groups| sed "s/\($DANGEROUS_GROUPS\)/${LG}${EX}&${NC}${DG}/g")
printStatus "$groups" "None"
if ! [ $isUserRoot ]; then
if ! [ "$isUserRoot" ]; then
printQuestion "Sudo ...................."
if [ -x "$(command -v sudo)" ]; then
if sudo -n -l 2>/dev/null; then
@@ -631,7 +632,7 @@ containerPrivileges() {
fi
}
containerExploits() {
containerExploitAlpine() {
# If we are on an alpine linux disto check for CVE20195021
if [ -f "/etc/alpine-release" ]; then
alpineVersion=$(cat /etc/alpine-release)
@@ -648,6 +649,62 @@ containerExploits() {
fi
}
containerExploitAPI() {
# Check if docker api is exposed (including CVE-2025-9074)
api_available="0"
api_host=""
api_hosts="192.168.65.7:2375 172.17.0.1:2375"
printQuestion "Docker API exposed ......"
if [ -x "$(command -v curl)" ] || [ -x "$(command -v wget)" ]; then
for host in $api_hosts; do
if [ -x "$(command -v curl)" ]; then
if curl -s --connect-timeout 1 "http://$host/version" >/dev/null 2>&1; then
api_available="1"
api_host="$host"
break
fi
else
if wget -O - "http://$host/version" --connect-timeout=1 --tries=1 -q >/dev/null 2>&1; then
api_available="1"
api_host="$host"
break
fi
fi
done
if [ "$api_available" = "0" ]; then
printNo
return
fi
printSuccess "Yes ($api_host)"
printQuestion "└── CVE-2025-9074 ......."
if [ -x "$(command -v curl)" ]; then
if curl -s --connect-timeout 1 "http://$api_host/containers/json" >/dev/null 2>&1; then
printYesEx
printTip "$TIP_CVE_2025_9074"
else
printNo
fi
elif wget -O - "http://$api_host/containers/json" --connect-timeout=1 --tries=1 -q >/dev/null 2>&1; then
printYesEx
printTip "$TIP_CVE_2025_9074"
else
printNo
fi
else
printError "Unknown (curl/wget not installed)"
fi
}
containerExploits() {
containerExploitAlpine
containerExploitAPI
}
enumerateContainers() {
printSection "Enumerating Containers"

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,7 +1,7 @@
#!/bin/bash
#
# Copyright (c) 2016-2023, https://github.com/mzet-
# Copyright (c) 2016-2026, https://github.com/mzet-
#
# linux-exploit-suggester.sh comes with ABSOLUTELY NO WARRANTY.
# This is free software, and you are welcome to redistribute it
@@ -9,7 +9,7 @@
# file for usage of this software.
#
VERSION=v1.1
VERSION=v1.2
# bash colors
#txtred="\e[0;31m"
@@ -852,6 +852,18 @@ author: wbowling (orginal exploit author); bcoles (author of exploit update at '
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2018-14634]${txtrst} Mutagen Astronomy
Reqs: pkg=linux-kernel,x86_64,ver>=4.14.1,ver<=4.14.54
Tags: debian=8,RHEL=6|7
Rank: 1
analysis-url: https://www.qualys.com/2018/09/25/cve-2018-14634/mutagen-astronomy-integer-overflow-linux-create_elf_tables-cve-2018-14634.txt
exploit-db: 45516
Comments: systems with less than 32GB of RAM are unlikely to be affected by this issue
author: Qualys
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2018-18955]${txtrst} subuid_shell
Reqs: pkg=linux-kernel,ver>=4.15,ver<=4.19.2,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1,cmd:[ -u /usr/bin/newuidmap ],cmd:[ -u /usr/bin/newgidmap ]
@@ -916,6 +928,18 @@ author: chompie1337
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2021-3493]${txtrst} Ubuntu OverlayFS
Reqs: pkg=linux-kernel,ver>=3.13,ver<5.14,x86_64
Tags: ubuntu=(14.04|16.04|18.04|20.04|20.10)
Rank: 1
analysis-url: https://ssd-disclosure.com/ssd-advisory-overlayfs-pe/
src-url: https://raw.githubusercontent.com/briskets/CVE-2021-3493/refs/heads/main/exploit.c
Comments: Only Ubuntu is affected.
author: ssd-disclosure
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2021-22555]${txtrst} Netfilter heap out-of-bounds write
Reqs: pkg=linux-kernel,ver>=2.6.19,ver<=5.12-rc6
@@ -937,11 +961,25 @@ Tags: ubuntu=(20.04|21.04),debian=11
Rank: 1
analysis-url: https://dirtypipe.cm4all.com/
src-url: https://haxx.in/files/dirtypipez.c
bof-url: https://raw.githubusercontent.com/The-Z-Labs/bof-launcher/refs/heads/main/bofs/src/dirtypipe.zig
Comments: BOF version o the exploit available to be run with bof-launcher.
exploit-db: 50808
author: blasty (original exploit author: Max Kellermann)
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2022-0995]${txtrst} watch_queue
Reqs: pkg=linux-kernel,ver>=5.8,ver<5.16.5,x86_64
Tags: ubuntu=21.10{kernel:5.13.0.37-generic}
Rank: 1
analysis-url: https://github.com/Bonfee/CVE-2022-0995
src-url: https://github.com/Bonfee/CVE-2022-0995/archive/refs/heads/main.zip
Comments: Not 100% reliable, may need to be run a couple of times. It rare cases it may panic the kernel.
author: Bonfee (vulnerability discovery and PoC: Jann Horn)
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2022-2586]${txtrst} nft_object UAF
Reqs: pkg=linux-kernel,ver>=3.16,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1
@@ -967,6 +1005,30 @@ author: vulnerability discovery: EDG Team from NCC Group; Author of this exploit
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2023-0386]${txtrst} OverlayFS suid smuggle
Reqs: pkg=linux-kernel,ver>=5.11,ver<=6.2,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1
Tags: ubuntu=22.04.1{kernel:5.15.0-57-generic}
Rank: 1
analysis-url: https://securitylabs.datadoghq.com/articles/overlayfs-cve-2023-0386/
src-url: https://github.com/xkaneiki/CVE-2023-0386/archive/refs/heads/main.zip
Comments: CONFIG_USER_NS needs to be enabled && kernel.unprivileged_userns_clone=1 required
author: vuln discovery: Miklos Szeredi; exploit author: xkaneiki
EOF
)
EXPLOITS[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2024-1086]${txtrst} double-free in nf_tables
Reqs: pkg=linux-kernel,x86_64,ver>=5.14,ver<=6.6,CONFIG_NF_TABLES=y,CONFIG_USER_NS=y,sysctl:kernel.unprivileged_userns_clone==1
Tags: debian=12,ubuntu=22.04
Rank: 1
analysis-url: https://pwning.tech/nftables/
src-url: https://github.com/Notselwyn/CVE-2024-1086/archive/refs/heads/main.zip
Comments: CONFIG_USER_NS and CONFIG_NF_TABLES need to be enabled && kernel.unprivileged_userns_clone=1 required
author: notselwyn
EOF
)
############ USERSPACE EXPLOITS ###########################
n=0
@@ -1539,6 +1601,17 @@ author: berdav
EOF
)
EXPLOITS_USERSPACE[((n++))]=$(cat <<EOF
Name: ${txtgrn}[CVE-2025-32463]${txtrst} sudo-chwoot
Reqs: pkg=sudo,ver>=1.9.14,ver<=1.9.17
Tags: ubuntu=24.04.1,fedora=41
Rank: 1
analysis-url: https://www.stratascale.com/resource/cve-2025-32463-sudo-chroot-elevation-of-privilege/
src-url: https://github.com/mirchr/CVE-2025-32463-sudo-chwoot/archive/refs/heads/main.zip
author: Rich Mirch
EOF
)
###########################################################
## security related HW/kernel features
###########################################################
@@ -1828,11 +1901,11 @@ EOF
version() {
echo "linux-exploit-suggester "$VERSION", mzet, https://z-labs.eu, March 2019"
echo "linux-exploit-suggester $VERSION by mzet"
}
usage() {
echo "LES ver. $VERSION (https://github.com/mzet-/linux-exploit-suggester) by @_mzet_"
echo "LES ver. $VERSION (https://github.com/mzet-/linux-exploit-suggester) by mzet"
echo
echo "Usage: linux-exploit-suggester.sh [OPTIONS]"
echo
@@ -2626,6 +2699,7 @@ for EXP_TEMP in "${SORTED_EXPLOITS[@]}"; do
EXPLOIT_DB=$(echo "$EXP" | grep "exploit-db: " | awk '{print $2}')
analysis_url=$(echo "$EXP" | grep "analysis-url: " | awk '{print $2}')
ext_url=$(echo "$EXP" | grep "ext-url: " | awk '{print $2}')
bof_url=$(echo "$EXP" | grep "bof-url: " | awk '{print $2}')
comments=$(echo "$EXP" | grep "Comments: " | cut -d' ' -f 2-)
reqs=$(echo "$EXP" | grep "Reqs: " | cut -d' ' -f 2)
@@ -2679,6 +2753,7 @@ for EXP_TEMP in "${SORTED_EXPLOITS[@]}"; do
[ -n "$tags" ] && echo -e " Tags: $tags"
echo -e " Download URL: $src_url"
[ -n "$ext_url" ] && echo -e " ext-url: $ext_url"
[ -n "$bof_url" ] && echo -e " bof-url: $bof_url"
[ -n "$comments" ] && echo -e " Comments: $comments"
# handles --full filter option

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@@ -58,6 +58,8 @@ CALL :ColorLine " %E%41mWinPEAS should be used for authorized penetration test
CALL :ColorLine " %E%41mAny misuse of this software will not be the responsibility of the author or of any other collaborator.%E%40;97m"
CALL :ColorLine " %E%41mUse it at your own networks and/or with the network owner's permission.%E%40;97m"
ECHO.
ECHO. [i] Best Linux PE and hardening course: https://hacktricks-training.com/courses/lhe/
ECHO.
:SystemInfo
CALL :ColorLine "%E%32m[*]%E%97m BASIC SYSTEM INFO"
@@ -71,7 +73,7 @@ CALL :T_Progress 2
:ListHotFixes
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic qfe get Caption,Description,HotFixID,InstalledOn | more
wmic qfe get Caption,Description,HotFixID,InstalledOn
) else (
powershell -command "Get-HotFix | Format-Table -AutoSize"
)
@@ -204,7 +206,7 @@ CALL :T_Progress 1
CALL :ColorLine " %E%33m[+]%E%97m Registered Anti-Virus(AV)"
where wmic >nul 2>&1
if %errorlevel% equ 0 (
WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List | more
WMIC /Node:localhost /Namespace:\\root\SecurityCenter2 Path AntiVirusProduct Get displayName /Format:List
) else (
powershell -command "Get-CimInstance -Namespace root/SecurityCenter2 -ClassName AntiVirusProduct | Select-Object -ExpandProperty displayName"
)
@@ -238,7 +240,7 @@ CALL :ColorLine " %E%33m[+]%E%97m MOUNTED DISKS"
ECHO. [i] Maybe you find something interesting
where wmic >nul 2>&1
if %errorlevel% equ 0 (
wmic logicaldisk get caption | more
wmic logicaldisk get caption
) else (
fsutil fsinfo drives
)
@@ -405,7 +407,7 @@ CALL :T_Progress 1
:BasicUserInfo
CALL :ColorLine "%E%32m[*]%E%97m BASIC USER INFO
ECHO. [i] Check if you are inside the Administrators group or if you have enabled any token that can be use to escalate privileges like SeImpersonatePrivilege, SeAssignPrimaryPrivilege, SeTcbPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeCreateTokenPrivilege, SeLoadDriverPrivilege, SeTakeOwnershipPrivilege, SeDebbugPrivilege
ECHO. [i] Check if you are inside the Administrators group or if you have enabled any token that can be use to escalate privileges like SeImpersonatePrivilege, SeAssignPrimaryPrivilege, SeTcbPrivilege, SeBackupPrivilege, SeRestorePrivilege, SeCreateTokenPrivilege, SeLoadDriverPrivilege, SeTakeOwnershipPrivilege, SeDebugPrivilege
ECHO. [?] https://book.hacktricks.wiki/en/windows-hardening/windows-local-privilege-escalation/index.html#users--groups
ECHO.
CALL :ColorLine " %E%33m[+]%E%97m CURRENT USER"
@@ -670,7 +672,7 @@ if "%long%" == "true" (
ECHO.
where wmic >nul 2>&1
if !errorlevel! equ 0 (
for /f %%x in ('wmic logicaldisk get name ^| more') do (
for /f %%x in ('wmic logicaldisk get name') do (
set tdrive=%%x
if "!tdrive:~1,2!" == ":" (
%%x

View File

Binary file not shown.

View File

Binary file not shown.

0
win/PetitPotam.py → tools/exploits/PetitPotam.py Normal file → Executable file
View File

View File

@@ -5,8 +5,6 @@ import os
import re
import sys
import pty
import util
import upload_file
import time
import random
import threading
@@ -16,6 +14,9 @@ import select
import argparse
import signal
from hackingscripts.utils import util
from hackingscripts.tools.misc import upload_file
try:
import SocketServer
except ImportError:

View File

118
tools/misc/tcp_template.py Normal file
View File

@@ -0,0 +1,118 @@
#!/usr/bin/env python
import re
import sys
import json
import argparse
import urllib.parse
def generate_template(listen_address, listen_port, remote_host, remote_port):
# we could all need that
imports = [
"os",
"socket",
"threading"
]
partial_imports = {
"hackingscripts.utils": ["util"],
"hackingscripts.utils.packeter": ["Packer", "Parser"]
}
imports = "\n".join(f"import {i}" for i in sorted(imports, key=len))
imports += "\n" + "\n".join(sorted(list(f"from {p} import {', '.join(i)}" for p, i in partial_imports.items()), key=len))
return f"""#!/usr/bin/env python
#
# THE BASE OF THIS FILE WAS AUTOMATICALLY GENERATED BY {' '.join(sys.argv)}
# For more information, visit: https://git.romanh.de/Roman/HackingScripts
#
{imports}
BUFFER_SIZE = 4096
class Packet:
def __init__(self):
pass
@staticmethod
def from_data(data):
packet = Packet()
parser = Parser(data)
# TODO: auto-generated method stub
return packet
def pack(self):
buf = Packer()
# TODO: auto-generated method stub
return buf.get()
def forward(source, destination):
try:
while True:
data = source.recv(BUFFER_SIZE)
if not data:
break
# TODO: Parse / Manipulate packet
# packet = Packet.from_data(data)
# repacked = packet.pack()
destination.sendall(data)
except Exception:
pass
finally:
source.close()
destination.close()
def handle_client(client_socket, remote_host, remote_port):
try:
remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
remote_socket.connect((remote_host, remote_port))
except Exception as e:
print(f"Failed to connect to remote: {{e}}")
client_socket.close()
return
# Start bidirectional forwarding
threading.Thread(target=forward, args=(client_socket, remote_socket), daemon=True).start()
threading.Thread(target=forward, args=(remote_socket, client_socket), daemon=True).start()
def start_proxy(local_host, local_port, remote_host, remote_port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind((local_host, local_port))
server.listen(100)
print(f"[*] Forwarding from {{local_host}}:{{local_port}} to {{remote_host}}:{{remote_port}}")
while True:
client_socket, addr = server.accept()
print(f"[+] Connection from {{addr[0]}}:{{addr[1]}}")
threading.Thread(
target=handle_client,
args=(client_socket, remote_host, remote_port),
daemon=True
).start()
if __name__ == "__main__":
start_proxy({repr(listen_address)}, {listen_port}, {repr(remote_host)}, {remote_port})
"""
if __name__ == "__main__":
parser = argparse.ArgumentParser(
description="Exploit Template for tcp application attacks",
formatter_class=argparse.RawTextHelpFormatter
)
parser.add_argument("la", type=str, help="Listen Address")
parser.add_argument("lp", type=int, help="Listen Port", choices=range(1,65535+1))
parser.add_argument("rh", type=str, help="Remote Host")
parser.add_argument("rp", type=int, help="Remote Port", choices=range(1,65535+1))
args = parser.parse_args()
template = generate_template(args.la, args.lp, args.rh, args.rp)
print(template)

View File

@@ -2,9 +2,10 @@
import sys
import os
import util
import argparse
from hackingscripts.utils import util
def serve_file(listen_sock, path, forever=False):
try:
while True:

View File

@@ -17,7 +17,8 @@ def generate_template(base_url, features):
partial_imports = {
"bs4": ["BeautifulSoup"],
"hackingscripts": ["util", "rev_shell"],
"hackingscripts.utils": ["util"],
"hackingscripts.tools.exploits": ["rev_shell"],
"urllib3.exceptions": ["InsecureRequestWarning"]
}

View File

0
dnsserver.py → tools/server/dnsserver.py Normal file → Executable file
View File

0
ftpserver.py → tools/server/ftpserver.py Normal file → Executable file
View File

0
smtpserver.py → tools/server/smtpserver.py Normal file → Executable file
View File

0
sshserver.py → tools/server/sshserver.py Normal file → Executable file
View File

View File

@@ -1,14 +1,15 @@
#!/usr/bin/env python
import argparse
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse
import threading
import requests
import time
import os
import ssl
import util
from http.server import BaseHTTPRequestHandler, HTTPServer
from urllib.parse import urlparse
from hackingscripts.utils import util
from hackingscripts.tools.server.xss_handler import generate_payload as generate_xss_payload
class FileServerRequestHandler(BaseHTTPRequestHandler):
@@ -357,7 +358,6 @@ if __name__ == "__main__":
file_server.forwardRequest("/proxy", url)
print("Exfiltrate data using:", file_server.get_full_url("/proxy", ip_address))
elif args.action == "xss":
from xss_handler import generate_payload as generate_xss_payload
payload_type = args.payload if args.payload else "img"
xss = generate_xss_payload(payload_type, file_server.get_full_url("/exfiltrate", ip_address))
file_server.addFile("/xss", xss)

View File

@@ -39,26 +39,25 @@ get_latest_version () {
}
echo "Updating scripts…"
download https://raw.githubusercontent.com/initstring/uptux/master/uptux.py uptux.py
download https://raw.githubusercontent.com/pentestmonkey/unix-privesc-check/master/upc.sh unix-privesc-check.sh
download https://github.com/DominicBreuker/pspy/releases/latest/download/pspy64 pspy64
download https://github.com/DominicBreuker/pspy/releases/latest/download/pspy32 pspy
download https://raw.githubusercontent.com/flozz/p0wny-shell/master/shell.php p0wny-shell.php
download https://raw.githubusercontent.com/diego-treitos/linux-smart-enumeration/master/lse.sh lse.sh
download https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh linux-exploit-suggester.sh
download https://github.com/rebootuser/LinEnum/raw/master/LinEnum.sh LinEnum.sh
download https://github.com/stealthcopter/deepce/raw/main/deepce.sh deepce.sh
download https://raw.githubusercontent.com/topotam/PetitPotam/main/PetitPotam.py PetitPotam.py
download https://raw.githubusercontent.com/initstring/uptux/master/uptux.py payloads/linux/uptux.py
download https://raw.githubusercontent.com/pentestmonkey/unix-privesc-check/master/upc.sh payloads/linux/unix-privesc-check.sh
download https://github.com/DominicBreuker/pspy/releases/latest/download/pspy64 payloads/linux/pspy64
download https://github.com/DominicBreuker/pspy/releases/latest/download/pspy32 payloads/linux/pspy
download https://raw.githubusercontent.com/flozz/p0wny-shell/master/shell.php payloads/web/p0wny-shell.php
download https://raw.githubusercontent.com/diego-treitos/linux-smart-enumeration/master/lse.sh payloads/linux/lse.sh
download https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh payloads/linux/linux-exploit-suggester.sh
download https://github.com/rebootuser/LinEnum/raw/master/LinEnum.sh payloads/linux/LinEnum.sh
download https://github.com/stealthcopter/deepce/raw/main/deepce.sh payloads/linux/deepce.sh
echo ""
echo "Updating LinPEAS + WinPEAS…"
peas_version=$(get_latest_version peass-ng/PEASS-ng)
if [ ! -z "$peas_version" ]; then
echo "Got PEAS version: $peas_version"
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/linpeas.sh linpeas.sh
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/winPEASx86.exe win/winPEAS.exe
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/winPEASx64.exe win/winPEASx64.exe
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/winPEAS.bat win/winPEAS.bat
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/linpeas.sh payloads/linux/linpeas.sh
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/winPEASx86.exe payloads/windows/winPEAS.exe
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/winPEASx64.exe payloads/windows/winPEASx64.exe
download https://github.com/peass-ng/PEASS-ng/releases/download/$peas_version/winPEAS.bat payloads/windows/winPEAS.bat
else
echo "Unable to determine latest PEAS version"
fi
@@ -66,24 +65,24 @@ fi
# TODO: add others
echo ""
echo "Updating windows tools…"
download https://live.sysinternals.com/accesschk.exe win/accesschk.exe
download https://live.sysinternals.com/accesschk64.exe win/accesschk64.exe
download https://github.com/int0x33/nc.exe/raw/master/nc.exe win/nc.exe
download https://github.com/int0x33/nc.exe/raw/master/nc64.exe win/nc64.exe
download https://github.com/k4sth4/Juicy-Potato/raw/main/x86/jp32.exe win/JuicyPotato.exe
download https://github.com/k4sth4/Juicy-Potato/raw/main/x64/jp.exe win/JuicyPotato64.exe
download https://github.com/uknowsec/SweetPotato/raw/master/SweetPotato-Webshell-new/bin/Release/SweetPotato.exe win/SweetPotato.exe
download https://github.com/BeichenDream/GodPotato/releases/latest/download/GodPotato-NET4.exe win/GodPotato.exe
download https://raw.githubusercontent.com/topotam/PetitPotam/main/PetitPotam.py win/PetitPotam.py
download https://live.sysinternals.com/accesschk.exe payloads/windows/accesschk.exe
download https://live.sysinternals.com/accesschk64.exe payloads/windows/accesschk64.exe
download https://github.com/int0x33/nc.exe/raw/master/nc.exe payloads/windows/nc.exe
download https://github.com/int0x33/nc.exe/raw/master/nc64.exe payloads/windows/nc64.exe
download https://github.com/k4sth4/Juicy-Potato/raw/main/x86/jp32.exe payloads/windows/JuicyPotato.exe
download https://github.com/k4sth4/Juicy-Potato/raw/main/x64/jp.exe payloads/windows/JuicyPotato64.exe
download https://github.com/uknowsec/SweetPotato/raw/master/SweetPotato-Webshell-new/bin/Release/SweetPotato.exe payloads/windows/SweetPotato.exe
download https://github.com/BeichenDream/GodPotato/releases/latest/download/GodPotato-NET4.exe payloads/windows/GodPotato.exe
download https://raw.githubusercontent.com/topotam/PetitPotam/main/PetitPotam.py tools/exploits/PetitPotam.py
echo ""
chisel_version=$(get_latest_version jpillora/chisel v)
if [ ! -z "$chisel_version" ]; then
echo "Got Chisel version: $chisel_version"
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_linux_386.gz" | gzip -d > chisel
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_linux_amd64.gz" | gzip -d > chisel64
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_windows_386.gz" | gzip -d > win/chisel.exe
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_windows_amd64.gz" | gzip -d > win/chisel64.exe
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_linux_386.gz" | gzip -d > payloads/linux/chisel
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_linux_amd64.gz" | gzip -d > payloads/linux/chisel64
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_windows_386.gz" | gzip -d > payloads/windows/chisel.exe
curl -s -L "https://github.com/jpillora/chisel/releases/download/v${chisel_version}/chisel_${chisel_version}_windows_amd64.gz" | gzip -d > payloads/windows/chisel64.exe
else
echo "Unable to determine latest chisel version"
fi
@@ -91,14 +90,14 @@ fi
sharphound_version=$(get_latest_version BloodHoundAD/SharpHound v)
if [ ! -z "$sharphound_version" ]; then
echo "Got Sharphound version: $sharphound_version"
download_zip https://github.com/BloodHoundAD/SharpHound/releases/download/v${sharphound_version}/SharpHound-v${sharphound_version}.zip win/ SharpHound.exe SharpHound.ps1
download_zip https://github.com/BloodHoundAD/SharpHound/releases/download/v${sharphound_version}/SharpHound-v${sharphound_version}.zip payloads/windows/ SharpHound.exe SharpHound.ps1
fi
socat_version=$(get_latest_version "3ndG4me/socat" v)
if [ ! -z "$socat_version" ]; then
echo "Got socat version: $socat_version"
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx86.bin socat
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx64.bin socat64
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx86.exe win/socat.exe
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx64.exe win/socat64.exe
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx86.bin payloads/linux/socat
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx64.bin payloads/linux/socat64
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx86.exe payloads/windows/socat.exe
download https://github.com/3ndG4me/socat/releases/download/v${socat_version}/socatx64.exe payloads/windows/socat64.exe
fi

0
utils/__init__.py Normal file
View File

View File

133
utils/packeter.py Normal file
View File

@@ -0,0 +1,133 @@
import struct
class StructWrapper:
@staticmethod
def _endian(e):
return ">" if e else "<"
@staticmethod
def _format_size(f):
format_sizes = {
"c": 1,
"h": 2, "H": 2,
"i": 4, "I": 4,
"q": 8, "Q": 8,
}
assert f in format_sizes
return format_sizes[f]
class Parser(StructWrapper):
def __init__(self, data, big_endian=False):
self.data = data
self.offset = 0
self.big_endian = big_endian
def eof(self):
return self.offset >= len(self.data)
def remaining_size(self):
return len(self.data[self.offset:])
def _struct_unpack(self, big_endian, f):
size = self._format_size(f)
assert self.remaining_size() >= size
# grab default endianess, when none is given
if big_endian is None:
big_endian = self.big_endian
value = struct.unpack(self._endian(big_endian) + f, self.data[self.offset:self.offset+size])[0]
self.offset += size
return value
def read_byte(self):
return self._struct_unpack(big_endian, "c")
def read_char(self):
return chr(self.read_byte())
def read_signed_short(self, big_endian=None):
return self._struct_unpack(big_endian, "h")
def read_unsigned_short(self, big_endian=None):
return self._struct_unpack(big_endian, "H")
def read_signed_int(self, big_endian=None):
return self._struct_unpack(big_endian, "i")
def read_unsigned_int(self, big_endian=None):
return self._struct_unpack(big_endian, "I")
def read_signed_long(self, big_endian=None):
return self._struct_unpack(big_endian, "q")
def read_unsigned_long(self, big_endian=None):
return self._struct_unpack(big_endian, "Q")
def read_bin(self, length):
d = self.data[self.offset:self.offset+length]
assert len(self.data[self.offset:]) >= length
self.offset += length
return d
def read_until(self, byte):
data = b""
while not self.eof():
c = self.read_byte()
if c == byte:
break
data += c
return data
class Packer(StructWrapper):
def __init__(self, big_endian=False):
self.buffer = b""
self.offset = 0
self.big_endian = big_endian
def get(self):
return self.buffer
def length(self):
return len(self.buffer)
def _struct_pack(self, big_endian, f, value):
# grab default endianess, when none is given
if big_endian is None:
big_endian = self.big_endian
size = self._format_size(f)
self.buffer += struct.pack(self._endian(big_endian) + f, value)
self.offset += size
def write_byte(self, value):
self._struct_pack(big_endian, "c", value)
def write_char(self, value):
self._struct_pack(big_endian, "c", value.encode())
def write_signed_short(self, value, big_endian=None):
self._struct_pack(big_endian, "c", value)
def write_unsigned_short(self, value, big_endian=None):
self._struct_pack(big_endian, "H", value)
def write_signed_int(self, value, big_endian=None):
self._struct_unpack(big_endian, "i", value)
def write_unsigned_int(self, value, big_endian=None):
self._struct_unpack(big_endian, "I", value)
def write_signed_long(self, value, big_endian=None):
self._struct_unpack(big_endian, "q", value)
def rwrite_unsigned_long(self, value, big_endian=None):
self._struct_unpack(big_endian, "Q", value)
def write_bin(self, value):
self.buffer += value
self.offset += len(value)
def write_string(self, value, encoding="UTF-8"):
self.write_bin(value.encode(encoding))

View File

View File

@@ -14,6 +14,18 @@ import re
import json
import urllib.parse
def hex_dump(data, column_size=16):
printables = (string.ascii_letters + string.digits + string.punctuation).encode()
for i in range(0, len(data), column_size):
row = data[i:i+column_size]
as_string = "".join("." if bytes([b]) not in printables else chr(b) for b in row)
as_hex = " ".join("%02x" % b for b in row)
if len(row) < column_size:
as_hex += " " * 3 * (column_size - len(row))
print("%08x" % (i * column_size), "|", as_hex, "|", as_string)
def is_port_in_use(port):
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
@@ -158,12 +170,11 @@ def assert_regex_match(pattern, data, err=None):
err = f"[-] Data does not match pattern '{pattern}': '{data}'" if err is None else err
exit_with_error(None, err)
def open_server(address, ports=None, retry=True):
def open_server(address, ports=None, retry=False):
listen_port = None
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
while retry:
while True:
if isinstance(ports, int):
listen_port = ports
retry = False
@@ -173,12 +184,15 @@ def open_server(address, ports=None, retry=True):
listen_port = random.randint(10000,65535)
try:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((address, listen_port))
sock.listen(1)
return sock
except Exception as e:
if not retry:
print("[-] Unable to listen on port %d: %s" % (listenPort, str(e)))
if retry:
print("[-] Unable to listen on port %d: %s, Retrying…" % (listen_port, str(e)))
time.sleep(1.0)
else:
raise e
class Stack:

View File

@@ -1,273 +0,0 @@
#!/usr/bin/env python
import re
import sys
import json
import argparse
import requests
import urllib.parse
import util
from bs4 import BeautifulSoup
from crawl_urls import Crawler
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
class WebServiceFinder:
def __init__(self, args):
self.parseUrl(args.url)
self.parseCookies(args.cookie)
self.headers = { }
self.session = requests.Session()
self.verbose = args.verbose
if args.user_agent:
self.headers["User-Agent"] = args.user_agent
def parseUrl(self, url):
parts = urllib.parse.urlparse(url)
if parts.scheme == '':
self.url = "http://" + url
self.scheme = "http"
elif parts.scheme not in ["http","https"]:
print("[-] Unsupported URL scheme:", parts.scheme)
exit(1)
else:
self.url = url
self.scheme = parts.scheme
def resolve(self, uri):
if uri is None or uri.strip() == "":
return self.url
elif urllib.parse.urlparse(uri).scheme != "":
return uri
target = self.url
if not target.endswith("/"):
target += "/"
if uri.startswith("/"):
uri = uri[1:]
return target + uri
def do_get(self, uri, **args):
uri = self.resolve(uri)
if self.verbose:
sys.stdout.write("GET %s: " % uri)
res = self.session.get(uri, headers=self.headers, cookies=self.cookies, verify=False, **args)
if self.verbose:
sys.stdout.write("%d %s\n" % (res.status_code, res.reason))
return res
def parseCookies(self, cookie_list):
self.cookies = { }
if cookie_list:
for cookie in cookie_list:
cookie = cookie.strip()
if "=" in cookie:
index = cookie.find("=")
key, val = cookie[0:index], cookie[index+1:]
self.cookies[key] = val
else:
self.cookies[cookie] = ""
def scan(self):
print("[ ] Retrieving:", self.url)
uri = "/"
while True:
startPage = self.do_get(uri, allow_redirects=False)
if startPage.status_code in [301, 302, 397, 308]:
uri = startPage.headers["Location"]
if urllib.parse.urlparse(uri).scheme == "https" and self.scheme == "http":
self.url = self.url.replace("http","https",1)
self.scheme = "https"
print("[+] Server redirecting to:", uri)
else:
break
self.analyseHeaders(startPage)
if "text/html" in startPage.headers["Content-Type"]:
self.analyseHtml(startPage)
elif "text/xml" in startPage.headers["Content-Type"]:
self.analyseXml(startPage)
self.analyseRobots()
self.analyseSitemap()
self.analyseChangelog()
self.checkJoomlaVersion()
self.checkManifest()
def checkManifest(self):
url = "/static/manifest.json"
res = self.do_get(url)
if res.status_code == 200:
try:
manifest = json.loads(res.text)
if "name" in manifest:
print("[+] Found manifest name:", manifest["name"])
except:
pass
def checkJoomlaVersion(self):
url = "/administrator/manifests/files/joomla.xml"
res = self.do_get(url)
if res.status_code == 200:
soup = BeautifulSoup(res.text, "lxml")
extension = soup.find("extension")
if extension and extension.has_attr("version"):
print("[+] Found Joomla version:", extension["version"])
def analyseHeaders(self, res):
phpFound = False
banner_headers = ["Server", "X-Powered-By", "X-Runtime", "X-Version"]
for banner in banner_headers:
if banner in res.headers:
phpFound = phpFound or ("PHP" in res.headers[banner])
print("[+] %s Header: %s" % (banner, res.headers[banner]))
if not phpFound and "PHPSESSID" in self.session.cookies:
print("[+] PHP detected, unknown version")
def printMatch(self, title, match, group=1, version_func=str):
if match:
version = "Unknown version" if group is None or len(match.groups()) <= group else version_func(match.group(group))
print("[+] Found %s: %s" % (title, version))
return True
return False
def retrieveMoodleVersion(self, v):
res = requests.get("https://docs.moodle.org/dev/Releases")
soup = BeautifulSoup(res.text, "html.parser")
versionStr = "Unknown"
for tr in soup.find_all("tr"):
tds = tr.find_all("td")
th = tr.find("th")
if len(tds) == 4 and th and int(tds[1].text.strip()) == v:
versionStr = th.text.strip()
if versionStr.startswith("Moodle "):
versionStr = versionStr[len("Moodle"):].strip()
break
return "%s (%d)" % (versionStr, v)
def analyseXml(self,res):
soup = BeautifulSoup(res.text, "lxml")
title = soup.find("title")
if title:
print("[+] Found XML title:", title.text.strip())
generator = soup.find("generator")
if generator:
if generator.has_attr("version"):
print("[+] Found XML Generator version:", generator["version"])
def analyseHtml(self, res):
soup = BeautifulSoup(res.text, "html.parser")
meta_generator = soup.find("meta", {"name":"generator"})
if meta_generator:
banner = meta_generator["content"].strip()
print("[+] Meta Generator:", banner)
body = soup.find("body")
if body:
gitea_pattern = re.compile(r"Gitea Version: ([0-9\.]*)")
self.printMatch("Gitea", gitea_pattern.search(body.text))
footer = soup.find("footer")
if footer:
content = footer.text.strip()
gogs_pattern = re.compile(r"(^|\s)Gogs Version: ([a-zA-Z0-9.-]+)($|\s)")
go_pattern = re.compile(r"(^|\s)Go([0-9.]+)($|\s+)")
self.printMatch("Gogs", gogs_pattern.search(content), 2)
self.printMatch("Go", go_pattern.search(content), 2)
versionInfo = soup.find("div", {"class": "versionInfo"})
if versionInfo:
content = versionInfo.text.strip()
cacti_pattern = re.compile(r"Version ([0-9.]*) .* The Cacti Group")
self.printMatch("Cacti", cacti_pattern.search(content), 1)
poweredBy = soup.find(id="poweredBy")
if poweredBy:
content = poweredBy.text.strip()
osticket_pattern = re.compile(r"powered by osTicket")
self.printMatch("OsTicket", osticket_pattern.search(content))
moodle_pattern_1 = re.compile(r"^https://download.moodle.org/mobile\?version=(\d+)(&|$)")
moodle_pattern_2 = re.compile(r"^https://docs.moodle.org/(\d+)/")
litecart_pattern = re.compile(r"^https://www.litecart.net")
wordpress_pattern = re.compile(r"/wp-(admin|includes|content)/(([^/]+)/)*(wp-emoji-release.min.js|style.min.css)\?ver=([0-9.]+)(&|$)")
urls = Crawler(self.url).collect_urls(soup)
for url in urls:
self.printMatch("Moodle", moodle_pattern_1.search(url), version_func=lambda v: self.retrieveMoodleVersion(int(v)))
self.printMatch("Moodle", moodle_pattern_2.search(url), version_func=lambda v: "%d.%d" % (int(v)//10,int(v)%10))
self.printMatch("Litecart", litecart_pattern.search(url), group=None)
if self.printMatch("Wordpress", wordpress_pattern.search(url), group=5):
print("[ ] You should consider using 'wpscan' for further investigations and more accurate results")
def analyseRobots(self):
res = self.do_get("/robots.txt", allow_redirects=False)
if res.status_code != 200:
print("[-] robots.txt not found or inaccessible")
return False
def analyseSitemap(self):
res = self.do_get("/sitemap.xml", allow_redirects=False)
if res.status_code != 200:
print("[-] sitemap.xml not found or inaccessible")
return False
def analyseChangelog(self):
drupal_pattern = re.compile("^Drupal ([0-9.]+),")
drupal_found = False
changelog_files = ["CHANGELOG", "CHANGELOG.txt"]
for file in changelog_files:
res = self.do_get(file, allow_redirects=False)
if res.status_code != 200:
continue
print("[+] Found:", file)
for line in res.text.split("\n"):
line = line.strip()
if not drupal_found and self.printMatch("Drupal", drupal_pattern.search(line)):
drupal_found = True
def banner():
print("""
,--------. ,--. ,--------. ,--. ,--. ,--.
'--. .--',---. ,---.,-' '-.'--. .--',---. ,---. | | ,--. ,--. / | / \\
| | | .-. :( .-''-. .-' | | | .-. || .-. || | \ `' / `| | | () |
| | \ --..-' `) | | | | ' '-' '' '-' '| | \ / | |.--.\ /
`--' `----'`----' `--' `--' `---' `---' `--' `--' `--''--' `--'
""")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("url", help="The target URI to scan to, e.g. http://example.com:8080/dir/")
parser.add_argument("--proxy", help="Proxy to connect through") # TODO
parser.add_argument("--user-agent", help="User-Agent to use")
parser.add_argument("--cookie", help="Cookies to send", action='append')
parser.add_argument('--verbose', '-v', help="Verbose otuput", action='store_true')
args = parser.parse_args()
banner()
client = WebServiceFinder(args)
client.scan()