Skip to content

Instantly share code, notes, and snippets.

@two06
Created August 31, 2023 09:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save two06/237398c143120beb8139577bf0d27b91 to your computer and use it in GitHub Desktop.
Save two06/237398c143120beb8139577bf0d27b91 to your computer and use it in GitHub Desktop.
Python tool for interacting with Excel Python container (preview release)
#!/usr/bin/python3
import requests
import sys
import uuid
from requests.packages.urllib3.exceptions import InsecureRequestWarning
#Disable annoying warnings about using burp proxy.
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
http_proxy = "http://127.0.0.1:8080"
https_proxy = "http://127.0.0.1:8080"
proxies = {
"http" : http_proxy,
"https" : https_proxy
}
bearer_token = "Bearer <REDACTED>"
session_id = str(uuid.uuid4())
correlation_ID = str(uuid.uuid4())
headers = {
"Connection": "Keep-Alive",
"Content-Type": "application/json",
"Authorization": bearer_token,
"User-Agent": "Microsoft Office/16.0 (Windows NT 10.0; Microsoft Excel 16.0.16818; Pro)",
"SessionId": session_id,
"X-Correlation-ID": correlation_ID
}
headersFileSend = {
"Connection": "Keep-Alive",
"Authorization": bearer_token,
"User-Agent": "Microsoft Office/16.0 (Windows NT 10.0; Microsoft Excel 16.0.16818; Pro)",
"SessionId": session_id,
"X-Correlation-ID": correlation_ID
}
def send_initial_request():
url = "https://service-preview.officepy.microsoftusercontent.com/"
response = requests.post(url, headers=headers, proxies=proxies, verify=False)
if response.status_code == 201:
try:
jsonResponse = response.json()
return jsonResponse["url"]
except Exception as err:
print(f"[!] Exception occured: {err}")
return
else:
print("[!] Error status code: " + str(response.status_code) )
def send_stage_2_request(url):
json_data = {"zone":0,"zoneId":""+ str(uuid.uuid4()) +"","definitionId":"00000000-0000-0000-0000-000000000000","connectionId":""+str(uuid.uuid4())+""}
rUrl = url + "/api/environments"
response = requests.post(rUrl, headers=headers, json=json_data, allow_redirects=False, proxies=proxies, verify=False)
if response.status_code == 201:
try:
jsonResponse = response.json()
return jsonResponse["id"]
except Exception as err:
print(f"[!] Exception occured: {err}")
return
else:
print("[!] Error status code: " + str(response.status_code) )
def send_stage_3_request(url, id):
rUrl = url + "/proxy/api/environments/" + str(id) + "/runtimes"
response = requests.post(rUrl, headers=headers, allow_redirects=False, proxies=proxies, verify=False)
if response.status_code == 201:
try:
jsonResponse = response.json()
return jsonResponse["id"]
except Exception as err:
print(f"[!] Exception occured: {err}")
return
else:
print("[!] Error status code: " + str(response.status_code) )
def send_setup_code_request(url, environmentID, runtimeID):
rUrl = url + "/proxy/api/environments/" + environmentID + "/runtimes/" + runtimeID + "/execute2?flags=0"
fileName = "code.txt"
fileContent = """
for __var__ in list(globals().keys()):
if not __var__.startswith('__') and not __var__.startswith('_'):
del globals()[__var__]
del __var__
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels as sm
import excel
import warnings
warnings.simplefilter('ignore')
from excel import client_timezone, client_locale
excel.set_xl_scalar_conversion(excel.convert_to_scalar)
excel.set_xl_array_conversion(excel.convert_to_dataframe)
"""
files = {'code': ('code.txt', fileContent)}
#do multipart post here
response = requests.post(rUrl, headers=headersFileSend, files=files, proxies=proxies, verify=False)
if response.status_code == 200:
return True
else:
print("[!] Error status code: " + str(response.status_code) )
return False
def run_code(url, environmentID, runtimeID, code, data, precode):
rUrl = url + "/proxy/api/environments/" + environmentID + "/runtimes/" + runtimeID + "/executelongoperation2?flags=2&timeout=30"
dataFileName = "data.json"
precodeFileName = "precode.txt"
codeFileName = "code.txt"
files = {
'data': ('data.json', data),
'precode': ('precode.txt', precode),
'code': ('code.txt', code)
}
#do multipart post here
response = requests.post(rUrl, headers=headersFileSend, files=files, proxies=proxies, verify=False)
if response.status_code == 200:
return response.content
else:
print("[!] Error status code: " + str(response.status_code) )
return ""
if __name__ == "__main__":
print("PyCel - Excel Python interface by @two06")
print("")
print("[+] Making initial request...")
url = send_initial_request()
print("[+] Fetching environmentID ...")
environmentID = send_stage_2_request(url)
print("[+] Fetching resource ID...")
id = send_stage_3_request(url, environmentID)
#send our intitial setup file
print("[+] Performing setup request...")
res = send_setup_code_request(url, environmentID, id)
if res == False:
print("[!] sending setup file data")
sys.exit()
#send our code to run
data = '{"B1":"foobar"}'
precode = """
from excel import xl_ref as xl
import excel
_ref_context = excel.get_ref_context()
_ref_context.clear()
_ref_context["B1"] = excel.get_ref_context_data("B1")
"""
code = """
X = 1
Y = 2
print(xl("B1"))
X + Y
"""
print("[*] Running code...")
res = run_code(url, environmentID, id, code, data, precode)
print(res)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment