Created
December 9, 2024 19:31
-
-
Save qtc-de/c1e6950cce7cdc2281dbbc0160e7a0ec to your computer and use it in GitHub Desktop.
This script contains a python version of sccm-http-looter (https://github.com/badsectorlabs/sccm-http-looter)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# This script contains a python version of sccm-http-looter (https://github.com/badsectorlabs/sccm-http-looter) | |
# The following additional packages may need to be installed depending on the usage: | |
# | |
# pip install requests-ntlm (required for authenticated access to SCCM DPs) | |
# pip install requests[socks] (required for usage over socks proxy) | |
# | |
# The script attempts to obtain a package list via HTTP directory listing. However, when dealing | |
# with large package lists, this is not 100% reliable as the server may cut the amount of entries | |
# being returned. Once the package list was obtained, it is stored as `{host}-sccm-packages.txt`. | |
# Using the --packages option, you can also use an already obtained list. | |
import re | |
import time | |
import requests | |
import argparse | |
import urllib.parse | |
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 GLS/100.10.9939.100' | |
parser = argparse.ArgumentParser(description='sccm-http v1.0.0 - Loot SCCM DPs via HTTP') | |
parser.add_argument('url', help='url of the SCCM depot server') | |
parser.add_argument('--username', metavar='name', help='username for NTLM authentication') | |
parser.add_argument('--password', metavar='pw', help='password for NTLM authentication') | |
parser.add_argument('--domain', metavar='dom', help='domain for NTLM authentication') | |
parser.add_argument('--user-agent', metavar='ua', default=USER_AGENT, help='user agent to use (default: chrome)') | |
parser.add_argument('--proxy', metavar='proxy', help='proxy server to use') | |
parser.add_argument('--list-only', action='store_true', help='only obtain the package list') | |
parser.add_argument('--packages', metavar='file', type=argparse.FileType('r'), help='list of packages to check') | |
parser.add_argument('--delay', metavar='int', default=0, type=int, help='amount of time between each request in seconds (default: 0)') | |
def main(): | |
''' | |
Main method :) | |
''' | |
args = parser.parse_args() | |
session = requests.Session() | |
if args.proxy: | |
proxies = { | |
'http': args.proxy, | |
'https': args.proxy, | |
} | |
session.proxies.update(proxies) | |
if args.username or args.password or args.domain: | |
if not (args.username and args.password and args.domain): | |
print('[-] If credentials are used, all auth parameters need to be specified.') | |
return | |
from requests_ntlm import HttpNtlmAuth | |
session.auth = HttpNtlmAuth(f'{args.domain}\\{args.username}', args.password) | |
if not args.packages: | |
count = 0 | |
url = f'{args.url}/SMS_DP_SMSPKG$/DataLib' | |
hostname = urllib.parse.urlparse(url).netloc | |
print('[+] Obtaining package list...') | |
response = session.get(url) | |
regex = re.compile(f'{args.url}/?SMS_DP_SMSPKG\\$/DataLib/([^"<]+)"') | |
with open(f'{hostname}-sccm-packages.txt', 'w') as output: | |
for item in regex.finditer(response.text): | |
if item.group(1).endswith('.INI'): | |
continue | |
print(item.group(1), file=output) | |
count += 1 | |
print(f'[+] Obtained {count} package names.') | |
print(f'[+] Results have been written to {hostname}-sccm-packages.txt') | |
if args.list_only: | |
return | |
print(f'[+] Using {hostname}-sccm-packages.txt as input file.') | |
args.packages = open(f'{hostname}-sccm-packages.txt') | |
lines = args.packages.readlines() | |
for line in lines: | |
package = line.strip() | |
url = f'{args.url}/SMS_DP_SMSPKG$/{package}' | |
regex_pre = re.compile('^([^<]+ )<a') | |
regex_post = re.compile(f'{args.url}/?SMS_DP_SMSPKG\\$/{package}/([^"<]+)"') | |
print(f'[+] {package}') | |
response = session.get(url) | |
if response.status_code not in [200, 404]: | |
if response.status_code == 401: | |
print('[-] Unauthorized. Credentials required / incorrect ?') | |
return | |
else: | |
print('[-] Obtained unexpected HTTP {response.status_code} response.') | |
print(response.headers) | |
print(response.text) | |
return | |
else: | |
if response.status_code == 200: | |
found = False | |
items = response.text.split('<br>') | |
for item in items: | |
pre = regex_pre.search(item) | |
found = regex_post.search(item) | |
if pre: | |
preface = pre.group(1) | |
preface = preface.replace('<', ' ') | |
preface = preface.replace('>', '') | |
else: | |
preface = '\t' | |
if found: | |
print(f'[+] {preface}{found.group(1)}') | |
if not found: | |
print(response.text) | |
else: | |
print('[+] \tNot Found!') | |
time.sleep(args.delay) | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment